From: Yan Zheng <yanzheng@21cn.com>
To: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, David Stevens <dlstevens@us.ibm.com>
Subject: Re: [PATCH][MCAST]Two fix for implementation of MLDv2 .
Date: Wed, 02 Nov 2005 22:23:34 +0800 [thread overview]
Message-ID: <4368CBE6.9040702@21cn.com> (raw)
In-Reply-To: <7e77d27c0511020538o4b1f3244l@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2382 bytes --]
Hi.
Here is my another patch. It makes a node send state change report properly when a multicast address's soure filter mode change is cause by forwarding state change and etc.
Regards.
Signed-off-by: Yan Zheng <yanzheng@21cn.com>
Index:net/ipv6/mcast.c
===========================================================
--- linux-2.6.14/net/ipv6/mcast.c 2005-10-30 23:09:33.000000000 +0800
+++ /tmp/ipv6/mcast.c 2005-11-02 22:04:32.000000000 +0800
@@ -128,7 +128,8 @@ static DEFINE_RWLOCK(ipv6_sk_mc_lock);
static struct socket *igmp6_socket;
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+static int ipv6_dev_mc_dec_intern(struct inet6_dev *idev,
+ struct in6_addr *addr, int delta);
static void igmp6_join_group(struct ifmcaddr6 *ma);
static void igmp6_leave_group(struct ifmcaddr6 *ma);
@@ -270,7 +271,7 @@ int ipv6_sock_mc_drop(struct sock *sk, i
if (idev) {
(void) ip6_mc_leave_src(sk,mc_lst,idev);
- __ipv6_dev_mc_dec(idev, &mc_lst->addr);
+ ipv6_dev_mc_dec_intern(idev,&mc_lst->addr,1);
in6_dev_put(idev);
}
dev_put(dev);
@@ -336,7 +337,7 @@ void ipv6_sock_mc_close(struct sock *sk)
if (idev) {
(void) ip6_mc_leave_src(sk, mc_lst, idev);
- __ipv6_dev_mc_dec(idev, &mc_lst->addr);
+ ipv6_dev_mc_dec_intern(idev, &mc_lst->addr, 1);
in6_dev_put(idev);
}
dev_put(dev);
@@ -907,10 +908,9 @@ int ipv6_dev_mc_inc(struct net_device *d
return 0;
}
-/*
- * device multicast group del
- */
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+
+static int ipv6_dev_mc_dec_intern(struct inet6_dev *idev,
+ struct in6_addr *addr, int delta)
{
struct ifmcaddr6 *ma, **map;
@@ -920,20 +920,27 @@ int __ipv6_dev_mc_dec(struct inet6_dev *
if (--ma->mca_users == 0) {
*map = ma->next;
write_unlock_bh(&idev->lock);
-
igmp6_group_dropped(ma);
-
ma_put(ma);
return 0;
}
write_unlock_bh(&idev->lock);
+ if (!delta && ip6_mc_del_src(idev, addr,
+ MCAST_EXCLUDE, 0, NULL, 0))
+ return -EINVAL; // bug
return 0;
}
}
write_unlock_bh(&idev->lock);
-
return -ENOENT;
}
+/*
+ * device multicast group del
+ */
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+{
+ return ipv6_dev_mc_dec_intern(idev, addr, 0);
+}
int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
{
[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 5996 bytes --]
--- linux-2.6.14/net/ipv6/mcast.c 2005-10-30 23:09:33.000000000 +0800
+++ linux/net/ipv6/mcast.c 2005-11-02 21:25:27.000000000 +0800
@@ -128,7 +128,8 @@ static DEFINE_RWLOCK(ipv6_sk_mc_lock);
static struct socket *igmp6_socket;
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+static int ipv6_dev_mc_dec_intern(struct inet6_dev *idev,
+ struct in6_addr *addr, int delta);
static void igmp6_join_group(struct ifmcaddr6 *ma);
static void igmp6_leave_group(struct ifmcaddr6 *ma);
@@ -164,7 +165,7 @@ static int ip6_mc_leave_src(struct sock
#define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
#define MLDV2_EXP(thresh, nbmant, nbexp, value) \
((value) < (thresh) ? (value) : \
- ((MLDV2_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \
+ ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \
(MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp))))
#define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
@@ -270,7 +271,7 @@ int ipv6_sock_mc_drop(struct sock *sk, i
if (idev) {
(void) ip6_mc_leave_src(sk,mc_lst,idev);
- __ipv6_dev_mc_dec(idev, &mc_lst->addr);
+ ipv6_dev_mc_dec_intern(idev,&mc_lst->addr,1);
in6_dev_put(idev);
}
dev_put(dev);
@@ -336,7 +337,7 @@ void ipv6_sock_mc_close(struct sock *sk)
if (idev) {
(void) ip6_mc_leave_src(sk, mc_lst, idev);
- __ipv6_dev_mc_dec(idev, &mc_lst->addr);
+ ipv6_dev_mc_dec_intern(idev, &mc_lst->addr, 1);
in6_dev_put(idev);
}
dev_put(dev);
@@ -545,8 +546,10 @@ int ip6_mc_msfilter(struct sock *sk, str
sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max));
goto done;
}
- } else
+ } else {
newpsl = NULL;
+ (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0);
+ }
psl = pmc->sflist;
if (psl) {
(void) ip6_mc_del_src(idev, group, pmc->sfmode,
@@ -907,10 +910,8 @@ int ipv6_dev_mc_inc(struct net_device *d
return 0;
}
-/*
- * device multicast group del
- */
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+static int ipv6_dev_mc_dec_intern(struct inet6_dev *idev,
+ struct in6_addr *addr, int delta)
{
struct ifmcaddr6 *ma, **map;
@@ -920,20 +921,27 @@ int __ipv6_dev_mc_dec(struct inet6_dev *
if (--ma->mca_users == 0) {
*map = ma->next;
write_unlock_bh(&idev->lock);
-
igmp6_group_dropped(ma);
-
ma_put(ma);
return 0;
}
write_unlock_bh(&idev->lock);
+ if (!delta && ip6_mc_del_src(idev, addr,
+ MCAST_EXCLUDE, 0, NULL, 0))
+ return -EINVAL; // bug
return 0;
}
}
write_unlock_bh(&idev->lock);
-
return -ENOENT;
}
+/*
+ * device multicast group del
+ */
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+{
+ return ipv6_dev_mc_dec_intern(idev, addr, 0);
+}
int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
{
@@ -1087,7 +1095,7 @@ static void mld_marksources(struct ifmca
int igmp6_event_query(struct sk_buff *skb)
{
- struct mld2_query *mlh2 = (struct mld2_query *) skb->h.raw;
+ struct mld2_query *mlh2 = NULL;
struct ifmcaddr6 *ma;
struct in6_addr *group;
unsigned long max_delay;
@@ -1140,6 +1148,21 @@ int igmp6_event_query(struct sk_buff *sk
/* clear deleted report items */
mld_clear_delrec(idev);
} else if (len >= 28) {
+ int srcs_offset = sizeof(struct mld2_query) -
+ sizeof(struct icmp6hdr);
+ if (!pskb_may_pull(skb, srcs_offset)) {
+ in6_dev_put(idev);
+ return -EINVAL;
+ }
+ mlh2 = (struct mld2_query *) skb->h.raw;
+ if (mlh2->nsrcs != 0) {
+ if (!pskb_may_pull(skb, srcs_offset +
+ mlh2->nsrcs * sizeof(struct in6_addr))) {
+ in6_dev_put(idev);
+ return -EINVAL;
+ }
+ mlh2 = (struct mld2_query *) skb->h.raw;
+ }
max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000;
if (!max_delay)
max_delay = 1;
@@ -1256,10 +1279,13 @@ static int is_in(struct ifmcaddr6 *pmc,
{
switch (type) {
case MLD2_MODE_IS_INCLUDE:
- case MLD2_MODE_IS_EXCLUDE:
if (gdeleted || sdeleted)
return 0;
return !((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp);
+ case MLD2_MODE_IS_EXCLUDE:
+ if (gdeleted || sdeleted)
+ return 0;
+ return 1;
case MLD2_CHANGE_TO_INCLUDE:
if (gdeleted || sdeleted)
return 0;
@@ -1428,13 +1454,15 @@ static struct sk_buff *add_grec(struct s
struct mld2_report *pmr;
struct mld2_grec *pgr = NULL;
struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list;
- int scount, first, isquery, truncate;
+ int scount, first, isquery, ischange, truncate;
if (pmc->mca_flags & MAF_NOREPORT)
return skb;
isquery = type == MLD2_MODE_IS_INCLUDE ||
type == MLD2_MODE_IS_EXCLUDE;
+ ischange = type == MLD2_CHANGE_TO_INCLUDE ||
+ type == MLD2_CHANGE_TO_EXCLUDE;
truncate = type == MLD2_MODE_IS_EXCLUDE ||
type == MLD2_CHANGE_TO_EXCLUDE;
@@ -1444,7 +1472,7 @@ static struct sk_buff *add_grec(struct s
if (type == MLD2_ALLOW_NEW_SOURCES ||
type == MLD2_BLOCK_OLD_SOURCES)
return skb;
- if (pmc->mca_crcount || isquery) {
+ if (ischange || isquery) {
/* make sure we have room for group header and at
* least one source.
*/
@@ -1460,9 +1488,12 @@ static struct sk_buff *add_grec(struct s
pmr = skb ? (struct mld2_report *)skb->h.raw : NULL;
/* EX and TO_EX get a fresh packet, if needed */
- if (truncate) {
- if (pmr && pmr->ngrec &&
- AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
+ if (truncate || ischange) {
+ int min_len;
+ min_len = truncate ? grec_size(pmc, type, gdeleted, sdeleted) :
+ (sizeof(struct mld2_grec) + sizeof(struct in6_addr));
+ if (((pmr && pmr->ngrec) || ischange) &&
+ AVAILABLE(skb) < min_len) {
if (skb)
mld_sendpack(skb);
skb = mld_newpack(dev, dev->mtu);
@@ -1471,6 +1502,10 @@ static struct sk_buff *add_grec(struct s
first = 1;
scount = 0;
psf_prev = NULL;
+ if (ischange) {
+ skb = add_grhead(skb, pmc, type, &pgr);
+ first = 0;
+ }
for (psf=*psf_list; psf; psf=psf_next) {
struct in6_addr *psrc;
next prev parent reply other threads:[~2005-11-02 14:22 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-11-02 8:29 [PATCH][MCAST]Two fix for implementation of MLDv2 Yan Zheng
[not found] ` <7e77d27c0511020538o4b1f3244l@mail.gmail.com>
2005-11-02 14:23 ` Yan Zheng [this message]
2005-11-03 1:22 ` Yan Zheng
2005-11-03 13:26 ` Yan Zheng
2005-11-04 4:30 ` David Stevens
2005-11-04 6:19 ` Yan Zheng
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=4368CBE6.9040702@21cn.com \
--to=yanzheng@21cn.com \
--cc=dlstevens@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.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.