Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Mar 2012 09:30:12 GMT
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        freebsd-net@FreeBSD.org
Subject:   kern/165863
Message-ID:  <201203090930.q299UCPX057950@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/165863; it has been noted by GNATS.

From: Gleb Smirnoff <glebius@FreeBSD.org>
To: Eric van Gyzen <eric_van_gyzen@dell.com>,
        Eric van Gyzen <eric@vangyzen.net>, emaste@FreeBSD.org
Cc: bug-followup@FreeBSD.org
Subject: kern/165863
Date: Fri, 9 Mar 2012 13:20:56 +0400

 --BXVAT5kNtrzKuDFl
 Content-Type: text/plain; charset=koi8-r
 Content-Disposition: inline
 
   Hello, Eric and Ed.
 
   Can you look at this patch? I decided to utilize newer callout API,
 that allows to delegate lock retrieval to the callout subsystem, and
 this makes things simplier. Hope that should work.
 
   Patch is against head.
 
   Eric, can you please send me your test programs, that you use to
 reproduce the bug?
 
 -- 
 Totus tuus, Glebius.
 
 --BXVAT5kNtrzKuDFl
 Content-Type: text/x-diff; charset=koi8-r
 Content-Disposition: attachment; filename="kern165863.diff"
 
 Index: in.c
 ===================================================================
 --- in.c	(revision 232689)
 +++ in.c	(working copy)
 @@ -1279,11 +1279,12 @@
  {
  	struct in_llentry *lle;
  
 -	lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_DONTWAIT | M_ZERO);
 +	lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
  	if (lle == NULL)		/* NB: caller generates msg */
  		return NULL;
  
 -	callout_init(&lle->base.la_timer, CALLOUT_MPSAFE);
 +	LLE_LOCK_INIT(&lle->base);
 +	callout_init_rw(&lle->base.la_timer, &lle->base.lle_lock, 0);
  	/*
  	 * For IPv4 this will trigger "arpresolve" to generate
  	 * an ARP request.
 @@ -1292,46 +1293,44 @@
  	lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
  	lle->base.lle_refcnt = 1;
  	lle->base.lle_free = in_lltable_free;
 -	LLE_LOCK_INIT(&lle->base);
 -	return &lle->base;
 +
 +	return (&lle->base);
  }
  
  #define IN_ARE_MASKED_ADDR_EQUAL(d, a, m)	(			\
  	    (((ntohl((d)->sin_addr.s_addr) ^ (a)->sin_addr.s_addr) & (m)->sin_addr.s_addr)) == 0 )
  
  static void
 -in_lltable_prefix_free(struct lltable *llt, 
 -		       const struct sockaddr *prefix,
 -		       const struct sockaddr *mask,
 -		       u_int flags)
 +in_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
 +    const struct sockaddr *mask, u_int flags)
  {
  	const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix;
  	const struct sockaddr_in *msk = (const struct sockaddr_in *)mask;
  	struct llentry *lle, *next;
 -	register int i;
 +	int i;
  	size_t pkts_dropped;
  
 -	for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
 +	IF_AFDATA_WLOCK(llt->llt_ifp);
 +	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
  		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
  
  		        /* 
  			 * (flags & LLE_STATIC) means deleting all entries
 -			 * including static ARP entries
 +			 * including static ARP entries.
  			 */
 -			if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle), 
 -						     pfx, msk) &&
 -			    ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC))) {
 -				int canceled;
 +			if (IN_ARE_MASKED_ADDR_EQUAL(satosin(L3_ADDR(lle)), 
 +			    pfx, msk) && ((flags & LLE_STATIC) ||
 +			    !(lle->la_flags & LLE_STATIC))) {
  
 -				canceled = callout_drain(&lle->la_timer);
  				LLE_WLOCK(lle);
 -				if (canceled)
 +				if (callout_stop(&lle->la_timer))
  					LLE_REMREF(lle);
  				pkts_dropped = llentry_free(lle);
  				ARPSTAT_ADD(dropped, pkts_dropped);
  			}
  		}
  	}
 +	IF_AFDATA_WUNLOCK(llt->llt_ifp);
  }
  
  
 Index: if_ether.c
 ===================================================================
 --- if_ether.c	(revision 232689)
 +++ if_ether.c	(working copy)
 @@ -163,38 +163,23 @@
  static void
  arptimer(void *arg)
  {
 +	struct llentry *lle = (struct llentry *)arg;
  	struct ifnet *ifp;
 -	struct llentry   *lle;
 -	int pkts_dropped;
 +	size_t pkts_dropped;
  
 -	KASSERT(arg != NULL, ("%s: arg NULL", __func__));
 -	lle = (struct llentry *)arg;
 +	LLE_WLOCK_ASSERT(lle);
 +
 +	if (lle->la_flags & LLE_STATIC)
 +		return;
 +
  	ifp = lle->lle_tbl->llt_ifp;
  	CURVNET_SET(ifp->if_vnet);
 -	IF_AFDATA_LOCK(ifp);
 -	LLE_WLOCK(lle);
 -	if (lle->la_flags & LLE_STATIC)
 -		LLE_WUNLOCK(lle);
 -	else {
 -		if (!callout_pending(&lle->la_timer) &&
 -		    callout_active(&lle->la_timer)) {
 -			callout_stop(&lle->la_timer);
 -			LLE_REMREF(lle);
 -			pkts_dropped = llentry_free(lle);
 -			ARPSTAT_ADD(dropped, pkts_dropped);
 -			ARPSTAT_INC(timeouts);
 -		} else {
 -#ifdef DIAGNOSTIC
 -			struct sockaddr *l3addr = L3_ADDR(lle);
 -			log(LOG_INFO, 
 -			    "arptimer issue: %p, IPv4 address: \"%s\"\n", lle,
 -			    inet_ntoa(
 -			        ((const struct sockaddr_in *)l3addr)->sin_addr));
 -#endif
 -			LLE_WUNLOCK(lle);
 -		}
 -	}
 -	IF_AFDATA_UNLOCK(ifp);
 +
 +	LLE_REMREF(lle);
 +	pkts_dropped = llentry_free(lle);
 +	ARPSTAT_ADD(dropped, pkts_dropped);
 +	ARPSTAT_INC(timeouts);
 +
  	CURVNET_RESTORE();
  }
  
 
 --BXVAT5kNtrzKuDFl--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203090930.q299UCPX057950>