Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 184551
b: refs/heads/master
c: 3729d50
h: refs/heads/master
i:
  184549: 605b70d
  184547: 015f6c5
  184543: 0182bcb
v: v3
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Feb 27, 2010
1 parent eab62e9 commit 74d6672
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 15 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: bd38081160bb3d036db98472e537b6a7dd4da51a
refs/heads/master: 3729d5021257b283f7fce33d957893162ccb2c9d
15 changes: 10 additions & 5 deletions trunk/drivers/net/veth.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,19 +333,17 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
struct veth_priv *priv;
char ifname[IFNAMSIZ];
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
struct ifinfomsg *ifmp;
struct net *net;

/*
* create and register peer first
*
* struct ifinfomsg is at the head of VETH_INFO_PEER, but we
* skip it since no info from it is useful yet
*/

if (data != NULL && data[VETH_INFO_PEER] != NULL) {
struct nlattr *nla_peer;

nla_peer = data[VETH_INFO_PEER];
ifmp = nla_data(nla_peer);
err = nla_parse(peer_tb, IFLA_MAX,
nla_data(nla_peer) + sizeof(struct ifinfomsg),
nla_len(nla_peer) - sizeof(struct ifinfomsg),
Expand All @@ -358,8 +356,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
return err;

tbp = peer_tb;
} else
} else {
ifmp = NULL;
tbp = tb;
}

if (tbp[IFLA_IFNAME])
nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
Expand Down Expand Up @@ -387,6 +387,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,

netif_carrier_off(peer);

err = rtnl_configure_link(peer, ifmp);
if (err < 0)
goto err_configure_peer;

/*
* register dev last
*
Expand Down Expand Up @@ -428,6 +432,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
err_register_dev:
/* nothing to do */
err_alloc_name:
err_configure_peer:
unregister_netdevice(peer);
return err;

Expand Down
2 changes: 2 additions & 0 deletions trunk/include/net/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
extern int rtnl_configure_link(struct net_device *dev,
const struct ifinfomsg *ifm);
extern const struct nla_policy ifla_policy[IFLA_MAX+1];

#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
Expand Down
52 changes: 43 additions & 9 deletions trunk/net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,19 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
}
}

static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
const struct ifinfomsg *ifm)
{
unsigned int flags = ifm->ifi_flags;

/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
if (ifm->ifi_change)
flags = (flags & ifm->ifi_change) |
(dev->flags & ~ifm->ifi_change);

return flags;
}

static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
const struct net_device_stats *b)
{
Expand Down Expand Up @@ -904,13 +917,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
}

if (ifm->ifi_flags || ifm->ifi_change) {
unsigned int flags = ifm->ifi_flags;

/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
if (ifm->ifi_change)
flags = (flags & ifm->ifi_change) |
(dev->flags & ~ifm->ifi_change);
err = dev_change_flags(dev, flags);
err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
if (err < 0)
goto errout;
}
Expand Down Expand Up @@ -1053,6 +1060,26 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
return 0;
}

int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
{
unsigned int old_flags;
int err;

old_flags = dev->flags;
if (ifm && (ifm->ifi_flags || ifm->ifi_change)) {
err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
if (err < 0)
return err;
}

dev->rtnl_link_state = RTNL_LINK_INITIALIZED;
rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);

__dev_notify_flags(dev, old_flags);
return 0;
}
EXPORT_SYMBOL(rtnl_configure_link);

struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[])
{
Expand All @@ -1074,6 +1101,7 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,

dev_net_set(dev, net);
dev->rtnl_link_ops = ops;
dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
dev->real_num_tx_queues = real_num_queues;

if (strchr(dev->name, '%')) {
Expand Down Expand Up @@ -1203,7 +1231,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (!(nlh->nlmsg_flags & NLM_F_CREATE))
return -ENODEV;

if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
if (ifm->ifi_index)
return -EOPNOTSUPP;
if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
return -EOPNOTSUPP;
Expand Down Expand Up @@ -1234,9 +1262,15 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = ops->newlink(net, dev, tb, data);
else
err = register_netdevice(dev);
if (err < 0 && !IS_ERR(dev))
if (err < 0 && !IS_ERR(dev)) {
free_netdev(dev);
goto out;
}

err = rtnl_configure_link(dev, ifm);
if (err < 0)
unregister_netdevice(dev);
out:
put_net(dest_net);
return err;
}
Expand Down

0 comments on commit 74d6672

Please sign in to comment.