Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STP #867

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft

STP #867

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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 @@ -651,6 +651,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
Loading