Compare commits

...
49 Commits
Author SHA1 Message Date
Joachim WibergandGitHub deee48d36a Merge pull request #817 from kernelkit/rel
Minor release engineering fixes
2024-11-08 19:37:58 +01:00
Joachim Wiberg 23e24635fe .github: create new discussion only on GA releases
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 18:51:09 +01:00
Joachim Wiberg eb38d4538f .github: remember to sync tags
The gh repo sync, used by our internal cronjob, does not sync tags, for
details see <https://github.com/cli/cli/issues/5023>.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 18:38:50 +01:00
Joachim WibergandGitHub 2910d8b9bf Merge pull request #811 from kernelkit/bootstrap-refactor
Early bootstrap refactor

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 15:20:39 +01:00
Joachim Wiberg 6bdfdbe164 doc: update ChangeLog for v24.10.2 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg ceb78d66a2 board/common: convert tc error message to useful information
When we opportunistically set up mqprio on all interfaces, we pass over
interfaces without offloading support.  Catch that error message and log
an informational message about which interfaces are skipped.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg 9ac77be9eb confd: fix scary error message on systems without USB ports
Check if the "usb-ports" key exists in /run/system.json before calling jq,
otherise we get the following error message:

Nov  8 05:11:45 ix bootstrap[3349]: jq: error (at <stdin>:0): Cannot iterate over null (null)

Also, minor whitespace cleanup and bashisms fixes.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg d692a3d745 board/common: enable syslog for rauc
In 0f410eb a patch was added to RAUC to allow native logging to syslog,
it was however never enabled.  This patch enables logging to syslog.

Fix #809

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg 597da90b05 board/commoon: use dbus machine-id as /etc/machine-id
Bootstrapping a system with D-Bus using Finit will create the machine-id
file /var/lib/dbus/machine-id, this can be used as the unique machine-id
for services like RAUC, so let's set that as /etc/machine-id to reduce
the log spam we get otherwise:

Nov  7 06:18:08 test-05-25-f8 rauc[5512]: Failed to get machine-id: Failed to open file <E2>M-^@M-^\/etc/machine-id<E2>M-^@M-^]: No such file or directory

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg 5d524006a3 board/aarch64: styx: led setup using a plain script at boot
After the initial probe, set up all port leds:

 - Disable all LEDs
 - Enable netdev trigger for all green LEDs (tp + sfp)
 - Enable link statux and rx/tx activity
 - Skip all aux LEDs

Also in script, a neat little flash function that can be used both for a
production test, to verify all LEDs work, and at runtime to locate the
device in a rack of devicess.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg 4c1de659cb board/aarch64: styx: rename second green led and drop second sfp led
On Rev. B, the second LED on the copper ports is green instead of yellow.
This patch renames them from yellow -> aux => <device>:aux:tp

Also on Rev. B, the second LED for SFP ports do not work at all.  This
patch drops them from the device tree to avoid confusion.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg 3b01f2d806 Revert "board/aarch64: styx: Remove unconnected LED"
This reverts commit 7d1a708274.  Turns out
the second LED is actually connected.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg 4e2458e18a board/common: introduce conditions for bootstrap services
Some services launched at bootstrap must be possible to override per
product.  One such service is iitod, which manages the LEDs in Infix.

This change makes allows a product specific init script to clear the
led condtion, preventing Finit from lauching iitod.  Also, rename the
ixinit-done condition to match the nomenclature used already.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg dc741bb567 board/common: use compatible string to install and run overrides
This patch use the new compatible array in /run/system.json, installing
in order, least to most significant product overrides.

We also introduce a new way to run product specific scripts at init, to
override default behavior in Infix, e.g., LED control.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg d5d487070f board/common: probe: add compatible array to /run/system.json
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg 7052c54165 board/common: probe: minor, pep8 fixes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 14:30:04 +01:00
Joachim Wiberg e25eb1966e patches/linux: minor fix to 6393X led handling
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 09:13:33 +01:00
Joachim Wiberg fe1c47e107 .github: allow release job to create new discussions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 09:13:33 +01:00
Jon-Olov VatnandGitHub 57b66ec6d3 Merge pull request #810 from kernelkit/doc-ieee-group-forward
Documentation of forwarding IEEE reserved group addresses
2024-11-08 09:04:28 +01:00
Jon-Olov Vatn 9103d31950 Minor formulation change in ieee group forwarding documentation
Fix #788

[skip ci]
2024-11-08 09:03:34 +01:00
Jon-Olov Vatn 32ec9887b9 Adding documentation on forwarding ieee reserved group addresses
Fix #788

[skip ci]
2024-11-08 09:02:49 +01:00
Joachim WibergandGitHub e0458ca079 Merge pull request #814 from kernelkit/doc-ospf-redistribute
Add rudimentary documentation on global OSPF settings

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-08 08:58:24 +01:00
Jon-Olov Vatn e9aefc517f Add rudimentary documenation on global OSPF settings
Fix #812

Doc covering
- redistribute static/connected
- distribute-default-route [always]
- explicit-router-id

[skip ci]
2024-11-08 08:21:02 +01:00
Mattias WalströmandGitHub 20295b08b5 Merge pull request #808 from kernelkit/set-hostname
Set hostname in infamy
2024-11-07 11:14:11 +01:00
Joachim WibergandGitHub 7a9f1c1d7a Merge pull request #786 from kernelkit/update-discovery-md
Update discovery.md on mDNS Information

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-11-07 10:43:12 +01:00
Mattias Walström 7e08555013 tests: Convert to put_config_dicts
Convert from put_config_dict to put_config_dicts
2024-11-07 10:13:05 +01:00
Mattias Walström 82ff83c50d infamy: Set hostname from logical topology
If no hostname is specified, set it to the dut-name in
logical topology
2024-11-07 09:47:36 +01:00
Jon-Olov Vatn d277f5a860 Updated Changelog wrt to changes in Discovery documentation
[skip ci]
2024-11-07 09:07:10 +01:00
Jon-Olov Vatn f537e2fc13 Update description of netbrowse service
Use proposal from review.

[skip ci]
2024-11-07 09:00:14 +01:00
Jon-Olov Vatn 73070f40c4 Minor updates to discovery doc
Changing title on the section on netbrowse service

[skip ci]
2024-11-07 09:00:14 +01:00
Jon-Olov Vatn a0fb42e46d Minor updates to discovery documentation
- Adding info on how to disable LLDP
- Avoiding clickable URL to https://network.local

[skip ci]
2024-11-07 09:00:14 +01:00
Jon-Olov Vatn a820beebfa Updates to discovery documentation
Use infix-c0-ff-ee (or similar) rather than infix-00-00-00
Adapting picture and text for netbrowse function to use more than on unit

[skip ci]
2024-11-07 09:00:14 +01:00
Ahmed KaricandJon-Olov Vatn 204672779b doc: Update discovery.md
Add information about:
  - mDNS alias
  - https://network.local

[skip ci]

Fixes #738
2024-11-07 09:00:14 +01:00
Mattias WalströmandGitHub 6a9f9fd3cc Merge pull request #806 from kernelkit/put-config-dicts
Put config dicts
2024-11-06 20:54:55 +01:00
Mattias Walström a78fd3da0a test: ospf_bfd: Wait for correct route before continue
This to make the test to be more stable.
2024-11-06 20:23:53 +01:00
Mattias Walström 8721255554 test: ospf_multiarea: Set static router-id
This is to workaround #807. To test automatic router id selection
a new test is required, which sets interfaces and activate ospf in
separete NETCONF/RESTCONF query.
2024-11-06 14:59:00 +01:00
Mattias Walström 5079691201 test: Convert ospf_multiarea to use put_config_dicts 2024-11-06 12:06:19 +01:00
Mattias Walström a23634dd7e test: Implement put_config_dicts
Add all configuration in one command.
Also update the test igmp_vlan to use
put_config_dicts instead of put_config_dict
2024-11-06 12:06:19 +01:00
Tobias WaldekranzandGitHub 3840ebc9fe Merge pull request #799 from kernelkit/ospf-bfd
test: Multi-Port Network Namespaces
2024-11-05 15:46:30 +01:00
Tobias Waldekranz 56abfde8ec test: netns: Add missing class documentation to describe TPMRs
[skip-ci]
2024-11-05 15:45:00 +01:00
Tobias Waldekranz 96d200fe70 test: vlan_ping: Improve test step description and structure
Initially done as a workaround for the MACVLAN create/remove race. But
even though the old version of this test now works, this refactor
provides better test step descriptions, making it easier to follow for
anyone looking to manually verify the functionality.
2024-11-04 14:42:31 +01:00
Tobias Waldekranz 7f2f3768db test: ospf_bfd: Verify fast fail-over using BFD 2024-11-04 14:42:31 +01:00
Tobias Waldekranz dc92db4e9f test: netns: Add Two-Port MAC Relay (TPMR)
This is a specialized namespace, containing two ports,
which (hopefully) acts as completely transparent "bump-on-the-wire"
bridge.

Useful in scenarios where you want to test what happens when the flow
of packets between two nodes is disrupted. E.g., for testing fail-over
behavior in dynamic routing protocols, L2 redundancy, VRRP etc.
2024-11-04 14:42:31 +01:00
Tobias Waldekranz be828d46c9 test: netns: Poll for MACVLAN removal completion
Now that we're using the `passthru` mode of MACVLANs, it seems we can
rely on the parent interface's promiscuity going down to 0 as an
indication that the kernel has completed the removal of the interface,
and will accept the creation of a new one.
2024-11-04 14:42:31 +01:00
Tobias Waldekranz a4a4a49eae test: netns: Guard against "double free" when failing to setup netns
When used as a context manager, __exit__ will be called even though
__enter__ might throw an exception half way through. So there is no
guarantee that the instance is on the cleanup list when we get to
stop().
2024-11-04 14:42:31 +01:00
Tobias Waldekranz 2a6e4402f8 test: netns: Clean up lingering namespaces on test exit
This gets rid of annoying "Address already in use" errors when running
tests repeatedly from a test-sh.
2024-11-04 14:42:31 +01:00
Tobias Waldekranz 3031bba047 test: netns: Use passthru mode for MACVLANs
This mode let's us receive all packets from the parent device, which
is automatically set in promiscuous mode, and let's the MACVLAN
transmit packets with any SA, which we need to implement a TPMR (or a
bridge or anything else we might dream up)
2024-11-04 14:42:31 +01:00
Tobias Waldekranz f9e430e41d test: netns: Generalize IsolatedMacVlan to support multiple interfaces
This is needed to create namespaces with MACVLANs from different
parent interfaces. The first consumer will be a Two-Port Mac
Relay (TPMR), so that we can control the flow of packets between two
nodes.
2024-11-04 14:42:31 +01:00
Tobias Waldekranz 17403afeb4 test: pcap: Avoid creating dumpcap zombies
Story time:

In the days of yore, we generated PCAPs using tcpdump, which will
flush any buffered packets to its output file on reception of
SIGUSR2. Therefore we sent a USR2 before terminating the capture.

At some point, we switched over to use tshark to capture packets for
us, but the SIGUSR2 sayed in place.

It turns out, tshark will just die on USR2, abandoning the dumpcap
child it has created, which means the enclosing network namespace
can't be properly torn down.

Therefore:

Remove skip sending USR2 and just send TERM directly.
2024-11-04 14:42:31 +01:00
69 changed files with 1856 additions and 807 deletions
+1
View File
@@ -33,3 +33,4 @@ Releases
- Easy to forget adaptations/hacks in customer repos -- may need Infix change/support
- Ensure the markdown link for the release diff is updated
- Ensure subrepos are tagged (can be automated, see kernelkit/infix#393)
- Sync tags for all repo. sync activities
+4 -1
View File
@@ -101,6 +101,7 @@ jobs:
runs-on: [ self-hosted, release ]
permissions:
contents: write
discussions: write
steps:
- uses: actions/checkout@v4
with:
@@ -115,12 +116,14 @@ jobs:
ver=${GITHUB_REF#refs/tags/}
fi
echo "ver=${ver}" >> $GITHUB_OUTPUT
echo "cat=" >> $GITHUB_OUTPUT
if echo $ver | grep -qE 'v[0-9.]+(-alpha|-beta|-rc)[0-9]*'; then
echo "pre=true" >> $GITHUB_OUTPUT
echo "latest=false" >> $GITHUB_OUTPUT
elif echo $ver | grep -qE '^v[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then
echo "pre=false" >> $GITHUB_OUTPUT
echo "latest=true" >> $GITHUB_OUTPUT
echo "cat=Releases" >> $GITHUB_OUTPUT
else
echo "pre=false" >> $GITHUB_OUTPUT
echo "latest=false" >> $GITHUB_OUTPUT
@@ -150,7 +153,7 @@ jobs:
name: Infix ${{ github.ref_name }}
prerelease: ${{ steps.rel.outputs.pre }}
makeLatest: ${{ steps.rel.outputs.latest }}
discussionCategory: Releases
discussionCategory: ${{ steps.rel.outputs.cat }}
bodyFile: release.md
artifacts: "*.tar.gz*"
+28 -4
View File
@@ -265,14 +265,38 @@
};
};
#define SWP_LED(_func) \
#define SWP_LED \
leds { \
#address-cells = <1>; \
#size-cells = <0>; \
\
led@0 { \
reg = <0>; \
function = _func; \
function = "tp"; \
color = <LED_COLOR_ID_GREEN>; \
default-state = "keep"; \
}; \
led@1 { \
reg = <1>; \
function = "aux"; \
color = <LED_COLOR_ID_GREEN>; \
default-state = "off"; \
}; \
}
/* SFP LEDs
* Rev A. LEDs do not work at all
* Rev B. only outer-most (green) LEDs work
*/
#define SFP_LED \
leds { \
#address-cells = <1>; \
#size-cells = <0>; \
\
led@0 { \
reg = <0>; \
function = "sfp"; \
color = <LED_COLOR_ID_GREEN>; \
default-state = "keep"; \
}; \
@@ -287,7 +311,7 @@
phy-mode = "10gbase-r"; \
managed = "in-band-status"; \
sfp = <_sfp>; \
SWP_LED("sfp"); \
SFP_LED; \
}
#define XSWCPU(_n, _eth) \
@@ -321,7 +345,7 @@
nvmem-cell-names = "mac-address"; \
phy-mode = "gmii"; \
phy-handle = <_phy>; \
SWP_LED("tp"); \
SWP_LED; \
}
#define GPHY(_n) \
+111
View File
@@ -0,0 +1,111 @@
#!/bin/sh
# Raw switch LED Control for systems that do not run iitod
LEDS=$(find /sys/class/leds -iname '*mdio-mii*')
LINK=$(find /sys/class/leds -iname '*mdio-mii*p')
# Disable ALL switch port LEDs
clear()
{
for led in $LEDS; do
echo 0 > "${led}/brightness"
done
}
setup()
{
for led in $LINK; do
echo netdev > "${led}/trigger"
done
for led in $LINK; do
cd "$led"
# No sleep here, it's enough with the delay from previous loop
echo 1 > link
sleep 0.1
echo 1 > rx
sleep 0.1
echo 1 > tx
cd - >/dev/null
done
}
leds()
{
for led in $LINK; do
printf "%3s: %s\n" "$(cat "$led/device_name" 2>/dev/null)" "$led"
done
}
list()
{
leds | sort | while read -r port path; do
printf "%4s %s\n" "$port" "$(basename "$path")"
aux=${path%%:tp}:aux
if [ -e "$aux" ]; then
printf "%3s: %s\n" "" "$(basename "$aux")"
fi
done
}
flash()
{
sec=$1
for led in $LEDS; do
echo timer > "${led}/trigger"
done
for led in $LEDS; do
echo 84 > "${led}/delay_on"
echo 84 > "${led}/delay_off"
done
sleep "$sec"
clear
}
usage()
{
echo "usage: $0 [command]"
echo
echo "flash [SEC] Flash all LEDs to locate device in rack, default: 5 sec"
echo "list List all LEDs"
echo "setup Set up and start normal operation"
echo "start Call at system init, clears all LEDs and sets up normal op"
echo "stop Clear all LEDs, may be called at system shutdown"
echo
echo "Please ensure no other tool or daemon is already managing the LEDs."
}
cmd=$1; shift
case $cmd in
flash)
flash ${1:-5}
setup
;;
help)
usage
exit 0
;;
list | ls)
list
;;
setup)
setup
;;
start)
initctl -nbq cond clear led
clear
setup
;;
stop)
clear
;;
*)
usage
exit 1
;;
esac
@@ -0,0 +1 @@
/usr/libexec/styx/led.sh
+1
View File
@@ -0,0 +1 @@
RAUC_ARGS="-s"
+1
View File
@@ -0,0 +1 @@
/var/lib/dbus/machine-id
@@ -8,10 +8,11 @@ import struct
import subprocess
import sys
onieprom = importlib.machinery.SourceFileLoader("onieprom","/bin/onieprom").load_module()
SYSTEM_JSON = "/run/system.json"
onieprom = importlib.machinery.SourceFileLoader("onieprom", "/bin/onieprom").load_module()
SYSTEM_JSON = "/run/system.json"
KKIT_IANA_PEM = 61046
class DTSystem:
BASE = "/sys/firmware/devicetree/base"
INFIX = BASE + "/chosen/infix"
@@ -28,7 +29,9 @@ class DTSystem:
if not os.path.exists(phandle):
continue
ph, = struct.unpack(">L", open(phandle, "rb").read())
with open(phandle, "rb") as f:
data = f.read()
ph, = struct.unpack(">L", data)
dt[ph] = root
sys = {}
@@ -40,14 +43,18 @@ class DTSystem:
if not os.path.exists(phandle):
continue
ph, = struct.unpack(">L", open(phandle, "rb").read())
with open(phandle, "rb") as f:
data = f.read()
ph, = struct.unpack(">L", data)
if ph not in sys:
sys[ph] = []
sys[ph].append(root)
phs = set(list(dt.keys()) + list(sys.keys()))
self.devs = { ph: [Device(ph, dt.get(ph), s if s is not None else "") for s in (sys.get(ph) or []) if ph is not None] for ph in phs }
self.devs = {ph: [Device(ph, dt.get(ph), s if s is not None else "")
for s in (sys.get(ph) or []) if ph is not None]
for ph in phs}
self.base = Device(0, None, DTSystem.BASE)
self.infix = Device(0, None, DTSystem.INFIX)
@@ -56,7 +63,8 @@ class DTSystem:
if not os.path.exists(path):
return ()
data = open(path, "rb").read()
with open(path, "rb") as f:
data = f.read()
elems = len(data) // struct.calcsize(">L")
return struct.unpack(">" + elems * "L", data)
@@ -69,7 +77,8 @@ class DTSystem:
return {}
try:
data = onieprom.from_tlv(open(dev.attrpath("nvmem"), "rb", 0))
with open(dev.attrpath("nvmem"), "rb", 0) as f:
data = onieprom.from_tlv(f)
except:
data = {}
@@ -84,14 +93,18 @@ class DTSystem:
}
def infix_usb_devices(self, out):
names=self.infix.str_array("usb-port-names", ())
phs=self.__get_phandle_array("usb-ports")
data=dict(zip(names,phs))
names = self.infix.str_array("usb-port-names", ())
phs = self.__get_phandle_array("usb-ports")
data = dict(zip(names, phs))
if data != {}:
out["usb-ports"] = []
for name,ph in data.items():
[out["usb-ports"].extend([{"name": name, "path": dev.attrpath("authorized")}, {"name": name, "path": dev.attrpath("authorized_default")}]) for dev in self.devices_from_ph(ph)]
for name, ph in data.items():
[out["usb-ports"].extend([{
"name": name,
"path": dev.attrpath("authorized")}, {
"name": name,
"path": dev.attrpath("authorized_default")
}]) for dev in self.devices_from_ph(ph)]
def infix_devices(self, kind):
phs = self.__get_phandle_array(kind)
@@ -101,6 +114,7 @@ class DTSystem:
flat_devices = [device for sublist in self.infix_devices("vpds") for device in sublist]
return [self.into_vpd(device) for device in flat_devices]
class QEMUSystem:
BASE = "/sys/firmware/qemu_fw_cfg"
REV = BASE + "/rev"
@@ -110,7 +124,8 @@ class QEMUSystem:
data = {}
if os.path.exists(QEMUSystem.VPD):
try:
data = onieprom.from_tlv(open(QEMUSystem.VPD, "rb", 0))
with open(QEMUSystem.VPD, "rb", 0) as f:
data = onieprom.from_tlv(f)
except:
pass
@@ -127,31 +142,27 @@ class QEMUSystem:
def usb_ports(self):
ports = [
{
"name": "USB",
"path": "/sys/bus/usb/devices/usb1/authorized"
},
{
"name": "USB",
"path": "/sys/bus/usb/devices/usb1/authorized_default"
},
{
"name": "USB2",
"path": "/sys/bus/usb/devices/usb2/authorized"
},
{
"name": "USB2",
"path": "/sys/bus/usb/devices/usb2/authorized_default"
}]
"name": "USB",
"path": "/sys/bus/usb/devices/usb1/authorized"
}, {
"name": "USB",
"path": "/sys/bus/usb/devices/usb1/authorized_default"
}, {
"name": "USB2",
"path": "/sys/bus/usb/devices/usb2/authorized"
}, {
"name": "USB2",
"path": "/sys/bus/usb/devices/usb2/authorized_default"
}]
return ports
class Device:
def __init__(self, ph, dtpath, syspath):
self.ph, self.dtpath, self.syspath = ph, dtpath, syspath
def available(self):
return self.syspath != None
return self.syspath is not None
def __getitem__(self, attr):
return self.attr(attr).decode("utf-8").strip("\0")
@@ -159,7 +170,6 @@ class Device:
def __setitem__(self, attr, value):
return self.attr(attr, val=value.encode("utf-8"))
def attrpath(self, attr):
return os.path.join(self.syspath, attr)
@@ -168,13 +178,16 @@ class Device:
def attr(self, attr, default=None, val=None):
if not self.hasattr(attr):
return default if val == None else False
return default if val is None else False
if val:
open(self.attrpath(attr), "wb").write(value)
with open(self.attrpath(attr), "wb") as f:
f.write(val)
return True
return open(self.attrpath(attr), "rb").read()
with open(self.attrpath(attr), "rb") as f:
data = f.read()
return data
def str(self, attr, default=None):
val = self.attr(attr)
@@ -194,7 +207,9 @@ class Device:
if not self.hasdtattr(attr):
return default
return open(self.dtattrpath(attr), "rb").read()
with open(self.dtattrpath(attr), "rb") as f:
data = f.read()
return data
def dtstr(self, attr, default=None):
val = self.dtattr(attr)
@@ -212,6 +227,7 @@ def vpd_get_json_ve(vpd, pem):
return out
def vpd_get_pwhash(vpd):
if not vpd.get("trusted"):
return None
@@ -219,8 +235,9 @@ def vpd_get_pwhash(vpd):
kkit = vpd_get_json_ve(vpd, KKIT_IANA_PEM)
return kkit.get("pwhash")
def vpd_inject(out, vpds):
out["vpd"] = { vpd["board"]: vpd for vpd in vpds }
out["vpd"] = {vpd["board"]: vpd for vpd in vpds}
product = out["vpd"].get("product", {}).get("data", {})
hoistattrs = ("vendor", "product-name", "part-number", "serial-number", "mac-address")
@@ -234,6 +251,7 @@ def vpd_inject(out, vpds):
out["factory-password-hash"] = pwhash
break
def qemu_base_mac():
"""Find MAC address of first non-loopback interface, subtract with 1"""
base_path = '/sys/class/net'
@@ -244,7 +262,8 @@ def qemu_base_mac():
continue
try:
# pylint: disable=invalid-name
with open(os.path.join(base_path, iface, 'address'), 'r', encoding='ascii') as f:
fn = os.path.join(base_path, iface, 'address')
with open(fn, 'r', encoding='ascii') as f:
mac = f.read().strip()
interfaces.append((mac, iface))
except FileNotFoundError:
@@ -261,6 +280,7 @@ def qemu_base_mac():
return None
def probe_qemusystem(out):
"""Probe Qemu based test systems and 'make run'"""
admin_hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"
@@ -288,6 +308,7 @@ def probe_qemusystem(out):
subprocess.run("initctl -nbq cond set qemu".split(), check=False)
return 0
def probe_dtsystem(out):
"""Probe DTS based system, expects a VPD in ONIE PROM format."""
dtsys = DTSystem()
@@ -297,6 +318,8 @@ def probe_dtsystem(out):
if model:
out["product-name"] = model
out["compatible"] = dtsys.base.str_array("compatible")
staticpw = dtsys.infix.str("factory-password-hash")
if not out["factory-password-hash"]:
out["factory-password-hash"] = staticpw
@@ -304,6 +327,7 @@ def probe_dtsystem(out):
vpd_inject(out, vpds)
return 0
def main():
out = {
"vendor": None,
@@ -338,5 +362,6 @@ def main():
shutil.chown(SYSTEM_JSON, user="root", group="wheel")
return err
if __name__ == "__main__":
sys.exit(main())
@@ -1,22 +1,48 @@
#!/bin/sh
# Find and install any product specific files in /etc before bootstrap
# Find, install, and run product specific files and script in /etc
# before resuming bootstrap.
#
# Use /etc/product/init.d/S01-myscript for scripts, may be a symlink, it
# will be called with `start` as its only argument.
#
# The compatible array is listed in the same order as the device tree,
# most significant to least. Hence the reverse.[], to ensure overrides
# are applied in order of significance.
ident=$(basename "$0")
PRODUCT_INIT=/etc/product/init.d
PREFIXD=/usr/share/product
PRODUCT=$(jq -r '."product-name" | ascii_downcase' /run/system.json)
COMPATIBLES=$(jq -r '.compatible | reverse.[] | ascii_downcase' /run/system.json)
note()
{
logger -I $$ -k -p user.notice -t "$ident" "$1"
}
DIR="$PREFIXD/$PRODUCT"
if [ -z "$PRODUCT" ] || [ ! -d "$DIR" ]; then
note "No vendor/product specific directory found, using built-in defaults."
exit 0
found=false
for PRODUCT in $COMPATIBLES; do
DIR="$PREFIXD/$PRODUCT"
if [ -d "$DIR" ]; then
note "Using vendor/product-specific defaults for $PRODUCT."
for dir in "$DIR"/*; do
[ -d "$dir" ] && cp -a "$dir" /
done
found=true
fi
done
if [ "$found" = false ]; then
note "No vendor/product-specific directory found, using built-in defaults."
fi
note "Using vendor/product specific defaults."
for dir in "$DIR"/*; do
[ -d "$dir" ] && cp -a "$dir" /
done
# Conditions for bootstrap services, this enables product specific
# init scripts to prevent select services from starting.
initctl -nbq cond set led
note "Calling runparts $PRODUCT_INIT/S[0-9]+.* start"
/usr/libexec/finit/runparts -bsp "$PRODUCT_INIT"
# Product specific init done.
initctl -nbq cond set product
exit 0
@@ -46,7 +46,11 @@ while [ "$1" ]; do
[ $txqs -lt 2 ] && continue
[ $txqs -gt 8 ] && txqs=8
tc qdisc add dev $iface root mqprio hw 1 \
num_tc $txqs $(map $txqs) $(queues $txqs) || true
output=$(tc qdisc add dev $iface root mqprio hw 1 \
num_tc $txqs $(map $txqs) $(queues $txqs) 2>&1) || true
if echo "$output" | grep -q "does not support hardware offload"; then
echo "Skipping $iface, hardware offload not supported."
elif [ -n "$output" ]; then
echo "$output"
fi
done
@@ -1,2 +1,2 @@
#!/bin/sh
exec initctl -bq cond set ixinit-done
exec initctl -bq cond set ixinit
+21 -2
View File
@@ -4,7 +4,7 @@ Change Log
All notable changes to the project are documented in this file.
[v24.10.2][UNRELEASED]
[v24.10.2][] - 2024-11-08
-------------------------
### Changes
@@ -22,12 +22,30 @@ All notable changes to the project are documented in this file.
- Support for saving and restoring system clock from a disk file. This
allows restoring the system clock to a sane date in case the RTC is
disabled or does not have a valid time, issue #794
- Update device discovery chapter with information on `infix.local` mDNS
alias, `netbrowse` support to discover *all* local units, and command
examples for disabling LLDP and mDNS services, issue #786
- Updated OSPF documentation to include information on *global OSPF
settings* (`redistribution`, `explicit-router-id`, etc.), issue #812
- Added information on *forwarding of IEEE reserved group addresses*
to bridge section of networking documentation, issue #788
- Add support for bootstrap conditions and early init product overrides
- Styx: enable second Ethernet port LED in device tree, again, rename
it: yellow -> aux, and make sure it is turned off at boot
- Styx: disable second port LED for the 4xSFP slots, does not work
- Styx: override iitod (LED daemon) with a product specific LED script
### Fixes
- Fix #685: DSA conduit interface not always detected, randomly causing
major issues configuring systems with multiple switch cores
- Fix #778: reactivate OpenSSL backend for libssh/libssh2 for NanoPI R2S.
This fixes a regression in v24.10.0 causing loss of NETCONF supprt
This fixes a regression in v24.10.0 causing loss of NETCONF support
- Fix #809: enable syslog logging for RAUC
- Fix harmless bootstrap log error message on systems without USB ports:
`jq: error (at <stdin>:0): Cannot iterate over null (null)`
- Change confusing `tc` log error message: `Error: does not support
hardware offload` to `Skipping $iface, hardware offload not supported.`
[v24.10.1][] - 2024-10-18
@@ -1276,6 +1294,7 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
[buildroot]: https://buildroot.org/
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.10.1...HEAD
[v24.10.2]: https://github.com/kernelkit/infix/compare/v24.10.1...v24.10.2
[v24.10.1]: https://github.com/kernelkit/infix/compare/v24.10.0...v24.10.1
[v24.10.0]: https://github.com/kernelkit/infix/compare/v24.09.0...v24.10.0
[v24.09.0]: https://github.com/kernelkit/infix/compare/v24.08.0...v24.09.0
+142 -28
View File
@@ -16,14 +16,14 @@ seen in the response.
In the example below, the PC is connected to Infix via interface *tap0*
(*tap0* is *if1* in Figure 1) and Infix responds with address
*fe80::ff:fe00:0*.
*fe80::ff:fec0:ffed*.
```
linux-pc:# ping -6 -L -c 3 ff02::1%tap0
PING ff02::1%tap0(ff02::1%tap0) 56 data bytes
64 bytes from fe80::ff:fe00:0%tap0: icmp_seq=1 ttl=64 time=0.558 ms
64 bytes from fe80::ff:fe00:0%tap0: icmp_seq=2 ttl=64 time=0.419 ms
64 bytes from fe80::ff:fe00:0%tap0: icmp_seq=3 ttl=64 time=0.389 ms
64 bytes from fe80::ff:fec0:ffed%tap0: icmp_seq=1 ttl=64 time=0.558 ms
64 bytes from fe80::ff:fec0:ffed%tap0: icmp_seq=2 ttl=64 time=0.419 ms
64 bytes from fe80::ff:fec0:ffed%tap0: icmp_seq=3 ttl=64 time=0.389 ms
--- ff02::1%tap0 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2043ms
@@ -34,9 +34,9 @@ linux-pc:#
The PC could connect then connect to Infix, e.g., using SSH.
```
linux-pc:# ssh admin@fe80::ff:fe00:0%tap0
admin@fe80::ff:fe00:0%tap0's password: admin
admin@infix-00-00-00:~$
linux-pc:# ssh admin@fe80::ff:fec0:ffed%tap0
admin@fe80::ff:fec0:ffed%tap0's password: admin
admin@infix-c0-ff-ee:~$
```
## Discovery mechanisms available in Infix
@@ -55,18 +55,18 @@ linux-pc:# tcpdump -i tap0 -Qin -v ether proto 0x88cc
tcpdump: listening on tap0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:51:52.061071 LLDP, length 193
Chassis ID TLV (1), length 7
Subtype MAC address (4): 02:00:00:00:00:00 (oui Unknown)
Subtype MAC address (4): 02:00:00:c0:ff:ee (oui Unknown)
Port ID TLV (2), length 7
Subtype MAC address (3): 02:00:00:00:00:00 (oui Unknown)
Subtype MAC address (3): 02:00:00:c0:ff:ee (oui Unknown)
Time to Live TLV (3), length 2: TTL 120s
System Name TLV (5), length 14: infix-00-00-00
System Name TLV (5), length 14: infix-c0-ff-ee
System Description TLV (6), length 91
Infix by KernelKit Linux 5.19.17 #1 SMP PREEMPT_DYNAMIC Wed Jun 7 08:47:23 CEST 2023 x86_64
System Capabilities TLV (7), length 4
System Capabilities [Bridge, WLAN AP, Router, Station Only] (0x009c)
Enabled Capabilities [Station Only] (0x0080)
Management Address TLV (8), length 24
Management Address length 17, AFI IPv6 (2): fe80::ff:fe00:0
Management Address length 17, AFI IPv6 (2): fe80::ff:fec0:ffed
Interface Index Interface Numbering (2): 2
Port Description TLV (4), length 4: eth0
Organization specific TLV (127), length 9: OUI IEEE 802.3 Private (0x00120f)
@@ -97,11 +97,11 @@ linux-pc:# sudo tcpdump -i tap0 -Qin -v ether proto 0x88cc
tcpdump: listening on tap0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:46:07.908665 LLDP, length 207
Chassis ID TLV (1), length 7
Subtype MAC address (4): 02:00:00:00:00:00 (oui Unknown)
Subtype MAC address (4): 02:00:00:c0:ff:ee (oui Unknown)
Port ID TLV (2), length 7
Subtype MAC address (3): 02:00:00:00:00:00 (oui Unknown)
Subtype MAC address (3): 02:00:00:c0:ff:ee (oui Unknown)
Time to Live TLV (3), length 2: TTL 120s
System Name TLV (5), length 14: infix-00-00-00
System Name TLV (5), length 14: infix-c0-ff-ee
System Description TLV (6), length 91
Infix by KernelKit Linux 5.19.17 #1 SMP PREEMPT_DYNAMIC Wed Jun 7 08:47:23 CEST 2023 x86_64
System Capabilities TLV (7), length 4
@@ -134,6 +134,15 @@ linux-pc:#
(LLDP)](https://github.com/lldp/lldpd) includes *lldpcli*, which
is handy to sniff and display LLDP packets.
The LLDP service can be disabled using the following commands.
```
admin@infix-c0-ff-ee:/> configure
admin@infix-c0-ff-ee:/config/> no lldp
admin@infix-c0-ff-ee:/config/> leave
admin@infix-c0-ff-ee:/>
```
### mDNS
DNS-SD/mDNS can be used to discover Infix units and services. Infix
@@ -144,33 +153,138 @@ be used to search for devices advertising their services via mDNS.
```
linux-pc:# avahi-browse -ar
+ tap0 IPv6 infix-00-00-00 SFTP File Transfer local
+ tap0 IPv4 infix-00-00-00 SFTP File Transfer local
+ tap0 IPv6 infix-00-00-00 SSH Remote Terminal local
+ tap0 IPv4 infix-00-00-00 SSH Remote Terminal local
= tap0 IPv4 infix-00-00-00 SFTP File Transfer local
hostname = [infix-00-00-00.local]
+ tap0 IPv6 infix-c0-ff-ee SFTP File Transfer local
+ tap0 IPv4 infix-c0-ff-ee SFTP File Transfer local
+ tap0 IPv6 infix-c0-ff-ee SSH Remote Terminal local
+ tap0 IPv4 infix-c0-ff-ee SSH Remote Terminal local
= tap0 IPv4 infix-c0-ff-ee SFTP File Transfer local
hostname = [infix-c0-ff-ee.local]
address = [10.0.1.1]
port = [22]
txt = []
= tap0 IPv4 infix-00-00-00 SSH Remote Terminal local
hostname = [infix-00-00-00.local]
= tap0 IPv4 infix-c0-ff-ee SSH Remote Terminal local
hostname = [infix-c0-ff-ee.local]
address = [10.0.1.1]
port = [22]
txt = []
= tap0 IPv6 infix-00-00-00 SFTP File Transfer local
hostname = [infix-00-00-00.local]
address = [fe80::ff:fe00:0]
= tap0 IPv6 infix-c0-ff-ee SFTP File Transfer local
hostname = [infix-c0-ff-ee.local]
address = [fe80::ff:fec0:ffed]
port = [22]
txt = []
= tap0 IPv6 infix-00-00-00 SSH Remote Terminal local
hostname = [infix-00-00-00.local]
address = [fe80::ff:fe00:0]
= tap0 IPv6 infix-c0-ff-ee SSH Remote Terminal local
hostname = [infix-c0-ff-ee.local]
address = [fe80::ff:fec0:ffed]
port = [22]
txt = []
^C
linux-pc:#
```
Additionally, *avahi-resolve-host-name* can be used to verify domain
name mappings for IP addresses. By default, it translates from IPv4
addresses. This function allows users to confirm that addresses are
mapped correctly.
```
linux-pc:# avahi-resolve-host-name infix-c0-ff-ee.local
infix-c0-ff-ee.local 10.0.1.1
linux-pc:#
```
Thanks to mDNS we can use the advertised name instead of the IP
address for operations like `ping` and `ssh` as shown below:
```
linux-pc:# ping infix-c0-ff-ee.local -c 3
PING infix-c0-ff-ee.local (10.0.1.1) 56(84) bytes of data.
64 bytes from 10.0.1.1: icmp_seq=1 ttl=64 time=0.852 ms
64 bytes from 10.0.1.1: icmp_seq=2 ttl=64 time=1.12 ms
64 bytes from 10.0.1.1: icmp_seq=3 ttl=64 time=1.35 ms
--- infix-c0-ff-ee.local ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.852/1.105/1.348/0.202 ms
linux-pc:# ssh admin@infix-c0-ff-ee.local
(admin@infix-c0-ff-ee.local) Password:
.-------.
| . . | Infix -- a Network Operating System
|-. v .-| https://kernelkit.org
'-'---'-
Run the command 'cli' for interactive OAM
linux-pc:#
```
To disable mDNS/mDNS-SD, type the commands:
```
admin@infix-c0-ff-ee:/> configure
admin@infix-c0-ff-ee:/config/> no mdns
admin@infix-c0-ff-ee:/config/> leave
```
#### Human-Friendly Hostname Alias
Each Infix unit will advertise itself as *infix.local*, in addition to
its full hostname (e.g., *infix-c0-ff-ee.local* or *foo.local*). This
alias works seamlessly on a network with a single Infix device, and
makes it easy to connect when the exact hostname is not known in
advance. The examples below show how the alias can be used for
actions such as pinging or establishing an SSH connection:
```
linux-pc:# ping infix.local -c 3
PING infix.local (10.0.1.1) 56(84) bytes of data.
64 bytes from 10.0.1.1: icmp_seq=1 ttl=64 time=0.751 ms
64 bytes from 10.0.1.1: icmp_seq=2 ttl=64 time=2.28 ms
64 bytes from 10.0.1.1: icmp_seq=3 ttl=64 time=1.42 ms
--- infix.local ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.751/1.482/2.281/0.626 ms
linux-pc:# ssh admin@infix.local
(admin@infix.local) Password:
.-------.
| . . | Infix -- a Network Operating System
|-. v .-| https://kernelkit.org
'-'---'-
Run the command 'cli' for interactive OAM
linux-pc:#
```
When multiple Infix devices are present on the LAN the alias will not
uniquely identify a device; *infix.local* will refer to any of the
Infix devices, likely the one that first appeared.
> When multiple Infix units are present, use the full hostname (e.g.,
> *infix-c0-ff-ee.local* or *foo.local*) rather than the alias
> infix.local to deterministically connect to a unit.
#### Netbrowse service to find all your devices
Another mDNS alias that all Infix devices can advertise is
*network.local*. This is a web service which basically runs avahi-browse
and displays a table of other Infix devices and their services.
![Netbrowse Service - network.local](img/network-local.png)
With multiple Infix devices on the LAN, one will be your portal to
access all others, if it goes down another will take its place.
To disable the netbrowse service, the following commands can be used:
```
admin@infix-c0-ff-ee:/> configure
admin@infix-c0-ff-ee:/config/> edit web
admin@infix-c0-ff-ee:/config/web/> no netbrowse
admin@infix-c0-ff-ee:/config/web/> leave
```
[^2]: [mdns-scan](http://0pointer.de/lennart/projects/mdns-scan/): a
tool for scanning for mDNS/DNS-SD published services on the local
network
Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

+58
View File
@@ -383,6 +383,32 @@ an IGMP/MLD fast-leave port.
[RFC3376]: https://www.rfc-editor.org/rfc/rfc3376.html
[RFC3810]: https://www.rfc-editor.org/rfc/rfc3810.html
#### Forwarding of IEEE Reserved Group Addresses
Addresses in range `01:80:C2:00:00:0X` are used by various bridge
signaling protocols, and are not forwarded by default. Still, it is
sometimes useful to let the bridge forward such packets, and Infix
supports this by specifying protocol names or the last address
*nibble* as decimal value `0..15`.
```
admin@example:/config/> edit interface br0 bridge
admin@example:/config/interface/br0/bridge/> set ieee-group-forward <?>
[0..15] List of IEEE link-local protocols to forward, e.g., STP, LLDP
dot1x 802.1X Port-Based Network Access Control.
lacp 802.3 Slow Protocols, e.g., LACP.
lldp 802.1AB Link Layer Discovery Protocol (LLDP).
stp Spanning Tree (STP/RSPT/MSTP).
admin@example:/config/interface/br0/bridge/> set ieee-group-forward
```
The following example configures bridge *br0* to forward LLDP packets.
```
admin@example:/config/interface/br0/bridge/> set ieee-group-forward lldp
admin@example:/config/interface/br0/bridge/>
```
### VLAN Interfaces
Creating a VLAN can be done in many ways. This section assumes VLAN
@@ -1011,6 +1037,38 @@ an Ethernet interface can be done as follows.
admin@example:/config/routing/control-plane-protocol/ospfv2/name/default/ospf/area/0.0.0.0/interface/e0/> set interface-type point-to-point
admin@example:/config/routing/control-plane-protocol/ospfv2/name/default/ospf/area/0.0.0.0/interface/e0/>
#### OSPF global settings
In addition to *area* and *interface* specific settings, OSPF provides
global settings for route redistribution and OSPF router identifier.
```
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
admin@example:/config/routing/control-plane-protocol/ospfv2/name/default/ospf/> set ?
area List of OSPF areas.
default-route-advertise Distribute default route to network
explicit-router-id Defined in RFC 2328. A 32-bit number
redistribute Redistribute protocols into OSPF
admin@example:/config/routing/control-plane-protocol/ospfv2/name/default/ospf/> set
```
- Explicit router ID: By default the router will pick an IP address
from one of its OSPF interfaces as OSPF router ID. An explicit ID is
used to get a deterministic behavior, e.g., `set explicit-router-id
1.1.1.1`.
- Redistribution: `set redistribute static` and `set redistribute connected`
can be used to include static or connected routes into the OSPF routing
domain. These routes are redistributed as *external type-2* (E2)
routes.
- Advertising default route: An OSPF router can be made to distribute
a default route into the OSPF domain by command `set
default-route-advertise enabled`. This route is distributed as long
as the router itself has an *active* default route in its routing
table. By adding command `set default-route-advertise always` the
router will distribute a default route even when it lacks a default
route. The default route will be distributed as an *external type-2*
(E2) route.
#### Debug OSPFv2
+1 -1
View File
@@ -1,6 +1,6 @@
#set DEBUG=1
run name:bootstrap log:prio:user.notice norestart <usr/ixinit-done> \
run name:bootstrap log:prio:user.notice norestart <usr/ixinit> \
[S] /usr/libexec/confd/bootstrap \
-- Bootstrapping YANG datastore
+1 -1
View File
@@ -1 +1 @@
service [S0123456789] <!pid/syslogd> iitod -- LED daemon
service [S0123456789] <!usr/product,usr/led> iitod -- LED daemon
@@ -1,7 +1,7 @@
From 4be3e500b670f7b98e3dd6696b8e51e83f122c65 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 25 Jan 2024 21:36:59 +0100
Subject: [PATCH 01/33] net: phy: add support for PHY LEDs polarity modes
Subject: [PATCH 01/34] net: phy: add support for PHY LEDs polarity modes
Organization: Addiva Elektronik
Add support for PHY LEDs polarity modes. Some PHY require LED to be set
@@ -22,6 +22,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20240125203702.4552-4-ansuelsmth@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/phy/phy_device.c | 16 ++++++++++++++++
include/linux/phy.h | 22 ++++++++++++++++++++++
@@ -1,7 +1,7 @@
From 4833b140cd11a57dd9f59754cdacfd71bc564c8f Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Mon, 4 Dec 2023 11:08:11 +0100
Subject: [PATCH 02/33] net: mvmdio: Support setting the MDC frequency on XSMI
Subject: [PATCH 02/34] net: mvmdio: Support setting the MDC frequency on XSMI
controllers
Organization: Addiva Elektronik
@@ -14,6 +14,7 @@ Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20231204100811.2708884-4-tobias@waldekranz.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/ethernet/marvell/mvmdio.c | 44 +++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
@@ -1,7 +1,7 @@
From 50a2973e8a520a82e9f9ec15a1f69e059ce7a334 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:23 +0100
Subject: [PATCH 03/33] net: dsa: mv88e6xxx: Create API to read a single stat
Subject: [PATCH 03/34] net: dsa: mv88e6xxx: Create API to read a single stat
counter
Organization: Addiva Elektronik
@@ -16,6 +16,7 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 162 ++++++++++++++++++-------------
drivers/net/dsa/mv88e6xxx/chip.h | 27 +++---
@@ -1,7 +1,7 @@
From 5916503e23e7f85796c1f927747e66b9535bac53 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:25 +0100
Subject: [PATCH 04/33] net: dsa: mv88e6xxx: Give each hw stat an ID
Subject: [PATCH 04/34] net: dsa: mv88e6xxx: Give each hw stat an ID
Organization: Addiva Elektronik
With the upcoming standard counter group support, we are no longer
@@ -16,6 +16,7 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 138 +++++++++++++++++--------------
1 file changed, 75 insertions(+), 63 deletions(-)
@@ -1,7 +1,7 @@
From 32dda6562734ec8ee667bc546f3ef56794d5bf82 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:26 +0100
Subject: [PATCH 05/33] net: dsa: mv88e6xxx: Add "eth-mac" counter group
Subject: [PATCH 05/34] net: dsa: mv88e6xxx: Add "eth-mac" counter group
support
Organization: Addiva Elektronik
@@ -12,6 +12,7 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 39 ++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
@@ -1,7 +1,7 @@
From 36adbdd466ec550cab8b2ae54177f674c02cf631 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:27 +0100
Subject: [PATCH 06/33] net: dsa: mv88e6xxx: Limit histogram counters to
Subject: [PATCH 06/34] net: dsa: mv88e6xxx: Limit histogram counters to
ingress traffic
Organization: Addiva Elektronik
@@ -27,6 +27,7 @@ Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 6 +++---
drivers/net/dsa/mv88e6xxx/global1.c | 7 +++----
@@ -1,7 +1,7 @@
From abfa532c1149525b128b8c76d80965f55e208240 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 14 Dec 2023 14:50:28 +0100
Subject: [PATCH 07/33] net: dsa: mv88e6xxx: Add "rmon" counter group support
Subject: [PATCH 07/34] net: dsa: mv88e6xxx: Add "rmon" counter group support
Organization: Addiva Elektronik
Report the applicable subset of an mv88e6xxx port's counters using
@@ -11,6 +11,7 @@ Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 42 ++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
@@ -1,11 +1,13 @@
From 4407b94b4a08536fccb6eea2826955ff12d63ec2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Nov 2023 19:44:32 +0100
Subject: [PATCH 09/33] net: dsa: mv88e6xxx: Add LED infrastructure
Subject: [PATCH 09/34] net: dsa: mv88e6xxx: Add LED infrastructure
Organization: Addiva Elektronik
Parse DT for LEDs and register them for devices that support it,
though no actual implementations exist yet.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 5 +-
@@ -1,13 +1,15 @@
From a5cf5c0353db07e74d7a29dd4d5c2cb7775d5bec Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Nov 2023 21:59:35 +0100
Subject: [PATCH 10/33] net: dsa: mv88e6xxx: Add LED support for 6393X
Subject: [PATCH 10/34] net: dsa: mv88e6xxx: Add LED support for 6393X
Organization: Addiva Elektronik
Trigger support:
- "none"
- "timer"
- "netdev"
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 1 +
drivers/net/dsa/mv88e6xxx/leds.c | 226 +++++++++++++++++++++++++++++++
@@ -1,13 +1,15 @@
From be94ec851dbb8e55c3f5e82f197b2dc59566aea2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 12 Mar 2024 10:27:24 +0100
Subject: [PATCH 11/33] net: dsa: mv88e6xxx: Fix timeout on waiting for PPU on
Subject: [PATCH 11/34] 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: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -1,7 +1,7 @@
From 69092f83541e6539ab82eec3052325c403675de4 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 16 Jan 2024 16:00:55 +0100
Subject: [PATCH 12/33] net: dsa: Support MDB memberships whose L2 addresses
Subject: [PATCH 12/34] net: dsa: Support MDB memberships whose L2 addresses
overlap
Organization: Addiva Elektronik
@@ -29,6 +29,8 @@ as long as the count is positive. Fortunately, all the infrastructure
needed to do this is already in place, since it is also needed on CPU
and DSA ports. Thus, "implement" this by simply removing the guards
which previously skipped reference countung on user ports.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
net/dsa/switch.c | 16 ----------------
1 file changed, 16 deletions(-)
@@ -1,7 +1,7 @@
From 7c19df77212d0728874515e97cf297863a6ff2cd Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 19 Sep 2023 18:38:10 +0200
Subject: [PATCH 13/33] net: phy: marvell10g: Support firmware loading on
Subject: [PATCH 13/34] net: phy: marvell10g: Support firmware loading on
88X3310
Organization: Addiva Elektronik
@@ -11,6 +11,8 @@ its RAM, ask userspace for the binary and load it over XMDIO.
We have no choice but to bail out of the probe if firmware is not
available, as the device does not have any built-in image on which to
fall back.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/phy/marvell10g.c | 161 +++++++++++++++++++++++++++++++++++
1 file changed, 161 insertions(+)
@@ -1,13 +1,15 @@
From 0c34b42b7a72ddf1af6f3534870d647801e493fa Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 21 Nov 2023 20:15:24 +0100
Subject: [PATCH 14/33] net: phy: marvell10g: Fix power-up when strapped to
Subject: [PATCH 14/34] 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
affected by this setting.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/phy/marvell10g.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
@@ -1,7 +1,7 @@
From 6576918d3348f8e20802379d568d7632228af4d7 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 15 Nov 2023 20:58:42 +0100
Subject: [PATCH 15/33] net: phy: marvell10g: Add LED support for 88X3310
Subject: [PATCH 15/34] net: phy: marvell10g: Add LED support for 88X3310
Organization: Addiva Elektronik
Pickup the LEDs from the state in which the hardware reset or
@@ -17,6 +17,8 @@ Trigger support:
software blinking
- "netdev": Offload link or duplex information to the solid behavior;
tx and/or rx activity to blink behavior.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/phy/marvell10g.c | 422 +++++++++++++++++++++++++++++++++++
1 file changed, 422 insertions(+)
@@ -1,7 +1,7 @@
From 1ad7f010e46133c725df5cab4d85f71f689ca191 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 12 Dec 2023 09:51:05 +0100
Subject: [PATCH 16/33] net: phy: marvell10g: Support LEDs tied to a single
Subject: [PATCH 16/34] net: phy: marvell10g: Support LEDs tied to a single
media side
Organization: Addiva Elektronik
@@ -14,6 +14,8 @@ tied to a particular media side, and use that information to refine
the offloading of the "netdev" trigger, such that LEDs attached to the
RJ45 jack only lights up when a copper link is established, and vice
versa for the SFP cage.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/phy/marvell10g.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
@@ -1,7 +1,7 @@
From 11b9a3e328241edede03b6615bb9b0f1a40b9b7d 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/33] nvmem: layouts: onie-tlv: Let device probe even when
Subject: [PATCH 17/34] nvmem: layouts: onie-tlv: Let device probe even when
TLV is invalid
Organization: Addiva Elektronik
@@ -13,6 +13,8 @@ be successfully probed.
Therefore, settle for reporting data corruption issues in the log, and
simply refrain from registering any cells in those cases.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/nvmem/layouts/onie-tlv.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -1,7 +1,7 @@
From ce1148b5c2e33541ad13ff2c4769d0b37d4e42b9 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/33] net: bridge: avoid classifying unknown multicast as
Subject: [PATCH 18/34] net: bridge: avoid classifying unknown multicast as
mrouters_only
Organization: Addiva Elektronik
@@ -1,7 +1,7 @@
From ce74ee8c5461cc53851ca323b4dfc9937cab0e41 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/33] net: bridge: Ignore router ports when forwarding L2
Subject: [PATCH 19/34] net: bridge: Ignore router ports when forwarding L2
multicast
Organization: Addiva Elektronik
@@ -1,9 +1,10 @@
From 3c9b05198e0b7193f2dcddc1860cd77f0adbc3a2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 21 Mar 2024 19:12:15 +0100
Subject: [PATCH 20/33] net: dsa: Support EtherType based priority overrides
Subject: [PATCH 20/34] net: dsa: Support EtherType based priority overrides
Organization: Addiva Elektronik
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
include/net/dsa.h | 4 ++++
net/dsa/slave.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
@@ -1,10 +1,11 @@
From 333134a4ff2b8dd7fb00a75560254de96d1082ad Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Fri, 22 Mar 2024 16:15:43 +0100
Subject: [PATCH 21/33] net: dsa: mv88e6xxx: Support EtherType based priority
Subject: [PATCH 21/34] net: dsa: mv88e6xxx: Support EtherType based priority
overrides
Organization: Addiva Elektronik
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 64 +++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/chip.h | 21 ++++++++++
@@ -1,7 +1,7 @@
From cdddc24c05cedc0d0fabc48da17ec26aeb7c1ef9 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 27 Mar 2024 10:10:19 +0100
Subject: [PATCH 22/33] net: phy: Do not resume PHY when attaching
Subject: [PATCH 22/34] net: phy: Do not resume PHY when attaching
Organization: Addiva Elektronik
The PHY should not start negotiating with its link-partner until
@@ -15,6 +15,8 @@ Otherwise, drivers that attached to their PHYs during
probing (e.g. DSA) would end up with a physical link being
established, even though the corresponding interface was still
administratively down.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/phy/phy_device.c | 1 -
1 file changed, 1 deletion(-)
@@ -1,7 +1,7 @@
From 1ec21a3fc54fb447501fd7edbf692b00a31fe3ec Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 27 Mar 2024 15:52:43 +0100
Subject: [PATCH 23/33] net: dsa: mv88e6xxx: Improve indirect register access
Subject: [PATCH 23/34] net: dsa: mv88e6xxx: Improve indirect register access
perf on 6393
Organization: Addiva Elektronik
@@ -13,6 +13,8 @@ previous families).
Therefore, add a new set of SMI operations which remaps accesses to
such registers to the corresponding directly addressable register. All
other accesses use the regular indirect interface.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 7 +++
drivers/net/dsa/mv88e6xxx/global1.h | 3 ++
@@ -1,7 +1,7 @@
From 5d7be493dcaa75ee69d521043062389d7772f8dc Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Thu, 4 Apr 2024 16:36:30 +0200
Subject: [PATCH 24/33] net: bridge: drop delay for applying strict multicast
Subject: [PATCH 24/34] net: bridge: drop delay for applying strict multicast
filtering
Organization: Addiva Elektronik
@@ -1,7 +1,7 @@
From 492a824661dbc188b5abeb7434b5cf67c2016415 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Mon, 22 Apr 2024 23:18:01 +0200
Subject: [PATCH 25/33] net: dsa: mv88e6xxx: Honor ports being managed via
Subject: [PATCH 25/34] net: dsa: mv88e6xxx: Honor ports being managed via
in-band-status
Organization: Addiva Elektronik
@@ -13,6 +13,8 @@ USXGMII autoneg)
This state is the default set up by mv88e6xxx_port_setup_mac(), so all
we have to do is to make the phylink MAC callbacks no-ops in cases
when in-band-status is being used.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++++
1 file changed, 6 insertions(+)
@@ -1,7 +1,7 @@
From c9c9597a47b00b720f5223c83ab05bb89481eda8 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 24 Apr 2024 21:35:26 +0200
Subject: [PATCH 26/33] net: dsa: mv88e6xxx: Fix port policy config on 6393X
Subject: [PATCH 26/34] net: dsa: mv88e6xxx: Fix port policy config on 6393X
Organization: Addiva Elektronik
mv88e6393x_port_policy_{read,write} expect the `pointer` argument to
@@ -16,6 +16,7 @@ never enabled on DSA ports, which broke standalone port isolation in
multichip switch trees made up of 6393X decices.
Fixes: 6584b26020fc ("net: dsa: mv88e6xxx: implement .port_set_policy for Amethyst")
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/port.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -1,7 +1,7 @@
From 4ff224b5f5de1347a1f686aa85cb918a7db18879 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 24 Apr 2024 22:41:04 +0200
Subject: [PATCH 27/33] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
Subject: [PATCH 27/34] net: dsa: mv88e6xxx: Limit rsvd2cpu policy to user
ports on 6393X
Organization: Addiva Elektronik
@@ -29,6 +29,8 @@ Before this change, due to rsvd2cpu being enabled on the CPU port, the
switch would try to trap it back to the CPU. Given that the CPU is
trusted, instead assume that it indeed meant for the packet to be
forwarded like any other.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/port.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
@@ -1,7 +1,7 @@
From f0d4beabe769fec594b309c3f1ebb79cfdbede8b Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 29 Apr 2024 15:14:51 +0200
Subject: [PATCH 28/33] usb: core: adjust log level for unauthorized devices
Subject: [PATCH 28/34] usb: core: adjust log level for unauthorized devices
Organization: Addiva Elektronik
The fact that a USB device currently is not authorized is not an error,
@@ -1,7 +1,7 @@
From 5f96d718c850084504c53ec0b8d9fcf75ea9996c Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 15 May 2024 13:50:58 +0200
Subject: [PATCH 29/33] net: dsa: mv88e6xxx: Grab register lock during counter
Subject: [PATCH 29/34] net: dsa: mv88e6xxx: Grab register lock during counter
snapshotting
Organization: Addiva Elektronik
@@ -9,6 +9,8 @@ This was missing for the standard counter groups. Since no caller
already holds the lock, opt for pushing the locking down into
mv88e6xxx_stats_snapshot() rather than having it duplicated at each
call site.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
@@ -1,7 +1,7 @@
From 6d4c436335003259cc02a0f015fd3d1d54e988a2 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 May 2024 14:51:54 +0200
Subject: [PATCH 30/33] net: bridge: Differentiate MDB additions from
Subject: [PATCH 30/34] net: bridge: Differentiate MDB additions from
modifications
Organization: Addiva Elektronik
@@ -21,6 +21,8 @@ generated.
Therefore, discriminate new groups from changes to existing groups by
introducing a RTM_SETMDB events to be used in the latter scenario.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
include/uapi/linux/rtnetlink.h | 2 ++
net/bridge/br_mdb.c | 4 ++--
@@ -1,7 +1,7 @@
From c333c612688d5e974b95fcf4b04f185d7cf4f80d Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 28 May 2024 10:38:42 +0200
Subject: [PATCH 31/33] net: dsa: tag_dsa: Use tag priority as initial
Subject: [PATCH 31/34] net: dsa: tag_dsa: Use tag priority as initial
skb->priority
Organization: Addiva Elektronik
@@ -19,6 +19,8 @@ Ideally we could then map this priority to an internal one, like we
can do with an "ingress-qos-map" on VLAN interfaces. Until that is
implemented, support the setup that is likely to be the most common; a
1:1 mapping from FPri to skb->priority.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
net/dsa/tag_dsa.c | 7 +++++++
1 file changed, 7 insertions(+)
@@ -1,7 +1,7 @@
From 18c025745fd8b8c9b3e688e9d78668a56cf71217 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 28 May 2024 11:04:22 +0200
Subject: [PATCH 32/33] net: dsa: mv88e6xxx: Add mqprio qdisc support
Subject: [PATCH 32/34] net: dsa: mv88e6xxx: Add mqprio qdisc support
Organization: Addiva Elektronik
Add support for attaching mqprio qdisc's to mv88e6xxx ports and use
@@ -24,6 +24,8 @@ are effectively only specifying the QPri.
Since FPri is always a 3-bit field, even on older chips with only 4
physical queues, always report 8 queues and let the chip's policy
handle the mapping down to the "real" number.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 70 ++++++++++++++++++++++++++++++++
net/dsa/tag_dsa.c | 4 +-
@@ -1,7 +1,7 @@
From f2d4ff12c7a0e644cbeac6675b755fb4a87b362a Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Wed, 29 May 2024 13:20:41 +0200
Subject: [PATCH 33/33] net: dsa: mv88e6xxx: Use VLAN prio over IP when both
Subject: [PATCH 33/34] net: dsa: mv88e6xxx: Use VLAN prio over IP when both
are available
Organization: Addiva Elektronik
@@ -22,6 +22,8 @@ main reasons for choosing the new default:
packet's priority. As the packet then moves through the network
core over trusted VLAN trunks, the packet should keep its original
priority, independent of what inner protocol fields may indicate.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
@@ -0,0 +1,43 @@
From ceaaa4f44f9b3ec82c4e0a24c2322aae58fa3aa0 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Wed, 6 Nov 2024 15:39:33 +0100
Subject: [PATCH 34/34] net: dsa: mb88e6xxx: use EOPNOTSUPP for unsupported
flags
Organization: Addiva Elektronik
Make sure to return correct error code for unsupported flags, and
propagate any error.
Follow-up to a5cf5c0
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
drivers/net/dsa/mv88e6xxx/leds.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/leds.c b/drivers/net/dsa/mv88e6xxx/leds.c
index b2a55d96b506..fe1ed3ed2a8a 100644
--- a/drivers/net/dsa/mv88e6xxx/leds.c
+++ b/drivers/net/dsa/mv88e6xxx/leds.c
@@ -99,7 +99,7 @@ static int mv88e6393x_led_flags_to_mode(struct mv88e6xxx_led *led, unsigned long
return i;
}
- return -EINVAL;
+ return -EOPNOTSUPP;
}
static int mv88e6393x_led_mode_to_flags(struct mv88e6xxx_led *led, u8 mode,
@@ -216,6 +216,9 @@ static int mv88e6393x_led_hw_control_set(struct mv88e6xxx_led *led,
{
int mode = mv88e6393x_led_flags_to_mode(led, flags);
+ if (mode < 0)
+ return mode;
+
return mv88e6393x_led_set(led, mode);
}
--
2.43.0
+15 -11
View File
@@ -1,19 +1,23 @@
#!/bin/sh
set -e
usb_ports=$(cat /run/system.json | jq -r '.["usb-ports"] | map(.name) | unique | join(" ")')
if jq -e '.["usb-ports"]' /run/system.json > /dev/null; then
usb_ports=$(jq -r '.["usb-ports"] | map(.name) | unique | join(" ")' /run/system.json)
else
usb_ports=""
fi
gen_port()
{
local port="$1"
cat <<EOF
{
"class": "infix-hardware:usb",
"name": "$port",
"state": {
"admin-state": "unlocked"
}
}
port="$1"
cat <<EOF
{
"class": "infix-hardware:usb",
"name": "$port",
"state": {
"admin-state": "unlocked"
}
}
EOF
}
first=1
@@ -24,7 +28,7 @@ cat <<EOF
EOF
for port in $usb_ports; do
if [ $first -eq 0 ]; then
echo -n ','
echo -n ','
fi
first=0;
gen_port "$port"
+195 -192
View File
@@ -46,208 +46,211 @@ with infamy.Test() as test:
with test.step("Configure device"):
dut1.put_config_dict("ietf-interfaces",
dut1.put_config_dicts(
{
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"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": {
"vlans": {
"vlan": [
{
"vid": 55,
"untagged": [ d1send ],
"tagged": [ d1trunk, "br0" ],
"multicast": {
"snooping": True
}
},
{
"vid": 77,
"untagged": [ d1receiver ],
"tagged": [ d1trunk, "br0" ],
"multicast": {
"snooping": True
}
}
]
}
}
}
]
"name": d1send,
"enabled": True,
"bridge-port": {
"bridge": "br0",
"pvid": 55
}
})
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": 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": [
{
"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": {
"vlans": {
"vlan": [
{
"vid": 55,
"untagged": [ d2receive ],
"tagged": [ d2trunk, "br0" ],
"multicast": {
"snooping": True
}
},
{
"vid": 77,
"untagged": [ d2sender ],
"tagged": [ d2trunk, "br0" ],
"multicast": {
"snooping": True
}
}
]
}
}
"ip": "10.0.1.1",
"prefix-length": 24
}
]
},
"vlan": {
"id": 55,
"lower-layer-if": "br0"
}
})
dut2.put_config_dict("ietf-system", {
"system": {
"hostname": "dut2"
},
{
"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": {
"vlans": {
"vlan": [
{
"vid": 55,
"untagged": [ d1send ],
"tagged": [ d1trunk, "br0" ],
"multicast": {
"snooping": True
}
},
{
"vid": 77,
"untagged": [ d1receiver ],
"tagged": [ d1trunk, "br0" ],
"multicast": {
"snooping": True
}
}
]
}
}
}
]
}
},
"ietf-system": {
"system": {
"hostname": "dut1"
}
}
}
})
)
dut2.put_config_dicts(
{
"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": {
"vlans": {
"vlan": [
{
"vid": 55,
"untagged": [ d2receive ],
"tagged": [ d2trunk, "br0" ],
"multicast": {
"snooping": True
}
},
{
"vid": 77,
"untagged": [ d2sender ],
"tagged": [ d2trunk, "br0" ],
"multicast": {
"snooping": True
}
}
]
}
}
}
]
}
},
"ietf-system": {
"system": {
"hostname": "dut2"
}
}
})
with infamy.IsolatedMacVlan(hsendd1) as d1send_ns, \
infamy.IsolatedMacVlan(hreceived1) as d1receive_ns, \
@@ -16,10 +16,12 @@ endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUT
. Set up VLAN interface on host:data with IP 10.0.0.1
. Configure VLAN 10 interface on target:data with IP 10.0.0.2
. Waiting for links to come up
. Ping 10.0.0.2 from VLAN 10 on host:data with IP 10.0.0.1
. Remove VLAN interface from target:data, and test again (should not be able to ping)
. Wait for links to come up
. Verify that host:data can reach 10.0.0.2
. Remove VLAN interface from target:data
. Verify that host:data can no longer reach 10.0.0.2
<<<
+16 -24
View File
@@ -10,31 +10,21 @@ import infamy.iface as iface
from infamy import until
def test_ping(hport, should_pass):
with infamy.IsolatedMacVlan(hport) as ns:
try:
ns.runsh("""
set -ex
ip link set iface up
ip link add dev vlan10 link iface up type vlan id 10
ip addr add 10.0.0.1/24 dev vlan10
""")
if should_pass:
ns.must_reach("10.0.0.2")
else:
ns.must_not_reach("10.0.0.2")
except Exception as e:
print(f"An error occurred during the VLAN setup or ping test: {e}")
raise
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUT"):
env = infamy.Env()
target = env.attach("target", "mgmt")
_, tport = env.ltop.xlate("target", "data")
with test.step("Set up VLAN interface on host:data with IP 10.0.0.1"):
_, hport = env.ltop.xlate("host", "data")
datanet = infamy.IsolatedMacVlan(hport).start()
datanet.runsh("""
set -ex
ip link set iface up
ip link add dev vlan10 link iface up type vlan id 10
ip addr add 10.0.0.1/24 dev vlan10
""")
with test.step("Configure VLAN 10 interface on target:data with IP 10.0.0.2"):
target.put_config_dict("ietf-interfaces", {
@@ -64,16 +54,18 @@ with infamy.Test() as test:
}
})
with test.step("Waiting for links to come up"):
with test.step("Wait for links to come up"):
until(lambda: iface.get_param(target, tport, "oper-status") == "up")
with test.step("Ping 10.0.0.2 from VLAN 10 on host:data with IP 10.0.0.1"):
with test.step("Verify that host:data can reach 10.0.0.2"):
_, hport = env.ltop.xlate("host", "data")
test_ping(hport,True)
datanet.must_reach("10.0.0.2")
with test.step("Remove VLAN interface from target:data, and test again (should not be able to ping)"):
with test.step("Remove VLAN interface from target:data"):
target.delete_xpath(f"/ietf-interfaces:interfaces/interface[name='{tport}.10']")
with test.step("Verify that host:data can no longer reach 10.0.0.2"):
_, hport = env.ltop.xlate("host", "data")
test_ping(hport,False)
datanet.must_not_reach("10.0.0.2")
test.succeed()
+2
View File
@@ -11,3 +11,5 @@ include::ospf_basic/Readme.adoc[]
include::ospf_unnumbered_interface/Readme.adoc[]
include::ospf_multiarea/Readme.adoc[]
include::ospf_bfd/Readme.adoc[]
+3
View File
@@ -10,3 +10,6 @@
- name: ospf_multiarea
case: ospf_multiarea/test.py
- name: ospf_bfd
case: ospf_bfd/test.py
@@ -0,0 +1,35 @@
=== OSPF BFD
==== Description
Verify that a router running OSPF, with Bidirectional Forwarding
Detection (BFD) enabled, will detect link faults even when the
physical layer is still operational.
This can typically happen when one logical link, from OSPF's
perspective, is made up of multiple physical links containing media
converters without link fault forwarding.
==== Topology
ifdef::topdoc[]
image::../../test/case/ietf_routing/ospf_bfd/topology.svg[OSPF BFD topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::ospf_bfd/topology.svg[OSPF BFD topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[OSPF BFD topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUTs
. Setup TPMR between R1fast and R2fast
. Configure R1 and R2
. Setup IP addresses and default routes on h1 and h2
. Wait for R1 and R2 to peer
. Verify connectivity from PC:src to PC:dst via fast link
. Disable forwarding between R1fast and R2fast to trigger fail-over
. Verify connectivity from PC:src to PC:dst via slow link
<<<
+183
View File
@@ -0,0 +1,183 @@
#!/usr/bin/env python3
"""
OSPF BFD
Verify that a router running OSPF, with Bidirectional Forwarding
Detection (BFD) enabled, will detect link faults even when the
physical layer is still operational.
This can typically happen when one logical link, from OSPF's
perspective, is made up of multiple physical links containing media
converters without link fault forwarding.
"""
import time
import infamy
import infamy.route as route
from infamy.netns import TPMR
from infamy.util import until, parallel
def config(target, params):
name = params["name"]
dif, fif, sif = \
params["link"]["data"], \
params["link"]["fast"], \
params["link"]["slow"]
rid, daddr, faddr, saddr = \
params["addr"]["rid"], \
params["addr"]["data"], \
params["addr"]["fast"], \
params["addr"]["slow"]
def ifconfig(name, addr, plen):
return {
"name": name,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": addr,
"prefix-length": plen,
}]}
}
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
ifconfig("lo", rid, 32),
ifconfig(dif, daddr, 24),
ifconfig(fif, faddr, 30),
ifconfig(sif, saddr, 30),
]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": name,
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces":
{
"interface": [{
"bfd": {
"enabled": True
},
"name": fif,
"hello-interval": 1,
"dead-interval": 10,
"cost": 100,
},
{
"bfd": {
"enabled": True
},
"name": sif,
"hello-interval": 1,
"dead-interval": 10,
"cost": 200,
}, {
"name": dif,
"passive": True,
}]
},
}]
}
}
}]
}
}
})
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUTs"):
env = infamy.Env()
R1 = env.attach("R1", "mgmt")
R2 = env.attach("R2", "mgmt")
with test.step("Setup TPMR between R1fast and R2fast"):
breaker = TPMR(env.ltop.xlate("PC", "R1fast")[1],
env.ltop.xlate("PC", "R2fast")[1]).start()
with test.step("Configure R1 and R2"):
r1cfg = {
"name": "R1",
"addr": {
"rid": "192.168.1.1",
"data": "192.168.10.1",
"fast": "192.168.100.1",
"slow": "192.168.200.1",
},
"link": {
"data": env.ltop.xlate("R1", "h1")[1],
"fast": env.ltop.xlate("R1", "fast")[1],
"slow": env.ltop.xlate("R1", "slow")[1],
}
}
r2cfg = {
"name": "R2",
"addr": {
"rid": "192.168.1.2",
"data": "192.168.20.1",
"fast": "192.168.100.2",
"slow": "192.168.200.2",
},
"link": {
"data": env.ltop.xlate("R2", "h2")[1],
"fast": env.ltop.xlate("R2", "fast")[1],
"slow": env.ltop.xlate("R2", "slow")[1],
}
}
parallel(config(R1, r1cfg), config(R2, r2cfg))
with test.step("Setup IP addresses and default routes on h1 and h2"):
_, h1 = env.ltop.xlate("PC", "h1")
_, h2 = env.ltop.xlate("PC", "h2")
h1net = infamy.IsolatedMacVlan(h1).start()
h1net.addip("192.168.10.2")
h1net.addroute("default", "192.168.10.1")
h2net = infamy.IsolatedMacVlan(h2).start()
h2net.addip("192.168.20.2")
h2net.addroute("default", "192.168.20.1")
with test.step("Wait for R1 and R2 to peer"):
print("Waiting for R1 and R2 to peer")
until(lambda: route.ipv4_route_exist(R1, "192.168.20.0/24", "192.168.100.2", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R2, "192.168.10.0/24", "192.168.100.1", proto="ietf-ospf:ospfv2"), attempts=200)
with test.step("Verify connectivity from PC:src to PC:dst via fast link"):
h1net.must_reach("192.168.20.2")
hops = [row[1] for row in h1net.traceroute("192.168.20.2")]
assert "192.168.100.2" in hops, f"Path to h2 ({repr(hops)}), does not use fast link"
with test.step("Disable forwarding between R1fast and R2fast to trigger fail-over"):
breaker.block()
print("Give BFD some time to detect the bad link, " +
"but not enough for the OSPF dead interval expire")
time.sleep(1)
with test.step("Verify connectivity from PC:src to PC:dst via slow link"):
h1net.must_reach("192.168.20.2")
hops = [row[1] for row in h1net.traceroute("192.168.20.2")]
assert "192.168.200.2" in hops, f"Path to h2 ({repr(hops)}), does not use slow link"
test.succeed()
@@ -0,0 +1,39 @@
graph "ospf-bfd" {
layout="neato";
overlap="false";
esep="+20";
size=10
node [shape=record, fontname="DejaVu Sans Mono, Book"];
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
R1 [
label=" { { R1 | <slow> slow } | { <mgmt> mgmt | <h1> h1 | <fast> fast } }",
pos="0,6!",
kind="infix",
];
R2 [
label="{ { <slow> slow | R2 } | { <fast> fast | <h2> h2 | <mgmt> mgmt } }",
pos="18,6!",
kind="infix",
];
PC [
label="{ { <R1mgmt> R1mgmt | <h1> h1 | <R1fast> R1fast | <R2fast> R2fast | <h2> h2 | <R2mgmt> R2mgmt } | PC }",
pos="9,0!",
kind="controller",
];
PC:R1mgmt -- R1:mgmt [kind=mgmt, color="lightgray"]
PC:R2mgmt -- R2:mgmt [kind=mgmt, color="lightgray"]
PC:h1 -- R1:h1
PC:h2 -- R2:h2
R1:fast -- PC:R1fast [color="lightgreen", taillabel="Cost: 100"]
R2:fast -- PC:R2fast [color="lightgreen"]
R1:slow -- R2:slow [color="crimson", taillabel="Cost: 200"]
}
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Title: ospf&#45;bfd Pages: 1 -->
<svg width="432pt" height="156pt"
viewBox="0.00 0.00 432.03 155.51" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 151.51)">
<title>ospf&#45;bfd</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-151.51 428.03,-151.51 428.03,4 -4,4"/>
<!-- R1 -->
<g id="node1" class="node">
<title>R1</title>
<polygon fill="none" stroke="black" points="0,-97.51 0,-143.51 133,-143.51 133,-97.51 0,-97.51"/>
<text text-anchor="middle" x="29" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1</text>
<polyline fill="none" stroke="black" points="58,-120.51 58,-143.51 "/>
<text text-anchor="middle" x="95.5" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">slow</text>
<polyline fill="none" stroke="black" points="0,-120.51 133,-120.51 "/>
<text text-anchor="middle" x="25" y="-105.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="50,-97.51 50,-120.51 "/>
<text text-anchor="middle" x="66.5" y="-105.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">h1</text>
<polyline fill="none" stroke="black" points="83,-97.51 83,-120.51 "/>
<text text-anchor="middle" x="108" y="-105.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">fast</text>
</g>
<!-- R2 -->
<g id="node2" class="node">
<title>R2</title>
<polygon fill="none" stroke="black" points="291.03,-97.51 291.03,-143.51 424.03,-143.51 424.03,-97.51 291.03,-97.51"/>
<text text-anchor="middle" x="328.53" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">slow</text>
<polyline fill="none" stroke="black" points="366.03,-120.51 366.03,-143.51 "/>
<text text-anchor="middle" x="395.03" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2</text>
<polyline fill="none" stroke="black" points="291.03,-120.51 424.03,-120.51 "/>
<text text-anchor="middle" x="316.03" y="-105.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">fast</text>
<polyline fill="none" stroke="black" points="341.03,-97.51 341.03,-120.51 "/>
<text text-anchor="middle" x="357.53" y="-105.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">h2</text>
<polyline fill="none" stroke="black" points="374.03,-97.51 374.03,-120.51 "/>
<text text-anchor="middle" x="399.03" y="-105.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
</g>
<!-- R1&#45;&#45;R2 -->
<g id="edge7" class="edge">
<title>R1:slow&#45;&#45;R2:slow</title>
<path fill="none" stroke="crimson" stroke-width="2" d="M133.5,-132.51C133.5,-132.51 290.53,-132.51 290.53,-132.51"/>
<text text-anchor="middle" x="168" y="-136.31" font-family="DejaVu Serif, Book" font-size="14.00">Cost: 200</text>
</g>
<!-- PC -->
<g id="node3" class="node">
<title>PC</title>
<polygon fill="none" stroke="black" points="47.01,-0.5 47.01,-46.5 377.01,-46.5 377.01,-0.5 47.01,-0.5"/>
<text text-anchor="middle" x="80.01" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1mgmt</text>
<polyline fill="none" stroke="black" points="113.01,-23.5 113.01,-46.5 "/>
<text text-anchor="middle" x="129.51" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">h1</text>
<polyline fill="none" stroke="black" points="146.01,-23.5 146.01,-46.5 "/>
<text text-anchor="middle" x="179.01" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1fast</text>
<polyline fill="none" stroke="black" points="212.01,-23.5 212.01,-46.5 "/>
<text text-anchor="middle" x="245.01" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2fast</text>
<polyline fill="none" stroke="black" points="278.01,-23.5 278.01,-46.5 "/>
<text text-anchor="middle" x="294.51" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">h2</text>
<polyline fill="none" stroke="black" points="311.01,-23.5 311.01,-46.5 "/>
<text text-anchor="middle" x="344.01" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2mgmt</text>
<polyline fill="none" stroke="black" points="47.01,-23.5 377.01,-23.5 "/>
<text text-anchor="middle" x="212.01" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">PC</text>
</g>
<!-- R1&#45;&#45;PC -->
<g id="edge5" class="edge">
<title>R1:fast&#45;&#45;PC:R1fast</title>
<path fill="none" stroke="lightgreen" stroke-width="2" d="M133.5,-108.51C133.5,-108.51 179.01,-46.5 179.01,-46.5"/>
<text text-anchor="middle" x="168" y="-112.31" font-family="DejaVu Serif, Book" font-size="14.00">Cost: 100</text>
</g>
<!-- R2&#45;&#45;PC -->
<g id="edge6" class="edge">
<title>R2:fast&#45;&#45;PC:R2fast</title>
<path fill="none" stroke="lightgreen" stroke-width="2" d="M290.53,-108.51C290.53,-108.51 245.01,-46.5 245.01,-46.5"/>
</g>
<!-- PC&#45;&#45;R1 -->
<g id="edge1" class="edge">
<title>PC:R1mgmt&#45;&#45;R1:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M80.01,-46.5C80.01,-46.5 24.5,-97.51 24.5,-97.51"/>
</g>
<!-- PC&#45;&#45;R1 -->
<g id="edge3" class="edge">
<title>PC:h1&#45;&#45;R1:h1</title>
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M129.01,-46.5C129.01,-46.5 66.5,-97.51 66.5,-97.51"/>
</g>
<!-- PC&#45;&#45;R2 -->
<g id="edge2" class="edge">
<title>PC:R2mgmt&#45;&#45;R2:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M344.01,-46.5C344.01,-46.5 399.53,-97.51 399.53,-97.51"/>
</g>
<!-- PC&#45;&#45;R2 -->
<g id="edge4" class="edge">
<title>PC:h2&#45;&#45;R2:h2</title>
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M295.01,-46.5C295.01,-46.5 357.53,-97.51 357.53,-97.51"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

+352 -311
View File
@@ -54,7 +54,8 @@ import infamy
import infamy.route as route
from infamy.util import until, parallel
def config_target1(target, ring1, ring2, cross):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -65,7 +66,8 @@ def config_target1(target, ring1, ring2, cross):
"address": [{
"ip": "10.0.12.1",
"prefix-length": 30
}]}
}]
}
},
{
"name": ring2,
@@ -75,7 +77,8 @@ def config_target1(target, ring1, ring2, cross):
"address": [{
"ip": "10.0.41.2",
"prefix-length": 30
}]}
}]
}
},
{
"name": cross,
@@ -92,93 +95,103 @@ def config_target1(target, ring1, ring2, cross):
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"address": [
{
"ip": "11.0.8.1",
"prefix-length": 24
},
{
"ip": "10.0.0.1",
"prefix-length": 32
}]
},
{
"ip": "10.0.0.1",
"prefix-length": 32
}
]
}
}
]
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "10.0.0.1",
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces":
{
"interface": [{
"bfd": {
"enabled": True
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "10.0.0.1",
"areas": {
"area": [
{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [
{
"bfd": {
"enabled": True
},
"name": ring1,
"hello-interval": 1,
"enabled": True
}
]
}
},
"name": ring1,
"hello-interval": 1,
"enabled": True
}]
}
},{
"area-id": "0.0.0.1",
"area-type": "nssa-area",
"summary": False,
"interfaces":
{
"interface": [{
"bfd": {
"enabled": True
{
"area-id": "0.0.0.1",
"area-type": "nssa-area",
"summary": False,
"interfaces": {
"interface": [
{
"bfd": {
"enabled": True
},
"name": cross,
"hello-interval": 1,
"enabled": True,
"cost": 2000
},
{
"name": "lo",
"enabled": True
}
]
}
},
"name": cross,
"hello-interval": 1,
"enabled": True,
"cost": 2000
},
{
"name": "lo",
"enabled": True
}]
{
"area-id": "0.0.0.2",
"interfaces": {
"interface": [
{
"bfd": {
"enabled": True
},
"name": ring2,
"hello-interval": 1,
"enabled": True,
"interface-type": "point-to-point"
}
]
}
}
]
}
},{
"area-id": "0.0.0.2",
"interfaces":
{
"interface": [{
"bfd": {
"enabled": True
},
"name": ring2,
"hello-interval": 1,
"enabled": True,
"interface-type": "point-to-point"
}]
}
}]
}
}
}
}]
]
}
}
}
})
target.put_config_dict("ietf-system", {
},
"ietf-system": {
"system": {
"hostname": "R1"
}
})
}
})
def config_target2(target, ring1, ring2, cross):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -189,7 +202,8 @@ def config_target2(target, ring1, ring2, cross):
"address": [{
"ip": "10.0.23.1",
"prefix-length": 30
}]}
}]
}
},
{
"name": ring2,
@@ -199,7 +213,8 @@ def config_target2(target, ring1, ring2, cross):
"address": [{
"ip": "10.0.12.2",
"prefix-length": 30
}]}
}]
}
},
{
"name": cross,
@@ -209,212 +224,238 @@ def config_target2(target, ring1, ring2, cross):
"address": [{
"ip": "10.0.24.1",
"prefix-length": 30
}]}
}]
}
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [
{
"ip": "10.0.0.2",
"prefix-length": 32
},
{
"ip": "11.0.9.1",
"prefix-length": 24
},
{
"ip": "11.0.10.1",
"prefix-length": 24
},
{
"ip": "11.0.11.1",
"prefix-length": 24
},
{
"ip": "11.0.12.1",
"prefix-length": 24
},
{
"ip": "11.0.13.1",
"prefix-length": 24
},
{
"ip": "11.0.14.1",
"prefix-length": 24
},
{
"ip": "11.0.15.1",
"prefix-length": 24
}
]
}
}
]
}
},
"ietf-system": {
"system": {
"hostname": "R2"
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "1.1.1.1",
"areas": {
"area": [
{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [
{
"bfd": {
"enabled": True
},
"name": ring2,
"hello-interval": 1,
"enabled": True
},
{
"name": "lo",
"enabled": True
}
]
}
},
{
"area-id": "0.0.0.1",
"area-type": "nssa-area",
"summary": False,
"interfaces": {
"interface": [
{
"bfd": {
"enabled": True
},
"name": ring1,
"hello-interval": 1,
"enabled": True
}
]
}
},
{
"area-id": "0.0.0.2",
"interfaces": {
"interface": [
{
"bfd": {
"enabled": True
},
"name": cross,
"hello-interval": 1,
"cost": 2000,
"enabled": True
}
]
}
}
]
}
}
}
]
}
}
}
})
def config_target3(target, ring2, cross, link):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": ring2,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.23.2",
"prefix-length": 30
}]
}
},
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.3.1",
"prefix-length": 24
}]
}
},
{
"name": cross,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.13.2",
"prefix-length": 30
}]
}
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"ip": "10.0.0.2",
"ip": "10.0.0.3",
"prefix-length": 32
}, {
"ip": "11.0.9.1",
"prefix-length": 24
}, {
"ip": "11.0.10.1",
"prefix-length": 24
}, {
"ip": "11.0.11.1",
"prefix-length": 24
}, {
"ip": "11.0.12.1",
"prefix-length": 24
}, {
"ip": "11.0.13.1",
"prefix-length": 24
}, {
"ip": "11.0.14.1",
"prefix-length": 24
}, {
"ip": "11.0.15.1",
"prefix-length": 24
}]
}
}
]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": "R2"
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "1.1.1.1",
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [{
"bfd": {
"enabled": True
},
"name": ring2,
"hello-interval": 1,
"enabled": True
}, {
"name": "lo",
"enabled": True
}]
}
}, {
"area-id": "0.0.0.1",
"area-type": "nssa-area",
"summary": False,
"interfaces": {
"interface": [{
"bfd": {
"enabled": True
},
"name": ring1,
"hello-interval": 1,
}]
}
}, {
"area-id": "0.0.0.2",
"interfaces": {
"interface": [{
"bfd": {
"enabled": True
},
"name": cross,
"hello-interval": 1,
"cost": 2000
}]
}
}]
}
}
}]
}
}
})
def config_target3(target, ring2, cross, link):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": ring2,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.23.2",
"prefix-length": 30
}]
}
},
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.3.1",
"prefix-length": 24
}]
}
},
{
"name": cross,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.13.2",
"prefix-length": 30
}]
}
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"ip": "10.0.0.3",
"prefix-length": 32
}]
}
}
]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": "R3"
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"areas": {
"area": [{
"area-id": "0.0.0.1",
"area-type": "nssa-area",
"summary": False,
"interfaces": {
"interface": [{
"bfd": {
]
}
},
"ietf-system": {
"system": {
"hostname": "R3"
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "10.0.0.3",
"areas": {
"area": [{
"area-id": "0.0.0.1",
"area-type": "nssa-area",
"summary": False,
"interfaces": {
"interface": [{
"bfd": {
"enabled": True
},
"name": cross,
"hello-interval": 1,
"enabled": True,
"cost": 2000
}, {
"bfd": {
"enabled": True
},
"name": ring2,
"hello-interval": 1,
"enabled": True
},
"name": cross,
"hello-interval": 1,
"enabled": True,
"cost": 2000
}, {
"bfd": {
}, {
"name": link,
"enabled": True,
"passive": True
}, {
"name": "lo",
"enabled": True
},
"name": ring2,
"hello-interval": 1,
"enabled": True
}, {
"name": link,
"enabled": True,
"passive": True
}, {
"name": "lo",
"enabled": True
}]
}
}]
}]
}
}]
}
}
}
}]
}]
}
}
}
})
def config_target4(target, ring1, cross, link):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": ring1,
@@ -459,57 +500,57 @@ def config_target4(target, ring1, cross, link):
}
]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": "R4"
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"redistribute": {
"redistribute": [{
"protocol": "connected"
}]
},
"areas": {
"area": [{
"area-id": "0.0.0.2",
"interfaces": {
"interface": [{
"bfd": {
"enabled": True
},
"name": ring1,
"hello-interval": 1,
"enabled": True,
"interface-type": "point-to-point"
}, {
"bfd": {
"enabled": True
},
"name": cross,
"hello-interval": 1,
"enabled": True,
"cost": 5000
}, {
"name": "lo",
"enabled": True
},
"ietf-system": {
"system": {
"hostname": "R4"
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "10.0.0.4",
"redistribute": {
"redistribute": [{
"protocol": "connected"
}]
}
}]
},
"areas": {
"area": [{
"area-id": "0.0.0.2",
"interfaces": {
"interface": [{
"bfd": {
"enabled": True
},
"name": ring1,
"hello-interval": 1,
"enabled": True,
"interface-type": "point-to-point"
}, {
"bfd": {
"enabled": True
},
"name": cross,
"hello-interval": 1,
"enabled": True,
"cost": 5000
}, {
"name": "lo",
"enabled": True
}]
}
}]
}
}
}
}
]
]
}
}
}
})
+107 -104
View File
@@ -27,96 +27,99 @@ from infamy.util import until, parallel
def config_target1(target, data, link):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": data,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.10.1",
"prefix-length": 24
}]},
"ipv6": {
"forwarding": True,
"address": [{
"ip": "2001:db8:3c4d:10::1",
"prefix-length": 64
}]
}
},
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.50.1",
"prefix-length": 24
}]
},
"ipv6": {
"forwarding": True,
"address": [{
"ip": "2001:db8:3c4d:50::1",
"prefix-length": 64
}]
}
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"ip": "192.168.100.1",
"prefix-length": 32
}]
},
"ipv6": {
"address": [{
"ip": "2001:db8:3c4d:100::1",
"prefix-length": 128
}]
}
}
]
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": data,
"enabled": True,
"ipv4": {
"route": [{
"destination-prefix": "192.168.200.1/32",
"next-hop": {
"next-hop-address": "192.168.50.2"
}
"forwarding": True,
"address": [{
"ip": "192.168.10.1",
"prefix-length": 24
}]},
"ipv6": {
"forwarding": True,
"address": [{
"ip": "2001:db8:3c4d:10::1",
"prefix-length": 64
}]
}
},
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.50.1",
"prefix-length": 24
}]
},
"ipv6": {
"route": [{
"destination-prefix": "2001:db8:3c4d:200::1/128",
"next-hop": {
"next-hop-address": "2001:db8:3c4d:50::2"
}
"forwarding": True,
"address": [{
"ip": "2001:db8:3c4d:50::1",
"prefix-length": 64
}]
}
}
}]
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"ip": "192.168.100.1",
"prefix-length": 32
}]
},
"ipv6": {
"address": [{
"ip": "2001:db8:3c4d:100::1",
"prefix-length": 128
}]
}
}
]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "192.168.200.1/32",
"next-hop": {
"next-hop-address": "192.168.50.2"
}
}]
},
"ipv6": {
"route": [{
"destination-prefix": "2001:db8:3c4d:200::1/128",
"next-hop": {
"next-hop-address": "2001:db8:3c4d:50::2"
}
}]
}
}
}]
}
}
}
})
def config_target2(target, link):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -157,33 +160,33 @@ def config_target2(target, link):
}
]
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "0.0.0.0/0",
"next-hop": {
"next-hop-address": "192.168.50.1"
}
}]
},
"ipv6": {
"route": [{
"destination-prefix": "::/0",
"next-hop": {
"next-hop-address": "2001:db8:3c4d:50::1"
}
}]
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "0.0.0.0/0",
"next-hop": {
"next-hop-address": "192.168.50.1"
}
}]
},
"ipv6": {
"route": [{
"destination-prefix": "::/0",
"next-hop": {
"next-hop-address": "2001:db8:3c4d:50::1"
}
}]
}
}
}
}]
}]
}
}
}
})
+2 -2
View File
@@ -14,13 +14,13 @@ with infamy.Test() as test:
target = env.attach("target", "mgmt")
with test.step("Set timezone to Australia/Perth"):
target.put_config_dict("ietf-system", {
target.put_config_dicts({"ietf-system": {
"system": {
"clock": {
"timezone-name": "Australia/Perth" # always +8:00, no DTS
}
}
})
}})
with test.step("Verify current time offset is +08:00"):
current_datetime=target.get_current_time_with_offset()
@@ -13,13 +13,13 @@ with infamy.Test() as test:
target = env.attach("target", "mgmt")
with test.step("Set timezone UTC offset to +12"):
target.put_config_dict("ietf-system", {
target.put_config_dicts({"ietf-system": {
"system": {
"clock": {
"timezone-utc-offset": "12"
}
}
})
}})
with test.step("Verify current time offset is +12:00"):
current_datetime=target.get_current_time_with_offset()
+15 -6
View File
@@ -16,7 +16,7 @@ import lxml
import netconf_client.connect
import netconf_client.ncclient
import infamy.iface as iface
from infamy.transport import Transport
from infamy.transport import Transport,infer_put_dict
from netconf_client.error import RpcError
from . import env
@@ -214,7 +214,7 @@ class Device(Transport):
else:
return f"<filter type=\"xpath\" select=\"{xpath}\" {xmlns} />"
return None
def _parse_response(self, response, parse):
"""Helper function to handle XML response parsing."""
if not response:
@@ -273,10 +273,10 @@ class Device(Transport):
xpath_filter = self._build_xpath_filter(xpath, get_data_xpath=True)
response = self.ncc.get_data(datastore="ds:operational", filter=xpath_filter)
parsed_data = self._parse_response(response, parse)
if parse and parsed_data:
return parsed_data.print_dict()
return parsed_data
def get_config(self, xpath):
@@ -313,6 +313,16 @@ class Device(Transport):
continue
break
def put_config_dicts(self, models):
config = ""
infer_put_dict(self.name, models)
for model in models.keys():
mod = self.ly.get_module(model)
lyd = mod.parse_data_dict(models[model], no_state=True, validate=False)
config+=lyd.print_mem("xml", with_siblings=True, pretty=False)+"\n"
return self.put_config(config)
def put_config_dict(self, modname, edit):
"""Convert Python dictionary to XMl and send as configuration"""
mod = self.ly.get_module(modname)
@@ -344,8 +354,8 @@ class Device(Transport):
def get_schemas_list(self):
schemas = []
data = self.get_dict("/netconf-state")
for d in data["netconf-state"]["schemas"]["schema"]:
schema = {}
schema["identifier"] = d['identifier']
@@ -428,4 +438,3 @@ class Device(Transport):
return current_datetime.text
else:
raise ValueError("current-datetime element not found in the response")
+164 -27
View File
@@ -1,4 +1,5 @@
import ctypes
import json
import multiprocessing
import os
import random
@@ -18,31 +19,58 @@ def setns(fd, nstype):
__NR_setns = 308
__libc.syscall(__NR_setns, fd, nstype)
class IsolatedMacVlan:
"""Create an isolated interface on top of a PC interface."""
def __init__(self, parent, ifname="iface", lo=True):
class IsolatedMacVlans:
"""A network namespace containing a multiple MACVLANs
Stacks a MACVLAN on top of each specificed controller interface,
and moves those interfaces to a separate namespace, isolating it
from all others.
NOTE: For the simple case when only one interface needs to be
mapped, see IsolatedMacVlan below.
Example:
netns = IsolatedMacVlans({ "eth2": "a", "eth3": "b" })
netns:
.--------.
| a b | (MACVLANs)
'-+----+-'
| |
eth0 eth1 eth2 eth3
"""
Instances = []
def Cleanup():
for ns in list(IsolatedMacVlans.Instances):
ns.stop()
def __init__(self, ifmap, lo=True):
self.sleeper = None
self.parent, self.ifname, self.lo = parent, ifname, lo
self.ifmap, self.lo = ifmap, lo
self.ping_timeout = env.ENV.attr("ping_timeout", 5)
def __enter__(self):
def start(self):
self.sleeper = subprocess.Popen(["unshare", "-r", "-n", "sh", "-c",
"echo && exec sleep infinity"],
stdout=subprocess.PIPE)
self.sleeper.stdout.readline()
try:
subprocess.run(["ip", "link", "add",
"dev", self.ifname,
"link", self.parent,
"address", self._stable_mac(),
"netns", str(self.sleeper.pid),
"type", "macvlan"], check=True)
self.runsh(f"""
while ! ip link show dev {self.ifname}; do
sleep 0.1
done
""")
for parent, ifname in self.ifmap.items():
subprocess.run(["ip", "link", "add",
"dev", ifname,
"link", parent,
"address", self._stable_mac(parent),
"netns", str(self.sleeper.pid),
"type", "macvlan", "mode", "passthru"], check=True)
self.runsh(f"""
while ! ip link show dev {ifname}; do
sleep 0.1
done
""")
except Exception as e:
self.__exit__(None, None, None)
raise e
@@ -54,14 +82,43 @@ class IsolatedMacVlan:
self.__exit__(None, None, None)
raise e
self.Instances.append(self)
return self
def __exit__(self, val, typ, tb):
def stop(self):
self.sleeper.kill()
self.sleeper.wait()
time.sleep(0.5)
def _stable_mac(self):
for n in range(100):
promisc = False
for parent in self.ifmap.keys():
iplink = subprocess.run(f"ip -d -j link show dev {parent}".split(),
stdout=subprocess.PIPE, check=True)
link = json.loads(iplink.stdout)[0]
if link["promiscuity"]:
# Use promisc as a substitute for an indicator
# of whether the kernel has actually removed
# the passthru MACVLAN yet or not
promisc = True
break
if not promisc:
break
time.sleep(.1)
else:
raise TimeoutError("Lingering MACVLAN")
if self in self.Instances:
self.Instances.remove(self)
def __enter__(self):
return self.start()
def __exit__(self, val, typ, tb):
return self.stop()
def _stable_mac(self, parent):
"""Generate address for MACVLAN
By default, the kernel will assign a random address. This
@@ -75,7 +132,7 @@ class IsolatedMacVlan:
the resource exhaustion issue.
"""
random.seed(self.parent)
random.seed(parent)
a = list(random.randbytes(6))
a[0] |= 0x02
a[0] &= ~0x01
@@ -146,13 +203,13 @@ class IsolatedMacVlan:
ip -{p} route add {subnet}{prefix_length} via {nexthop}
""", check=True)
def addip(self, addr, prefix_length=24, proto="ipv4"):
def addip(self, ifname, addr, prefix_length=24, proto="ipv4"):
p=proto[3]
self.runsh(f"""
set -ex
ip link set iface up
ip -{p} addr add {addr}/{prefix_length} dev iface
ip -{p} addr add {addr}/{prefix_length} dev {ifname}
""", check=True)
@@ -188,8 +245,7 @@ class IsolatedMacVlan:
raise Exception(res)
def must_receive(self, expr, timeout=None, ifname=None, must=True):
ifname = ifname if ifname else self.ifname
def must_receive(self, expr, ifname, timeout=None, must=True):
timeout = timeout if timeout else self.ping_timeout
tshark = self.run(["tshark", "-nl", f"-i{ifname}",
@@ -207,10 +263,43 @@ class IsolatedMacVlan:
def must_not_receive(self, *args, **kwargs):
self.must_receive(*args, **kwargs, must=False)
def pcap(self, expr, ifname=None):
ifname = ifname if ifname else self.ifname
def pcap(self, expr, ifname):
return Pcap(self, ifname, expr)
class IsolatedMacVlan(IsolatedMacVlans):
"""A network namespace containing a single MACVLAN
Stacks a MACVLAN on top of an interface on the controller, and
moves that interface to a separate namespace, isolating it from
all other interfaces.
Example:
netns = IsolatedMacVlan("eth3")
netns:
.-------.
| iface | (MACVLAN)
'---+---'
|
eth0 eth1 eth2 eth3
"""
def __init__(self, parent, ifname="iface", lo=True):
self._ifname = ifname
return super().__init__(ifmap={ parent: ifname }, lo=lo)
def addip(self, addr, prefix_length=24, proto="ipv4"):
return super().addip(ifname=self._ifname, addr=addr, prefix_length=prefix_length, proto=proto)
def must_receive(self, expr, timeout=None, ifname=None, must=True):
ifname = ifname if ifname else self._ifname
return super().must_receive(expr=expr, ifname=ifname, timeout=timeout, must=must)
def pcap(self, expr, ifname=None):
ifname = ifname if ifname else self._ifname
return super().pcap(expr=expr, ifname=ifname)
class Pcap:
def __init__(self, netns, ifname, expr):
self.netns, self.ifname, self.expr = netns, ifname, expr
@@ -253,7 +342,6 @@ class Pcap:
# terminating the capture.
time.sleep(sleep)
self.proc.send_signal(signal.SIGUSR2)
self.proc.terminate()
try:
_, stderr = self.proc.communicate(5)
@@ -272,3 +360,52 @@ class Pcap:
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
text=True, check=True)
return tcpdump.stdout
class TPMR(IsolatedMacVlans):
"""Two-Port MAC Relay
Creates a network namespace containing two controller interfaces
(`a` and `b`). By default, tc rules are setup to copy all frames
ingressing on `a` to egress on `b`, and vice versa.
These rules can be removed and reinserted dynamically using the
`block()` and `forward()` methods, respectively.
This is useful to verify the correctness of fail-over behavior in
various protocols. See ospf_bfd for a usage example.
"""
def __init__(self, a, b):
super().__init__(ifmap={ a: "a", b: "b" }, lo=False)
def start(self, forward=True):
ret = super().start()
for dev in ("a", "b"):
self.run(f"ip link set dev {dev} promisc on up".split())
self.run(f"tc qdisc add dev {dev} clsact".split())
if forward:
self.forward()
return ret
def _clear_ingress(self, iface):
return self.run(f"tc filter del dev {iface} ingress".split())
def _add_redir(self, frm, to):
cmd = \
"tc filter add dev".split() \
+ [frm] \
+ "ingress matchall action mirred egress redirect dev".split() \
+ [to]
return self.run(cmd)
def forward(self):
for iface in ("a", "b"):
self._clear_ingress(iface)
self._add_redir(iface, "a" if iface == "b" else "b")
def block(self):
for iface in ("a", "b"):
self._clear_ingress(iface)
+14 -2
View File
@@ -10,7 +10,7 @@ import time
from requests.auth import HTTPBasicAuth
from urllib3.exceptions import InsecureRequestWarning
from dataclasses import dataclass
from infamy.transport import Transport
from infamy.transport import Transport, infer_put_dict
from . import env
# We know we have a self-signed certificate, silence warning about it
@@ -244,7 +244,7 @@ class Device(Transport):
# Directly pass the dictionary without using json.dumps
response = requests_workaround_put(
f"{self.restconf_url}/ds/ietf-datastores:{datastore}/",
f"{self.restconf_url}/ds/ietf-datastores:{datastore}",
json=data,
headers=self.headers,
auth=self.auth,
@@ -262,6 +262,18 @@ class Device(Transport):
for k, v in ds.items():
return {container: v}
def put_config_dicts(self, models):
infer_put_dict(self.name, models)
running = self.get_running()
for model in models.keys():
mod = self.lyctx.get_module(model)
lyd = mod.parse_data_dict(models[model], no_state=True, validate=False)
running.merge(lyd)
return self.put_datastore("running", json.loads(running.print_mem("json", with_siblings=True, pretty=False)))
def put_config_dict(self, modname, edit):
"""Add @edit to running config and put the whole configuration"""
+4
View File
@@ -4,6 +4,8 @@ import subprocess
import sys
import traceback
import infamy.netns
class Test:
def __init__(self, output=sys.stdout):
self.out = output
@@ -24,6 +26,8 @@ class Test:
self.out.write(f"# Exiting ({now})\n")
self.out.flush()
infamy.netns.IsolatedMacVlans.Cleanup()
if not e:
self._not_ok("Missing explicit test result\n")
else:
+8
View File
@@ -1,6 +1,14 @@
from abc import ABC, abstractmethod
from infamy.neigh import ll6ping
def infer_put_dict(name, models):
if not models.get("ietf-system"):
models["ietf-system"] = { "system": { "hostname": name} }
else:
if not models["ietf-system"].get("system"):
models["ieft-system"]["system"] = {}
if not models["ietf-system"]["system"].get("hostname"):
models["ietf-system"]["system"]["hostname"] = name
class Transport(ABC):
"""Common functions for NETCONF/RESTCONF"""