netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next] net/multicast: should not send source list records when have filter mode change
@ 2016-08-02 10:02 Hangbin Liu
  2016-08-02 10:10 ` Hangbin Liu
  0 siblings, 1 reply; 2+ messages in thread
From: Hangbin Liu @ 2016-08-02 10:02 UTC (permalink / raw)
  To: netdev; +Cc: Hannes Frederic Sowa, David Miller, Hangbin Liu

Based on RFC3376 5.1 and RFC3810 6.1

   If the per-interface listening change that triggers the new report is
   a filter mode change, then the next [Robustness Variable] State
   Change Reports will include a Filter Mode Change Record.  This
   applies even if any number of source list changes occur in that
   period.

   Old State         New State         State Change Record Sent
   ---------         ---------         ------------------------
   INCLUDE (A)       EXCLUDE (B)       TO_EX (B)
   EXCLUDE (A)       INCLUDE (B)       TO_IN (B)

So we should not send source-list change if there is a filter-mode change.

Here are two scenarios:
1. Group deleted and filter mode is EXCLUDE, which means we need send a
   TO_IN { }.
2. Not group deleted, but has pcm->crcount, which means we need send a
   normal filter-mode-change.

At the same time, if the type is ALLOW or BLOCK, and have psf->sf_crcount,
we stop add records and decrease sf_crcount directly

Reference: https://www.ietf.org/mail-archive/web/magma/current/msg01274.html

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 net/ipv4/igmp.c  | 10 ++++++++++
 net/ipv6/mcast.c | 10 ++++++++++
 2 files changed, 20 insertions(+)

diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 9b4ca87..606cc3e 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -472,6 +472,15 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
 			continue;
 		}
 
+		/* Based on RFC3376 5.1. Should not send source-list change
+		 * records when there is a filter mode change.
+		 */
+		if (((gdeleted && pmc->sfmode == MCAST_EXCLUDE) ||
+		     (!gdeleted && pmc->crcount)) &&
+		    (type == IGMPV3_ALLOW_NEW_SOURCES ||
+		     type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount)
+			goto decrease_sf_crcount;
+
 		/* clear marks on query responses */
 		if (isquery)
 			psf->sf_gsresp = 0;
@@ -499,6 +508,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
 		scount++; stotal++;
 		if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
 		     type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
+decrease_sf_crcount:
 			psf->sf_crcount--;
 			if ((sdeleted || gdeleted) && psf->sf_crcount == 0) {
 				if (psf_prev)
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index d64ee7e..75c1fc5 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1739,6 +1739,15 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
 			continue;
 		}
 
+		/* Based on RFC3810 6.1. Should not send source-list change
+		 * records when there is a filter mode change.
+		 */
+		if (((gdeleted && pmc->mca_sfmode == MCAST_EXCLUDE) ||
+		     (!gdeleted && pmc->mca_crcount)) &&
+		    (type == MLD2_ALLOW_NEW_SOURCES ||
+		     type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount)
+			goto decrease_sf_crcount;
+
 		/* clear marks on query responses */
 		if (isquery)
 			psf->sf_gsresp = 0;
@@ -1766,6 +1775,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
 		scount++; stotal++;
 		if ((type == MLD2_ALLOW_NEW_SOURCES ||
 		     type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
+decrease_sf_crcount:
 			psf->sf_crcount--;
 			if ((sdeleted || gdeleted) && psf->sf_crcount == 0) {
 				if (psf_prev)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH net-next] net/multicast: should not send source list records when have filter mode change
  2016-08-02 10:02 [PATCH net-next] net/multicast: should not send source list records when have filter mode change Hangbin Liu
@ 2016-08-02 10:10 ` Hangbin Liu
  0 siblings, 0 replies; 2+ messages in thread
From: Hangbin Liu @ 2016-08-02 10:10 UTC (permalink / raw)
  To: network dev; +Cc: Hannes Frederic Sowa, David Miller, Hangbin Liu

Hi,

Here are some tests with this patch. It's hard to test all scenarios. So I just
did a part. And all looks good so far.

Please tell me if there is anything unclear.

Thanks
Hangbin


Group: 239.1.1.1
A: 192.168.1.1
B: 192.168.1.2
C: 192.168.1.3
------------------------------------------------------------------------
# Section 1: diff before/after patch
## Test 1: EX{A} -> IN{A}

Before patch:
15:24:00.451637 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 56, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 2 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.1 }] [gaddr 239.1.1.1 to_in {
192.168.1.1 }]
After patch:
15:22:50.398652 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 44, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]

## Test 2: IN{A} -> EX{A}

Before patch:
15:24:10.239734 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 56, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 2 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.1 }] [gaddr 239.1.1.1 to_ex {
192.168.1.1 }]
After patch:
15:22:59.754639 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 44, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { 192.168.1.1 }]


------------------------------------------------------------------------
# Section 2: Functional test with this patch
## Test 1: IN{ } ->
Case-1 IN{ } -> IN{ }
    Do nothing
Case-2 IN{ } -> IN{A}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]
Case-3 IN{ } -> EX{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { }]
Case-4 IN{} -> EX{A}
    Not supported

## Test 2: EX{ } ->
Case-1 EX{ } -> EX{ }
    Do nothing
Case-2 EX{ } -> EX{A}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.1 }]
Case-3 EX{ } -> IN{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { }]
Case-4 EX{ } -> IN{A}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]

## Test 3: IN{A} ->
Case-1 IN{A} -> IN{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.1 }]
Case-2 IN{A} -> IN{A}
    Do nothing
Case-3 IN{A} -> IN{B}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 2 group record(s)
[gaddr 239.1.1.1 allow { 192.168.1.2 }] [gaddr 239.1.1.1 block {
192.168.1.1 }]
Case-4 IN{A} -> EX{ }
Case-5 IN{A} -> EX{A}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { 192.168.1.1 }]
Case-6 IN{A} -> EX{B}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { 192.168.1.2 }]

## Test 4: EX{A} ->
Case-1 EX{A} -> EX{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 allow { 192.168.1.1 }]
Case-2 EX{A} -> EX{A}
    Do nothing
Case-3 EX{A} -> EX{B}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 2 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.2 }] [gaddr 239.1.1.1 allow {
192.168.1.1 }]
Case-4 EX{A} -> IN{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { }]
Case-5 EX{A} -> IN{A}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]
Case-6 EX{A} -> IN{B}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.2 }]


------------------------------------------------------------------------
# Section 3: New change record during change record.
Case-1:
IN{A} -> IN{AB} -> sleep 1 -> IN{AC}
EX{AB} -> EX{AC} -> sleep 1 -> IN{}

23:32:14.602458 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 40, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { }]
23:32:21.230500 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 40, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { }]
23:32:24.610438 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 44, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]
23:32:25.978493 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 44, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]
23:32:34.621459 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 44, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 allow { 192.168.1.2 }]
23:32:35.630439 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 56, options (RA))
    ^^ we can see only send 1 allow{B} record, and then start send
allow{C}, block{b}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 2 group record(s)
[gaddr 239.1.1.1 allow { 192.168.1.3 }] [gaddr 239.1.1.1 block {
192.168.1.2 }]
23:32:39.566551 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 56, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 2 group record(s)
[gaddr 239.1.1.1 allow { 192.168.1.3 }] [gaddr 239.1.1.1 block {
192.168.1.2 }]
23:32:50.641450 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { 192.168.1.1 192.168.1.2 }]
23:32:51.650439 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { 192.168.1.1 192.168.1.3 }]
23:32:51.850474 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 56, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 2 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.3 }] [gaddr 239.1.1.1 allow {
192.168.1.2 }]
    ^^ Here EX{AB} -> EX{AC}, we can see the BLOCK{C}, ALLOW{B} only
send once and start TO_IN{ }
23:33:06.663455 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 40, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { }]
23:33:08.086493 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 40, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { }]

Case-2: IN{A} -> IN{ABC} -> sleep 1 -> EX{AB} -> sleep 1 -> IN{BC}

02:18:27.216445 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 40, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { }]
02:18:28.354479 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 40, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { }]
02:18:37.226445 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 44, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]
02:18:39.510496 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 44, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 }]
02:18:47.236445 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 allow { 192.168.1.2 192.168.1.3 }]
    ^^ ALLOW{BC} once and start TO_EX{AB}
02:18:48.246448 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { 192.168.1.1 192.168.1.2 }]
    ^^ TO_EX{AB} once and start TO_IN{BC}
02:18:49.256450 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.2 192.168.1.3 }]
02:18:58.558556 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.2 192.168.1.3 }]
02:19:04.268441 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.3 192.168.1.2 }]
02:19:12.510502 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto
IGMP (2), length 48, options (RA))
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.3 192.168.1.2 }]


------------------------------------------------------------------------
# Section 3: Multi sockets
Case-1:

S1 EX{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { }]
S1 EX{A}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.1 }]
S2 EX{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 allow { 192.168.1.1 }]
S2 IN{B}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.1 }]
S1 IN{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.2 }]
S2 IN{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.2 }]

Case-2:

S1 EX{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_ex { }]
S2 EX{ }
    Do Nothing
S1 IN{A}
    Do Nothing
S2 IN{A}
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 to_in { 192.168.1.1 192.168.1.2 }]
S1 IN{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.1 }]
S2 IN{ }
    192.168.1.100 > 224.0.0.22: igmp v3 report, 1 group record(s)
[gaddr 239.1.1.1 block { 192.168.1.2 }]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2016-08-02 14:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-02 10:02 [PATCH net-next] net/multicast: should not send source list records when have filter mode change Hangbin Liu
2016-08-02 10:10 ` Hangbin Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).