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