diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -4141,6 +4141,7 @@ net/bridgestp.c optional bridge | if_bridge net/ieee8023ad_lacp.c optional lagg net/if.c standard +net/ifq.c standard net/if_bridge.c optional bridge inet | if_bridge inet net/if_clone.c standard net/if_dead.c standard diff --git a/sys/net/ifq.h b/sys/net/ifq.h --- a/sys/net/ifq.h +++ b/sys/net/ifq.h @@ -315,19 +315,25 @@ IFQ_PURGE(ifq); \ } while (0) +#ifdef ALTQ +int drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m); +void drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m_new); +struct mbuf *drbr_peek(struct ifnet *ifp, struct buf_ring *br); +void drbr_flush(struct ifnet *ifp, struct buf_ring *br); +struct mbuf *drbr_dequeue(struct ifnet *ifp, struct buf_ring *br); +void drbr_advance(struct ifnet *ifp, struct buf_ring *br); +struct mbuf *drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br, + int (*func) (struct mbuf *, void *), void *arg); +int drbr_empty(struct ifnet *ifp, struct buf_ring *br); +int drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br); +int drbr_inuse(struct ifnet *ifp, struct buf_ring *br); + +#else /* !ALTQ */ static __inline int drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m) { int error = 0; -#ifdef ALTQ - if (ALTQ_IS_ENABLED(&ifp->if_snd)) { - IFQ_ENQUEUE(&ifp->if_snd, m, error); - if (error) - if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1); - return (error); - } -#endif error = buf_ring_enqueue(br, m); if (error) m_freem(m); @@ -342,35 +348,12 @@ * The top of the list needs to be swapped * for this one. */ -#ifdef ALTQ - if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { - /* - * Peek in altq case dequeued it - * so put it back. - */ - IFQ_DRV_PREPEND(&ifp->if_snd, m_new); - return; - } -#endif buf_ring_putback_sc(br, m_new); } static __inline struct mbuf * drbr_peek(struct ifnet *ifp, struct buf_ring *br) { -#ifdef ALTQ - struct mbuf *m; - if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { - /* - * Pull it off like a dequeue - * since drbr_advance() does nothing - * for altq and drbr_putback() will - * use the old prepend function. - */ - IFQ_DEQUEUE(&ifp->if_snd, m); - return (m); - } -#endif return ((struct mbuf *)buf_ring_peek_clear_sc(br)); } @@ -379,44 +362,19 @@ { struct mbuf *m; -#ifdef ALTQ - if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) - IFQ_PURGE(&ifp->if_snd); -#endif while ((m = (struct mbuf *)buf_ring_dequeue_sc(br)) != NULL) m_freem(m); } -static __inline void -drbr_free(struct buf_ring *br, struct malloc_type *type) -{ - - drbr_flush(NULL, br); - buf_ring_free(br, type); -} - static __inline struct mbuf * drbr_dequeue(struct ifnet *ifp, struct buf_ring *br) { -#ifdef ALTQ - struct mbuf *m; - - if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { - IFQ_DEQUEUE(&ifp->if_snd, m); - return (m); - } -#endif return ((struct mbuf *)buf_ring_dequeue_sc(br)); } static __inline void drbr_advance(struct ifnet *ifp, struct buf_ring *br) { -#ifdef ALTQ - /* Nothing to do here since peek dequeues in altq case */ - if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) - return; -#endif return (buf_ring_advance_sc(br)); } @@ -425,19 +383,6 @@ int (*func) (struct mbuf *, void *), void *arg) { struct mbuf *m; -#ifdef ALTQ - if (ALTQ_IS_ENABLED(&ifp->if_snd)) { - IFQ_LOCK(&ifp->if_snd); - IFQ_POLL_NOLOCK(&ifp->if_snd, m); - if (m != NULL && func(m, arg) == 0) { - IFQ_UNLOCK(&ifp->if_snd); - return (NULL); - } - IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m); - IFQ_UNLOCK(&ifp->if_snd); - return (m); - } -#endif m = (struct mbuf *)buf_ring_peek(br); if (m == NULL || func(m, arg) == 0) return (NULL); @@ -448,32 +393,29 @@ static __inline int drbr_empty(struct ifnet *ifp, struct buf_ring *br) { -#ifdef ALTQ - if (ALTQ_IS_ENABLED(&ifp->if_snd)) - return (IFQ_IS_EMPTY(&ifp->if_snd)); -#endif return (buf_ring_empty(br)); } static __inline int drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br) { -#ifdef ALTQ - if (ALTQ_IS_ENABLED(&ifp->if_snd)) - return (1); -#endif return (!buf_ring_empty(br)); } static __inline int drbr_inuse(struct ifnet *ifp, struct buf_ring *br) { -#ifdef ALTQ - if (ALTQ_IS_ENABLED(&ifp->if_snd)) - return (ifp->if_snd.ifq_len); -#endif return (buf_ring_count(br)); } +#endif /* ALTQ */ + +static __inline void +drbr_free(struct buf_ring *br, struct malloc_type *type) +{ + + drbr_flush(NULL, br); + buf_ring_free(br, type); +} extern int ifqmaxlen; diff --git a/sys/net/ifq.c b/sys/net/ifq.c new file mode 100644 --- /dev/null +++ b/sys/net/ifq.c @@ -0,0 +1,176 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: @(#)if.h 8.1 (Berkeley) 6/10/93 + */ + +#include +#include + +#ifndef ALTQ +#define ALTQ /* Needed for ifq.h prototypes only. */ +#endif + +#include +#include +#include + +int +drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m) +{ + int error = 0; + + if (ALTQ_IS_ENABLED(&ifp->if_snd)) { + IFQ_ENQUEUE(&ifp->if_snd, m, error); + if (error) + if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1); + return (error); + } + error = buf_ring_enqueue(br, m); + if (error) + m_freem(m); + + return (error); +} + +void +drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m_new) +{ + /* + * The top of the list needs to be swapped + * for this one. + */ + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { + /* + * Peek in altq case dequeued it + * so put it back. + */ + IFQ_DRV_PREPEND(&ifp->if_snd, m_new); + return; + } + buf_ring_putback_sc(br, m_new); +} + +struct mbuf * +drbr_peek(struct ifnet *ifp, struct buf_ring *br) +{ + struct mbuf *m; + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { + /* + * Pull it off like a dequeue + * since drbr_advance() does nothing + * for altq and drbr_putback() will + * use the old prepend function. + */ + IFQ_DEQUEUE(&ifp->if_snd, m); + return (m); + } + return ((struct mbuf *)buf_ring_peek_clear_sc(br)); +} + +void +drbr_flush(struct ifnet *ifp, struct buf_ring *br) +{ + struct mbuf *m; + + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) + IFQ_PURGE(&ifp->if_snd); + while ((m = (struct mbuf *)buf_ring_dequeue_sc(br)) != NULL) + m_freem(m); +} + +struct mbuf * +drbr_dequeue(struct ifnet *ifp, struct buf_ring *br) +{ + struct mbuf *m; + + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { + IFQ_DEQUEUE(&ifp->if_snd, m); + return (m); + } + return ((struct mbuf *)buf_ring_dequeue_sc(br)); +} + +void +drbr_advance(struct ifnet *ifp, struct buf_ring *br) +{ + /* Nothing to do here since peek dequeues in altq case */ + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) + return; + return (buf_ring_advance_sc(br)); +} + +struct mbuf * +drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br, + int (*func) (struct mbuf *, void *), void *arg) +{ + struct mbuf *m; + if (ALTQ_IS_ENABLED(&ifp->if_snd)) { + IFQ_LOCK(&ifp->if_snd); + IFQ_POLL_NOLOCK(&ifp->if_snd, m); + if (m != NULL && func(m, arg) == 0) { + IFQ_UNLOCK(&ifp->if_snd); + return (NULL); + } + IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m); + IFQ_UNLOCK(&ifp->if_snd); + return (m); + } + m = (struct mbuf *)buf_ring_peek(br); + if (m == NULL || func(m, arg) == 0) + return (NULL); + + return ((struct mbuf *)buf_ring_dequeue_sc(br)); +} + +int +drbr_empty(struct ifnet *ifp, struct buf_ring *br) +{ + if (ALTQ_IS_ENABLED(&ifp->if_snd)) + return (IFQ_IS_EMPTY(&ifp->if_snd)); + return (buf_ring_empty(br)); +} + +int +drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br) +{ + if (ALTQ_IS_ENABLED(&ifp->if_snd)) + return (1); + return (!buf_ring_empty(br)); +} + +int +drbr_inuse(struct ifnet *ifp, struct buf_ring *br) +{ + if (ALTQ_IS_ENABLED(&ifp->if_snd)) + return (ifp->if_snd.ifq_len); + return (buf_ring_count(br)); +} +