X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=bridge.c;h=d29c3c0ccc49d061b71a9adb76711e0477e329ee;hp=d3b28677527eeaf23ade82f6adfd5355057c3e67;hb=8cb06c3efe734a521507cba7b5f0ba206e2476e0;hpb=e30469d12b735f5789d664cb3e22a2a29a6aa619 diff --git a/bridge.c b/bridge.c index d3b2867..d29c3c0 100644 --- a/bridge.c +++ b/bridge.c @@ -1,3 +1,16 @@ +/* + * netifd - network interface daemon + * Copyright (C) 2012 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include #include #include @@ -71,6 +84,7 @@ struct bridge_state { bool active; bool force_active; + struct bridge_member *primary_port; struct vlist_tree members; int n_present; }; @@ -83,6 +97,34 @@ struct bridge_member { char name[]; }; +static void +bridge_reset_primary(struct bridge_state *bst) +{ + struct bridge_member *bm; + + if (!bst->primary_port && + (bst->dev.settings.flags & DEV_OPT_MACADDR)) + return; + + bst->primary_port = NULL; + bst->dev.settings.flags &= ~DEV_OPT_MACADDR; + vlist_for_each_element(&bst->members, bm, node) { + uint8_t *macaddr; + + if (!bm->present) + continue; + + bst->primary_port = bm; + if (bm->dev.dev->settings.flags & DEV_OPT_MACADDR) + macaddr = bm->dev.dev->settings.macaddr; + else + macaddr = bm->dev.dev->orig_settings.macaddr; + memcpy(bst->dev.settings.macaddr, macaddr, 6); + bst->dev.settings.flags |= DEV_OPT_MACADDR; + return; + } +} + static int bridge_disable_member(struct bridge_member *bm) { @@ -132,11 +174,15 @@ bridge_remove_member(struct bridge_member *bm) if (!bm->present) return; - bm->present = false; - bm->bst->n_present--; + if (bm == bst->primary_port); + bridge_reset_primary(bst); + if (bst->dev.active) bridge_disable_member(bm); + bm->present = false; + bm->bst->n_present--; + bst->force_active = false; if (bst->n_present == 0) device_set_present(&bst->dev, false); @@ -214,6 +260,7 @@ bridge_set_up(struct bridge_state *bst) return -ENOENT; } + bridge_reset_primary(bst); ret = bst->set_state(&bst->dev, true); if (ret < 0) bridge_set_down(bst); @@ -342,7 +389,6 @@ bridge_free(struct device *dev) { struct bridge_state *bst; - device_cleanup(dev); bst = container_of(dev, struct bridge_state, dev); vlist_flush_all(&bst->members); free(bst); @@ -392,8 +438,8 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb) struct blob_attr *cur; /* defaults */ - cfg->stp = true; - cfg->forward_delay = 1; + cfg->stp = false; + cfg->forward_delay = 2; cfg->igmp_snoop = true; if ((cur = tb[BRIDGE_ATTR_STP]))