Download raw body.
veb(4): "lock" mac addresses on ports
this adds a "locked" flags to ports in veb(4), which is modelled on the
"locked" keyword and the associated behaviour in vm.conf. it requires
the source mac address in frames received by a port have an address
entry on the veb(4) that points to that same port.
there's similar functionality in vmware vswitches (and probably other
hypervisors too) when you configure MAC address changes and forged
transmits to be rejected.
in practice this means you can configure static mac address entries on a
veb port, and then lock the port so only those mac addresses can come
from that same port.
it doesnt make sense to me to use this functionality on a port with
learning and discover (unicast flooding) enabled, so veb(4) requires
them to be configured exclusively.
so say i have a vm.conf like this:
vm test {
memory 1G
disk "/var/vmd/v.qcow2" format qcow2
interface tap0 {
locked lladdr fe:e1:ba:d2:3a:ae
# don't need switch config cos it's already added to veb0
}
}
i could remove locked from vm.conf and implement the equivalent policy
in veb(4) like below, with the addition of locking down the vport0 in
the same way:
$ doas cat /etc/hostname.tap0
up
$ doas cat /etc/hostname.vport0
lladdr 00:50:56:a1:73:91
inet 192.0.2.34 255.255.255.0
up
$ doas cat /etc/hostname.veb0
add aggr0
add tap0
-learn tap0
-discover tap0
locked tap0
static tap0 fe:e1:ba:d2:3a:ae
add vport0
-learn vport0
-discover vport0
locked vport0
static vport0 00:50:56:a1:73:91
up
$ ifconfig veb0
veb0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST>
index 11 llprio 3
groups: veb
aggr0 flags=3<LEARNING,DISCOVER>
port 1 ifpriority 0 ifcost 0
tap0 flags=2000<LOCKED>
port 12 ifpriority 0 ifcost 0
vport0 flags=2000<LOCKED>
port 13 ifpriority 0 ifcost 0
Addresses (max cache: 100, timeout: 240):
00:00:5e:00:01:11 aggr0 1 flags=0<>
00:00:5e:00:01:47 aggr0 1 flags=0<>
00:50:56:50:55:00 aggr0 21 flags=0<>
00:50:56:50:78:a0 aggr0 0 flags=0<>
00:50:56:52:51:21 aggr0 59 flags=0<>
00:50:56:55:90:d9 aggr0 3 flags=0<>
00:50:56:55:e9:71 aggr0 48 flags=0<>
00:50:56:5b:e7:5a aggr0 24 flags=0<>
00:50:56:5f:60:23 aggr0 51 flags=0<>
00:50:56:5f:f4:fc aggr0 37 flags=0<>
00:50:56:a1:3d:14 aggr0 126 flags=0<>
00:50:56:a1:61:bc aggr0 243 flags=0<>
00:50:56:a1:73:91 vport0 0 flags=1<STATIC>
fe:e1:ba:d0:74:ef aggr0 2 flags=0<>
fe:e1:ba:d2:3a:ae tap0 0 flags=1<STATIC>
the implementation is surprisingly simple.
thoughts? ok?
Index: sys/net/if_bridge.h
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.h,v
diff -u -p -r1.73 if_bridge.h
--- sys/net/if_bridge.h 11 Nov 2021 10:03:10 -0000 1.73
+++ sys/net/if_bridge.h 16 Oct 2025 02:56:16 -0000
@@ -74,6 +74,7 @@ struct ifbreq {
#define IFBIF_BSTP_AUTOPTP 0x0080 /* member stp autoptp enabled */
#define IFBIF_SPAN 0x0100 /* ifs is a span port (ro) */
#define IFBIF_LOCAL 0x1000 /* local port in switch(4) */
+#define IFBIF_LOCKED 0x2000 /* restrict rx src mac with fib */
#define IFBIF_RO_MASK 0x0f00 /* read only bits */
/* SIOCBRDGFLUSH */
Index: sys/net/if_veb.c
===================================================================
RCS file: /cvs/src/sys/net/if_veb.c,v
diff -u -p -r1.44 if_veb.c
--- sys/net/if_veb.c 7 Oct 2025 07:52:46 -0000 1.44
+++ sys/net/if_veb.c 16 Oct 2025 02:56:16 -0000
@@ -64,7 +64,8 @@
#endif
/* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */
-#define VEB_IFBIF_FLAGS (IFBIF_LEARNING|IFBIF_DISCOVER|IFBIF_BLOCKNONIP)
+#define VEB_IFBIF_FLAGS \
+ (IFBIF_LOCKED|IFBIF_LEARNING|IFBIF_DISCOVER|IFBIF_BLOCKNONIP)
struct veb_rule {
TAILQ_ENTRY(veb_rule) vr_entry;
@@ -1176,6 +1107,17 @@ veb_port_input(struct ifnet *ifp0, struc
eh = mtod(m, struct ether_header *);
src = ether_addr_to_e64((struct ether_addr *)eh->ether_shost);
+ if (ISSET(p->p_bif_flags, IFBIF_LOCKED)) {
+ struct veb_port *rp;
+
+ smr_read_enter();
+ rp = etherbridge_resolve(&sc->sc_eb, src);
+ smr_read_leave();
+
+ if (rp != p)
+ goto drop;
+ }
+
/* Is this a MAC Bridge component Reserved address? */
if (ETH64_IS_8021_RSVD(dst)) {
if (!ISSET(ifp->if_flags, IFF_LINK0)) {
@@ -2089,6 +2031,9 @@ veb_port_set_flags(struct veb_softc *sc,
if (ISSET(ifbr->ifbr_ifsflags, ~VEB_IFBIF_FLAGS))
return (EINVAL);
+ if (ISSET(ifbr->ifbr_ifsflags, IFBIF_LOCKED) &&
+ ISSET(ifbr->ifbr_ifsflags, IFBIF_LEARNING|IFBIF_DISCOVER))
+ return (EINVAL);
p = veb_port_get(sc, ifbr->ifbr_ifsname);
if (p == NULL)
Index: sbin/ifconfig/brconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/brconfig.c,v
diff -u -p -r1.33 brconfig.c
--- sbin/ifconfig/brconfig.c 6 Jan 2025 17:49:29 -0000 1.33
+++ sbin/ifconfig/brconfig.c 16 Oct 2025 02:56:16 -0000
@@ -60,7 +60,7 @@ int bridge_arprule(struct ifbrlreq *, in
#define IFBAFBITS "\020\1STATIC"
#define IFBIFBITS \
-"\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4STP\5EDGE\6AUTOEDGE\7PTP\10AUTOPTP\11SPAN\15LOCAL"
+"\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4STP\5EDGE\6AUTOEDGE\7PTP\10AUTOPTP\11SPAN\15LOCAL\16LOCKED"
#define PV2ID(pv, epri, eaddr) do { \
epri = pv >> 48; \
@@ -128,6 +128,18 @@ void
unsetlearn(const char *val, int d)
{
bridge_ifclrflag(val, IFBIF_LEARNING);
+}
+
+void
+setlocked(const char *val, int d)
+{
+ bridge_ifsetflag(val, IFBIF_LOCKED);
+}
+
+void
+unsetlocked(const char *val, int d)
+{
+ bridge_ifclrflag(val, IFBIF_LOCKED);
}
void
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
diff -u -p -r1.476 ifconfig.c
--- sbin/ifconfig/ifconfig.c 22 Mar 2025 07:24:49 -0000 1.476
+++ sbin/ifconfig/ifconfig.c 16 Oct 2025 02:56:16 -0000
@@ -562,6 +562,8 @@ const struct cmd {
{ "-blocknonip",NEXTARG, 0, unsetblocknonip },
{ "learn", NEXTARG, 0, setlearn },
{ "-learn", NEXTARG, 0, unsetlearn },
+ { "locked", NEXTARG, 0, setlocked },
+ { "-locked", NEXTARG, 0, unsetlocked },
{ "stp", NEXTARG, 0, setstp },
{ "-stp", NEXTARG, 0, unsetstp },
{ "edge", NEXTARG, 0, setedge },
Index: sbin/ifconfig/ifconfig.h
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.h,v
diff -u -p -r1.6 ifconfig.h
--- sbin/ifconfig/ifconfig.h 6 Jan 2025 17:49:29 -0000 1.6
+++ sbin/ifconfig/ifconfig.h 16 Oct 2025 02:56:16 -0000
@@ -29,6 +29,8 @@ void setblocknonip(const char *, int);
void unsetblocknonip(const char *, int);
void setlearn(const char *, int);
void unsetlearn(const char *, int);
+void setlocked(const char *, int);
+void unsetlocked(const char *, int);
void setstp(const char *, int);
void unsetstp(const char *, int);
void setedge(const char *, int);
veb(4): "lock" mac addresses on ports