Commit 43eadf90 authored by Kirill Smelkov's avatar Kirill Smelkov

X ipv4: mr: Don't output packet to loopback twice

If multicast routing software configures kernel to forward incoming
multicast frames from external interfaces to lo, then, currently, every
packet will be delivered to local host exactly twice:

- once via xmit over real loopback device, and
- once via dev_loopback_xmit() called by ip_mc_output.

-> Fix this double delivery by avoiding second dev_loopback_xmit() call if
target device is already known to be of loopback kind.

For the referece: IPv6 already behaves this way starting from Linux 2.1.89
(commit 3b0db29e in historical repository):

    ip6_finish_output2(net, sk, skb)
    	if (ipv6_addr_is_multicast(daddr)) {
    		if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(sk) &&	<-- NOTE `dev->flags & IFF_LOOPBACK`
    			...
    			dev_loopback_xmit

    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv6/ip6_output.c?id=v5.18-rc5-28-ga7391ad35724#n81

XXX link to my test program

XXX not sure whether we should `& IFF_LOOPBACK` or check `dev == net->loop_device`
    or `& IFF_LOOPBACK && dev->netns == net`

XXX test

XXX Cc
Signed-off-by: Kirill Smelkov's avatarKirill Smelkov <kirr@nexedi.com>
parent 4950b699
...@@ -374,7 +374,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) ...@@ -374,7 +374,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)
*/ */
if (rt->rt_flags&RTCF_MULTICAST) { if (rt->rt_flags&RTCF_MULTICAST) {
if (sk_mc_loop(sk) if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(sk)
#ifdef CONFIG_IP_MROUTE #ifdef CONFIG_IP_MROUTE
/* Small optimization: do not loopback not local frames, /* Small optimization: do not loopback not local frames,
which returned after forwarding; they will be dropped which returned after forwarding; they will be dropped
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment