svn commit: r277076 - projects/ifnet/sys/net

Gleb Smirnoff glebius at FreeBSD.org
Mon Jan 12 16:18:37 UTC 2015


Author: glebius
Date: Mon Jan 12 16:18:34 2015
New Revision: 277076
URL: https://svnweb.freebsd.org/changeset/base/277076

Log:
  Say good-bye to ifqueue and ifq.h. In new world order, drivers can opt-in
  for software queue defining ifdrv_maxqlen. It is minimalistic queue
  implemented over mbufq, and should satisfy non-high-end drivers.
  
  Sponsored by:	Nginx, Inc.

Deleted:
  projects/ifnet/sys/net/ifq.h
Modified:
  projects/ifnet/sys/net/if.c
  projects/ifnet/sys/net/if.h
  projects/ifnet/sys/net/if_debug.c
  projects/ifnet/sys/net/if_mib.c
  projects/ifnet/sys/net/if_var.h

Modified: projects/ifnet/sys/net/if.c
==============================================================================
--- projects/ifnet/sys/net/if.c	Mon Jan 12 15:52:08 2015	(r277075)
+++ projects/ifnet/sys/net/if.c	Mon Jan 12 16:18:34 2015	(r277076)
@@ -102,6 +102,7 @@
 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
 
+int	ifqmaxlen = IFQ_MAXLEN;
 SYSCTL_INT(_net_link, OID_AUTO, ifqmaxlen, CTLFLAG_RDTUN,
     &ifqmaxlen, 0, "max send queue size");
 
@@ -173,6 +174,9 @@ static int	if_getgroupmembers(struct ifg
 static void	if_delgroups(struct ifnet *);
 static void	if_attach_internal(struct ifnet *, int);
 static void	if_detach_internal(struct ifnet *, int);
+static struct ifqueue * if_snd_alloc(int);
+static void	if_snd_free(struct ifqueue *);
+static void	if_snd_qflush(if_t);
 
 #ifdef INET6
 /*
@@ -183,7 +187,6 @@ extern void	nd6_setmtu(struct ifnet *);
 #endif
 
 VNET_DEFINE(int, if_index);
-int	ifqmaxlen = IFQ_MAXLEN;
 VNET_DEFINE(struct ifnethead, ifnet);	/* depend on static init XXX */
 VNET_DEFINE(struct ifgrouphead, ifg_head);
 
@@ -456,11 +459,17 @@ ifdriver_bless(struct ifdriver *ifdrv, s
 #undef COPY
 	}
 
-	KASSERT((ifdrv->ifdrv_ops.ifop_transmit == NULL &&
-	    ifdrv->ifdrv_ops.ifop_qflush == NULL) ||   
-            (ifdrv->ifdrv_ops.ifop_transmit != NULL &&
-	    ifdrv->ifdrv_ops.ifop_qflush != NULL),
-            ("transmit and qflush must both either be set or both be NULL"));
+	/*
+	 * If driver has ifdrv_maxqlen defined, then it opts-in
+	 * for * generic software queue, and thus for default
+	 * ifop_qflush.
+	 */
+	if (ifdrv->ifdrv_maxqlen > 0) {
+		KASSERT(ifdrv->ifdrv_ops.ifop_qflush == NULL,
+		    ("%s: fdrv_maxqlen > 0 and ifop_qflush",
+		    ifdrv->ifdrv_name));
+		ifdrv->ifdrv_ops.ifop_qflush = if_snd_qflush;
+	}
 
 	if (ifdrv->ifdrv_ops.ifop_get_counter == NULL)
 		ifdrv->ifdrv_ops.ifop_get_counter = if_get_counter_default;
@@ -543,6 +552,9 @@ if_attach(struct if_attach_args *ifat)
 	} else
 		ifp->if_tsomax = ifdrv->ifdrv_tsomax;
 
+	if (ifdrv->ifdrv_maxqlen > 0)
+		ifp->if_snd = if_snd_alloc(ifdrv->ifdrv_maxqlen);
+
 	IF_ADDR_LOCK_INIT(ifp);
 	IF_AFDATA_LOCK_INIT(ifp);
 	TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp);
@@ -558,8 +570,6 @@ if_attach(struct if_attach_args *ifat)
 	else
 		strlcpy(ifp->if_xname, ifdrv->ifdrv_name, IFNAMSIZ);
 
-	ifq_init(&ifp->if_snd, ifp); /* XXXGL */
-
 	ifindex_alloc(ifp);
 	refcount_init(&ifp->if_refcount, 1);
 
@@ -627,7 +637,8 @@ if_free_internal(struct ifnet *ifp)
 		free(ifp->if_description, M_IFDESCR);
 	IF_AFDATA_DESTROY(ifp);
 	IF_ADDR_LOCK_DESTROY(ifp);
-	ifq_delete(&ifp->if_snd);
+	if (ifp->if_snd)
+		if_snd_free(ifp->if_snd);
 
 	for (int i = 0; i < IFCOUNTERS; i++)
 		counter_u64_free(ifp->if_counters[i]);
@@ -676,28 +687,6 @@ if_rele(struct ifnet *ifp)
 	if_free_internal(ifp);
 }
 
-void
-ifq_init(struct ifaltq *ifq, struct ifnet *ifp)
-{
-	
-	mtx_init(&ifq->ifq_mtx, ifp->if_xname, "if send queue", MTX_DEF);
-
-	if (ifq->ifq_maxlen == 0) 
-		ifq->ifq_maxlen = ifqmaxlen;
-
-	ifq->altq_type = 0;
-	ifq->altq_disc = NULL;
-	ifq->altq_flags &= ALTQF_CANTCHANGE;
-	ifq->altq_tbr  = NULL;
-	ifq->altq_ifp  = ifp;
-}
-
-void
-ifq_delete(struct ifaltq *ifq)
-{
-	mtx_destroy(&ifq->ifq_mtx);
-}
-
 /*
  * Compute the least common TSO limit.
  */
@@ -2251,6 +2240,7 @@ if_unroute(struct ifnet *ifp, int flag, 
 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
 		if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
 			pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
+	if_qflush(ifp);
 
 	if (ifp->if_carp)
 		(*carp_linkstate_p)(ifp);
@@ -2366,32 +2356,6 @@ if_up(struct ifnet *ifp)
 }
 
 /*
- * Flush an interface queue.
- */
-void
-if_qflush(struct ifnet *ifp)
-{
-	struct mbuf *m, *n;
-	struct ifaltq *ifq;
-	
-	ifq = &ifp->if_snd;
-	IFQ_LOCK(ifq);
-#ifdef ALTQ
-	if (ALTQ_IS_ENABLED(ifq))
-		ALTQ_PURGE(ifq);
-#endif
-	n = ifq->ifq_head;
-	while ((m = n) != 0) {
-		n = m->m_nextpkt;
-		m_freem(m);
-	}
-	ifq->ifq_head = 0;
-	ifq->ifq_tail = 0;
-	ifq->ifq_len = 0;
-	IFQ_UNLOCK(ifq);
-}
-
-/*
  * Map interface name to interface structure pointer, with or without
  * returning a reference.
  */
@@ -3685,6 +3649,101 @@ if_foreach_maddr(if_t ifp, ifmaddr_cb_t 
 }
 
 /*
+ * Generic software queue, that many non-high-end drivers use.  For now
+ * it is minimalistic version of classic BSD ifqueue, but we can swap it
+ * to any other implementation later.
+ */
+struct ifqueue {
+	struct mbufq	ifq_mbq;
+	struct mtx	ifq_mtx;
+};
+
+static struct ifqueue *
+if_snd_alloc(int maxlen)
+{
+	struct ifqueue *ifq;
+
+	ifq = malloc(sizeof(struct ifqueue), M_IFNET, M_WAITOK);
+	mbufq_init(&ifq->ifq_mbq, maxlen);
+	mtx_init(&ifq->ifq_mtx, "ifqueue", NULL, MTX_DEF);
+
+	return (ifq);
+}
+
+static void
+if_snd_free(struct ifqueue *ifq)
+{
+
+	mtx_destroy(&ifq->ifq_mtx);
+	free(ifq, M_IFNET);
+}
+
+/*
+ * Flush software interface queue.
+ */
+static void
+if_snd_qflush(if_t ifp)
+{
+	struct ifqueue *ifq;
+	struct mbuf *m, *n;
+	
+	ifq = ifp->if_snd;
+	mtx_lock(&ifq->ifq_mtx);
+	n = mbufq_flush(&ifq->ifq_mbq);
+	mtx_unlock(&ifq->ifq_mtx);
+	while ((m = n) != NULL) {
+		n = m->m_nextpkt;
+		m_freem(m);
+	}
+}
+
+int
+if_snd_len(if_t ifp)
+{
+	struct ifqueue *ifq = ifp->if_snd;
+
+	return (mbufq_len(&ifq->ifq_mbq));
+}
+
+int
+if_snd_enqueue(struct ifnet *ifp, struct mbuf *m)
+{
+	struct ifqueue *ifq = ifp->if_snd;
+	int error;
+
+	mtx_lock(&ifq->ifq_mtx);
+	error = mbufq_enqueue(&ifq->ifq_mbq, m);
+	mtx_unlock(&ifq->ifq_mtx);
+	if (error) {
+		m_freem(m);
+		if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
+	}
+	return (error);
+}
+
+struct mbuf *
+if_snd_dequeue(if_t ifp)
+{
+	struct ifqueue *ifq = ifp->if_snd;
+	struct mbuf *m;
+
+	mtx_lock(&ifq->ifq_mtx);
+	m = mbufq_dequeue(&ifq->ifq_mbq);
+	mtx_unlock(&ifq->ifq_mtx);
+	return (m);
+}
+
+void
+if_snd_prepend(if_t ifp, struct mbuf *m)
+{
+	struct ifqueue *ifq = ifp->if_snd;
+
+	mtx_lock(&ifq->ifq_mtx);
+	mbufq_prepend(&ifq->ifq_mbq, m);
+	mtx_unlock(&ifq->ifq_mtx);
+}
+
+/*
  * Implementation of if ops, that can be called from drivers.
  */
 void

Modified: projects/ifnet/sys/net/if.h
==============================================================================
--- projects/ifnet/sys/net/if.h	Mon Jan 12 15:52:08 2015	(r277075)
+++ projects/ifnet/sys/net/if.h	Mon Jan 12 16:18:34 2015	(r277076)
@@ -655,6 +655,7 @@ struct ifdriver {
 	uint8_t		ifdrv_addrlen;	/* media address length */
 	uint32_t	ifdrv_dlt;	/* from net/bpf.h */
 	uint32_t	ifdrv_dlt_hdrlen;
+	uint32_t	ifdrv_maxqlen;	/* max queue length for if_snd */
 	/*
 	 * Owned by stack.  Drivers shouldn't initialize these!
 	 */
@@ -725,6 +726,14 @@ void	if_foreach_addr(if_t, ifaddr_cb_t, 
 void	if_foreach_maddr(if_t, ifmaddr_cb_t, void *);
 
 /*
+ * Generic software send queue manipulation.
+ */
+int	if_snd_len(if_t);
+int	if_snd_enqueue(if_t, struct mbuf *);
+struct mbuf * if_snd_dequeue(if_t);
+void	if_snd_prepend(if_t, struct mbuf *);
+
+/*
  * Type-enforcing inliners over declared above functions.
  */
 static inline uint64_t

Modified: projects/ifnet/sys/net/if_debug.c
==============================================================================
--- projects/ifnet/sys/net/if_debug.c	Mon Jan 12 15:52:08 2015	(r277075)
+++ projects/ifnet/sys/net/if_debug.c	Mon Jan 12 16:18:34 2015	(r277076)
@@ -71,16 +71,6 @@ if_show_ifnet(struct ifnet *ifp)
 	IF_DB_PRINTF("0x%08x", if_flags);
 	IF_DB_PRINTF("0x%08x", if_capabilities);
 	IF_DB_PRINTF("0x%08x", if_capenable);
-	IF_DB_PRINTF("%p", if_snd.ifq_head);
-	IF_DB_PRINTF("%p", if_snd.ifq_tail);
-	IF_DB_PRINTF("%d", if_snd.ifq_len);
-	IF_DB_PRINTF("%d", if_snd.ifq_maxlen);
-	IF_DB_PRINTF("%p", if_snd.ifq_drv_head);
-	IF_DB_PRINTF("%p", if_snd.ifq_drv_tail);
-	IF_DB_PRINTF("%d", if_snd.ifq_drv_len);
-	IF_DB_PRINTF("%d", if_snd.ifq_drv_maxlen);
-	IF_DB_PRINTF("%d", if_snd.altq_type);
-	IF_DB_PRINTF("%x", if_snd.altq_flags);
 	IF_DB_PRINTF("%u", if_fib);
 #undef IF_DB_PRINTF
 }

Modified: projects/ifnet/sys/net/if_mib.c
==============================================================================
--- projects/ifnet/sys/net/if_mib.c	Mon Jan 12 15:52:08 2015	(r277075)
+++ projects/ifnet/sys/net/if_mib.c	Mon Jan 12 16:18:34 2015	(r277076)
@@ -103,8 +103,8 @@ sysctl_ifdata(SYSCTL_HANDLER_ARGS) /* XX
 		if_data_copy(ifp, &ifmd.ifmd_data);
 
 		ifmd.ifmd_flags = ifp->if_flags;
-		ifmd.ifmd_snd_len = ifp->if_snd.ifq_len;
-		ifmd.ifmd_snd_maxlen = ifp->if_snd.ifq_maxlen;
+		ifmd.ifmd_snd_len = 0;		/* XXXGL */
+		ifmd.ifmd_snd_maxlen = 0;	/* XXXGL */
 		ifmd.ifmd_snd_drops = if_get_counter(ifp, IFCOUNTER_OQDROPS);
 
 		error = SYSCTL_OUT(req, &ifmd, sizeof ifmd);

Modified: projects/ifnet/sys/net/if_var.h
==============================================================================
--- projects/ifnet/sys/net/if_var.h	Mon Jan 12 15:52:08 2015	(r277075)
+++ projects/ifnet/sys/net/if_var.h	Mon Jan 12 16:18:34 2015	(r277076)
@@ -123,7 +123,6 @@ struct ifnet {
 	time_t		if_epoch;	/* uptime at attach or stat reset */
 	struct timeval	if_lastchange;	/* time of last administrative change */
 
-	struct  ifaltq if_snd;		/* output queue (includes altq) */
 	struct	task if_linktask;	/* task for link change events */
 
 	/* Addresses of different protocol families assigned to this if. */
@@ -149,6 +148,7 @@ struct ifnet {
 
 	/* Additional features hung off the interface. */
 	u_int	if_fib;			/* interface FIB */
+	struct	ifqueue *if_snd;	/* software send queue */
 	struct	vnet *if_vnet;		/* pointer to network stack instance */
 	struct	vnet *if_home_vnet;	/* where this ifnet originates from */
 	struct  ifvlantrunk *if_vlantrunk; /* pointer to 802.1q data */
@@ -454,6 +454,14 @@ if_transmit(if_t ifp, struct mbuf *m)
 	return (ifp->if_ops->ifop_transmit(ifp, m));
 }
 
+static inline void
+if_qflush(if_t ifp)
+{
+
+	if (ifp->if_ops->ifop_qflush != NULL)
+		ifp->if_ops->ifop_qflush(ifp);
+}
+
 static inline int
 if_output(if_t ifp, struct mbuf *m, const struct sockaddr *dst,
     struct route *ro)
@@ -518,7 +526,4 @@ if_addrlen(const if_t ifp)
 	return (ifp->if_drv->ifdrv_addrlen);
 }
 #endif /* _KERNEL */
-
-#include <net/ifq.h>	/* XXXAO: temporary unconditional include */
-
 #endif /* !_NET_IF_VAR_H_ */


More information about the svn-src-projects mailing list