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

|
||||
@@ -16,21 +24,38 @@
|
||||
|
||||
## Data Plane
|
||||
|
||||
The blocks you ctose, and how you connect them, defines your data plane. Here we see an example of how to bridge a virtual port with a physical LAN.
|
||||
The blocks you choose, and how you connect them, defines your data plane.
|
||||
Here we see an example of how to bridge a virtual port with a physical
|
||||
LAN.
|
||||
|
||||

|
||||
|
||||
Depending on the (optional) VLAN filtering of the bridge, the container may have full or limited connectivity with outside ports, as well as the internal CPU.
|
||||
Depending on the (optional) VLAN filtering of the bridge, the container
|
||||
may have full or limited connectivity with outside ports, as well as the
|
||||
internal CPU.
|
||||
|
||||
In fact the virtual port connected to the bridge can be member of several VLANs, with each VLAN being an interface with an IP address inside the container.
|
||||
In fact the virtual port connected to the bridge can be member of
|
||||
several VLANs, with each VLAN being an interface with an IP address
|
||||
inside the container.
|
||||
|
||||
Thanks to Linux, and technologies like switchdev, that allow you to split a switching fabric into unique (isolated) ports, the full separation and virtualization of all Ethernet layer properties are possible to share with a container. Meaning, all the building blocks used on the left hand side can also be used freely on the right hand side as well.
|
||||
Thanks to Linux, and technologies like switchdev, that allow you to
|
||||
split a switching fabric into unique (isolated) ports, the full
|
||||
separation and virtualization of all Ethernet layer properties are
|
||||
possible to share with a container. Meaning, all the building blocks
|
||||
used on the left hand side can also be used freely on the right hand
|
||||
side as well.
|
||||
|
||||
### Bridging
|
||||
|
||||
This is the most central part of the system. A bridge is a switch, and a switch is a bridge. In Linux, setting up a bridge with ports connected to physical switch fabric, means you manage the actual switch fabric!
|
||||
This is the most central part of the system. A bridge is a switch, and
|
||||
a switch is a bridge. In Linux, setting up a bridge with ports
|
||||
connected to physical switch fabric, means you manage the actual switch
|
||||
fabric!
|
||||
|
||||
In Infix ports are by default not switch ports, unless the customer specific factory config sets it up this way. To enable switching between ports you create a bridge and then add ports to that bridge. That's it.
|
||||
In Infix ports are by default not switch ports, unless the customer
|
||||
specific factory config sets it up this way. To enable switching
|
||||
between ports you create a bridge and then add ports to that
|
||||
bridge. That's it.
|
||||
|
||||
```
|
||||
admin@example:/> configure
|
||||
@@ -43,12 +68,19 @@ admin@example:/config/> leave
|
||||
|
||||
Here we add two ports to bridge `br0`: `eth0` and `eth1`.
|
||||
|
||||
> **Note:** Infix has many built-in helpers controlled by convention. E.g., if you name your bridge `brN`, where `N` is a number, Infix will set the interface type automatically for you, and unlock all bridge features for you.
|
||||
> **Note:** Infix has many built-in helpers controlled by convention.
|
||||
> E.g., if you name your bridge `brN`, where `N` is a number, Infix sets
|
||||
> the interface type automatically and unlocks all bridge features.
|
||||
> Other "magic" names are `ethN.M` for VLAN M on top of `ethN`, or
|
||||
> `dockerN` to create an IP masquerading container bridge.
|
||||
|
||||
#### VLAN Filtering Bridge
|
||||
|
||||
By default bridges in Linux do not filter based on VLAN tags. It can be enabled in Infix when creating a bridge by adding a port to a VLAN as a tagged or untagged member.
|
||||
Use the port default VID (PVID) setting to control VLAN association for traffic ingressing a port untagged (default PVID: 1).
|
||||
By default bridges in Linux do not filter based on VLAN tags. It can be
|
||||
enabled in Infix when creating a bridge by adding a port to a VLAN as a
|
||||
tagged or untagged member. Use the port default VID (PVID) setting to
|
||||
control VLAN association for traffic ingressing a port untagged (default
|
||||
PVID: 1).
|
||||
|
||||
```
|
||||
admin@example:/config/> edit interface br0
|
||||
@@ -66,21 +98,32 @@ This sets `eth0` as an untagged member of VLAN 10 and `eth1` as an
|
||||
untagged member of VLAN 20. Switching between these ports is thus
|
||||
prohibited.
|
||||
|
||||
To terminate a VLAN in the switch itself, either for switch management or for routing, the bridge must become a (tagged) member of the VLAN.
|
||||
To terminate a VLAN in the switch itself, either for switch management
|
||||
or for routing, the bridge must become a (tagged) member of the VLAN.
|
||||
|
||||
```
|
||||
admin@example:/config/interface/br0/> set bridge vlans vlan 10 tagged br0
|
||||
admin@example:/config/interface/br0/> set bridge vlans vlan 20 tagged br0
|
||||
```
|
||||
> To route or to manage via a VLAN, a VLAN interface also needs to be created on top of the bridge, see section [VLAN Interfaces](#vlan-interfaces) below.
|
||||
|
||||
> To route or to manage via a VLAN, a VLAN interface needs to be created
|
||||
> on top of the bridge, see section [VLAN Interfaces](#vlan-interfaces)
|
||||
> below for more on this topic.
|
||||
|
||||
|
||||
### VLAN Interfaces
|
||||
|
||||
Creating a VLAN can be done in many ways. This section assumes VLAN interfaces created atop another Linux interface. E.g., the VLAN interfaces created on top of the Ethernet interface or bridge in the picture below.
|
||||
Creating a VLAN can be done in many ways. This section assumes VLAN
|
||||
interfaces created atop another Linux interface. E.g., the VLAN
|
||||
interfaces created on top of the Ethernet interface or bridge in the
|
||||
picture below.
|
||||
|
||||

|
||||
|
||||
A VLAN interface is basically a filtering abstraction. When you run `tcpdump` on a VLAN interface you will only see the frames matching the VLAN ID of the interface, compared to *all* the VLAN IDs if you run `tcpdump` on the lower-layer interface.
|
||||
A VLAN interface is basically a filtering abstraction. When you run
|
||||
`tcpdump` on a VLAN interface you will only see the frames matching the
|
||||
VLAN ID of the interface, compared to *all* the VLAN IDs if you run
|
||||
`tcpdump` on the lower-layer interface.
|
||||
|
||||
```
|
||||
admin@example:/> configure
|
||||
@@ -90,7 +133,8 @@ admin@example:/config/interface/eth0.20/> set vlan lower-layer-if eth0
|
||||
admin@example:/config/interface/eth0.20/> leave
|
||||
```
|
||||
|
||||
The example below assumes bridge br0 is already created, see [VLAN Filtering Bridge](#vlan-filtering-bridge).
|
||||
The example below assumes bridge br0 is already created, see [VLAN
|
||||
Filtering Bridge](#vlan-filtering-bridge).
|
||||
|
||||
```
|
||||
admin@example:/> configure
|
||||
@@ -100,15 +144,57 @@ admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0
|
||||
admin@example:/config/interface/vlan10/> leave
|
||||
```
|
||||
|
||||
As conventions, a VLAN interface for VID 20 on top of an Ethernet interface *eth0* is named *eth0.20*, and a VLAN interface for VID 10 on top of a bridge interface *br0* is named *vlan10*.
|
||||
As conventions, a VLAN interface for VID 20 on top of an Ethernet
|
||||
interface *eth0* is named *eth0.20*, and a VLAN interface for VID 10 on
|
||||
top of a bridge interface *br0* is named *vlan10*.
|
||||
|
||||
> **Note:** If you name your VLAN interface `foo0.N` or `vlanN`, where `N` is a number, Infix will set the interface type automatically for you.
|
||||
|
||||
|
||||
### VETH Pairs
|
||||
|
||||
A Virtual Ethernet (VETH) pair is basically a virtual Ethernet cable. A
|
||||
cable can be "plugged in" to a bridge and the other end can be given to
|
||||
a [container](container.md), or plugged into another bridge.
|
||||
|
||||
The latter example is useful if you have multiple bridges in the system
|
||||
with different properties (VLAN filtering, IEEE group forwarding, etc.),
|
||||
but still want some way of communicating between these domains.
|
||||
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit interface veth0a
|
||||
admin@example:/config/interface/veth0a/> set veth peer veth0b
|
||||
admin@example:/config/interface/veth0a/> end
|
||||
admin@example:/config/> diff
|
||||
interfaces {
|
||||
+ interface veth0a {
|
||||
+ type veth;
|
||||
+ veth {
|
||||
+ peer veth0b;
|
||||
+ }
|
||||
+ }
|
||||
+ interface veth0b {
|
||||
+ type veth;
|
||||
+ veth {
|
||||
+ peer veth0a;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
admin@example:/config/>
|
||||
```
|
||||
|
||||
> **Note:** this is another example of the automatic inference of the
|
||||
> interface type from the name. Any name can be used, but then you have
|
||||
> to set the interface type to `veth` manually.
|
||||
|
||||
|
||||
## Management Plane
|
||||
|
||||
This section details IP Addresses And Other Per-Interface IP settings.
|
||||
|
||||
Infix support several network interface types, each can be assigned one or more IP addresses, both IPv4 and IPv6 are supported.
|
||||
Infix support several network interface types, each can be assigned one
|
||||
or more IP addresses, both IPv4 and IPv6 are supported.
|
||||
|
||||

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