From owner-svn-src-projects@FreeBSD.ORG Mon Jan 12 16:18:37 2015 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 16892244; Mon, 12 Jan 2015 16:18:37 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id EBA9A16B; Mon, 12 Jan 2015 16:18:36 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0CGIagY091598; Mon, 12 Jan 2015 16:18:36 GMT (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0CGIZSD091593; Mon, 12 Jan 2015 16:18:35 GMT (envelope-from glebius@FreeBSD.org) Message-Id: <201501121618.t0CGIZSD091593@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: glebius set sender to glebius@FreeBSD.org using -f From: Gleb Smirnoff Date: Mon, 12 Jan 2015 16:18:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r277076 - projects/ifnet/sys/net X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Jan 2015 16:18:37 -0000 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 /* XXXAO: temporary unconditional include */ - #endif /* !_NET_IF_VAR_H_ */