[rtems-libbsd commit] BPF(4): Add support
Sebastian Huber
sebh at rtems.org
Mon Dec 16 14:29:34 UTC 2013
Module: rtems-libbsd
Branch: master
Commit: e10d1cdc456189ddf391daf4561171e61604ec56
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=e10d1cdc456189ddf391daf4561171e61604ec56
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Fri Dec 13 10:57:03 2013 +0100
BPF(4): Add support
---
freebsd/sys/net/bpf.c | 280 ++++++++++++++++++++++++++++
freebsd/sys/net/bpfdesc.h | 9 +
freebsd/usr.bin/netstat/bpf.c | 2 +
libbsd.txt | 2 +
rtemsbsd/include/rtems/bsd/local/opt_bpf.h | 1 +
5 files changed, 294 insertions(+), 0 deletions(-)
diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c
index 55e60e9..10ad355 100644
--- a/freebsd/sys/net/bpf.c
+++ b/freebsd/sys/net/bpf.c
@@ -88,6 +88,11 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_freebsd.h>
#include <security/mac/mac_framework.h>
+#ifdef __rtems__
+#include <rtems/imfs.h>
+#define devfs_get_cdevpriv(x) 0
+#define devtoname(x) "bpf"
+#endif /* __rtems__ */
MALLOC_DEFINE(M_BPF, "BPF", "BPF data");
@@ -173,9 +178,11 @@ SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW, 0, "bpf sysctl");
int bpf_maxinsns = BPF_MAXINSNS;
SYSCTL_INT(_net_bpf, OID_AUTO, maxinsns, CTLFLAG_RW,
&bpf_maxinsns, 0, "Maximum bpf program instructions");
+#ifndef __rtems__
static int bpf_zerocopy_enable = 0;
SYSCTL_INT(_net_bpf, OID_AUTO, zerocopy_enable, CTLFLAG_RW,
&bpf_zerocopy_enable, 0, "Enable new zero-copy BPF buffer sessions");
+#endif /* __rtems__ */
static SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_MPSAFE | CTLFLAG_RW,
bpf_stats_sysctl, "bpf statistics portal");
@@ -185,6 +192,7 @@ SYSCTL_VNET_INT(_net_bpf, OID_AUTO, optimize_writers,
CTLFLAG_RW, &VNET_NAME(bpf_optimize_writers), 0,
"Do not send packets until BPF program is set");
+#ifndef __rtems__
static d_open_t bpfopen;
static d_read_t bpfread;
static d_write_t bpfwrite;
@@ -202,6 +210,7 @@ static struct cdevsw bpf_cdevsw = {
.d_name = "bpf",
.d_kqfilter = bpfkqfilter,
};
+#endif /* __rtems__ */
static struct filterops bpfread_filtops = {
.f_isfd = 1,
@@ -256,9 +265,11 @@ bpf_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset, void *src,
case BPF_BUFMODE_BUFFER:
return (bpf_buffer_append_bytes(d, buf, offset, src, len));
+#ifndef __rtems__
case BPF_BUFMODE_ZBUF:
d->bd_zcopy++;
return (bpf_zerocopy_append_bytes(d, buf, offset, src, len));
+#endif /* __rtems__ */
default:
panic("bpf_buf_append_bytes");
@@ -276,9 +287,11 @@ bpf_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset, void *src,
case BPF_BUFMODE_BUFFER:
return (bpf_buffer_append_mbuf(d, buf, offset, src, len));
+#ifndef __rtems__
case BPF_BUFMODE_ZBUF:
d->bd_zcopy++;
return (bpf_zerocopy_append_mbuf(d, buf, offset, src, len));
+#endif /* __rtems__ */
default:
panic("bpf_buf_append_mbuf");
@@ -298,9 +311,11 @@ bpf_buf_reclaimed(struct bpf_d *d)
case BPF_BUFMODE_BUFFER:
return;
+#ifndef __rtems__
case BPF_BUFMODE_ZBUF:
bpf_zerocopy_buf_reclaimed(d);
return;
+#endif /* __rtems__ */
default:
panic("bpf_buf_reclaimed");
@@ -318,10 +333,12 @@ bpf_canfreebuf(struct bpf_d *d)
BPFD_LOCK_ASSERT(d);
+#ifndef __rtems__
switch (d->bd_bufmode) {
case BPF_BUFMODE_ZBUF:
return (bpf_zerocopy_canfreebuf(d));
}
+#endif /* __rtems__ */
return (0);
}
@@ -335,10 +352,12 @@ bpf_canwritebuf(struct bpf_d *d)
{
BPFD_LOCK_ASSERT(d);
+#ifndef __rtems__
switch (d->bd_bufmode) {
case BPF_BUFMODE_ZBUF:
return (bpf_zerocopy_canwritebuf(d));
}
+#endif /* __rtems__ */
return (1);
}
@@ -353,11 +372,13 @@ bpf_buffull(struct bpf_d *d)
BPFD_LOCK_ASSERT(d);
+#ifndef __rtems__
switch (d->bd_bufmode) {
case BPF_BUFMODE_ZBUF:
bpf_zerocopy_buffull(d);
break;
}
+#endif /* __rtems__ */
}
/*
@@ -369,11 +390,13 @@ bpf_bufheld(struct bpf_d *d)
BPFD_LOCK_ASSERT(d);
+#ifndef __rtems__
switch (d->bd_bufmode) {
case BPF_BUFMODE_ZBUF:
bpf_zerocopy_bufheld(d);
break;
}
+#endif /* __rtems__ */
}
static void
@@ -384,8 +407,10 @@ bpf_free(struct bpf_d *d)
case BPF_BUFMODE_BUFFER:
return (bpf_buffer_free(d));
+#ifndef __rtems__
case BPF_BUFMODE_ZBUF:
return (bpf_zerocopy_free(d));
+#endif /* __rtems__ */
default:
panic("bpf_buf_free");
@@ -414,27 +439,39 @@ static int
bpf_ioctl_getzmax(struct thread *td, struct bpf_d *d, size_t *i)
{
+#ifndef __rtems__
if (d->bd_bufmode != BPF_BUFMODE_ZBUF)
return (EOPNOTSUPP);
return (bpf_zerocopy_ioctl_getzmax(td, d, i));
+#else /* __rtems__ */
+ return (EOPNOTSUPP);
+#endif /* __rtems__ */
}
static int
bpf_ioctl_rotzbuf(struct thread *td, struct bpf_d *d, struct bpf_zbuf *bz)
{
+#ifndef __rtems__
if (d->bd_bufmode != BPF_BUFMODE_ZBUF)
return (EOPNOTSUPP);
return (bpf_zerocopy_ioctl_rotzbuf(td, d, bz));
+#else /* __rtems__ */
+ return (EOPNOTSUPP);
+#endif /* __rtems__ */
}
static int
bpf_ioctl_setzbuf(struct thread *td, struct bpf_d *d, struct bpf_zbuf *bz)
{
+#ifndef __rtems__
if (d->bd_bufmode != BPF_BUFMODE_ZBUF)
return (EOPNOTSUPP);
return (bpf_zerocopy_ioctl_setzbuf(td, d, bz));
+#else /* __rtems__ */
+ return (EOPNOTSUPP);
+#endif /* __rtems__ */
}
/*
@@ -802,10 +839,15 @@ bpf_dtor(void *data)
* EBUSY if file is open by another process.
*/
/* ARGSUSED */
+#ifndef __rtems__
static int
+#else /* __rtems__ */
+static struct bpf_d *
+#endif /* __rtems__ */
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct bpf_d *d;
+#ifndef __rtems__
int error, size;
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
@@ -814,6 +856,14 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
free(d, M_BPF);
return (error);
}
+#else /* __rtems__ */
+ u_int size;
+
+ d = malloc(sizeof(*d), M_BPF, M_NOWAIT | M_ZERO);
+ if (d == NULL) {
+ return (d);
+ }
+#endif /* __rtems__ */
/*
* For historical reasons, perform a one-time initialization call to
@@ -838,16 +888,26 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
size = d->bd_bufsize;
bpf_buffer_ioctl_sblen(d, &size);
+#ifndef __rtems__
return (0);
+#else /* __rtems__ */
+ return (d);
+#endif /* __rtems__ */
}
/*
* bpfread - read next chunk of packets from buffers
*/
static int
+#ifndef __rtems__
bpfread(struct cdev *dev, struct uio *uio, int ioflag)
+#else /* __rtems__ */
+bpfread(struct bpf_d *d, struct uio *uio, int ioflag)
+#endif /* __rtems__ */
{
+#ifndef __rtems__
struct bpf_d *d;
+#endif /* __rtems__ */
int error;
int non_block;
int timed_out;
@@ -990,8 +1050,10 @@ bpf_wakeup(struct bpf_d *d)
d->bd_state = BPF_IDLE;
}
wakeup(d);
+#ifndef __rtems__
if (d->bd_async && d->bd_sig && d->bd_sigio)
pgsigio(&d->bd_sigio, d->bd_sig, 0);
+#endif /* __rtems__ */
selwakeuppri(&d->bd_sel, PRINET);
KNOTE_LOCKED(&d->bd_sel.si_note, 0);
@@ -1028,9 +1090,15 @@ bpf_ready(struct bpf_d *d)
}
static int
+#ifndef __rtems__
bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
+#else /* __rtems__ */
+bpfwrite(struct bpf_d *d, struct uio *uio, int ioflag)
+#endif /* __rtems__ */
{
+#ifndef __rtems__
struct bpf_d *d;
+#endif /* __rtems__ */
struct ifnet *ifp;
struct mbuf *m, *mc;
struct sockaddr dst;
@@ -1180,10 +1248,17 @@ reset_d(struct bpf_d *d)
*/
/* ARGSUSED */
static int
+#ifndef __rtems__
bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
struct thread *td)
+#else /* __rtems__ */
+bpfioctl(struct bpf_d *d, u_long cmd, caddr_t addr, int flags,
+ struct thread *td)
+#endif /* __rtems__ */
{
+#ifndef __rtems__
struct bpf_d *d;
+#endif /* __rtems__ */
int error;
error = devfs_get_cdevpriv((void **)&d);
@@ -1615,11 +1690,13 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case FIONBIO: /* Non-blocking I/O */
break;
+#ifndef __rtems__
case FIOASYNC: /* Send signal on receive packets */
BPFD_LOCK(d);
d->bd_async = *(int *)addr;
BPFD_UNLOCK(d);
break;
+#endif /* __rtems__ */
case FIOSETOWN:
/*
@@ -1684,10 +1761,12 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case BPF_BUFMODE_BUFFER:
break;
+#ifndef __rtems__
case BPF_BUFMODE_ZBUF:
if (bpf_zerocopy_enable)
break;
/* FALLSTHROUGH */
+#endif /* __rtems__ */
default:
CURVNET_RESTORE();
@@ -1885,7 +1964,9 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
*/
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
+#ifndef __rtems__
case BPF_BUFMODE_ZBUF:
+#endif /* __rtems__ */
if (d->bd_sbuf == NULL)
return (EINVAL);
break;
@@ -1908,9 +1989,15 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
* Otherwise, return false but make a note that a selwakeup() must be done.
*/
static int
+#ifndef __rtems__
bpfpoll(struct cdev *dev, int events, struct thread *td)
+#else /* __rtems__ */
+bpfpoll(struct bpf_d *d, int events, struct thread *td)
+#endif /* __rtems__ */
{
+#ifndef __rtems__
struct bpf_d *d;
+#endif /* __rtems__ */
int revents;
if (devfs_get_cdevpriv((void **)&d) != 0 || d->bd_bif == NULL)
@@ -1944,10 +2031,19 @@ bpfpoll(struct cdev *dev, int events, struct thread *td)
* Support for kevent() system call. Register EVFILT_READ filters and
* reject all others.
*/
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
int
+#ifndef __rtems__
bpfkqfilter(struct cdev *dev, struct knote *kn)
+#else /* __rtems__ */
+bpfkqfilter(struct bpf_d *d, struct knote *kn)
+#endif /* __rtems__ */
{
+#ifndef __rtems__
struct bpf_d *d;
+#endif /* __rtems__ */
if (devfs_get_cdevpriv((void **)&d) != 0 ||
kn->kn_filter != EVFILT_READ)
@@ -2671,18 +2767,200 @@ bpf_setdlt(struct bpf_d *d, u_int dlt)
}
return (bp == NULL ? EINVAL : 0);
}
+#ifdef __rtems__
+static struct bpf_d *
+bpf_imfs_get_context_by_iop(const rtems_libio_t *iop)
+{
+ return iop->data1;
+}
+
+static int
+bpf_imfs_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
+{
+ struct bpf_d *d;
+
+ d = bpfopen(NULL, 0, 0, NULL);
+ iop->data1 = d;
+
+ if (d != NULL) {
+ return (0);
+ } else {
+ rtems_set_errno_and_return_minus_one(ENOMEM);
+ }
+}
+
+static int
+bpf_imfs_close(rtems_libio_t *iop)
+{
+ struct bpf_d *d = bpf_imfs_get_context_by_iop(iop);
+
+ bpf_dtor(d);
+
+ return (0);
+}
+
+static ssize_t
+bpf_imfs_readv(rtems_libio_t *iop, const struct iovec *iov, int iovcnt, ssize_t total)
+{
+ struct bpf_d *d = bpf_imfs_get_context_by_iop(iop);
+ struct thread *td = rtems_bsd_get_curthread_or_null();
+ struct uio uio = {
+ .uio_iov = iov,
+ .uio_iovcnt = iovcnt,
+ .uio_offset = 0,
+ .uio_resid = total,
+ .uio_segflg = UIO_USERSPACE,
+ .uio_rw = UIO_READ,
+ .uio_td = td
+ };
+ int error;
+
+ if (td != NULL) {
+ error = bpfread(d, &uio,
+ rtems_libio_to_fcntl_flags(iop->flags));
+ } else {
+ error = ENOMEM;
+ }
+
+ if (error == 0) {
+ return (total - uio.uio_resid);
+ } else {
+ rtems_set_errno_and_return_minus_one(error);
+ }
+}
+
+static ssize_t
+bpf_imfs_read(rtems_libio_t *iop, void *buffer, size_t count)
+{
+ struct iovec iov = {
+ .iov_base = buffer,
+ .iov_len = count
+ };
+
+ return bpf_imfs_readv(iop, &iov, 1, count);
+}
+
+static ssize_t
+bpf_imfs_writev(rtems_libio_t *iop, const struct iovec *iov, int iovcnt, ssize_t total)
+{
+ struct bpf_d *d = bpf_imfs_get_context_by_iop(iop);
+ struct thread *td = rtems_bsd_get_curthread_or_null();
+ struct uio uio = {
+ .uio_iov = iov,
+ .uio_iovcnt = iovcnt,
+ .uio_offset = 0,
+ .uio_resid = total,
+ .uio_segflg = UIO_USERSPACE,
+ .uio_rw = UIO_WRITE,
+ .uio_td = td
+ };
+ int error;
+
+ if (td != NULL) {
+ error = bpfwrite(d, &uio,
+ rtems_libio_to_fcntl_flags(iop->flags));
+ } else {
+ error = ENOMEM;
+ }
+
+ if (error == 0) {
+ return (total - uio.uio_resid);
+ } else {
+ rtems_set_errno_and_return_minus_one(error);
+ }
+}
+
+static ssize_t
+bpf_imfs_write(rtems_libio_t *iop, const void *buffer, size_t count)
+{
+ struct iovec iov = {
+ .iov_base = buffer,
+ .iov_len = count
+ };
+
+ return bpf_imfs_writev(iop, &iov, 1, count);
+}
+
+static int
+bpf_imfs_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
+{
+ struct bpf_d *d = bpf_imfs_get_context_by_iop(iop);
+ struct thread *td = rtems_bsd_get_curthread_or_null();
+ int error;
+
+ if (td != 0) {
+ error = bpfioctl(d, request, buffer, 0, td);
+ } else {
+ error = ENOMEM;
+ }
+
+ return rtems_bsd_error_to_status_and_errno(error);
+}
+
+static int
+bpf_imfs_poll(rtems_libio_t *iop, int events)
+{
+ struct bpf_d *d = bpf_imfs_get_context_by_iop(iop);
+
+ return (bpfpoll(d, events, rtems_bsd_get_curthread_or_wait_forever()));
+}
+
+static int
+bpf_imfs_kqfilter(rtems_libio_t *iop, struct knote *kn)
+{
+ struct bpf_d *d = bpf_imfs_get_context_by_iop(iop);
+
+ return (bpfkqfilter(d, kn));
+}
+
+static const rtems_filesystem_file_handlers_r bpf_imfs_handlers = {
+ .open_h = bpf_imfs_open,
+ .close_h = bpf_imfs_close,
+ .read_h = bpf_imfs_read,
+ .write_h = bpf_imfs_write,
+ .ioctl_h = bpf_imfs_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek_file,
+ .fstat_h = rtems_filesystem_default_fstat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl,
+ .poll_h = bpf_imfs_poll,
+ .kqfilter_h = bpf_imfs_kqfilter,
+ .readv_h = bpf_imfs_readv,
+ .writev_h = bpf_imfs_writev
+};
+
+static const IMFS_node_control bpf_imfs_control = {
+ .imfs_type = IMFS_GENERIC,
+ .handlers = &bpf_imfs_handlers,
+ .node_initialize = IMFS_node_initialize_default,
+ .node_remove = IMFS_node_remove_default,
+ .node_destroy = IMFS_node_destroy_default
+};
+#endif /* __rtems__ */
static void
bpf_drvinit(void *unused)
{
+#ifndef __rtems__
struct cdev *dev;
+#else /* __rtems__ */
+ mode_t mode = S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO;
+ int rv;
+#endif /* __rtems__ */
mtx_init(&bpf_mtx, "bpf global lock", NULL, MTX_DEF);
LIST_INIT(&bpf_iflist);
+#ifndef __rtems__
dev = make_dev(&bpf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "bpf");
/* For compatibility */
make_dev_alias(dev, "bpf0");
+#else /* __rtems__ */
+ rv = IMFS_make_generic_node("/dev/bpf", mode, &bpf_imfs_control, NULL);
+ BSD_ASSERT(rv == 0);
+#endif /* __rtems__ */
/* Register interface departure handler */
bpf_ifdetach_cookie = EVENTHANDLER_REGISTER(
@@ -2735,7 +3013,9 @@ bpfstats_fill_xbpf(struct xbpf_d *d, struct bpf_d *bd)
d->bd_hdrcmplt = bd->bd_hdrcmplt;
d->bd_direction = bd->bd_direction;
d->bd_feedback = bd->bd_feedback;
+#ifndef __rtems__
d->bd_async = bd->bd_async;
+#endif /* __rtems__ */
d->bd_rcount = bd->bd_rcount;
d->bd_dcount = bd->bd_dcount;
d->bd_fcount = bd->bd_fcount;
diff --git a/freebsd/sys/net/bpfdesc.h b/freebsd/sys/net/bpfdesc.h
index 496f0b3..60ed11f 100644
--- a/freebsd/sys/net/bpfdesc.h
+++ b/freebsd/sys/net/bpfdesc.h
@@ -85,7 +85,9 @@ struct bpf_d {
int bd_direction; /* select packet direction */
int bd_tstamp; /* select time stamping function */
int bd_feedback; /* true to feed back sent packets */
+#ifndef __rtems__
int bd_async; /* non-zero if packet reception should generate signal */
+#endif /* __rtems__ */
int bd_sig; /* signal to send upon packet reception */
struct sigio * bd_sigio; /* information for async I/O */
struct selinfo bd_sel; /* bsd select info */
@@ -112,8 +114,13 @@ struct bpf_d {
#define BPFD_UNLOCK(bd) mtx_unlock(&(bd)->bd_lock)
#define BPFD_LOCK_ASSERT(bd) mtx_assert(&(bd)->bd_lock, MA_OWNED)
+#ifndef __rtems__
#define BPF_PID_REFRESH(bd, td) (bd)->bd_pid = (td)->td_proc->p_pid
#define BPF_PID_REFRESH_CUR(bd) (bd)->bd_pid = curthread->td_proc->p_pid
+#else /* __rtems__ */
+#define BPF_PID_REFRESH(bd, td) do { } while (0)
+#define BPF_PID_REFRESH_CUR(bd) do { } while (0)
+#endif /* __rtems__ */
#define BPF_LOCK() mtx_lock(&bpf_mtx)
#define BPF_UNLOCK() mtx_unlock(&bpf_mtx)
@@ -129,7 +136,9 @@ struct xbpf_d {
int bd_hdrcmplt;
int bd_direction;
int bd_feedback;
+#ifndef __rtems__
int bd_async;
+#endif /* __rtems__ */
u_int64_t bd_rcount;
u_int64_t bd_dcount;
u_int64_t bd_fcount;
diff --git a/freebsd/usr.bin/netstat/bpf.c b/freebsd/usr.bin/netstat/bpf.c
index b429ed6..50e12fa 100644
--- a/freebsd/usr.bin/netstat/bpf.c
+++ b/freebsd/usr.bin/netstat/bpf.c
@@ -89,7 +89,9 @@ bpf_flags(struct xbpf_d *bd, char *flagbuf)
*flagbuf++ = (bd->bd_direction == BPF_D_IN) ? '-' :
((bd->bd_direction == BPF_D_OUT) ? 'o' : 's');
*flagbuf++ = bd->bd_feedback ? 'b' : '-';
+#ifndef __rtems__
*flagbuf++ = bd->bd_async ? 'a' : '-';
+#endif /* __rtems__ */
*flagbuf++ = bd->bd_locked ? 'l' : '-';
*flagbuf++ = '\0';
}
diff --git a/libbsd.txt b/libbsd.txt
index a428573..2831a63 100644
--- a/libbsd.txt
+++ b/libbsd.txt
@@ -109,6 +109,8 @@ the current Git submodule commit is this
* <sys/param.h>: Update Newlib to use a MSIZE of 256.
+* BPF(4): Add support for zero-copy buffers.
+
[listing]
----
/* sysinit section? */
diff --git a/rtemsbsd/include/rtems/bsd/local/opt_bpf.h b/rtemsbsd/include/rtems/bsd/local/opt_bpf.h
index e69de29..77a5d9e 100644
--- a/rtemsbsd/include/rtems/bsd/local/opt_bpf.h
+++ b/rtemsbsd/include/rtems/bsd/local/opt_bpf.h
@@ -0,0 +1 @@
+#define DEV_BPF 1
More information about the vc
mailing list