bridge: make hotplug-added vlans default to tagged
[project/netifd.git] / bridge.c
index 15e09dd1c26dc31d382617653d88e1d67025822b..fb1f196ad3c892ddb7d22b80396017b417ca2895 100644 (file)
--- a/bridge.c
+++ b/bridge.c
@@ -206,7 +206,7 @@ __bridge_set_member_vlan(struct bridge_member *bm, struct bridge_vlan *vlan,
        if (bm->pvid == vlan->vid)
                flags |= BRVLAN_F_PVID;
 
-       system_bridge_vlan(port->ifname, vlan->vid, add, flags);
+       system_bridge_vlan(port->ifname, vlan->vid, -1, add, flags);
 }
 
 static void
@@ -233,7 +233,7 @@ bridge_set_local_vlan(struct bridge_state *bst, struct bridge_vlan *vlan, bool a
        if (!vlan->local && add)
                return;
 
-       system_bridge_vlan(bst->dev.ifname, vlan->vid, add, BRVLAN_F_SELF);
+       system_bridge_vlan(bst->dev.ifname, vlan->vid, -1, add, BRVLAN_F_SELF);
 }
 
 static void
@@ -339,10 +339,8 @@ static void bridge_stp_notify(struct bridge_state *bst)
        if (cfg->stp_proto)
                blobmsg_add_string(&b, "proto", cfg->stp_proto);
        blobmsg_add_u32(&b, "forward_delay", cfg->forward_delay);
-       if (cfg->flags & BRIDGE_OPT_HELLO_TIME)
-               blobmsg_add_u32(&b, "hello_time", cfg->hello_time);
-       if (cfg->flags & BRIDGE_OPT_MAX_AGE)
-               blobmsg_add_u32(&b, "max_age", cfg->max_age);
+       blobmsg_add_u32(&b, "hello_time", cfg->hello_time);
+       blobmsg_add_u32(&b, "max_age", cfg->max_age);
        if (cfg->flags & BRIDGE_OPT_AGEING_TIME)
                blobmsg_add_u32(&b, "ageing_time", cfg->ageing_time);
        netifd_ubus_device_notify("stp_init", b.head, 1000);
@@ -363,7 +361,7 @@ bridge_enable_interface(struct bridge_state *bst)
 
        if (bst->has_vlans) {
                /* delete default VLAN 1 */
-               system_bridge_vlan(bst->dev.ifname, 1, false, BRVLAN_F_SELF);
+               system_bridge_vlan(bst->dev.ifname, 1, -1, false, BRVLAN_F_SELF);
 
                bridge_set_local_vlans(bst, true);
        }
@@ -396,6 +394,17 @@ bridge_disable_interface(struct bridge_state *bst)
        bst->active = false;
 }
 
+static void
+bridge_member_add_extra_vlans(struct bridge_member *bm)
+{
+       struct device *dev = bm->dev.dev;
+       int i;
+
+       for (i = 0; i < dev->n_extra_vlan; i++)
+               system_bridge_vlan(dev->ifname, dev->extra_vlan[i].start,
+                                  dev->extra_vlan[i].end, true, 0);
+}
+
 static int
 bridge_enable_member(struct bridge_member *bm)
 {
@@ -437,8 +446,9 @@ bridge_enable_member(struct bridge_member *bm)
        bm->active = true;
        if (bst->has_vlans) {
                /* delete default VLAN 1 */
-               system_bridge_vlan(bm->dev.dev->ifname, 1, false, 0);
+               system_bridge_vlan(bm->dev.dev->ifname, 1, -1, false, 0);
 
+               bridge_member_add_extra_vlans(bm);
                vlist_for_each_element(&bst->dev.vlans, vlan, node)
                        bridge_set_member_vlan(bm, vlan, true);
        }
@@ -514,8 +524,6 @@ restart:
                goto restart;
        }
 
-       device_lock();
-
        device_remove_user(&bm->dev);
        uloop_timeout_cancel(&bm->check_timer);
 
@@ -531,8 +539,6 @@ restart:
                device_set_present(dev, true);
        }
 
-       device_unlock();
-
        free(bm);
 }
 
@@ -788,14 +794,14 @@ bridge_hotplug_set_member_vlans(struct bridge_state *bst, struct blob_attr *vlan
 {
        struct bridge_vlan *vlan;
        struct blob_attr *cur;
-       int rem;
+       size_t rem;
 
        if (!vlans)
                return;
 
        blobmsg_for_each_attr(cur, vlans, rem) {
                struct bridge_vlan_hotplug_port *port;
-               uint16_t flags = BRVLAN_F_UNTAGGED;
+               uint16_t flags = 0;
                char *name_buf;
                unsigned int vid;
                char *end;
@@ -822,8 +828,8 @@ bridge_hotplug_set_member_vlans(struct bridge_state *bst, struct blob_attr *vlan
 
                        for (end++; *end; end++) {
                                switch (*end) {
-                               case 't':
-                                       flags &= ~BRVLAN_F_UNTAGGED;
+                               case 'u':
+                                       flags |= BRVLAN_F_UNTAGGED;
                                        break;
                                case '*':
                                        flags |= BRVLAN_F_PVID;
@@ -940,7 +946,7 @@ bridge_dump_port(struct blob_buf *b, struct bridge_vlan_port *port)
        bool tagged = !(port->flags & BRVLAN_F_UNTAGGED);
        bool pvid = (port->flags & BRVLAN_F_PVID);
 
-       blobmsg_printf(b, "%s%s%s%s\n", port->ifname,
+       blobmsg_printf(b, NULL, "%s%s%s%s", port->ifname,
                tagged || pvid ? ":" : "",
                tagged ? "t" : "",
                pvid ? "*" : "");
@@ -974,12 +980,15 @@ bridge_dump_vlan(struct blob_buf *b, struct bridge_vlan *vlan)
 static void
 bridge_dump_info(struct device *dev, struct blob_buf *b)
 {
+       struct bridge_config *cfg;
        struct bridge_state *bst;
        struct bridge_member *bm;
        struct bridge_vlan *vlan;
        void *list;
+       void *c;
 
        bst = container_of(dev, struct bridge_state, dev);
+       cfg = &bst->config;
 
        system_if_dump_info(dev, b);
        list = blobmsg_open_array(b, "bridge-members");
@@ -993,6 +1002,29 @@ bridge_dump_info(struct device *dev, struct blob_buf *b)
 
        blobmsg_close_array(b, list);
 
+       c = blobmsg_open_table(b, "bridge-attributes");
+
+       blobmsg_add_u8(b, "stp", cfg->stp);
+       blobmsg_add_u32(b, "forward_delay", cfg->forward_delay);
+       blobmsg_add_u32(b, "priority", cfg->priority);
+       blobmsg_add_u32(b, "ageing_time", cfg->ageing_time);
+       blobmsg_add_u32(b, "hello_time", cfg->hello_time);
+       blobmsg_add_u32(b, "max_age", cfg->max_age);
+       blobmsg_add_u8(b, "igmp_snooping", cfg->igmp_snoop);
+       blobmsg_add_u8(b, "bridge_empty", cfg->bridge_empty);
+       blobmsg_add_u8(b, "multicast_querier", cfg->multicast_querier);
+       blobmsg_add_u32(b, "hash_max", cfg->hash_max);
+       blobmsg_add_u32(b, "robustness", cfg->robustness);
+       blobmsg_add_u32(b, "query_interval", cfg->query_interval);
+       blobmsg_add_u32(b, "query_response_interval", cfg->query_response_interval);
+       blobmsg_add_u32(b, "last_member_interval", cfg->last_member_interval);
+       blobmsg_add_u8(b, "vlan_filtering", cfg->vlan_filtering);
+       blobmsg_add_u8(b, "stp_kernel", cfg->stp_kernel);
+       if (cfg->stp_proto)
+               blobmsg_add_string(b, "stp_proto", cfg->stp_proto);
+
+       blobmsg_close_table(b, c);
+
        if (avl_is_empty(&dev->vlans.avl))
                return;
 
@@ -1010,7 +1042,8 @@ bridge_config_init(struct device *dev)
        struct bridge_state *bst;
        struct bridge_vlan *vlan;
        struct blob_attr *cur;
-       int i, rem;
+       size_t rem;
+       int i;
 
        bst = container_of(dev, struct bridge_state, dev);
 
@@ -1045,7 +1078,6 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb)
        memset(cfg, 0, sizeof(*cfg));
        cfg->stp = false;
        cfg->stp_kernel = false;
-       cfg->forward_delay = 2;
        cfg->robustness = 2;
        cfg->igmp_snoop = false;
        cfg->multicast_querier = false;
@@ -1057,6 +1089,10 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb)
        cfg->priority = 0x7FFF;
        cfg->vlan_filtering = false;
 
+       cfg->forward_delay = 8;
+       cfg->max_age = 10;
+       cfg->hello_time = 1;
+
        if ((cur = tb[BRIDGE_ATTR_STP]))
                cfg->stp = blobmsg_get_bool(cur);
 
@@ -1106,15 +1142,11 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb)
                cfg->flags |= BRIDGE_OPT_AGEING_TIME;
        }
 
-       if ((cur = tb[BRIDGE_ATTR_HELLO_TIME])) {
+       if ((cur = tb[BRIDGE_ATTR_HELLO_TIME]))
                cfg->hello_time = blobmsg_get_u32(cur);
-               cfg->flags |= BRIDGE_OPT_HELLO_TIME;
-       }
 
-       if ((cur = tb[BRIDGE_ATTR_MAX_AGE])) {
+       if ((cur = tb[BRIDGE_ATTR_MAX_AGE]))
                cfg->max_age = blobmsg_get_u32(cur);
-               cfg->flags |= BRIDGE_OPT_MAX_AGE;
-       }
 
        if ((cur = tb[BRIDGE_ATTR_BRIDGE_EMPTY]))
                cfg->bridge_empty = blobmsg_get_bool(cur);
@@ -1159,16 +1191,22 @@ bridge_reload(struct device *dev, struct blob_attr *attr)
 
                diff = 0;
                uci_blob_diff(tb_dev, otb_dev, &device_attr_list, &diff);
-               if (diff)
-                   ret = DEV_CONFIG_RESTART;
+               if (diff) {
+                       ret = DEV_CONFIG_RESTART;
+                       D(DEVICE, "Bridge %s device attributes have changed, diff=0x%lx\n",
+                         dev->ifname, diff);
+               }
 
                blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, otb_br,
                        blob_data(bst->config_data), blob_len(bst->config_data));
 
                diff = 0;
                uci_blob_diff(tb_br, otb_br, &bridge_attr_list, &diff);
-               if (diff & ~(1 << BRIDGE_ATTR_PORTS))
-                   ret = DEV_CONFIG_RESTART;
+               if (diff & ~(1 << BRIDGE_ATTR_PORTS)) {
+                       ret = DEV_CONFIG_RESTART;
+                       D(DEVICE, "Bridge %s attributes have changed, diff=0x%lx\n",
+                         dev->ifname, diff);
+               }
 
                bridge_config_init(dev);
        }