mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net/multicast: should not send source list records when have filter mode change
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									013ad40d37
								
							
						
					
					
						commit
						a052517a8f
					
				
					 2 changed files with 20 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue