From 24e9bd867b8d4b967f896aaa4b182c6616ac610b Mon Sep 17 00:00:00 2001 From: jan Date: Mon, 27 Feb 2023 09:35:32 +0000 Subject: [PATCH] Turn off TSO if interface is added to layer 2 devices. ok bluhm@, claudio@ --- sys/net/if.c | 63 ++++++++++++++++++++++++++------------------- sys/net/if.h | 3 ++- sys/net/if_bridge.c | 11 +++++++- sys/net/if_tpmr.c | 4 ++- sys/net/if_veb.c | 4 ++- 5 files changed, 54 insertions(+), 31 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index e805f21c42f..90a78d7f109 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.683 2022/11/23 16:57:37 kn Exp $ */ +/* $OpenBSD: if.c,v 1.684 2023/02/27 09:35:32 jan Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -2056,43 +2056,20 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) ifr->ifr_flags &= ~IFXF_WOL; error = ENOTSUP; } +#endif if (ISSET(ifp->if_capabilities, IFCAP_TSO) && ISSET(ifr->ifr_flags, IFXF_TSO) != ISSET(ifp->if_xflags, IFXF_TSO)) { - struct ifreq ifrq; - - s = splnet(); - if (ISSET(ifr->ifr_flags, IFXF_TSO)) - ifp->if_xflags |= IFXF_TSO; + ifsettso(ifp, 1); else - ifp->if_xflags &= ~IFXF_TSO; - - NET_ASSERT_LOCKED(); /* for ioctl */ - KERNEL_ASSERT_LOCKED(); /* for if_flags */ - - if (ISSET(ifp->if_flags, IFF_UP)) { - /* go down for a moment... */ - ifp->if_flags &= ~IFF_UP; - ifrq.ifr_flags = ifp->if_flags; - (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, - (caddr_t)&ifrq); - - /* ... and up again */ - ifp->if_flags |= IFF_UP; - ifrq.ifr_flags = ifp->if_flags; - (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, - (caddr_t)&ifrq); - } - - splx(s); + ifsettso(ifp, 0); } else if (!ISSET(ifp->if_capabilities, IFCAP_TSO) && ISSET(ifr->ifr_flags, IFXF_TSO)) { ifr->ifr_flags &= ~IFXF_TSO; error = ENOTSUP; } -#endif if (error == 0) ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) | @@ -3135,6 +3112,38 @@ ifpromisc(struct ifnet *ifp, int pswitch) return (error); } +/* Set/clear TSO flag and restart interface if needed. */ +void +ifsettso(struct ifnet *ifp, int on) +{ + struct ifreq ifrq; + int s = splnet(); + + NET_ASSERT_LOCKED(); /* for ioctl */ + KERNEL_ASSERT_LOCKED(); /* for if_flags */ + + if (on && !ISSET(ifp->if_xflags, IFXF_TSO)) + SET(ifp->if_xflags, IFXF_TSO); + else if (!on && ISSET(ifp->if_xflags, IFXF_TSO)) + CLR(ifp->if_xflags, IFXF_TSO); + else + goto out; + + if (ISSET(ifp->if_flags, IFF_UP)) { + /* go down for a moment... */ + CLR(ifp->if_flags, IFF_UP); + ifrq.ifr_flags = ifp->if_flags; + (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); + + /* ... and up again */ + SET(ifp->if_flags, IFF_UP); + ifrq.ifr_flags = ifp->if_flags; + (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq); + } + out: + splx(s); +} + void ifa_add(struct ifnet *ifp, struct ifaddr *ifa) { diff --git a/sys/net/if.h b/sys/net/if.h index 278679be2ef..6a046623747 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.209 2022/06/27 15:11:23 jan Exp $ */ +/* $OpenBSD: if.h,v 1.210 2023/02/27 09:35:32 jan Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -544,6 +544,7 @@ void if_getdata(struct ifnet *, struct if_data *); void ifinit(void); int ifioctl(struct socket *, u_long, caddr_t, struct proc *); int ifpromisc(struct ifnet *, int); +void ifsettso(struct ifnet *, int); struct ifg_group *if_creategroup(const char *); int if_addgroup(struct ifnet *, const char *); int if_delgroup(struct ifnet *, const char *); diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 708f3d56abb..a202556e41f 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.364 2022/08/07 00:57:43 bluhm Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.365 2023/02/27 09:35:32 jan Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -337,6 +337,10 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) * released. */ + NET_LOCK(); + ifsettso(ifs, 0); + NET_UNLOCK(); + bif->bridge_sc = sc; bif->ifp = ifs; bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; @@ -395,6 +399,11 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ENOMEM; break; } + + NET_LOCK(); + ifsettso(ifs, 0); + NET_UNLOCK(); + bif->bridge_sc = sc; bif->ifp = ifs; bif->bif_flags = IFBIF_SPAN; diff --git a/sys/net/if_tpmr.c b/sys/net/if_tpmr.c index 5fc186c4a3e..9f2b2dec125 100644 --- a/sys/net/if_tpmr.c +++ b/sys/net/if_tpmr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tpmr.c,v 1.31 2021/07/07 20:19:01 sashan Exp $ */ +/* $OpenBSD: if_tpmr.c,v 1.32 2023/02/27 09:35:32 jan Exp $ */ /* * Copyright (c) 2019 The University of Queensland @@ -521,6 +521,8 @@ tpmr_add_port(struct tpmr_softc *sc, const struct ifbreq *req) goto put; } + ifsettso(ifp0, 0); + p->p_ifp0 = ifp0; p->p_tpmr = sc; diff --git a/sys/net/if_veb.c b/sys/net/if_veb.c index b24eab61115..c5f865b7154 100644 --- a/sys/net/if_veb.c +++ b/sys/net/if_veb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_veb.c,v 1.29 2022/06/01 17:34:13 sashan Exp $ */ +/* $OpenBSD: if_veb.c,v 1.30 2023/02/27 09:35:32 jan Exp $ */ /* * Copyright (c) 2021 David Gwynne @@ -1465,6 +1465,8 @@ veb_add_port(struct veb_softc *sc, const struct ifbreq *req, unsigned int span) goto put; } + ifsettso(ifp0, 0); + p->p_ifp0 = ifp0; p->p_veb = sc; -- 2.20.1