From f53b019e3b9c566c1558586c1ccda33019257a28 Mon Sep 17 00:00:00 2001 From: wollman Date: Tue, 9 Jul 1996 19:12:53 +0000 Subject: This is a proposal-in-code for a substantial modification of the way the high kernel calls into a protocol stack to perform requests on the user's behalf. We replace the pr_usrreq() entry in struct protosw with a pointer to a structure containing pointers to functions which implement the various reuqests; each function is declared with the correct type and number of arguments. (This is unlike the current scheme in which a quarter of the requests take arguments of type other than (struct mbuf *) and the difference is papered over with casts.) There are a few benefits to this new scheme: 1) Arguments are passed with their correct types, and null-pointer dummies are no longer necessary. 2) There should be slightly better caching effects from eliminating the prximity to extraneous code and th switch in pr_usrreq(). 3) It becomes much easier to change the types of the arguments to something other than `struct mbuf *' (e.g.,pushing the work of sosend() into the protocol as advocated by Van Jacobson). There is one principal drawback: existing protocol stacks need to be modified. This is alleviated by compatibility code in uipc_socket2.c and uipc_domain.c which emulates the new interface in terms of the old and vice versa. This idea is not original to me. I read about what Jacobson did in one of his papers and have tried to implement the first steps towards something like that here. Much work remains to be done. --- sys/kern/uipc_domain.c | 12 ++- sys/kern/uipc_sockbuf.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++- sys/kern/uipc_socket2.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++- sys/sys/protosw.h | 53 +++++++++++- 4 files changed, 500 insertions(+), 5 deletions(-) (limited to 'sys') diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index b64a44b..c989f94 100644 --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93 - * $Id: uipc_domain.c,v 1.11 1995/12/02 17:10:38 bde Exp $ + * $Id: uipc_domain.c,v 1.12 1995/12/16 02:13:50 bde Exp $ */ #include @@ -103,9 +103,17 @@ domaininit(dummy) for (dp = domains; dp; dp = dp->dom_next) { if (dp->dom_init) (*dp->dom_init)(); - for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++){ +#ifdef PRU_OLDSTYLE + /* See comments in uipc_socket2.c. */ + if (pr->pr_usrreqs == 0) + pr->pr_usrreqs = &pru_oldstyle; + else if(pr->pr_usrreq == 0) + pr->pr_usrreq = pr_newstyle_usrreq; +#endif if (pr->pr_init) (*pr->pr_init)(); + } } if (max_linkhdr < 16) /* XXX */ diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index b3bdc44..4a8227d 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 - * $Id: uipc_socket2.c,v 1.9 1996/03/11 15:37:32 davidg Exp $ + * $Id: uipc_socket2.c,v 1.10 1996/06/12 05:07:35 gpalmer Exp $ */ #include @@ -754,3 +754,221 @@ sbdroprecord(sb) } while (m); } } + +#ifdef PRU_OLDSTYLE +/* + * The following routines mediate between the old-style `pr_usrreq' + * protocol implementations and the new-style `struct pr_usrreqs' + * calling convention. + */ + +/* syntactic sugar */ +#define nomb (struct mbuf *)0 + +static int +old_abort(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_ABORT, nomb, nomb, nomb); +} + +static int +old_accept(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_ACCEPT, nomb, nam, nomb); +} + +static int +old_attach(struct socket *so, int proto) +{ + return so->so_proto->pr_usrreq(so, PRU_ATTACH, nomb, + (struct mbuf *)proto, /* XXX */ + nomb); +} + +static int +old_bind(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_BIND, nomb, nam, nomb); +} + +static int +old_connect(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_CONNECT, nomb, nam, nomb); +} + +static int +old_connect2(struct socket *so1, struct socket *so2) +{ + return so1->so_proto->pr_usrreq(so1, PRU_CONNECT2, nomb, + (struct mbuf *)so2, nomb); +} + +static int +old_control(struct socket *so, int cmd, caddr_t data) +{ + return so->so_proto->pr_usrreq(so, PRU_CONTROL, (struct mbuf *)cmd, + (struct mbuf *)data, nomb); +} + +static int +old_detach(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_DETACH, nomb, nomb, nomb); +} + +static int +old_disconnect(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_DISCONNECT, nomb, nomb, nomb); +} + +static int +old_listen(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_LISTEN, nomb, nomb, nomb); +} + +static int +old_peeraddr(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_PEERADDR, nomb, nam, nomb); +} + +static int +old_rcvd(struct socket *so, int flags) +{ + return so->so_proto->pr_usrreq(so, PRU_RCVD, nomb, + (struct mbuf *)flags, /* XXX */ + nomb); +} + +static int +old_rcvoob(struct socket *so, struct mbuf *m, int flags) +{ + return so->so_proto->pr_usrreq(so, PRU_RCVOOB, m, + (struct mbuf *)flags, /* XXX */ + nomb); +} + +static int +old_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *addr, + struct mbuf *control) +{ + int req; + + if (flags & PRUS_OOB) { + req = PRU_SENDOOB; + } else if(flags & PRUS_EOF) { + req = PRU_SEND_EOF; + } else { + req = PRU_SEND; + } + return so->so_proto->pr_usrreq(so, req, m, addr, control); +} + +static int +old_sense(struct socket *so, struct stat *sb) +{ + return so->so_proto->pr_usrreq(so, PRU_SENSE, (struct mbuf *)sb, + nomb, nomb); +} + +static int +old_shutdown(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_SHUTDOWN, nomb, nomb, nomb); +} + +static int +old_sockaddr(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_SOCKADDR, nomb, nam, nomb); +} + +struct pr_usrreqs pru_oldstyle = { + old_abort, old_accept, old_attach, old_bind, old_connect, + old_connect2, old_control, old_detach, old_disconnect, + old_listen, old_peeraddr, old_rcvd, old_rcvoob, old_send, + old_sense, old_shutdown, old_sockaddr +}; + +/* + * This function is glue going the other way. It is present to allow + * for this interface to be actively developed from both directions + * (i.e., work on the kernel and protocol stacks proceeds simultaneously). + * It is expected that this function will probably cease to exist much + * sooner than the pru_oldstyle interface, above, will, because once the + * all of the high-kernel use of pr_usrreq() is removed the function is + * no longer needed. + */ +int +pr_newstyle_usrreq(struct socket *so, int req, struct mbuf *m, + struct mbuf *nam, struct mbuf *control) +{ + struct pr_usrreqs *pru = so->so_proto->pr_usrreqs; + + switch(req) { + case PRU_ABORT: + return pru->pru_abort(so); + + case PRU_ACCEPT: + return pru->pru_accept(so, nam); + + case PRU_ATTACH: + return pru->pru_attach(so, (int)nam); + + case PRU_BIND: + return pru->pru_bind(so, nam); + + case PRU_CONNECT: + return pru->pru_connect(so, nam); + + case PRU_CONNECT2: + return pru->pru_connect2(so, (struct socket *)nam); + + case PRU_CONTROL: + return pru->pru_control(so, (int)m, (caddr_t)nam); + + case PRU_DETACH: + return pru->pru_detach(so); + + case PRU_DISCONNECT: + return pru->pru_disconnect(so); + + case PRU_LISTEN: + return pru->pru_listen(so); + + case PRU_PEERADDR: + return pru->pru_peeraddr(so, nam); + + case PRU_RCVD: + return pru->pru_rcvd(so, (int)nam); + + case PRU_RCVOOB: + return pru->pru_rcvoob(so, m, (int)nam); + + case PRU_SEND: + return pru->pru_send(so, 0, m, nam, control); + + case PRU_SENDOOB: + return pru->pru_send(so, PRUS_OOB, m, nam, control); + + case PRU_SEND_EOF: + return pru->pru_send(so, PRUS_EOF, m, nam, control); + + case PRU_SENSE: + return pru->pru_sense(so, (struct stat *)m); + + case PRU_SHUTDOWN: + return pru->pru_shutdown(so); + + case PRU_SOCKADDR: + return pru->pru_sockaddr(so, nam); + + } + + panic("pru_newstyle_usrreq: unhandled request %d", req); +} + +#endif /* PRU_OLDSTYLE */ diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index b3bdc44..4a8227d 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 - * $Id: uipc_socket2.c,v 1.9 1996/03/11 15:37:32 davidg Exp $ + * $Id: uipc_socket2.c,v 1.10 1996/06/12 05:07:35 gpalmer Exp $ */ #include @@ -754,3 +754,221 @@ sbdroprecord(sb) } while (m); } } + +#ifdef PRU_OLDSTYLE +/* + * The following routines mediate between the old-style `pr_usrreq' + * protocol implementations and the new-style `struct pr_usrreqs' + * calling convention. + */ + +/* syntactic sugar */ +#define nomb (struct mbuf *)0 + +static int +old_abort(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_ABORT, nomb, nomb, nomb); +} + +static int +old_accept(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_ACCEPT, nomb, nam, nomb); +} + +static int +old_attach(struct socket *so, int proto) +{ + return so->so_proto->pr_usrreq(so, PRU_ATTACH, nomb, + (struct mbuf *)proto, /* XXX */ + nomb); +} + +static int +old_bind(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_BIND, nomb, nam, nomb); +} + +static int +old_connect(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_CONNECT, nomb, nam, nomb); +} + +static int +old_connect2(struct socket *so1, struct socket *so2) +{ + return so1->so_proto->pr_usrreq(so1, PRU_CONNECT2, nomb, + (struct mbuf *)so2, nomb); +} + +static int +old_control(struct socket *so, int cmd, caddr_t data) +{ + return so->so_proto->pr_usrreq(so, PRU_CONTROL, (struct mbuf *)cmd, + (struct mbuf *)data, nomb); +} + +static int +old_detach(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_DETACH, nomb, nomb, nomb); +} + +static int +old_disconnect(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_DISCONNECT, nomb, nomb, nomb); +} + +static int +old_listen(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_LISTEN, nomb, nomb, nomb); +} + +static int +old_peeraddr(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_PEERADDR, nomb, nam, nomb); +} + +static int +old_rcvd(struct socket *so, int flags) +{ + return so->so_proto->pr_usrreq(so, PRU_RCVD, nomb, + (struct mbuf *)flags, /* XXX */ + nomb); +} + +static int +old_rcvoob(struct socket *so, struct mbuf *m, int flags) +{ + return so->so_proto->pr_usrreq(so, PRU_RCVOOB, m, + (struct mbuf *)flags, /* XXX */ + nomb); +} + +static int +old_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *addr, + struct mbuf *control) +{ + int req; + + if (flags & PRUS_OOB) { + req = PRU_SENDOOB; + } else if(flags & PRUS_EOF) { + req = PRU_SEND_EOF; + } else { + req = PRU_SEND; + } + return so->so_proto->pr_usrreq(so, req, m, addr, control); +} + +static int +old_sense(struct socket *so, struct stat *sb) +{ + return so->so_proto->pr_usrreq(so, PRU_SENSE, (struct mbuf *)sb, + nomb, nomb); +} + +static int +old_shutdown(struct socket *so) +{ + return so->so_proto->pr_usrreq(so, PRU_SHUTDOWN, nomb, nomb, nomb); +} + +static int +old_sockaddr(struct socket *so, struct mbuf *nam) +{ + return so->so_proto->pr_usrreq(so, PRU_SOCKADDR, nomb, nam, nomb); +} + +struct pr_usrreqs pru_oldstyle = { + old_abort, old_accept, old_attach, old_bind, old_connect, + old_connect2, old_control, old_detach, old_disconnect, + old_listen, old_peeraddr, old_rcvd, old_rcvoob, old_send, + old_sense, old_shutdown, old_sockaddr +}; + +/* + * This function is glue going the other way. It is present to allow + * for this interface to be actively developed from both directions + * (i.e., work on the kernel and protocol stacks proceeds simultaneously). + * It is expected that this function will probably cease to exist much + * sooner than the pru_oldstyle interface, above, will, because once the + * all of the high-kernel use of pr_usrreq() is removed the function is + * no longer needed. + */ +int +pr_newstyle_usrreq(struct socket *so, int req, struct mbuf *m, + struct mbuf *nam, struct mbuf *control) +{ + struct pr_usrreqs *pru = so->so_proto->pr_usrreqs; + + switch(req) { + case PRU_ABORT: + return pru->pru_abort(so); + + case PRU_ACCEPT: + return pru->pru_accept(so, nam); + + case PRU_ATTACH: + return pru->pru_attach(so, (int)nam); + + case PRU_BIND: + return pru->pru_bind(so, nam); + + case PRU_CONNECT: + return pru->pru_connect(so, nam); + + case PRU_CONNECT2: + return pru->pru_connect2(so, (struct socket *)nam); + + case PRU_CONTROL: + return pru->pru_control(so, (int)m, (caddr_t)nam); + + case PRU_DETACH: + return pru->pru_detach(so); + + case PRU_DISCONNECT: + return pru->pru_disconnect(so); + + case PRU_LISTEN: + return pru->pru_listen(so); + + case PRU_PEERADDR: + return pru->pru_peeraddr(so, nam); + + case PRU_RCVD: + return pru->pru_rcvd(so, (int)nam); + + case PRU_RCVOOB: + return pru->pru_rcvoob(so, m, (int)nam); + + case PRU_SEND: + return pru->pru_send(so, 0, m, nam, control); + + case PRU_SENDOOB: + return pru->pru_send(so, PRUS_OOB, m, nam, control); + + case PRU_SEND_EOF: + return pru->pru_send(so, PRUS_EOF, m, nam, control); + + case PRU_SENSE: + return pru->pru_sense(so, (struct stat *)m); + + case PRU_SHUTDOWN: + return pru->pru_shutdown(so); + + case PRU_SOCKADDR: + return pru->pru_sockaddr(so, nam); + + } + + panic("pru_newstyle_usrreq: unhandled request %d", req); +} + +#endif /* PRU_OLDSTYLE */ diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h index feb34b8..29b7ca4 100644 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)protosw.h 8.1 (Berkeley) 6/2/93 - * $Id: protosw.h,v 1.8 1995/11/21 12:55:13 bde Exp $ + * $Id: protosw.h,v 1.9 1995/12/16 02:14:44 bde Exp $ */ #ifndef _SYS_PROTOSW_H_ @@ -91,6 +91,7 @@ struct protosw { /* slow timeout (500ms) */ void (*pr_drain) __P((void)); /* flush any excess space possible */ + struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */ }; #define PR_SLOWHZ 2 /* 2 slow timeouts per second */ @@ -147,6 +148,7 @@ struct protosw { #define PRU_SLOWTIMO 19 /* 500ms timeout */ #define PRU_PROTORCV 20 /* receive from below */ #define PRU_PROTOSEND 21 /* send to below */ +/* end for protocol's internal use */ #define PRU_SEND_EOF 22 /* send and close */ #define PRU_NREQ 22 @@ -162,6 +164,55 @@ char *prurequests[] = { }; #endif +#ifdef KERNEL /* users shouldn't see this decl */ +struct stat; + +/* + * If the ordering here looks odd, that's because it's alphabetical. + */ +struct pr_usrreqs { + int (*pru_abort) __P((struct socket *so)); + int (*pru_accept) __P((struct socket *so, struct mbuf *nam)); + int (*pru_attach) __P((struct socket *so, int proto)); + int (*pru_bind) __P((struct socket *so, struct mbuf *nam)); + int (*pru_connect) __P((struct socket *so, struct mbuf *nam)); + int (*pru_connect2) __P((struct socket *so1, struct socket *so2)); + int (*pru_control) __P((struct socket *so, int cmd, caddr_t data)); + int (*pru_detach) __P((struct socket *so)); + int (*pru_disconnect) __P((struct socket *so)); + int (*pru_listen) __P((struct socket *so)); + int (*pru_peeraddr) __P((struct socket *so, struct mbuf *nam)); + int (*pru_rcvd) __P((struct socket *so, int flags)); + int (*pru_rcvoob) __P((struct socket *so, struct mbuf *m, int flags)); + /* + * The `m' parameter here is almost certainly going to become a + * `struct uio' at some point in the future. Similar changes + * will probably happen for the receive entry points. + */ + int (*pru_send) __P((struct socket *so, int flags, struct mbuf *m, + struct mbuf *addr, struct mbuf *control)); +#define PRUS_OOB 0x1 +#define PRUS_EOF 0x2 + int (*pru_sense) __P((struct socket *so, struct stat *sb)); + int (*pru_shutdown) __P((struct socket *so)); + int (*pru_sockaddr) __P((struct socket *so, struct mbuf *nam)); +}; + +#define PRU_OLDSTYLE + +#ifdef PRU_OLDSTYLE +/* + * Protocols which don't yet implement pr_usrreqs can point it to this + * structure, which will call the old pr_usrreq() entry point with the + * appropriate arguments. + */ +extern struct pr_usrreqs pru_oldstyle; +int pr_newstyle_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, + struct mbuf *); +#endif /* PRU_OLDSTYLE */ + +#endif /* KERNEL */ + /* * The arguments to the ctlinput routine are * (*protosw[].pr_ctlinput)(cmd, sa, arg); -- cgit v1.1