diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-21 13:47:02 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:41 +0200 |
commit | bcdce02d9bc8150e1d191ed5ca9da45b7604964a (patch) | |
tree | 3b2faf509db7672ee1fc98857736470be97e7ed8 /freebsd/sys/net | |
parent | Update to FreeBSD head 2018-04-01 (diff) | |
download | rtems-libbsd-bcdce02d9bc8150e1d191ed5ca9da45b7604964a.tar.bz2 |
Update to FreeBSD head 2018-06-01
Git mirror commit fb63610a69b0eb7f69a201ba05c4c1a7a2739cf9.
Update #3472.
Diffstat (limited to 'freebsd/sys/net')
35 files changed, 990 insertions, 2480 deletions
diff --git a/freebsd/sys/net/altq/altq_subr.c b/freebsd/sys/net/altq/altq_subr.c index 6a385560..47a353fc 100644 --- a/freebsd/sys/net/altq/altq_subr.c +++ b/freebsd/sys/net/altq/altq_subr.c @@ -436,8 +436,8 @@ tbr_timeout(arg) VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); - for (ifp = TAILQ_FIRST(&V_ifnet); ifp; - ifp = TAILQ_NEXT(ifp, if_link)) { + for (ifp = CK_STAILQ_FIRST(&V_ifnet); ifp; + ifp = CK_STAILQ_NEXT(ifp, if_link)) { /* read from if_snd unlocked */ if (!TBR_IS_ENABLED(&ifp->if_snd)) continue; diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c index 24927e8b..57aff5b8 100644 --- a/freebsd/sys/net/bpf.c +++ b/freebsd/sys/net/bpf.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/opt_bpf.h> -#include <rtems/bsd/local/opt_compat.h> #include <rtems/bsd/local/opt_ddb.h> #include <rtems/bsd/local/opt_netgraph.h> @@ -106,6 +105,10 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_BPF, "BPF", "BPF data"); +static struct bpf_if_ext dead_bpf_if = { + .bif_dlist = LIST_HEAD_INITIALIZER() +}; + struct bpf_if { #define bif_next bif_ext.bif_next #define bif_dlist bif_ext.bif_dlist @@ -167,6 +170,9 @@ struct bpf_dltlist32 { #define BIOCSETFNR32 _IOW('B', 130, struct bpf_program32) #endif +#define BPF_LOCK() sx_xlock(&bpf_sx) +#define BPF_UNLOCK() sx_xunlock(&bpf_sx) +#define BPF_LOCK_ASSERT() sx_assert(&bpf_sx, SA_XLOCKED) /* * bpf_iflist is a list of BPF interface structures, each corresponding to a * specific DLT. The same network interface might have several BPF interface @@ -174,7 +180,7 @@ struct bpf_dltlist32 { * frames, ethernet frames, etc). */ static LIST_HEAD(, bpf_if) bpf_iflist, bpf_freelist; -static struct mtx bpf_mtx; /* bpf global lock */ +static struct sx bpf_sx; /* bpf global lock */ static int bpf_bpfd_cnt; static void bpf_attachd(struct bpf_d *, struct bpf_if *); @@ -2752,7 +2758,7 @@ bpfdetach(struct ifnet *ifp) */ BPFIF_WLOCK(bp); bp->bif_flags |= BPFIF_FLAG_DYING; - *bp->bif_bpf = NULL; + *bp->bif_bpf = (struct bpf_if *)&dead_bpf_if; BPFIF_WUNLOCK(bp); CTR4(KTR_NET, "%s: sheduling free for encap %d (%p) for if %p", @@ -3090,7 +3096,7 @@ bpf_drvinit(void *unused) int rv; #endif /* __rtems__ */ - mtx_init(&bpf_mtx, "bpf global lock", NULL, MTX_DEF); + sx_init(&bpf_sx, "bpf global lock"); LIST_INIT(&bpf_iflist); LIST_INIT(&bpf_freelist); @@ -3253,13 +3259,13 @@ bpf_stats_sysctl(SYSCTL_HANDLER_ARGS) SYSINIT(bpfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,bpf_drvinit,NULL); #else /* !DEV_BPF && !NETGRAPH_BPF */ + /* * NOP stubs to allow bpf-using drivers to load and function. * * A 'better' implementation would allow the core bpf functionality * to be loaded at runtime. */ -static struct bpf_if bp_null; void bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen) @@ -3287,7 +3293,7 @@ void bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp) { - *driverp = &bp_null; + *driverp = (struct bpf_if *)&dead_bpf_if; } void diff --git a/freebsd/sys/net/bpfdesc.h b/freebsd/sys/net/bpfdesc.h index 695d3d40..95093cff 100644 --- a/freebsd/sys/net/bpfdesc.h +++ b/freebsd/sys/net/bpfdesc.h @@ -125,9 +125,6 @@ struct bpf_d { #define BPF_PID_REFRESH_CUR(bd) do { } while (0) #endif /* __rtems__ */ -#define BPF_LOCK() mtx_lock(&bpf_mtx) -#define BPF_UNLOCK() mtx_unlock(&bpf_mtx) -#define BPF_LOCK_ASSERT() mtx_assert(&bpf_mtx, MA_OWNED) /* * External representation of the bpf descriptor */ diff --git a/freebsd/sys/net/bridgestp.c b/freebsd/sys/net/bridgestp.c index 472b9634..49e772b3 100644 --- a/freebsd/sys/net/bridgestp.c +++ b/freebsd/sys/net/bridgestp.c @@ -2045,7 +2045,7 @@ bstp_reinit(struct bstp_state *bs) * bridges in the same STP domain. */ IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (ifp->if_type != IFT_ETHER) continue; /* Not Ethernet */ diff --git a/freebsd/sys/net/dlt.h b/freebsd/sys/net/dlt.h index dc818521..639e5a7f 100644 --- a/freebsd/sys/net/dlt.h +++ b/freebsd/sys/net/dlt.h @@ -122,9 +122,9 @@ /* * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and - * Mac OS X; don't use it for anything else. (FreeBSD uses 121, - * which collides with DLT_HHDLC, even though it doesn't use 18 - * for anything and doesn't appear to have ever used it for anything.) + * macOS; don't use it for anything else. (FreeBSD uses 121, which + * collides with DLT_HHDLC, even though it doesn't use 18 for + * anything and doesn't appear to have ever used it for anything.) * * We define it as 18 on those platforms; it is, unfortunately, used * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC @@ -342,7 +342,7 @@ * * FreeBSD's libpcap won't map a link-layer header type of 18 - i.e., * DLT_PFSYNC files from OpenBSD and possibly older versions of NetBSD, - * DragonFly BSD, and OS X - to DLT_PFSYNC, so code built with FreeBSD's + * DragonFly BSD, and macOS - to DLT_PFSYNC, so code built with FreeBSD's * libpcap won't treat those files as DLT_PFSYNC files. * * Other libpcaps won't map a link-layer header type of 121 to DLT_PFSYNC; @@ -948,14 +948,14 @@ * the pseudo-header is: * * struct dl_ipnetinfo { - * u_int8_t dli_version; - * u_int8_t dli_family; - * u_int16_t dli_htype; - * u_int32_t dli_pktlen; - * u_int32_t dli_ifindex; - * u_int32_t dli_grifindex; - * u_int32_t dli_zsrc; - * u_int32_t dli_zdst; + * uint8_t dli_version; + * uint8_t dli_family; + * uint16_t dli_htype; + * uint32_t dli_pktlen; + * uint32_t dli_ifindex; + * uint32_t dli_grifindex; + * uint32_t dli_zsrc; + * uint32_t dli_zdst; * }; * * dli_version is 2 for the current version of the pseudo-header. @@ -1231,7 +1231,7 @@ * So I'll just give them one; hopefully this will show up in a * libpcap release in time for them to get this into 10.10 Big Sur * or whatever Mavericks' successor is called. LINKTYPE_PKTAP - * will be 258 *even on OS X*; that is *intentional*, so that + * will be 258 *even on macOS*; that is *intentional*, so that * PKTAP files look the same on *all* OSes (different OSes can have * different numerical values for a given DLT_, but *MUST NOT* have * different values for what goes in a file, as files can be moved @@ -1243,9 +1243,9 @@ * and that will continue to be DLT_USER2 on Darwin-based OSes. That way, * binary compatibility with Mavericks is preserved for programs using * this version of libpcap. This does mean that if you were using - * DLT_USER2 for some capture device on OS X, you can't do so with + * DLT_USER2 for some capture device on macOS, you can't do so with * this version of libpcap, just as you can't with Apple's libpcap - - * on OS X, they define DLT_PKTAP to be DLT_USER2, so programs won't + * on macOS, they define DLT_PKTAP to be DLT_USER2, so programs won't * be able to distinguish between PKTAP and whatever you were using * DLT_USER2 for. * @@ -1305,6 +1305,66 @@ #define DLT_RDS 265 /* + * USB packets, beginning with a Darwin (macOS, etc.) header. + */ +#define DLT_USB_DARWIN 266 + +/* + * OpenBSD DLT_OPENFLOW. + */ +#define DLT_OPENFLOW 267 + +/* + * SDLC frames containing SNA PDUs. + */ +#define DLT_SDLC 268 + +/* + * per "Selvig, Bjorn" <b.selvig@ti.com> used for + * TI protocol sniffer. + */ +#define DLT_TI_LLN_SNIFFER 269 + +/* + * per: Erik de Jong <erikdejong at gmail.com> for + * https://github.com/eriknl/LoRaTap/releases/tag/v0.1 + */ +#define DLT_LORATAP 270 + +/* + * per: Stefanha at gmail.com for + * http://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html + * and: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vsockmon.h + * for: http://qemu-project.org/Features/VirtioVsock + */ +#define DLT_VSOCK 271 + +/* + * Nordic Semiconductor Bluetooth LE sniffer. + */ +#define DLT_NORDIC_BLE 272 + +/* + * Excentis DOCSIS 3.1 RF sniffer (XRA-31) + * per: bruno.verstuyft at excentis.com + * http://www.xra31.com/xra-header + */ +#define DLT_DOCSIS31_XRA31 273 + +/* + * mPackets, as specified by IEEE 802.3br Figure 99-4, starting + * with the preamble and always ending with a CRC field. + */ +#define DLT_ETHERNET_MPACKET 274 + +/* + * DisplayPort AUX channel monitoring data as specified by VESA + * DisplayPort(DP) Standard preceeded by a pseudo-header. + * per dirk.eibach at gdsys.cc + */ +#define DLT_DISPLAYPORT_AUX 275 + +/* * In case the code that includes this file (directly or indirectly) * has also included OS files that happen to define DLT_MATCHING_MAX, * with a different value (perhaps because that OS hasn't picked up @@ -1314,7 +1374,7 @@ #ifdef DLT_MATCHING_MAX #undef DLT_MATCHING_MAX #endif -#define DLT_MATCHING_MAX 265 /* highest value in the "matching" range */ +#define DLT_MATCHING_MAX 275 /* highest value in the "matching" range */ /* * DLT and savefile link type values are split into a class and diff --git a/freebsd/sys/net/fddi.h b/freebsd/sys/net/fddi.h deleted file mode 100644 index 0badcc3c..00000000 --- a/freebsd/sys/net/fddi.h +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com) - * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. 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. - * - * @(#)if_fddi.h 8.1 (Berkeley) 6/10/93 - * $FreeBSD$ - */ - -#ifndef _NETINET_IF_FDDI_H_ -#define _NETINET_IF_FDDI_H_ - -#define FDDIIPMTU 4352 -#define FDDIMTU 4470 -#define FDDIMIN 3 - -#define FDDIFC_C 0x80 /* 0b10000000 */ -#define FDDIFC_L 0x40 /* 0b01000000 */ -#define FDDIFC_F 0x30 /* 0b00110000 */ -#define FDDIFC_Z 0x0F /* 0b00001111 */ -#define FDDIFC_CLFF 0xF0 /* Class/Length/Format bits */ -#define FDDIFC_ZZZZ 0x0F /* Control bits */ - -/* - * FDDI Frame Control values. (48-bit addressing only). - */ -#define FDDIFC_VOID 0x40 /* Void frame */ -#define FDDIFC_NRT 0x80 /* Nonrestricted token */ -#define FDDIFC_RT 0xc0 /* Restricted token */ -#define FDDIFC_MAC_BEACON 0xc2 /* MAC Beacon frame */ -#define FDDIFC_MAC_CLAIM 0xc3 /* MAC Claim frame */ -#define FDDIFC_LLC_ASYNC 0x50 -#define FDDIFC_LLC_PRIO0 0 -#define FDDIFC_LLC_PRIO1 1 -#define FDDIFC_LLC_PRIO2 2 -#define FDDIFC_LLC_PRIO3 3 -#define FDDIFC_LLC_PRIO4 4 -#define FDDIFC_LLC_PRIO5 5 -#define FDDIFC_LLC_PRIO6 6 -#define FDDIFC_LLC_PRIO7 7 -#define FDDIFC_LLC_SYNC 0xd0 -#define FDDIFC_IMP_ASYNC 0x60 /* Implementor Async. */ -#define FDDIFC_IMP_SYNC 0xe0 /* Implementor Synch. */ -#define FDDIFC_SMT 0x40 -#define FDDIFC_SMT_INFO 0x41 /* SMT Info */ -#define FDDIFC_SMT_NSA 0x4F /* SMT Next station adrs */ -#define FDDIFC_MAC 0xc0 /* MAC frame */ - -#define FDDI_ADDR_LEN 6 -#define FDDI_HDR_LEN (sizeof(struct fddi_header)) - -/* - * Structure of an 100Mb/s FDDI header. - */ -struct fddi_header { - u_char fddi_fc; - u_char fddi_dhost[FDDI_ADDR_LEN]; - u_char fddi_shost[FDDI_ADDR_LEN]; -}; - -#if defined(_KERNEL) -#define fddi_ipmulticast_min ether_ipmulticast_min -#define fddi_ipmulticast_max ether_ipmulticast_max -#define fddi_addmulti ether_addmulti -#define fddi_delmulti ether_delmulti -#define fddi_sprintf ether_sprintf - -#define FDDI_BPF_UNSUPPORTED 0 -#define FDDI_BPF_SUPPORTED 1 - -void fddi_ifattach(struct ifnet *, const u_int8_t *, int); -void fddi_ifdetach(struct ifnet *, int); -int fddi_ioctl(struct ifnet *, u_long, caddr_t); - -#endif /* _KERNEL */ -#endif /* _NET_FDDI_H_ */ diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c index bbf2ddd0..d4c18b46 100644 --- a/freebsd/sys/net/if.c +++ b/freebsd/sys/net/if.c @@ -34,7 +34,6 @@ * $FreeBSD$ */ -#include <rtems/bsd/local/opt_compat.h> #include <rtems/bsd/local/opt_inet6.h> #include <rtems/bsd/local/opt_inet.h> @@ -44,6 +43,7 @@ #include <sys/malloc.h> #include <sys/sbuf.h> #include <sys/bus.h> +#include <sys/epoch.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/priv.h> @@ -90,6 +90,7 @@ #include <netinet/ip_carp.h> #ifdef INET #include <netinet/if_ether.h> +#include <netinet/netdump/netdump.h> #endif /* INET */ #ifdef INET6 #include <netinet6/in6_var.h> @@ -106,6 +107,13 @@ _Static_assert(sizeof(((struct ifreq *)0)->ifr_name) == offsetof(struct ifreq, ifr_ifru), "gap between ifr_name and ifr_ifru"); +#ifndef __rtems__ +__read_mostly epoch_t net_epoch_preempt; +__read_mostly epoch_t net_epoch; +#else /* __rtems__ */ +EPOCH_DEFINE(_bsd_net_epoch_preempt, EPOCH_PREEMPT); +EPOCH_DEFINE(_bsd_net_epoch, 0); +#endif /* __rtems__ */ #ifdef COMPAT_FREEBSD32 #include <sys/mount.h> #include <compat/freebsd32/freebsd32.h> @@ -144,7 +152,37 @@ struct ifreq32 { CTASSERT(sizeof(struct ifreq) == sizeof(struct ifreq32)); CTASSERT(__offsetof(struct ifreq, ifr_ifru) == __offsetof(struct ifreq32, ifr_ifru)); -#endif + +struct ifgroupreq32 { + char ifgr_name[IFNAMSIZ]; + u_int ifgr_len; + union { + char ifgru_group[IFNAMSIZ]; + uint32_t ifgru_groups; + } ifgr_ifgru; +}; + +struct ifmediareq32 { + char ifm_name[IFNAMSIZ]; + int ifm_current; + int ifm_mask; + int ifm_status; + int ifm_active; + int ifm_count; + uint32_t ifm_ulist; /* (int *) */ +}; +#define SIOCGIFMEDIA32 _IOC_NEWTYPE(SIOCGIFMEDIA, struct ifmediareq32) +#define SIOCGIFXMEDIA32 _IOC_NEWTYPE(SIOCGIFXMEDIA, struct ifmediareq32) + +#define _CASE_IOC_IFGROUPREQ_32(cmd) \ + case _IOC_NEWTYPE((cmd), struct ifgroupreq32): +#else /* !COMPAT_FREEBSD32 */ +#define _CASE_IOC_IFGROUPREQ_32(cmd) +#endif /* !COMPAT_FREEBSD32 */ + +#define CASE_IOC_IFGROUPREQ(cmd) \ + _CASE_IOC_IFGROUPREQ_32(cmd) \ + case (cmd) union ifreq_union { struct ifreq ifr; @@ -153,6 +191,13 @@ union ifreq_union { #endif }; +union ifgroupreq_union { + struct ifgroupreq ifgr; +#ifdef COMPAT_FREEBSD32 + struct ifgroupreq32 ifgr32; +#endif +}; + SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); @@ -185,7 +230,6 @@ static MALLOC_DEFINE(M_IFDESCR, "ifdescr", "ifnet descriptions"); static struct sx ifdescr_sx; SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr"); -void (*bridge_linkstate_p)(struct ifnet *ifp); void (*ng_ether_link_state_p)(struct ifnet *ifp, int state); void (*lagg_linkstate_p)(struct ifnet *ifp, int state); /* These are external hooks for CARP. */ @@ -219,8 +263,7 @@ struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL; static void if_attachdomain(void *); static void if_attachdomain1(struct ifnet *); static int ifconf(u_long, caddr_t); -static void if_freemulti(struct ifmultiaddr *); -static void if_grow(void); +static void *if_grow(void); static void if_input_default(struct ifnet *, struct mbuf *); static int if_requestencap_default(struct ifnet *, struct if_encap_req *); static void if_route(struct ifnet *, int flag, int fam); @@ -309,9 +352,7 @@ ifnet_byindex(u_short idx) { struct ifnet *ifp; - IFNET_RLOCK_NOSLEEP(); ifp = ifnet_byindex_locked(idx); - IFNET_RUNLOCK_NOSLEEP(); return (ifp); } @@ -336,12 +377,11 @@ ifnet_byindex_ref(u_short idx) * failure. */ static u_short -ifindex_alloc(void) +ifindex_alloc(void **old) { u_short idx; IFNET_WLOCK_ASSERT(); -retry: /* * Try to find an empty slot below V_if_index. If we fail, take the * next slot. @@ -353,8 +393,8 @@ retry: /* Catch if_index overflow. */ if (idx >= V_if_indexlim) { - if_grow(); - goto retry; + *old = if_grow(); + return (USHRT_MAX); } if (idx > V_if_index) V_if_index = idx; @@ -383,21 +423,10 @@ ifindex_free(u_short idx) } static void -ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp) -{ - - IFNET_WLOCK_ASSERT(); - - V_ifindex_table[idx] = ifp; -} - -static void ifnet_setbyindex(u_short idx, struct ifnet *ifp) { - IFNET_WLOCK(); - ifnet_setbyindex_locked(idx, ifp); - IFNET_WUNLOCK(); + V_ifindex_table[idx] = ifp; } struct ifaddr * @@ -424,12 +453,15 @@ ifaddr_byindex(u_short idx) static void vnet_if_init(const void *unused __unused) { + void *old; - TAILQ_INIT(&V_ifnet); - TAILQ_INIT(&V_ifg_head); + CK_STAILQ_INIT(&V_ifnet); + CK_STAILQ_INIT(&V_ifg_head); IFNET_WLOCK(); - if_grow(); /* create initial table */ + old = if_grow(); /* create initial table */ IFNET_WUNLOCK(); + epoch_wait_preempt(net_epoch_preempt); + free(old, M_IFNET); vnet_if_clone_init(); } VNET_SYSINIT(vnet_if_init, SI_SUB_INIT_IF, SI_ORDER_SECOND, vnet_if_init, @@ -440,9 +472,9 @@ static void vnet_if_uninit(const void *unused __unused) { - VNET_ASSERT(TAILQ_EMPTY(&V_ifnet), ("%s:%d tailq &V_ifnet=%p " + VNET_ASSERT(CK_STAILQ_EMPTY(&V_ifnet), ("%s:%d tailq &V_ifnet=%p " "not empty", __func__, __LINE__, &V_ifnet)); - VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head), ("%s:%d tailq &V_ifg_head=%p " + VNET_ASSERT(CK_STAILQ_EMPTY(&V_ifg_head), ("%s:%d tailq &V_ifg_head=%p " "not empty", __func__, __LINE__, &V_ifg_head)); free((caddr_t)V_ifindex_table, M_IFNET); @@ -456,7 +488,7 @@ vnet_if_return(const void *unused __unused) struct ifnet *ifp, *nifp; /* Return all inherited interfaces to their parent vnets. */ - TAILQ_FOREACH_SAFE(ifp, &V_ifnet, if_link, nifp) { + CK_STAILQ_FOREACH_SAFE(ifp, &V_ifnet, if_link, nifp) { if (ifp->if_home_vnet != ifp->if_vnet) if_vmove(ifp, ifp->if_home_vnet); } @@ -465,13 +497,16 @@ VNET_SYSUNINIT(vnet_if_return, SI_SUB_VNET_DONE, SI_ORDER_ANY, vnet_if_return, NULL); #endif -static void + +static void * if_grow(void) { int oldlim; u_int n; struct ifnet **e; + void *old; + old = NULL; IFNET_WLOCK_ASSERT(); oldlim = V_if_indexlim; IFNET_WUNLOCK(); @@ -480,14 +515,15 @@ if_grow(void) IFNET_WLOCK(); if (V_if_indexlim != oldlim) { free(e, M_IFNET); - return; + return (NULL); } if (V_ifindex_table != NULL) { memcpy((caddr_t)e, (caddr_t)V_ifindex_table, n/2); - free((caddr_t)V_ifindex_table, M_IFNET); + old = V_ifindex_table; } V_if_indexlim <<= 1; V_ifindex_table = e; + return (old); } /* @@ -500,11 +536,19 @@ if_alloc(u_char type) { struct ifnet *ifp; u_short idx; + void *old; ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO); + restart: IFNET_WLOCK(); - idx = ifindex_alloc(); - ifnet_setbyindex_locked(idx, IFNET_HOLD); + idx = ifindex_alloc(&old); + if (__predict_false(idx == USHRT_MAX)) { + IFNET_WUNLOCK(); + epoch_wait_preempt(net_epoch_preempt); + free(old, M_IFNET); + goto restart; + } + ifnet_setbyindex(idx, IFNET_HOLD); IFNET_WUNLOCK(); ifp->if_index = idx; ifp->if_type = type; @@ -525,9 +569,9 @@ if_alloc(u_char type) TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp); ifp->if_afdata_initialized = 0; IF_AFDATA_LOCK_INIT(ifp); - TAILQ_INIT(&ifp->if_addrhead); - TAILQ_INIT(&ifp->if_multiaddrs); - TAILQ_INIT(&ifp->if_groups); + CK_STAILQ_INIT(&ifp->if_addrhead); + CK_STAILQ_INIT(&ifp->if_multiaddrs); + CK_STAILQ_INIT(&ifp->if_groups); #ifdef MAC mac_ifnet_init(ifp); #endif @@ -573,6 +617,15 @@ if_free_internal(struct ifnet *ifp) free(ifp, M_IFNET); } +static void +if_destroy(epoch_context_t ctx) +{ + struct ifnet *ifp; + + ifp = __containerof(ctx, struct ifnet, if_epoch_ctx); + if_free_internal(ifp); +} + /* * Deregister an interface and free the associated storage. */ @@ -591,7 +644,7 @@ if_free(struct ifnet *ifp) IFNET_WUNLOCK(); if (refcount_release(&ifp->if_refcount)) - if_free_internal(ifp); + epoch_call(net_epoch_preempt, &ifp->if_epoch_ctx, if_destroy); CURVNET_RESTORE(); } @@ -614,7 +667,7 @@ if_rele(struct ifnet *ifp) if (!refcount_release(&ifp->if_refcount)) return; - if_free_internal(ifp); + epoch_call(net_epoch_preempt, &ifp->if_epoch_ctx, if_destroy); } void @@ -795,7 +848,7 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) sdl->sdl_len = masklen; while (namelen != 0) sdl->sdl_data[--namelen] = 0xff; - TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); + CK_STAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); /* Reliably crash if used uninitialized. */ ifp->if_broadcastaddr = NULL; @@ -837,7 +890,7 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) * of the interface. */ for (ifa = ifp->if_addr; ifa != NULL; - ifa = TAILQ_NEXT(ifa, ifa_link)) { + ifa = CK_STAILQ_NEXT(ifa, ifa_link)) { if (ifa->ifa_addr->sa_family == AF_LINK) { sdl = (struct sockaddr_dl *)ifa->ifa_addr; sdl->sdl_index = ifp->if_index; @@ -847,7 +900,7 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) #endif IFNET_WLOCK(); - TAILQ_INSERT_TAIL(&V_ifnet, ifp, if_link); + CK_STAILQ_INSERT_TAIL(&V_ifnet, ifp, if_link); #ifdef VIMAGE curvnet->vnet_ifcnt++; #endif @@ -864,12 +917,24 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) rt_ifannouncemsg(ifp, IFAN_ARRIVAL); } +#ifndef __rtems__ +static void +if_epochalloc(void *dummy __unused) +{ + + net_epoch_preempt = epoch_alloc(EPOCH_PREEMPT); + net_epoch = epoch_alloc(0); +} +SYSINIT(ifepochalloc, SI_SUB_TASKQ + 1, SI_ORDER_ANY, + if_epochalloc, NULL); +#endif /* __rtems__ */ + static void if_attachdomain(void *dummy) { struct ifnet *ifp; - TAILQ_FOREACH(ifp, &V_ifnet, if_link) + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) if_attachdomain1(ifp); } SYSINIT(domainifattach, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_SECOND, @@ -911,8 +976,8 @@ if_purgeaddrs(struct ifnet *ifp) { struct ifaddr *ifa, *next; - /* XXX cannot hold IF_ADDR_WLOCK over called functions. */ - TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) { + NET_EPOCH_ENTER(); + CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) { if (ifa->ifa_addr->sa_family == AF_LINK) continue; #ifdef INET @@ -937,10 +1002,11 @@ if_purgeaddrs(struct ifnet *ifp) } #endif /* INET6 */ IF_ADDR_WLOCK(ifp); - TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); + CK_STAILQ_REMOVE(&ifp->if_addrhead, ifa, ifaddr, ifa_link); IF_ADDR_WUNLOCK(ifp); ifa_free(ifa); } + NET_EPOCH_EXIT(); } /* @@ -951,11 +1017,13 @@ static void if_purgemaddrs(struct ifnet *ifp) { struct ifmultiaddr *ifma; - struct ifmultiaddr *next; IF_ADDR_WLOCK(ifp); - TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) + while (!CK_STAILQ_EMPTY(&ifp->if_multiaddrs)) { + ifma = CK_STAILQ_FIRST(&ifp->if_multiaddrs); + CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link); if_delmulti_locked(ifp, ifma, 1); + } IF_ADDR_WUNLOCK(ifp); } @@ -1002,9 +1070,9 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) ifp->if_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; #endif IFNET_WLOCK(); - TAILQ_FOREACH(iter, &V_ifnet, if_link) + CK_STAILQ_FOREACH(iter, &V_ifnet, if_link) if (iter == ifp) { - TAILQ_REMOVE(&V_ifnet, ifp, if_link); + CK_STAILQ_REMOVE(&V_ifnet, ifp, ifnet, if_link); found = 1; break; } @@ -1032,7 +1100,7 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) #ifdef VIMAGE curvnet->vnet_ifcnt--; #endif - + epoch_wait_preempt(net_epoch_preempt); /* * In any case (destroy or vmove) detach us from the groups * and remove/wait for pending events on the taskq. @@ -1125,9 +1193,9 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) /* We can now free link ifaddr. */ IF_ADDR_WLOCK(ifp); - if (!TAILQ_EMPTY(&ifp->if_addrhead)) { - ifa = TAILQ_FIRST(&ifp->if_addrhead); - TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); + if (!CK_STAILQ_EMPTY(&ifp->if_addrhead)) { + ifa = CK_STAILQ_FIRST(&ifp->if_addrhead); + CK_STAILQ_REMOVE(&ifp->if_addrhead, ifa, ifaddr, ifa_link); IF_ADDR_WUNLOCK(ifp); ifa_free(ifa); } else @@ -1172,6 +1240,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { struct if_clone *ifc; u_int bif_dlt, bif_hdrlen; + void *old; int rc; /* @@ -1212,10 +1281,16 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet) * Switch to the context of the target vnet. */ CURVNET_SET_QUIET(new_vnet); - + restart: IFNET_WLOCK(); - ifp->if_index = ifindex_alloc(); - ifnet_setbyindex_locked(ifp->if_index, ifp); + ifp->if_index = ifindex_alloc(&old); + if (__predict_false(ifp->if_index == USHRT_MAX)) { + IFNET_WUNLOCK(); + epoch_wait_preempt(net_epoch_preempt); + free(old, M_IFNET); + goto restart; + } + ifnet_setbyindex(ifp->if_index, ifp); IFNET_WUNLOCK(); if_attach_internal(ifp, 1, ifc); @@ -1352,7 +1427,7 @@ if_addgroup(struct ifnet *ifp, const char *groupname) return (EINVAL); IFNET_WLOCK(); - TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) + CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) { IFNET_WUNLOCK(); return (EEXIST); @@ -1371,7 +1446,7 @@ if_addgroup(struct ifnet *ifp, const char *groupname) return (ENOMEM); } - TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) + CK_STAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, groupname)) break; @@ -1385,8 +1460,8 @@ if_addgroup(struct ifnet *ifp, const char *groupname) } strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group)); ifg->ifg_refcnt = 0; - TAILQ_INIT(&ifg->ifg_members); - TAILQ_INSERT_TAIL(&V_ifg_head, ifg, ifg_next); + CK_STAILQ_INIT(&ifg->ifg_members); + CK_STAILQ_INSERT_TAIL(&V_ifg_head, ifg, ifg_next); new = 1; } @@ -1395,8 +1470,8 @@ if_addgroup(struct ifnet *ifp, const char *groupname) ifgm->ifgm_ifp = ifp; IF_ADDR_WLOCK(ifp); - TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next); - TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next); + CK_STAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next); + CK_STAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next); IF_ADDR_WUNLOCK(ifp); IFNET_WUNLOCK(); @@ -1416,9 +1491,10 @@ if_delgroup(struct ifnet *ifp, const char *groupname) { struct ifg_list *ifgl; struct ifg_member *ifgm; + int freeifgl; IFNET_WLOCK(); - TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) + CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) break; if (ifgl == NULL) { @@ -1426,27 +1502,30 @@ if_delgroup(struct ifnet *ifp, const char *groupname) return (ENOENT); } + freeifgl = 0; IF_ADDR_WLOCK(ifp); - TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next); + CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next); IF_ADDR_WUNLOCK(ifp); - TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) + CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) if (ifgm->ifgm_ifp == ifp) break; - if (ifgm != NULL) { - TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next); - free(ifgm, M_TEMP); - } + if (ifgm != NULL) + CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifg_member, ifgm_next); if (--ifgl->ifgl_group->ifg_refcnt == 0) { - TAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_next); - IFNET_WUNLOCK(); + CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, ifg_next); + freeifgl = 1; + } + IFNET_WUNLOCK(); + + epoch_wait_preempt(net_epoch_preempt); + if (freeifgl) { EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group); free(ifgl->ifgl_group, M_TEMP); - } else - IFNET_WUNLOCK(); - + } + free(ifgm, M_TEMP); free(ifgl, M_TEMP); EVENTHANDLER_INVOKE(group_change_event, groupname); @@ -1463,38 +1542,39 @@ if_delgroups(struct ifnet *ifp) struct ifg_list *ifgl; struct ifg_member *ifgm; char groupname[IFNAMSIZ]; + int ifglfree; IFNET_WLOCK(); - while (!TAILQ_EMPTY(&ifp->if_groups)) { - ifgl = TAILQ_FIRST(&ifp->if_groups); + while (!CK_STAILQ_EMPTY(&ifp->if_groups)) { + ifgl = CK_STAILQ_FIRST(&ifp->if_groups); strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ); IF_ADDR_WLOCK(ifp); - TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next); + CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next); IF_ADDR_WUNLOCK(ifp); - TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) + CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) if (ifgm->ifgm_ifp == ifp) break; - if (ifgm != NULL) { - TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, + if (ifgm != NULL) + CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifg_member, ifgm_next); - free(ifgm, M_TEMP); + ifglfree = 0; + if (--ifgl->ifgl_group->ifg_refcnt == 0) { + CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, ifg_next); + ifglfree = 1; } - if (--ifgl->ifgl_group->ifg_refcnt == 0) { - TAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_next); - IFNET_WUNLOCK(); + IFNET_WUNLOCK(); + epoch_wait_preempt(net_epoch_preempt); + free(ifgm, M_TEMP); + if (ifglfree) { EVENTHANDLER_INVOKE(group_detach_event, - ifgl->ifgl_group); + ifgl->ifgl_group); free(ifgl->ifgl_group, M_TEMP); - } else - IFNET_WUNLOCK(); - - free(ifgl, M_TEMP); - + } EVENTHANDLER_INVOKE(group_change_event, groupname); IFNET_WLOCK(); @@ -1502,31 +1582,56 @@ if_delgroups(struct ifnet *ifp) IFNET_WUNLOCK(); } +static char * +ifgr_group_get(void *ifgrp) +{ + union ifgroupreq_union *ifgrup; + + ifgrup = ifgrp; +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) + return (&ifgrup->ifgr32.ifgr_ifgru.ifgru_group[0]); +#endif + return (&ifgrup->ifgr.ifgr_ifgru.ifgru_group[0]); +} + +static struct ifg_req * +ifgr_groups_get(void *ifgrp) +{ + union ifgroupreq_union *ifgrup; + + ifgrup = ifgrp; +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) + return ((struct ifg_req *)(uintptr_t) + ifgrup->ifgr32.ifgr_ifgru.ifgru_groups); +#endif + return (ifgrup->ifgr.ifgr_ifgru.ifgru_groups); +} + /* - * Stores all groups from an interface in memory pointed - * to by data + * Stores all groups from an interface in memory pointed to by ifgr. */ static int -if_getgroup(struct ifgroupreq *data, struct ifnet *ifp) +if_getgroup(struct ifgroupreq *ifgr, struct ifnet *ifp) { int len, error; struct ifg_list *ifgl; struct ifg_req ifgrq, *ifgp; - struct ifgroupreq *ifgr = data; if (ifgr->ifgr_len == 0) { IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) + CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) ifgr->ifgr_len += sizeof(struct ifg_req); IF_ADDR_RUNLOCK(ifp); return (0); } len = ifgr->ifgr_len; - ifgp = ifgr->ifgr_groups; + ifgp = ifgr_groups_get(ifgr); /* XXX: wire */ IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { + CK_STAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { if (len < sizeof(ifgrq)) { IF_ADDR_RUNLOCK(ifp); return (EINVAL); @@ -1547,19 +1652,18 @@ if_getgroup(struct ifgroupreq *data, struct ifnet *ifp) } /* - * Stores all members of a group in memory pointed to by data + * Stores all members of a group in memory pointed to by igfr */ static int -if_getgroupmembers(struct ifgroupreq *data) +if_getgroupmembers(struct ifgroupreq *ifgr) { - struct ifgroupreq *ifgr = data; struct ifg_group *ifg; struct ifg_member *ifgm; struct ifg_req ifgrq, *ifgp; int len, error; IFNET_RLOCK(); - TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) + CK_STAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, ifgr->ifgr_name)) break; if (ifg == NULL) { @@ -1568,15 +1672,15 @@ if_getgroupmembers(struct ifgroupreq *data) } if (ifgr->ifgr_len == 0) { - TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) + CK_STAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) ifgr->ifgr_len += sizeof(ifgrq); IFNET_RUNLOCK(); return (0); } len = ifgr->ifgr_len; - ifgp = ifgr->ifgr_groups; - TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) { + ifgp = ifgr_groups_get(ifgr); + CK_STAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) { if (len < sizeof(ifgrq)) { IFNET_RUNLOCK(); return (EINVAL); @@ -1736,19 +1840,28 @@ ifa_ref(struct ifaddr *ifa) refcount_acquire(&ifa->ifa_refcnt); } +static void +ifa_destroy(epoch_context_t ctx) +{ + struct ifaddr *ifa; + + ifa = __containerof(ctx, struct ifaddr, ifa_epoch_ctx); + counter_u64_free(ifa->ifa_opackets); + counter_u64_free(ifa->ifa_ipackets); + counter_u64_free(ifa->ifa_obytes); + counter_u64_free(ifa->ifa_ibytes); + free(ifa, M_IFADDR); +} + void ifa_free(struct ifaddr *ifa) { - if (refcount_release(&ifa->ifa_refcnt)) { - counter_u64_free(ifa->ifa_opackets); - counter_u64_free(ifa->ifa_ipackets); - counter_u64_free(ifa->ifa_obytes); - counter_u64_free(ifa->ifa_ibytes); - free(ifa, M_IFADDR); - } + if (refcount_release(&ifa->ifa_refcnt)) + epoch_call(net_epoch_preempt, &ifa->ifa_epoch_ctx, ifa_destroy); } + static int ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa, struct sockaddr *ia) @@ -1770,9 +1883,10 @@ ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa, error = rtrequest1_fib(cmd, &info, NULL, ifp->if_fib); - if (error != 0) - log(LOG_DEBUG, "%s: %s failed for interface %s: %u\n", - __func__, otype, if_name(ifp), error); + if (error != 0 && + !(cmd == RTM_ADD && error == EEXIST) && + !(cmd == RTM_DELETE && error == ENOENT)) + if_printf(ifp, "%s failed: %d\n", otype, error); return (error); } @@ -1815,22 +1929,18 @@ ifa_switch_loopback_route(struct ifaddr *ifa, struct sockaddr *ia) * Locate an interface based on a complete address. */ /*ARGSUSED*/ -static struct ifaddr * -ifa_ifwithaddr_internal(const struct sockaddr *addr, int getref) +struct ifaddr * +ifa_ifwithaddr(const struct sockaddr *addr) { struct ifnet *ifp; struct ifaddr *ifa; - IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { - IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + MPASS(in_epoch()); + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (sa_equal(addr, ifa->ifa_addr)) { - if (getref) - ifa_ref(ifa); - IF_ADDR_RUNLOCK(ifp); goto done; } /* IP6 doesn't have broadcast */ @@ -1838,32 +1948,24 @@ ifa_ifwithaddr_internal(const struct sockaddr *addr, int getref) ifa->ifa_broadaddr && ifa->ifa_broadaddr->sa_len != 0 && sa_equal(ifa->ifa_broadaddr, addr)) { - if (getref) - ifa_ref(ifa); - IF_ADDR_RUNLOCK(ifp); goto done; } } - IF_ADDR_RUNLOCK(ifp); } ifa = NULL; done: - IFNET_RUNLOCK_NOSLEEP(); return (ifa); } -struct ifaddr * -ifa_ifwithaddr(const struct sockaddr *addr) -{ - - return (ifa_ifwithaddr_internal(addr, 1)); -} - int ifa_ifwithaddr_check(const struct sockaddr *addr) { + int rc; - return (ifa_ifwithaddr_internal(addr, 0) != NULL); + NET_EPOCH_ENTER(); + rc = (ifa_ifwithaddr(addr) != NULL); + NET_EPOCH_EXIT(); + return (rc); } /* @@ -1876,28 +1978,23 @@ ifa_ifwithbroadaddr(const struct sockaddr *addr, int fibnum) struct ifnet *ifp; struct ifaddr *ifa; - IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + MPASS(in_epoch()); + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum)) continue; - IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && ifa->ifa_broadaddr->sa_len != 0 && sa_equal(ifa->ifa_broadaddr, addr)) { - ifa_ref(ifa); - IF_ADDR_RUNLOCK(ifp); goto done; } } - IF_ADDR_RUNLOCK(ifp); } ifa = NULL; done: - IFNET_RUNLOCK_NOSLEEP(); return (ifa); } @@ -1911,28 +2008,23 @@ ifa_ifwithdstaddr(const struct sockaddr *addr, int fibnum) struct ifnet *ifp; struct ifaddr *ifa; - IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + MPASS(in_epoch()); + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((ifp->if_flags & IFF_POINTOPOINT) == 0) continue; if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum)) continue; - IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (ifa->ifa_dstaddr != NULL && sa_equal(addr, ifa->ifa_dstaddr)) { - ifa_ref(ifa); - IF_ADDR_RUNLOCK(ifp); goto done; } } - IF_ADDR_RUNLOCK(ifp); } ifa = NULL; done: - IFNET_RUNLOCK_NOSLEEP(); return (ifa); } @@ -1949,6 +2041,7 @@ ifa_ifwithnet(const struct sockaddr *addr, int ignore_ptp, int fibnum) u_int af = addr->sa_family; const char *addr_data = addr->sa_data, *cplim; + MPASS(in_epoch()); /* * AF_LINK addresses can be looked up directly by their index number, * so do that if we can. @@ -1965,12 +2058,10 @@ ifa_ifwithnet(const struct sockaddr *addr, int ignore_ptp, int fibnum) * on ifa_maybe once we find one, as we release the IF_ADDR_RLOCK() that * kept it stable when we move onto the next interface. */ - IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum)) continue; - IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { const char *cp, *cp2, *cp3; if (ifa->ifa_addr->sa_family != af) @@ -1987,7 +2078,6 @@ next: continue; */ if (ifa->ifa_dstaddr != NULL && sa_equal(addr, ifa->ifa_dstaddr)) { - ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto done; } @@ -2021,21 +2111,14 @@ next: continue; ifa_preferred(ifa_maybe, ifa) || rn_refines((caddr_t)ifa->ifa_netmask, (caddr_t)ifa_maybe->ifa_netmask)) { - if (ifa_maybe != NULL) - ifa_free(ifa_maybe); ifa_maybe = ifa; - ifa_ref(ifa_maybe); } } } - IF_ADDR_RUNLOCK(ifp); } ifa = ifa_maybe; ifa_maybe = NULL; done: - IFNET_RUNLOCK_NOSLEEP(); - if (ifa_maybe != NULL) - ifa_free(ifa_maybe); return (ifa); } @@ -2054,8 +2137,8 @@ ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp) if (af >= AF_MAX) return (NULL); - IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + MPASS(in_epoch()); + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != af) continue; if (ifa_maybe == NULL) @@ -2084,9 +2167,6 @@ ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp) } ifa = ifa_maybe; done: - if (ifa != NULL) - ifa_ref(ifa); - IF_ADDR_RUNLOCK(ifp); return (ifa); } @@ -2122,14 +2202,19 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == NULL) || ((ifp = ifa->ifa_ifp) == NULL) || ((dst = rt_key(rt)) == NULL)) return; + NET_EPOCH_ENTER(); ifa = ifaof_ifpforaddr(dst, ifp); if (ifa) { oifa = rt->rt_ifa; + if (oifa != ifa) { + ifa_free(oifa); + ifa_ref(ifa); + } rt->rt_ifa = ifa; - ifa_free(oifa); if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, info); } + NET_EPOCH_EXIT(); } struct sockaddr_dl * @@ -2177,7 +2262,7 @@ if_unroute(struct ifnet *ifp, int flag, int fam) ifp->if_flags &= ~flag; getmicrotime(&ifp->if_lastchange); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFDOWN, ifa->ifa_addr); ifp->if_qflush(ifp); @@ -2200,7 +2285,7 @@ if_route(struct ifnet *ifp, int flag, int fam) ifp->if_flags |= flag; getmicrotime(&ifp->if_lastchange); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFUP, ifa->ifa_addr); if (ifp->if_carp) @@ -2255,7 +2340,7 @@ do_link_state_change(void *arg, int pending) if (ifp->if_carp) (*carp_linkstate_p)(ifp); if (ifp->if_bridge) - (*bridge_linkstate_p)(ifp); + ifp->if_bridge_linkstate(ifp); if (ifp->if_lagg) (*lagg_linkstate_p)(ifp, link_state); @@ -2266,7 +2351,7 @@ do_link_state_change(void *arg, int pending) if (pending > 1) if_printf(ifp, "%d link states coalesced\n", pending); if (log_link_state_change) - log(LOG_NOTICE, "%s: link state changed to %s\n", ifp->if_xname, + if_printf(ifp, "link state changed to %s\n", (link_state == LINK_STATE_UP) ? "UP" : "DOWN" ); EVENTHANDLER_INVOKE(ifnet_link_event, ifp, link_state); CURVNET_RESTORE(); @@ -2332,7 +2417,7 @@ ifunit_ref(const char *name) struct ifnet *ifp; IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0 && !(ifp->if_flags & IFF_DYING)) break; @@ -2349,7 +2434,7 @@ ifunit(const char *name) struct ifnet *ifp; IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0) break; } @@ -2358,13 +2443,13 @@ ifunit(const char *name) } static void * -ifr_buffer_get_buffer(struct thread *td, void *data) +ifr_buffer_get_buffer(void *data) { union ifreq_union *ifrup; ifrup = data; #ifdef COMPAT_FREEBSD32 - if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) + if (SV_CURPROC_FLAG(SV_ILP32)) return ((void *)(uintptr_t) ifrup->ifr32.ifr_ifru.ifru_buffer.buffer); #endif @@ -2372,13 +2457,13 @@ ifr_buffer_get_buffer(struct thread *td, void *data) } static void -ifr_buffer_set_buffer_null(struct thread *td, void *data) +ifr_buffer_set_buffer_null(void *data) { union ifreq_union *ifrup; ifrup = data; #ifdef COMPAT_FREEBSD32 - if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) + if (SV_CURPROC_FLAG(SV_ILP32)) ifrup->ifr32.ifr_ifru.ifru_buffer.buffer = 0; else #endif @@ -2386,26 +2471,26 @@ ifr_buffer_set_buffer_null(struct thread *td, void *data) } static size_t -ifr_buffer_get_length(struct thread *td, void *data) +ifr_buffer_get_length(void *data) { union ifreq_union *ifrup; ifrup = data; #ifdef COMPAT_FREEBSD32 - if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) + if (SV_CURPROC_FLAG(SV_ILP32)) return (ifrup->ifr32.ifr_ifru.ifru_buffer.length); #endif return (ifrup->ifr.ifr_ifru.ifru_buffer.length); } static void -ifr_buffer_set_length(struct thread *td, void *data, size_t len) +ifr_buffer_set_length(void *data, size_t len) { union ifreq_union *ifrup; ifrup = data; #ifdef COMPAT_FREEBSD32 - if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) + if (SV_CURPROC_FLAG(SV_ILP32)) ifrup->ifr32.ifr_ifru.ifru_buffer.length = len; else #endif @@ -2486,12 +2571,12 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) else { /* space for terminating nul */ descrlen = strlen(ifp->if_description) + 1; - if (ifr_buffer_get_length(td, ifr) < descrlen) - ifr_buffer_set_buffer_null(td, ifr); + if (ifr_buffer_get_length(ifr) < descrlen) + ifr_buffer_set_buffer_null(ifr); else error = copyout(ifp->if_description, - ifr_buffer_get_buffer(td, ifr), descrlen); - ifr_buffer_set_length(td, ifr, descrlen); + ifr_buffer_get_buffer(ifr), descrlen); + ifr_buffer_set_length(ifr, descrlen); } sx_sunlock(&ifdescr_sx); break; @@ -2507,15 +2592,15 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) * length parameter is supposed to count the * terminating nul in. */ - if (ifr_buffer_get_length(td, ifr) > ifdescr_maxlen) + if (ifr_buffer_get_length(ifr) > ifdescr_maxlen) return (ENAMETOOLONG); - else if (ifr_buffer_get_length(td, ifr) == 0) + else if (ifr_buffer_get_length(ifr) == 0) descrbuf = NULL; else { - descrbuf = malloc(ifr_buffer_get_length(td, ifr), + descrbuf = malloc(ifr_buffer_get_length(ifr), M_IFDESCR, M_WAITOK | M_ZERO); - error = copyin(ifr_buffer_get_buffer(td, ifr), descrbuf, - ifr_buffer_get_length(td, ifr) - 1); + error = copyin(ifr_buffer_get_buffer(ifr), descrbuf, + ifr_buffer_get_length(ifr) - 1); if (error) { free(descrbuf, M_IFDESCR); break; @@ -2569,8 +2654,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) else if (ifp->if_pcount == 0) ifp->if_flags &= ~IFF_PROMISC; if (log_promisc_mode_change) - log(LOG_INFO, "%s: permanently promiscuous mode %s\n", - ifp->if_xname, + if_printf(ifp, "permanently promiscuous mode %s\n", ((new_flags & IFF_PPROMISC) ? "enabled" : "disabled")); } @@ -2633,8 +2717,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) rt_ifannouncemsg(ifp, IFAN_DEPARTURE); EVENTHANDLER_INVOKE(ifnet_departure_event, ifp); - log(LOG_INFO, "%s: changing name to '%s'\n", - ifp->if_xname, new_name); + if_printf(ifp, "changing name to '%s'\n", new_name); IF_ADDR_WLOCK(ifp); strlcpy(ifp->if_xname, new_name, sizeof(ifp->if_xname)); @@ -2709,6 +2792,9 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) if (error == 0) { getmicrotime(&ifp->if_lastchange); rt_ifmsg(ifp); +#ifdef INET + NETDUMP_REINIT(ifp); +#endif } /* * If the link MTU changed, do network layer specific procedure. @@ -2805,34 +2891,28 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) error = if_gethwaddr(ifp, ifr); break; - case SIOCAIFGROUP: - { - struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr; - + CASE_IOC_IFGROUPREQ(SIOCAIFGROUP): error = priv_check(td, PRIV_NET_ADDIFGROUP); if (error) return (error); - if ((error = if_addgroup(ifp, ifgr->ifgr_group))) + if ((error = if_addgroup(ifp, + ifgr_group_get((struct ifgroupreq *)data)))) return (error); break; - } - case SIOCGIFGROUP: - if ((error = if_getgroup((struct ifgroupreq *)ifr, ifp))) + CASE_IOC_IFGROUPREQ(SIOCGIFGROUP): + if ((error = if_getgroup((struct ifgroupreq *)data, ifp))) return (error); break; - case SIOCDIFGROUP: - { - struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr; - + CASE_IOC_IFGROUPREQ(SIOCDIFGROUP): error = priv_check(td, PRIV_NET_DELIFGROUP); if (error) return (error); - if ((error = if_delgroup(ifp, ifgr->ifgr_group))) + if ((error = if_delgroup(ifp, + ifgr_group_get((struct ifgroupreq *)data)))) return (error); break; - } #ifdef __rtems__ case RTEMS_SIOSIFINPUT: @@ -2868,12 +2948,48 @@ struct ifconf32 { #define SIOCGIFCONF32 _IOWR('i', 36, struct ifconf32) #endif +#ifdef COMPAT_FREEBSD32 +static void +ifmr_init(struct ifmediareq *ifmr, caddr_t data) +{ + struct ifmediareq32 *ifmr32; + + ifmr32 = (struct ifmediareq32 *)data; + memcpy(ifmr->ifm_name, ifmr32->ifm_name, + sizeof(ifmr->ifm_name)); + ifmr->ifm_current = ifmr32->ifm_current; + ifmr->ifm_mask = ifmr32->ifm_mask; + ifmr->ifm_status = ifmr32->ifm_status; + ifmr->ifm_active = ifmr32->ifm_active; + ifmr->ifm_count = ifmr32->ifm_count; + ifmr->ifm_ulist = (int *)(uintptr_t)ifmr32->ifm_ulist; +} + +static void +ifmr_update(const struct ifmediareq *ifmr, caddr_t data) +{ + struct ifmediareq32 *ifmr32; + + ifmr32 = (struct ifmediareq32 *)data; + ifmr32->ifm_current = ifmr->ifm_current; + ifmr32->ifm_mask = ifmr->ifm_mask; + ifmr32->ifm_status = ifmr->ifm_status; + ifmr32->ifm_active = ifmr->ifm_active; + ifmr32->ifm_count = ifmr->ifm_count; +} +#endif + /* * Interface ioctls. */ int ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) { +#ifdef COMPAT_FREEBSD32 + caddr_t saved_data = NULL; + struct ifmediareq ifmr; +#endif + struct ifmediareq *ifmrp; struct ifnet *ifp; struct ifreq *ifr; int error; @@ -2918,8 +3034,21 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) } #endif } - ifr = (struct ifreq *)data; + ifmrp = NULL; +#ifdef COMPAT_FREEBSD32 + switch (cmd) { + case SIOCGIFMEDIA32: + case SIOCGIFXMEDIA32: + ifmrp = &ifmr; + ifmr_init(ifmrp, data); + cmd = _IOC_NEWTYPE(cmd, struct ifmediareq); + saved_data = data; + data = (caddr_t)ifmrp; + } +#endif + + ifr = (struct ifreq *)data; switch (cmd) { #ifdef VIMAGE case SIOCSIFRVNET: @@ -2927,8 +3056,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) if (error == 0) error = if_vmove_reclaim(td, ifr->ifr_name, ifr->ifr_jid); - CURVNET_RESTORE(); - return (error); + goto out_noref; #endif case SIOCIFCREATE: case SIOCIFCREATE2: @@ -2937,23 +3065,21 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) error = if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name), cmd == SIOCIFCREATE2 ? ifr_data_get_ptr(ifr) : NULL); - CURVNET_RESTORE(); - return (error); + goto out_noref; case SIOCIFDESTROY: error = priv_check(td, PRIV_NET_IFDESTROY); if (error == 0) error = if_clone_destroy(ifr->ifr_name); - CURVNET_RESTORE(); - return (error); + goto out_noref; case SIOCIFGCLONERS: error = if_clone_list((struct if_clonereq *)data); - CURVNET_RESTORE(); - return (error); - case SIOCGIFGMEMB: + goto out_noref; + + CASE_IOC_IFGROUPREQ(SIOCGIFGMEMB): error = if_getgroupmembers((struct ifgroupreq *)data); - CURVNET_RESTORE(); - return (error); + goto out_noref; + #if defined(INET) || defined(INET6) case SIOCSVH: case SIOCGVH: @@ -2961,29 +3087,24 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) error = EPROTONOSUPPORT; else error = (*carp_ioctl_p)(ifr, cmd, td); - CURVNET_RESTORE(); - return (error); + goto out_noref; #endif } ifp = ifunit_ref(ifr->ifr_name); if (ifp == NULL) { - CURVNET_RESTORE(); - return (ENXIO); + error = ENXIO; + goto out_noref; } error = ifhwioctl(cmd, ifp, data, td); - if (error != ENOIOCTL) { - if_rele(ifp); - CURVNET_RESTORE(); - return (error); - } + if (error != ENOIOCTL) + goto out_ref; oif_flags = ifp->if_flags; if (so->so_proto == NULL) { - if_rele(ifp); - CURVNET_RESTORE(); - return (EOPNOTSUPP); + error = EOPNOTSUPP; + goto out_ref; } /* @@ -3008,7 +3129,19 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) in6_if_up(ifp); #endif } + +out_ref: if_rele(ifp); +out_noref: +#ifdef COMPAT_FREEBSD32 + if (ifmrp != NULL) { + KASSERT((cmd == SIOCGIFMEDIA || cmd == SIOCGIFXMEDIA), + ("ifmrp non-NULL, but cmd is not an ifmedia req 0x%lx", + cmd)); + data = saved_data; + ifmr_update(ifmrp, data); + } +#endif CURVNET_RESTORE(); return (error); } @@ -3103,8 +3236,7 @@ ifpromisc(struct ifnet *ifp, int pswitch) /* If promiscuous mode status has changed, log a message */ if (error == 0 && ((ifp->if_flags ^ oldflags) & IFF_PROMISC) && log_promisc_mode_change) - log(LOG_INFO, "%s: promiscuous mode %s\n", - ifp->if_xname, + if_printf(ifp, "promiscuous mode %s\n", (ifp->if_flags & IFF_PROMISC) ? "enabled" : "disabled"); return (error); } @@ -3143,14 +3275,14 @@ again: valid_len = 0; IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { int addrs; /* - * Zero the ifr_name buffer to make sure we don't - * disclose the contents of the stack. + * Zero the ifr to make sure we don't disclose the contents + * of the stack. */ - memset(ifr.ifr_name, 0, sizeof(ifr.ifr_name)); + memset(&ifr, 0, sizeof(ifr)); if (strlcpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)) >= sizeof(ifr.ifr_name)) { @@ -3161,14 +3293,20 @@ again: addrs = 0; IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { struct sockaddr *sa = ifa->ifa_addr; if (prison_if(curthread->td_ucred, sa) != 0) continue; addrs++; if (sa->sa_len <= sizeof(*sa)) { - ifr.ifr_addr = *sa; + if (sa->sa_len < sizeof(*sa)) { + memset(&ifr.ifr_ifru.ifru_addr, 0, + sizeof(ifr.ifr_ifru.ifru_addr)); + memcpy(&ifr.ifr_ifru.ifru_addr, sa, + sa->sa_len); + } else + ifr.ifr_ifru.ifru_addr = *sa; sbuf_bcat(sb, &ifr, sizeof(ifr)); max_len += sizeof(ifr); } else { @@ -3184,7 +3322,6 @@ again: } IF_ADDR_RUNLOCK(ifp); if (addrs == 0) { - bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); sbuf_bcat(sb, &ifr, sizeof(ifr)); max_len += sizeof(ifr); @@ -3228,7 +3365,7 @@ if_findmulti(struct ifnet *ifp, const struct sockaddr *sa) IF_ADDR_LOCK_ASSERT(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (sa->sa_family == AF_LINK) { if (sa_dl_equal(ifma->ifma_addr, sa)) break; @@ -3295,8 +3432,11 @@ if_allocmulti(struct ifnet *ifp, struct sockaddr *sa, struct sockaddr *llsa, * counting, notifying the driver, handling routing messages, and releasing * any dependent link layer state. */ +#ifdef MCAST_VERBOSE +extern void kdb_backtrace(void); +#endif static void -if_freemulti(struct ifmultiaddr *ifma) +if_freemulti_internal(struct ifmultiaddr *ifma) { KASSERT(ifma->ifma_refcount == 0, ("if_freemulti: refcount %d", @@ -3304,10 +3444,33 @@ if_freemulti(struct ifmultiaddr *ifma) if (ifma->ifma_lladdr != NULL) free(ifma->ifma_lladdr, M_IFMADDR); +#ifdef MCAST_VERBOSE + kdb_backtrace(); + printf("%s freeing ifma: %p\n", __func__, ifma); +#endif free(ifma->ifma_addr, M_IFMADDR); free(ifma, M_IFMADDR); } +static void +if_destroymulti(epoch_context_t ctx) +{ + struct ifmultiaddr *ifma; + + ifma = __containerof(ctx, struct ifmultiaddr, ifma_epoch_ctx); + if_freemulti_internal(ifma); +} + +void +if_freemulti(struct ifmultiaddr *ifma) +{ + KASSERT(ifma->ifma_refcount == 0, ("if_freemulti_epoch: refcount %d", + ifma->ifma_refcount)); + + epoch_call(net_epoch_preempt, &ifma->ifma_epoch_ctx, if_destroymulti); +} + + /* * Register an additional multicast address with a network interface. * @@ -3335,6 +3498,12 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa, struct sockaddr_dl sdl; int error; +#ifdef INET + IN_MULTI_LIST_UNLOCK_ASSERT(); +#endif +#ifdef INET6 + IN6_MULTI_LIST_UNLOCK_ASSERT(); +#endif /* * If the address is already present, return a new reference to it; * otherwise, allocate storage and set up a new address. @@ -3395,7 +3564,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa, error = ENOMEM; goto free_llsa_out; } - TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma, + CK_STAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma, ifma_link); } else ll_ifma->ifma_refcount++; @@ -3407,7 +3576,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa, * referenced link layer address. Add the primary address to the * ifnet address list. */ - TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); + CK_STAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); if (retifma != NULL) *retifma = ifma; @@ -3459,7 +3628,7 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa) struct ifnet *oifp; IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(oifp, &V_ifnet, if_link) + CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link) if (ifp == oifp) break; if (ifp != oifp) @@ -3499,11 +3668,17 @@ if_delallmulti(struct ifnet *ifp) struct ifmultiaddr *next; IF_ADDR_WLOCK(ifp); - TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) + CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) if_delmulti_locked(ifp, ifma, 0); IF_ADDR_WUNLOCK(ifp); } +void +if_delmulti_ifma(struct ifmultiaddr *ifma) +{ + if_delmulti_ifma_flags(ifma, 0); +} + /* * Delete a multicast group membership by group membership pointer. * Network-layer protocol domains must use this routine. @@ -3511,11 +3686,14 @@ if_delallmulti(struct ifnet *ifp) * It is safe to call this routine if the ifp disappeared. */ void -if_delmulti_ifma(struct ifmultiaddr *ifma) +if_delmulti_ifma_flags(struct ifmultiaddr *ifma, int flags) { struct ifnet *ifp; int lastref; - + MCDPRINTF("%s freeing ifma: %p\n", __func__, ifma); +#ifdef INET + IN_MULTI_LIST_UNLOCK_ASSERT(); +#endif ifp = ifma->ifma_ifp; #ifdef DIAGNOSTIC if (ifp == NULL) { @@ -3524,13 +3702,11 @@ if_delmulti_ifma(struct ifmultiaddr *ifma) struct ifnet *oifp; IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(oifp, &V_ifnet, if_link) + CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link) if (ifp == oifp) break; - if (ifp != oifp) { - printf("%s: ifnet %p disappeared\n", __func__, ifp); + if (ifp != oifp) ifp = NULL; - } IFNET_RUNLOCK_NOSLEEP(); } #endif @@ -3540,7 +3716,7 @@ if_delmulti_ifma(struct ifmultiaddr *ifma) if (ifp != NULL) IF_ADDR_WLOCK(ifp); - lastref = if_delmulti_locked(ifp, ifma, 0); + lastref = if_delmulti_locked(ifp, ifma, flags); if (ifp != NULL) { /* @@ -3574,6 +3750,7 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching) } ifp = ifma->ifma_ifp; + MCDPRINTF("%s freeing %p from %s \n", __func__, ifma, ifp ? ifp->if_xname : ""); /* * If the ifnet is detaching, null out references to ifnet, @@ -3599,6 +3776,9 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching) if (--ifma->ifma_refcount > 0) return 0; + if (ifp != NULL && detaching == 0) + CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link); + /* * If this ifma is a network-layer ifma, a link-layer ifma may * have been associated with it. Release it first if so. @@ -3611,18 +3791,21 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching) ll_ifma->ifma_ifp = NULL; /* XXX */ if (--ll_ifma->ifma_refcount == 0) { if (ifp != NULL) { - TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, + CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr, ifma_link); } if_freemulti(ll_ifma); } } +#ifdef INVARIANTS + if (ifp) { + struct ifmultiaddr *ifmatmp; - if (ifp != NULL) - TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); - + CK_STAILQ_FOREACH(ifmatmp, &ifp->if_multiaddrs, ifma_link) + MPASS(ifma != ifmatmp); + } +#endif if_freemulti(ifma); - /* * The last reference to this instance of struct ifmultiaddr * was released; the hardware should be notified of this change. @@ -3644,38 +3827,36 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) struct sockaddr_dl *sdl; struct ifaddr *ifa; struct ifreq ifr; + int rc; - IF_ADDR_RLOCK(ifp); + rc = 0; + NET_EPOCH_ENTER(); ifa = ifp->if_addr; if (ifa == NULL) { - IF_ADDR_RUNLOCK(ifp); - return (EINVAL); + rc = EINVAL; + goto out; } - ifa_ref(ifa); - IF_ADDR_RUNLOCK(ifp); + sdl = (struct sockaddr_dl *)ifa->ifa_addr; if (sdl == NULL) { - ifa_free(ifa); - return (EINVAL); + rc = EINVAL; + goto out; } if (len != sdl->sdl_alen) { /* don't allow length to change */ - ifa_free(ifa); - return (EINVAL); + rc = EINVAL; + goto out; } switch (ifp->if_type) { case IFT_ETHER: - case IFT_FDDI: case IFT_XETHER: case IFT_L2VLAN: case IFT_BRIDGE: - case IFT_ARCNET: case IFT_IEEE8023ADLAG: bcopy(lladdr, LLADDR(sdl), len); - ifa_free(ifa); break; default: - ifa_free(ifa); - return (ENODEV); + rc = ENODEV; + goto out; } /* @@ -3683,6 +3864,7 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) * to re-init it in order to reprogram its * address filter. */ + NET_EPOCH_EXIT(); if ((ifp->if_flags & IFF_UP) != 0) { if (ifp->if_ioctl) { ifp->if_flags &= ~IFF_UP; @@ -3697,6 +3879,9 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) } EVENTHANDLER_INVOKE(iflladdr_event, ifp); return (0); + out: + NET_EPOCH_EXIT(); + return (rc); } /* @@ -3777,16 +3962,16 @@ if_initname(struct ifnet *ifp, const char *name, int unit) } int -if_printf(struct ifnet *ifp, const char * fmt, ...) +if_printf(struct ifnet *ifp, const char *fmt, ...) { + char if_fmt[256]; va_list ap; - int retval; - retval = printf("%s: ", ifp->if_xname); + snprintf(if_fmt, sizeof(if_fmt), "%s: %s", ifp->if_xname, fmt); va_start(ap, fmt); - retval += vprintf(fmt, ap); + vlog(LOG_INFO, if_fmt, ap); va_end(ap); - return (retval); + return (0); } void @@ -4149,7 +4334,7 @@ if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max) uint8_t *lmta = (uint8_t *)mta; int mcnt = 0; - TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -4184,7 +4369,7 @@ if_multiaddr_count(if_t ifp, int max) count = 0; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; count++; @@ -4202,7 +4387,7 @@ if_multi_apply(struct ifnet *ifp, int (*filter)(void *, struct ifmultiaddr *, in int cnt = 0; if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) cnt += filter(arg, ifma, cnt); if_maddr_runlock(ifp); return (cnt); diff --git a/freebsd/sys/net/if_arc.h b/freebsd/sys/net/if_arc.h deleted file mode 100644 index 8bed38b8..00000000 --- a/freebsd/sys/net/if_arc.h +++ /dev/null @@ -1,145 +0,0 @@ -/* $NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp $ */ -/* $FreeBSD$ */ - -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1982, 1986, 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: NetBSD: if_ether.h,v 1.10 1994/06/29 06:37:55 cgd Exp - * @(#)if_ether.h 8.1 (Berkeley) 6/10/93 - */ - -#ifndef _NET_IF_ARC_H_ -#define _NET_IF_ARC_H_ - -/* - * Arcnet address - 1 octets - * don't know who uses this. - */ -struct arc_addr { - u_int8_t arc_addr_octet[1]; -} __packed; - -/* - * Structure of a 2.5MB/s Arcnet header. - * as given to interface code. - */ -struct arc_header { - u_int8_t arc_shost; - u_int8_t arc_dhost; - u_int8_t arc_type; - /* - * only present for newstyle encoding with LL fragmentation. - * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead. - */ - u_int8_t arc_flag; - u_int16_t arc_seqid; - - /* - * only present in exception packets (arc_flag == 0xff) - */ - u_int8_t arc_type2; /* same as arc_type */ - u_int8_t arc_flag2; /* real flag value */ - u_int16_t arc_seqid2; /* real seqid value */ -} __packed; - -#define ARC_ADDR_LEN 1 - -#define ARC_HDRLEN 3 -#define ARC_HDRNEWLEN 6 -#define ARC_HDRNEWLEN_EXC 10 - -/* these lengths are data link layer length - 2 * ARC_ADDR_LEN */ -#define ARC_MIN_LEN 1 -#define ARC_MIN_FORBID_LEN 254 -#define ARC_MAX_FORBID_LEN 256 -#define ARC_MAX_LEN 508 -#define ARC_MAX_DATA 504 - -/* RFC 1051 */ -#define ARCTYPE_IP_OLD 240 /* IP protocol */ -#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ - -/* RFC 1201 */ -#define ARCTYPE_IP 212 /* IP protocol */ -#define ARCTYPE_ARP 213 /* address resolution protocol */ -#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ - -#define ARCTYPE_ATALK 221 /* Appletalk */ -#define ARCTYPE_BANIAN 247 /* Banyan Vines */ -#define ARCTYPE_IPX 250 /* Novell IPX */ - -#define ARCTYPE_INET6 0xc4 /* IPng */ -#define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */ - -#define ARCMTU 507 -#define ARCMIN 0 - -#define ARC_PHDS_MAXMTU 60480 - -struct arccom { - struct ifnet *ac_ifp; /* network-visible interface */ - - u_int16_t ac_seqid; /* seq. id used by PHDS encap. */ - - u_int8_t arc_shost; - u_int8_t arc_dhost; - u_int8_t arc_type; - - u_int8_t dummy0; - u_int16_t dummy1; - int sflag, fsflag, rsflag; - struct mbuf *curr_frag; - - struct ac_frag { - u_int8_t af_maxflag; /* from first packet */ - u_int8_t af_lastseen; /* last split flag seen */ - u_int16_t af_seqid; - struct mbuf *af_packet; - } ac_fragtab[256]; /* indexed by sender ll address */ -}; - -#ifdef _KERNEL -extern u_int8_t arcbroadcastaddr; -extern int arc_ipmtu; /* XXX new ip only, no RFC 1051! */ - -void arc_ifattach(struct ifnet *, u_int8_t); -void arc_ifdetach(struct ifnet *); -void arc_storelladdr(struct ifnet *, u_int8_t); -int arc_isphds(u_int8_t); -void arc_input(struct ifnet *, struct mbuf *); -int arc_output(struct ifnet *, struct mbuf *, - const struct sockaddr *, struct route *); -int arc_ioctl(struct ifnet *, u_long, caddr_t); - -void arc_frag_init(struct ifnet *); -struct mbuf * arc_frag_next(struct ifnet *); -#endif - -#endif /* _NET_IF_ARC_H_ */ diff --git a/freebsd/sys/net/if_arcsubr.c b/freebsd/sys/net/if_arcsubr.c deleted file mode 100644 index 9f0a03d5..00000000 --- a/freebsd/sys/net/if_arcsubr.c +++ /dev/null @@ -1,833 +0,0 @@ -#include <machine/rtems-bsd-kernel-space.h> - -/* $NetBSD: if_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $ */ -/* $FreeBSD$ */ - -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1994, 1995 Ignatios Souvatzis - * Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. 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: NetBSD: if_ethersubr.c,v 1.9 1994/06/29 06:36:11 cgd Exp - * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 - * - */ -#include <rtems/bsd/local/opt_inet.h> -#include <rtems/bsd/local/opt_inet6.h> - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <sys/errno.h> -#include <sys/syslog.h> - -#include <machine/cpu.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/netisr.h> -#include <net/route.h> -#include <net/if_dl.h> -#include <net/if_types.h> -#include <net/if_arc.h> -#include <net/if_arp.h> -#include <net/bpf.h> -#include <net/if_llatbl.h> - -#if defined(INET) || defined(INET6) -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/if_ether.h> -#endif - -#ifdef INET6 -#include <netinet6/nd6.h> -#endif - -#define ARCNET_ALLOW_BROKEN_ARP - -static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); -static int arc_resolvemulti(struct ifnet *, struct sockaddr **, - struct sockaddr *); - -u_int8_t arcbroadcastaddr = 0; - -#define ARC_LLADDR(ifp) (*(u_int8_t *)IF_LLADDR(ifp)) - -#define senderr(e) { error = (e); goto bad;} -#define SIN(s) ((const struct sockaddr_in *)(s)) - -/* - * ARCnet output routine. - * Encapsulate a packet of type family for the local net. - * Assumes that ifp is actually pointer to arccom structure. - */ -int -arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, - struct route *ro) -{ - struct arc_header *ah; - int error; - u_int8_t atype, adst; - int loop_copy = 0; - int isphds; -#if defined(INET) || defined(INET6) - int is_gw = 0; -#endif - - if (!((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING))) - return(ENETDOWN); /* m, m1 aren't initialized yet */ - - error = 0; -#if defined(INET) || defined(INET6) - if (ro != NULL) - is_gw = (ro->ro_flags & RT_HAS_GW) != 0; -#endif - - switch (dst->sa_family) { -#ifdef INET - case AF_INET: - - /* - * For now, use the simple IP addr -> ARCnet addr mapping - */ - if (m->m_flags & (M_BCAST|M_MCAST)) - adst = arcbroadcastaddr; /* ARCnet broadcast address */ - else if (ifp->if_flags & IFF_NOARP) - adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; - else { - error = arpresolve(ifp, is_gw, m, dst, &adst, NULL, - NULL); - if (error) - return (error == EWOULDBLOCK ? 0 : error); - } - - atype = (ifp->if_flags & IFF_LINK0) ? - ARCTYPE_IP_OLD : ARCTYPE_IP; - break; - case AF_ARP: - { - struct arphdr *ah; - ah = mtod(m, struct arphdr *); - ah->ar_hrd = htons(ARPHRD_ARCNET); - - loop_copy = -1; /* if this is for us, don't do it */ - - switch(ntohs(ah->ar_op)) { - case ARPOP_REVREQUEST: - case ARPOP_REVREPLY: - atype = ARCTYPE_REVARP; - break; - case ARPOP_REQUEST: - case ARPOP_REPLY: - default: - atype = ARCTYPE_ARP; - break; - } - - if (m->m_flags & M_BCAST) - bcopy(ifp->if_broadcastaddr, &adst, ARC_ADDR_LEN); - else - bcopy(ar_tha(ah), &adst, ARC_ADDR_LEN); - - } - break; -#endif -#ifdef INET6 - case AF_INET6: - if ((m->m_flags & M_MCAST) != 0) - adst = arcbroadcastaddr; /* ARCnet broadcast address */ - else { - error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL, - NULL); - if (error != 0) - return (error == EWOULDBLOCK ? 0 : error); - } - atype = ARCTYPE_INET6; - break; -#endif - case AF_UNSPEC: - { - const struct arc_header *ah; - - loop_copy = -1; - ah = (const struct arc_header *)dst->sa_data; - adst = ah->arc_dhost; - atype = ah->arc_type; - - if (atype == ARCTYPE_ARP) { - atype = (ifp->if_flags & IFF_LINK0) ? - ARCTYPE_ARP_OLD: ARCTYPE_ARP; - -#ifdef ARCNET_ALLOW_BROKEN_ARP - /* - * XXX It's not clear per RFC826 if this is needed, but - * "assigned numbers" say this is wrong. - * However, e.g., AmiTCP 3.0Beta used it... we make this - * switchable for emergency cases. Not perfect, but... - */ - if (ifp->if_flags & IFF_LINK2) - mtod(m, struct arphdr *)->ar_pro = atype - 1; -#endif - } - break; - } - default: - if_printf(ifp, "can't handle af%d\n", dst->sa_family); - senderr(EAFNOSUPPORT); - } - - isphds = arc_isphds(atype); - M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_NOWAIT); - if (m == NULL) - senderr(ENOBUFS); - ah = mtod(m, struct arc_header *); - ah->arc_type = atype; - ah->arc_dhost = adst; - ah->arc_shost = ARC_LLADDR(ifp); - if (isphds) { - ah->arc_flag = 0; - ah->arc_seqid = 0; - } - - if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { - if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { - struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT); - - (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); - } else if (ah->arc_dhost == ah->arc_shost) { - (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); - return (0); /* XXX */ - } - } - - BPF_MTAP(ifp, m); - - error = ifp->if_transmit(ifp, m); - - return (error); - -bad: - if (m) - m_freem(m); - return (error); -} - -void -arc_frag_init(struct ifnet *ifp) -{ - struct arccom *ac; - - ac = (struct arccom *)ifp->if_l2com; - ac->curr_frag = 0; -} - -struct mbuf * -arc_frag_next(struct ifnet *ifp) -{ - struct arccom *ac; - struct mbuf *m; - struct arc_header *ah; - - ac = (struct arccom *)ifp->if_l2com; - if ((m = ac->curr_frag) == NULL) { - int tfrags; - - /* dequeue new packet */ - IF_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - return 0; - - ah = mtod(m, struct arc_header *); - if (!arc_isphds(ah->arc_type)) - return m; - - ++ac->ac_seqid; /* make the seqid unique */ - tfrags = howmany(m->m_pkthdr.len, ARC_MAX_DATA); - ac->fsflag = 2 * tfrags - 3; - ac->sflag = 0; - ac->rsflag = ac->fsflag; - ac->arc_dhost = ah->arc_dhost; - ac->arc_shost = ah->arc_shost; - ac->arc_type = ah->arc_type; - - m_adj(m, ARC_HDRNEWLEN); - ac->curr_frag = m; - } - - /* split out next fragment and return it */ - if (ac->sflag < ac->fsflag) { - /* we CAN'T have short packets here */ - ac->curr_frag = m_split(m, ARC_MAX_DATA, M_NOWAIT); - if (ac->curr_frag == 0) { - m_freem(m); - return 0; - } - - M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); - if (m == NULL) { - m_freem(ac->curr_frag); - ac->curr_frag = 0; - return 0; - } - - ah = mtod(m, struct arc_header *); - ah->arc_flag = ac->rsflag; - ah->arc_seqid = ac->ac_seqid; - - ac->sflag += 2; - ac->rsflag = ac->sflag; - } else if ((m->m_pkthdr.len >= - ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && - (m->m_pkthdr.len <= - ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { - ac->curr_frag = 0; - - M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_NOWAIT); - if (m == NULL) - return 0; - - ah = mtod(m, struct arc_header *); - ah->arc_flag = 0xFF; - ah->arc_seqid = 0xFFFF; - ah->arc_type2 = ac->arc_type; - ah->arc_flag2 = ac->sflag; - ah->arc_seqid2 = ac->ac_seqid; - } else { - ac->curr_frag = 0; - - M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); - if (m == NULL) - return 0; - - ah = mtod(m, struct arc_header *); - ah->arc_flag = ac->sflag; - ah->arc_seqid = ac->ac_seqid; - } - - ah->arc_dhost = ac->arc_dhost; - ah->arc_shost = ac->arc_shost; - ah->arc_type = ac->arc_type; - - return m; -} - -/* - * Defragmenter. Returns mbuf if last packet found, else - * NULL. frees incoming mbuf as necessary. - */ - -static __inline struct mbuf * -arc_defrag(struct ifnet *ifp, struct mbuf *m) -{ - struct arc_header *ah, *ah1; - struct arccom *ac; - struct ac_frag *af; - struct mbuf *m1; - char *s; - int newflen; - u_char src,dst,typ; - - ac = (struct arccom *)ifp->if_l2com; - - if (m->m_len < ARC_HDRNEWLEN) { - m = m_pullup(m, ARC_HDRNEWLEN); - if (m == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - return NULL; - } - } - - ah = mtod(m, struct arc_header *); - typ = ah->arc_type; - - if (!arc_isphds(typ)) - return m; - - src = ah->arc_shost; - dst = ah->arc_dhost; - - if (ah->arc_flag == 0xff) { - m_adj(m, 4); - - if (m->m_len < ARC_HDRNEWLEN) { - m = m_pullup(m, ARC_HDRNEWLEN); - if (m == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - return NULL; - } - } - - ah = mtod(m, struct arc_header *); - } - - af = &ac->ac_fragtab[src]; - m1 = af->af_packet; - s = "debug code error"; - - if (ah->arc_flag & 1) { - /* - * first fragment. We always initialize, which is - * about the right thing to do, as we only want to - * accept one fragmented packet per src at a time. - */ - if (m1 != NULL) - m_freem(m1); - - af->af_packet = m; - m1 = m; - af->af_maxflag = ah->arc_flag; - af->af_lastseen = 0; - af->af_seqid = ah->arc_seqid; - - return NULL; - /* notreached */ - } else { - /* check for unfragmented packet */ - if (ah->arc_flag == 0) - return m; - - /* do we have a first packet from that src? */ - if (m1 == NULL) { - s = "no first frag"; - goto outofseq; - } - - ah1 = mtod(m1, struct arc_header *); - - if (ah->arc_seqid != ah1->arc_seqid) { - s = "seqid differs"; - goto outofseq; - } - - if (typ != ah1->arc_type) { - s = "type differs"; - goto outofseq; - } - - if (dst != ah1->arc_dhost) { - s = "dest host differs"; - goto outofseq; - } - - /* typ, seqid and dst are ok here. */ - - if (ah->arc_flag == af->af_lastseen) { - m_freem(m); - return NULL; - } - - if (ah->arc_flag == af->af_lastseen + 2) { - /* ok, this is next fragment */ - af->af_lastseen = ah->arc_flag; - m_adj(m,ARC_HDRNEWLEN); - - /* - * m_cat might free the first mbuf (with pkthdr) - * in 2nd chain; therefore: - */ - - newflen = m->m_pkthdr.len; - - m_cat(m1,m); - - m1->m_pkthdr.len += newflen; - - /* is it the last one? */ - if (af->af_lastseen > af->af_maxflag) { - af->af_packet = NULL; - return(m1); - } else - return NULL; - } - s = "other reason"; - /* if all else fails, it is out of sequence, too */ - } -outofseq: - if (m1) { - m_freem(m1); - af->af_packet = NULL; - } - - if (m) - m_freem(m); - - log(LOG_INFO,"%s: got out of seq. packet: %s\n", - ifp->if_xname, s); - - return NULL; -} - -/* - * return 1 if Packet Header Definition Standard, else 0. - * For now: old IP, old ARP aren't obviously. Lacking correct information, - * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. - * (Apple and Novell corporations were involved, among others, in PHDS work). - * Easiest is to assume that everybody else uses that, too. - */ -int -arc_isphds(u_int8_t type) -{ - return (type != ARCTYPE_IP_OLD && - type != ARCTYPE_ARP_OLD && - type != ARCTYPE_DIAGNOSE); -} - -/* - * Process a received Arcnet packet; - * the packet is in the mbuf chain m with - * the ARCnet header. - */ -void -arc_input(struct ifnet *ifp, struct mbuf *m) -{ - struct arc_header *ah; - int isr; - u_int8_t atype; - - if ((ifp->if_flags & IFF_UP) == 0) { - m_freem(m); - return; - } - - /* possibly defragment: */ - m = arc_defrag(ifp, m); - if (m == NULL) - return; - - BPF_MTAP(ifp, m); - - ah = mtod(m, struct arc_header *); - /* does this belong to us? */ - if ((ifp->if_flags & IFF_PROMISC) == 0 - && ah->arc_dhost != arcbroadcastaddr - && ah->arc_dhost != ARC_LLADDR(ifp)) { - m_freem(m); - return; - } - - if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); - - if (ah->arc_dhost == arcbroadcastaddr) { - m->m_flags |= M_BCAST|M_MCAST; - if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); - } - - atype = ah->arc_type; - switch (atype) { -#ifdef INET - case ARCTYPE_IP: - m_adj(m, ARC_HDRNEWLEN); - isr = NETISR_IP; - break; - - case ARCTYPE_IP_OLD: - m_adj(m, ARC_HDRLEN); - isr = NETISR_IP; - break; - - case ARCTYPE_ARP: - if (ifp->if_flags & IFF_NOARP) { - /* Discard packet if ARP is disabled on interface */ - m_freem(m); - return; - } - m_adj(m, ARC_HDRNEWLEN); - isr = NETISR_ARP; -#ifdef ARCNET_ALLOW_BROKEN_ARP - mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); -#endif - break; - - case ARCTYPE_ARP_OLD: - if (ifp->if_flags & IFF_NOARP) { - /* Discard packet if ARP is disabled on interface */ - m_freem(m); - return; - } - m_adj(m, ARC_HDRLEN); - isr = NETISR_ARP; -#ifdef ARCNET_ALLOW_BROKEN_ARP - mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); -#endif - break; -#endif -#ifdef INET6 - case ARCTYPE_INET6: - m_adj(m, ARC_HDRNEWLEN); - isr = NETISR_IPV6; - break; -#endif - default: - m_freem(m); - return; - } - M_SETFIB(m, ifp->if_fib); - netisr_dispatch(isr, m); -} - -/* - * Register (new) link level address. - */ -void -arc_storelladdr(struct ifnet *ifp, u_int8_t lla) -{ - ARC_LLADDR(ifp) = lla; -} - -/* - * Perform common duties while attaching to interface list - */ -void -arc_ifattach(struct ifnet *ifp, u_int8_t lla) -{ - struct ifaddr *ifa; - struct sockaddr_dl *sdl; - struct arccom *ac; - - if_attach(ifp); - ifp->if_addrlen = 1; - ifp->if_hdrlen = ARC_HDRLEN; - ifp->if_mtu = 1500; - ifp->if_resolvemulti = arc_resolvemulti; - if (ifp->if_baudrate == 0) - ifp->if_baudrate = 2500000; - ifa = ifp->if_addr; - KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); - sdl = (struct sockaddr_dl *)ifa->ifa_addr; - sdl->sdl_type = IFT_ARCNET; - sdl->sdl_alen = ifp->if_addrlen; - - if (ifp->if_flags & IFF_BROADCAST) - ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; - - ac = (struct arccom *)ifp->if_l2com; - ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ - if (lla == 0) { - /* XXX this message isn't entirely clear, to me -- cgd */ - log(LOG_ERR,"%s: link address 0 reserved for broadcasts. Please change it and ifconfig %s down up\n", - ifp->if_xname, ifp->if_xname); - } - arc_storelladdr(ifp, lla); - - ifp->if_broadcastaddr = &arcbroadcastaddr; - - bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); -} - -void -arc_ifdetach(struct ifnet *ifp) -{ - bpfdetach(ifp); - if_detach(ifp); -} - -int -arc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct ifaddr *ifa = (struct ifaddr *) data; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - - switch (command) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - ifp->if_init(ifp->if_softc); /* before arpwhohas */ - arp_ifinit(ifp, ifa); - break; -#endif - default: - ifp->if_init(ifp->if_softc); - break; - } - break; - - case SIOCGIFADDR: - ifr->ifr_addr.sa_data[0] = ARC_LLADDR(ifp); - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifr == NULL) - error = EAFNOSUPPORT; - else { - switch (ifr->ifr_addr.sa_family) { - case AF_INET: - case AF_INET6: - error = 0; - break; - default: - error = EAFNOSUPPORT; - break; - } - } - break; - - case SIOCSIFMTU: - /* - * Set the interface MTU. - * mtu can't be larger than ARCMTU for RFC1051 - * and can't be larger than ARC_PHDS_MTU - */ - if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || - ifr->ifr_mtu > ARC_PHDS_MAXMTU) - error = EINVAL; - else - ifp->if_mtu = ifr->ifr_mtu; - break; - } - - return (error); -} - -/* based on ether_resolvemulti() */ -int -arc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, - struct sockaddr *sa) -{ - struct sockaddr_dl *sdl; -#ifdef INET - struct sockaddr_in *sin; -#endif -#ifdef INET6 - struct sockaddr_in6 *sin6; -#endif - - switch(sa->sa_family) { - case AF_LINK: - /* - * No mapping needed. Just check that it's a valid MC address. - */ - sdl = (struct sockaddr_dl *)sa; - if (*LLADDR(sdl) != arcbroadcastaddr) - return EADDRNOTAVAIL; - *llsa = NULL; - return 0; -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)sa; - if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) - return EADDRNOTAVAIL; - sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); - sdl->sdl_alen = ARC_ADDR_LEN; - *LLADDR(sdl) = 0; - *llsa = (struct sockaddr *)sdl; - return 0; -#endif -#ifdef INET6 - case AF_INET6: - sin6 = (struct sockaddr_in6 *)sa; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* - * An IP6 address of 0 means listen to all - * of the Ethernet multicast address used for IP6. - * (This is used for multicast routers.) - */ - ifp->if_flags |= IFF_ALLMULTI; - *llsa = NULL; - return 0; - } - if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) - return EADDRNOTAVAIL; - sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); - sdl->sdl_alen = ARC_ADDR_LEN; - *LLADDR(sdl) = 0; - *llsa = (struct sockaddr *)sdl; - return 0; -#endif - - default: - /* - * Well, the text isn't quite right, but it's the name - * that counts... - */ - return EAFNOSUPPORT; - } -} - -static MALLOC_DEFINE(M_ARCCOM, "arccom", "ARCNET interface internals"); - -static void* -arc_alloc(u_char type, struct ifnet *ifp) -{ - struct arccom *ac; - - ac = malloc(sizeof(struct arccom), M_ARCCOM, M_WAITOK | M_ZERO); - ac->ac_ifp = ifp; - - return (ac); -} - -static void -arc_free(void *com, u_char type) -{ - - free(com, M_ARCCOM); -} - -static int -arc_modevent(module_t mod, int type, void *data) -{ - - switch (type) { - case MOD_LOAD: - if_register_com_alloc(IFT_ARCNET, arc_alloc, arc_free); - break; - case MOD_UNLOAD: - if_deregister_com_alloc(IFT_ARCNET); - break; - default: - return EOPNOTSUPP; - } - - return (0); -} - -static moduledata_t arc_mod = { - "arcnet", - arc_modevent, - 0 -}; - -DECLARE_MODULE(arcnet, arc_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); -MODULE_VERSION(arcnet, 1); diff --git a/freebsd/sys/net/if_arp.h b/freebsd/sys/net/if_arp.h index 1a66c89c..070dbafe 100644 --- a/freebsd/sys/net/if_arp.h +++ b/freebsd/sys/net/if_arp.h @@ -49,7 +49,6 @@ struct arphdr { u_short ar_hrd; /* format of hardware address */ #define ARPHRD_ETHER 1 /* ethernet hardware format */ #define ARPHRD_IEEE802 6 /* token-ring hardware format */ -#define ARPHRD_ARCNET 7 /* arcnet hardware format */ #define ARPHRD_FRELAY 15 /* frame relay hardware format */ #define ARPHRD_IEEE1394 24 /* firewire hardware format */ #define ARPHRD_INFINIBAND 32 /* infiniband hardware format */ diff --git a/freebsd/sys/net/if_bridge.c b/freebsd/sys/net/if_bridge.c index 248cd45a..3e774934 100644 --- a/freebsd/sys/net/if_bridge.c +++ b/freebsd/sys/net/if_bridge.c @@ -74,8 +74,8 @@ * * - Currently only supports Ethernet-like interfaces (Ethernet, * 802.11, VLANs on Ethernet, etc.) Figure out a nice way - * to bridge other types of interfaces (FDDI-FDDI, and maybe - * consider heterogeneous bridges). + * to bridge other types of interfaces (maybe consider + * heterogeneous bridges). */ #include <sys/cdefs.h> @@ -342,7 +342,6 @@ static int bridge_fragment(struct ifnet *, struct mbuf **mp, static void bridge_linkstate(struct ifnet *ifp); static void bridge_linkcheck(struct bridge_softc *sc); -extern void (*bridge_linkstate_p)(struct ifnet *ifp); /* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */ #define VLANTAGOF(_m) \ @@ -558,10 +557,7 @@ bridge_modevent(module_t mod, int type, void *data) bridge_rtnode_zone = uma_zcreate("bridge_rtnode", sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - bridge_input_p = bridge_input; - bridge_output_p = bridge_output; bridge_dn_p = bridge_dummynet; - bridge_linkstate_p = bridge_linkstate; bridge_detach_cookie = EVENTHANDLER_REGISTER( ifnet_departure_event, bridge_ifdetach, NULL, EVENTHANDLER_PRI_ANY); @@ -570,10 +566,7 @@ bridge_modevent(module_t mod, int type, void *data) EVENTHANDLER_DEREGISTER(ifnet_departure_event, bridge_detach_cookie); uma_zdestroy(bridge_rtnode_zone); - bridge_input_p = NULL; - bridge_output_p = NULL; bridge_dn_p = NULL; - bridge_linkstate_p = NULL; break; default: return (EOPNOTSUPP); @@ -1043,6 +1036,9 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, KASSERT(bif->bif_addrcnt == 0, ("%s: %d bridge routes referenced", __func__, bif->bif_addrcnt)); + ifs->if_bridge_output = NULL; + ifs->if_bridge_input = NULL; + ifs->if_bridge_linkstate = NULL; BRIDGE_UNLOCK(sc); if (!gone) { switch (ifs->if_type) { @@ -1200,6 +1196,9 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) } ifs->if_bridge = sc; + ifs->if_bridge_output = bridge_output; + ifs->if_bridge_input = bridge_input; + ifs->if_bridge_linkstate = bridge_linkstate; bstp_create(&sc->sc_stp, &bif->bif_stp, bif->bif_ifp); /* * XXX: XLOCK HERE!?! diff --git a/freebsd/sys/net/if_bridgevar.h b/freebsd/sys/net/if_bridgevar.h index 84ff8d21..f4f61706 100644 --- a/freebsd/sys/net/if_bridgevar.h +++ b/freebsd/sys/net/if_bridgevar.h @@ -309,23 +309,20 @@ struct ifbpstpconf { (_sc)->sc_iflist_xcnt--; \ } while (0) -#define BRIDGE_INPUT(_ifp, _m) do { \ - KASSERT(bridge_input_p != NULL, \ +#define BRIDGE_INPUT(_ifp, _m) do { \ + KASSERT((_ifp)->if_bridge_input != NULL, \ ("%s: if_bridge not loaded!", __func__)); \ - _m = (*bridge_input_p)(_ifp, _m); \ + _m = (*(_ifp)->if_bridge_input)(_ifp, _m); \ if (_m != NULL) \ _ifp = _m->m_pkthdr.rcvif; \ } while (0) #define BRIDGE_OUTPUT(_ifp, _m, _err) do { \ - KASSERT(bridge_output_p != NULL, \ + KASSERT((_ifp)->if_bridge_output != NULL, \ ("%s: if_bridge not loaded!", __func__)); \ - _err = (*bridge_output_p)(_ifp, _m, NULL, NULL); \ + _err = (*(_ifp)->if_bridge_output)(_ifp, _m, NULL, NULL); \ } while (0) -extern struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); -extern int (*bridge_output_p)(struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *); extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); #endif /* _KERNEL */ diff --git a/freebsd/sys/net/if_clone.c b/freebsd/sys/net/if_clone.c index 295bddf4..5a9c20c2 100644 --- a/freebsd/sys/net/if_clone.c +++ b/freebsd/sys/net/if_clone.c @@ -69,6 +69,7 @@ struct if_clone { char ifc_name[IFCLOSIZ]; /* (c) Name of device, e.g. `gif' */ struct unrhdr *ifc_unrhdr; /* (c) alloc_unr(9) header */ int ifc_maxunit; /* (c) maximum unit number */ + int ifc_flags; long ifc_refcnt; /* (i) Reference count. */ LIST_HEAD(, ifnet) ifc_iflist; /* (i) List of cloned interfaces */ struct mtx ifc_mtx; /* Mutex to protect members. */ @@ -234,7 +235,8 @@ if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params) if (ifp == NULL) panic("%s: lookup failed for %s", __func__, name); - if_addgroup(ifp, ifc->ifc_name); + if ((ifc->ifc_flags & IFC_NOGROUP) == 0) + if_addgroup(ifp, ifc->ifc_name); IF_CLONE_LOCK(ifc); IFC_IFLIST_INSERT(ifc, ifp); @@ -321,8 +323,8 @@ if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) CURVNET_RESTORE(); return (ENXIO); /* ifp is not on the list. */ } - - if_delgroup(ifp, ifc->ifc_name); + if ((ifc->ifc_flags & IFC_NOGROUP) == 0) + if_delgroup(ifp, ifc->ifc_name); if (ifc->ifc_type == SIMPLE) err = ifc_simple_destroy(ifc, ifp); @@ -330,7 +332,8 @@ if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) err = (*ifc->ifc_destroy)(ifc, ifp); if (err != 0) { - if_addgroup(ifp, ifc->ifc_name); + if ((ifc->ifc_flags & IFC_NOGROUP) == 0) + if_addgroup(ifp, ifc->ifc_name); IF_CLONE_LOCK(ifc); IFC_IFLIST_INSERT(ifc, ifp); @@ -415,7 +418,7 @@ if_clone_simple(const char *name, ifcs_create_t create, ifcs_destroy_t destroy, for (unit = 0; unit < minifs; unit++) { char name[IFNAMSIZ]; - int error; + int error __unused; snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit); error = if_clone_createif(ifc, name, IFNAMSIZ, NULL); @@ -555,9 +558,10 @@ if_clone_findifc(struct ifnet *ifp) void if_clone_addgroup(struct ifnet *ifp, struct if_clone *ifc) { - - if_addgroup(ifp, ifc->ifc_name); - IF_CLONE_REMREF(ifc); + if ((ifc->ifc_flags & IFC_NOGROUP) == 0) { + if_addgroup(ifp, ifc->ifc_name); + IF_CLONE_REMREF(ifc); + } } /* @@ -734,3 +738,21 @@ ifc_simple_destroy(struct if_clone *ifc, struct ifnet *ifp) return (0); } + +const char * +ifc_name(struct if_clone *ifc) +{ + return (ifc->ifc_name); +} + +void +ifc_flags_set(struct if_clone *ifc, int flags) +{ + ifc->ifc_flags = flags; +} + +int +ifc_flags_get(struct if_clone *ifc) +{ + return (ifc->ifc_flags); +} diff --git a/freebsd/sys/net/if_clone.h b/freebsd/sys/net/if_clone.h index f26ab63b..5dceacf6 100644 --- a/freebsd/sys/net/if_clone.h +++ b/freebsd/sys/net/if_clone.h @@ -37,6 +37,8 @@ #ifdef _KERNEL +#define IFC_NOGROUP 0x1 + struct if_clone; /* Methods. */ @@ -59,6 +61,9 @@ void if_clone_detach(struct if_clone *); int ifc_name2unit(const char *name, int *unit); int ifc_alloc_unit(struct if_clone *, int *); void ifc_free_unit(struct if_clone *, int); +const char *ifc_name(struct if_clone *); +void ifc_flags_set(struct if_clone *, int flags); +int ifc_flags_get(struct if_clone *); #ifdef _SYS_EVENTHANDLER_H_ /* Interface clone event. */ diff --git a/freebsd/sys/net/if_epair.c b/freebsd/sys/net/if_epair.c index 106c0a43..d727bc2c 100644 --- a/freebsd/sys/net/if_epair.c +++ b/freebsd/sys/net/if_epair.c @@ -55,10 +55,14 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/hash.h> +#include <sys/jail.h> #include <sys/kernel.h> +#include <sys/libkern.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/module.h> +#include <sys/proc.h> #include <sys/refcount.h> #include <sys/queue.h> #include <sys/smp.h> @@ -253,7 +257,7 @@ static void epair_nh_sintr(struct mbuf *m) { struct ifnet *ifp; - struct epair_softc *sc; + struct epair_softc *sc __unused; ifp = m->m_pkthdr.rcvif; (*ifp->if_input)(ifp, m); @@ -298,7 +302,7 @@ epair_nh_drainedcpu(u_int cpuid) IFQ_LOCK(&ifp->if_snd); if (IFQ_IS_EMPTY(&ifp->if_snd)) { - struct epair_softc *sc; + struct epair_softc *sc __unused; STAILQ_REMOVE(&epair_dpcpu->epair_ifp_drain_list, elm, epair_ifp_drain, ifp_next); @@ -339,7 +343,7 @@ epair_remove_ifp_from_draining(struct ifnet *ifp) STAILQ_FOREACH_SAFE(elm, &epair_dpcpu->epair_ifp_drain_list, ifp_next, tvar) { if (ifp == elm->ifp) { - struct epair_softc *sc; + struct epair_softc *sc __unused; STAILQ_REMOVE( &epair_dpcpu->epair_ifp_drain_list, elm, @@ -715,6 +719,9 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) struct ifnet *ifp; char *dp; int error, unit, wildcard; + uint64_t hostid; + uint32_t key[3]; + uint32_t hash; uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ /* @@ -726,14 +733,12 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) if (params) { scb = (struct epair_softc *)params; ifp = scb->ifp; - /* Assign a hopefully unique, locally administered etheraddr. */ - eaddr[0] = 0x02; - eaddr[3] = (ifp->if_index >> 8) & 0xff; - eaddr[4] = ifp->if_index & 0xff; + /* Copy epairNa etheraddr and change the last byte. */ + memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN); eaddr[5] = 0x0b; ether_ifattach(ifp, eaddr); /* Correctly set the name for the cloner list. */ - strlcpy(name, scb->ifp->if_xname, len); + strlcpy(name, ifp->if_xname, len); return (0); } @@ -837,10 +842,21 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) ifp->if_init = epair_init; if_setsendqlen(ifp, ifqmaxlen); if_setsendqready(ifp); - /* Assign a hopefully unique, locally administered etheraddr. */ + + /* + * Calculate the etheraddr hashing the hostid and the + * interface index. The result would be hopefully unique + */ + getcredhostid(curthread->td_ucred, (unsigned long *)&hostid); + if (hostid == 0) + arc4rand(&hostid, sizeof(hostid), 0); + key[0] = (uint32_t)ifp->if_index; + key[1] = (uint32_t)(hostid & 0xffffffff); + key[2] = (uint32_t)((hostid >> 32) & 0xfffffffff); + hash = jenkins_hash32(key, 3, 0); + eaddr[0] = 0x02; - eaddr[3] = (ifp->if_index >> 8) & 0xff; - eaddr[4] = ifp->if_index & 0xff; + memcpy(&eaddr[1], &hash, 4); eaddr[5] = 0x0a; ether_ifattach(ifp, eaddr); sca->if_qflush = ifp->if_qflush; diff --git a/freebsd/sys/net/if_ethersubr.c b/freebsd/sys/net/if_ethersubr.c index 78ff2385..3893d331 100644 --- a/freebsd/sys/net/if_ethersubr.c +++ b/freebsd/sys/net/if_ethersubr.c @@ -104,9 +104,6 @@ void (*ng_ether_detach_p)(struct ifnet *ifp); void (*vlan_input_p)(struct ifnet *, struct mbuf *); /* if_bridge(4) support */ -struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); -int (*bridge_output_p)(struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *); void (*bridge_dn_p)(struct mbuf *, struct ifnet *); /* if_lagg(4) support */ @@ -518,7 +515,7 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m) } eh = mtod(m, struct ether_header *); etype = ntohs(eh->ether_type); - random_harvest_queue(m, sizeof(*m), 2, RANDOM_NET_ETHER); + random_harvest_queue_ether(m, sizeof(*m), 2); CURVNET_SET_QUIET(ifp->if_vnet); @@ -1130,10 +1127,13 @@ ether_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (error != 0) break; if (ifr->ifr_lan_pcp > 7 && - ifr->ifr_lan_pcp != IFNET_PCP_NONE) + ifr->ifr_lan_pcp != IFNET_PCP_NONE) { error = EINVAL; - else + } else { ifp->if_pcp = ifr->ifr_lan_pcp; + /* broadcast event about PCP change */ + EVENTHANDLER_INVOKE(ifnet_event, ifp, IFNET_EVENT_PCP); + } break; case SIOCGLANPCP: diff --git a/freebsd/sys/net/if_fddisubr.c b/freebsd/sys/net/if_fddisubr.c deleted file mode 100644 index c011346e..00000000 --- a/freebsd/sys/net/if_fddisubr.c +++ /dev/null @@ -1,669 +0,0 @@ -#include <machine/rtems-bsd-kernel-space.h> - -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) 1995, 1996 - * Matt Thomas <matt@3am-software.com>. All rights reserved. - * Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. 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_ethersubr.c,v 1.5 1994/12/13 22:31:45 wollman Exp - * $FreeBSD$ - */ - -#include <rtems/bsd/local/opt_inet.h> -#include <rtems/bsd/local/opt_inet6.h> - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/sockio.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/if_dl.h> -#include <net/if_llc.h> -#include <net/if_types.h> -#include <net/if_llatbl.h> - -#include <net/ethernet.h> -#include <net/netisr.h> -#include <net/route.h> -#include <net/bpf.h> -#include <net/fddi.h> - -#if defined(INET) || defined(INET6) -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/if_ether.h> -#endif -#ifdef INET6 -#include <netinet6/nd6.h> -#endif - -#ifdef DECNET -#include <netdnet/dn.h> -#endif - -#include <security/mac/mac_framework.h> - -static const u_char fddibroadcastaddr[FDDI_ADDR_LEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - -static int fddi_resolvemulti(struct ifnet *, struct sockaddr **, - struct sockaddr *); -static int fddi_output(struct ifnet *, struct mbuf *, const struct sockaddr *, - struct route *); -static void fddi_input(struct ifnet *ifp, struct mbuf *m); - -#define senderr(e) do { error = (e); goto bad; } while (0) - -/* - * FDDI output routine. - * Encapsulate a packet of type family for the local net. - * Use trailer local net encapsulation if enough data in first - * packet leaves a multiple of 512 bytes of data in remainder. - */ -static int -fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, - struct route *ro) -{ - u_int16_t type; - int loop_copy = 0, error = 0, hdrcmplt = 0; - u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN]; - struct fddi_header *fh; -#if defined(INET) || defined(INET6) - int is_gw = 0; -#endif - -#ifdef MAC - error = mac_ifnet_check_transmit(ifp, m); - if (error) - senderr(error); -#endif - - if (ifp->if_flags & IFF_MONITOR) - senderr(ENETDOWN); - if (!((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING))) - senderr(ENETDOWN); - getmicrotime(&ifp->if_lastchange); - -#if defined(INET) || defined(INET6) - if (ro != NULL) - is_gw = (ro->ro_flags & RT_HAS_GW) != 0; -#endif - - switch (dst->sa_family) { -#ifdef INET - case AF_INET: { - error = arpresolve(ifp, is_gw, m, dst, edst, NULL, NULL); - if (error) - return (error == EWOULDBLOCK ? 0 : error); - type = htons(ETHERTYPE_IP); - break; - } - case AF_ARP: - { - struct arphdr *ah; - ah = mtod(m, struct arphdr *); - ah->ar_hrd = htons(ARPHRD_ETHER); - - loop_copy = -1; /* if this is for us, don't do it */ - - switch (ntohs(ah->ar_op)) { - case ARPOP_REVREQUEST: - case ARPOP_REVREPLY: - type = htons(ETHERTYPE_REVARP); - break; - case ARPOP_REQUEST: - case ARPOP_REPLY: - default: - type = htons(ETHERTYPE_ARP); - break; - } - - if (m->m_flags & M_BCAST) - bcopy(ifp->if_broadcastaddr, edst, FDDI_ADDR_LEN); - else - bcopy(ar_tha(ah), edst, FDDI_ADDR_LEN); - - } - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL); - if (error) - return (error == EWOULDBLOCK ? 0 : error); - type = htons(ETHERTYPE_IPV6); - break; -#endif /* INET6 */ - case pseudo_AF_HDRCMPLT: - { - const struct ether_header *eh; - - hdrcmplt = 1; - eh = (const struct ether_header *)dst->sa_data; - bcopy(eh->ether_shost, esrc, FDDI_ADDR_LEN); - /* FALLTHROUGH */ - } - - case AF_UNSPEC: - { - const struct ether_header *eh; - - loop_copy = -1; - eh = (const struct ether_header *)dst->sa_data; - bcopy(eh->ether_dhost, edst, FDDI_ADDR_LEN); - if (*edst & 1) - m->m_flags |= (M_BCAST|M_MCAST); - type = eh->ether_type; - break; - } - - case AF_IMPLINK: - { - fh = mtod(m, struct fddi_header *); - error = EPROTONOSUPPORT; - switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) { - case FDDIFC_LLC_ASYNC: { - /* legal priorities are 0 through 7 */ - if ((fh->fddi_fc & FDDIFC_Z) > 7) - goto bad; - break; - } - case FDDIFC_LLC_SYNC: { - /* FDDIFC_Z bits reserved, must be zero */ - if (fh->fddi_fc & FDDIFC_Z) - goto bad; - break; - } - case FDDIFC_SMT: { - /* FDDIFC_Z bits must be non zero */ - if ((fh->fddi_fc & FDDIFC_Z) == 0) - goto bad; - break; - } - default: { - /* anything else is too dangerous */ - goto bad; - } - } - error = 0; - if (fh->fddi_dhost[0] & 1) - m->m_flags |= (M_BCAST|M_MCAST); - goto queue_it; - } - default: - if_printf(ifp, "can't handle af%d\n", dst->sa_family); - senderr(EAFNOSUPPORT); - } - - /* - * Add LLC header. - */ - if (type != 0) { - struct llc *l; - M_PREPEND(m, LLC_SNAPFRAMELEN, M_NOWAIT); - if (m == NULL) - senderr(ENOBUFS); - l = mtod(m, struct llc *); - l->llc_control = LLC_UI; - l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP; - l->llc_snap.org_code[0] = - l->llc_snap.org_code[1] = - l->llc_snap.org_code[2] = 0; - l->llc_snap.ether_type = htons(type); - } - - /* - * Add local net header. If no space in first mbuf, - * allocate another. - */ - M_PREPEND(m, FDDI_HDR_LEN, M_NOWAIT); - if (m == NULL) - senderr(ENOBUFS); - fh = mtod(m, struct fddi_header *); - fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; - bcopy((caddr_t)edst, (caddr_t)fh->fddi_dhost, FDDI_ADDR_LEN); - queue_it: - if (hdrcmplt) - bcopy((caddr_t)esrc, (caddr_t)fh->fddi_shost, FDDI_ADDR_LEN); - else - bcopy(IF_LLADDR(ifp), (caddr_t)fh->fddi_shost, - FDDI_ADDR_LEN); - - /* - * If a simplex interface, and the packet is being sent to our - * Ethernet address or a broadcast address, loopback a copy. - * XXX To make a simplex device behave exactly like a duplex - * device, we should copy in the case of sending to our own - * ethernet address (thus letting the original actually appear - * on the wire). However, we don't do that here for security - * reasons and compatibility with the original behavior. - */ - if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { - if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { - struct mbuf *n; - n = m_copym(m, 0, M_COPYALL, M_NOWAIT); - (void) if_simloop(ifp, n, dst->sa_family, - FDDI_HDR_LEN); - } else if (bcmp(fh->fddi_dhost, fh->fddi_shost, - FDDI_ADDR_LEN) == 0) { - (void) if_simloop(ifp, m, dst->sa_family, - FDDI_HDR_LEN); - return (0); /* XXX */ - } - } - - error = (ifp->if_transmit)(ifp, m); - if (error) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - - return (error); - -bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - if (m) - m_freem(m); - return (error); -} - -/* - * Process a received FDDI packet. - */ -static void -fddi_input(ifp, m) - struct ifnet *ifp; - struct mbuf *m; -{ - int isr; - struct llc *l; - struct fddi_header *fh; - - /* - * Do consistency checks to verify assumptions - * made by code past this point. - */ - if ((m->m_flags & M_PKTHDR) == 0) { - if_printf(ifp, "discard frame w/o packet header\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - m_freem(m); - return; - } - if (m->m_pkthdr.rcvif == NULL) { - if_printf(ifp, "discard frame w/o interface pointer\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - m_freem(m); - return; - } - - m = m_pullup(m, FDDI_HDR_LEN); - if (m == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - goto dropanyway; - } - fh = mtod(m, struct fddi_header *); - - /* - * Discard packet if interface is not up. - */ - if (!((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING))) - goto dropanyway; - - /* - * Give bpf a chance at the packet. - */ - BPF_MTAP(ifp, m); - - /* - * Interface marked for monitoring; discard packet. - */ - if (ifp->if_flags & IFF_MONITOR) { - m_freem(m); - return; - } - -#ifdef MAC - mac_ifnet_create_mbuf(ifp, m); -#endif - - /* - * Update interface statistics. - */ - if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); - getmicrotime(&ifp->if_lastchange); - - /* - * Discard non local unicast packets when interface - * is in promiscuous mode. - */ - if ((ifp->if_flags & IFF_PROMISC) && ((fh->fddi_dhost[0] & 1) == 0) && - (bcmp(IF_LLADDR(ifp), (caddr_t)fh->fddi_dhost, - FDDI_ADDR_LEN) != 0)) - goto dropanyway; - - /* - * Set mbuf flags for bcast/mcast. - */ - if (fh->fddi_dhost[0] & 1) { - if (bcmp(ifp->if_broadcastaddr, fh->fddi_dhost, - FDDI_ADDR_LEN) == 0) - m->m_flags |= M_BCAST; - else - m->m_flags |= M_MCAST; - if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); - } - -#ifdef M_LINK0 - /* - * If this has a LLC priority of 0, then mark it so upper - * layers have a hint that it really came via a FDDI/Ethernet - * bridge. - */ - if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0) - m->m_flags |= M_LINK0; -#endif - - /* Strip off FDDI header. */ - m_adj(m, FDDI_HDR_LEN); - - m = m_pullup(m, LLC_SNAPFRAMELEN); - if (m == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - goto dropanyway; - } - l = mtod(m, struct llc *); - - switch (l->llc_dsap) { - case LLC_SNAP_LSAP: - { - u_int16_t type; - if ((l->llc_control != LLC_UI) || - (l->llc_ssap != LLC_SNAP_LSAP)) { - if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1); - goto dropanyway; - } - if (l->llc_snap.org_code[0] != 0 || - l->llc_snap.org_code[1] != 0 || - l->llc_snap.org_code[2] != 0) { - if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1); - goto dropanyway; - } - - type = ntohs(l->llc_snap.ether_type); - m_adj(m, LLC_SNAPFRAMELEN); - - switch (type) { -#ifdef INET - case ETHERTYPE_IP: - isr = NETISR_IP; - break; - - case ETHERTYPE_ARP: - if (ifp->if_flags & IFF_NOARP) - goto dropanyway; - isr = NETISR_ARP; - break; -#endif -#ifdef INET6 - case ETHERTYPE_IPV6: - isr = NETISR_IPV6; - break; -#endif -#ifdef DECNET - case ETHERTYPE_DECNET: - isr = NETISR_DECNET; - break; -#endif - default: - /* printf("fddi_input: unknown protocol 0x%x\n", type); */ - if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1); - goto dropanyway; - } - break; - } - - default: - /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */ - if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1); - goto dropanyway; - } - M_SETFIB(m, ifp->if_fib); - netisr_dispatch(isr, m); - return; - -dropanyway: - if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); - if (m) - m_freem(m); - return; -} - -/* - * Perform common duties while attaching to interface list - */ -void -fddi_ifattach(ifp, lla, bpf) - struct ifnet *ifp; - const u_int8_t *lla; - int bpf; -{ - struct ifaddr *ifa; - struct sockaddr_dl *sdl; - - ifp->if_type = IFT_FDDI; - ifp->if_addrlen = FDDI_ADDR_LEN; - ifp->if_hdrlen = 21; - - if_attach(ifp); /* Must be called before additional assignments */ - - ifp->if_mtu = FDDIMTU; - ifp->if_output = fddi_output; - ifp->if_input = fddi_input; - ifp->if_resolvemulti = fddi_resolvemulti; - ifp->if_broadcastaddr = fddibroadcastaddr; - ifp->if_baudrate = 100000000; -#ifdef IFF_NOTRAILERS - ifp->if_flags |= IFF_NOTRAILERS; -#endif - ifa = ifp->if_addr; - KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); - - sdl = (struct sockaddr_dl *)ifa->ifa_addr; - sdl->sdl_type = IFT_FDDI; - sdl->sdl_alen = ifp->if_addrlen; - bcopy(lla, LLADDR(sdl), ifp->if_addrlen); - - if (bpf) - bpfattach(ifp, DLT_FDDI, FDDI_HDR_LEN); - - return; -} - -void -fddi_ifdetach(ifp, bpf) - struct ifnet *ifp; - int bpf; -{ - - if (bpf) - bpfdetach(ifp); - - if_detach(ifp); - - return; -} - -int -fddi_ioctl (ifp, command, data) - struct ifnet *ifp; - u_long command; - caddr_t data; -{ - struct ifaddr *ifa; - struct ifreq *ifr; - int error; - - ifa = (struct ifaddr *) data; - ifr = (struct ifreq *) data; - error = 0; - - switch (command) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: /* before arpwhohas */ - ifp->if_init(ifp->if_softc); - arp_ifinit(ifp, ifa); - break; -#endif - default: - ifp->if_init(ifp->if_softc); - break; - } - break; - case SIOCGIFADDR: - bcopy(IF_LLADDR(ifp), &ifr->ifr_addr.sa_data[0], - FDDI_ADDR_LEN); - break; - case SIOCSIFMTU: - /* - * Set the interface MTU. - */ - if (ifr->ifr_mtu > FDDIMTU) { - error = EINVAL; - } else { - ifp->if_mtu = ifr->ifr_mtu; - } - break; - default: - error = EINVAL; - break; - } - - return (error); -} - -static int -fddi_resolvemulti(ifp, llsa, sa) - struct ifnet *ifp; - struct sockaddr **llsa; - struct sockaddr *sa; -{ - struct sockaddr_dl *sdl; -#ifdef INET - struct sockaddr_in *sin; -#endif -#ifdef INET6 - struct sockaddr_in6 *sin6; -#endif - u_char *e_addr; - - switch(sa->sa_family) { - case AF_LINK: - /* - * No mapping needed. Just check that it's a valid MC address. - */ - sdl = (struct sockaddr_dl *)sa; - e_addr = LLADDR(sdl); - if ((e_addr[0] & 1) != 1) - return (EADDRNOTAVAIL); - *llsa = NULL; - return (0); - -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)sa; - if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) - return (EADDRNOTAVAIL); - sdl = link_init_sdl(ifp, *llsa, IFT_FDDI); - sdl->sdl_nlen = 0; - sdl->sdl_alen = FDDI_ADDR_LEN; - sdl->sdl_slen = 0; - e_addr = LLADDR(sdl); - ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); - *llsa = (struct sockaddr *)sdl; - return (0); -#endif -#ifdef INET6 - case AF_INET6: - sin6 = (struct sockaddr_in6 *)sa; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* - * An IP6 address of 0 means listen to all - * of the Ethernet multicast address used for IP6. - * (This is used for multicast routers.) - */ - ifp->if_flags |= IFF_ALLMULTI; - *llsa = NULL; - return (0); - } - if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) - return (EADDRNOTAVAIL); - sdl = link_init_sdl(ifp, *llsa, IFT_FDDI); - sdl->sdl_nlen = 0; - sdl->sdl_alen = FDDI_ADDR_LEN; - sdl->sdl_slen = 0; - e_addr = LLADDR(sdl); - ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); - *llsa = (struct sockaddr *)sdl; - return (0); -#endif - - default: - /* - * Well, the text isn't quite right, but it's the name - * that counts... - */ - return (EAFNOSUPPORT); - } - - return (0); -} - -static moduledata_t fddi_mod = { - "fddi", /* module name */ - NULL, /* event handler */ - 0 /* extra data */ -}; - -DECLARE_MODULE(fddi, fddi_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); -MODULE_VERSION(fddi, 1); diff --git a/freebsd/sys/net/if_ipsec.c b/freebsd/sys/net/if_ipsec.c index 91afe2ab..eaeecd5a 100644 --- a/freebsd/sys/net/if_ipsec.c +++ b/freebsd/sys/net/if_ipsec.c @@ -440,7 +440,7 @@ ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af) m->m_pkthdr.rcvif = ifp; IPSEC_SC_RUNLOCK(); - /* m_clrprotoflags(m); */ + m_clrprotoflags(m); M_SETFIB(m, ifp->if_fib); BPF_MTAP2(ifp, &af, sizeof(af), m); if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); diff --git a/freebsd/sys/net/if_lagg.c b/freebsd/sys/net/if_lagg.c index 36c8095a..578078c2 100644 --- a/freebsd/sys/net/if_lagg.c +++ b/freebsd/sys/net/if_lagg.c @@ -75,6 +75,18 @@ __FBSDID("$FreeBSD$"); #include <net/if_lagg.h> #include <net/ieee8023ad_lacp.h> +#define LAGG_RLOCK() epoch_enter_preempt(net_epoch_preempt) +#define LAGG_RUNLOCK() epoch_exit_preempt(net_epoch_preempt) +#define LAGG_RLOCK_ASSERT() MPASS(in_epoch()) +#define LAGG_UNLOCK_ASSERT() MPASS(!in_epoch()) + +#define LAGG_SX_INIT(_sc) sx_init(&(_sc)->sc_sx, "if_lagg sx") +#define LAGG_SX_DESTROY(_sc) sx_destroy(&(_sc)->sc_sx) +#define LAGG_XLOCK(_sc) sx_xlock(&(_sc)->sc_sx) +#define LAGG_XUNLOCK(_sc) sx_xunlock(&(_sc)->sc_sx) +#define LAGG_SXLOCK_ASSERT(_sc) sx_assert(&(_sc)->sc_sx, SA_LOCKED) +#define LAGG_XLOCK_ASSERT(_sc) sx_assert(&(_sc)->sc_sx, SA_XLOCKED) + /* Special flags we should propagate to the lagg ports. */ static struct { int flag; @@ -336,14 +348,11 @@ lagg_proto_detach(struct lagg_softc *sc) lagg_proto pr; LAGG_XLOCK_ASSERT(sc); - LAGG_WLOCK_ASSERT(sc); pr = sc->sc_proto; sc->sc_proto = LAGG_PROTO_NONE; if (lagg_protos[pr].pr_detach != NULL) lagg_protos[pr].pr_detach(sc); - else - LAGG_WUNLOCK(sc); } static int @@ -439,10 +448,10 @@ lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag) if (ifp->if_softc != arg) /* Not our event */ return; - LAGG_SLOCK(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vtag); - LAGG_SUNLOCK(sc); + LAGG_RUNLOCK(); } /* @@ -458,10 +467,10 @@ lagg_unregister_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag) if (ifp->if_softc != arg) /* Not our event */ return; - LAGG_SLOCK(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp, vtag); - LAGG_SUNLOCK(sc); + LAGG_RUNLOCK(); } static int @@ -477,7 +486,6 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) free(sc, M_DEVBUF); return (ENOSPC); } - LAGG_LOCK_INIT(sc); LAGG_SX_INIT(sc); LAGG_XLOCK(sc); @@ -490,7 +498,7 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) lagg_proto_attach(sc, LAGG_PROTO_DEFAULT); - SLIST_INIT(&sc->sc_ports); + CK_SLIST_INIT(&sc->sc_ports); /* Initialise pseudo media types */ ifmedia_init(&sc->sc_media, 0, lagg_media_change, @@ -548,13 +556,11 @@ lagg_clone_destroy(struct ifnet *ifp) EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vlan_detach); /* Shutdown and remove lagg ports */ - while ((lp = SLIST_FIRST(&sc->sc_ports)) != NULL) + while ((lp = CK_SLIST_FIRST(&sc->sc_ports)) != NULL) lagg_port_destroy(lp, 1); /* Unhook the aggregation protocol */ - LAGG_WLOCK(sc); lagg_proto_detach(sc); - LAGG_UNLOCK_ASSERT(sc); LAGG_XUNLOCK(sc); ifmedia_removeall(&sc->sc_media); @@ -566,7 +572,6 @@ lagg_clone_destroy(struct ifnet *ifp) LAGG_LIST_UNLOCK(); LAGG_SX_DESTROY(sc); - LAGG_LOCK_DESTROY(sc); free(sc, M_DEVBUF); } @@ -582,7 +587,7 @@ lagg_capabilities(struct lagg_softc *sc) /* Get common enabled capabilities for the lagg ports */ ena = ~0; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) ena &= lp->lp_ifp->if_capenable; ena = (ena == ~0 ? 0 : ena); @@ -592,7 +597,7 @@ lagg_capabilities(struct lagg_softc *sc) */ do { pena = ena; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { lagg_setcaps(lp, ena); ena &= lp->lp_ifp->if_capenable; } @@ -602,7 +607,7 @@ lagg_capabilities(struct lagg_softc *sc) cap = ~0; hwa = ~(uint64_t)0; memset(&hw_tsomax, 0, sizeof(hw_tsomax)); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { cap &= lp->lp_ifp->if_capabilities; hwa &= lp->lp_ifp->if_hwassist; if_hw_tsomax_common(lp->lp_ifp, &hw_tsomax); @@ -653,7 +658,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) return (EPROTONOSUPPORT); /* Allow the first Ethernet member to define the MTU */ - if (SLIST_EMPTY(&sc->sc_ports)) + if (CK_SLIST_EMPTY(&sc->sc_ports)) sc->sc_ifp->if_mtu = ifp->if_mtu; else if (sc->sc_ifp->if_mtu != ifp->if_mtu) { if_printf(sc->sc_ifp, "invalid MTU for %s\n", @@ -690,19 +695,16 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) bcopy(IF_LLADDR(ifp), lp->lp_lladdr, ETHER_ADDR_LEN); lp->lp_ifcapenable = ifp->if_capenable; - if (SLIST_EMPTY(&sc->sc_ports)) { - LAGG_WLOCK(sc); + if (CK_SLIST_EMPTY(&sc->sc_ports)) { bcopy(IF_LLADDR(ifp), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); lagg_proto_lladdr(sc); - LAGG_WUNLOCK(sc); EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp); } else { if_setlladdr(ifp, IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); } lagg_setflags(lp, 1); - LAGG_WLOCK(sc); - if (SLIST_EMPTY(&sc->sc_ports)) + if (CK_SLIST_EMPTY(&sc->sc_ports)) sc->sc_primary = lp; /* Change the interface type */ @@ -725,28 +727,27 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) * is predictable and `ifconfig laggN create ...` command * will lead to the same result each time. */ - SLIST_FOREACH(tlp, &sc->sc_ports, lp_entries) { + LAGG_RLOCK(); + CK_SLIST_FOREACH(tlp, &sc->sc_ports, lp_entries) { if (tlp->lp_ifp->if_index < ifp->if_index && ( - SLIST_NEXT(tlp, lp_entries) == NULL || - SLIST_NEXT(tlp, lp_entries)->lp_ifp->if_index > + CK_SLIST_NEXT(tlp, lp_entries) == NULL || + ((struct lagg_port*)CK_SLIST_NEXT(tlp, lp_entries))->lp_ifp->if_index > ifp->if_index)) break; } + LAGG_RUNLOCK(); if (tlp != NULL) - SLIST_INSERT_AFTER(tlp, lp, lp_entries); + CK_SLIST_INSERT_AFTER(tlp, lp, lp_entries); else - SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries); + CK_SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries); sc->sc_count++; lagg_setmulti(lp); - LAGG_WUNLOCK(sc); if ((error = lagg_proto_addport(sc, lp)) != 0) { /* Remove the port, without calling pr_delport. */ - LAGG_WLOCK(sc); lagg_port_destroy(lp, 0); - LAGG_UNLOCK_ASSERT(sc); return (error); } @@ -766,7 +767,7 @@ lagg_port_checkstacking(struct lagg_softc *sc) int m = 0; LAGG_SXLOCK_ASSERT(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (lp->lp_flags & LAGG_PORT_STACK) { sc_ptr = (struct lagg_softc *)lp->lp_ifp->if_softc; m = MAX(m, lagg_port_checkstacking(sc_ptr)); @@ -777,6 +778,19 @@ lagg_port_checkstacking(struct lagg_softc *sc) } #endif +static void +lagg_port_destroy_cb(epoch_context_t ec) +{ + struct lagg_port *lp; + struct ifnet *ifp; + + lp = __containerof(ec, struct lagg_port, lp_epoch_ctx); + ifp = lp->lp_ifp; + + if_rele(ifp); + free(lp, M_DEVBUF); +} + static int lagg_port_destroy(struct lagg_port *lp, int rundelport) { @@ -788,11 +802,8 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) LAGG_XLOCK_ASSERT(sc); - if (rundelport) { - LAGG_WLOCK(sc); + if (rundelport) lagg_proto_delport(sc, lp); - } else - LAGG_WLOCK_ASSERT(sc); if (lp->lp_detaching == 0) lagg_clrmulti(lp); @@ -811,14 +822,14 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) } /* Finally, remove the port from the lagg */ - SLIST_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entries); + CK_SLIST_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entries); sc->sc_count--; /* Update the primary interface */ if (lp == sc->sc_primary) { uint8_t lladdr[ETHER_ADDR_LEN]; - if ((lp0 = SLIST_FIRST(&sc->sc_ports)) == NULL) + if ((lp0 = CK_SLIST_FIRST(&sc->sc_ports)) == NULL) bzero(&lladdr, ETHER_ADDR_LEN); else bcopy(lp0->lp_lladdr, lladdr, ETHER_ADDR_LEN); @@ -826,19 +837,16 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) if (sc->sc_destroying == 0) { bcopy(lladdr, IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); lagg_proto_lladdr(sc); - LAGG_WUNLOCK(sc); EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp); - } else - LAGG_WUNLOCK(sc); + } /* * Update lladdr for each port (new primary needs update * as well, to switch from old lladdr to its 'real' one) */ - SLIST_FOREACH(lp_ptr, &sc->sc_ports, lp_entries) + CK_SLIST_FOREACH(lp_ptr, &sc->sc_ports, lp_entries) if_setlladdr(lp_ptr->lp_ifp, lladdr, ETHER_ADDR_LEN); - } else - LAGG_WUNLOCK(sc); + } if (lp->lp_ifflags) if_printf(ifp, "%s: lp_ifflags unclean\n", __func__); @@ -849,9 +857,11 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) if_setlladdr(ifp, lp->lp_lladdr, ETHER_ADDR_LEN); } - if_rele(ifp); - free(lp, M_DEVBUF); - + /* + * free port and release it's ifnet reference after a grace period has + * elapsed. + */ + epoch_call(net_epoch_preempt, &lp->lp_epoch_ctx, lagg_port_destroy_cb); /* Update lagg capabilities */ lagg_capabilities(sc); lagg_linkstate(sc); @@ -880,15 +890,15 @@ lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; } - LAGG_SLOCK(sc); + LAGG_RLOCK(); if ((lp = ifp->if_lagg) == NULL || lp->lp_softc != sc) { error = ENOENT; - LAGG_SUNLOCK(sc); + LAGG_RUNLOCK(); break; } lagg_port2req(lp, rp); - LAGG_SUNLOCK(sc); + LAGG_RUNLOCK(); break; case SIOCSIFCAP: @@ -944,17 +954,16 @@ lagg_get_counter(struct ifnet *ifp, ift_counter cnt) struct lagg_softc *sc; struct lagg_port *lp; struct ifnet *lpifp; - struct rm_priotracker tracker; uint64_t newval, oldval, vsum; /* Revise this when we've got non-generic counters. */ KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt)); sc = (struct lagg_softc *)ifp->if_softc; - LAGG_RLOCK(sc, &tracker); vsum = 0; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { /* Saved attached value */ oldval = lp->port_counters.val[cnt]; /* current value */ @@ -963,6 +972,7 @@ lagg_get_counter(struct ifnet *ifp, ift_counter cnt) /* Calculate diff and save new */ vsum += newval - oldval; } + LAGG_RUNLOCK(); /* * Add counter data which might be added by upper @@ -975,7 +985,6 @@ lagg_get_counter(struct ifnet *ifp, ift_counter cnt) */ vsum += sc->detached_counters.val[cnt]; - LAGG_RUNLOCK(sc, &tracker); return (vsum); } @@ -1081,7 +1090,7 @@ lagg_init(void *xsc) * This might be if_setlladdr() notification * that lladdr has been changed. */ - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (memcmp(IF_LLADDR(ifp), IF_LLADDR(lp->lp_ifp), ETHER_ADDR_LEN) != 0) if_setlladdr(lp->lp_ifp, IF_LLADDR(ifp), ETHER_ADDR_LEN); @@ -1126,7 +1135,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCGLAGG: - LAGG_SLOCK(sc); + LAGG_XLOCK(sc); buflen = sc->sc_count * sizeof(struct lagg_reqport); outbuf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); ra->ra_proto = sc->sc_proto; @@ -1134,7 +1143,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) count = 0; buf = outbuf; len = min(ra->ra_size, buflen); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (len < sizeof(rpbuf)) break; @@ -1144,7 +1153,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) buf += sizeof(rpbuf); len -= sizeof(rpbuf); } - LAGG_SUNLOCK(sc); + LAGG_XUNLOCK(sc); ra->ra_ports = count; ra->ra_size = count * sizeof(rpbuf); error = copyout(outbuf, ra->ra_port, ra->ra_size); @@ -1160,14 +1169,13 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } LAGG_XLOCK(sc); - LAGG_WLOCK(sc); lagg_proto_detach(sc); - LAGG_UNLOCK_ASSERT(sc); + LAGG_UNLOCK_ASSERT(); lagg_proto_attach(sc, ra->ra_proto); LAGG_XUNLOCK(sc); break; case SIOCGLAGGOPTS: - LAGG_SLOCK(sc); + LAGG_XLOCK(sc); ro->ro_opts = sc->sc_opts; if (sc->sc_proto == LAGG_PROTO_LACP) { struct lacp_softc *lsc; @@ -1185,13 +1193,13 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ro->ro_active = sc->sc_active; } else { ro->ro_active = 0; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) ro->ro_active += LAGG_PORTACTIVE(lp); } ro->ro_bkt = sc->sc_bkt; ro->ro_flapping = sc->sc_flapping; ro->ro_flowid_shift = sc->flowid_shift; - LAGG_SUNLOCK(sc); + LAGG_XUNLOCK(sc); break; case SIOCSLAGGOPTS: if (sc->sc_proto == LAGG_PROTO_ROUNDROBIN) { @@ -1298,14 +1306,14 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCGLAGGFLAGS: rf->rf_flags = 0; - LAGG_SLOCK(sc); + LAGG_XLOCK(sc); if (sc->sc_flags & MBUF_HASHFLAG_L2) rf->rf_flags |= LAGG_F_HASHL2; if (sc->sc_flags & MBUF_HASHFLAG_L3) rf->rf_flags |= LAGG_F_HASHL3; if (sc->sc_flags & MBUF_HASHFLAG_L4) rf->rf_flags |= LAGG_F_HASHL4; - LAGG_SUNLOCK(sc); + LAGG_XUNLOCK(sc); break; case SIOCSLAGGHASH: error = priv_check(td, PRIV_NET_LAGG); @@ -1332,17 +1340,17 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; } - LAGG_SLOCK(sc); + LAGG_RLOCK(); if ((lp = (struct lagg_port *)tpif->if_lagg) == NULL || lp->lp_softc != sc) { error = ENOENT; - LAGG_SUNLOCK(sc); + LAGG_RUNLOCK(); if_rele(tpif); break; } lagg_port2req(lp, rp); - LAGG_SUNLOCK(sc); + LAGG_RUNLOCK(); if_rele(tpif); break; case SIOCSLAGGPORT: @@ -1407,7 +1415,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCSIFFLAGS: /* Set flags on ports too */ LAGG_XLOCK(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { lagg_setflags(lp, 1); } @@ -1432,12 +1440,12 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCADDMULTI: case SIOCDELMULTI: - LAGG_WLOCK(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + LAGG_XLOCK(sc); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { lagg_clrmulti(lp); lagg_setmulti(lp); } - LAGG_WUNLOCK(sc); + LAGG_XUNLOCK(sc); error = 0; break; case SIOCSIFMEDIA: @@ -1447,7 +1455,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCSIFCAP: LAGG_XLOCK(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (lp->lp_ioctl != NULL) (*lp->lp_ioctl)(lp->lp_ifp, cmd, data); } @@ -1525,9 +1533,8 @@ lagg_setmulti(struct lagg_port *lp) struct ifmultiaddr *ifma; int error; - LAGG_WLOCK_ASSERT(sc); IF_ADDR_WLOCK(scifp); - TAILQ_FOREACH(ifma, &scifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &scifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; mc = malloc(sizeof(struct lagg_mc), M_DEVBUF, M_NOWAIT); @@ -1556,7 +1563,7 @@ lagg_clrmulti(struct lagg_port *lp) { struct lagg_mc *mc; - LAGG_WLOCK_ASSERT(lp->lp_softc); + LAGG_XLOCK_ASSERT(lp->lp_softc); while ((mc = SLIST_FIRST(&lp->lp_mc_head)) != NULL) { SLIST_REMOVE(&lp->lp_mc_head, mc, lagg_mc, mc_entries); if (mc->mc_ifma && lp->lp_detaching == 0) @@ -1636,16 +1643,12 @@ static int lagg_transmit(struct ifnet *ifp, struct mbuf *m) { struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; - int error, len, mcast; - struct rm_priotracker tracker; - - len = m->m_pkthdr.len; - mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0; + int error; - LAGG_RLOCK(sc, &tracker); + LAGG_RLOCK(); /* We need a Tx algorithm and at least one port */ if (sc->sc_proto == LAGG_PROTO_NONE || sc->sc_count == 0) { - LAGG_RUNLOCK(sc, &tracker); + LAGG_RUNLOCK(); m_freem(m); if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); return (ENXIO); @@ -1654,7 +1657,7 @@ lagg_transmit(struct ifnet *ifp, struct mbuf *m) ETHER_BPF_MTAP(ifp, m); error = lagg_proto_start(sc, m); - LAGG_RUNLOCK(sc, &tracker); + LAGG_RUNLOCK(); if (error != 0) if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); @@ -1676,33 +1679,25 @@ lagg_input(struct ifnet *ifp, struct mbuf *m) struct lagg_port *lp = ifp->if_lagg; struct lagg_softc *sc = lp->lp_softc; struct ifnet *scifp = sc->sc_ifp; - struct rm_priotracker tracker; - LAGG_RLOCK(sc, &tracker); + LAGG_RLOCK(); if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || - (lp->lp_flags & LAGG_PORT_DISABLED) || + lp->lp_detaching != 0 || sc->sc_proto == LAGG_PROTO_NONE) { - LAGG_RUNLOCK(sc, &tracker); + LAGG_RUNLOCK(); m_freem(m); return (NULL); } ETHER_BPF_MTAP(scifp, m); - if (lp->lp_detaching != 0) { + m = lagg_proto_input(sc, lp, m); + if (m != NULL && (scifp->if_flags & IFF_MONITOR) != 0) { m_freem(m); m = NULL; - } else - m = lagg_proto_input(sc, lp, m); - - if (m != NULL) { - if (scifp->if_flags & IFF_MONITOR) { - m_freem(m); - m = NULL; - } } - LAGG_RUNLOCK(sc, &tracker); + LAGG_RUNLOCK(); return (m); } @@ -1727,12 +1722,12 @@ lagg_media_status(struct ifnet *ifp, struct ifmediareq *imr) imr->ifm_status = IFM_AVALID; imr->ifm_active = IFM_ETHER | IFM_AUTO; - LAGG_SLOCK(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (LAGG_PORTACTIVE(lp)) imr->ifm_status |= IFM_ACTIVE; } - LAGG_SUNLOCK(sc); + LAGG_RUNLOCK(); } static void @@ -1745,12 +1740,14 @@ lagg_linkstate(struct lagg_softc *sc) LAGG_XLOCK_ASSERT(sc); /* Our link is considered up if at least one of our ports is active */ - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (lp->lp_ifp->if_link_state == LINK_STATE_UP) { new_link = LINK_STATE_UP; break; } } + LAGG_RUNLOCK(); if_link_state_change(sc->sc_ifp, new_link); /* Update if_baudrate to reflect the max possible speed */ @@ -1763,8 +1760,10 @@ lagg_linkstate(struct lagg_softc *sc) case LAGG_PROTO_LOADBALANCE: case LAGG_PROTO_BROADCAST: speed = 0; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) speed += lp->lp_ifp->if_baudrate; + LAGG_RUNLOCK(); sc->sc_ifp->if_baudrate = speed; break; case LAGG_PROTO_LACP: @@ -1805,20 +1804,22 @@ lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) rval = lp; goto found; } - if ((lp_next = SLIST_NEXT(lp, lp_entries)) != NULL && + if ((lp_next = CK_SLIST_NEXT(lp, lp_entries)) != NULL && LAGG_PORTACTIVE(lp_next)) { rval = lp_next; goto found; } -search: - SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { + search: + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (LAGG_PORTACTIVE(lp_next)) { + LAGG_RUNLOCK(); rval = lp_next; goto found; } } - + LAGG_RUNLOCK(); found: return (rval); } @@ -1859,10 +1860,10 @@ lagg_rr_start(struct lagg_softc *sc, struct mbuf *m) p = atomic_fetchadd_32(&sc->sc_seq, 1); p %= sc->sc_count; - lp = SLIST_FIRST(&sc->sc_ports); + lp = CK_SLIST_FIRST(&sc->sc_ports); while (p--) - lp = SLIST_NEXT(lp, lp_entries); + lp = CK_SLIST_NEXT(lp, lp_entries); /* * Check the port's link state. This will return the next active @@ -1900,7 +1901,8 @@ lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m) struct lagg_port *lp, *last = NULL; struct mbuf *m0; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (!LAGG_PORTACTIVE(lp)) continue; @@ -1920,6 +1922,8 @@ lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m) } last = lp; } + LAGG_RUNLOCK(); + if (last == NULL) { m_freem(m); return (ENOENT); @@ -2003,11 +2007,12 @@ lagg_lb_attach(struct lagg_softc *sc) struct lagg_port *lp; struct lagg_lb *lb; + LAGG_XLOCK_ASSERT(sc); lb = malloc(sizeof(struct lagg_lb), M_DEVBUF, M_WAITOK | M_ZERO); lb->lb_key = m_ether_tcpip_hash_init(); sc->sc_psc = lb; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lagg_lb_port_create(lp); } @@ -2017,7 +2022,6 @@ lagg_lb_detach(struct lagg_softc *sc) struct lagg_lb *lb; lb = (struct lagg_lb *)sc->sc_psc; - LAGG_WUNLOCK(sc); if (lb != NULL) free(lb, M_DEVBUF); } @@ -2030,7 +2034,8 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp) int i = 0; bzero(&lb->lb_ports, sizeof(lb->lb_ports)); - SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { + LAGG_RLOCK(); + CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (lp_next == lp) continue; if (i >= LAGG_MAX_PORTS) @@ -2040,6 +2045,7 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp) sc->sc_ifname, lp_next->lp_ifp->if_xname, i); lb->lb_ports[i++] = lp_next; } + LAGG_RUNLOCK(); return (0); } @@ -2106,7 +2112,8 @@ lagg_lacp_attach(struct lagg_softc *sc) struct lagg_port *lp; lacp_attach(sc); - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + LAGG_XLOCK_ASSERT(sc); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_create(lp); } @@ -2116,13 +2123,12 @@ lagg_lacp_detach(struct lagg_softc *sc) struct lagg_port *lp; void *psc; - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + LAGG_XLOCK_ASSERT(sc); + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_destroy(lp); psc = sc->sc_psc; sc->sc_psc = NULL; - LAGG_WUNLOCK(sc); - lacp_detach(psc); } @@ -2134,11 +2140,11 @@ lagg_lacp_lladdr(struct lagg_softc *sc) LAGG_SXLOCK_ASSERT(sc); /* purge all the lacp ports */ - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_destroy(lp); /* add them back in */ - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_create(lp); } diff --git a/freebsd/sys/net/if_lagg.h b/freebsd/sys/net/if_lagg.h index 201d909a..f1e2d8f4 100644 --- a/freebsd/sys/net/if_lagg.h +++ b/freebsd/sys/net/if_lagg.h @@ -42,9 +42,8 @@ #define LAGG_PORT_ACTIVE 0x00000004 /* port is active */ #define LAGG_PORT_COLLECTING 0x00000008 /* port is receiving frames */ #define LAGG_PORT_DISTRIBUTING 0x00000010 /* port is sending frames */ -#define LAGG_PORT_DISABLED 0x00000020 /* port is disabled */ #define LAGG_PORT_BITS "\20\01MASTER\02STACK\03ACTIVE\04COLLECTING" \ - "\05DISTRIBUTING\06DISABLED" + "\05DISTRIBUTING" /* Supported lagg PROTOs */ typedef enum { @@ -218,7 +217,7 @@ struct lagg_softc { uint32_t sc_flags; int sc_destroying; /* destroying lagg */ - SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */ + CK_SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */ SLIST_ENTRY(lagg_softc) sc_entries; eventhandler_tag vlan_attach; @@ -252,29 +251,10 @@ struct lagg_port { const struct sockaddr *, struct route *); struct lagg_counters port_counters; /* ifp counters copy */ - SLIST_ENTRY(lagg_port) lp_entries; + CK_SLIST_ENTRY(lagg_port) lp_entries; + struct epoch_context lp_epoch_ctx; }; -#define LAGG_LOCK_INIT(_sc) rm_init(&(_sc)->sc_mtx, "if_lagg rmlock") -#define LAGG_LOCK_DESTROY(_sc) rm_destroy(&(_sc)->sc_mtx) -#define LAGG_RLOCK(_sc, _p) rm_rlock(&(_sc)->sc_mtx, (_p)) -#define LAGG_WLOCK(_sc) rm_wlock(&(_sc)->sc_mtx) -#define LAGG_RUNLOCK(_sc, _p) rm_runlock(&(_sc)->sc_mtx, (_p)) -#define LAGG_WUNLOCK(_sc) rm_wunlock(&(_sc)->sc_mtx) -#define LAGG_RLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_RLOCKED) -#define LAGG_WLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_WLOCKED) -#define LAGG_UNLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_UNLOCKED) - -#define LAGG_SX_INIT(_sc) sx_init(&(_sc)->sc_sx, "if_lagg sx") -#define LAGG_SX_DESTROY(_sc) sx_destroy(&(_sc)->sc_sx) -#define LAGG_SLOCK(_sc) sx_slock(&(_sc)->sc_sx) -#define LAGG_XLOCK(_sc) sx_xlock(&(_sc)->sc_sx) -#define LAGG_SUNLOCK(_sc) sx_sunlock(&(_sc)->sc_sx) -#define LAGG_XUNLOCK(_sc) sx_xunlock(&(_sc)->sc_sx) -#define LAGG_SXLOCK_ASSERT(_sc) sx_assert(&(_sc)->sc_sx, SA_LOCKED) -#define LAGG_SLOCK_ASSERT(_sc) sx_assert(&(_sc)->sc_sx, SA_SLOCKED) -#define LAGG_XLOCK_ASSERT(_sc) sx_assert(&(_sc)->sc_sx, SA_XLOCKED) - extern struct mbuf *(*lagg_input_p)(struct ifnet *, struct mbuf *); extern void (*lagg_linkstate_p)(struct ifnet *, int ); diff --git a/freebsd/sys/net/if_llatbl.c b/freebsd/sys/net/if_llatbl.c index d98153b9..d6e9dbaf 100644 --- a/freebsd/sys/net/if_llatbl.c +++ b/freebsd/sys/net/if_llatbl.c @@ -148,7 +148,7 @@ htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg) error = 0; for (i = 0; i < llt->llt_hsize; i++) { - LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { + CK_LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { error = f(llt, lle, farg); if (error != 0) break; @@ -175,7 +175,7 @@ htable_link_entry(struct lltable *llt, struct llentry *lle) lle->lle_tbl = llt; lle->lle_head = lleh; lle->la_flags |= LLE_LINKED; - LIST_INSERT_HEAD(lleh, lle, lle_next); + CK_LIST_INSERT_HEAD(lleh, lle, lle_next); } static void @@ -184,7 +184,7 @@ htable_unlink_entry(struct llentry *lle) if ((lle->la_flags & LLE_LINKED) != 0) { IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp); - LIST_REMOVE(lle, lle_next); + CK_LIST_REMOVE(lle, lle_next); lle->la_flags &= ~(LLE_VALID | LLE_LINKED); #if 0 lle->lle_tbl = NULL; @@ -209,7 +209,7 @@ htable_prefix_free_cb(struct lltable *llt, struct llentry *lle, void *farg) if (llt->llt_match_prefix(pmd->addr, pmd->mask, pmd->flags, lle)) { LLE_WLOCK(lle); - LIST_INSERT_HEAD(&pmd->dchain, lle, lle_chain); + CK_LIST_INSERT_HEAD(&pmd->dchain, lle, lle_chain); } return (0); @@ -226,7 +226,7 @@ htable_prefix_free(struct lltable *llt, const struct sockaddr *addr, pmd.addr = addr; pmd.mask = mask; pmd.flags = flags; - LIST_INIT(&pmd.dchain); + CK_LIST_INIT(&pmd.dchain); IF_AFDATA_WLOCK(llt->llt_ifp); /* Push matching lles to chain */ @@ -235,7 +235,7 @@ htable_prefix_free(struct lltable *llt, const struct sockaddr *addr, llentries_unlink(llt, &pmd.dchain); IF_AFDATA_WUNLOCK(llt->llt_ifp); - LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next) + CK_LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next) lltable_free_entry(llt, lle); } @@ -252,7 +252,7 @@ llentries_unlink(struct lltable *llt, struct llentries *head) { struct llentry *lle, *next; - LIST_FOREACH_SAFE(lle, head, lle_chain, next) + CK_LIST_FOREACH_SAFE(lle, head, lle_chain, next) llt->llt_unlink_entry(lle); } @@ -498,7 +498,7 @@ lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg) dchain = (struct llentries *)farg; LLE_WLOCK(lle); - LIST_INSERT_HEAD(dchain, lle, lle_chain); + CK_LIST_INSERT_HEAD(dchain, lle, lle_chain); return (0); } @@ -516,14 +516,14 @@ lltable_free(struct lltable *llt) lltable_unlink(llt); - LIST_INIT(&dchain); + CK_LIST_INIT(&dchain); IF_AFDATA_WLOCK(llt->llt_ifp); /* Push all lles to @dchain */ lltable_foreach_lle(llt, lltable_free_cb, &dchain); llentries_unlink(llt, &dchain); IF_AFDATA_WUNLOCK(llt->llt_ifp); - LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) { + CK_LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) { if (callout_stop(&lle->lle_timer) > 0) LLE_REMREF(lle); llentry_free(lle); @@ -546,7 +546,7 @@ lltable_drain(int af) continue; for (i=0; i < llt->llt_hsize; i++) { - LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { + CK_LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { LLE_WLOCK(lle); if (lle->la_hold) { m_freem(lle->la_hold); @@ -622,7 +622,7 @@ lltable_allocate_htbl(uint32_t hsize) M_LLTABLE, M_WAITOK | M_ZERO); for (i = 0; i < llt->llt_hsize; i++) - LIST_INIT(&llt->lle_head[i]); + CK_LIST_INIT(&llt->lle_head[i]); /* Set some default callbacks */ llt->llt_link_entry = htable_link_entry; @@ -848,7 +848,7 @@ llatbl_lle_show(struct llentry_sa *la) lle = &la->base; db_printf("lle=%p\n", lle); - db_printf(" lle_next=%p\n", lle->lle_next.le_next); + db_printf(" lle_next=%p\n", lle->lle_next.cle_next); db_printf(" lle_lock=%p\n", &lle->lle_lock); db_printf(" lle_tbl=%p\n", lle->lle_tbl); db_printf(" lle_head=%p\n", lle->lle_head); @@ -919,7 +919,7 @@ llatbl_llt_show(struct lltable *llt) llt, llt->llt_af, llt->llt_ifp); for (i = 0; i < llt->llt_hsize; i++) { - LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { + CK_LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { llatbl_lle_show((struct llentry_sa *)lle); if (db_pager_quit) diff --git a/freebsd/sys/net/if_llatbl.h b/freebsd/sys/net/if_llatbl.h index 9cec4ac7..74301284 100644 --- a/freebsd/sys/net/if_llatbl.h +++ b/freebsd/sys/net/if_llatbl.h @@ -34,13 +34,15 @@ __FBSDID("$FreeBSD$"); #include <sys/_rwlock.h> #include <netinet/in.h> +#include <sys/epoch.h> +#include <sys/ck.h> struct ifnet; struct sysctl_req; struct rt_msghdr; struct rt_addrinfo; struct llentry; -LIST_HEAD(llentries, llentry); +CK_LIST_HEAD(llentries, llentry); #define LLE_MAX_LINKHDR 24 /* Full IB header */ /* @@ -48,7 +50,7 @@ LIST_HEAD(llentries, llentry); * a shared lock */ struct llentry { - LIST_ENTRY(llentry) lle_next; + CK_LIST_ENTRY(llentry) lle_next; union { struct in_addr addr4; struct in6_addr addr6; @@ -76,10 +78,11 @@ struct llentry { int lle_refcnt; char *ll_addr; /* link-layer address */ - LIST_ENTRY(llentry) lle_chain; /* chain of deleted items */ + CK_LIST_ENTRY(llentry) lle_chain; /* chain of deleted items */ struct callout lle_timer; struct rwlock lle_lock; struct mtx req_mtx; + struct epoch_context lle_epoch_ctx; }; #define LLE_WLOCK(lle) rw_wlock(&(lle)->lle_lock) diff --git a/freebsd/sys/net/if_loop.c b/freebsd/sys/net/if_loop.c index bae46891..988b9f9d 100644 --- a/freebsd/sys/net/if_loop.c +++ b/freebsd/sys/net/if_loop.c @@ -138,7 +138,7 @@ lo_clone_create(struct if_clone *ifc, int unit, caddr_t params) ifp->if_output = looutput; ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_capabilities = ifp->if_capenable = - IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6; + IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 | IFCAP_LINKSTATE; ifp->if_hwassist = LO_CSUM_FEATURES | LO_CSUM_FEATURES6; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); @@ -415,6 +415,8 @@ loioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSIFFLAGS: + if_link_state_change(ifp, (ifp->if_flags & IFF_UP) ? + LINK_STATE_UP: LINK_STATE_DOWN); break; case SIOCSIFCAP: diff --git a/freebsd/sys/net/if_media.c b/freebsd/sys/net/if_media.c index cceb0079..867f7fc3 100644 --- a/freebsd/sys/net/if_media.c +++ b/freebsd/sys/net/if_media.c @@ -401,18 +401,6 @@ struct ifmedia_description ifm_subtype_ethernet_descriptions[] = struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; -struct ifmedia_description ifm_subtype_tokenring_descriptions[] = - IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; - -struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = - IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; - -struct ifmedia_description ifm_subtype_fddi_descriptions[] = - IFM_SUBTYPE_FDDI_DESCRIPTIONS; - -struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = - IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; - struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; @@ -448,16 +436,6 @@ struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { NULL, }, { - &ifm_subtype_tokenring_descriptions[0], - &ifm_subtype_tokenring_option_descriptions[0], - NULL, - }, - { - &ifm_subtype_fddi_descriptions[0], - &ifm_subtype_fddi_option_descriptions[0], - NULL, - }, - { &ifm_subtype_ieee80211_descriptions[0], &ifm_subtype_ieee80211_option_descriptions[0], &ifm_subtype_ieee80211_mode_descriptions[0] diff --git a/freebsd/sys/net/if_media.h b/freebsd/sys/net/if_media.h index ecc2b418..97cd6552 100644 --- a/freebsd/sys/net/if_media.h +++ b/freebsd/sys/net/if_media.h @@ -217,32 +217,6 @@ uint64_t ifmedia_baudrate(int); #define IFM_ETH_XSHIFT 6 /* shift XTYPE next to TMASK */ /* - * Token ring - */ -#define IFM_TOKEN 0x00000040 -#define IFM_TOK_STP4 3 /* Shielded twisted pair 4m - DB9 */ -#define IFM_TOK_STP16 4 /* Shielded twisted pair 16m - DB9 */ -#define IFM_TOK_UTP4 5 /* Unshielded twisted pair 4m - RJ45 */ -#define IFM_TOK_UTP16 6 /* Unshielded twisted pair 16m - RJ45 */ -#define IFM_TOK_STP100 7 /* Shielded twisted pair 100m - DB9 */ -#define IFM_TOK_UTP100 8 /* Unshielded twisted pair 100m - RJ45 */ -#define IFM_TOK_ETR 0x00000200 /* Early token release */ -#define IFM_TOK_SRCRT 0x00000400 /* Enable source routing features */ -#define IFM_TOK_ALLR 0x00000800 /* All routes / Single route bcast */ -#define IFM_TOK_DTR 0x00002000 /* Dedicated token ring */ -#define IFM_TOK_CLASSIC 0x00004000 /* Classic token ring */ -#define IFM_TOK_AUTO 0x00008000 /* Automatic Dedicate/Classic token ring */ - -/* - * FDDI - */ -#define IFM_FDDI 0x00000060 -#define IFM_FDDI_SMF 3 /* Single-mode fiber */ -#define IFM_FDDI_MMF 4 /* Multi-mode fiber */ -#define IFM_FDDI_UTP 5 /* CDDI / UTP */ -#define IFM_FDDI_DA 0x00000100 /* Dual attach / single attach */ - -/* * IEEE 802.11 Wireless */ #define IFM_IEEE80211 0x00000080 @@ -393,8 +367,6 @@ struct ifmedia_description { #define IFM_TYPE_DESCRIPTIONS { \ { IFM_ETHER, "Ethernet" }, \ - { IFM_TOKEN, "Token ring" }, \ - { IFM_FDDI, "FDDI" }, \ { IFM_IEEE80211, "IEEE 802.11 Wireless Ethernet" }, \ { IFM_ATM, "ATM" }, \ { 0, NULL }, \ @@ -511,55 +483,6 @@ struct ifmedia_description { { 0, NULL }, \ } -#define IFM_SUBTYPE_TOKENRING_DESCRIPTIONS { \ - { IFM_TOK_STP4, "DB9/4Mbit" }, \ - { IFM_TOK_STP16, "DB9/16Mbit" }, \ - { IFM_TOK_UTP4, "UTP/4Mbit" }, \ - { IFM_TOK_UTP16, "UTP/16Mbit" }, \ - { IFM_TOK_STP100, "STP/100Mbit" }, \ - { IFM_TOK_UTP100, "UTP/100Mbit" }, \ - { 0, NULL }, \ -} - -#define IFM_SUBTYPE_TOKENRING_ALIASES { \ - { IFM_TOK_STP4, "4STP" }, \ - { IFM_TOK_STP16, "16STP" }, \ - { IFM_TOK_UTP4, "4UTP" }, \ - { IFM_TOK_UTP16, "16UTP" }, \ - { IFM_TOK_STP100, "100STP" }, \ - { IFM_TOK_UTP100, "100UTP" }, \ - { 0, NULL }, \ -} - -#define IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS { \ - { IFM_TOK_ETR, "EarlyTokenRelease" }, \ - { IFM_TOK_SRCRT, "SourceRouting" }, \ - { IFM_TOK_ALLR, "AllRoutes" }, \ - { IFM_TOK_DTR, "Dedicated" }, \ - { IFM_TOK_CLASSIC,"Classic" }, \ - { IFM_TOK_AUTO, " " }, \ - { 0, NULL }, \ -} - -#define IFM_SUBTYPE_FDDI_DESCRIPTIONS { \ - { IFM_FDDI_SMF, "Single-mode" }, \ - { IFM_FDDI_MMF, "Multi-mode" }, \ - { IFM_FDDI_UTP, "UTP" }, \ - { 0, NULL }, \ -} - -#define IFM_SUBTYPE_FDDI_ALIASES { \ - { IFM_FDDI_SMF, "SMF" }, \ - { IFM_FDDI_MMF, "MMF" }, \ - { IFM_FDDI_UTP, "CDDI" }, \ - { 0, NULL }, \ -} - -#define IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS { \ - { IFM_FDDI_DA, "Dual-attach" }, \ - { 0, NULL }, \ -} - #define IFM_SUBTYPE_IEEE80211_DESCRIPTIONS { \ { IFM_IEEE80211_FH1, "FH/1Mbps" }, \ { IFM_IEEE80211_FH2, "FH/2Mbps" }, \ @@ -797,15 +720,6 @@ struct ifmedia_baudrate { { IFM_ETHER | IFM_25G_ACC, IF_Gbps(25ULL) }, \ { IFM_ETHER | IFM_25G_AOC, IF_Gbps(25ULL) }, \ \ - { IFM_TOKEN | IFM_TOK_STP4, IF_Mbps(4) }, \ - { IFM_TOKEN | IFM_TOK_STP16, IF_Mbps(16) }, \ - { IFM_TOKEN | IFM_TOK_UTP4, IF_Mbps(4) }, \ - { IFM_TOKEN | IFM_TOK_UTP16, IF_Mbps(16) }, \ - \ - { IFM_FDDI | IFM_FDDI_SMF, IF_Mbps(100) }, \ - { IFM_FDDI | IFM_FDDI_MMF, IF_Mbps(100) }, \ - { IFM_FDDI | IFM_FDDI_UTP, IF_Mbps(100) }, \ - \ { IFM_IEEE80211 | IFM_IEEE80211_FH1, IF_Mbps(1) }, \ { IFM_IEEE80211 | IFM_IEEE80211_FH2, IF_Mbps(2) }, \ { IFM_IEEE80211 | IFM_IEEE80211_DS2, IF_Mbps(2) }, \ @@ -842,10 +756,6 @@ struct ifmedia_status_description { #define IFM_STATUS_DESCRIPTIONS { \ { IFM_ETHER, IFM_AVALID, IFM_ACTIVE, \ { "no carrier", "active" } }, \ - { IFM_FDDI, IFM_AVALID, IFM_ACTIVE, \ - { "no ring", "inserted" } }, \ - { IFM_TOKEN, IFM_AVALID, IFM_ACTIVE, \ - { "no ring", "inserted" } }, \ { IFM_IEEE80211, IFM_AVALID, IFM_ACTIVE, \ { "no network", "active" } }, \ { IFM_ATM, IFM_AVALID, IFM_ACTIVE, \ diff --git a/freebsd/sys/net/if_spppsubr.c b/freebsd/sys/net/if_spppsubr.c index 1f85c00f..f5b78dec 100644 --- a/freebsd/sys/net/if_spppsubr.c +++ b/freebsd/sys/net/if_spppsubr.c @@ -4839,7 +4839,7 @@ sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) */ si = NULL; if_addr_rlock(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (ifa->ifa_addr->sa_family == AF_INET) { si = (struct sockaddr_in *)ifa->ifa_addr; sm = (struct sockaddr_in *)ifa->ifa_netmask; @@ -4881,7 +4881,7 @@ sppp_set_ip_addr(struct sppp *sp, u_long src) */ si = NULL; if_addr_rlock(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family == AF_INET) { si = (struct sockaddr_in *)ifa->ifa_addr; if (si != NULL) { @@ -4943,7 +4943,7 @@ sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, */ si = NULL; if_addr_rlock(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (ifa->ifa_addr->sa_family == AF_INET6) { si = (struct sockaddr_in6 *)ifa->ifa_addr; sm = (struct sockaddr_in6 *)ifa->ifa_netmask; @@ -4998,7 +4998,7 @@ sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) sin6 = NULL; if_addr_rlock(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { diff --git a/freebsd/sys/net/if_stf.c b/freebsd/sys/net/if_stf.c index 2aab358c..1d16b2d7 100644 --- a/freebsd/sys/net/if_stf.c +++ b/freebsd/sys/net/if_stf.c @@ -278,7 +278,7 @@ static int stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) { struct stf_softc *sc = ifp->if_softc; - int err; + int err __unused; err = encap_detach(sc->encap_cookie); KASSERT(err == 0, ("Unexpected error detaching encap_cookie")); @@ -386,7 +386,7 @@ stf_getsrcifa6(struct ifnet *ifp, struct in6_addr *addr, struct in6_addr *mask) struct in_addr in; if_addr_rlock(ifp); - TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) { if (ia->ifa_addr->sa_family != AF_INET6) continue; sin6 = (struct sockaddr_in6 *)ia->ifa_addr; @@ -563,7 +563,7 @@ stf_checkaddr4(struct stf_softc *sc, struct in_addr *in, struct ifnet *inifp) * reject packets with broadcast */ IN_IFADDR_RLOCK(&in_ifa_tracker); - TAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) { + CK_STAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) { if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0) continue; if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) { diff --git a/freebsd/sys/net/if_tap.c b/freebsd/sys/net/if_tap.c index ce143f9f..c918a14e 100644 --- a/freebsd/sys/net/if_tap.c +++ b/freebsd/sys/net/if_tap.c @@ -39,7 +39,6 @@ * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $ */ -#include <rtems/bsd/local/opt_compat.h> #include <rtems/bsd/local/opt_inet.h> #include <sys/param.h> @@ -80,7 +79,6 @@ #include <net/if_tapvar.h> #include <net/if_tap.h> - #define CDEV_NAME "tap" #define TAPDEBUG if (tapdebug) printf @@ -551,7 +549,7 @@ tapclose(struct cdev *dev, int foo, int bar, struct thread *td) if (ifp->if_drv_flags & IFF_DRV_RUNNING) { ifp->if_drv_flags &= ~IFF_DRV_RUNNING; mtx_unlock(&tp->tap_mtx); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { rtinit(ifa, (int)RTM_DELETE, 0); } if_purgeaddrs(ifp); diff --git a/freebsd/sys/net/if_tun.c b/freebsd/sys/net/if_tun.c index 598a5c14..e4a0b02f 100644 --- a/freebsd/sys/net/if_tun.c +++ b/freebsd/sys/net/if_tun.c @@ -476,7 +476,7 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td) ifp->if_drv_flags &= ~IFF_DRV_RUNNING; mtx_unlock(&tp->tun_mtx); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { /* deal w/IPv4 PtP destination; unlocked read */ if (ifa->ifa_addr->sa_family == AF_INET) { rtinit(ifa, (int)RTM_DELETE, @@ -518,7 +518,7 @@ tuninit(struct ifnet *ifp) #ifdef INET if_addr_rlock(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family == AF_INET) { struct sockaddr_in *si; diff --git a/freebsd/sys/net/if_var.h b/freebsd/sys/net/if_var.h index a131c496..f8e18f7e 100644 --- a/freebsd/sys/net/if_var.h +++ b/freebsd/sys/net/if_var.h @@ -70,27 +70,29 @@ struct route; /* if_output */ struct vnet; struct ifmedia; struct netmap_adapter; +struct netdump_methods; #ifdef _KERNEL #include <sys/mbuf.h> /* ifqueue only? */ #include <sys/buf_ring.h> #include <net/vnet.h> #endif /* _KERNEL */ +#include <sys/ck.h> #include <sys/counter.h> +#include <sys/epoch.h> #include <sys/lock.h> /* XXX */ #include <sys/mutex.h> /* struct ifqueue */ #include <sys/rwlock.h> /* XXX */ #include <sys/sx.h> /* XXX */ #include <sys/_task.h> /* if_link_task */ - #define IF_DUNIT_NONE -1 #include <net/altq/if_altq.h> -TAILQ_HEAD(ifnethead, ifnet); /* we use TAILQs so that the order of */ -TAILQ_HEAD(ifaddrhead, ifaddr); /* instantiation is preserved in the list */ -TAILQ_HEAD(ifmultihead, ifmultiaddr); -TAILQ_HEAD(ifgrouphead, ifg_group); +CK_STAILQ_HEAD(ifnethead, ifnet); /* we use TAILQs so that the order of */ +CK_STAILQ_HEAD(ifaddrhead, ifaddr); /* instantiation is preserved in the list */ +CK_STAILQ_HEAD(ifmultihead, ifmultiaddr); +CK_STAILQ_HEAD(ifgrouphead, ifg_group); #ifdef _KERNEL VNET_DECLARE(struct pfil_head, link_pfil_hook); /* packet filter hooks */ @@ -103,6 +105,15 @@ VNET_DECLARE(struct hhook_head *, ipsec_hhh_in[HHOOK_IPSEC_COUNT]); VNET_DECLARE(struct hhook_head *, ipsec_hhh_out[HHOOK_IPSEC_COUNT]); #define V_ipsec_hhh_in VNET(ipsec_hhh_in) #define V_ipsec_hhh_out VNET(ipsec_hhh_out) +#ifndef __rtems__ +extern epoch_t net_epoch_preempt; +extern epoch_t net_epoch; +#else /* __rtems__ */ +extern struct epoch _bsd_net_epoch_preempt; +#define net_epoch_preempt &_bsd_net_epoch_preempt +extern struct epoch _bsd_net_epoch; +#define net_epoch &_bsd_net_epoch +#endif /* __rtems__ */ #endif /* _KERNEL */ typedef enum { @@ -234,9 +245,9 @@ typedef void (if_snd_tag_free_t)(struct m_snd_tag *); */ struct ifnet { /* General book keeping of interface lists. */ - TAILQ_ENTRY(ifnet) if_link; /* all struct ifnets are chained */ + CK_STAILQ_ENTRY(ifnet) if_link; /* all struct ifnets are chained (CK_) */ LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */ - TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */ + CK_STAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if (CK_) */ /* protected by if_addr_lock */ u_char if_alloctype; /* if_type at time of allocation */ @@ -276,7 +287,7 @@ struct ifnet { struct task if_linktask; /* task for link change events */ /* Addresses of different protocol families assigned to this if. */ - struct rwlock if_addr_lock; /* lock to protect address lists */ + struct mtx if_addr_lock; /* lock to protect address lists */ /* * if_addrhead is the list of all addresses associated to * an interface. @@ -293,7 +304,7 @@ struct ifnet { struct ifaddr *if_addr; /* pointer to link-level address */ void *if_hw_addr; /* hardware link-level address */ const u_int8_t *if_broadcastaddr; /* linklevel broadcast bytestring */ - struct rwlock if_afdata_lock; + struct mtx if_afdata_lock; void *if_afdata[AF_MAX]; int if_afdata_initialized; @@ -317,6 +328,10 @@ struct ifnet { struct route *); void (*if_input) /* input routine (from h/w driver) */ (struct ifnet *, struct mbuf *); + struct mbuf *(*if_bridge_input)(struct ifnet *, struct mbuf *); + int (*if_bridge_output)(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); + void (*if_bridge_linkstate)(struct ifnet *ifp); if_start_fn_t if_start; /* initiate output routine */ if_ioctl_fn_t if_ioctl; /* ioctl routine */ if_init_fn_t if_init; /* Init routine */ @@ -370,6 +385,14 @@ struct ifnet { #ifndef __rtems__ /* + * Netdump hooks to be called while dumping. + */ + struct netdump_methods *if_netdump_methods; +#endif /* __rtems__ */ + struct epoch_context if_epoch_ctx; + +#ifndef __rtems__ + /* * Spare fields to be added before branching a stable branch, so * that structure can be enhanced without changing the kernel * binary interface. @@ -396,14 +419,18 @@ struct rtems_ifinputreq { /* * Locks for address lists on the network interface. */ -#define IF_ADDR_LOCK_INIT(if) rw_init(&(if)->if_addr_lock, "if_addr_lock") -#define IF_ADDR_LOCK_DESTROY(if) rw_destroy(&(if)->if_addr_lock) -#define IF_ADDR_WLOCK(if) rw_wlock(&(if)->if_addr_lock) -#define IF_ADDR_WUNLOCK(if) rw_wunlock(&(if)->if_addr_lock) -#define IF_ADDR_RLOCK(if) rw_rlock(&(if)->if_addr_lock) -#define IF_ADDR_RUNLOCK(if) rw_runlock(&(if)->if_addr_lock) -#define IF_ADDR_LOCK_ASSERT(if) rw_assert(&(if)->if_addr_lock, RA_LOCKED) -#define IF_ADDR_WLOCK_ASSERT(if) rw_assert(&(if)->if_addr_lock, RA_WLOCKED) +#define IF_ADDR_LOCK_INIT(if) mtx_init(&(if)->if_addr_lock, "if_addr_lock", NULL, MTX_DEF) +#define IF_ADDR_LOCK_DESTROY(if) mtx_destroy(&(if)->if_addr_lock) +#define IF_ADDR_RLOCK(if) epoch_enter_preempt(net_epoch_preempt); +#define IF_ADDR_RUNLOCK(if) epoch_exit_preempt(net_epoch_preempt); + +#define IF_ADDR_WLOCK(if) mtx_lock(&(if)->if_addr_lock) +#define IF_ADDR_WUNLOCK(if) mtx_unlock(&(if)->if_addr_lock) +#define IF_ADDR_LOCK_ASSERT(if) MPASS(in_epoch() || mtx_owned(&(if)->if_addr_lock)) +#define IF_ADDR_WLOCK_ASSERT(if) mtx_assert(&(if)->if_addr_lock, MA_OWNED) +#define NET_EPOCH_ENTER() epoch_enter_preempt(net_epoch_preempt) +#define NET_EPOCH_EXIT() epoch_exit_preempt(net_epoch_preempt) + /* * Function variations on locking macros intended to be used by loadable @@ -435,6 +462,8 @@ EVENTHANDLER_DECLARE(ifnet_link_event, ifnet_link_event_handler_t); /* Interface up/down event */ #define IFNET_EVENT_UP 0 #define IFNET_EVENT_DOWN 1 +#define IFNET_EVENT_PCP 2 /* priority code point, PCP */ + typedef void (*ifnet_event_fn)(void *, struct ifnet *ifp, int event); EVENTHANDLER_DECLARE(ifnet_event, ifnet_event_fn); #endif /* _SYS_EVENTHANDLER_H_ */ @@ -446,18 +475,18 @@ struct ifg_group { char ifg_group[IFNAMSIZ]; u_int ifg_refcnt; void *ifg_pf_kif; - TAILQ_HEAD(, ifg_member) ifg_members; - TAILQ_ENTRY(ifg_group) ifg_next; + CK_STAILQ_HEAD(, ifg_member) ifg_members; /* (CK_) */ + CK_STAILQ_ENTRY(ifg_group) ifg_next; /* (CK_) */ }; struct ifg_member { - TAILQ_ENTRY(ifg_member) ifgm_next; + CK_STAILQ_ENTRY(ifg_member) ifgm_next; /* (CK_) */ struct ifnet *ifgm_ifp; }; struct ifg_list { struct ifg_group *ifgl_group; - TAILQ_ENTRY(ifg_list) ifgl_next; + CK_STAILQ_ENTRY(ifg_list) ifgl_next; /* (CK_) */ }; #ifdef _SYS_EVENTHANDLER_H_ @@ -473,21 +502,21 @@ EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t); #endif /* _SYS_EVENTHANDLER_H_ */ #define IF_AFDATA_LOCK_INIT(ifp) \ - rw_init(&(ifp)->if_afdata_lock, "if_afdata") + mtx_init(&(ifp)->if_afdata_lock, "if_afdata", NULL, MTX_DEF) -#define IF_AFDATA_WLOCK(ifp) rw_wlock(&(ifp)->if_afdata_lock) -#define IF_AFDATA_RLOCK(ifp) rw_rlock(&(ifp)->if_afdata_lock) -#define IF_AFDATA_WUNLOCK(ifp) rw_wunlock(&(ifp)->if_afdata_lock) -#define IF_AFDATA_RUNLOCK(ifp) rw_runlock(&(ifp)->if_afdata_lock) +#define IF_AFDATA_WLOCK(ifp) mtx_lock(&(ifp)->if_afdata_lock) +#define IF_AFDATA_RLOCK(ifp) epoch_enter_preempt(net_epoch_preempt) +#define IF_AFDATA_WUNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_lock) +#define IF_AFDATA_RUNLOCK(ifp) epoch_exit_preempt(net_epoch_preempt) #define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp) #define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp) -#define IF_AFDATA_TRYLOCK(ifp) rw_try_wlock(&(ifp)->if_afdata_lock) -#define IF_AFDATA_DESTROY(ifp) rw_destroy(&(ifp)->if_afdata_lock) +#define IF_AFDATA_TRYLOCK(ifp) mtx_trylock(&(ifp)->if_afdata_lock) +#define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_lock) -#define IF_AFDATA_LOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_LOCKED) -#define IF_AFDATA_RLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_RLOCKED) -#define IF_AFDATA_WLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_WLOCKED) -#define IF_AFDATA_UNLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_UNLOCKED) +#define IF_AFDATA_LOCK_ASSERT(ifp) MPASS(in_epoch() || mtx_owned(&(ifp)->if_afdata_lock)) +#define IF_AFDATA_RLOCK_ASSERT(ifp) MPASS(in_epoch()); +#define IF_AFDATA_WLOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_lock, MA_OWNED) +#define IF_AFDATA_UNLOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_lock, MA_NOTOWNED) /* * 72 was chosen below because it is the size of a TCP/IP @@ -515,7 +544,7 @@ struct ifaddr { struct sockaddr *ifa_netmask; /* used to determine subnet */ struct ifnet *ifa_ifp; /* back-pointer to interface */ struct carp_softc *ifa_carp; /* pointer to CARP data */ - TAILQ_ENTRY(ifaddr) ifa_link; /* queue macro glue */ + CK_STAILQ_ENTRY(ifaddr) ifa_link; /* queue macro glue */ void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */ (int, struct rtentry *, struct rt_addrinfo *); u_short ifa_flags; /* mostly rt_flags for cloning */ @@ -527,6 +556,7 @@ struct ifaddr { counter_u64_t ifa_opackets; counter_u64_t ifa_ibytes; counter_u64_t ifa_obytes; + struct epoch_context ifa_epoch_ctx; }; struct ifaddr * ifa_alloc(size_t size, int flags); @@ -538,13 +568,14 @@ void ifa_ref(struct ifaddr *ifa); * structure except that it keeps track of multicast addresses. */ struct ifmultiaddr { - TAILQ_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */ + CK_STAILQ_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */ struct sockaddr *ifma_addr; /* address this membership is for */ struct sockaddr *ifma_lladdr; /* link-layer translation, if any */ struct ifnet *ifma_ifp; /* back-pointer to interface */ u_int ifma_refcount; /* reference count */ void *ifma_protospec; /* protocol-specific state, if any */ struct ifmultiaddr *ifma_llifma; /* pointer to ifma for ifma_lladdr */ + struct epoch_context ifma_epoch_ctx; }; extern struct rwlock ifnet_rwlock; @@ -565,16 +596,16 @@ extern struct sx ifnet_sxlock; * write, but also whether it was acquired with sleep support or not. */ #define IFNET_RLOCK_ASSERT() sx_assert(&ifnet_sxlock, SA_SLOCKED) -#define IFNET_RLOCK_NOSLEEP_ASSERT() rw_assert(&ifnet_rwlock, RA_RLOCKED) +#define IFNET_RLOCK_NOSLEEP_ASSERT() MPASS(in_epoch()) #define IFNET_WLOCK_ASSERT() do { \ sx_assert(&ifnet_sxlock, SA_XLOCKED); \ rw_assert(&ifnet_rwlock, RA_WLOCKED); \ } while (0) #define IFNET_RLOCK() sx_slock(&ifnet_sxlock) -#define IFNET_RLOCK_NOSLEEP() rw_rlock(&ifnet_rwlock) +#define IFNET_RLOCK_NOSLEEP() epoch_enter_preempt(net_epoch_preempt) #define IFNET_RUNLOCK() sx_sunlock(&ifnet_sxlock) -#define IFNET_RUNLOCK_NOSLEEP() rw_runlock(&ifnet_rwlock) +#define IFNET_RUNLOCK_NOSLEEP() epoch_exit_preempt(net_epoch_preempt) /* * Look up an ifnet given its index; the _ref variant also acquires a @@ -602,6 +633,12 @@ VNET_DECLARE(struct ifnet *, loif); /* first loopback interface */ #define V_if_index VNET(if_index) #define V_loif VNET(loif) +#ifdef MCAST_VERBOSE +#define MCDPRINTF printf +#else +#define MCDPRINTF(...) +#endif + int if_addgroup(struct ifnet *, const char *); int if_delgroup(struct ifnet *, const char *); int if_addmulti(struct ifnet *, struct sockaddr *, struct ifmultiaddr **); @@ -611,12 +648,14 @@ void if_attach(struct ifnet *); void if_dead(struct ifnet *); int if_delmulti(struct ifnet *, struct sockaddr *); void if_delmulti_ifma(struct ifmultiaddr *); +void if_delmulti_ifma_flags(struct ifmultiaddr *, int flags); void if_detach(struct ifnet *); void if_purgeaddrs(struct ifnet *); void if_delallmulti(struct ifnet *); void if_down(struct ifnet *); struct ifmultiaddr * if_findmulti(struct ifnet *, const struct sockaddr *); +void if_freemulti(struct ifmultiaddr *ifma); void if_free(struct ifnet *); void if_initname(struct ifnet *, const char *, int); void if_link_state_change(struct ifnet *, int); diff --git a/freebsd/sys/net/if_vlan.c b/freebsd/sys/net/if_vlan.c index 79294427..26f6bbde 100644 --- a/freebsd/sys/net/if_vlan.c +++ b/freebsd/sys/net/if_vlan.c @@ -611,7 +611,7 @@ vlan_setmulti(struct ifnet *ifp) /* Now program new ones. */ IF_ADDR_WLOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); @@ -1949,6 +1949,8 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } ifv->ifv_pcp = ifr->ifr_vlan_pcp; vlan_tag_recalculate(ifv); + /* broadcast event about PCP change */ + EVENTHANDLER_INVOKE(ifnet_event, ifp, IFNET_EVENT_PCP); break; case SIOCSIFCAP: diff --git a/freebsd/sys/net/iflib.h b/freebsd/sys/net/iflib.h index 02319322..140c488b 100644 --- a/freebsd/sys/net/iflib.h +++ b/freebsd/sys/net/iflib.h @@ -36,6 +36,8 @@ #include <sys/nv.h> #include <sys/gtaskqueue.h> +struct if_clone; + /* * The value type for indexing, limits max descriptors * to 65535 can be conditionally redefined to uint32_t @@ -57,6 +59,8 @@ struct if_shared_ctx; typedef struct if_shared_ctx *if_shared_ctx_t; struct if_int_delay_info; typedef struct if_int_delay_info *if_int_delay_info_t; +struct if_pseudo; +typedef struct if_pseudo *if_pseudo_t; /* * File organization: @@ -194,6 +198,9 @@ typedef struct if_softc_ctx { int isc_vectors; int isc_nrxqsets; int isc_ntxqsets; + uint8_t isc_min_tx_latency; /* disable doorbell update batching */ + uint8_t isc_rx_mvec_enable; /* generate mvecs on rx */ + uint32_t isc_txrx_budget_bytes_max; int isc_msix_bar; /* can be model specific - initialize in attach_pre */ int isc_tx_nsegments; /* can be model specific - initialize in attach_pre */ int isc_ntxd[8]; @@ -214,6 +221,7 @@ typedef struct if_softc_ctx { int isc_rss_table_mask; int isc_nrxqsets_max; int isc_ntxqsets_max; + uint32_t isc_tx_qdepth; iflib_intr_mode_t isc_intr; uint16_t isc_max_frame_size; /* set at init time by driver */ @@ -259,6 +267,7 @@ struct if_shared_ctx { int isc_rx_process_limit; int isc_tx_reclaim_thresh; int isc_flags; + const char *isc_name; }; typedef struct iflib_dma_info { @@ -320,7 +329,39 @@ typedef enum { * Driver needs frames padded to some minimum length */ #define IFLIB_NEED_ETHER_PAD 0x100 - +/* + * Packets can be freed immediately after encap + */ +#define IFLIB_TXD_ENCAP_PIO 0x00200 +/* + * Use RX completion handler + */ +#define IFLIB_RX_COMPLETION 0x00400 +/* + * Skip refilling cluster free lists + */ +#define IFLIB_SKIP_CLREFILL 0x00800 +/* + * Don't reset on hang + */ +#define IFLIB_NO_HANG_RESET 0x01000 +/* + * Don't need/want most of the niceties of + * queue management + */ +#define IFLIB_PSEUDO 0x02000 +/* + * No DMA support needed / wanted + */ +#define IFLIB_VIRTUAL 0x04000 +/* + * autogenerate a MAC address + */ +#define IFLIB_GEN_MAC 0x08000 +/* + * Interface needs admin task to ignore interface up/down status + */ +#define IFLIB_ADMIN_ALWAYS_RUN 0x10000 /* @@ -363,18 +404,18 @@ int iflib_device_deregister(if_ctx_t); -int iflib_irq_alloc(if_ctx_t, if_irq_t, int, driver_filter_t, void *filter_arg, driver_intr_t, void *arg, char *name); +int iflib_irq_alloc(if_ctx_t, if_irq_t, int, driver_filter_t, void *filter_arg, driver_intr_t, void *arg, const char *name); int iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, - iflib_intr_type_t type, driver_filter_t *filter, - void *filter_arg, int qid, char *name); -void iflib_softirq_alloc_generic(if_ctx_t ctx, if_irq_t irq, iflib_intr_type_t type, void *arg, int qid, char *name); + iflib_intr_type_t type, driver_filter_t *filter, + void *filter_arg, int qid, const char *name); +void iflib_softirq_alloc_generic(if_ctx_t ctx, if_irq_t irq, iflib_intr_type_t type, void *arg, int qid, const char *name); void iflib_irq_free(if_ctx_t ctx, if_irq_t irq); void iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, char *name); -void iflib_config_gtask_init(if_ctx_t ctx, struct grouptask *gtask, - gtask_fn_t *fn, char *name); +void iflib_config_gtask_init(void *ctx, struct grouptask *gtask, + gtask_fn_t *fn, const char *name); void iflib_config_gtask_deinit(struct grouptask *gtask); @@ -396,7 +437,7 @@ int iflib_dma_alloc_multi(if_ctx_t ctx, int *sizes, iflib_dma_info_t *dmalist, i void iflib_dma_free_multi(iflib_dma_info_t *dmalist, int count); -struct mtx *iflib_ctx_lock_get(if_ctx_t); +struct sx *iflib_ctx_lock_get(if_ctx_t); struct mtx *iflib_qset_lock_get(if_ctx_t, uint16_t); void iflib_led_create(if_ctx_t ctx); @@ -404,4 +445,9 @@ void iflib_led_create(if_ctx_t ctx); void iflib_add_int_delay_sysctl(if_ctx_t, const char *, const char *, if_int_delay_info_t, int, int); +/* + * Pseudo device support + */ +if_pseudo_t iflib_clone_register(if_shared_ctx_t); +void iflib_clone_deregister(if_pseudo_t); #endif /* __IFLIB_H_ */ diff --git a/freebsd/sys/net/pfvar.h b/freebsd/sys/net/pfvar.h index dfff0b87..824b8ec3 100644 --- a/freebsd/sys/net/pfvar.h +++ b/freebsd/sys/net/pfvar.h @@ -38,8 +38,11 @@ #include <sys/param.h> #include <sys/queue.h> #include <sys/counter.h> +#include <sys/cpuset.h> #include <sys/malloc.h> #include <sys/refcount.h> +#include <sys/lock.h> +#include <sys/rmlock.h> #include <sys/tree.h> #include <vm/uma.h> @@ -147,14 +150,15 @@ extern struct mtx pf_unlnkdrules_mtx; #define PF_UNLNKDRULES_LOCK() mtx_lock(&pf_unlnkdrules_mtx) #define PF_UNLNKDRULES_UNLOCK() mtx_unlock(&pf_unlnkdrules_mtx) -extern struct rwlock pf_rules_lock; -#define PF_RULES_RLOCK() rw_rlock(&pf_rules_lock) -#define PF_RULES_RUNLOCK() rw_runlock(&pf_rules_lock) -#define PF_RULES_WLOCK() rw_wlock(&pf_rules_lock) -#define PF_RULES_WUNLOCK() rw_wunlock(&pf_rules_lock) -#define PF_RULES_ASSERT() rw_assert(&pf_rules_lock, RA_LOCKED) -#define PF_RULES_RASSERT() rw_assert(&pf_rules_lock, RA_RLOCKED) -#define PF_RULES_WASSERT() rw_assert(&pf_rules_lock, RA_WLOCKED) +extern struct rmlock pf_rules_lock; +#define PF_RULES_RLOCK_TRACKER struct rm_priotracker _pf_rules_tracker +#define PF_RULES_RLOCK() rm_rlock(&pf_rules_lock, &_pf_rules_tracker) +#define PF_RULES_RUNLOCK() rm_runlock(&pf_rules_lock, &_pf_rules_tracker) +#define PF_RULES_WLOCK() rm_wlock(&pf_rules_lock) +#define PF_RULES_WUNLOCK() rm_wunlock(&pf_rules_lock) +#define PF_RULES_ASSERT() rm_assert(&pf_rules_lock, RA_LOCKED) +#define PF_RULES_RASSERT() rm_assert(&pf_rules_lock, RA_RLOCKED) +#define PF_RULES_WASSERT() rm_assert(&pf_rules_lock, RA_WLOCKED) extern struct sx pf_end_lock; @@ -1638,6 +1642,7 @@ void pfr_detach_table(struct pfr_ktable *); int pfr_clr_tables(struct pfr_table *, int *, int); int pfr_add_tables(struct pfr_table *, int, int *, int); int pfr_del_tables(struct pfr_table *, int, int *, int); +int pfr_table_count(struct pfr_table *, int); int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int); int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int); int pfr_clr_tstats(struct pfr_table *, int, int *, int); diff --git a/freebsd/sys/net/route.c b/freebsd/sys/net/route.c index ade738a2..c2348e31 100644 --- a/freebsd/sys/net/route.c +++ b/freebsd/sys/net/route.c @@ -238,7 +238,7 @@ route_init(void) if (rt_numfibs == 0) rt_numfibs = 1; } -SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0); +SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, NULL); static int rtentry_zinit(void *mem, int size, int how) @@ -626,12 +626,12 @@ rtredirect_fib(struct sockaddr *dst, struct rib_head *rnh; ifa = NULL; + NET_EPOCH_ENTER(); rnh = rt_tables_get_rnh(fibnum, dst->sa_family); if (rnh == NULL) { error = EAFNOSUPPORT; goto out; } - /* verify the gateway is directly reachable */ if ((ifa = ifa_ifwithnet(gateway, 0, fibnum)) == NULL) { error = ENETUNREACH; @@ -685,6 +685,7 @@ rtredirect_fib(struct sockaddr *dst, info.rti_info[RTAX_DST] = dst; info.rti_info[RTAX_GATEWAY] = gateway; info.rti_info[RTAX_NETMASK] = netmask; + ifa_ref(ifa); info.rti_ifa = ifa; info.rti_flags = flags; error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum); @@ -719,7 +720,8 @@ rtredirect_fib(struct sockaddr *dst, done: if (rt) RTFREE_LOCKED(rt); -out: + out: + NET_EPOCH_EXIT(); if (error) V_rtstat.rts_badredirect++; else if (stat != NULL) @@ -730,8 +732,6 @@ out: info.rti_info[RTAX_NETMASK] = netmask; info.rti_info[RTAX_AUTHOR] = src; rt_missmsg_fib(RTM_REDIRECT, &info, flags, error, fibnum); - if (ifa != NULL) - ifa_free(ifa); } /* @@ -762,6 +762,7 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway, struct ifaddr *ifa; int not_found = 0; + MPASS(in_epoch()); if ((flags & RTF_GATEWAY) == 0) { /* * If we are adding a route to an interface, @@ -790,7 +791,7 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway, rt = rtalloc1_fib(gateway, 0, flags, fibnum); if (rt == NULL) - return (NULL); + goto out; /* * dismiss a gateway that is reachable only * through the default router @@ -809,21 +810,19 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway, } if (!not_found && rt->rt_ifa != NULL) { ifa = rt->rt_ifa; - ifa_ref(ifa); } RT_REMREF(rt); RT_UNLOCK(rt); if (not_found || ifa == NULL) - return (NULL); + goto out; } if (ifa->ifa_addr->sa_family != dst->sa_family) { struct ifaddr *oifa = ifa; ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); if (ifa == NULL) ifa = oifa; - else - ifa_free(oifa); } + out: return (ifa); } @@ -933,7 +932,7 @@ rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, int flags) info->rti_flags = rt->rt_flags; info->rti_ifp = rt->rt_ifp; info->rti_ifa = rt->rt_ifa; - + ifa_ref(info->rti_ifa); if (flags & NHR_REF) { /* Do 'traditional' refcouting */ if_ref(info->rti_ifp); @@ -1309,17 +1308,19 @@ int rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum) { struct ifaddr *ifa; - int error = 0; + int needref, error; /* * ifp may be specified by sockaddr_dl * when protocol address is ambiguous. */ + error = 0; + needref = (info->rti_ifa == NULL); + NET_EPOCH_ENTER(); if (info->rti_ifp == NULL && ifpaddr != NULL && ifpaddr->sa_family == AF_LINK && (ifa = ifa_ifwithnet(ifpaddr, 0, fibnum)) != NULL) { info->rti_ifp = ifa->ifa_ifp; - ifa_free(ifa); } if (info->rti_ifa == NULL && ifaaddr != NULL) info->rti_ifa = ifa_ifwithaddr(ifaaddr); @@ -1337,11 +1338,13 @@ rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum) info->rti_ifa = ifa_ifwithroute(flags, sa, sa, fibnum); } - if ((ifa = info->rti_ifa) != NULL) { + if (needref && info->rti_ifa != NULL) { if (info->rti_ifp == NULL) - info->rti_ifp = ifa->ifa_ifp; + info->rti_ifp = info->rti_ifa->ifa_ifp; + ifa_ref(info->rti_ifa); } else error = ENETUNREACH; + NET_EPOCH_EXIT(); return (error); } @@ -1618,12 +1621,9 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, error = rt_getifa_fib(info, fibnum); if (error) return (error); - } else - ifa_ref(info->rti_ifa); - ifa = info->rti_ifa; + } rt = uma_zalloc(V_rtzone, M_NOWAIT); if (rt == NULL) { - ifa_free(ifa); return (ENOBUFS); } rt->rt_flags = RTF_UP | flags; @@ -1632,7 +1632,6 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, * Add the gateway. Possibly re-malloc-ing the storage for it. */ if ((error = rt_setgate(rt, dst, gateway)) != 0) { - ifa_free(ifa); uma_zfree(V_rtzone, rt); return (error); } @@ -1655,6 +1654,8 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, * This moved from below so that rnh->rnh_addaddr() can * examine the ifa and ifa->ifa_ifp if it so desires. */ + ifa = info->rti_ifa; + ifa_ref(ifa); rt->rt_ifa = ifa; rt->rt_ifp = ifa->ifa_ifp; rt->rt_weight = 1; @@ -1819,6 +1820,7 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info, if (rt->rt_ifa->ifa_rtrequest != NULL) rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, info); ifa_free(rt->rt_ifa); + rt->rt_ifa = NULL; } /* Update gateway address */ if (info->rti_info[RTAX_GATEWAY] != NULL) { @@ -1870,8 +1872,10 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info, } bad: RT_UNLOCK(rt); - if (free_ifa != 0) + if (free_ifa != 0) { ifa_free(info->rti_ifa); + info->rti_ifa = NULL; + } return (error); } @@ -2090,6 +2094,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum) * Do the actual request */ bzero((caddr_t)&info, sizeof(info)); + ifa_ref(ifa); info.rti_ifa = ifa; info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED; diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c index 900413a0..c0c5c5c2 100644 --- a/freebsd/sys/net/rtsock.c +++ b/freebsd/sys/net/rtsock.c @@ -33,7 +33,6 @@ * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 * $FreeBSD$ */ -#include <rtems/bsd/local/opt_compat.h> #include <rtems/bsd/local/opt_mpath.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> @@ -467,7 +466,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, * that belongs to the jail. */ IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { struct sockaddr *sa; sa = ifa->ifa_addr; if (sa->sa_family != AF_INET) @@ -509,7 +508,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, * that belongs to the jail. */ IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { struct sockaddr *sa; sa = ifa->ifa_addr; if (sa->sa_family != AF_INET6) @@ -797,12 +796,14 @@ route_output(struct mbuf *m, struct socket *so, ...) rt->rt_ifp->if_type == IFT_PROPVIRTUAL) { struct ifaddr *ifa; + NET_EPOCH_ENTER(); ifa = ifa_ifwithnet(info.rti_info[RTAX_DST], 1, RT_ALL_FIBS); if (ifa != NULL) rt_maskedcopy(ifa->ifa_addr, &laddr, ifa->ifa_netmask); + NET_EPOCH_EXIT(); } else rt_maskedcopy(rt->rt_ifa->ifa_addr, &laddr, @@ -1424,7 +1425,10 @@ rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma) bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_IFA] = ifma->ifma_addr; - info.rti_info[RTAX_IFP] = ifp ? ifp->if_addr->ifa_addr : NULL; + if (ifp && ifp->if_addr) + info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr; + else + info.rti_info[RTAX_IFP] = NULL; /* * If a link-layer address is present, present it as a ``gateway'' * (similarly to how ARP entries, e.g., are presented). @@ -1746,7 +1750,7 @@ sysctl_iflist(int af, struct walkarg *w) bzero((caddr_t)&info, sizeof(info)); bzero(&ifd, sizeof(ifd)); IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; if_data_copy(ifp, &ifd); @@ -1767,7 +1771,7 @@ sysctl_iflist(int af, struct walkarg *w) if (error) goto done; } - while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) { + while ((ifa = CK_STAILQ_NEXT(ifa, ifa_link)) != NULL) { if (af && af != ifa->ifa_addr->sa_family) continue; if (prison_if(w->w_req->td->td_ucred, @@ -1816,13 +1820,13 @@ sysctl_ifmalist(int af, struct walkarg *w) bzero((caddr_t)&info, sizeof(info)); IFNET_RLOCK_NOSLEEP(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; ifa = ifp->if_addr; info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL; IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (af && af != ifma->ifma_addr->sa_family) continue; if (prison_if(w->w_req->td->td_ucred, |