Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys PR kern/53562
details: https://anonhg.NetBSD.org/src/rev/0b27a3e4f018
branches: trunk
changeset: 995202:0b27a3e4f018
user: rin <rin%NetBSD.org@localhost>
date: Wed Dec 12 01:46:47 2018 +0000
description:
PR kern/53562
Handle TX offload in software when a packet is sent via
bridge_output(). We can send it as is in the following
exceptional cases:
For unicast:
(1) When the destination interface is the same as source.
(2) When the destination supports all TX offload options
specified in a packet.
For multicast/broadcast:
(3) When all the members of the bridge support the specified
TX offload options.
For (3), add sc_csum_flags_tx flag to bridge softc, which is
logical AND b/w capabilities of TX offload options in member
interface (ifp->if_csum_flags_tx). The flag is updated when a
member is (i) added to or (ii) removed from a bridge, or (iii)
if_csum_flags_tx flag of a member interface is manipulated via
ifconfig(8).
Turn on M_CSUM_TSOv[46] bit in ifp->if_csum_flags_tx flag when
TSO[46] is enabled for that interface.
OK msaitoh thorpej
diffstat:
sys/net/if.c | 58 ++++++++------
sys/net/if_bridge.c | 134 +++++++++++++++++++++++++++++++----
sys/net/if_bridgevar.h | 5 +-
sys/rump/librump/rumpnet/net_stub.c | 5 +-
4 files changed, 155 insertions(+), 47 deletions(-)
diffs (truncated from 381 to 300 lines):
diff -r 62d3bb0f8e71 -r 0b27a3e4f018 sys/net/if.c
--- a/sys/net/if.c Wed Dec 12 01:40:20 2018 +0000
+++ b/sys/net/if.c Wed Dec 12 01:46:47 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.441 2018/11/15 10:23:56 maxv Exp $ */
+/* $NetBSD: if.c,v 1.442 2018/12/12 01:46:47 rin Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.441 2018/11/15 10:23:56 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.442 2018/12/12 01:46:47 rin Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -149,6 +149,11 @@
#include "fddi.h"
#include "token.h"
+#include "bridge.h"
+#if NBRIDGE > 0
+#include <net/if_bridgevar.h>
+#endif
+
#include "carp.h"
#if NCARP > 0
#include <netinet/ip_carp.h>
@@ -2909,40 +2914,41 @@
/* Pre-compute the checksum flags mask. */
ifp->if_csum_flags_tx = 0;
ifp->if_csum_flags_rx = 0;
- if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) {
+ if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx)
ifp->if_csum_flags_tx |= M_CSUM_IPv4;
- }
- if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) {
+ if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx)
ifp->if_csum_flags_rx |= M_CSUM_IPv4;
- }
-
- if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) {
+
+ if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx)
ifp->if_csum_flags_tx |= M_CSUM_TCPv4;
- }
- if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) {
+ if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx)
ifp->if_csum_flags_rx |= M_CSUM_TCPv4;
- }
-
- if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) {
+
+ if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx)
ifp->if_csum_flags_tx |= M_CSUM_UDPv4;
- }
- if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) {
+ if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx)
ifp->if_csum_flags_rx |= M_CSUM_UDPv4;
- }
-
- if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx) {
+
+ if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx)
ifp->if_csum_flags_tx |= M_CSUM_TCPv6;
- }
- if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) {
+ if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx)
ifp->if_csum_flags_rx |= M_CSUM_TCPv6;
- }
-
- if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx) {
+
+ if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx)
ifp->if_csum_flags_tx |= M_CSUM_UDPv6;
- }
- if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) {
+ if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx)
ifp->if_csum_flags_rx |= M_CSUM_UDPv6;
- }
+
+ if (ifp->if_capenable & IFCAP_TSOv4)
+ ifp->if_csum_flags_tx |= M_CSUM_TSOv4;
+ if (ifp->if_capenable & IFCAP_TSOv6)
+ ifp->if_csum_flags_tx |= M_CSUM_TSOv6;
+
+#if NBRIDGE > 0
+ if (ifp->if_bridge != NULL)
+ bridge_calc_csum_flags(ifp->if_bridge);
+#endif
+
if (ifp->if_flags & IFF_UP)
return ENETRESET;
return 0;
diff -r 62d3bb0f8e71 -r 0b27a3e4f018 sys/net/if_bridge.c
--- a/sys/net/if_bridge.c Wed Dec 12 01:40:20 2018 +0000
+++ b/sys/net/if_bridge.c Wed Dec 12 01:46:47 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bridge.c,v 1.160 2018/11/09 06:44:31 ozaki-r Exp $ */
+/* $NetBSD: if_bridge.c,v 1.161 2018/12/12 01:46:47 rin Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.160 2018/11/09 06:44:31 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.161 2018/12/12 01:46:47 rin Exp $");
#ifdef _KERNEL_OPT
#include "opt_bridge_ipf.h"
@@ -112,6 +112,7 @@
#include <net/if_ether.h>
#include <net/if_bridgevar.h>
+#include <net/ether_sw_offload.h>
#if defined(BRIDGE_IPF)
/* Used for bridge_ip[6]_checkbasic */
@@ -123,7 +124,6 @@
#include <netinet/ip6.h>
#include <netinet6/in6_var.h>
-#include <netinet6/ip6_var.h>
#include <netinet6/ip6_private.h> /* XXX */
#endif /* BRIDGE_IPF */
@@ -750,6 +750,30 @@
BRIDGE_LOCK(sc);
}
+/*
+ * bridge_calc_csum_flags:
+ *
+ * Calculate logical and b/w csum flags each member interface supports.
+ */
+void
+bridge_calc_csum_flags(struct bridge_softc *sc)
+{
+ struct bridge_iflist *bif;
+ struct ifnet *ifs;
+ int flags = ~0;
+
+ BRIDGE_LOCK(sc);
+ BRIDGE_IFLIST_READER_FOREACH(bif, sc) {
+ ifs = bif->bif_ifp;
+ flags &= ifs->if_csum_flags_tx;
+ }
+ sc->sc_csum_flags_tx = flags;
+ BRIDGE_UNLOCK(sc);
+#ifdef DEBUG
+ printf("%s: 0x%x\n", __func__, flags);
+#endif
+}
+
static int
bridge_ioctl_add(struct bridge_softc *sc, void *arg)
{
@@ -827,12 +851,14 @@
BRIDGE_UNLOCK(sc);
+ bridge_calc_csum_flags(sc);
+
if (sc->sc_if.if_flags & IFF_RUNNING)
bstp_initialization(sc);
else
bstp_stop(sc);
- out:
+out:
if_put(ifs, &psref);
if (error) {
if (bif != NULL)
@@ -890,6 +916,7 @@
}
bridge_rtdelete(sc, ifs);
+ bridge_calc_csum_flags(sc);
if (sc->sc_if.if_flags & IFF_RUNNING)
bstp_initialization(sc);
@@ -1086,7 +1113,7 @@
count++;
len -= sizeof(bareq);
}
- out:
+out:
BRIDGE_RT_UNLOCK(sc);
bac->ifbac_len = sizeof(bareq) * count;
@@ -1460,6 +1487,7 @@
struct ether_header *eh;
struct ifnet *dst_if;
struct bridge_softc *sc;
+ struct mbuf *n;
int s;
/*
@@ -1493,7 +1521,7 @@
if (__predict_false(sc == NULL) ||
(sc->sc_if.if_flags & IFF_RUNNING) == 0) {
dst_if = ifp;
- goto sendunicast;
+ goto unicast_asis;
}
/*
@@ -1504,13 +1532,85 @@
dst_if = NULL;
else
dst_if = bridge_rtlookup(sc, eh->ether_dhost);
- if (dst_if == NULL) {
+
+ /*
+ * In general, we need to handle TX offload in software before
+ * enqueueing a packet. However, we can send it as is in the
+ * cases of unicast via (1) the source interface, or (2) an
+ * interface which supports the specified offload options.
+ * For multicast or broadcast, send it as is only if (3) all
+ * the member interfaces support the specified options.
+ */
+
+ /*
+ * Unicast via the source interface.
+ */
+ if (dst_if == ifp)
+ goto unicast_asis;
+
+ /*
+ * Unicast via other interface.
+ */
+ if (dst_if != NULL) {
+ KASSERT(m->m_flags & M_PKTHDR);
+ if (TX_OFFLOAD_SUPPORTED(dst_if->if_csum_flags_tx,
+ m->m_pkthdr.csum_flags)) {
+ /*
+ * Unicast via an interface which supports the
+ * specified offload options.
+ */
+ goto unicast_asis;
+ }
+
+ /*
+ * Handle TX offload in software. For TSO, a packet is
+ * split into multiple chunks. Thus, the return value of
+ * ether_sw_offload_tx() is mbuf chain consists of them.
+ */
+ m = ether_sw_offload_tx(ifp, m);
+ if (m == NULL)
+ return 0;
+
+ do {
+ n = m->m_nextpkt;
+ if ((dst_if->if_flags & IFF_RUNNING) == 0)
+ m_freem(m);
+ else
+ bridge_enqueue(sc, dst_if, m, 0);
+ m = n;
+ } while (m != NULL);
+
+ return 0;
+ }
+
+ /*
+ * Multicast or broadcast.
+ */
+ if (TX_OFFLOAD_SUPPORTED(sc->sc_csum_flags_tx,
+ m->m_pkthdr.csum_flags)) {
+ /*
+ * Specified TX offload options are supported by all
+ * the member interfaces of this bridge.
+ */
+ m->m_nextpkt = NULL; /* XXX */
+ } else {
+ /*
+ * Otherwise, handle TX offload in software.
+ */
+ m = ether_sw_offload_tx(ifp, m);
+ if (m == NULL)
+ return 0;
+ }
+
+ do {
/* XXX Should call bridge_broadcast, but there are locking
* issues which need resolving first. */
struct bridge_iflist *bif;
struct mbuf *mc;
bool used = false;
+ n = m->m_nextpkt;
+
BRIDGE_PSZ_RENTER(s);
BRIDGE_IFLIST_READER_FOREACH(bif, sc) {
struct psref psref;
@@ -1594,21 +1694,19 @@
Home |
Main Index |
Thread Index |
Old Index