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 {