netdev
[Top] [All Lists]

Re: Source Specific Query of MLDv2 [PATCH]

To: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@xxxxxxxxxxxxxx>
Subject: Re: Source Specific Query of MLDv2 [PATCH]
From: David Stevens <dlstevens@xxxxxxxxxx>
Date: Tue, 10 Feb 2004 17:45:43 -0700
Cc: davem@xxxxxxxxxx, hibi665@xxxxxxx, netdev@xxxxxxxxxxx, "Hideaki YOSHIFUJI" <yoshfuji@xxxxxxxxxxxxxxxxxxxxxxxxx>, yoshfuji@xxxxxxxxxxxxxx
In-reply-to: <20040210.125124.97248371.yoshfuji@xxxxxxxxxxxxxx>
Sender: netdev-bounce@xxxxxxxxxxx

"Hideaki YOSHIFUJI" <yoshfuji@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote on 02/09/2004 07:51:24 PM:

> likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)))?

If your question is "why use the deliver variable?", I left that because it'd
need to be re-added when multicast routing is supported. This patch puts it back,
and eliminates "discard" (including within the "#if 0" code).

> Where is pskb_pull()?
> I'd suggest to check the protocol number != icmp there.
> After doing pskb_pull() in icmpv6_rcv(), we see type field.


Oops! I missed that one. This patch adds it. I did not
split the protocol check from the type check because they'd be
in two different places (less clear what they're for). By keeping
it in one place, it's clear exactly which packets are excepted,
and the only cost is an extra do-nothing pskb_pull() for ICMP
multicasts coming from a host that is excluded by the source
filters.

> BTW, I want to keep #if 0 ... #endif portion.
> We're working on this... :-)


I put it back in this patch, but edited it to remove "discard".

+-DLS

diff -ruN linux-2.6.2/include/net/addrconf.h linux-2.6.2F2/include/net/addrconf.h
--- linux-2.6.2/include/net/addrconf.h 2004-02-03 19:44:17.000000000 -0800
+++ linux-2.6.2F2/include/net/addrconf.h 2004-02-10 15:17:00.000000000 -0800
@@ -98,6 +98,7 @@

extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
struct in6_addr *src_addr);
+extern int ipv6_is_mld(struct sk_buff *skb);

extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);

diff -ruN linux-2.6.2/net/ipv6/ip6_input.c linux-2.6.2F2/net/ipv6/ip6_input.c
--- linux-2.6.2/net/ipv6/ip6_input.c 2004-02-03 19:44:14.000000000 -0800
+++ linux-2.6.2F2/net/ipv6/ip6_input.c 2004-02-10 16:23:51.808947560 -0800
@@ -168,11 +168,19 @@

smp_read_barrier_depends();
if (ipprot->flags & INET6_PROTO_FINAL) {
+ struct ipv6hdr *hdr;
+
if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) {
skb->csum = csum_sub(skb->csum,
    csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
cksum_sub++;
}

+ hdr = skb->nh.ipv6h;
+ if (ipv6_addr_is_multicast(&hdr->daddr) &&
+    !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
+    &hdr->saddr) &&
+    !ipv6_is_mld(skb))
+ goto discard;
}
if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
   !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
@@ -211,15 +219,14 @@

int ip6_mc_input(struct sk_buff *skb)
{
- struct ipv6hdr *hdr;
- int deliver = 0;
- int discard = 1;
+ struct ipv6hdr *hdr;
+ int deliver;

IP6_INC_STATS_BH(Ip6InMcastPkts);

hdr = skb->nh.ipv6h;
- if (ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, &hdr->saddr))
- deliver = 1;
+ deliver = !(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) ||
+    ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);

/*
* IPv6 multicast router mode isnt currently supported.
@@ -238,23 +245,21 @@

if (deliver) {
skb2 = skb_clone(skb, GFP_ATOMIC);
+ dst_output(skb2);
} else {
- discard = 0;
- skb2 = skb;
+ dst_output(skb);
+ return 0;
}
-
- dst_output(skb2);
}

}
#endif

- if (deliver) {
- discard = 0;
+ if (likely(deliver)) {
ip6_input(skb);
+ return 0;
}
-
- if (discard)
- kfree_skb(skb);
+ /* discard */
+ kfree_skb(skb);

return 0;
}
diff -ruN linux-2.6.2/net/ipv6/mcast.c linux-2.6.2F2/net/ipv6/mcast.c
--- linux-2.6.2/net/ipv6/mcast.c 2004-02-03 19:44:28.000000000 -0800
+++ linux-2.6.2F2/net/ipv6/mcast.c 2004-02-10 15:15:52.000000000 -0800
@@ -901,6 +901,30 @@
}

/*
+ * identify MLD packets for MLD filter exceptions
+ */
+int ipv6_is_mld(struct sk_buff *skb)
+{
+ struct icmp6hdr *pic;
+
+ if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
+ return 0;
+
+ pic = (struct icmp6hdr *)skb->h.raw;
+
+ switch (pic->icmp6_type) {
+ case ICMPV6_MGM_QUERY:
+ case ICMPV6_MGM_REPORT:
+ case ICMPV6_MGM_REDUCTION:
+ case ICMPV6_MLD2_REPORT:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
 * check if the interface/address pair is valid
 */
int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
@@ -918,7 +942,7 @@
break;
}
if (mc) {

- if (!ipv6_addr_any(src_addr)) {
+ if (src_addr && !ipv6_addr_any(src_addr)) {
struct ip6_sf_list *psf;

spin_lock_bh(&mc->mca_lock);

(See attached file: mldx4.patch)

Attachment: mldx4.patch
Description: Binary data

<Prev in Thread] Current Thread [Next in Thread>