svn commit: r277123 - projects/ifnet/sys/netgraph
Gleb Smirnoff
glebius at FreeBSD.org
Tue Jan 13 09:05:50 UTC 2015
Author: glebius
Date: Tue Jan 13 09:05:49 2015
New Revision: 277123
URL: https://svnweb.freebsd.org/changeset/base/277123
Log:
Convert ng_iface(4) to new ifnet API.
Since this interface type is somewhat special, it still includes
if_var.h. All what ng_iface needs to know is if_transmit() macro
and access to if_index, which normal drivers shouldn't need. It
is lesser evil to make ng_iface(4) aware of ifnet structure,
rather than provide access to these fields to all drivers. Might
be rethought however.
Committed via: ng0
Sponsored by: Nginx, Inc.
Modified:
projects/ifnet/sys/netgraph/ng_iface.c
Modified: projects/ifnet/sys/netgraph/ng_iface.c
==============================================================================
--- projects/ifnet/sys/netgraph/ng_iface.c Tue Jan 13 09:02:06 2015 (r277122)
+++ projects/ifnet/sys/netgraph/ng_iface.c Tue Jan 13 09:05:49 2015 (r277123)
@@ -69,10 +69,10 @@
#include <sys/syslog.h>
#include <sys/libkern.h>
+#include <net/bpf.h>
#include <net/if.h>
-#include <net/if_var.h>
+#include <net/if_var.h> /* XXXGL: for if_transmit() and if_index. */
#include <net/if_types.h>
-#include <net/bpf.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/vnet.h>
@@ -116,16 +116,13 @@ struct ng_iface_private {
typedef struct ng_iface_private *priv_p;
/* Interface methods */
-static void ng_iface_start(struct ifnet *ifp);
-static int ng_iface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
-static int ng_iface_output(struct ifnet *ifp, struct mbuf *m0,
+static int ng_iface_transmit(if_t, struct mbuf *);
+static int ng_iface_ioctl(if_t, u_long cmd, caddr_t data);
+static int ng_iface_output(if_t, struct mbuf *m0,
const struct sockaddr *dst, struct route *ro);
-static void ng_iface_bpftap(struct ifnet *ifp,
- struct mbuf *m, sa_family_t family);
-static int ng_iface_send(struct ifnet *ifp, struct mbuf *m,
- sa_family_t sa);
+static int ng_iface_send(if_t, struct mbuf *m, sa_family_t sa);
#ifdef DEBUG
-static void ng_iface_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data);
+static void ng_iface_print_ioctl(if_t, int cmd, caddr_t data);
#endif
/* Netgraph methods */
@@ -194,6 +191,19 @@ NETGRAPH_INIT(iface, &typestruct);
static VNET_DEFINE(struct unrhdr *, ng_iface_unit);
#define V_ng_iface_unit VNET(ng_iface_unit)
+static struct ifdriver ng_ifdrv = {
+ .ifdrv_ops = {
+ .ifop_origin = IFOP_ORIGIN_DRIVER,
+ .ifop_output = ng_iface_output,
+ .ifop_transmit = ng_iface_transmit,
+ .ifop_ioctl = ng_iface_ioctl,
+ },
+ .ifdrv_name = NG_IFACE_IFACE_NAME,
+ .ifdrv_type = IFT_PROPVIRTUAL,
+ .ifdrv_dlt = DLT_NULL,
+ .ifdrv_dlt_hdrlen = sizeof(uint32_t),
+};
+
/************************************************************************
HELPER STUFF
************************************************************************/
@@ -264,7 +274,7 @@ get_iffam_from_name(const char *name)
* Process an ioctl for the virtual interface
*/
static int
-ng_iface_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+ng_iface_ioctl(if_t ifp, u_long command, caddr_t data)
{
struct ifreq *const ifr = (struct ifreq *) data;
int error = 0;
@@ -276,29 +286,11 @@ ng_iface_ioctl(struct ifnet *ifp, u_long
/* These two are mostly handled at a higher layer */
case SIOCSIFADDR:
- ifp->if_flags |= IFF_UP;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE);
+ if_addflags(ifp, IF_FLAGS, IFF_UP);
break;
case SIOCGIFADDR:
break;
-
- /* Set flags */
case SIOCSIFFLAGS:
- /*
- * If the interface is marked up and stopped, then start it.
- * If it is marked down and running, then stop it.
- */
- if (ifr->ifr_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE);
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING |
- IFF_DRV_OACTIVE);
- }
break;
/* Set the interface MTU */
@@ -307,7 +299,7 @@ ng_iface_ioctl(struct ifnet *ifp, u_long
|| ifr->ifr_mtu < NG_IFACE_MTU_MIN)
error = EINVAL;
else
- ifp->if_mtu = ifr->ifr_mtu;
+ if_set(ifp, IF_MTU, ifr->ifr_mtu);
break;
/* Stuff that's not supported */
@@ -333,16 +325,14 @@ ng_iface_ioctl(struct ifnet *ifp, u_long
*/
static int
-ng_iface_output(struct ifnet *ifp, struct mbuf *m,
- const struct sockaddr *dst, struct route *ro)
+ng_iface_output(if_t ifp, struct mbuf *m, const struct sockaddr *dst,
+ struct route *ro)
{
struct m_tag *mtag;
uint32_t af;
- int error;
/* Check interface flags */
- if (!((ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING))) {
+ if ((if_get(ifp, IF_FLAGS) & IFF_UP) == 0) {
m_freem(m);
return (ENETDOWN);
}
@@ -350,19 +340,18 @@ ng_iface_output(struct ifnet *ifp, struc
/* Protect from deadly infinite recursion. */
mtag = NULL;
while ((mtag = m_tag_locate(m, MTAG_NGIF, MTAG_NGIF_CALLED, mtag))) {
- if (*(struct ifnet **)(mtag + 1) == ifp) {
- log(LOG_NOTICE, "Loop detected on %s\n", ifp->if_xname);
+ if (*(if_t *)(mtag + 1) == ifp) {
+ log(LOG_NOTICE, "Loop detected on %s\n", if_name(ifp));
m_freem(m);
return (EDEADLK);
}
}
- mtag = m_tag_alloc(MTAG_NGIF, MTAG_NGIF_CALLED, sizeof(struct ifnet *),
- M_NOWAIT);
+ mtag = m_tag_alloc(MTAG_NGIF, MTAG_NGIF_CALLED, sizeof(if_t), M_NOWAIT);
if (mtag == NULL) {
m_freem(m);
return (ENOMEM);
}
- *(struct ifnet **)(mtag + 1) = ifp;
+ *(if_t *)(mtag + 1) = ifp;
m_tag_prepend(m, mtag);
/* BPF writes need to be handled specially. */
@@ -371,56 +360,31 @@ ng_iface_output(struct ifnet *ifp, struc
else
af = dst->sa_family;
- /* Berkeley packet filter */
- ng_iface_bpftap(ifp, m, af);
-
- if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
- M_PREPEND(m, sizeof(sa_family_t), M_NOWAIT);
- if (m == NULL) {
- if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
- return (ENOBUFS);
- }
- *(sa_family_t *)m->m_data = af;
- error = (ifp->if_transmit)(ifp, m);
- } else
- error = ng_iface_send(ifp, m, af);
+ M_PREPEND(m, sizeof(sa_family_t), M_NOWAIT);
+ if (m == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
+ return (ENOBUFS);
+ }
+ *(sa_family_t *)m->m_data = af;
- return (error);
+ return (if_transmit(ifp, m));
}
/*
* Start method is used only when ALTQ is enabled.
*/
-static void
-ng_iface_start(struct ifnet *ifp)
+static int
+ng_iface_transmit(if_t ifp, struct mbuf *m)
{
- struct mbuf *m;
- sa_family_t sa;
+ sa_family_t af;
- KASSERT(ALTQ_IS_ENABLED(&ifp->if_snd), ("%s without ALTQ", __func__));
+ af = *mtod(m, sa_family_t *);
+ KASSERT(af != AF_UNSPEC, ("%s: af = AF_UNSPEC", __func__));
+ m_adj(m, sizeof(sa_family_t));
- for(;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- sa = *mtod(m, sa_family_t *);
- m_adj(m, sizeof(sa_family_t));
- ng_iface_send(ifp, m, sa);
- }
-}
+ if_mtap(ifp, m, &af, sizeof(af));
-/*
- * Flash a packet by the BPF (requires prepending 4 byte AF header)
- * Note the phoney mbuf; this is OK because BPF treats it read-only.
- */
-static void
-ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, sa_family_t family)
-{
- KASSERT(family != AF_UNSPEC, ("%s: family=AF_UNSPEC", __func__));
- if (bpf_peers_present(ifp->if_bpf)) {
- int32_t family4 = (int32_t)family;
- bpf_mtap2(ifp->if_bpf, &family4, sizeof(family4), m);
- }
+ return (ng_iface_send(ifp, m, af));
}
/*
@@ -429,9 +393,9 @@ ng_iface_bpftap(struct ifnet *ifp, struc
* ng_iface_output().
*/
static int
-ng_iface_send(struct ifnet *ifp, struct mbuf *m, sa_family_t sa)
+ng_iface_send(if_t ifp, struct mbuf *m, sa_family_t sa)
{
- const priv_p priv = (priv_p) ifp->if_softc;
+ const priv_p priv = if_getsoftc(ifp, IF_DRIVER_SOFTC);
const iffam_p iffam = get_iffam_from_af(sa);
int error;
int len;
@@ -439,7 +403,7 @@ ng_iface_send(struct ifnet *ifp, struct
/* Check address family to determine hook (if known) */
if (iffam == NULL) {
m_freem(m);
- log(LOG_WARNING, "%s: can't handle af%d\n", ifp->if_xname, sa);
+ log(LOG_WARNING, "%s: can't handle af%d\n", if_name(ifp), sa);
return (EAFNOSUPPORT);
}
@@ -455,7 +419,8 @@ ng_iface_send(struct ifnet *ifp, struct
if (error == 0) {
if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- }
+ } else
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return (error);
}
@@ -466,7 +431,7 @@ ng_iface_send(struct ifnet *ifp, struct
*/
static void
-ng_iface_print_ioctl(struct ifnet *ifp, int command, caddr_t data)
+ng_iface_print_ioctl(if_t ifp, int command, caddr_t data)
{
char *str;
@@ -487,7 +452,7 @@ ng_iface_print_ioctl(struct ifnet *ifp,
str = "IO??";
}
log(LOG_DEBUG, "%s: %s('%c', %d, char[%d])\n",
- ifp->if_xname,
+ if_name(ifp),
str,
IOCGROUP(command),
command & 0xff,
@@ -505,53 +470,28 @@ ng_iface_print_ioctl(struct ifnet *ifp,
static int
ng_iface_constructor(node_p node)
{
- struct ifnet *ifp;
+ struct if_attach_args ifat = {
+ .ifat_version = IF_ATTACH_VERSION,
+ .ifat_drv = &ng_ifdrv,
+ .ifat_mtu = NG_IFACE_MTU_DEFAULT,
+ .ifat_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_NOARP |
+ IFF_MULTICAST,
+ .ifat_baudrate = 64000, /* XXX */
+ };
priv_p priv;
- /* Allocate node and interface private structures */
priv = malloc(sizeof(*priv), M_NETGRAPH_IFACE, M_WAITOK | M_ZERO);
- ifp = if_alloc(IFT_PROPVIRTUAL);
- if (ifp == NULL) {
- free(priv, M_NETGRAPH_IFACE);
- return (ENOMEM);
- }
-
- /* Link them together */
- ifp->if_softc = priv;
- priv->ifp = ifp;
-
- /* Get an interface unit number */
- priv->unit = alloc_unr(V_ng_iface_unit);
-
- /* Link together node and private info */
NG_NODE_SET_PRIVATE(node, priv);
priv->node = node;
-
- /* Initialize interface structure */
- if_initname(ifp, NG_IFACE_IFACE_NAME, priv->unit);
- ifp->if_output = ng_iface_output;
- ifp->if_start = ng_iface_start;
- ifp->if_ioctl = ng_iface_ioctl;
- ifp->if_mtu = NG_IFACE_MTU_DEFAULT;
- ifp->if_flags = (IFF_SIMPLEX|IFF_POINTOPOINT|IFF_NOARP|IFF_MULTICAST);
- ifp->if_type = IFT_PROPVIRTUAL; /* XXX */
- ifp->if_addrlen = 0; /* XXX */
- ifp->if_hdrlen = 0; /* XXX */
- ifp->if_baudrate = 64000; /* XXX */
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
+ ifat.ifat_softc = priv;
+ ifat.ifat_dunit = priv->unit = alloc_unr(V_ng_iface_unit);
+ priv->ifp = if_attach(&ifat);
/* Give this node the same name as the interface (if possible) */
- if (ng_name_node(node, ifp->if_xname) != 0)
+ if (ng_name_node(node, if_name(priv->ifp)) != 0)
log(LOG_WARNING, "%s: can't acquire netgraph name\n",
- ifp->if_xname);
-
- /* Attach the interface */
- if_attach(ifp);
- bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
+ if_name(priv->ifp));
- /* Done */
return (0);
}
@@ -582,7 +522,7 @@ static int
ng_iface_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
const priv_p priv = NG_NODE_PRIVATE(node);
- struct ifnet *const ifp = priv->ifp;
+ const if_t ifp = priv->ifp;
struct ng_mesg *resp = NULL;
int error = 0;
struct ng_mesg *msg;
@@ -597,7 +537,7 @@ ng_iface_rcvmsg(node_p node, item_p item
error = ENOMEM;
break;
}
- strlcpy(resp->data, ifp->if_xname, IFNAMSIZ);
+ strlcpy(resp->data, if_name(ifp), IFNAMSIZ);
break;
case NGM_IFACE_POINT2POINT:
@@ -605,18 +545,18 @@ ng_iface_rcvmsg(node_p node, item_p item
{
/* Deny request if interface is UP */
- if ((ifp->if_flags & IFF_UP) != 0)
+ if ((if_get(ifp, IF_FLAGS) & IFF_UP) != 0)
return (EBUSY);
/* Change flags */
switch (msg->header.cmd) {
case NGM_IFACE_POINT2POINT:
- ifp->if_flags |= IFF_POINTOPOINT;
- ifp->if_flags &= ~IFF_BROADCAST;
+ if_addflags(ifp, IF_FLAGS, IFF_POINTOPOINT);
+ if_clrflags(ifp, IF_FLAGS, IFF_BROADCAST);
break;
case NGM_IFACE_BROADCAST:
- ifp->if_flags &= ~IFF_POINTOPOINT;
- ifp->if_flags |= IFF_BROADCAST;
+ if_clrflags(ifp, IF_FLAGS, IFF_POINTOPOINT);
+ if_addflags(ifp, IF_FLAGS, IFF_BROADCAST);
break;
}
break;
@@ -628,7 +568,7 @@ ng_iface_rcvmsg(node_p node, item_p item
error = ENOMEM;
break;
}
- *((uint32_t *)resp->data) = priv->ifp->if_index;
+ *((uint32_t *)resp->data) = ifp->if_index;
break;
default:
@@ -665,8 +605,9 @@ ng_iface_rcvdata(hook_p hook, item_p ite
{
const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
const iffam_p iffam = get_iffam_from_hook(priv, hook);
- struct ifnet *const ifp = priv->ifp;
+ const if_t ifp = priv->ifp;
struct mbuf *m;
+ sa_family_t af;
int isr;
NGI_GET_M(item, m);
@@ -674,7 +615,7 @@ ng_iface_rcvdata(hook_p hook, item_p ite
/* Sanity checks */
KASSERT(iffam != NULL, ("%s: iffam", __func__));
M_ASSERTPKTHDR(m);
- if ((ifp->if_flags & IFF_UP) == 0) {
+ if ((if_get(ifp, IF_FLAGS) & IFF_UP) == 0) {
NG_FREE_M(m);
return (ENETDOWN);
}
@@ -687,7 +628,8 @@ ng_iface_rcvdata(hook_p hook, item_p ite
m->m_pkthdr.rcvif = ifp;
/* Berkeley packet filter */
- ng_iface_bpftap(ifp, m, iffam->family);
+ af = iffam->family;
+ if_mtap(ifp, m, &af, sizeof(af));
/* Send packet */
switch (iffam->family) {
@@ -706,7 +648,7 @@ ng_iface_rcvdata(hook_p hook, item_p ite
return (EAFNOSUPPORT);
}
random_harvest(&(m->m_data), 12, 2, RANDOM_NET_NG);
- M_SETFIB(m, ifp->if_fib);
+ M_SETFIB(m, if_get(ifp, IF_FIB));
netisr_dispatch(isr, m);
return (0);
}
@@ -724,9 +666,7 @@ ng_iface_shutdown(node_p node)
* hence we have to change the current vnet context here.
*/
CURVNET_SET_QUIET(priv->ifp->if_vnet);
- bpfdetach(priv->ifp);
if_detach(priv->ifp);
- if_free(priv->ifp);
CURVNET_RESTORE();
priv->ifp = NULL;
free_unr(V_ng_iface_unit, priv->unit);
More information about the svn-src-projects
mailing list