Module Name:    src
Committed By:   knakahara
Date:           Fri Nov 25 05:03:12 UTC 2016

Modified Files:
        src/sys/net: if_spppsubr.c if_spppvar.h

Log Message:
make workqueue sppp_{set,clear}_ip_addrs to be able to call pserialize_perform.


To generate a diff of this commit:
cvs rdiff -u -r1.158 -r1.159 src/sys/net/if_spppsubr.c
cvs rdiff -u -r1.17 -r1.18 src/sys/net/if_spppvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if_spppsubr.c
diff -u src/sys/net/if_spppsubr.c:1.158 src/sys/net/if_spppsubr.c:1.159
--- src/sys/net/if_spppsubr.c:1.158	Fri Nov 25 05:00:29 2016
+++ src/sys/net/if_spppsubr.c	Fri Nov 25 05:03:12 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_spppsubr.c,v 1.158 2016/11/25 05:00:29 knakahara Exp $	 */
+/*	$NetBSD: if_spppsubr.c,v 1.159 2016/11/25 05:03:12 knakahara Exp $	 */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.158 2016/11/25 05:00:29 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.159 2016/11/25 05:03:12 knakahara Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -66,6 +66,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_spppsubr.
 #include <sys/kauth.h>
 #include <sys/cprng.h>
 #include <sys/module.h>
+#include <sys/workqueue.h>
+#include <sys/atomic.h>
 
 #include <net/if.h>
 #include <net/netisr.h>
@@ -365,7 +367,9 @@ static int sppp_params(struct sppp *sp, 
 #ifdef INET
 static void sppp_get_ip_addrs(struct sppp *sp, uint32_t *src, uint32_t *dst,
 			      uint32_t *srcmask);
+static void sppp_set_ip_addrs_work(struct work *wk, void *arg);
 static void sppp_set_ip_addrs(struct sppp *sp);
+static void sppp_clear_ip_addrs_work(struct work *wk, void *arg);
 static void sppp_clear_ip_addrs(struct sppp *sp);
 #endif
 static void sppp_keepalive(void *dummy);
@@ -948,6 +952,9 @@ sppp_detach(struct ifnet *ifp)
 			break;
 		}
 
+	workqueue_destroy(sp->ipcp.set_addrs_wq);
+	workqueue_destroy(sp->ipcp.clear_addrs_wq);
+
 	/* Stop keepalive handler. */
 	if (! spppq) {
 		callout_stop(&keepalive_ch);
@@ -2725,6 +2732,8 @@ sppp_lcp_check_and_close(struct sppp *sp
 static void
 sppp_ipcp_init(struct sppp *sp)
 {
+	int error;
+
 	sp->ipcp.opts = 0;
 	sp->ipcp.flags = 0;
 	sp->state[IDX_IPCP] = STATE_INITIAL;
@@ -2732,6 +2741,20 @@ sppp_ipcp_init(struct sppp *sp)
 	sp->pp_seq[IDX_IPCP] = 0;
 	sp->pp_rseq[IDX_IPCP] = 0;
 	callout_init(&sp->ch[IDX_IPCP], 0);
+
+	error = workqueue_create(&sp->ipcp.set_addrs_wq, "ipcp_set_addrs",
+	    sppp_set_ip_addrs_work, sp, PRI_SOFTNET, IPL_NET, 0);
+	if (error)
+		panic("%s: set_addrs workqueue_create failed (%d)\n",
+		    __func__, error);
+	error = workqueue_create(&sp->ipcp.clear_addrs_wq, "ipcp_clear_addrs",
+	    sppp_clear_ip_addrs_work, sp, PRI_SOFTNET, IPL_NET, 0);
+	if (error)
+		panic("%s: clear_addrs workqueue_create failed (%d)\n",
+		    __func__, error);
+
+	sp->ipcp.set_addrs_enqueued = 0;
+	sp->ipcp.clear_addrs_enqueued = 0;
 }
 
 static void
@@ -2797,7 +2820,6 @@ sppp_ipcp_open(struct sppp *sp)
 static void
 sppp_ipcp_close(struct sppp *sp)
 {
-	STDDCL;
 
 	sppp_close_event(&ipcp, sp);
 #ifdef INET
@@ -2807,15 +2829,6 @@ sppp_ipcp_close(struct sppp *sp)
 		 */
 		sppp_clear_ip_addrs(sp);
 #endif
-
-	if (sp->pp_saved_mtu > 0) {
-		ifp->if_mtu = sp->pp_saved_mtu;
-		sp->pp_saved_mtu = 0;
-		if (debug)
-			log(LOG_DEBUG,
-			    "%s: resetting MTU to %" PRIu64 " bytes\n",
-			    ifp->if_xname, ifp->if_mtu);
-	}
 }
 
 static void
@@ -3163,21 +3176,7 @@ sppp_ipcp_tlu(struct sppp *sp)
 {
 #ifdef INET
 	/* we are up. Set addresses and notify anyone interested */
-	STDDCL;
-
 	sppp_set_ip_addrs(sp);
-
-	if (ifp->if_mtu > sp->lcp.their_mru) {
-		sp->pp_saved_mtu = ifp->if_mtu;
-		ifp->if_mtu = sp->lcp.their_mru;
-		if (debug)
-			log(LOG_DEBUG,
-			    "%s: setting MTU to %" PRIu64 " bytes\n",
-			    ifp->if_xname, ifp->if_mtu);
-	}
-
-	if (sp->pp_con)
-		sp->pp_con(sp);
 #endif
 }
 
@@ -4874,18 +4873,23 @@ sppp_get_ip_addrs(struct sppp *sp, uint3
  * If an address is 0, leave it the way it is.
  */
 static void
-sppp_set_ip_addrs(struct sppp *sp)
+sppp_set_ip_addrs_work(struct work *wk, void *arg)
 {
+	struct sppp *sp = arg;
 	STDDCL;
 	struct ifaddr *ifa;
 	struct sockaddr_in *si, *dest;
 	uint32_t myaddr = 0, hisaddr = 0;
+	int s;
+
+	atomic_swap_uint(&sp->ipcp.set_addrs_enqueued, 0);
 
 	/*
 	 * Pick the first AF_INET address from the list,
 	 * aliases don't make any sense on a p2p link anyway.
 	 */
 	si = dest = NULL;
+	s = pserialize_read_enter();
 	IFADDR_READER_FOREACH(ifa, ifp) {
 		if (ifa->ifa_addr->sa_family == AF_INET) {
 			si = (struct sockaddr_in *)ifa->ifa_addr;
@@ -4893,6 +4897,7 @@ sppp_set_ip_addrs(struct sppp *sp)
 			break;
 		}
 	}
+	pserialize_read_exit(s);
 
 	if ((sp->ipcp.flags & IPCP_MYADDR_DYN) && (sp->ipcp.flags & IPCP_MYADDR_SEEN))
 		myaddr = sp->ipcp.req_myaddr;
@@ -4941,23 +4946,50 @@ sppp_set_ip_addrs(struct sppp *sp)
 			    (struct mbuf **)SIOCAIFADDR, ifp, PFIL_IFADDR);
 		}
 	}
+
+	if (ifp->if_mtu > sp->lcp.their_mru) {
+		sp->pp_saved_mtu = ifp->if_mtu;
+		ifp->if_mtu = sp->lcp.their_mru;
+		if (debug)
+			log(LOG_DEBUG,
+			    "%s: setting MTU to %" PRIu64 " bytes\n",
+			    ifp->if_xname, ifp->if_mtu);
+	}
+
+	if (sp->pp_con)
+		sp->pp_con(sp);
+}
+
+static void
+sppp_set_ip_addrs(struct sppp *sp)
+{
+
+	if (atomic_swap_uint(&sp->ipcp.set_addrs_enqueued, 1) == 1)
+		return;
+
+	workqueue_enqueue(sp->ipcp.set_addrs_wq, &sp->ipcp.set_addrs_wk, NULL);
 }
 
 /*
  * Clear IP addresses.  Must be called at splnet.
  */
 static void
-sppp_clear_ip_addrs(struct sppp *sp)
+sppp_clear_ip_addrs_work(struct work *wk, void *arg)
 {
+	struct sppp *sp = arg;
 	STDDCL;
 	struct ifaddr *ifa;
 	struct sockaddr_in *si, *dest;
+	int s;
+
+	atomic_swap_uint(&sp->ipcp.clear_addrs_enqueued, 0);
 
 	/*
 	 * Pick the first AF_INET address from the list,
 	 * aliases don't make any sense on a p2p link anyway.
 	 */
 	si = dest = NULL;
+	s = pserialize_read_enter();
 	IFADDR_READER_FOREACH(ifa, ifp) {
 		if (ifa->ifa_addr->sa_family == AF_INET) {
 			si = (struct sockaddr_in *)ifa->ifa_addr;
@@ -4965,6 +4997,7 @@ sppp_clear_ip_addrs(struct sppp *sp)
 			break;
 		}
 	}
+	pserialize_read_exit(s);
 
 	if (si != NULL) {
 		struct sockaddr_in new_sin = *si;
@@ -5000,6 +5033,25 @@ sppp_clear_ip_addrs(struct sppp *sp)
 			    (struct mbuf **)SIOCAIFADDR, ifp, PFIL_IFADDR);
 		}
 	}
+
+	if (sp->pp_saved_mtu > 0) {
+		ifp->if_mtu = sp->pp_saved_mtu;
+		sp->pp_saved_mtu = 0;
+		if (debug)
+			log(LOG_DEBUG,
+			    "%s: resetting MTU to %" PRIu64 " bytes\n",
+			    ifp->if_xname, ifp->if_mtu);
+	}
+}
+
+static void
+sppp_clear_ip_addrs(struct sppp *sp)
+{
+
+	if (atomic_swap_uint(&sp->ipcp.clear_addrs_enqueued, 1) == 1)
+		return;
+
+	workqueue_enqueue(sp->ipcp.clear_addrs_wq, &sp->ipcp.clear_addrs_wk, NULL);
 }
 #endif
 

Index: src/sys/net/if_spppvar.h
diff -u src/sys/net/if_spppvar.h:1.17 src/sys/net/if_spppvar.h:1.18
--- src/sys/net/if_spppvar.h:1.17	Wed Sep 14 10:58:38 2016
+++ src/sys/net/if_spppvar.h	Fri Nov 25 05:03:12 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_spppvar.h,v 1.17 2016/09/14 10:58:38 roy Exp $	*/
+/*	$NetBSD: if_spppvar.h,v 1.18 2016/11/25 05:03:12 knakahara Exp $	*/
 
 #ifndef _NET_IF_SPPPVAR_H_
 #define _NET_IF_SPPPVAR_H_
@@ -26,6 +26,8 @@
  * From: Id: if_sppp.h,v 1.7 1998/12/01 20:20:19 hm Exp
  */
 
+#include <sys/workqueue.h>
+
 #include <net/if_media.h>
 
 #define IDX_LCP 0		/* idx into state table */
@@ -61,6 +63,14 @@ struct sipcp {
 	uint32_t saved_hisaddr;/* if hisaddr (IPv4) is dynamic, save original one here, in network byte order */
 	uint32_t req_hisaddr;	/* remote address requested */
 	uint32_t req_myaddr;	/* local address requested */
+
+	struct workqueue *set_addrs_wq;
+	struct work set_addrs_wk;
+	u_int set_addrs_enqueued;
+
+	struct workqueue *clear_addrs_wq;
+	struct work clear_addrs_wk;
+	u_int clear_addrs_enqueued;
 };
 
 struct sauth {

Reply via email to