summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1996-07-09 19:12:53 +0000
committerwollman <wollman@FreeBSD.org>1996-07-09 19:12:53 +0000
commitf53b019e3b9c566c1558586c1ccda33019257a28 (patch)
tree9c22bb256c7ddccd3022df002ff86c9b5678643b /sys
parentba8d9388bd19ffc402d860c2376f96c7e618e193 (diff)
downloadFreeBSD-src-f53b019e3b9c566c1558586c1ccda33019257a28.zip
FreeBSD-src-f53b019e3b9c566c1558586c1ccda33019257a28.tar.gz
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/uipc_domain.c12
-rw-r--r--sys/kern/uipc_sockbuf.c220
-rw-r--r--sys/kern/uipc_socket2.c220
-rw-r--r--sys/sys/protosw.h53
4 files changed, 500 insertions, 5 deletions
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 <sys/param.h>
@@ -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 <sys/param.h>
@@ -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 <sys/param.h>
@@ -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);
OpenPOWER on IntegriCloud