[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

(usagi-users 03398) Re: MLDv2 linux implementation questions



David,

Thanks for the quick fixup, but this patch causes a kernel panic on my i386
architecture after the first SSM calls. Also, would it be possible to
fix the IPv4 code
too ?

To reproduce :

./test_msf ff3e::1234

>p 2001:6::1 0
>r 2001:6::1 0
=> kernel panic.

Hoerdt Mickaël

David Stevens wrote:

>Hoerdt,
>        Here's the complete patch, which should
>fix the problem you've seen. Please let me know if
>you turn up anything else, of course. :-)
>
>                                +-DLS
>diff -ruNp linux-2.6.11.12/net/ipv6/ipv6_sockglue.c 
>linux-2.6.11.12MCT/net/ipv6/ipv6_sockglue.c
>--- linux-2.6.11.12/net/ipv6/ipv6_sockglue.c    2005-03-01 
>23:37:48.000000000 -0800
>+++ linux-2.6.11.12MCT/net/ipv6/ipv6_sockglue.c 2005-06-15 
>14:17:46.000000000 -0700
>@@ -423,11 +423,12 @@ done:
>                        psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
>                        retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
>                                &psin6->sin6_addr);
>-                       if (retv)
>+                       /* prior join w/ different source is ok */
>+                       if (retv && retv != -EADDRINUSE)
>                                break;
>                        omode = MCAST_INCLUDE;
>                        add = 1;
>-               } else /*IP_DROP_SOURCE_MEMBERSHIP */ {
>+               } else /* MCAST_LEAVE_SOURCE_GROUP */ {
>                        omode = MCAST_INCLUDE;
>                        add = 0;
>                }
>diff -ruNp linux-2.6.11.12/net/ipv6/mcast.c 
>linux-2.6.11.12MCT/net/ipv6/mcast.c
>--- linux-2.6.11.12/net/ipv6/mcast.c    2005-03-01 23:38:25.000000000 
>-0800
>+++ linux-2.6.11.12MCT/net/ipv6/mcast.c 2005-06-14 16:37:22.000000000 
>-0700
>@@ -188,6 +188,16 @@ int ipv6_sock_mc_join(struct sock *sk, i
>        if (!ipv6_addr_is_multicast(addr))
>                return -EINVAL;
> 
>+       read_lock_bh(&ipv6_sk_mc_lock);
>+       for (mc_lst=np->ipv6_mc_list; mc_lst; mc_lst=mc_lst->next) {
>+               if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
>+                   ipv6_addr_equal(&mc_lst->addr, addr)) {
>+                       read_unlock_bh(&ipv6_sk_mc_lock);
>+                       return -EADDRINUSE;
>+               }
>+       }
>+       read_unlock_bh(&ipv6_sk_mc_lock);
>+
>        mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), 
>GFP_KERNEL);
> 
>        if (mc_lst == NULL)
>@@ -241,19 +251,18 @@ int ipv6_sock_mc_join(struct sock *sk, i
> /*
>  *     socket leave on multicast group
>  */
>-int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr 
>*addr)
>+static int __ipv6_sock_mc_drop(struct sock *sk, int ifindex,
>+       struct in6_addr *addr)
> {
>        struct ipv6_pinfo *np = inet6_sk(sk);
>        struct ipv6_mc_socklist *mc_lst, **lnk;
> 
>-       write_lock_bh(&ipv6_sk_mc_lock);
>        for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = 
>&mc_lst->next) {
>                if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
>                    ipv6_addr_equal(&mc_lst->addr, addr)) {
>                        struct net_device *dev;
> 
>                        *lnk = mc_lst->next;
>-                       write_unlock_bh(&ipv6_sk_mc_lock);
> 
>                        if ((dev = dev_get_by_index(mc_lst->ifindex)) != 
>NULL) {
>                                struct inet6_dev *idev = in6_dev_get(dev);
>@@ -269,11 +278,21 @@ int ipv6_sock_mc_drop(struct sock *sk, i
>                        return 0;
>                }
>        }
>-       write_unlock_bh(&ipv6_sk_mc_lock);
> 
>        return -ENOENT;
> }
> 
>+int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr 
>*addr)
>+{
>+       int rv;
>+
>+       write_lock_bh(&ipv6_sk_mc_lock);
>+       rv = __ipv6_sock_mc_drop(sk, ifindex, addr);
>+       write_unlock_bh(&ipv6_sk_mc_lock);
>+       return rv;
>+}
>+
>+
> static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int 
>ifindex)
> {
>        struct net_device *dev = NULL;
>@@ -368,6 +387,7 @@ int ip6_mc_source(int add, int omode, st
> 
>        err = -EADDRNOTAVAIL;
> 
>+       write_lock_bh(&ipv6_sk_mc_lock);
>        for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
>                if (pgsr->gsr_interface && pmc->ifindex != 
>pgsr->gsr_interface)
>                        continue;
>@@ -401,6 +421,13 @@ int ip6_mc_source(int add, int omode, st
>                if (rv)         /* source not found */
>                        goto done;
> 
>+               /* special case - (INCLUDE, empty) == LEAVE_GROUP */
>+               if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
>+                       err = __ipv6_sock_mc_drop(sk, pgsr->gsr_interface,
>+                               group);
>+                       goto done;
>+               }
>+
>                /* update the interface filter */
>                ip6_mc_del_src(idev, group, omode, 1, source, 1);
> 
>@@ -453,6 +480,7 @@ int ip6_mc_source(int add, int omode, st
>        /* update the interface list */
>        ip6_mc_add_src(idev, group, omode, 1, source, 1);
> done:
>+       write_unlock_bh(&ipv6_sk_mc_lock);
>        read_unlock_bh(&idev->lock);
>        in6_dev_put(idev);
>        dev_put(dev);
>
>
>  
>