Module Name: src
Committed By: yamaguchi
Date: Wed Nov 25 09:35:24 UTC 2020
Modified Files:
src/sys/net: if_spppsubr.c if_spppvar.h
Log Message:
Change a state of control protocol in thread context
reviewed by [email protected].
To generate a diff of this commit:
cvs rdiff -u -r1.197 -r1.198 src/sys/net/if_spppsubr.c
cvs rdiff -u -r1.26 -r1.27 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.197 src/sys/net/if_spppsubr.c:1.198
--- src/sys/net/if_spppsubr.c:1.197 Wed Nov 25 09:30:49 2020
+++ src/sys/net/if_spppsubr.c Wed Nov 25 09:35:23 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_spppsubr.c,v 1.197 2020/11/25 09:30:49 yamaguchi Exp $ */
+/* $NetBSD: if_spppsubr.c,v 1.198 2020/11/25 09:35:23 yamaguchi Exp $ */
/*
* Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.197 2020/11/25 09:30:49 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.198 2020/11/25 09:35:23 yamaguchi Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -237,11 +237,11 @@ struct cp {
#define CP_QUAL 0x08 /* this is a quality reporting protocol */
const char *name; /* name of this control protocol */
/* event handlers */
- void (*Up)(struct sppp *);
- void (*Down)(struct sppp *);
- void (*Open)(struct sppp *);
- void (*Close)(struct sppp *);
- void (*TO)(void *);
+ void (*Up)(struct sppp *, void *);
+ void (*Down)(struct sppp *, void *);
+ void (*Open)(struct sppp *, void *);
+ void (*Close)(struct sppp *, void *);
+ void (*TO)(struct sppp *, void *);
int (*RCR)(struct sppp *, struct lcp_header *, int);
void (*RCN_rej)(struct sppp *, struct lcp_header *, int);
void (*RCN_nak)(struct sppp *, struct lcp_header *, int);
@@ -271,6 +271,8 @@ static callout_t keepalive_ch;
SPPP_LOCK(_sp, RW_WRITER); \
}while (0)
#define SPPP_DOWNGRADE(_sp) rw_downgrade(&(_sp)->pp_lock)
+#define SPPP_WQ_SET(_wk, _func, _arg) \
+ sppp_wq_set((_wk), (_func), __UNCONST((_arg)))
#ifdef INET
#ifndef SPPPSUBR_MPSAFE
@@ -301,36 +303,51 @@ static int sppp_output(struct ifnet *, s
static void sppp_cisco_send(struct sppp *, int, int32_t, int32_t);
static void sppp_cisco_input(struct sppp *, struct mbuf *);
+static void sppp_cp_init(const struct cp *, struct sppp *);
+static void sppp_cp_fini(const struct cp *, struct sppp *);
+static void sppp_cp_input(const struct cp *, struct sppp *,
+ struct mbuf *);
static void sppp_cp_input(const struct cp *, struct sppp *,
struct mbuf *);
static void sppp_cp_send(struct sppp *, u_short, u_char,
u_char, u_short, void *);
/* static void sppp_cp_timeout(void *arg); */
static void sppp_cp_change_state(const struct cp *, struct sppp *, int);
+static struct workqueue *
+ sppp_wq_create(struct sppp *, const char *, pri_t, int, int);
+static void sppp_wq_destroy(struct sppp *, struct workqueue *);
+static void sppp_wq_set(struct sppp_work *,
+ void (*)(struct sppp *, void *), void *);
+static void sppp_wq_add(struct workqueue *, struct sppp_work *);
+static void sppp_wq_wait(struct workqueue *, struct sppp_work *);
+static void sppp_cp_to_lcp(void *);
+static void sppp_cp_to_ipcp(void *);
+static void sppp_cp_to_ipv6cp(void *);
static void sppp_auth_send(const struct cp *, struct sppp *,
unsigned int, unsigned int, ...);
-static void sppp_up_event(const struct cp *, struct sppp *);
-static void sppp_down_event(const struct cp *, struct sppp *);
-static void sppp_open_event(const struct cp *, struct sppp *);
-static void sppp_close_event(const struct cp *, struct sppp *);
-static void sppp_to_event(const struct cp *, struct sppp *);
-static void sppp_rcr_event(const struct cp *, struct sppp *);
-static void sppp_rca_event(const struct cp *, struct sppp *);
-static void sppp_rcn_event(const struct cp *, struct sppp *);
-static void sppp_rtr_event(const struct cp *, struct sppp *);
-static void sppp_rta_event(const struct cp *, struct sppp *);
-static void sppp_rxj_event(const struct cp *, struct sppp *);
+static void sppp_up_event(struct sppp *, void *);
+static void sppp_down_event(struct sppp *, void *);
+static void sppp_open_event(struct sppp *, void *);
+static void sppp_close_event(struct sppp *, void *);
+static void sppp_to_event(struct sppp *, void *);
+static void sppp_rcr_event(struct sppp *, void *);
+static void sppp_rca_event(struct sppp *, void *);
+static void sppp_rcn_event(struct sppp *, void *);
+static void sppp_rtr_event(struct sppp *, void *);
+static void sppp_rta_event(struct sppp *, void *);
+static void sppp_rxj_event(struct sppp *, void *);
+static void sppp_null_event(struct sppp *, void *);
static void sppp_null(struct sppp *);
static void sppp_sca_scn(const struct cp *, struct sppp *);
static void sppp_lcp_init(struct sppp *);
-static void sppp_lcp_up(struct sppp *);
-static void sppp_lcp_down(struct sppp *);
-static void sppp_lcp_open(struct sppp *);
-static void sppp_lcp_close(struct sppp *);
-static void sppp_lcp_TO(void *);
+static void sppp_lcp_up(struct sppp *, void *);
+static void sppp_lcp_down(struct sppp *, void *);
+static void sppp_lcp_open(struct sppp *, void *);
+static void sppp_lcp_close(struct sppp *, void *);
+static void sppp_lcp_TO(struct sppp *, void *);
static int sppp_lcp_RCR(struct sppp *, struct lcp_header *, int);
static void sppp_lcp_RCN_rej(struct sppp *, struct lcp_header *, int);
static void sppp_lcp_RCN_nak(struct sppp *, struct lcp_header *, int);
@@ -343,11 +360,11 @@ static void sppp_lcp_check_and_close(str
static int sppp_ncp_check(struct sppp *);
static void sppp_ipcp_init(struct sppp *);
-static void sppp_ipcp_up(struct sppp *);
-static void sppp_ipcp_down(struct sppp *);
-static void sppp_ipcp_open(struct sppp *);
-static void sppp_ipcp_close(struct sppp *);
-static void sppp_ipcp_TO(void *);
+static void sppp_ipcp_up(struct sppp *, void *);
+static void sppp_ipcp_down(struct sppp *, void *);
+static void sppp_ipcp_open(struct sppp *, void *);
+static void sppp_ipcp_close(struct sppp *, void *);
+static void sppp_ipcp_TO(struct sppp *, void *);
static int sppp_ipcp_RCR(struct sppp *, struct lcp_header *, int);
static void sppp_ipcp_RCN_rej(struct sppp *, struct lcp_header *, int);
static void sppp_ipcp_RCN_nak(struct sppp *, struct lcp_header *, int);
@@ -358,11 +375,11 @@ static void sppp_ipcp_tlf(struct sppp *)
static void sppp_ipcp_scr(struct sppp *);
static void sppp_ipv6cp_init(struct sppp *);
-static void sppp_ipv6cp_up(struct sppp *);
-static void sppp_ipv6cp_down(struct sppp *);
-static void sppp_ipv6cp_open(struct sppp *);
-static void sppp_ipv6cp_close(struct sppp *);
-static void sppp_ipv6cp_TO(void *);
+static void sppp_ipv6cp_up(struct sppp *, void *);
+static void sppp_ipv6cp_down(struct sppp *, void *);
+static void sppp_ipv6cp_open(struct sppp *, void *);
+static void sppp_ipv6cp_close(struct sppp *, void *);
+static void sppp_ipv6cp_TO(struct sppp *, void *);
static int sppp_ipv6cp_RCR(struct sppp *, struct lcp_header *, int);
static void sppp_ipv6cp_RCN_rej(struct sppp *, struct lcp_header *, int);
static void sppp_ipv6cp_RCN_nak(struct sppp *, struct lcp_header *, int);
@@ -374,8 +391,8 @@ static void sppp_ipv6cp_scr(struct sppp
static void sppp_pap_input(struct sppp *, struct mbuf *);
static void sppp_pap_init(struct sppp *);
-static void sppp_pap_open(struct sppp *);
-static void sppp_pap_close(struct sppp *);
+static void sppp_pap_open(struct sppp *, void *);
+static void sppp_pap_close(struct sppp *, void *);
static void sppp_pap_TO(void *);
static void sppp_pap_my_TO(void *);
static void sppp_pap_tlu(struct sppp *);
@@ -384,8 +401,8 @@ static void sppp_pap_scr(struct sppp *);
static void sppp_chap_input(struct sppp *, struct mbuf *);
static void sppp_chap_init(struct sppp *);
-static void sppp_chap_open(struct sppp *);
-static void sppp_chap_close(struct sppp *);
+static void sppp_chap_open(struct sppp *, void *);
+static void sppp_chap_close(struct sppp *, void *);
static void sppp_chap_TO(void *);
static void sppp_chap_tlu(struct sppp *);
static void sppp_chap_tld(struct sppp *);
@@ -476,16 +493,16 @@ static const struct cp ipv6cp = {
static const struct cp pap = {
PPP_PAP, IDX_PAP, CP_AUTH, "pap",
- sppp_null, sppp_null, sppp_pap_open, sppp_pap_close,
- sppp_pap_TO, 0, 0, 0,
+ sppp_null_event, sppp_null_event, sppp_pap_open, sppp_pap_close,
+ sppp_null_event, 0, 0, 0,
sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null,
sppp_pap_scr, 0
};
static const struct cp chap = {
PPP_CHAP, IDX_CHAP, CP_AUTH, "chap",
- sppp_null, sppp_null, sppp_chap_open, sppp_chap_close,
- sppp_chap_TO, 0, 0, 0,
+ sppp_null_event, sppp_null_event, sppp_chap_open, sppp_chap_close,
+ sppp_null_event, 0, 0, 0,
sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null,
sppp_chap_scr, 0
};
@@ -771,16 +788,7 @@ sppp_output(struct ifnet *ifp, struct mb
* to start LCP for it.
*/
ifp->if_flags |= IFF_RUNNING;
-
- SPPP_UNLOCK(sp);
- splx(s);
-
- SPPP_LOCK(sp, RW_WRITER);
- lcp.Open(sp);
- SPPP_UNLOCK(sp);
-
- s = splnet();
- SPPP_LOCK(sp, RW_READER);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_open);
}
/*
@@ -978,6 +986,7 @@ void
sppp_attach(struct ifnet *ifp)
{
struct sppp *sp = (struct sppp *) ifp;
+ char xnamebuf[MAXCOMLEN];
/* Initialize keepalive handler. */
if (! spppq) {
@@ -1015,6 +1024,10 @@ sppp_attach(struct ifnet *ifp)
/* Lets not beat about the bush, we know we're down. */
ifp->if_link_state = LINK_STATE_DOWN;
+ snprintf(xnamebuf, sizeof(xnamebuf), "%s.wq_cp", ifp->if_xname);
+ sp->wq_cp = sppp_wq_create(sp, xnamebuf,
+ PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE);
+
memset(&sp->myauth, 0, sizeof sp->myauth);
memset(&sp->hisauth, 0, sizeof sp->hisauth);
SPPP_LOCK(sp, RW_WRITER);
@@ -1055,13 +1068,14 @@ sppp_detach(struct ifnet *ifp)
workqueue_destroy(sp->ipcp.update_addrs_wq);
pcq_destroy(sp->ipcp.update_addrs_q);
- callout_stop(&sp->scp[IDX_LCP].ch);
- callout_stop(&sp->scp[IDX_IPCP].ch);
+ sppp_cp_fini(&lcp, sp);
+ sppp_cp_fini(&ipcp, sp);
callout_stop(&sp->scp[IDX_PAP].ch);
callout_stop(&sp->scp[IDX_CHAP].ch);
#ifdef INET6
- callout_stop(&sp->scp[IDX_IPV6CP].ch);
+ sppp_cp_fini(&ipv6cp, sp);
#endif
+ sppp_wq_destroy(sp, sp->wq_cp);
callout_stop(&sp->pap_my_to_ch);
/* free authentication info */
@@ -1172,13 +1186,16 @@ sppp_ioctl(struct ifnet *ifp, u_long cmd
}
if (going_up || going_down) {
- lcp.Close(sp);
+ sp->lcp.reestablish = false;
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
}
if (going_up && newmode == 0) {
/* neither auto-dial nor passive */
ifp->if_flags |= IFF_RUNNING;
- if (!(sp->pp_flags & PP_CISCO))
- lcp.Open(sp);
+ if (!(sp->pp_flags & PP_CISCO)) {
+ sppp_wq_add(sp->wq_cp,
+ &sp->scp[IDX_LCP].work_open);
+ }
} else if (going_down) {
SPPP_UNLOCK(sp);
sppp_flush(ifp);
@@ -1477,6 +1494,81 @@ sppp_cp_send(struct sppp *sp, u_short pr
}
}
+static void
+sppp_cp_to_lcp(void *xsp)
+{
+ struct sppp *sp = xsp;
+
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_to);
+}
+
+static void
+sppp_cp_to_ipcp(void *xsp)
+{
+ struct sppp *sp = xsp;
+
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_IPCP].work_to);
+}
+
+static void
+sppp_cp_to_ipv6cp(void *xsp)
+{
+ struct sppp *sp = xsp;
+
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_IPV6CP].work_to);
+}
+
+static void
+sppp_cp_init(const struct cp *cp, struct sppp *sp)
+{
+ struct sppp_cp *scp;
+ typedef void (*sppp_co_cb_t)(void *);
+ static const sppp_co_cb_t to_cb[IDX_COUNT] = {
+ [IDX_LCP] = sppp_cp_to_lcp,
+ [IDX_IPCP] = sppp_cp_to_ipcp,
+ [IDX_IPV6CP] = sppp_cp_to_ipv6cp,
+ };
+
+ scp = &sp->scp[cp->protoidx];
+
+ SPPP_WQ_SET(&scp->work_up, cp->Up, cp);
+ SPPP_WQ_SET(&scp->work_down, cp->Down, cp);
+ SPPP_WQ_SET(&scp->work_open, cp->Open, cp);
+ SPPP_WQ_SET(&scp->work_close, cp->Close, cp);
+ SPPP_WQ_SET(&scp->work_to, cp->TO, cp);
+ SPPP_WQ_SET(&scp->work_rcr, sppp_rcr_event, cp);
+ SPPP_WQ_SET(&scp->work_rca, sppp_rca_event, cp);
+ SPPP_WQ_SET(&scp->work_rcn, sppp_rcn_event, cp);
+ SPPP_WQ_SET(&scp->work_rtr, sppp_rtr_event, cp);
+ SPPP_WQ_SET(&scp->work_rta, sppp_rta_event, cp);
+ SPPP_WQ_SET(&scp->work_rxj, sppp_rxj_event, cp);
+
+ callout_init(&scp->ch, CALLOUT_MPSAFE);
+ callout_setfunc(&scp->ch, to_cb[cp->protoidx], sp);
+}
+
+static void
+sppp_cp_fini(const struct cp *cp, struct sppp *sp)
+{
+ struct sppp_cp *scp;
+ scp = &sp->scp[cp->protoidx];
+
+ sppp_wq_wait(sp->wq_cp, &scp->work_up);
+ sppp_wq_wait(sp->wq_cp, &scp->work_down);
+ sppp_wq_wait(sp->wq_cp, &scp->work_open);
+ sppp_wq_wait(sp->wq_cp, &scp->work_close);
+ sppp_wq_wait(sp->wq_cp, &scp->work_to);
+ sppp_wq_wait(sp->wq_cp, &scp->work_rcr);
+ sppp_wq_wait(sp->wq_cp, &scp->work_rca);
+ sppp_wq_wait(sp->wq_cp, &scp->work_rcn);
+ sppp_wq_wait(sp->wq_cp, &scp->work_rtr);
+ sppp_wq_wait(sp->wq_cp, &scp->work_rta);
+ sppp_wq_wait(sp->wq_cp, &scp->work_rxj);
+
+ callout_halt(&scp->ch, NULL);
+ callout_destroy(&scp->ch);
+}
+
/*
* Handle incoming PPP control protocol packets.
*/
@@ -1536,7 +1628,7 @@ sppp_cp_input(const struct cp *cp, struc
return;
}
sp->scp[cp->protoidx].rconfid = h->ident;
- sppp_rcr_event(cp, sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[cp->protoidx].work_rcr);
break;
case CONF_ACK:
if (h->ident != sp->scp[cp->protoidx].confid) {
@@ -1547,7 +1639,7 @@ sppp_cp_input(const struct cp *cp, struc
if_statinc(ifp, if_ierrors);
break;
}
- sppp_rca_event(cp, sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[cp->protoidx].work_rca);
break;
case CONF_NAK:
case CONF_REJ:
@@ -1564,15 +1656,15 @@ sppp_cp_input(const struct cp *cp, struc
else /* CONF_REJ */
(cp->RCN_rej)(sp, h, len);
- sppp_rcn_event(cp, sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[cp->protoidx].work_rcn);
break;
case TERM_REQ:
sp->scp[cp->protoidx].rseq = h->ident;
- sppp_rtr_event(cp, sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[cp->protoidx].work_rtr);
break;
case TERM_ACK:
- sppp_rta_event(cp, sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[cp->protoidx].work_rta);
break;
case CODE_REJ:
/* XXX catastrophic rejects (RXJ-) aren't handled yet. */
@@ -1581,7 +1673,7 @@ sppp_cp_input(const struct cp *cp, struc
"danger will robinson\n",
ifp->if_xname, cp->name,
sppp_cp_type_name(h->type));
- sppp_rxj_event(cp, sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[cp->protoidx].work_rxj);
break;
case PROTO_REJ:
{
@@ -1616,11 +1708,12 @@ sppp_cp_input(const struct cp *cp, struc
*/
if (upper && !catastrophic) {
if (sp->scp[upper->protoidx].state == STATE_REQ_SENT) {
- upper->Close(sp);
+ sppp_wq_add(sp->wq_cp,
+ &sp->scp[upper->protoidx].work_close);
break;
}
}
- sppp_rxj_event(cp, sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[cp->protoidx].work_rxj);
break;
}
case DISC_REQ:
@@ -1657,8 +1750,8 @@ sppp_cp_input(const struct cp *cp, struc
/* Shut down the PPP link. */
/* XXX */
- lcp.Down(sp);
- lcp.Up(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_down);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_up);
break;
}
u32 = htonl(sp->lcp.magic);
@@ -1710,8 +1803,9 @@ sppp_cp_input(const struct cp *cp, struc
* Basically, the state transition handling in the automaton.
*/
static void
-sppp_up_event(const struct cp *cp, struct sppp *sp)
+sppp_up_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
STDDCL;
KASSERT(SPPP_WLOCKED(sp));
@@ -1738,8 +1832,9 @@ sppp_up_event(const struct cp *cp, struc
}
static void
-sppp_down_event(const struct cp *cp, struct sppp *sp)
+sppp_down_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
STDDCL;
KASSERT(SPPP_WLOCKED(sp));
@@ -1776,8 +1871,9 @@ sppp_down_event(const struct cp *cp, str
static void
-sppp_open_event(const struct cp *cp, struct sppp *sp)
+sppp_open_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
STDDCL;
KASSERT(SPPP_WLOCKED(sp));
@@ -1814,8 +1910,9 @@ sppp_open_event(const struct cp *cp, str
static void
-sppp_close_event(const struct cp *cp, struct sppp *sp)
+sppp_close_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
STDDCL;
KASSERT(SPPP_WLOCKED(sp));
@@ -1855,10 +1952,11 @@ sppp_close_event(const struct cp *cp, st
}
static void
-sppp_to_event(const struct cp *cp, struct sppp *sp)
+sppp_to_event(struct sppp *sp, void *xcp)
{
- STDDCL;
+ const struct cp *cp = xcp;
int s;
+ STDDCL;
KASSERT(SPPP_WLOCKED(sp));
@@ -1898,8 +1996,7 @@ sppp_to_event(const struct cp *cp, struc
case STATE_STOPPING:
sppp_cp_send(sp, cp->proto, TERM_REQ,
++sp->scp[cp->protoidx].seq, 0, 0);
- callout_reset(&sp->scp[cp->protoidx].ch, sp->lcp.timeout,
- cp->TO, sp);
+ callout_schedule(&sp->scp[cp->protoidx].ch, sp->lcp.timeout);
break;
case STATE_REQ_SENT:
case STATE_ACK_RCVD:
@@ -1909,8 +2006,7 @@ sppp_to_event(const struct cp *cp, struc
break;
case STATE_ACK_SENT:
(cp->scr)(sp);
- callout_reset(&sp->scp[cp->protoidx].ch, sp->lcp.timeout,
- cp->TO, sp);
+ callout_schedule(&sp->scp[cp->protoidx].ch, sp->lcp.timeout);
break;
}
@@ -1918,12 +2014,13 @@ sppp_to_event(const struct cp *cp, struc
}
static void
-sppp_rcr_event(const struct cp *cp, struct sppp *sp)
+sppp_rcr_event(struct sppp *sp, void *xcp)
{
- STDDCL;
+ const struct cp *cp = xcp;
u_char type;
void *buf;
size_t blen;
+ STDDCL;
type = sp->scp[cp->protoidx].rcr_type;
buf = sp->scp[cp->protoidx].rcr_buf;
@@ -2021,8 +2118,9 @@ sppp_rcr_event(const struct cp *cp, stru
}
static void
-sppp_rca_event(const struct cp *cp, struct sppp *sp)
+sppp_rca_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
STDDCL;
switch (sp->scp[cp->protoidx].state) {
@@ -2062,8 +2160,9 @@ sppp_rca_event(const struct cp *cp, stru
}
static void
-sppp_rcn_event(const struct cp *cp, struct sppp *sp)
+sppp_rcn_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
struct ifnet *ifp = &sp->pp_if;
switch (sp->scp[cp->protoidx].state) {
@@ -2096,8 +2195,9 @@ sppp_rcn_event(const struct cp *cp, stru
}
static void
-sppp_rtr_event(const struct cp *cp, struct sppp *sp)
+sppp_rtr_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
STDDCL;
switch (sp->scp[cp->protoidx].state) {
@@ -2133,8 +2233,9 @@ sppp_rtr_event(const struct cp *cp, stru
}
static void
-sppp_rta_event(const struct cp *cp, struct sppp *sp)
+sppp_rta_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
struct ifnet *ifp = &sp->pp_if;
switch (sp->scp[cp->protoidx].state) {
@@ -2170,8 +2271,9 @@ sppp_rta_event(const struct cp *cp, stru
}
static void
-sppp_rxj_event(const struct cp *cp, struct sppp *sp)
+sppp_rxj_event(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
struct ifnet *ifp = &sp->pp_if;
/* XXX catastrophic rejects (RXJ-) aren't handled yet. */
@@ -2219,8 +2321,7 @@ sppp_cp_change_state(const struct cp *cp
case STATE_REQ_SENT:
case STATE_ACK_RCVD:
case STATE_ACK_SENT:
- callout_reset(&sp->scp[cp->protoidx].ch, sp->lcp.timeout,
- cp->TO, sp);
+ callout_schedule(&sp->scp[cp->protoidx].ch, sp->lcp.timeout);
break;
}
}
@@ -2257,16 +2358,19 @@ sppp_lcp_init(struct sppp *sp)
sp->lcp.max_terminate = 2;
sp->lcp.max_configure = 10;
sp->lcp.max_failure = 10;
- callout_init(&sp->scp[IDX_LCP].ch, CALLOUT_MPSAFE);
+ sppp_cp_init(&lcp, sp);
}
static void
-sppp_lcp_up(struct sppp *sp)
+sppp_lcp_up(struct sppp *sp, void *xcp)
{
+ const struct cp *cp = xcp;
+ int pidx;
STDDCL;
KASSERT(SPPP_WLOCKED(sp));
+ pidx = cp->protoidx;
/* Initialize activity timestamp: opening a connection is an activity */
sp->pp_last_receive = sp->pp_last_activity = time_uptime;
@@ -2280,30 +2384,30 @@ sppp_lcp_up(struct sppp *sp)
log(LOG_DEBUG,
"%s: Up event", ifp->if_xname);
ifp->if_flags |= IFF_RUNNING;
- if (sp->scp[IDX_LCP].state == STATE_INITIAL) {
+ if (sp->scp[pidx].state == STATE_INITIAL) {
if (debug)
addlog("(incoming call)\n");
sp->pp_flags |= PP_CALLIN;
- lcp.Open(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[pidx].work_open);
} else if (debug)
addlog("\n");
} else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 &&
(sp->scp[IDX_LCP].state == STATE_INITIAL)) {
ifp->if_flags |= IFF_RUNNING;
- lcp.Open(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[pidx].work_open);
}
- sppp_up_event(&lcp, sp);
+ sppp_up_event(sp, xcp);
}
static void
-sppp_lcp_down(struct sppp *sp)
+sppp_lcp_down(struct sppp *sp, void *xcp)
{
STDDCL;
KASSERT(SPPP_WLOCKED(sp));
- sppp_down_event(&lcp, sp);
+ sppp_down_event(sp, xcp);
/*
* If this is neither a dial-on-demand nor a passive
@@ -2320,6 +2424,9 @@ sppp_lcp_down(struct sppp *sp)
SPPP_UNLOCK(sp);
if_down(ifp);
SPPP_LOCK(sp, RW_WRITER);
+
+ if (sp->lcp.reestablish)
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_open);
} else {
if (debug)
log(LOG_DEBUG,
@@ -2329,16 +2436,19 @@ sppp_lcp_down(struct sppp *sp)
sp->scp[IDX_LCP].fail_counter = 0;
sp->pp_flags &= ~PP_CALLIN;
if (sp->scp[IDX_LCP].state != STATE_INITIAL)
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
ifp->if_flags &= ~IFF_RUNNING;
+
}
static void
-sppp_lcp_open(struct sppp *sp)
+sppp_lcp_open(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
+ sp->lcp.reestablish = false;
+
if (sp->pp_if.if_mtu < PP_MTU) {
sp->lcp.mru = sp->pp_if.if_mtu;
sp->lcp.opts |= (1 << LCP_OPT_MRU);
@@ -2354,25 +2464,22 @@ sppp_lcp_open(struct sppp *sp)
else
sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO);
sp->pp_flags &= ~PP_NEEDAUTH;
- sppp_open_event(&lcp, sp);
+ sppp_open_event(sp, xcp);
}
static void
-sppp_lcp_close(struct sppp *sp)
+sppp_lcp_close(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
- sppp_close_event(&lcp, sp);
+ sppp_close_event(sp, xcp);
}
static void
-sppp_lcp_TO(void *cookie)
+sppp_lcp_TO(struct sppp *sp, void *xcp)
{
- struct sppp *sp = (struct sppp*)cookie;
- SPPP_LOCK(sp, RW_WRITER);
- sppp_to_event(&lcp, sp);
- SPPP_UNLOCK(sp);
+ sppp_to_event(sp, xcp);
}
/*
@@ -2573,8 +2680,10 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
IF_PURGE(&sp->pp_cpq);
/* XXX ? */
- lcp.Down(sp);
- lcp.Up(sp);
+ sppp_wq_add(sp->wq_cp,
+ &sp->scp[IDX_LCP].work_down);
+ sppp_wq_add(sp->wq_cp,
+ &sp->scp[IDX_LCP].work_up);
}
} else if (debug)
addlog(" [glitch]");
@@ -2786,7 +2895,7 @@ sppp_lcp_RCN_rej(struct sppp *sp, struct
}
if (debug)
addlog("[access denied]\n");
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
break;
}
}
@@ -2877,7 +2986,7 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
*/
if (debug)
addlog("[access denied]\n");
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
break;
}
}
@@ -2906,8 +3015,9 @@ sppp_lcp_tlu(struct sppp *sp)
}
for (i = 0; i < IDX_COUNT; i++)
- if ((cps[i])->flags & CP_QUAL)
- (cps[i])->Open(sp);
+ if ((cps[i])->flags & CP_QUAL) {
+ (cps[i])->Open(sp, __UNCONST(&cps[i]));
+ }
if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 ||
(sp->pp_flags & PP_NEEDAUTH) != 0)
@@ -2924,19 +3034,19 @@ sppp_lcp_tlu(struct sppp *sp)
*/
for (i = 0; i < IDX_COUNT; i++)
if ((cps[i])->flags & CP_AUTH)
- (cps[i])->Open(sp);
+ (cps[i])->Open(sp, __UNCONST(&cps[i]));
if (sp->pp_phase == SPPP_PHASE_NETWORK) {
/* Notify all NCPs. */
for (i = 0; i < IDX_COUNT; i++)
if ((cps[i])->flags & CP_NCP)
- (cps[i])->Open(sp);
+ (cps[i])->Open(sp, __UNCONST(&cps[i]));
}
/* Send Up events to all started protos. */
for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) {
if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) {
- (cps[i])->Up(sp);
+ (cps[i])->Up(sp, __UNCONST(&cps[i]));
}
}
@@ -2966,8 +3076,8 @@ sppp_lcp_tld(struct sppp *sp)
*/
for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) {
if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) {
- (cps[i])->Down(sp);
- (cps[i])->Close(sp);
+ (cps[i])->Down(sp, __UNCONST(&cps[i]));
+ (cps[i])->Close(sp,__UNCONST(&cps[i]));
}
}
}
@@ -3078,7 +3188,7 @@ sppp_lcp_check_and_close(struct sppp *sp
if (sppp_ncp_check(sp))
return;
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
}
@@ -3103,7 +3213,7 @@ sppp_ipcp_init(struct sppp *sp)
sp->scp[IDX_IPCP].fail_counter = 0;
sp->scp[IDX_IPCP].seq = 0;
sp->scp[IDX_IPCP].rseq = 0;
- callout_init(&sp->scp[IDX_IPCP].ch, CALLOUT_MPSAFE);
+ sppp_cp_init(&ipcp, sp);
error = workqueue_create(&sp->ipcp.update_addrs_wq, "ipcp_addr",
sppp_update_ip_addrs_work, sp, PRI_SOFTNET, IPL_NET, 0);
@@ -3116,21 +3226,21 @@ sppp_ipcp_init(struct sppp *sp)
}
static void
-sppp_ipcp_up(struct sppp *sp)
+sppp_ipcp_up(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
- sppp_up_event(&ipcp, sp);
+ sppp_up_event(sp, xcp);
}
static void
-sppp_ipcp_down(struct sppp *sp)
+sppp_ipcp_down(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
- sppp_down_event(&ipcp, sp);
+ sppp_down_event(sp, xcp);
}
static void
-sppp_ipcp_open(struct sppp *sp)
+sppp_ipcp_open(struct sppp *sp, void *xcp)
{
STDDCL;
uint32_t myaddr, hisaddr;
@@ -3176,16 +3286,16 @@ sppp_ipcp_open(struct sppp *sp)
*/
sp->ipcp.flags |= IPCP_HISADDR_DYN;
}
- sppp_open_event(&ipcp, sp);
+ sppp_open_event(sp, xcp);
}
static void
-sppp_ipcp_close(struct sppp *sp)
+sppp_ipcp_close(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
- sppp_close_event(&ipcp, sp);
+ sppp_close_event(sp, xcp);
#ifdef INET
if (sp->ipcp.flags & (IPCP_MYADDR_DYN|IPCP_HISADDR_DYN))
@@ -3197,13 +3307,10 @@ sppp_ipcp_close(struct sppp *sp)
}
static void
-sppp_ipcp_TO(void *cookie)
+sppp_ipcp_TO(struct sppp *sp, void *xcp)
{
- struct sppp *sp = cookie;
- SPPP_LOCK(sp, RW_WRITER);
- sppp_to_event(&ipcp, sp);
- SPPP_UNLOCK(sp);
+ sppp_to_event(sp, xcp);
}
/*
@@ -3701,27 +3808,27 @@ sppp_ipv6cp_init(struct sppp *sp)
sp->scp[IDX_IPV6CP].fail_counter = 0;
sp->scp[IDX_IPV6CP].seq = 0;
sp->scp[IDX_IPV6CP].rseq = 0;
- callout_init(&sp->scp[IDX_IPV6CP].ch, CALLOUT_MPSAFE);
+ sppp_cp_init(&ipv6cp, sp);
}
static void
-sppp_ipv6cp_up(struct sppp *sp)
+sppp_ipv6cp_up(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
- sppp_up_event(&ipv6cp, sp);
+ sppp_up_event(sp, xcp);
}
static void
-sppp_ipv6cp_down(struct sppp *sp)
+sppp_ipv6cp_down(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
- sppp_down_event(&ipv6cp, sp);
+ sppp_down_event(sp, xcp);
}
static void
-sppp_ipv6cp_open(struct sppp *sp)
+sppp_ipv6cp_open(struct sppp *sp, void *xcp)
{
STDDCL;
struct in6_addr myaddr, hisaddr;
@@ -3751,25 +3858,22 @@ sppp_ipv6cp_open(struct sppp *sp)
sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN;
sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID);
- sppp_open_event(&ipv6cp, sp);
+ sppp_open_event(sp, xcp);
}
static void
-sppp_ipv6cp_close(struct sppp *sp)
+sppp_ipv6cp_close(struct sppp *sp, void *xcp)
{
KASSERT(SPPP_WLOCKED(sp));
- sppp_close_event(&ipv6cp, sp);
+ sppp_close_event(sp, xcp);
}
static void
-sppp_ipv6cp_TO(void *cookie)
+sppp_ipv6cp_TO(struct sppp *sp, void *xcp)
{
- struct sppp *sp = cookie;
- SPPP_LOCK(sp, RW_WRITER);
- sppp_to_event(&ipv6cp, sp);
- SPPP_UNLOCK(sp);
+ sppp_to_event(sp, xcp);
}
/*
@@ -4232,7 +4336,7 @@ sppp_ipv6cp_init(struct sppp *sp)
}
static void
-sppp_ipv6cp_up(struct sppp *sp)
+sppp_ipv6cp_up(struct sppp *sp, void *xcp __unused)
{
KASSERT(SPPP_WLOCKED(sp));
@@ -4246,23 +4350,22 @@ sppp_ipv6cp_down(struct sppp *sp)
}
static void
-sppp_ipv6cp_open(struct sppp *sp)
+sppp_ipv6cp_open(struct sppp *sp, void *xcp __unused)
{
KASSERT(SPPP_WLOCKED(sp));
}
static void
-sppp_ipv6cp_close(struct sppp *sp)
+sppp_ipv6cp_close(struct sppp *sp, void *xcp __unused)
{
KASSERT(SPPP_WLOCKED(sp));
}
static void
-sppp_ipv6cp_TO(void *cookie)
+sppp_ipv6cp_TO(struct sppp *sp, void *xcp __unused)
{
- struct sppp *sp __diagused = cookie;
KASSERT(SPPP_WLOCKED(sp));
}
@@ -4680,10 +4783,12 @@ sppp_chap_init(struct sppp *sp)
sp->scp[IDX_CHAP].seq = 0;
sp->scp[IDX_CHAP].rseq = 0;
callout_init(&sp->scp[IDX_CHAP].ch, CALLOUT_MPSAFE);
+ callout_setfunc(&sp->scp[IDX_CHAP].ch,
+ sppp_chap_TO, sp);
}
static void
-sppp_chap_open(struct sppp *sp)
+sppp_chap_open(struct sppp *sp, void *xcp __unused)
{
KASSERT(SPPP_WLOCKED(sp));
@@ -4698,7 +4803,7 @@ sppp_chap_open(struct sppp *sp)
}
static void
-sppp_chap_close(struct sppp *sp)
+sppp_chap_close(struct sppp *sp, void *xcp __unused)
{
KASSERT(SPPP_WLOCKED(sp));
@@ -4773,7 +4878,7 @@ sppp_chap_tlu(struct sppp *sp)
*/
i = 300 + ((unsigned)(cprng_fast32() & 0xff00) >> 7);
- callout_reset(&sp->scp[IDX_CHAP].ch, i * hz, chap.TO, sp);
+ callout_schedule(&sp->scp[IDX_CHAP].ch, i * hz);
}
if (debug) {
@@ -4823,7 +4928,7 @@ sppp_chap_tld(struct sppp *sp)
callout_stop(&sp->scp[IDX_CHAP].ch);
sp->lcp.protos &= ~(1 << IDX_CHAP);
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
}
static void
@@ -5048,11 +5153,13 @@ sppp_pap_init(struct sppp *sp)
sp->scp[IDX_PAP].seq = 0;
sp->scp[IDX_PAP].rseq = 0;
callout_init(&sp->scp[IDX_PAP].ch, CALLOUT_MPSAFE);
+ callout_setfunc(&sp->scp[IDX_PAP].ch,
+ sppp_pap_TO, sp);
callout_init(&sp->pap_my_to_ch, CALLOUT_MPSAFE);
}
static void
-sppp_pap_open(struct sppp *sp)
+sppp_pap_open(struct sppp *sp, void *xcp __unused)
{
KASSERT(SPPP_WLOCKED(sp));
@@ -5072,7 +5179,7 @@ sppp_pap_open(struct sppp *sp)
}
static void
-sppp_pap_close(struct sppp *sp)
+sppp_pap_close(struct sppp *sp, void *xcp __unused)
{
KASSERT(SPPP_WLOCKED(sp));
@@ -5188,7 +5295,7 @@ sppp_pap_tld(struct sppp *sp)
callout_stop(&sp->pap_my_to_ch);
sp->lcp.protos &= ~(1 << IDX_PAP);
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
}
static void
@@ -5349,7 +5456,7 @@ sppp_keepalive(void *dummy)
printf("%s: no activity for %lu seconds\n",
sp->pp_if.if_xname,
(unsigned long)(now-sp->pp_last_activity));
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
SPPP_UNLOCK(sp);
continue;
}
@@ -5391,14 +5498,10 @@ sppp_keepalive(void *dummy)
sp->pp_alivecnt = 0;
/* we are down, close all open protocols */
- lcp.Close(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_close);
/* And now prepare LCP to reestablish the link, if configured to do so. */
- sppp_cp_change_state(&lcp, sp, STATE_STOPPED);
-
- /* Close connection immediately, completition of this
- * will summon the magic needed to reestablish it. */
- sppp_notify_tlf_wlocked(sp);
+ sp->lcp.reestablish = true;
SPPP_UNLOCK(sp);
continue;
@@ -6152,12 +6255,12 @@ sppp_phase_network(struct sppp *sp)
/* Notify NCPs now. */
for (i = 0; i < IDX_COUNT; i++)
if ((cps[i])->flags & CP_NCP)
- (cps[i])->Open(sp);
+ (cps[i])->Open(sp, __UNCONST(&cps[i]));
/* Send Up events to all NCPs. */
for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) {
- (cps[i])->Up(sp);
+ (cps[i])->Up(sp, __UNCONST(&cps[i]));
}
/* if no NCP is starting, all this was in vain, close down */
@@ -6362,6 +6465,12 @@ sppp_null(struct sppp *unused)
}
static void
+sppp_null_event(struct sppp *unused0 __unused, void *unused1 __unused)
+{
+ /* do just nothing */
+}
+
+static void
sppp_sca_scn(const struct cp *cp, struct sppp *sp)
{
STDDCL;
@@ -6420,18 +6529,14 @@ static void
sppp_notify_up(struct sppp *sp)
{
- SPPP_LOCK(sp, RW_WRITER);
- lcp.Up(sp);
- SPPP_UNLOCK(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_up);
}
static void
sppp_notify_down(struct sppp *sp)
{
- SPPP_LOCK(sp, RW_WRITER);
- lcp.Down(sp);
- SPPP_UNLOCK(sp);
+ sppp_wq_add(sp->wq_cp, &sp->scp[IDX_LCP].work_down);
}
static void
@@ -6499,3 +6604,71 @@ sppp_notify_chg_wlocked(struct sppp *sp)
sp->pp_chg(sp, sp->pp_phase);
SPPP_LOCK(sp, RW_WRITER);
}
+
+static void
+sppp_wq_work(struct work *wk, void *xsp)
+{
+ struct sppp *sp;
+ struct sppp_work *work;
+
+ sp = xsp;
+ work = container_of(wk, struct sppp_work, work);
+ atomic_cas_uint(&work->state, SPPP_WK_BUSY, SPPP_WK_FREE);
+
+ SPPP_LOCK(sp, RW_WRITER);
+ work->func(sp, work->arg);
+ SPPP_UNLOCK(sp);
+}
+
+static struct workqueue *
+sppp_wq_create(struct sppp *sp, const char *xnamebuf, pri_t prio, int ipl, int flags)
+{
+ struct workqueue *wq;
+ int error;
+
+ error = workqueue_create(&wq, xnamebuf, sppp_wq_work,
+ (void *)sp, prio, ipl, flags);
+ if (error) {
+ panic("%s: workqueue_create failed [%s, %d]\n",
+ sp->pp_if.if_xname, xnamebuf, error);
+ }
+
+ return wq;
+}
+
+static void
+sppp_wq_destroy(struct sppp *sp __unused, struct workqueue *wq)
+{
+
+ workqueue_destroy(wq);
+}
+
+static void
+sppp_wq_set(struct sppp_work *work,
+ void (*func)(struct sppp *, void *), void *arg)
+{
+
+ work->func = func;
+ work->arg = arg;
+}
+
+static void
+sppp_wq_add(struct workqueue *wq, struct sppp_work *work)
+{
+
+ if (atomic_cas_uint(&work->state, SPPP_WK_FREE, SPPP_WK_BUSY)
+ != SPPP_WK_FREE)
+ return;
+
+ KASSERT(work->func != NULL);
+ kpreempt_disable();
+ workqueue_enqueue(wq, &work->work, NULL);
+ kpreempt_enable();
+}
+static void
+sppp_wq_wait(struct workqueue *wq, struct sppp_work *work)
+{
+
+ atomic_swap_uint(&work->state, SPPP_WK_UNAVAIL);
+ workqueue_wait(wq, &work->work);
+}
Index: src/sys/net/if_spppvar.h
diff -u src/sys/net/if_spppvar.h:1.26 src/sys/net/if_spppvar.h:1.27
--- src/sys/net/if_spppvar.h:1.26 Wed Nov 25 09:18:45 2020
+++ src/sys/net/if_spppvar.h Wed Nov 25 09:35:23 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_spppvar.h,v 1.26 2020/11/25 09:18:45 yamaguchi Exp $ */
+/* $NetBSD: if_spppvar.h,v 1.27 2020/11/25 09:35:23 yamaguchi Exp $ */
#ifndef _NET_IF_SPPPVAR_H_
#define _NET_IF_SPPPVAR_H_
@@ -28,6 +28,17 @@
#include <sys/workqueue.h>
#include <sys/pcq.h>
+struct sppp;
+
+struct sppp_work {
+ struct work work;
+ void *arg;
+ void (*func)(struct sppp *, void *);
+ unsigned int state;
+#define SPPP_WK_FREE 0
+#define SPPP_WK_BUSY 1
+#define SPPP_WK_UNAVAIL 2
+};
#define IDX_LCP 0 /* idx into state table */
@@ -46,6 +57,7 @@ struct slcp {
/* multilink variables */
u_long mrru; /* our max received reconstructed unit */
u_long their_mrru; /* their max receive dreconstructed unit */
+ bool reestablish; /* reestablish after the next down event */
};
#define IDX_IPCP 1 /* idx into state table */
@@ -100,6 +112,18 @@ struct sppp_cp {
void *rcr_buf;
size_t rcr_blen;
int rcr_rlen;
+
+ struct sppp_work work_up;
+ struct sppp_work work_down;
+ struct sppp_work work_open;
+ struct sppp_work work_close;
+ struct sppp_work work_to;
+ struct sppp_work work_rcr;
+ struct sppp_work work_rca;
+ struct sppp_work work_rcn;
+ struct sppp_work work_rtr;
+ struct sppp_work work_rta;
+ struct sppp_work work_rxj;
};
struct sppp {
@@ -135,6 +159,7 @@ struct sppp {
struct callout_handle ch[IDX_COUNT]; /* per-proto and if callouts */
struct callout_handle pap_my_to_ch; /* PAP needs one more... */
#endif
+ struct workqueue *wq_cp;
struct sppp_cp scp[IDX_COUNT];
struct slcp lcp; /* LCP params */
struct sipcp ipcp; /* IPCP params */