diff options
author | David S. Miller <davem@davemloft.net> | 2014-04-24 13:53:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-24 13:53:01 -0400 |
commit | fc5e88354de53024f61d50c7fe9b5b182fc5800d (patch) | |
tree | ecff2dc9cee7be1e91d84e8db6f8491196c25d83 | |
parent | a64d90fd962c2956da7505f98a302408450365e2 (diff) | |
parent | c53864fd60227de025cb79e05493b13f69843971 (diff) |
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>
-rw-r--r-- | net/core/rtnetlink.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 64ad17d077ed..9837bebf93ce 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -774,7 +774,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, | |||
774 | return 0; | 774 | return 0; |
775 | } | 775 | } |
776 | 776 | ||
777 | static size_t rtnl_port_size(const struct net_device *dev) | 777 | static size_t rtnl_port_size(const struct net_device *dev, |
778 | u32 ext_filter_mask) | ||
778 | { | 779 | { |
779 | size_t port_size = nla_total_size(4) /* PORT_VF */ | 780 | size_t port_size = nla_total_size(4) /* PORT_VF */ |
780 | + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ | 781 | + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ |
@@ -790,7 +791,8 @@ static size_t rtnl_port_size(const struct net_device *dev) | |||
790 | size_t port_self_size = nla_total_size(sizeof(struct nlattr)) | 791 | size_t port_self_size = nla_total_size(sizeof(struct nlattr)) |
791 | + port_size; | 792 | + port_size; |
792 | 793 | ||
793 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) | 794 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent || |
795 | !(ext_filter_mask & RTEXT_FILTER_VF)) | ||
794 | return 0; | 796 | return 0; |
795 | if (dev_num_vf(dev->dev.parent)) | 797 | if (dev_num_vf(dev->dev.parent)) |
796 | return port_self_size + vf_ports_size + | 798 | return port_self_size + vf_ports_size + |
@@ -826,7 +828,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, | |||
826 | + nla_total_size(ext_filter_mask | 828 | + nla_total_size(ext_filter_mask |
827 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ | 829 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ |
828 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ | 830 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ |
829 | + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ | 831 | + rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ |
830 | + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ | 832 | + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ |
831 | + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */ | 833 | + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */ |
832 | + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */ | 834 | + 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) | |||
888 | return 0; | 890 | return 0; |
889 | } | 891 | } |
890 | 892 | ||
891 | static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev) | 893 | static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev, |
894 | u32 ext_filter_mask) | ||
892 | { | 895 | { |
893 | int err; | 896 | int err; |
894 | 897 | ||
895 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) | 898 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent || |
899 | !(ext_filter_mask & RTEXT_FILTER_VF)) | ||
896 | return 0; | 900 | return 0; |
897 | 901 | ||
898 | err = rtnl_port_self_fill(skb, dev); | 902 | err = rtnl_port_self_fill(skb, dev); |
@@ -1079,7 +1083,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
1079 | nla_nest_end(skb, vfinfo); | 1083 | nla_nest_end(skb, vfinfo); |
1080 | } | 1084 | } |
1081 | 1085 | ||
1082 | if (rtnl_port_fill(skb, dev)) | 1086 | if (rtnl_port_fill(skb, dev, ext_filter_mask)) |
1083 | goto nla_put_failure; | 1087 | goto nla_put_failure; |
1084 | 1088 | ||
1085 | if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) { | 1089 | 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) | |||
1198 | struct hlist_head *head; | 1202 | struct hlist_head *head; |
1199 | struct nlattr *tb[IFLA_MAX+1]; | 1203 | struct nlattr *tb[IFLA_MAX+1]; |
1200 | u32 ext_filter_mask = 0; | 1204 | u32 ext_filter_mask = 0; |
1205 | int err; | ||
1201 | 1206 | ||
1202 | s_h = cb->args[0]; | 1207 | s_h = cb->args[0]; |
1203 | s_idx = cb->args[1]; | 1208 | s_idx = cb->args[1]; |
@@ -1218,11 +1223,17 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1218 | hlist_for_each_entry_rcu(dev, head, index_hlist) { | 1223 | hlist_for_each_entry_rcu(dev, head, index_hlist) { |
1219 | if (idx < s_idx) | 1224 | if (idx < s_idx) |
1220 | goto cont; | 1225 | goto cont; |
1221 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | 1226 | err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, |
1222 | NETLINK_CB(cb->skb).portid, | 1227 | NETLINK_CB(cb->skb).portid, |
1223 | cb->nlh->nlmsg_seq, 0, | 1228 | cb->nlh->nlmsg_seq, 0, |
1224 | NLM_F_MULTI, | 1229 | NLM_F_MULTI, |
1225 | ext_filter_mask) <= 0) | 1230 | ext_filter_mask); |
1231 | /* If we ran out of room on the first message, | ||
1232 | * we're in trouble | ||
1233 | */ | ||
1234 | WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); | ||
1235 | |||
1236 | if (err <= 0) | ||
1226 | goto out; | 1237 | goto out; |
1227 | 1238 | ||
1228 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | 1239 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |