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