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