net: replace IFF_KNOWSEPOCH with IFF_NEEDSEPOCH

Expect that drivers call into the network stack with the net epoch
entered. This has already been the fact since early 2020. The net
interrupts, that are marked with INTR_TYPE_NET, were entering epoch
since 511d1afb6b. For the taskqueues there is NET_TASK_INIT() and
all drivers that were known back in 2020 we marked with it in
6c3e93cb5a. However in e87c494015 we took conservative approach
and preferred to opt-in rather than opt-out for the epoch.

This change not only reverts e87c494015 but adds a safety belt to
avoid panicing with INVARIANTS if there is a missed driver. With
INVARIANTS we will run in_epoch() check, print a warning and enter
the net epoch.  A driver that prints can be quickly fixed with the
IFF_NEEDSEPOCH flag, but better be augmented to properly enter the
epoch itself.

Note on TCP LRO: it is a backdoor to enter the TCP stack bypassing
some layers of net stack, ignoring either old IFF_KNOWSEPOCH or the
new IFF_NEEDSEPOCH.  But the tcp_lro_flush_all() asserts the presence
of network epoch.  Indeed, all NIC drivers that support LRO already
provide the epoch, either with help of INTR_TYPE_NET or just running
NET_EPOCH_ENTER() in their code.

Reviewed by:		zlei, gallatin, erj
Differential Revision:	https://reviews.freebsd.org/D39510
This commit is contained in:
Gleb Smirnoff 2023-04-17 09:08:35 -07:00
parent a540cdca31
commit a6b55ee6be
11 changed files with 59 additions and 16 deletions

View File

@ -312,7 +312,7 @@ rtnl_if_flags_to_linux(unsigned int if_flags)
case IFF_ALLMULTI:
result |= flag;
break;
case IFF_KNOWSEPOCH:
case IFF_NEEDSEPOCH:
case IFF_DRV_OACTIVE:
case IFF_SIMPLEX:
case IFF_LINK0:

View File

@ -2393,8 +2393,7 @@ ena_setup_ifnet(device_t pdev, struct ena_adapter *adapter,
if_setdev(ifp, pdev);
if_setsoftc(ifp, adapter);
if_setflags(ifp,
IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_KNOWSEPOCH);
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
if_setinitfn(ifp, ena_init);
if_settransmitfn(ifp, ena_mq_start);
if_setqflushfn(ifp, ena_qflush);

View File

@ -4526,8 +4526,7 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev)
if_initname(ifp, "mce", device_get_unit(mdev->pdev->dev.bsddev));
if_setmtu(ifp, ETHERMTU);
if_setinitfn(ifp, mlx5e_open);
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
IFF_KNOWSEPOCH);
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
if_setioctlfn(ifp, mlx5e_ioctl);
if_settransmitfn(ifp, mlx5e_xmit);
if_setqflushfn(ifp, if_qflush);

View File

@ -2111,7 +2111,7 @@ oce_attach_ifp(POCE_SOFTC sc)
ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
if_setflags(sc->ifp, IFF_BROADCAST | IFF_MULTICAST | IFF_KNOWSEPOCH);
if_setflags(sc->ifp, IFF_BROADCAST | IFF_MULTICAST);
if_setioctlfn(sc->ifp, oce_ioctl);
if_setstartfn(sc->ifp, oce_start);
if_setinitfn(sc->ifp, oce_init);

View File

@ -1103,8 +1103,7 @@ vtnet_setup_interface(struct vtnet_softc *sc)
dev = sc->vtnet_dev;
ifp = sc->vtnet_ifp;
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
IFF_KNOWSEPOCH);
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
if_setbaudrate(ifp, IF_Gbps(10));
if_setinitfn(ifp, vtnet_init);
if_setioctlfn(ifp, vtnet_ioctl);

View File

@ -144,7 +144,7 @@ struct if_data {
#define IFF_DEBUG 0x4 /* (n) turn on debugging */
#define IFF_LOOPBACK 0x8 /* (i) is a loopback net */
#define IFF_POINTOPOINT 0x10 /* (i) is a point-to-point link */
#define IFF_KNOWSEPOCH 0x20 /* (i) calls if_input in net epoch */
#define IFF_NEEDSEPOCH 0x20 /* (i) calls if_input w/o net epoch */
#define IFF_DRV_RUNNING 0x40 /* (d) resources allocated */
#define IFF_NOARP 0x80 /* (n) no address resolution protocol */
#define IFF_PROMISC 0x100 /* (n) receive all packets */
@ -179,7 +179,7 @@ struct if_data {
#define IFF_CANTCHANGE \
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_DRV_RUNNING|IFF_DRV_OACTIVE|\
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_PROMISC|\
IFF_DYING|IFF_CANTCONFIG|IFF_KNOWSEPOCH)
IFF_DYING|IFF_CANTCONFIG|IFF_NEEDSEPOCH)
/*
* Values for if_link_state.

View File

@ -543,7 +543,6 @@ epair_setup_ifp(struct epair_softc *sc, char *name, int unit)
ifp->if_dname = epairname;
ifp->if_dunit = unit;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_flags |= IFF_KNOWSEPOCH;
ifp->if_capabilities = IFCAP_VLAN_MTU;
ifp->if_capenable = IFCAP_VLAN_MTU;
ifp->if_transmit = epair_transmit;

View File

@ -56,6 +56,9 @@
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/uuid.h>
#ifdef KDB
#include <sys/kdb.h>
#endif
#include <net/ieee_oui.h>
#include <net/if.h>
@ -813,7 +816,27 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
struct mbuf *mn;
bool needs_epoch;
needs_epoch = !(ifp->if_flags & IFF_KNOWSEPOCH);
needs_epoch = (ifp->if_flags & IFF_NEEDSEPOCH);
#ifdef INVARIANTS
/*
* This temporary code is here to prevent epoch unaware and unmarked
* drivers to panic the system. Once all drivers are taken care of,
* the whole INVARIANTS block should go away.
*/
if (!needs_epoch && !in_epoch(net_epoch_preempt)) {
static bool printedonce;
needs_epoch = true;
if (!printedonce) {
printedonce = true;
if_printf(ifp, "called %s w/o net epoch! "
"PLEASE file a bug report.", __func__);
#ifdef KDB
kdb_backtrace();
#endif
}
}
#endif
/*
* The drivers are allowed to pass in a chain of packets linked with

View File

@ -25,6 +25,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_kbd.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@ -38,6 +39,9 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#ifdef KDB
#include <sys/kdb.h>
#endif
#include <net/bpf.h>
#include <net/ethernet.h>
@ -417,7 +421,27 @@ infiniband_input(struct ifnet *ifp, struct mbuf *m)
int isr;
bool needs_epoch;
needs_epoch = (ifp->if_flags & IFF_KNOWSEPOCH) == 0;
needs_epoch = (ifp->if_flags & IFF_NEEDSEPOCH);
#ifdef INVARIANTS
/*
* This temporary code is here to prevent epoch unaware and unmarked
* drivers to panic the system. Once all drivers are taken care of,
* the whole INVARIANTS block should go away.
*/
if (!needs_epoch && !in_epoch(net_epoch_preempt)) {
static bool printedonce;
needs_epoch = true;
if (!printedonce) {
printedonce = true;
if_printf(ifp, "called %s w/o net epoch! "
"PLEASE file a bug report.", __func__);
#ifdef KDB
kdb_backtrace();
#endif
}
}
#endif
CURVNET_SET_QUIET(ifp->if_vnet);
if (__predict_false(needs_epoch))

View File

@ -6010,7 +6010,7 @@ iflib_register(if_ctx_t ctx)
if_settransmitfn(ifp, iflib_if_transmit);
#endif
if_setqflushfn(ifp, iflib_if_qflush);
iflags = IFF_MULTICAST | IFF_KNOWSEPOCH;
iflags = IFF_MULTICAST;
if ((sctx->isc_flags & IFLIB_PSEUDO) &&
(sctx->isc_flags & IFLIB_PSEUDO_ETHER) == 0)

View File

@ -922,8 +922,8 @@ ipoib_intf_alloc(const char *name, struct ib_device *hca)
}
if_initname(dev, name, priv->unit);
if_setflags(dev, IFF_BROADCAST | IFF_MULTICAST);
if (hca->attrs.device_cap_flags & IB_DEVICE_KNOWSEPOCH)
if_setflagbits(dev, IFF_KNOWSEPOCH, 0);
if ((hca->attrs.device_cap_flags & IB_DEVICE_KNOWSEPOCH) == 0)
if_setflagbits(dev, IFF_NEEDSEPOCH, 0);
infiniband_ifattach(priv->dev, NULL, priv->broadcastaddr);