All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick Ruddy <pruddy@vyatta.att-mail.com>
To: netdev@vger.kernel.org
Cc: roopa@cumulusnetworks.com, jiri@resnulli.us, stephen@networkplumber.org
Subject: Re: [PATCH net-next 1/2] netlink: ipv4 IGMP join notifications
Date: Thu, 30 Aug 2018 17:44:16 +0100	[thread overview]
Message-ID: <70e2f41798fefa64f0fdb946ed25d342c60e3cca.camel@vyatta.att-mail.com> (raw)
In-Reply-To: <20180830093545.29465-2-pruddy@vyatta.att-mail.com>

Don't know what happened to the 0/2 cover for this series so here it
is:

This patch is an update to https://patchwork.ozlabs.org/patch/571127/.
The
previous patch was based on sending multicast MAC addresses in the
netlink messages to allow the programming of hardware. It was agreed to
rework this to use RTM_NEW/DELLINK messages which were more appropriate
for layer 2 addresses.
In the interim period it has become apparent that the applications
actually
needs to see the L3 multicast addresses which are joined for FORUS
processing so this patch has been reworked to send the L3 multicast
addresses using RTM_NEW/DELADDR.
These new multicast L3 netlink notifications should use the
IFA_MULTICAST
address type but this has been dropped in favour of IFA_ADDRESS as
during
testing it was noticed that some applications - notably getaddrinfo in
lib6c assume that there is an IFA_ADDRESS in a RTM_NEW/DELADDR and
blindly dereference it.
Finally the RTM_GETADDR for both address families has been modified to
include the multicast l3 addresses.

Patrick Ruddy (2):
  netlink: ipv4 IGMP join notifications
  netlink: ipv6 MLD join notifications

 include/linux/igmp.h |  2 +
 net/ipv4/devinet.c   | 39 +++++++++++++------
 net/ipv4/igmp.c      | 90 ++++++++++++++++++++++++++++++++++++++++++++
 net/ipv6/addrconf.c  | 44 ++++++++++++++++------
 net/ipv6/mcast.c     | 66 ++++++++++++++++++++++++++++++++
 5 files changed, 218 insertions(+), 23 deletions(-)

-- 
2.17.1

On Thu, 2018-08-30 at 10:35 +0100, Patrick Ruddy wrote:
> Some userspace applications need to know about IGMP joins from the kernel
> for 2 reasons
> 1. To allow the programming of multicast MAC filters in hardware
> 2. To form a multicast FORUS list for non link-local multicast
>    groups to be sent to the kernel and from there to the interested
>    party.
> (1) can be fulfilled but simply sending the hardware multicast MAC
> address to be programmed but (2) requires the L3 address to be sent
> since this cannot be constructed from the MAC address whereas the
> reverse translation is a standard library function.
> 
> This commit provides addition and deletion of multicast addresses
> using the RTM_NEWADDR and RTM_DELADDR messages. It also provides
> the RTM_GETADDR extension to allow multicast join state to be read
> from the kernel.
> 
> Signed-off-by: Patrick Ruddy <pruddy@vyatta.att-mail.com>
> ---
>  include/linux/igmp.h |  2 +
>  net/ipv4/devinet.c   | 39 +++++++++++++------
>  net/ipv4/igmp.c      | 90 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 120 insertions(+), 11 deletions(-)
> 
> diff --git a/include/linux/igmp.h b/include/linux/igmp.h
> index 119f53941c12..1fb417865e7d 100644
> --- a/include/linux/igmp.h
> +++ b/include/linux/igmp.h
> @@ -130,6 +130,8 @@ extern void ip_mc_unmap(struct in_device *);
>  extern void ip_mc_remap(struct in_device *);
>  extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
>  extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
> +extern int ip_mc_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb,
> +			     struct net_device *dev);
>  int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed);
>  
>  #endif
> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
> index ea4bd8a52422..42f7dcc4fb5e 100644
> --- a/net/ipv4/devinet.c
> +++ b/net/ipv4/devinet.c
> @@ -57,6 +57,7 @@
>  #endif
>  #include <linux/kmod.h>
>  #include <linux/netconf.h>
> +#include <linux/igmp.h>
>  
>  #include <net/arp.h>
>  #include <net/ip.h>
> @@ -1651,6 +1652,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
>  	int h, s_h;
>  	int idx, s_idx;
>  	int ip_idx, s_ip_idx;
> +	int multicast, mcast_idx;
>  	struct net_device *dev;
>  	struct in_device *in_dev;
>  	struct in_ifaddr *ifa;
> @@ -1659,6 +1661,8 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
>  	s_h = cb->args[0];
>  	s_idx = idx = cb->args[1];
>  	s_ip_idx = ip_idx = cb->args[2];
> +	multicast = cb->args[3];
> +	mcast_idx = cb->args[4];
>  
>  	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
>  		idx = 0;
> @@ -1675,18 +1679,29 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
>  			if (!in_dev)
>  				goto cont;
>  
> -			for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
> -			     ifa = ifa->ifa_next, ip_idx++) {
> -				if (ip_idx < s_ip_idx)
> -					continue;
> -				if (inet_fill_ifaddr(skb, ifa,
> -					     NETLINK_CB(cb->skb).portid,
> -					     cb->nlh->nlmsg_seq,
> -					     RTM_NEWADDR, NLM_F_MULTI) < 0) {
> -					rcu_read_unlock();
> -					goto done;
> +			if (!multicast) {
> +				for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
> +				     ifa = ifa->ifa_next, ip_idx++) {
> +					if (ip_idx < s_ip_idx)
> +						continue;
> +					if (inet_fill_ifaddr(skb, ifa,
> +							     NETLINK_CB(cb->skb).portid,
> +							     cb->nlh->nlmsg_seq,
> +							     RTM_NEWADDR,
> +							     NLM_F_MULTI) < 0) {
> +						rcu_read_unlock();
> +						goto done;
> +					}
> +					nl_dump_check_consistent(cb,
> +								 nlmsg_hdr(skb));
>  				}
> -				nl_dump_check_consistent(cb, nlmsg_hdr(skb));
> +				/* set for multicast loop */
> +				multicast++;
> +			}
> +			/* loop over multicast addresses */
> +			if (ip_mc_dump_ifaddr(skb, cb, dev) < 0) {
> +				rcu_read_unlock();
> +				goto done;
>  			}
>  cont:
>  			idx++;
> @@ -1698,6 +1713,8 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
>  	cb->args[0] = h;
>  	cb->args[1] = idx;
>  	cb->args[2] = ip_idx;
> +	cb->args[3] = multicast;
> +	cb->args[4] = mcast_idx;
>  
>  	return skb->len;
>  }
> diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
> index cf75f8944b05..c9bbd1d27124 100644
> --- a/net/ipv4/igmp.c
> +++ b/net/ipv4/igmp.c
> @@ -86,6 +86,7 @@
>  #include <linux/inetdevice.h>
>  #include <linux/igmp.h>
>  #include <linux/if_arp.h>
> +#include <net/netlink.h>
>  #include <linux/rtnetlink.h>
>  #include <linux/times.h>
>  #include <linux/pkt_sched.h>
> @@ -1384,6 +1385,91 @@ static void ip_mc_hash_remove(struct in_device *in_dev,
>  }
>  
>  
> +static int fill_addr(struct sk_buff *skb, struct net_device *dev, __be32 addr,
> +		     int type, unsigned int flags)
> +{
> +	struct nlmsghdr *nlh;
> +	struct ifaddrmsg *ifm;
> +
> +	nlh = nlmsg_put(skb, 0, 0, type, sizeof(*ifm), flags);
> +	if (!nlh)
> +		return -EMSGSIZE;
> +
> +	ifm = nlmsg_data(nlh);
> +	ifm->ifa_family = AF_INET;
> +	ifm->ifa_prefixlen = 32;
> +	ifm->ifa_flags = IFA_F_PERMANENT;
> +	ifm->ifa_scope = RT_SCOPE_LINK;
> +	ifm->ifa_index = dev->ifindex;
> +
> +	if (nla_put_in_addr(skb, IFA_ADDRESS, addr))
> +		goto nla_put_failure;
> +	nlmsg_end(skb, nlh);
> +	return 0;
> +
> +nla_put_failure:
> +	nlmsg_cancel(skb, nlh);
> +	return -EMSGSIZE;
> +}
> +
> +static inline size_t addr_nlmsg_size(void)
> +{
> +	return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
> +		+ nla_total_size(sizeof(__be32));
> +}
> +
> +static void ip_mc_addr_notify(struct net_device *dev, __be32 addr, int type)
> +{
> +	struct net *net = dev_net(dev);
> +	struct sk_buff *skb;
> +	int err = -ENOBUFS;
> +
> +	skb = nlmsg_new(addr_nlmsg_size(), GFP_ATOMIC);
> +	if (!skb)
> +		goto errout;
> +
> +	err = fill_addr(skb, dev, addr, type, 0);
> +	if (err < 0) {
> +		WARN_ON(err == -EMSGSIZE);
> +		kfree_skb(skb);
> +		goto errout;
> +	}
> +	rtnl_notify(skb, net, 0, RTNLGRP_IPV4_IFADDR, NULL, GFP_ATOMIC);
> +	return;
> +errout:
> +	if (err < 0)
> +		rtnl_set_sk_err(net, RTNLGRP_LINK, err);
> +}
> +
> +int ip_mc_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb,
> +		      struct net_device *dev)
> +{
> +	int s_idx;
> +	int idx = 0;
> +	struct ip_mc_list *im;
> +	struct in_device *in_dev;
> +
> +	ASSERT_RTNL();
> +
> +	s_idx = cb->args[4];
> +	in_dev = __in_dev_get_rtnl(dev);
> +
> +	for_each_pmc_rtnl(in_dev, im) {
> +		if (idx < s_idx)
> +			continue;
> +		if (fill_addr(skb, dev, im->multiaddr, RTM_NEWADDR,
> +			      NLM_F_MULTI) < 0)
> +			goto done;
> +		nl_dump_check_consistent(cb, nlmsg_hdr(skb));
> +		idx++;
> +	}
> +
> + done:
> +	cb->args[4] = idx;
> +
> +	return skb->len;
> +}
> +
>  /*
>   *	A socket has joined a multicast group on device dev.
>   */
> @@ -1433,6 +1519,8 @@ static void __ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
>  	igmpv3_del_delrec(in_dev, im);
>  #endif
>  	igmp_group_added(im);
> +
> +	ip_mc_addr_notify(in_dev->dev, addr, RTM_NEWADDR);
>  	if (!in_dev->dead)
>  		ip_rt_multicast_event(in_dev);
>  out:
> @@ -1664,6 +1752,8 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
>  				in_dev->mc_count--;
>  				igmp_group_dropped(i);
>  				ip_mc_clear_src(i);
> +				ip_mc_addr_notify(in_dev->dev, addr,
> +						  RTM_DELADDR);
>  
>  				if (!in_dev->dead)
>  					ip_rt_multicast_event(in_dev);

  reply	other threads:[~2018-08-30 20:47 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-30  9:35 [PATCH net-next 0/2] netlink: multicast join notifications Patrick Ruddy
2018-08-30  9:35 ` [PATCH net-next 1/2] netlink: ipv4 IGMP " Patrick Ruddy
2018-08-30 16:44   ` Patrick Ruddy [this message]
2018-08-31  4:23   ` kbuild test robot
2018-08-31  4:52   ` kbuild test robot
2018-08-31 11:20   ` [PATCH net-next v2 1/2] netlink: ipv4 igmp " Patrick Ruddy
2018-08-31 11:20     ` [PATCH net-next v2 2/2] netlink: ipv6 MLD " Patrick Ruddy
2018-08-31 16:29     ` [PATCH net-next v2 1/2] netlink: ipv4 igmp " Roopa Prabhu
2018-09-02 11:18       ` Patrick Ruddy
2018-09-03 23:12         ` Roopa Prabhu
2018-09-04  7:54           ` Patrick Ruddy
2018-09-04 16:36           ` Patrick Ruddy
2018-09-06  9:10   ` [PATCH net-next v3 " Patrick Ruddy
2018-09-06  9:10     ` [PATCH net-next v3 2/2] netlink: ipv6 MLD " Patrick Ruddy
2018-09-07  3:40     ` [PATCH net-next v3 1/2] netlink: ipv4 igmp " Roopa Prabhu
2018-09-13 17:03       ` Roopa Prabhu
2018-09-13 17:49         ` Patrick Ruddy
2018-09-18 13:12         ` Patrick Ruddy
2018-09-20  4:47           ` David Ahern
2018-09-25  9:34             ` Patrick Ruddy
2018-09-26 17:23               ` Roopa Prabhu
2018-10-01 15:38                 ` Roopa Prabhu
2018-08-30  9:35 ` [PATCH net-next 2/2] netlink: ipv6 MLD " Patrick Ruddy
2018-08-31  5:35   ` kbuild test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=70e2f41798fefa64f0fdb946ed25d342c60e3cca.camel@vyatta.att-mail.com \
    --to=pruddy@vyatta.att-mail.com \
    --cc=jiri@resnulli.us \
    --cc=netdev@vger.kernel.org \
    --cc=roopa@cumulusnetworks.com \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.