Skip to content

Commit

Permalink
Merge pull request #867 from kernelkit/stp
Browse files Browse the repository at this point in the history
STP
  • Loading branch information
wkz authored Jan 8, 2025
2 parents 49a0030 + f3f313b commit ac0acfe
Show file tree
Hide file tree
Showing 37 changed files with 966 additions and 19 deletions.
8 changes: 8 additions & 0 deletions board/common/rootfs/etc/finit.d/available/mstpd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# A single mstpd instance can manage multiple bridges, which are
# dynamically added/removed by the kernel via the /sbin/bridge-stp
# usermode helper. We depend on usr/mstpd so that confd can
# enable/disable the service without an initctl barrier, since it
# needs to already be running when a bridge interface with spanning
# tree enabled is created.
service env:-/etc/default/mstpd <!usr/mstpd> \
[S0123456789] mstpd $MSTPD_ARGS -- Spanning Tree daemon
1 change: 1 addition & 0 deletions board/common/rootfs/etc/finit.d/enabled/mstpd.conf
1 change: 1 addition & 0 deletions configs/aarch64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_IPTABLES_NFTABLES=y
BR2_PACKAGE_IPUTILS=y
BR2_PACKAGE_LLDPD=y
BR2_PACKAGE_MSTPD=y
BR2_PACKAGE_NETCALC=y
BR2_PACKAGE_NETCAT_OPENBSD=y
BR2_PACKAGE_NETSNMP=y
Expand Down
1 change: 1 addition & 0 deletions configs/aarch64_minimal_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ BR2_PACKAGE_FRR=y
BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_IPUTILS=y
BR2_PACKAGE_LLDPD=y
BR2_PACKAGE_MSTPD=y
BR2_PACKAGE_NETCALC=y
BR2_PACKAGE_NGINX=y
BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y
Expand Down
1 change: 1 addition & 0 deletions configs/riscv64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_IPTABLES_NFTABLES=y
BR2_PACKAGE_IPUTILS=y
BR2_PACKAGE_LLDPD=y
BR2_PACKAGE_MSTPD=y
BR2_PACKAGE_NETCALC=y
BR2_PACKAGE_NETCAT_OPENBSD=y
BR2_PACKAGE_NETSNMP=y
Expand Down
1 change: 1 addition & 0 deletions configs/x86_64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_IPTABLES_NFTABLES=y
BR2_PACKAGE_IPUTILS=y
BR2_PACKAGE_LLDPD=y
BR2_PACKAGE_MSTPD=y
BR2_PACKAGE_NETCALC=y
BR2_PACKAGE_NETCAT_OPENBSD=y
BR2_PACKAGE_NETSNMP=y
Expand Down
1 change: 1 addition & 0 deletions configs/x86_64_minimal_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ BR2_PACKAGE_FRR=y
BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_IPUTILS=y
BR2_PACKAGE_LLDPD=y
BR2_PACKAGE_MSTPD=y
BR2_PACKAGE_NETCALC=y
BR2_PACKAGE_NGINX=y
BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y
Expand Down
1 change: 1 addition & 0 deletions doc/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ All notable changes to the project are documented in this file.
- SSH Server is now configurable, issue #441
SSH Server and NETCONF Server now uses the same SSH hostkey in factory-config
- Add support for GRE/GRETAP tunnels
- Support for STP/RSTP on bridges

### Fixes

Expand Down
3 changes: 3 additions & 0 deletions package/skeleton-init-finit/skeleton/etc/bridge-stp.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Daemon is managed by finit(1), /sbin/bridge-stp should assume that
# it is already running and simply add/remove bridges as necessary
MANAGE_MSTPD='n'
3 changes: 3 additions & 0 deletions package/skeleton-init-finit/skeleton/etc/default/mstpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -d: Do _not_ [sic] daemonize
# -s: Log to syslog
MSTPD_ARGS="-d -s"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Make sure to configure the bridge to run on before starting mstpd
# Note: all 'sysv' type services are handed an extra 'start' or 'stop'
# argument when starting and stopping.
sysv name:mstpd [0123456] pid:!/run/mstpd.pid bridge-stp br0 -- MSTP daemon
# A single mstpd instance can manage multiple bridges, which are
# dynamically added/removed by the kernel via the /sbin/bridge-stp
# usermode helper.
service [S0123456789] env:-/etc/default/mstpd mstpd $MSTPD_ARGS -- Spanning Tree daemon
3 changes: 2 additions & 1 deletion src/confd/bin/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pkglibexec_SCRIPTS = bootstrap error load gen-service gen-hostname \
gen-interfaces gen-motd gen-hardware gen-version
gen-interfaces gen-motd gen-hardware gen-version \
mstpd-wait-online
sbin_SCRIPTS = dagger migrate
16 changes: 16 additions & 0 deletions src/confd/bin/mstpd-wait-online
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh
#
# Block until mstpd has opened its control socket

set -e

timeout=${1:-10}

for _ in $(seq $((timeout * 10))); do
ss -Haxn src '@.mstp_server*' | grep -q mstp_server && exit 0
sleep .1
done

logger -I $$ -p user.error -t mstpd-wait-online \
"Timeout waiting for mstpd to start"
exit 1
5 changes: 4 additions & 1 deletion src/confd/src/dagger.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ enum netdag_init {
/* Interface specific setup (bridge VLAN PVID) of lowers */
NETDAG_INIT_LOWERS_PROTO = 65,

/* Start daemons running on interface (zcip etc.) */
/* Start/configure daemons on interface (mstpd, zcip etc.) */
NETDAG_INIT_DAEMON = 70,

/* Inject lower-specific configuration to daemon (mstpd) */
NETDAG_INIT_DAEMON_LOWERS = 75,
};

FILE *dagger_fopen_net_init(struct dagger *d, const char *node, enum netdag_init order,
Expand Down
5 changes: 5 additions & 0 deletions src/confd/src/ietf-interfaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,11 @@ static sr_error_t ifchange_post(sr_session_ctx_t *session, struct dagger *net,
*/
err = bridge_mcd_gen(cifs);

/* Whenever at least one bridge has spanning tree enabled,
* start mstpd; otherwise, stop it.
*/
err = err ? : bridge_mstpd_gen(cifs);

return err ? SR_ERR_INTERNAL : SR_ERR_OK;
}

Expand Down
1 change: 1 addition & 0 deletions src/confd/src/ietf-interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ int netdag_gen_ip_addrs(struct dagger *net, FILE *ip, const char *proto,
struct lyd_node *cif, struct lyd_node *dif);

/* infix-if-bridge.c */
int bridge_mstpd_gen(struct lyd_node *cifs);
int bridge_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip, int add);
/* infix-if-bridge-mcd.c */
int bridge_mcd_gen(struct lyd_node *cifs);
Expand Down
76 changes: 76 additions & 0 deletions src/confd/src/infix-if-bridge-port.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,78 @@

#include "ietf-interfaces.h"

static const char *mstpd_cost_str(struct lyd_node *cost)
{
const char *val = lyd_get_value(cost);

if (!strcmp(val, "auto"))
return "0";

return val;
}

static int gen_stp_tree(FILE *mstpctl, const char *iface,
const char *brname, struct lyd_node *tree)
{
int mstid = 0;

fprintf(mstpctl, "settreeportcost %s %s %d %s\n", brname, iface, mstid,
mstpd_cost_str(lydx_get_child(tree, "internal-path-cost")));

fprintf(mstpctl, "settreeportprio %s %s %d %s\n", brname, iface, mstid,
lydx_get_cattr(tree, "priority"));

return 0;
}

static int gen_stp(struct lyd_node *cif)
{
const char *brname, *edge, *iface;
struct lyd_node *stp, *cist;
FILE *mstpctl;
int err;

brname = lydx_get_cattr(lydx_get_child(cif, "bridge-port"), "bridge");
if (!brname)
return 0;

if (!lydx_get_xpathf(cif, "../interface[name='%s']/bridge/stp", brname))
return 0;

iface = lydx_get_cattr(cif, "name");
stp = lydx_get_descendant(lyd_child(cif), "bridge-port", "stp", NULL);

mstpctl = dagger_fopen_net_init(&confd.netdag, brname,
NETDAG_INIT_DAEMON_LOWERS, "init-ports.mstpctl");
if (!mstpctl)
return -EIO;

fputs("#!/sbin/mstpctl -b\n", mstpctl);

edge = lydx_get_cattr(stp, "edge");
if (!strcmp(edge, "true")) {
fprintf(mstpctl, "setportautoedge %s %s no\n", brname, iface);
fprintf(mstpctl, "setportadminedge %s %s yes\n", brname, iface);
} else if (!strcmp(edge, "false")) {
fprintf(mstpctl, "setportautoedge %s %s no\n", brname, iface);
fprintf(mstpctl, "setportadminedge %s %s no\n", brname, iface);
} else if (!strcmp(edge, "auto")) {
fprintf(mstpctl, "setportautoedge %s %s yes\n", brname, iface);
}

cist = lydx_get_child(stp, "cist");
err = gen_stp_tree(mstpctl, iface, brname, cist);
if (err)
goto out_close;

fprintf(mstpctl, "setportpathcost %s %s %s\n", brname, iface,
mstpd_cost_str(lydx_get_child(cist, "external-path-cost")));

out_close:
fclose(mstpctl);
return err;
}

static const char *get_port_egress_mode(const char *iface, int vid, const char *brname)
{
static const char *modes[] = { "tagged", "untagged", NULL };
Expand Down Expand Up @@ -237,5 +309,9 @@ int bridge_port_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip)
if (err)
return err;

err = gen_stp(cif);
if (err)
return err;

return 0;
}
89 changes: 89 additions & 0 deletions src/confd/src/infix-if-bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,91 @@ static int gen_vlan(struct ixif_br *br)

/* VLAN */

/* STP */

int bridge_mstpd_gen(struct lyd_node *cifs)
{
struct ly_set *stp_brs;
int n, err = 0;
FILE *cond;

if (lyd_find_xpath(cifs, "../interface/bridge/stp", &stp_brs))
return -EINVAL;

n = stp_brs->count;
ly_set_free(stp_brs, NULL);

if (n) {
cond = dagger_fopen_next(&confd.netdag, "init", "@pre", 50, "enable-mstpd.sh");
if (!cond)
return -EIO;

fputs("initctl -bnq cond set mstpd\n"
"/usr/libexec/confd/mstpd-wait-online || exit 1\n", cond);
fclose(cond);
} else if (!dagger_is_bootstrap(&confd.netdag)) {
cond = dagger_fopen_current(&confd.netdag, "exit", "@post", 50, "disable-mstpd.sh");
if (!cond)
return -EIO;

fputs("initctl -bnq cond clear mstpd\n", cond);
fclose(cond);
}

return err;
}

static int gen_stp(struct ixif_br *br)
{
struct lyd_node *stp;
FILE *mstpctl;

stp = lydx_get_descendant(lyd_child(br->cif), "bridge", "stp", NULL);
if (!stp) {
fputs(" stp_state 0", br->bropts.fp);
return 0;
}

fputs(" stp_state 1", br->bropts.fp);

if (lydx_get_descendant(lyd_child(br->cif), "bridge", "vlans", NULL))
/* Use the MSTP compatible mode of managing port
* states, rather then the legacy (and default)
* per-VLAN mode. */
fputs(" mst_enabled 1", br->bropts.fp);

mstpctl = dagger_fopen_net_init(&confd.netdag, br->name,
NETDAG_INIT_DAEMON, "init-br.mstpctl");
if (!mstpctl)
return -EIO;

fputs("#!/sbin/mstpctl -b\n", mstpctl);

fprintf(mstpctl, "setforcevers %s %s\n", br->name,
lydx_get_cattr(stp, "force-protocol"));

fprintf(mstpctl, "setfdelay %s %s\n", br->name,
lydx_get_cattr(stp, "forward-delay"));

fprintf(mstpctl, "setmaxage %s %s\n", br->name,
lydx_get_cattr(stp, "max-age"));

fprintf(mstpctl, "settxholdcount %s %s\n", br->name,
lydx_get_cattr(stp, "transmit-hold-count"));

fprintf(mstpctl, "setmaxhops %s %s\n", br->name,
lydx_get_cattr(stp, "max-hops"));

fprintf(mstpctl, "settreeprio %s 0 %s\n", br->name,
lydx_get_cattr(lydx_get_child(stp, "cist"), "priority"));

fclose(mstpctl);
return 0;

}

/* STP */

/* BR */

static void gen_phys_address(struct ixif_br *br)
Expand Down Expand Up @@ -420,6 +505,10 @@ int bridge_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip, int add)
fputs(" mcast_flood_always 1", br.bropts.fp);
fputs(" vlan_default_pvid 0", br.bropts.fp);

err = gen_stp(&br);
if (err)
goto out;

err = gen_vlan(&br);
if (err)
goto out;
Expand Down
2 changes: 1 addition & 1 deletion src/confd/yang/confd.inc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ MODULES=(
"[email protected]"
"[email protected]"
"[email protected]"
"infix-interfaces@2024-11-27.yang -e vlan-filtering"
"infix-interfaces@2025-01-08.yang -e vlan-filtering"

# from rousette
"[email protected]"
Expand Down
2 changes: 1 addition & 1 deletion src/confd/yang/containers.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- sh -*-
# REMEMBER TO UPDATE infix-interfaces ALSO IN confd.inc
MODULES=(
"infix-interfaces@2024-11-27.yang -e vlan-filtering -e containers"
"infix-interfaces@2025-01-08.yang -e vlan-filtering -e containers"
"[email protected]"
)
Loading

0 comments on commit ac0acfe

Please sign in to comment.