Support PRU_BIND / PRU_LISTEN / PRU_ACCEPT in sockin.

This commit is contained in:
pooka 2008-11-25 20:39:57 +00:00
parent 50176705eb
commit eebcd28057
3 changed files with 108 additions and 31 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpuser.h,v 1.2 2008/11/18 12:39:35 pooka Exp $ */
/* $NetBSD: rumpuser.h,v 1.3 2008/11/25 20:39:57 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@ -154,5 +154,8 @@ int rumpuser_net_socket(int, int, int, int *);
int rumpuser_net_sendmsg(int, const struct msghdr *, int, int *);
int rumpuser_net_recvmsg(int, struct msghdr *, int, int *);
int rumpuser_net_connect(int, const struct sockaddr *, int, int *);
int rumpuser_net_bind(int, const struct sockaddr *, int, int *);
int rumpuser_net_accept(int, struct sockaddr *, int *, int *);
int rumpuser_net_listen(int, int, int *);
#endif /* _RUMP_RUMPUSER_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpuser_net.c,v 1.3 2008/10/15 13:02:29 pooka Exp $ */
/* $NetBSD: rumpuser_net.c,v 1.4 2008/11/25 20:39:57 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@ -61,3 +61,24 @@ rumpuser_net_connect(int s, const struct sockaddr *name, int len, int *error)
DOCALL_KLOCK(int, (connect(s, name, (socklen_t)len)));
}
int
rumpuser_net_bind(int s, const struct sockaddr *name, int len, int *error)
{
DOCALL_KLOCK(int, (bind(s, name, (socklen_t)len)));
}
int
rumpuser_net_accept(int s, struct sockaddr *name, int *lenp, int *error)
{
DOCALL_KLOCK(int, (accept(s, name, (socklen_t *)lenp)));
}
int
rumpuser_net_listen(int s, int backlog, int *error)
{
DOCALL_KLOCK(int, (listen(s, backlog)));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: sockin.c,v 1.4 2008/10/26 18:39:01 minskim Exp $ */
/* $NetBSD: sockin.c,v 1.5 2008/11/25 20:39:57 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@ -101,6 +101,37 @@ struct domain sockindomain = {
#define SO2S(so) ((intptr_t)(so->so_internal))
#define SOCKIN_SBSIZE 65536
struct sockin_unit {
struct socket *su_so;
LIST_ENTRY(sockin_unit) su_entries;
};
static LIST_HEAD(, sockin_unit) su_ent = LIST_HEAD_INITIALIZER(su_ent);
static kmutex_t su_mtx;
static bool rebuild;
static int nsock;
static int
registersock(struct socket *so, int news)
{
struct sockin_unit *su;
su = kmem_alloc(sizeof(*su), KM_NOSLEEP);
if (!su)
return ENOMEM;
so->so_internal = (void *)(intptr_t)news;
su->su_so = so;
mutex_enter(&su_mtx);
LIST_INSERT_HEAD(&su_ent, su, su_entries);
nsock++;
rebuild = true;
mutex_exit(&su_mtx);
return 0;
}
static void
sockin_process(struct socket *so)
{
@ -142,17 +173,32 @@ sockin_process(struct socket *so)
sorwakeup(so);
}
struct sockin_unit {
struct socket *su_so;
LIST_ENTRY(sockin_unit) su_entries;
};
static LIST_HEAD(, sockin_unit) su_ent = LIST_HEAD_INITIALIZER(su_ent);
static kmutex_t su_mtx;
static bool rebuild;
static int nsock;
#ifndef SOCKIN_NOTHREAD
static void
sockin_accept(struct socket *so)
{
struct socket *nso;
struct sockaddr_in sin;
int news, error, slen;
slen = sizeof(sin);
news = rumpuser_net_accept(SO2S(so), (struct sockaddr *)&sin,
&slen, &error);
if (news == -1)
return;
if ((nso = sonewconn(so, SS_ISCONNECTED)) == NULL)
goto errout;
if (registersock(nso, news) != 0)
goto errout;
return;
errout:
rumpuser_close(news, &error);
if (nso)
soclose(nso);
}
#define POLLTIMEOUT 100 /* check for new entries every 100ms */
/* XXX: doesn't handle socket (kernel) locking properly? */
@ -161,6 +207,7 @@ sockinworker(void *arg)
{
struct pollfd *pfds = NULL, *npfds;
struct sockin_unit *su_iter;
struct socket *so;
int cursock = 0, i, rv, error;
/*
@ -200,9 +247,15 @@ sockinworker(void *arg)
mutex_enter(&su_mtx);
LIST_FOREACH(su_iter, &su_ent, su_entries) {
if (SO2S(su_iter->su_so)==pfds[i].fd) {
so = su_iter->su_so;
mutex_exit(&su_mtx);
mutex_enter(softnet_lock);
sockin_process(su_iter->su_so);
if(so->so_options&SO_ACCEPTCONN)
sockin_accept(so);
else
sockin_process(so);
mutex_exit(softnet_lock);
mutex_enter(&su_mtx);
break;
}
}
@ -249,7 +302,6 @@ sockin_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
switch (req) {
case PRU_ATTACH:
{
struct sockin_unit *su;
int news;
sosetlock(so);
@ -259,29 +311,26 @@ sockin_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
break;
}
su = kmem_alloc(sizeof(*su), KM_NOSLEEP);
if (!su) {
error = ENOMEM;
break;
}
news = rumpuser_net_socket(PF_INET, so->so_proto->pr_type,
0, &error);
if (news == -1) {
kmem_free(su, sizeof(*su));
if (news == -1)
break;
}
so->so_internal = (void *)(intptr_t)news;
su->su_so = so;
mutex_enter(&su_mtx);
LIST_INSERT_HEAD(&su_ent, su, su_entries);
nsock++;
rebuild = true;
mutex_exit(&su_mtx);
if ((error = registersock(so, news)) != 0)
rumpuser_close(news, &error);
break;
}
case PRU_ACCEPT:
/* we do all the work in the worker thread */
break;
case PRU_BIND:
rumpuser_net_bind(SO2S(so), mtod(nam, const struct sockaddr *),
sizeof(struct sockaddr_in), &error);
break;
case PRU_CONNECT:
/* don't bother to connect udp sockets, always sendmsg */
if (so->so_proto->pr_type == SOCK_DGRAM)
@ -294,6 +343,10 @@ sockin_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
soisconnected(so);
break;
case PRU_LISTEN:
rumpuser_net_listen(SO2S(so), so->so_qlimit, &error);
break;
case PRU_SEND:
{
struct sockaddr *saddr;