forked from Minki/linux
Merge branch 'rtnetlink_vf_ports'
David Gibson says: ==================== Fix problems with with IFLA_VF_PORTS (v2) I've had a customer encounter a problem with getifaddrs(3) freezing up on a system with a Cisco enic device. I've discovered that the problem is caused by an enic device with a large number of SR-IOV virtual functions overflowing the normal sized packet buffer for netlink, leading to interfaces not being reported from an RTM_GETLINK request. The first patch here just makes the problem easier to locate if it occurs again in a different way, by adding a WARN_ON() when we run out of room in a netlink packet in this manner. The second patch actually fixes the problem, by only reporting IFLA_VF_PORTS information when the RTEXT_FILTER_VF flag is specified. v2: Corrected some CodingStyle problems ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fc5e88354d
@ -774,7 +774,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t rtnl_port_size(const struct net_device *dev)
|
||||
static size_t rtnl_port_size(const struct net_device *dev,
|
||||
u32 ext_filter_mask)
|
||||
{
|
||||
size_t port_size = nla_total_size(4) /* PORT_VF */
|
||||
+ nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */
|
||||
@ -790,7 +791,8 @@ static size_t rtnl_port_size(const struct net_device *dev)
|
||||
size_t port_self_size = nla_total_size(sizeof(struct nlattr))
|
||||
+ port_size;
|
||||
|
||||
if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent)
|
||||
if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent ||
|
||||
!(ext_filter_mask & RTEXT_FILTER_VF))
|
||||
return 0;
|
||||
if (dev_num_vf(dev->dev.parent))
|
||||
return port_self_size + vf_ports_size +
|
||||
@ -826,7 +828,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
|
||||
+ nla_total_size(ext_filter_mask
|
||||
& RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
|
||||
+ rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
|
||||
+ rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
|
||||
+ rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
|
||||
+ rtnl_link_get_size(dev) /* IFLA_LINKINFO */
|
||||
+ rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
|
||||
+ nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */
|
||||
@ -888,11 +890,13 @@ static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev)
|
||||
static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev,
|
||||
u32 ext_filter_mask)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent)
|
||||
if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent ||
|
||||
!(ext_filter_mask & RTEXT_FILTER_VF))
|
||||
return 0;
|
||||
|
||||
err = rtnl_port_self_fill(skb, dev);
|
||||
@ -1079,7 +1083,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
||||
nla_nest_end(skb, vfinfo);
|
||||
}
|
||||
|
||||
if (rtnl_port_fill(skb, dev))
|
||||
if (rtnl_port_fill(skb, dev, ext_filter_mask))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) {
|
||||
@ -1198,6 +1202,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
struct hlist_head *head;
|
||||
struct nlattr *tb[IFLA_MAX+1];
|
||||
u32 ext_filter_mask = 0;
|
||||
int err;
|
||||
|
||||
s_h = cb->args[0];
|
||||
s_idx = cb->args[1];
|
||||
@ -1218,11 +1223,17 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
hlist_for_each_entry_rcu(dev, head, index_hlist) {
|
||||
if (idx < s_idx)
|
||||
goto cont;
|
||||
if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, 0,
|
||||
NLM_F_MULTI,
|
||||
ext_filter_mask) <= 0)
|
||||
err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, 0,
|
||||
NLM_F_MULTI,
|
||||
ext_filter_mask);
|
||||
/* If we ran out of room on the first message,
|
||||
* we're in trouble
|
||||
*/
|
||||
WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
|
||||
|
||||
if (err <= 0)
|
||||
goto out;
|
||||
|
||||
nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
||||
|
Loading…
Reference in New Issue
Block a user