rtnetlink: fix frame size warning in rtnl_fill_ifinfo
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Tue, 17 Nov 2015 13:16:52 +0000 (14:16 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Nov 2015 20:25:44 +0000 (15:25 -0500)
Fix the following warning:

  CC      net/core/rtnetlink.o
net/core/rtnetlink.c: In function ‘rtnl_fill_ifinfo’:
net/core/rtnetlink.c:1308:1: warning: the frame size of 2864 bytes is larger than 2048 bytes [-Wframe-larger-than=]
 }
 ^
by splitting up the huge rtnl_fill_ifinfo into some smaller ones, so we
don't have the huge frame allocations at the same time.

Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/rtnetlink.c

index 504bd17b7456c3a16a0832ed28ede040c41ff316..34ba7a08876de74409ea5d2ad3af6f78124ff0a7 100644 (file)
@@ -1045,15 +1045,156 @@ static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb,
+                                             struct net_device *dev)
+{
+       const struct rtnl_link_stats64 *stats;
+       struct rtnl_link_stats64 temp;
+       struct nlattr *attr;
+
+       stats = dev_get_stats(dev, &temp);
+
+       attr = nla_reserve(skb, IFLA_STATS,
+                          sizeof(struct rtnl_link_stats));
+       if (!attr)
+               return -EMSGSIZE;
+
+       copy_rtnl_link_stats(nla_data(attr), stats);
+
+       attr = nla_reserve(skb, IFLA_STATS64,
+                          sizeof(struct rtnl_link_stats64));
+       if (!attr)
+               return -EMSGSIZE;
+
+       copy_rtnl_link_stats64(nla_data(attr), stats);
+
+       return 0;
+}
+
+static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
+                                              struct net_device *dev,
+                                              int vfs_num,
+                                              struct nlattr *vfinfo)
+{
+       struct ifla_vf_rss_query_en vf_rss_query_en;
+       struct ifla_vf_link_state vf_linkstate;
+       struct ifla_vf_spoofchk vf_spoofchk;
+       struct ifla_vf_tx_rate vf_tx_rate;
+       struct ifla_vf_stats vf_stats;
+       struct ifla_vf_trust vf_trust;
+       struct ifla_vf_vlan vf_vlan;
+       struct ifla_vf_rate vf_rate;
+       struct nlattr *vf, *vfstats;
+       struct ifla_vf_mac vf_mac;
+       struct ifla_vf_info ivi;
+
+       /* Not all SR-IOV capable drivers support the
+        * spoofcheck and "RSS query enable" query.  Preset to
+        * -1 so the user space tool can detect that the driver
+        * didn't report anything.
+        */
+       ivi.spoofchk = -1;
+       ivi.rss_query_en = -1;
+       ivi.trusted = -1;
+       memset(ivi.mac, 0, sizeof(ivi.mac));
+       /* The default value for VF link state is "auto"
+        * IFLA_VF_LINK_STATE_AUTO which equals zero
+        */
+       ivi.linkstate = 0;
+       if (dev->netdev_ops->ndo_get_vf_config(dev, vfs_num, &ivi))
+               return 0;
+
+       vf_mac.vf =
+               vf_vlan.vf =
+               vf_rate.vf =
+               vf_tx_rate.vf =
+               vf_spoofchk.vf =
+               vf_linkstate.vf =
+               vf_rss_query_en.vf =
+               vf_trust.vf = ivi.vf;
+
+       memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
+       vf_vlan.vlan = ivi.vlan;
+       vf_vlan.qos = ivi.qos;
+       vf_tx_rate.rate = ivi.max_tx_rate;
+       vf_rate.min_tx_rate = ivi.min_tx_rate;
+       vf_rate.max_tx_rate = ivi.max_tx_rate;
+       vf_spoofchk.setting = ivi.spoofchk;
+       vf_linkstate.link_state = ivi.linkstate;
+       vf_rss_query_en.setting = ivi.rss_query_en;
+       vf_trust.setting = ivi.trusted;
+       vf = nla_nest_start(skb, IFLA_VF_INFO);
+       if (!vf) {
+               nla_nest_cancel(skb, vfinfo);
+               return -EMSGSIZE;
+       }
+       if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) ||
+           nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) ||
+           nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate),
+                   &vf_rate) ||
+           nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate),
+                   &vf_tx_rate) ||
+           nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
+                   &vf_spoofchk) ||
+           nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
+                   &vf_linkstate) ||
+           nla_put(skb, IFLA_VF_RSS_QUERY_EN,
+                   sizeof(vf_rss_query_en),
+                   &vf_rss_query_en) ||
+           nla_put(skb, IFLA_VF_TRUST,
+                   sizeof(vf_trust), &vf_trust))
+               return -EMSGSIZE;
+       memset(&vf_stats, 0, sizeof(vf_stats));
+       if (dev->netdev_ops->ndo_get_vf_stats)
+               dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num,
+                                               &vf_stats);
+       vfstats = nla_nest_start(skb, IFLA_VF_STATS);
+       if (!vfstats) {
+               nla_nest_cancel(skb, vf);
+               nla_nest_cancel(skb, vfinfo);
+               return -EMSGSIZE;
+       }
+       if (nla_put_u64(skb, IFLA_VF_STATS_RX_PACKETS,
+                       vf_stats.rx_packets) ||
+           nla_put_u64(skb, IFLA_VF_STATS_TX_PACKETS,
+                       vf_stats.tx_packets) ||
+           nla_put_u64(skb, IFLA_VF_STATS_RX_BYTES,
+                       vf_stats.rx_bytes) ||
+           nla_put_u64(skb, IFLA_VF_STATS_TX_BYTES,
+                       vf_stats.tx_bytes) ||
+           nla_put_u64(skb, IFLA_VF_STATS_BROADCAST,
+                       vf_stats.broadcast) ||
+           nla_put_u64(skb, IFLA_VF_STATS_MULTICAST,
+                       vf_stats.multicast))
+               return -EMSGSIZE;
+       nla_nest_end(skb, vfstats);
+       nla_nest_end(skb, vf);
+       return 0;
+}
+
+static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
+{
+       struct rtnl_link_ifmap map = {
+               .mem_start   = dev->mem_start,
+               .mem_end     = dev->mem_end,
+               .base_addr   = dev->base_addr,
+               .irq         = dev->irq,
+               .dma         = dev->dma,
+               .port        = dev->if_port,
+       };
+       if (nla_put(skb, IFLA_MAP, sizeof(map), &map))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags, u32 ext_filter_mask)
 {
        struct ifinfomsg *ifm;
        struct nlmsghdr *nlh;
-       struct rtnl_link_stats64 temp;
-       const struct rtnl_link_stats64 *stats;
-       struct nlattr *attr, *af_spec;
+       struct nlattr *af_spec;
        struct rtnl_af_ops *af_ops;
        struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
 
@@ -1096,18 +1237,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
            nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down))
                goto nla_put_failure;
 
-       if (1) {
-               struct rtnl_link_ifmap map = {
-                       .mem_start   = dev->mem_start,
-                       .mem_end     = dev->mem_end,
-                       .base_addr   = dev->base_addr,
-                       .irq         = dev->irq,
-                       .dma         = dev->dma,
-                       .port        = dev->if_port,
-               };
-               if (nla_put(skb, IFLA_MAP, sizeof(map), &map))
-                       goto nla_put_failure;
-       }
+       if (rtnl_fill_link_ifmap(skb, dev))
+               goto nla_put_failure;
 
        if (dev->addr_len) {
                if (nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr) ||
@@ -1124,128 +1255,27 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        if (rtnl_phys_switch_id_fill(skb, dev))
                goto nla_put_failure;
 
-       attr = nla_reserve(skb, IFLA_STATS,
-                       sizeof(struct rtnl_link_stats));
-       if (attr == NULL)
-               goto nla_put_failure;
-
-       stats = dev_get_stats(dev, &temp);
-       copy_rtnl_link_stats(nla_data(attr), stats);
-
-       attr = nla_reserve(skb, IFLA_STATS64,
-                       sizeof(struct rtnl_link_stats64));
-       if (attr == NULL)
+       if (rtnl_fill_stats(skb, dev))
                goto nla_put_failure;
-       copy_rtnl_link_stats64(nla_data(attr), stats);
 
        if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF) &&
            nla_put_u32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)))
                goto nla_put_failure;
 
-       if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent
-           && (ext_filter_mask & RTEXT_FILTER_VF)) {
+       if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent &&
+           ext_filter_mask & RTEXT_FILTER_VF) {
                int i;
-
-               struct nlattr *vfinfo, *vf, *vfstats;
+               struct nlattr *vfinfo;
                int num_vfs = dev_num_vf(dev->dev.parent);
 
                vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
                if (!vfinfo)
                        goto nla_put_failure;
                for (i = 0; i < num_vfs; i++) {
-                       struct ifla_vf_info ivi;
-                       struct ifla_vf_mac vf_mac;
-                       struct ifla_vf_vlan vf_vlan;
-                       struct ifla_vf_rate vf_rate;
-                       struct ifla_vf_tx_rate vf_tx_rate;
-                       struct ifla_vf_spoofchk vf_spoofchk;
-                       struct ifla_vf_link_state vf_linkstate;
-                       struct ifla_vf_rss_query_en vf_rss_query_en;
-                       struct ifla_vf_stats vf_stats;
-                       struct ifla_vf_trust vf_trust;
-
-                       /*
-                        * Not all SR-IOV capable drivers support the
-                        * spoofcheck and "RSS query enable" query.  Preset to
-                        * -1 so the user space tool can detect that the driver
-                        * didn't report anything.
-                        */
-                       ivi.spoofchk = -1;
-                       ivi.rss_query_en = -1;
-                       ivi.trusted = -1;
-                       memset(ivi.mac, 0, sizeof(ivi.mac));
-                       /* The default value for VF link state is "auto"
-                        * IFLA_VF_LINK_STATE_AUTO which equals zero
-                        */
-                       ivi.linkstate = 0;
-                       if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
-                               break;
-                       vf_mac.vf =
-                               vf_vlan.vf =
-                               vf_rate.vf =
-                               vf_tx_rate.vf =
-                               vf_spoofchk.vf =
-                               vf_linkstate.vf =
-                               vf_rss_query_en.vf =
-                               vf_trust.vf = ivi.vf;
-
-                       memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
-                       vf_vlan.vlan = ivi.vlan;
-                       vf_vlan.qos = ivi.qos;
-                       vf_tx_rate.rate = ivi.max_tx_rate;
-                       vf_rate.min_tx_rate = ivi.min_tx_rate;
-                       vf_rate.max_tx_rate = ivi.max_tx_rate;
-                       vf_spoofchk.setting = ivi.spoofchk;
-                       vf_linkstate.link_state = ivi.linkstate;
-                       vf_rss_query_en.setting = ivi.rss_query_en;
-                       vf_trust.setting = ivi.trusted;
-                       vf = nla_nest_start(skb, IFLA_VF_INFO);
-                       if (!vf) {
-                               nla_nest_cancel(skb, vfinfo);
-                               goto nla_put_failure;
-                       }
-                       if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) ||
-                           nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) ||
-                           nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate),
-                                   &vf_rate) ||
-                           nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate),
-                                   &vf_tx_rate) ||
-                           nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
-                                   &vf_spoofchk) ||
-                           nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
-                                   &vf_linkstate) ||
-                           nla_put(skb, IFLA_VF_RSS_QUERY_EN,
-                                   sizeof(vf_rss_query_en),
-                                   &vf_rss_query_en) ||
-                           nla_put(skb, IFLA_VF_TRUST,
-                                   sizeof(vf_trust), &vf_trust))
+                       if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
                                goto nla_put_failure;
-                       memset(&vf_stats, 0, sizeof(vf_stats));
-                       if (dev->netdev_ops->ndo_get_vf_stats)
-                               dev->netdev_ops->ndo_get_vf_stats(dev, i,
-                                                                 &vf_stats);
-                       vfstats = nla_nest_start(skb, IFLA_VF_STATS);
-                       if (!vfstats) {
-                               nla_nest_cancel(skb, vf);
-                               nla_nest_cancel(skb, vfinfo);
-                               goto nla_put_failure;
-                       }
-                       if (nla_put_u64(skb, IFLA_VF_STATS_RX_PACKETS,
-                                       vf_stats.rx_packets) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_TX_PACKETS,
-                                       vf_stats.tx_packets) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_RX_BYTES,
-                                       vf_stats.rx_bytes) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_TX_BYTES,
-                                       vf_stats.tx_bytes) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_BROADCAST,
-                                       vf_stats.broadcast) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_MULTICAST,
-                                       vf_stats.multicast))
-                               goto nla_put_failure;
-                       nla_nest_end(skb, vfstats);
-                       nla_nest_end(skb, vf);
                }
+
                nla_nest_end(skb, vfinfo);
        }