aboutsummaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/ethernet.h23
-rw-r--r--sys/net/if_bridge.c305
-rw-r--r--sys/net/if_bridgevar.h29
-rw-r--r--sys/net/if_ethersubr.c5
-rw-r--r--sys/net/if_gif.h3
-rw-r--r--sys/net/if_lagg.c1
-rw-r--r--sys/net/if_vlan.c1
-rw-r--r--sys/net/if_vlan_var.h7
-rw-r--r--sys/net/pfvar.h13
9 files changed, 355 insertions, 32 deletions
diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h
index 6eefedba8775..01485cf26e06 100644
--- a/sys/net/ethernet.h
+++ b/sys/net/ethernet.h
@@ -62,6 +62,8 @@ struct ether_header {
u_char ether_shost[ETHER_ADDR_LEN];
u_short ether_type;
} __packed;
+_Static_assert(sizeof(struct ether_header) == ETHER_HDR_LEN,
+ "size of struct ether_header is wrong");
/*
* Structure of a 48-bit Ethernet address.
@@ -69,6 +71,8 @@ struct ether_header {
struct ether_addr {
u_char octet[ETHER_ADDR_LEN];
} __packed;
+_Static_assert(sizeof(struct ether_addr) == ETHER_ADDR_LEN,
+ "size of struct ether_addr is wrong");
#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */
#define ETHER_IS_IPV6_MULTICAST(addr) \
@@ -81,6 +85,23 @@ struct ether_addr {
(addr)[3] | (addr)[4] | (addr)[5]) == 0x00)
/*
+ * 802.1q VID constants from IEEE 802.1Q-2014, table 9-2.
+ */
+
+/* Null VID: The tag contains only PCP (priority) and DEI information. */
+#define DOT1Q_VID_NULL 0x0
+/* The default PVID for a bridge port. NB: bridge(4) does not honor this. */
+#define DOT1Q_VID_DEF_PVID 0x1
+/* The default SR_PVID for SRP Stream related traffic. */
+#define DOT1Q_VID_DEF_SR_PVID 0x2
+/* A VID reserved for implementation use, not permitted on the wire. */
+#define DOT1Q_VID_RSVD_IMPL 0xfff
+/* The lowest valid VID. */
+#define DOT1Q_VID_MIN 0x1
+/* The highest valid VID. */
+#define DOT1Q_VID_MAX 0xffe
+
+/*
* This is the type of the VLAN ID inside the tag, not the tag itself.
*/
typedef uint16_t ether_vlanid_t;
@@ -95,6 +116,8 @@ struct ether_vlan_header {
uint16_t evl_tag;
uint16_t evl_proto;
} __packed;
+_Static_assert(sizeof(struct ether_vlan_header) == ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN,
+ "size of struct ether_vlan_header is wrong");
#define EVL_VLID_MASK 0x0FFF
#define EVL_PRI_MASK 0xE000
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index bc421a8e156d..5b3ee740d75e 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -254,6 +254,8 @@ struct bridge_iflist {
uint32_t bif_addrcnt; /* cur. # of addresses */
uint32_t bif_addrexceeded;/* # of address violations */
struct epoch_context bif_epoch_ctx;
+ ether_vlanid_t bif_untagged; /* untagged vlan id */
+ ifbvlan_set_t bif_vlan_set; /* allowed tagged vlans */
};
/*
@@ -331,13 +333,12 @@ static void bridge_inject(struct ifnet *, struct mbuf *);
static int bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
static int bridge_enqueue(struct bridge_softc *, struct ifnet *,
- struct mbuf *);
+ struct mbuf *, struct bridge_iflist *);
static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp, int);
static void bridge_forward(struct bridge_softc *, struct bridge_iflist *,
struct mbuf *m);
static bool bridge_member_ifaddrs(void);
-
static void bridge_timer(void *);
static void bridge_broadcast(struct bridge_softc *, struct ifnet *,
@@ -353,6 +354,9 @@ static void bridge_rtage(struct bridge_softc *);
static void bridge_rtflush(struct bridge_softc *, int);
static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *,
ether_vlanid_t);
+static bool bridge_vfilter_in(const struct bridge_iflist *, struct mbuf *);
+static bool bridge_vfilter_out(const struct bridge_iflist *,
+ const struct mbuf *);
static void bridge_rtable_init(struct bridge_softc *);
static void bridge_rtable_fini(struct bridge_softc *);
@@ -400,6 +404,9 @@ static int bridge_ioctl_sma(struct bridge_softc *, void *);
static int bridge_ioctl_sifprio(struct bridge_softc *, void *);
static int bridge_ioctl_sifcost(struct bridge_softc *, void *);
static int bridge_ioctl_sifmaxaddr(struct bridge_softc *, void *);
+static int bridge_ioctl_sifuntagged(struct bridge_softc *, void *);
+static int bridge_ioctl_sifvlanset(struct bridge_softc *, void *);
+static int bridge_ioctl_gifvlanset(struct bridge_softc *, void *);
static int bridge_ioctl_addspan(struct bridge_softc *, void *);
static int bridge_ioctl_delspan(struct bridge_softc *, void *);
static int bridge_ioctl_gbparam(struct bridge_softc *, void *);
@@ -618,6 +625,14 @@ static const struct bridge_control bridge_control_table[] = {
{ bridge_ioctl_sifmaxaddr, sizeof(struct ifbreq),
BC_F_COPYIN|BC_F_SUSER },
+ { bridge_ioctl_sifuntagged, sizeof(struct ifbreq),
+ BC_F_COPYIN|BC_F_SUSER },
+
+ { bridge_ioctl_sifvlanset, sizeof(struct ifbif_vlan_req),
+ BC_F_COPYIN|BC_F_SUSER },
+
+ { bridge_ioctl_gifvlanset, sizeof(struct ifbif_vlan_req),
+ BC_F_COPYIN|BC_F_COPYOUT },
};
static const int bridge_control_table_size = nitems(bridge_control_table);
@@ -832,6 +847,7 @@ bridge_clone_create(struct if_clone *ifc, char *name, size_t len,
ifp->if_softc = sc;
if_initname(ifp, bridge_name, ifd->unit);
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_capabilities = ifp->if_capenable = IFCAP_VLAN_HWTAGGING;
ifp->if_ioctl = bridge_ioctl;
#ifdef ALTQ
ifp->if_start = bridge_altq_start;
@@ -954,6 +970,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
struct ifbaconf ifbaconf;
struct ifbrparam ifbrparam;
struct ifbropreq ifbropreq;
+ struct ifbif_vlan_req ifvlanreq;
} args;
struct ifdrv *ifd = (struct ifdrv *) data;
const struct bridge_control *bc;
@@ -1495,6 +1512,7 @@ bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
req->ifbr_addrcnt = bif->bif_addrcnt;
req->ifbr_addrmax = bif->bif_addrmax;
req->ifbr_addrexceeded = bif->bif_addrexceeded;
+ req->ifbr_untagged = bif->bif_untagged;
/* Copy STP state options as flags */
if (bp->bp_operedge)
@@ -1873,6 +1891,84 @@ bridge_ioctl_sifmaxaddr(struct bridge_softc *sc, void *arg)
}
static int
+bridge_ioctl_sifuntagged(struct bridge_softc *sc, void *arg)
+{
+ struct ifbreq *req = arg;
+ struct bridge_iflist *bif;
+
+ bif = bridge_lookup_member(sc, req->ifbr_ifsname);
+ if (bif == NULL)
+ return (ENOENT);
+
+ if (req->ifbr_untagged > DOT1Q_VID_MAX)
+ return (EINVAL);
+
+ if (req->ifbr_untagged != DOT1Q_VID_NULL)
+ bif->bif_flags |= IFBIF_VLANFILTER;
+ bif->bif_untagged = req->ifbr_untagged;
+ return (0);
+}
+
+static int
+bridge_ioctl_sifvlanset(struct bridge_softc *sc, void *arg)
+{
+ struct ifbif_vlan_req *req = arg;
+ struct bridge_iflist *bif;
+
+ bif = bridge_lookup_member(sc, req->bv_ifname);
+ if (bif == NULL)
+ return (ENOENT);
+
+ /* Reject invalid VIDs. */
+ if (BRVLAN_TEST(&req->bv_set, DOT1Q_VID_NULL) ||
+ BRVLAN_TEST(&req->bv_set, DOT1Q_VID_RSVD_IMPL))
+ return (EINVAL);
+
+ switch (req->bv_op) {
+ /* Replace the existing vlan set with the new set */
+ case BRDG_VLAN_OP_SET:
+ BIT_COPY(BRVLAN_SETSIZE, &req->bv_set, &bif->bif_vlan_set);
+ break;
+
+ /* Modify the existing vlan set to add the given vlans */
+ case BRDG_VLAN_OP_ADD:
+ BIT_OR(BRVLAN_SETSIZE, &bif->bif_vlan_set, &req->bv_set);
+ break;
+
+ /* Modify the existing vlan set to remove the given vlans */
+ case BRDG_VLAN_OP_DEL:
+ BIT_ANDNOT(BRVLAN_SETSIZE, &bif->bif_vlan_set, &req->bv_set);
+ break;
+
+ /* Invalid or unknown operation */
+ default:
+ return (EINVAL);
+ }
+
+ /*
+ * The only reason to modify the VLAN access list is to use VLAN
+ * filtering on this interface, so enable it automatically.
+ */
+ bif->bif_flags |= IFBIF_VLANFILTER;
+
+ return (0);
+}
+
+static int
+bridge_ioctl_gifvlanset(struct bridge_softc *sc, void *arg)
+{
+ struct ifbif_vlan_req *req = arg;
+ struct bridge_iflist *bif;
+
+ bif = bridge_lookup_member(sc, req->bv_ifname);
+ if (bif == NULL)
+ return (ENOENT);
+
+ BIT_COPY(BRVLAN_SETSIZE, &bif->bif_vlan_set, &req->bv_set);
+ return (0);
+}
+
+static int
bridge_ioctl_addspan(struct bridge_softc *sc, void *arg)
{
struct ifbreq *req = arg;
@@ -2150,12 +2246,25 @@ bridge_stop(struct ifnet *ifp, int disable)
*
*/
static int
-bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
+bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m,
+ struct bridge_iflist *bif)
{
int len, err = 0;
short mflags;
struct mbuf *m0;
+ /*
+ * Find the bridge member port this packet is being sent on, if the
+ * caller didn't already provide it.
+ */
+ if (bif == NULL)
+ bif = bridge_lookup_member_if(sc, dst_ifp);
+ if (bif == NULL) {
+ /* Perhaps the interface was removed from the bridge */
+ m_freem(m);
+ return (EINVAL);
+ }
+
/* We may be sending a fragment so traverse the mbuf */
for (; m; m = m0) {
m0 = m->m_nextpkt;
@@ -2164,6 +2273,18 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
mflags = m->m_flags;
/*
+ * If VLAN filtering is enabled, and the native VLAN ID of the
+ * outgoing interface matches the VLAN ID of the frame, remove
+ * the VLAN header.
+ */
+ if ((bif->bif_flags & IFBIF_VLANFILTER) &&
+ bif->bif_untagged != DOT1Q_VID_NULL &&
+ VLANTAGOF(m) == bif->bif_untagged) {
+ m->m_flags &= ~M_VLANTAG;
+ m->m_pkthdr.ether_vtag = 0;
+ }
+
+ /*
* If underlying interface can not do VLAN tag insertion itself
* then attach a packet tag that holds it.
*/
@@ -2234,7 +2355,7 @@ bridge_dummynet(struct mbuf *m, struct ifnet *ifp)
return;
}
- bridge_enqueue(sc, ifp, m);
+ bridge_enqueue(sc, ifp, m, NULL);
}
/*
@@ -2329,7 +2450,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
}
}
- bridge_enqueue(sc, dst_if, mc);
+ bridge_enqueue(sc, dst_if, mc, bif);
}
if (used == 0)
m_freem(m);
@@ -2347,7 +2468,7 @@ sendunicast:
return (0);
}
- bridge_enqueue(sc, dst_if, m);
+ bridge_enqueue(sc, dst_if, m, NULL);
return (0);
}
@@ -2364,17 +2485,18 @@ bridge_transmit(struct ifnet *ifp, struct mbuf *m)
struct ether_header *eh;
struct ifnet *dst_if;
int error = 0;
+ ether_vlanid_t vlan;
sc = ifp->if_softc;
ETHER_BPF_MTAP(ifp, m);
eh = mtod(m, struct ether_header *);
+ vlan = VLANTAGOF(m);
if (((m->m_flags & (M_BCAST|M_MCAST)) == 0) &&
- (dst_if = bridge_rtlookup(sc, eh->ether_dhost, DOT1Q_VID_NULL)) !=
- NULL) {
- error = bridge_enqueue(sc, dst_if, m);
+ (dst_if = bridge_rtlookup(sc, eh->ether_dhost, vlan)) != NULL) {
+ error = bridge_enqueue(sc, dst_if, m, NULL);
} else
bridge_broadcast(sc, ifp, m, 0);
@@ -2435,18 +2557,18 @@ bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
struct bridge_iflist *dbif;
struct ifnet *src_if, *dst_if, *ifp;
struct ether_header *eh;
- uint16_t vlan;
uint8_t *dst;
int error;
+ ether_vlanid_t vlan;
NET_EPOCH_ASSERT();
src_if = m->m_pkthdr.rcvif;
ifp = sc->sc_ifp;
+ vlan = VLANTAGOF(m);
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
- vlan = VLANTAGOF(m);
if ((sbif->bif_flags & IFBIF_STP) &&
sbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
@@ -2555,6 +2677,10 @@ bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
if (sbif->bif_flags & dbif->bif_flags & IFBIF_PRIVATE)
goto drop;
+ /* Do VLAN filtering. */
+ if (!bridge_vfilter_out(dbif, m))
+ goto drop;
+
if ((dbif->bif_flags & IFBIF_STP) &&
dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
goto drop;
@@ -2566,7 +2692,7 @@ bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
return;
}
- bridge_enqueue(sc, dst_if, m);
+ bridge_enqueue(sc, dst_if, m, dbif);
return;
drop:
@@ -2636,6 +2762,15 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
return (NULL);
}
+ /* Do VLAN filtering. */
+ if (!bridge_vfilter_in(bif, m)) {
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
+ m_freem(m);
+ return (NULL);
+ }
+ /* bridge_vfilter_in() may add a tag */
+ vlan = VLANTAGOF(m);
+
bridge_span(sc, m);
if (m->m_flags & (M_BCAST|M_MCAST)) {
@@ -2761,6 +2896,15 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
} \
if ((iface) != bifp) \
ETHER_BPF_MTAP(iface, m); \
+ /* Pass tagged packets to if_vlan, if it's loaded */ \
+ if (VLANTAGOF(m) != 0) { \
+ if (bifp->if_vlantrunk == NULL) { \
+ m_freem(m); \
+ return (NULL); \
+ } \
+ (*vlan_input_p)(bifp, m); \
+ return (NULL); \
+ } \
return (m); \
} \
\
@@ -2817,6 +2961,30 @@ bridge_inject(struct ifnet *ifp, struct mbuf *m)
{
struct bridge_softc *sc;
+ if (ifp->if_type == IFT_L2VLAN) {
+ /*
+ * vlan(4) gives us the vlan ifnet, so we need to get the
+ * bridge softc to get a pointer to ether_input to send the
+ * packet to.
+ */
+ struct ifnet *bifp = NULL;
+
+ if (vlan_trunkdev_p == NULL) {
+ m_freem(m);
+ return;
+ }
+
+ bifp = vlan_trunkdev_p(ifp);
+ if (bifp == NULL) {
+ m_freem(m);
+ return;
+ }
+
+ sc = if_getsoftc(bifp);
+ sc->sc_if_input(ifp, m);
+ return;
+ }
+
KASSERT((if_getcapenable(ifp) & IFCAP_NETMAP) != 0,
("%s: iface %s is not running in netmap mode",
__func__, if_name(ifp)));
@@ -2867,6 +3035,10 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
if (sbif && (sbif->bif_flags & dbif->bif_flags & IFBIF_PRIVATE))
continue;
+ /* Do VLAN filtering. */
+ if (!bridge_vfilter_out(dbif, m))
+ continue;
+
if ((dbif->bif_flags & IFBIF_STP) &&
dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
continue;
@@ -2910,7 +3082,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
continue;
}
- bridge_enqueue(sc, dst_if, mc);
+ bridge_enqueue(sc, dst_if, mc, dbif);
}
if (used == 0)
m_freem(m);
@@ -2946,11 +3118,116 @@ bridge_span(struct bridge_softc *sc, struct mbuf *m)
continue;
}
- bridge_enqueue(sc, dst_if, mc);
+ bridge_enqueue(sc, dst_if, mc, bif);
}
}
/*
+ * Incoming VLAN filtering. Given a frame and the member interface it was
+ * received on, decide whether the port configuration allows it.
+ */
+static bool
+bridge_vfilter_in(const struct bridge_iflist *sbif, struct mbuf *m)
+{
+ ether_vlanid_t vlan;
+
+ vlan = VLANTAGOF(m);
+ /* Make sure the vlan id is reasonable. */
+ if (vlan > DOT1Q_VID_MAX)
+ return (false);
+
+ /* If VLAN filtering isn't enabled, pass everything. */
+ if ((sbif->bif_flags & IFBIF_VLANFILTER) == 0)
+ return (true);
+
+ if (vlan == DOT1Q_VID_NULL) {
+ /*
+ * The frame doesn't have a tag. If the interface does not
+ * have an untagged vlan configured, drop the frame.
+ */
+ if (sbif->bif_untagged == DOT1Q_VID_NULL)
+ return (false);
+
+ /*
+ * Otherwise, insert a new tag based on the interface's
+ * untagged vlan id.
+ */
+ m->m_pkthdr.ether_vtag = sbif->bif_untagged;
+ m->m_flags |= M_VLANTAG;
+ } else {
+ /*
+ * The frame has a tag, so check it matches the interface's
+ * vlan access list. We explicitly do not accept tagged
+ * frames for the untagged vlan id here (unless it's also
+ * in the access list).
+ */
+ if (!BRVLAN_TEST(&sbif->bif_vlan_set, vlan))
+ return (false);
+ }
+
+ /* Accept the frame. */
+ return (true);
+}
+
+/*
+ * Outgoing VLAN filtering. Given a frame, its vlan, and the member interface
+ * we intend to send it to, decide whether the port configuration allows it to
+ * be sent.
+ */
+static bool
+bridge_vfilter_out(const struct bridge_iflist *dbif, const struct mbuf *m)
+{
+ struct ether_header *eh;
+ ether_vlanid_t vlan;
+
+ NET_EPOCH_ASSERT();
+
+ /* If VLAN filtering isn't enabled, pass everything. */
+ if ((dbif->bif_flags & IFBIF_VLANFILTER) == 0)
+ return (true);
+
+ vlan = VLANTAGOF(m);
+
+ /*
+ * Always allow untagged 802.1D STP frames, even if they would
+ * otherwise be dropped. This is required for STP to work on
+ * a filtering bridge.
+ *
+ * Tagged STP (Cisco PVST+) is a non-standard extension, so
+ * handle those frames via the normal filtering path.
+ */
+ eh = mtod(m, struct ether_header *);
+ if (vlan == DOT1Q_VID_NULL &&
+ memcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0)
+ return (true);
+
+ /*
+ * If the frame wasn't assigned to a vlan at ingress, drop it.
+ * We can't forward these frames to filtering ports because we
+ * don't know what VLAN they're supposed to be in.
+ */
+ if (vlan == DOT1Q_VID_NULL)
+ return (false);
+
+ /*
+ * If the frame's vlan matches the interfaces's untagged vlan,
+ * allow it.
+ */
+ if (vlan == dbif->bif_untagged)
+ return (true);
+
+ /*
+ * If the frame's vlan is on the interface's tagged access list,
+ * allow it.
+ */
+ if (BRVLAN_TEST(&dbif->bif_vlan_set, vlan))
+ return (true);
+
+ /* The frame was not permitted, so drop it. */
+ return (false);
+}
+
+/*
* bridge_rtupdate:
*
* Add a bridge routing entry.
diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h
index 90beb6c96d82..97b63e3d4416 100644
--- a/sys/net/if_bridgevar.h
+++ b/sys/net/if_bridgevar.h
@@ -78,6 +78,8 @@
#define _NET_IF_BRIDGEVAR_H_
#include <sys/types.h>
+#include <sys/_bitset.h>
+#include <sys/bitset.h>
#include <sys/callout.h>
#include <sys/queue.h>
#include <sys/condvar.h>
@@ -122,6 +124,9 @@
#define BRDGSPROTO 28 /* set protocol (ifbrparam) */
#define BRDGSTXHC 29 /* set tx hold count (ifbrparam) */
#define BRDGSIFAMAX 30 /* set max interface addrs (ifbreq) */
+#define BRDGSIFUNTAGGED 31 /* set if untagged vlan */
+#define BRDGSIFVLANSET 32 /* set if vlan set */
+#define BRDGGIFVLANSET 33 /* get if vlan set */
/*
* Generic bridge control request.
@@ -139,6 +144,7 @@ struct ifbreq {
uint32_t ifbr_addrcnt; /* member if addr number */
uint32_t ifbr_addrmax; /* member if addr max */
uint32_t ifbr_addrexceeded; /* member if addr violations */
+ ether_vlanid_t ifbr_untagged; /* member if untagged vlan */
uint8_t pad[32];
};
@@ -155,10 +161,11 @@ struct ifbreq {
#define IFBIF_BSTP_ADMEDGE 0x0200 /* member stp admin edge enabled */
#define IFBIF_BSTP_ADMCOST 0x0400 /* member stp admin path cost */
#define IFBIF_PRIVATE 0x0800 /* if is a private segment */
+#define IFBIF_VLANFILTER 0x1000 /* if does vlan filtering */
#define IFBIFBITS "\020\001LEARNING\002DISCOVER\003STP\004SPAN" \
"\005STICKY\014PRIVATE\006EDGE\007AUTOEDGE\010PTP" \
- "\011AUTOPTP"
+ "\011AUTOPTP\015VLANFILTER"
#define IFBIFMASK ~(IFBIF_BSTP_EDGE|IFBIF_BSTP_AUTOEDGE|IFBIF_BSTP_PTP| \
IFBIF_BSTP_AUTOPTP|IFBIF_BSTP_ADMEDGE| \
IFBIF_BSTP_ADMCOST) /* not saved */
@@ -304,6 +311,26 @@ struct ifbpstpconf {
eaddr[5] = pv >> 0; \
} while (0)
+/*
+ * Bridge VLAN access request.
+ */
+#define BRVLAN_SETSIZE 4096
+typedef __BITSET_DEFINE(ifbvlan_set, BRVLAN_SETSIZE) ifbvlan_set_t;
+
+#define BRVLAN_SET(set, bit) __BIT_SET(BRVLAN_SETSIZE, (bit), set)
+#define BRVLAN_CLR(set, bit) __BIT_CLR(BRVLAN_SETSIZE, (bit), set)
+#define BRVLAN_TEST(set, bit) __BIT_ISSET(BRVLAN_SETSIZE, (bit), set)
+
+#define BRDG_VLAN_OP_SET 1 /* replace current vlan set */
+#define BRDG_VLAN_OP_ADD 2 /* add vlans to current set */
+#define BRDG_VLAN_OP_DEL 3 /* remove vlans from current set */
+
+struct ifbif_vlan_req {
+ char bv_ifname[IFNAMSIZ];
+ uint8_t bv_op;
+ ifbvlan_set_t bv_set;
+};
+
#ifdef _KERNEL
#define BRIDGE_INPUT(_ifp, _m) do { \
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 7be4dfac23e7..3ae0c01c0efc 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -92,11 +92,6 @@
#include <crypto/sha1.h>
-#ifdef CTASSERT
-CTASSERT(sizeof (struct ether_header) == ETHER_ADDR_LEN * 2 + 2);
-CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN);
-#endif
-
VNET_DEFINE(pfil_head_t, link_pfil_head); /* Packet filter hooks */
/* netgraph node hooks for ng_ether(4) */
diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h
index 3c1846b8f82a..c6692d3dd6bc 100644
--- a/sys/net/if_gif.h
+++ b/sys/net/if_gif.h
@@ -120,7 +120,8 @@ int in6_gif_setopts(struct gif_softc *, u_int);
#define GIFGOPTS _IOWR('i', 150, struct ifreq)
#define GIFSOPTS _IOW('i', 151, struct ifreq)
+#define GIF_NOCLAMP 0x0001
#define GIF_IGNORE_SOURCE 0x0002
-#define GIF_OPTMASK (GIF_IGNORE_SOURCE)
+#define GIF_OPTMASK (GIF_NOCLAMP|GIF_IGNORE_SOURCE)
#endif /* _NET_IF_GIF_H_ */
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 9867a718e148..5b52bfa80e3b 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -718,6 +718,7 @@ lagg_capabilities(struct lagg_softc *sc)
sc->sc_ifp->if_capenable = ena;
sc->sc_ifp->if_capenable2 = ena2;
sc->sc_ifp->if_hwassist = hwa;
+ (void)if_hw_tsomax_update(sc->sc_ifp, &hw_tsomax);
getmicrotime(&sc->sc_ifp->if_lastchange);
if (sc->sc_ifflags & IFF_DEBUG)
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index e9e1c82cb688..22fcb7bf7c64 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -1673,6 +1673,7 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid,
*/
if (p->if_type != IFT_ETHER &&
p->if_type != IFT_L2VLAN &&
+ p->if_type != IFT_BRIDGE &&
(p->if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
return (EPROTONOSUPPORT);
if ((p->if_flags & VLAN_IFFLAGS) != VLAN_IFFLAGS)
diff --git a/sys/net/if_vlan_var.h b/sys/net/if_vlan_var.h
index f0b09445d04b..695bb81f77b3 100644
--- a/sys/net/if_vlan_var.h
+++ b/sys/net/if_vlan_var.h
@@ -126,13 +126,6 @@ struct vlanreq {
#define VLAN_PCP_MAX 7
-#define DOT1Q_VID_NULL 0x0
-#define DOT1Q_VID_DEF_PVID 0x1
-#define DOT1Q_VID_DEF_SR_PVID 0x2
-#define DOT1Q_VID_RSVD_IMPL 0xfff
-#define DOT1Q_VID_MIN 1 /* minimum valid vlan id */
-#define DOT1Q_VID_MAX 4094 /* maximum valid vlan id */
-
/*
* 802.1q full tag. Proto and vid are stored in host byte order.
*/
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 1416f0c2cdbe..452a8eb4024b 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -551,6 +551,9 @@ extern struct sx pf_end_lock;
#endif /* PF_INET_INET6 */
#ifdef _KERNEL
+
+void unhandled_af(int) __dead2;
+
static void inline
pf_addrcpy(struct pf_addr *dst, const struct pf_addr *src, sa_family_t af)
{
@@ -565,6 +568,8 @@ pf_addrcpy(struct pf_addr *dst, const struct pf_addr *src, sa_family_t af)
memcpy(&dst->v6, &src->v6, sizeof(dst->v6));
break;
#endif /* INET6 */
+ default:
+ unhandled_af(af);
}
}
#endif
@@ -1365,7 +1370,6 @@ struct pf_kruleset {
struct pf_krulequeue queues[2];
struct {
struct pf_krulequeue *ptr;
- struct pf_krule **ptr_array;
u_int32_t rcount;
u_int32_t ticket;
int open;
@@ -2300,7 +2304,6 @@ VNET_DECLARE(struct pf_krule *, pf_rulemarker);
#define V_pf_rulemarker VNET(pf_rulemarker)
#endif
-void unhandled_af(int) __dead2;
int pf_start(void);
int pf_stop(void);
void pf_initialize(void);
@@ -2496,7 +2499,7 @@ int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
u_int64_t, int, int, int);
int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t,
- pf_addr_filter_func_t);
+ pf_addr_filter_func_t, bool);
void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
struct pfr_ktable *
pfr_attach_table(struct pf_kruleset *, char *);
@@ -2530,6 +2533,8 @@ int pfr_ina_rollback(struct pfr_table *, u_int32_t, int *, int);
int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int);
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
int *, u_int32_t, int);
+struct pfr_ktable
+ *pfr_ktable_select_active(struct pfr_ktable *);
MALLOC_DECLARE(PFI_MTYPE);
VNET_DECLARE(struct pfi_kkif *, pfi_all);
@@ -2670,6 +2675,7 @@ int pf_ioctl_get_addrs(struct pf_nl_pooladdr *);
int pf_ioctl_get_addr(struct pf_nl_pooladdr *);
int pf_ioctl_get_rulesets(struct pfioc_ruleset *);
int pf_ioctl_get_ruleset(struct pfioc_ruleset *);
+int pf_ioctl_natlook(struct pfioc_natlook *);
void pf_krule_free(struct pf_krule *);
void pf_krule_clear_counters(struct pf_krule *);
@@ -2707,7 +2713,6 @@ u_short pf_map_addr(u_int8_t, struct pf_krule *,
u_short pf_map_addr_sn(u_int8_t, struct pf_krule *,
struct pf_addr *, struct pf_addr *,
struct pfi_kkif **nkif, struct pf_addr *,
- struct pf_ksrc_node **, struct pf_srchash **,
struct pf_kpool *, pf_sn_types_t);
int pf_get_transaddr_af(struct pf_krule *,
struct pf_pdesc *);