bridge: set the mac address based on the first active member
[project/netifd.git] / bridge.c
index 46967c8..1725162 100644 (file)
--- a/bridge.c
+++ b/bridge.c
@@ -1,3 +1,16 @@
+/*
+ * netifd - network interface daemon
+ * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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 <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -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,23 @@ struct bridge_member {
        char name[];
 };
 
+static void
+bridge_reset_primary(struct bridge_state *bst)
+{
+       struct bridge_member *bm;
+
+       bst->primary_port = NULL;
+       vlist_for_each_element(&bst->members, bm, node) {
+               if (!bm->present)
+                       continue;
+
+               bst->primary_port = bm;
+               memcpy(bst->dev.settings.macaddr, bm->dev.dev->settings.macaddr, 6);
+               bst->dev.settings.flags |= DEV_OPT_MACADDR;
+               return;
+       }
+}
+
 static int
 bridge_disable_member(struct bridge_member *bm)
 {
@@ -132,6 +163,9 @@ bridge_remove_member(struct bridge_member *bm)
        if (!bm->present)
                return;
 
+       if (bm == bst->primary_port);
+               bridge_reset_primary(bst);
+
        if (bst->dev.active)
                bridge_disable_member(bm);
 
@@ -215,6 +249,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);
@@ -343,7 +378,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);
@@ -393,7 +427,7 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb)
        struct blob_attr *cur;
 
        /* defaults */
-       cfg->stp = true;
+       cfg->stp = false;
        cfg->forward_delay = 2;
        cfg->igmp_snoop = true;