Date: Mon, 12 Jan 2015 16:18:35 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r277076 - projects/ifnet/sys/net Message-ID: <201501121618.t0CGIZSD091593@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501121618.t0CGIZSD091593>