#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/completion.h>
+#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/rculist.h>
#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
#include <net/genetlink.h>
#include "compat.h"
struct net_device *port;
int err;
- port = dev_get_by_index(&init_net, args[1]);
+ port = __dev_get_by_index(&init_net, args[1]);
if (!port)
return -EINVAL;
err = brc_send_port_add_del(dev, port, args[0] == BRCTL_ADD_IF);
- dev_put(port);
return err;
}
case SIOCBRDELIF: {
struct net_device *port;
- port = dev_get_by_index(&init_net, rq->ifr_ifindex);
+ port = __dev_get_by_index(&init_net, rq->ifr_ifindex);
if (!port)
return -EINVAL;
err = brc_send_port_add_del(dev, port, cmd == SIOCBRADDIF);
- dev_put(port);
break;
}
struct dp_dev *dp_dev = netdev_priv(dev);
struct datapath *dp = dp_dev->dp;
struct sk_buff *skb;
+ int error;
void *data;
+ int i;
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL)
NLA_PUT_STRING(skb, BRC_GENL_A_PORT_NAME, port->name);
genlmsg_end(skb, data);
- return genlmsg_multicast(skb, 0, brc_mc_group.id, GFP_KERNEL);
+ error = genlmsg_multicast(skb, 0, brc_mc_group.id, GFP_KERNEL);
+ if (error)
+ return error;
+
+ for (i = 0; i < 100; i++) {
+ int dev_ifindex = dev->ifindex;
+ int port_ifindex = port->ifindex;
+
+ rtnl_unlock();
+ msleep(10);
+ rtnl_lock();
+
+ dev = __dev_get_by_index(&init_net, dev_ifindex);
+ port = __dev_get_by_index(&init_net, port_ifindex);
+ if (!dev || !port)
+ return ENODEV;
+
+ if (add && port->br_port)
+ return port->br_port->dev ? 0 : -EBUSY;
+ else if (!add && !port->br_port)
+ return 0;
+ }
+ return -ETIMEDOUT;
nla_put_failure:
err:
#define dev_get_by_index(net, ifindex) \
dev_get_by_index((ifindex))
+#define __dev_get_by_name(net, name) \
+ __dev_get_by_name((name))
+
+#define __dev_get_by_index(net, ifindex) \
+ __dev_get_by_index((ifindex))
+
#endif /* linux kernel <= 2.6.23 */