#include <linux/kernel.h>
#include <linux/rtnetlink.h>
+#include <net/netlink.h>
#include "br_private.h"
+static inline size_t br_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ + nla_total_size(4) /* IFLA_MASTER */
+ + nla_total_size(4) /* IFLA_MTU */
+ + nla_total_size(4) /* IFLA_LINK */
+ + nla_total_size(1) /* IFLA_OPERSTATE */
+ + nla_total_size(1); /* IFLA_PROTINFO */
+}
+
/*
* Create one netlink message for one interface
* Contains port and master info as well as carrier and bridge state.
void br_ifinfo_notify(int event, struct net_bridge_port *port)
{
struct sk_buff *skb;
- int err = -ENOMEM;
+ int err = -ENOBUFS;
pr_debug("bridge notify event=%d\n", event);
- skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128),
- GFP_ATOMIC);
- if (!skb)
- goto err_out;
-
- err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
- if (err)
- goto err_kfree;
-
- NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
- netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
- return;
-
-err_kfree:
- kfree_skb(skb);
-err_out:
- netlink_set_err(rtnl, 0, RTNLGRP_LINK, err);
+ skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC);
+ if (skb == NULL)
+ goto errout;
+
+ err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
+ /* failure implies BUG in br_nlmsg_size() */
+ BUG_ON(err < 0);
+
+ err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+errout:
+ if (err < 0)
+ rtnl_set_sk_err(RTNLGRP_LINK, err);
}
/*