summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-21 13:47:02 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:41 +0200
commitbcdce02d9bc8150e1d191ed5ca9da45b7604964a (patch)
tree3b2faf509db7672ee1fc98857736470be97e7ed8 /freebsd/sys/net
parentUpdate to FreeBSD head 2018-04-01 (diff)
downloadrtems-libbsd-bcdce02d9bc8150e1d191ed5ca9da45b7604964a.tar.bz2
Update to FreeBSD head 2018-06-01
Git mirror commit fb63610a69b0eb7f69a201ba05c4c1a7a2739cf9. Update #3472.
Diffstat (limited to 'freebsd/sys/net')
-rw-r--r--freebsd/sys/net/altq/altq_subr.c4
-rw-r--r--freebsd/sys/net/bpf.c18
-rw-r--r--freebsd/sys/net/bpfdesc.h3
-rw-r--r--freebsd/sys/net/bridgestp.c2
-rw-r--r--freebsd/sys/net/dlt.h92
-rw-r--r--freebsd/sys/net/fddi.h107
-rw-r--r--freebsd/sys/net/if.c755
-rw-r--r--freebsd/sys/net/if_arc.h145
-rw-r--r--freebsd/sys/net/if_arcsubr.c833
-rw-r--r--freebsd/sys/net/if_arp.h1
-rw-r--r--freebsd/sys/net/if_bridge.c17
-rw-r--r--freebsd/sys/net/if_bridgevar.h13
-rw-r--r--freebsd/sys/net/if_clone.c38
-rw-r--r--freebsd/sys/net/if_clone.h5
-rw-r--r--freebsd/sys/net/if_epair.c38
-rw-r--r--freebsd/sys/net/if_ethersubr.c12
-rw-r--r--freebsd/sys/net/if_fddisubr.c669
-rw-r--r--freebsd/sys/net/if_ipsec.c2
-rw-r--r--freebsd/sys/net/if_lagg.c246
-rw-r--r--freebsd/sys/net/if_lagg.h28
-rw-r--r--freebsd/sys/net/if_llatbl.c28
-rw-r--r--freebsd/sys/net/if_llatbl.h9
-rw-r--r--freebsd/sys/net/if_loop.c4
-rw-r--r--freebsd/sys/net/if_media.c22
-rw-r--r--freebsd/sys/net/if_media.h90
-rw-r--r--freebsd/sys/net/if_spppsubr.c8
-rw-r--r--freebsd/sys/net/if_stf.c6
-rw-r--r--freebsd/sys/net/if_tap.c4
-rw-r--r--freebsd/sys/net/if_tun.c4
-rw-r--r--freebsd/sys/net/if_var.h113
-rw-r--r--freebsd/sys/net/if_vlan.c4
-rw-r--r--freebsd/sys/net/iflib.h62
-rw-r--r--freebsd/sys/net/pfvar.h21
-rw-r--r--freebsd/sys/net/route.c47
-rw-r--r--freebsd/sys/net/rtsock.c20
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,