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
(cherry picked from commit 44aae623ab
)
This commit is contained in:
parent
1e2a0cef6b
commit
1a86aab86a
@ -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
|
||||
|
@ -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);
|
||||
|
@ -39,6 +39,7 @@
|
||||
/* Netgraph control messages */
|
||||
enum {
|
||||
NGM_DEVICE_GET_DEVNAME,
|
||||
NGM_DEVICE_ETHERALIGN,
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
Loading…
Reference in New Issue
Block a user