git: 44aae623ab85 - main - Add ETHER_ALIGN support to ng_device(4).
Date: Sun, 14 Nov 2021 12:39:21 UTC
The branch main has been updated by manu:
URL: https://cgit.FreeBSD.org/src/commit/?id=44aae623ab858387301358b9b054cd229ce41068
commit 44aae623ab858387301358b9b054cd229ce41068
Author: Ian Lepore <ian@FreeBSD.org>
AuthorDate: 2021-11-09 14:34:06 +0000
Commit: Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2021-11-14 12:37:41 +0000
Add ETHER_ALIGN support to ng_device(4).
This adds a new ng_device command, NGM_DEVICE_ETHERALIGN, which has no
associated args. After the command arrives, the device begins adjusting all
packets sent out its hook to have ETHER_ALIGN bytes of padding at the
beginning of the packet. The ETHER_ALIGN padding is added only when
running on an architecture that requires strict alignment of IP headers
(based on the __NO_STRICT_ALIGNMENT macro, which is only #define'd on
x86 as of this writing).
This also adds ascii <-> binary command translation to ng_device, both for
the existing NGM_DEVICE_GET_DEVNAME and the new ETHERALIGN command.
This also gives a name to every ng_device node when it is constructed, using
the cdev device name (ngd0, ngd1, etc). This makes it easier to address
command msgs to the device using ngctl(8).
Reviewed by: donner, ray, adrian
Differential Revision: https://reviews.freebsd.org/D32905
MFC after: 1 week
---
share/man/man4/ng_device.4 | 16 ++++++++++++----
sys/netgraph/ng_device.c | 39 ++++++++++++++++++++++++++++++++++++++-
sys/netgraph/ng_device.h | 1 +
3 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/share/man/man4/ng_device.4 b/share/man/man4/ng_device.4
index 5374e646dbef..8b1ee32b8536 100644
--- a/share/man/man4/ng_device.4
+++ b/share/man/man4/ng_device.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 19, 2004
+.Dd November 8, 2021
.Dt NG_DEVICE 4
.Os
.Sh NAME
@@ -48,7 +48,7 @@ etc.
.Pp
The first node is created as
.Pa /dev/ngd0 ,
-all subsequent nodes
+subsequent nodes are
.Pa /dev/ngd1 , /dev/ngd2 ,
etc.
.Sh HOOKS
@@ -64,10 +64,18 @@ will be forwarded to the hook.
.Sh CONTROL MESSAGES
The
.Nm device
-node supports one non-generic control message:
+node supports the generic control messages, plus the following:
.Bl -tag -width 3n
.It Dv NGM_DEVICE_GET_DEVNAME
-Returns device name corresponding to a node.
+Returns the device name corresponding to the node.
+.It Dv NGM_DEVICE_ETHERALIGN
+Apply the system ETHER_ALIGN offset to mbufs sent out the node's hook,
+if running on an architecture that requires strict alignment.
+Use this option when the data being injected via the device node ultimately
+ends up being fed into the protocol stack as ethernet packets (e.g., via
+an
+.Xr ng_eiface 4
+node).
.El
.\" Additionally, the node accepts
.\" .Xr ioctl 2 Ns s
diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c
index ff62f7f44a35..032867ee4bf6 100644
--- a/sys/netgraph/ng_device.c
+++ b/sys/netgraph/ng_device.c
@@ -50,10 +50,12 @@
#include <sys/epoch.h>
#include <sys/queue.h>
#include <sys/socket.h>
+#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/uio.h>
#include <sys/vnode.h>
+#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <netinet/in.h>
@@ -63,6 +65,7 @@
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_device.h>
+#include <netgraph/ng_parse.h>
#define ERROUT(x) do { error = (x); goto done; } while (0)
@@ -75,6 +78,25 @@ static ng_newhook_t ng_device_newhook;
static ng_rcvdata_t ng_device_rcvdata;
static ng_disconnect_t ng_device_disconnect;
+/* List of commands and how to convert arguments to/from ASCII. */
+static const struct ng_cmdlist ng_device_cmds[] = {
+ {
+ NGM_DEVICE_COOKIE,
+ NGM_DEVICE_GET_DEVNAME,
+ "getdevname",
+ NULL,
+ &ng_parse_string_type
+ },
+ {
+ NGM_DEVICE_COOKIE,
+ NGM_DEVICE_ETHERALIGN,
+ "etheralign",
+ NULL,
+ NULL
+ },
+ { 0 }
+};
+
/* Netgraph type */
static struct ng_type ngd_typestruct = {
.version = NG_ABI_VERSION,
@@ -86,6 +108,7 @@ static struct ng_type ngd_typestruct = {
.newhook = ng_device_newhook,
.rcvdata = ng_device_rcvdata,
.disconnect = ng_device_disconnect,
+ .cmdlist = ng_device_cmds,
};
NETGRAPH_INIT(device, &ngd_typestruct);
@@ -97,6 +120,7 @@ struct ngd_private {
struct cdev *ngddev;
struct mtx ngd_mtx;
int unit;
+ int ether_align;
uint16_t flags;
#define NGDF_OPEN 0x0001
#define NGDF_RWAIT 0x0002
@@ -194,6 +218,11 @@ ng_device_constructor(node_p node)
/* XXX: race here? */
priv->ngddev->si_drv1 = priv;
+ /* Give this node the same name as the device (if possible). */
+ if (ng_name_node(node, devtoname(priv->ngddev)) != 0)
+ log(LOG_WARNING, "%s: can't acquire netgraph name\n",
+ devtoname(priv->ngddev));
+
return(0);
}
@@ -226,6 +255,13 @@ ng_device_rcvmsg(node_p node, item_p item, hook_p lasthook)
strlcpy((char *)resp->data, dn, strlen(dn) + 1);
break;
+ case NGM_DEVICE_ETHERALIGN:
+ /* Use ETHER_ALIGN on arches that require it. */
+#ifndef __NO_STRICT_ALIGNMENT
+ priv->ether_align = ETHER_ALIGN;
+#endif
+ break;
+
default:
error = EINVAL;
break;
@@ -468,7 +504,8 @@ ngdwrite(struct cdev *dev, struct uio *uio, int flag)
if (uio->uio_resid < 0 || uio->uio_resid > IP_MAXPACKET)
return (EIO);
- if ((m = m_uiotombuf(uio, M_NOWAIT, 0, 0, M_PKTHDR)) == NULL)
+ m = m_uiotombuf(uio, M_NOWAIT, 0, priv->ether_align, M_PKTHDR);
+ if (m == NULL)
return (ENOBUFS);
NET_EPOCH_ENTER(et);
diff --git a/sys/netgraph/ng_device.h b/sys/netgraph/ng_device.h
index 00877b7452b3..e8f8bfd62687 100644
--- a/sys/netgraph/ng_device.h
+++ b/sys/netgraph/ng_device.h
@@ -39,6 +39,7 @@
/* Netgraph control messages */
enum {
NGM_DEVICE_GET_DEVNAME,
+ NGM_DEVICE_ETHERALIGN,
};
#if 0