git: 44aae623ab85 - main - Add ETHER_ALIGN support to ng_device(4).

From: Emmanuel Vadot <manu_at_FreeBSD.org>
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