mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-30 20:43:02 +02:00
confd: handle small changes to bridge port properties
This patch adds support for small incremental changes to bridge ports. Changes where the libyang diff does not include a bridge reference so that it will have to be synthesized from the current configuration. For example, forgetting to set a port's PVID in a VLAN filtering bridge setup, changing a bridge port's multicast flooding properties, or any other per-bridge-port setting after the fact. Fixes #349. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
committed by
Tobias Waldekranz
parent
ce2e15e4d2
commit
3ebbd0bf4f
@@ -745,6 +745,57 @@ static int netdag_gen_ethtool(struct dagger *net, struct lyd_node *cif, struct l
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brport_pvid_adjust(FILE *br, struct lyd_node *vlan, int vid, const char *brport,
|
||||
struct lydx_diff *pvidiff, int tagged)
|
||||
{
|
||||
const char *type = tagged ? "tagged" : "untagged";
|
||||
struct lyd_node *port;
|
||||
|
||||
LYX_LIST_FOR_EACH(lyd_child(vlan), port, type) {
|
||||
if (strcmp(brport, lyd_get_value(port)))
|
||||
continue;
|
||||
|
||||
if (pvidiff->old && atoi(pvidiff->old) == vid)
|
||||
fprintf(br, "vlan add vid %d dev %s %s\n", vid, brport, type);
|
||||
if (pvidiff->new && atoi(pvidiff->new) == vid)
|
||||
fprintf(br, "vlan add vid %d dev %s pvid %s\n", vid, brport, type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when only pvid is changed for a bridge-port. Then we use the
|
||||
* cif data to iterate over all known VLANS for the given port.
|
||||
*/
|
||||
static int bridge_port_vlans(struct dagger *net, struct lyd_node *cif, const char *brname,
|
||||
const char *brport, struct lydx_diff *pvidiff)
|
||||
{
|
||||
struct lyd_node *bridge = lydx_find_by_name(lyd_parent(cif), "interface", brname);
|
||||
struct lyd_node *vlan, *vlans;
|
||||
int err = 0;
|
||||
FILE *br;
|
||||
|
||||
vlans = lydx_get_descendant(lyd_child(bridge), "bridge", "vlans", NULL);
|
||||
if (!vlans)
|
||||
goto done;
|
||||
|
||||
br = dagger_fopen_next(net, "init", brname, 60, "init.bridge");
|
||||
if (!br) {
|
||||
err = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
LYX_LIST_FOR_EACH(lyd_child(vlans), vlan, "vlan") {
|
||||
int vid = atoi(lydx_get_cattr(vlan, "vid"));
|
||||
|
||||
brport_pvid_adjust(br, vlan, vid, brport, pvidiff, 0);
|
||||
brport_pvid_adjust(br, vlan, vid, brport, pvidiff, 1);
|
||||
}
|
||||
|
||||
fclose(br);
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bridge_diff_vlan_port(struct dagger *net, FILE *br, const char *brname, int vid,
|
||||
const char *brport, int tagged, enum lydx_op op)
|
||||
{
|
||||
@@ -877,20 +928,52 @@ static void bridge_port_settings(FILE *next, const char *ifname, struct lyd_node
|
||||
|
||||
static int bridge_gen_ports(struct dagger *net, struct lyd_node *dif, struct lyd_node *cif, FILE *ip)
|
||||
{
|
||||
const char *ifname = lydx_get_cattr(cif, "name");
|
||||
struct lyd_node *node, *bridge;
|
||||
struct lydx_diff brdiff;
|
||||
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; /* bridge port but no diff, skip */
|
||||
if (!node)
|
||||
goto fail;
|
||||
|
||||
ifname = lydx_get_cattr(cif, "name");
|
||||
/*
|
||||
* If bridge is not in dif, then we only have bridge-port
|
||||
* settings and can use cif instead for any new settings
|
||||
* since we always set *all* port settings anyway.
|
||||
*/
|
||||
bridge = lydx_get_child(node, "bridge");
|
||||
if (!bridge) {
|
||||
struct lyd_node *pvid = lydx_get_child(node, "pvid");
|
||||
struct lydx_diff pvidiff;
|
||||
const char *brname;
|
||||
FILE *next;
|
||||
|
||||
node = lydx_get_descendant(lyd_child(cif), "bridge-port", NULL);
|
||||
brname = lydx_get_cattr(node, "bridge");
|
||||
if (!node || !brname)
|
||||
goto fail;
|
||||
|
||||
next = dagger_fopen_next(net, "init", ifname, 56, "init.ip");
|
||||
if (!next) {
|
||||
err = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
bridge_port_settings(next, ifname, cif);
|
||||
fclose(next);
|
||||
|
||||
/* Change in bridge port's PVID => change in VLAN port memberships */
|
||||
if (lydx_get_diff(pvid, &pvidiff))
|
||||
bridge_port_vlans(net, cif, brname, ifname, &pvidiff);
|
||||
|
||||
err = dagger_add_dep(net, brname, ifname);
|
||||
if (err)
|
||||
return ERR_IFACE(cif, err, "Unable to add dep \"%s\" to %s", ifname, brdiff);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (lydx_get_diff(bridge, &brdiff) && brdiff.old) {
|
||||
FILE *prev;
|
||||
|
||||
Reference in New Issue
Block a user