Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 340518
b: refs/heads/master
c: 2469ffd
h: refs/heads/master
v: v3
  • Loading branch information
John Fastabend authored and David S. Miller committed Oct 31, 2012
1 parent 34c3c87 commit ee79cfe
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e5a55a898720096f43bc24938f8875c0a1b34cd7
refs/heads/master: 2469ffd723f76ac2d3ce3d4f31ee31ee0a06cd38
18 changes: 18 additions & 0 deletions trunk/include/uapi/linux/if_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,23 @@ struct __fdb_entry {
__u16 unused;
};

/* Bridge Flags */
#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */
#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */

#define BRIDGE_MODE_VEB 0 /* Default loopback mode */
#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */

/* Bridge management nested attributes
* [IFLA_AF_SPEC] = {
* [IFLA_BRIDGE_FLAGS]
* [IFLA_BRIDGE_MODE]
* }
*/
enum {
IFLA_BRIDGE_FLAGS,
IFLA_BRIDGE_MODE,
__IFLA_BRIDGE_MAX,
};
#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
#endif /* _UAPI_LINUX_IF_BRIDGE_H */
2 changes: 0 additions & 2 deletions trunk/net/bridge/br_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
br_port_state_selection(p->br);
spin_unlock_bh(&p->br->lock);

br_ifinfo_notify(RTM_NEWLINK, p);

return 0;
}

Expand Down
4 changes: 3 additions & 1 deletion trunk/net/bridge/br_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ struct net_bridge_port

static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
{
struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
struct net_bridge_port *port =
rcu_dereference_rtnl(dev->rx_handler_data);

return br_port_exists(dev) ? port : NULL;
}

Expand Down
85 changes: 81 additions & 4 deletions trunk/net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -2295,13 +2295,60 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}

static inline size_t bridge_nlmsg_size(void)
{
return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ nla_total_size(sizeof(u32)) /* IFLA_MASTER */
+ nla_total_size(sizeof(u32)) /* IFLA_MTU */
+ nla_total_size(sizeof(u32)) /* IFLA_LINK */
+ nla_total_size(sizeof(u32)) /* IFLA_OPERSTATE */
+ nla_total_size(sizeof(u8)) /* IFLA_PROTINFO */
+ nla_total_size(sizeof(struct nlattr)) /* IFLA_AF_SPEC */
+ nla_total_size(sizeof(u16)) /* IFLA_BRIDGE_FLAGS */
+ nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */
}

static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
{
struct net *net = dev_net(dev);
struct net_device *master = dev->master;
struct sk_buff *skb;
int err = -EOPNOTSUPP;

skb = nlmsg_new(bridge_nlmsg_size(), GFP_ATOMIC);
if (!skb) {
err = -ENOMEM;
goto errout;
}

if (!flags && master && master->netdev_ops->ndo_bridge_getlink)
err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
else if (dev->netdev_ops->ndo_bridge_getlink)
err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);

if (err < 0)
goto errout;

rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
return 0;
errout:
WARN_ON(err == -EMSGSIZE);
kfree_skb(skb);
rtnl_set_sk_err(net, RTNLGRP_LINK, err);
return err;
}

static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
void *arg)
{
struct net *net = sock_net(skb->sk);
struct ifinfomsg *ifm;
struct net_device *dev;
int err = -EINVAL;
struct nlattr *br_spec, *attr = NULL;
int rem, err = -EOPNOTSUPP;
u16 flags = 0;

if (nlmsg_len(nlh) < sizeof(*ifm))
return -EINVAL;
Expand All @@ -2316,15 +2363,45 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
return -ENODEV;
}

if (dev->master && dev->master->netdev_ops->ndo_bridge_setlink) {
br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
if (br_spec) {
nla_for_each_nested(attr, br_spec, rem) {
if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
flags = nla_get_u16(attr);
break;
}
}
}

if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
if (!dev->master ||
!dev->master->netdev_ops->ndo_bridge_setlink) {
err = -EOPNOTSUPP;
goto out;
}

err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
if (err)
goto out;

flags &= ~BRIDGE_FLAGS_MASTER;
}

if (dev->netdev_ops->ndo_bridge_setlink)
err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
if ((flags & BRIDGE_FLAGS_SELF)) {
if (!dev->netdev_ops->ndo_bridge_setlink)
err = -EOPNOTSUPP;
else
err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh);

if (!err)
flags &= ~BRIDGE_FLAGS_SELF;
}

if (attr && nla_type(attr) == IFLA_BRIDGE_FLAGS)
memcpy(nla_data(attr), &flags, sizeof(flags));
/* Generate event to notify upper layer of bridge change */
if (!err)
err = rtnl_bridge_notify(dev, flags);
out:
return err;
}
Expand Down

0 comments on commit ee79cfe

Please sign in to comment.