diff mbox

[RFC,net-next,v2,2/5] rtnl/ipv6: use netconf msg to advertise forwarding status

Message ID 1351094579-3911-3-git-send-email-nicolas.dichtel@6wind.com
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Nicolas Dichtel Oct. 24, 2012, 4:02 p.m. UTC
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/uapi/linux/rtnetlink.h |  2 ++
 net/ipv6/addrconf.c            | 77 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

Comments

David Miller Oct. 26, 2012, 6:18 a.m. UTC | #1
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Wed, 24 Oct 2012 18:02:56 +0200

> +static inline int inet6_netconf_msgsize_devconf(int type)

Outside of header files, we don't add explicit inlines, we let
the compiler decide.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Nicolas Dichtel Oct. 26, 2012, 8:28 a.m. UTC | #2
This patch serie aims to advertising via netlink any change in the network
configuration of a protocol (network or transport). For example the announcement
when ip forwarding parameter is toggled. 

It adds a new kind of messages, RTM_NEWNETCONF/RTM_GETNETCONF.

The patch which adds the support of netconf messages in iproute2 will be sent
when the feature will be included.  If someone is interested to get it before,
just tell me!

v3: remove inline attribute in non header files

v2: rename functions to be consistent
    specify type of the attribute to notify when calling
    inet[6]_netconf_notify_devconf(), goal is to notify only thinks that
    changed.
    add RTM_GETNETCONF support

Comments are welcome.

Regards,
Nicolas
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Laight Oct. 26, 2012, 9:03 a.m. UTC | #3
> > +static inline int inet6_netconf_msgsize_devconf(int type)
> 
> Outside of header files, we don't add explicit inlines, we let
> the compiler decide.

Hmmm.... In my experience it makes bad decisions,
even for static functions that are only called once.
And yes, I have checked that the inlined code is smaller
and faster.

	David



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Oct. 26, 2012, 9:17 a.m. UTC | #4
From: "David Laight" <David.Laight@ACULAB.COM>
Date: Fri, 26 Oct 2012 10:03:54 +0100

>> > +static inline int inet6_netconf_msgsize_devconf(int type)
>> 
>> Outside of header files, we don't add explicit inlines, we let
>> the compiler decide.
> 
> Hmmm.... In my experience it makes bad decisions,
> even for static functions that are only called once.
> And yes, I have checked that the inlined code is smaller
> and faster.

This isn't for you to decide.  It's been decided long ago that we're
doing things tree wide doing things this way.

If GCC is not perfect, submit a well formed bug report, don't complain
here.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Oct. 28, 2012, 11:05 p.m. UTC | #5
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Fri, 26 Oct 2012 10:28:48 +0200

> This patch serie aims to advertising via netlink any change in the network
> configuration of a protocol (network or transport). For example the announcement
> when ip forwarding parameter is toggled. 
> 
> It adds a new kind of messages, RTM_NEWNETCONF/RTM_GETNETCONF.
> 
> The patch which adds the support of netconf messages in iproute2 will be sent
> when the feature will be included.  If someone is interested to get it before,
> just tell me!
> 
> v3: remove inline attribute in non header files
> 
> v2: rename functions to be consistent
>     specify type of the attribute to notify when calling
>     inet[6]_netconf_notify_devconf(), goal is to notify only thinks that
>     changed.
>     add RTM_GETNETCONF support
> 
> Comments are welcome.

All applied, thanks Nicolas.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 0043b41..a4d75ea 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -592,6 +592,8 @@  enum rtnetlink_groups {
 #define RTNLGRP_PHONET_ROUTE	RTNLGRP_PHONET_ROUTE
 	RTNLGRP_DCB,
 #define RTNLGRP_DCB		RTNLGRP_DCB
+	RTNLGRP_IPV6_NETCONF,
+#define RTNLGRP_IPV6_NETCONF	RTNLGRP_IPV6_NETCONF
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0424e4e..9bf4d1b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -81,6 +81,7 @@ 
 #include <net/pkt_sched.h>
 #include <linux/if_tunnel.h>
 #include <linux/rtnetlink.h>
+#include <linux/netconf.h>
 
 #ifdef CONFIG_IPV6_PRIVACY
 #include <linux/random.h>
@@ -460,6 +461,72 @@  static struct inet6_dev *ipv6_find_idev(struct net_device *dev)
 	return idev;
 }
 
+static inline int inet6_netconf_msgsize_devconf(int type)
+{
+	int size =  NLMSG_ALIGN(sizeof(struct netconfmsg))
+		    + nla_total_size(4);	/* NETCONFA_IFINDEX */
+
+	if (type == NETCONFA_FORWARDING)
+		size += nla_total_size(4);
+
+	return size;
+}
+
+static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
+				      struct ipv6_devconf *devconf, u32 portid,
+				      u32 seq, int event, unsigned int flags,
+				      int type)
+{
+	struct nlmsghdr  *nlh;
+	struct netconfmsg *ncm;
+
+	nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
+			flags);
+	if (nlh == NULL)
+		return -EMSGSIZE;
+
+	ncm = nlmsg_data(nlh);
+	ncm->ncm_family = AF_INET6;
+
+	if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
+		goto nla_put_failure;
+
+	if (type == NETCONFA_FORWARDING &&
+	    nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
+		goto nla_put_failure;
+
+	return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
+}
+
+static void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+					 struct ipv6_devconf *devconf)
+{
+	struct sk_buff *skb;
+	int err = -ENOBUFS;
+
+	skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_ATOMIC);
+	if (skb == NULL)
+		goto errout;
+
+	err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
+					 RTM_NEWNETCONF, 0, type);
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
+	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC);
+	return;
+errout:
+	if (err < 0)
+		rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
+}
+
 #ifdef CONFIG_SYSCTL
 static void dev_forward_change(struct inet6_dev *idev)
 {
@@ -486,6 +553,8 @@  static void dev_forward_change(struct inet6_dev *idev)
 		else
 			addrconf_leave_anycast(ifa);
 	}
+	inet6_netconf_notify_devconf(dev_net(dev), NETCONFA_FORWARDING,
+				     dev->ifindex, &idev->cnf);
 }
 
 
@@ -518,6 +587,10 @@  static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
 	*p = newf;
 
 	if (p == &net->ipv6.devconf_dflt->forwarding) {
+		if ((!newf) ^ (!old))
+			inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+						     NETCONFA_IFINDEX_DEFAULT,
+						     net->ipv6.devconf_dflt);
 		rtnl_unlock();
 		return 0;
 	}
@@ -525,6 +598,10 @@  static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
 	if (p == &net->ipv6.devconf_all->forwarding) {
 		net->ipv6.devconf_dflt->forwarding = newf;
 		addrconf_forward_change(net, newf);
+		if ((!newf) ^ (!old))
+			inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+						     NETCONFA_IFINDEX_ALL,
+						     net->ipv6.devconf_all);
 	} else if ((!newf) ^ (!old))
 		dev_forward_change((struct inet6_dev *)table->extra1);
 	rtnl_unlock();