|
@@ -106,6 +106,20 @@ done:
|
|
rtnl_unlock();
|
|
rtnl_unlock();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void release_nbp(struct kobject *kobj)
|
|
|
|
+{
|
|
|
|
+ struct net_bridge_port *p
|
|
|
|
+ = container_of(kobj, struct net_bridge_port, kobj);
|
|
|
|
+ kfree(p);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct kobj_type brport_ktype = {
|
|
|
|
+#ifdef CONFIG_SYSFS
|
|
|
|
+ .sysfs_ops = &brport_sysfs_ops,
|
|
|
|
+#endif
|
|
|
|
+ .release = release_nbp,
|
|
|
|
+};
|
|
|
|
+
|
|
static void destroy_nbp(struct net_bridge_port *p)
|
|
static void destroy_nbp(struct net_bridge_port *p)
|
|
{
|
|
{
|
|
struct net_device *dev = p->dev;
|
|
struct net_device *dev = p->dev;
|
|
@@ -114,7 +128,7 @@ static void destroy_nbp(struct net_bridge_port *p)
|
|
p->dev = NULL;
|
|
p->dev = NULL;
|
|
dev_put(dev);
|
|
dev_put(dev);
|
|
|
|
|
|
- br_sysfs_freeif(p);
|
|
|
|
|
|
+ kobject_put(&p->kobj);
|
|
}
|
|
}
|
|
|
|
|
|
static void destroy_nbp_rcu(struct rcu_head *head)
|
|
static void destroy_nbp_rcu(struct rcu_head *head)
|
|
@@ -138,6 +152,8 @@ static void del_nbp(struct net_bridge_port *p)
|
|
struct net_bridge *br = p->br;
|
|
struct net_bridge *br = p->br;
|
|
struct net_device *dev = p->dev;
|
|
struct net_device *dev = p->dev;
|
|
|
|
|
|
|
|
+ sysfs_remove_link(&br->ifobj, dev->name);
|
|
|
|
+
|
|
dev_set_promiscuity(dev, -1);
|
|
dev_set_promiscuity(dev, -1);
|
|
|
|
|
|
cancel_delayed_work(&p->carrier_check);
|
|
cancel_delayed_work(&p->carrier_check);
|
|
@@ -152,6 +168,8 @@ static void del_nbp(struct net_bridge_port *p)
|
|
|
|
|
|
rcu_assign_pointer(dev->br_port, NULL);
|
|
rcu_assign_pointer(dev->br_port, NULL);
|
|
|
|
|
|
|
|
+ kobject_del(&p->kobj);
|
|
|
|
+
|
|
call_rcu(&p->rcu, destroy_nbp_rcu);
|
|
call_rcu(&p->rcu, destroy_nbp_rcu);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -161,7 +179,6 @@ static void del_br(struct net_bridge *br)
|
|
struct net_bridge_port *p, *n;
|
|
struct net_bridge_port *p, *n;
|
|
|
|
|
|
list_for_each_entry_safe(p, n, &br->port_list, list) {
|
|
list_for_each_entry_safe(p, n, &br->port_list, list) {
|
|
- br_sysfs_removeif(p);
|
|
|
|
del_nbp(p);
|
|
del_nbp(p);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -261,6 +278,11 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
|
|
INIT_WORK(&p->carrier_check, port_carrier_check, dev);
|
|
INIT_WORK(&p->carrier_check, port_carrier_check, dev);
|
|
kobject_init(&p->kobj);
|
|
kobject_init(&p->kobj);
|
|
|
|
|
|
|
|
+ kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
|
|
|
|
+ p->kobj.ktype = &brport_ktype;
|
|
|
|
+ p->kobj.parent = &(dev->class_dev.kobj);
|
|
|
|
+ p->kobj.kset = NULL;
|
|
|
|
+
|
|
return p;
|
|
return p;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -388,31 +410,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
|
if (dev->br_port != NULL)
|
|
if (dev->br_port != NULL)
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
|
|
|
|
- if (IS_ERR(p = new_nbp(br, dev)))
|
|
|
|
|
|
+ p = new_nbp(br, dev);
|
|
|
|
+ if (IS_ERR(p))
|
|
return PTR_ERR(p);
|
|
return PTR_ERR(p);
|
|
|
|
|
|
- if ((err = br_fdb_insert(br, p, dev->dev_addr)))
|
|
|
|
- destroy_nbp(p);
|
|
|
|
-
|
|
|
|
- else if ((err = br_sysfs_addif(p)))
|
|
|
|
- del_nbp(p);
|
|
|
|
- else {
|
|
|
|
- rcu_assign_pointer(dev->br_port, p);
|
|
|
|
- dev_set_promiscuity(dev, 1);
|
|
|
|
|
|
+ err = kobject_add(&p->kobj);
|
|
|
|
+ if (err)
|
|
|
|
+ goto err0;
|
|
|
|
|
|
- list_add_rcu(&p->list, &br->port_list);
|
|
|
|
|
|
+ err = br_fdb_insert(br, p, dev->dev_addr);
|
|
|
|
+ if (err)
|
|
|
|
+ goto err1;
|
|
|
|
|
|
- spin_lock_bh(&br->lock);
|
|
|
|
- br_stp_recalculate_bridge_id(br);
|
|
|
|
- br_features_recompute(br);
|
|
|
|
- if ((br->dev->flags & IFF_UP)
|
|
|
|
- && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
|
|
|
|
- br_stp_enable_port(p);
|
|
|
|
- spin_unlock_bh(&br->lock);
|
|
|
|
|
|
+ err = br_sysfs_addif(p);
|
|
|
|
+ if (err)
|
|
|
|
+ goto err2;
|
|
|
|
|
|
- dev_set_mtu(br->dev, br_min_mtu(br));
|
|
|
|
- }
|
|
|
|
|
|
+ rcu_assign_pointer(dev->br_port, p);
|
|
|
|
+ dev_set_promiscuity(dev, 1);
|
|
|
|
+
|
|
|
|
+ list_add_rcu(&p->list, &br->port_list);
|
|
|
|
+
|
|
|
|
+ spin_lock_bh(&br->lock);
|
|
|
|
+ br_stp_recalculate_bridge_id(br);
|
|
|
|
+ br_features_recompute(br);
|
|
|
|
+ schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
|
|
|
|
+ spin_unlock_bh(&br->lock);
|
|
|
|
+
|
|
|
|
+ dev_set_mtu(br->dev, br_min_mtu(br));
|
|
|
|
+ kobject_uevent(&p->kobj, KOBJ_ADD);
|
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
+err2:
|
|
|
|
+ br_fdb_delete_by_port(br, p);
|
|
|
|
+err1:
|
|
|
|
+ kobject_del(&p->kobj);
|
|
|
|
+err0:
|
|
|
|
+ kobject_put(&p->kobj);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -424,7 +458,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
|
|
if (!p || p->br != br)
|
|
if (!p || p->br != br)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- br_sysfs_removeif(p);
|
|
|
|
del_nbp(p);
|
|
del_nbp(p);
|
|
|
|
|
|
spin_lock_bh(&br->lock);
|
|
spin_lock_bh(&br->lock);
|