Skip to content

Commit b1974ed

Browse files
ronenildavem330
authored andcommitted
netlink: Rightsize IFLA_AF_SPEC size calculation
if_nlmsg_size() overestimates the minimum allocation size of netlink dump request (when called from rtnl_calcit()) or the size of the message (when called from rtnl_getlink()). This is because ext_filter_mask is not supported by rtnl_link_get_af_size() and rtnl_link_get_size(). The over-estimation is significant when at least one netdev has many VLANs configured (8 bytes for each configured VLAN). This patch-set "rightsizes" the protocol specific attribute size calculation by propagating ext_filter_mask to rtnl_link_get_af_size() and adding this a argument to get_link_af_size op in rtnl_af_ops. Bridge module already used filtering aware sizing for notifications. br_get_link_af_size_filtered() is consistent with the modified get_link_af_size op so it replaces br_get_link_af_size() in br_af_ops. br_get_link_af_size() becomes unused and thus removed. Signed-off-by: Ronen Arad <[email protected]> Acked-by: Sridhar Samudrala <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6ac311a commit b1974ed

File tree

5 files changed

+11
-28
lines changed

5 files changed

+11
-28
lines changed

include/net/rtnetlink.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ struct rtnl_af_ops {
124124
int (*fill_link_af)(struct sk_buff *skb,
125125
const struct net_device *dev,
126126
u32 ext_filter_mask);
127-
size_t (*get_link_af_size)(const struct net_device *dev);
127+
size_t (*get_link_af_size)(const struct net_device *dev,
128+
u32 ext_filter_mask);
128129

129130
int (*validate_link_af)(const struct net_device *dev,
130131
const struct nlattr *attr);

net/bridge/br_netlink.c

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,29 +1214,10 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
12141214
return 0;
12151215
}
12161216

1217-
static size_t br_get_link_af_size(const struct net_device *dev)
1218-
{
1219-
struct net_bridge_port *p;
1220-
struct net_bridge *br;
1221-
int num_vlans = 0;
1222-
1223-
if (br_port_exists(dev)) {
1224-
p = br_port_get_rtnl(dev);
1225-
num_vlans = br_get_num_vlan_infos(nbp_vlan_group(p),
1226-
RTEXT_FILTER_BRVLAN);
1227-
} else if (dev->priv_flags & IFF_EBRIDGE) {
1228-
br = netdev_priv(dev);
1229-
num_vlans = br_get_num_vlan_infos(br_vlan_group(br),
1230-
RTEXT_FILTER_BRVLAN);
1231-
}
1232-
1233-
/* Each VLAN is returned in bridge_vlan_info along with flags */
1234-
return num_vlans * nla_total_size(sizeof(struct bridge_vlan_info));
1235-
}
12361217

12371218
static struct rtnl_af_ops br_af_ops __read_mostly = {
12381219
.family = AF_BRIDGE,
1239-
.get_link_af_size = br_get_link_af_size,
1220+
.get_link_af_size = br_get_link_af_size_filtered,
12401221
};
12411222

12421223
struct rtnl_link_ops br_link_ops __read_mostly = {

net/core/rtnetlink.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ void rtnl_af_unregister(struct rtnl_af_ops *ops)
497497
}
498498
EXPORT_SYMBOL_GPL(rtnl_af_unregister);
499499

500-
static size_t rtnl_link_get_af_size(const struct net_device *dev)
500+
static size_t rtnl_link_get_af_size(const struct net_device *dev,
501+
u32 ext_filter_mask)
501502
{
502503
struct rtnl_af_ops *af_ops;
503504
size_t size;
@@ -509,7 +510,7 @@ static size_t rtnl_link_get_af_size(const struct net_device *dev)
509510
if (af_ops->get_link_af_size) {
510511
/* AF_* + nested data */
511512
size += nla_total_size(sizeof(struct nlattr)) +
512-
af_ops->get_link_af_size(dev);
513+
af_ops->get_link_af_size(dev, ext_filter_mask);
513514
}
514515
}
515516

@@ -900,7 +901,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
900901
+ rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
901902
+ rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
902903
+ rtnl_link_get_size(dev) /* IFLA_LINKINFO */
903-
+ rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
904+
+ rtnl_link_get_af_size(dev, ext_filter_mask) /* IFLA_AF_SPEC */
904905
+ nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_PORT_ID */
905906
+ nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_SWITCH_ID */
906907
+ nla_total_size(1); /* IFLA_PROTO_DOWN */
@@ -3443,4 +3444,3 @@ void __init rtnetlink_init(void)
34433444
rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, NULL);
34443445
rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL);
34453446
}
3446-

net/ipv4/devinet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,7 +1644,8 @@ static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
16441644
rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err);
16451645
}
16461646

1647-
static size_t inet_get_link_af_size(const struct net_device *dev)
1647+
static size_t inet_get_link_af_size(const struct net_device *dev,
1648+
u32 ext_filter_mask)
16481649
{
16491650
struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr);
16501651

@@ -2398,4 +2399,3 @@ void __init devinet_init(void)
23982399
rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
23992400
inet_netconf_dump_devconf, NULL);
24002401
}
2401-

net/ipv6/addrconf.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4788,7 +4788,8 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
47884788
return -EMSGSIZE;
47894789
}
47904790

4791-
static size_t inet6_get_link_af_size(const struct net_device *dev)
4791+
static size_t inet6_get_link_af_size(const struct net_device *dev,
4792+
u32 ext_filter_mask)
47924793
{
47934794
if (!__in6_dev_get(dev))
47944795
return 0;

0 commit comments

Comments
 (0)