Index: if_bpe.c =================================================================== RCS file: /cvs/src/sys/net/if_bpe.c,v retrieving revision 1.18 diff -u -p -r1.18 if_bpe.c --- if_bpe.c 26 Feb 2021 01:28:51 -0000 1.18 +++ if_bpe.c 5 Mar 2021 10:34:12 -0000 @@ -710,7 +710,7 @@ bpe_add_addr(struct bpe_softc *sc, const static int bpe_del_addr(struct bpe_softc *sc, const struct ifbareq *ifba) { - return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst)); + return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst, 0)); } static inline struct bpe_softc * Index: if_etherbridge.c =================================================================== RCS file: /cvs/src/sys/net/if_etherbridge.c,v retrieving revision 1.5 diff -u -p -r1.5 if_etherbridge.c --- if_etherbridge.c 26 Feb 2021 08:31:23 -0000 1.5 +++ if_etherbridge.c 5 Mar 2021 10:34:12 -0000 @@ -449,7 +449,8 @@ etherbridge_add_addr(struct etherbridge return (error); } int -etherbridge_del_addr(struct etherbridge *eb, const struct ether_addr *ea) +etherbridge_del_addr(struct etherbridge *eb, const struct ether_addr *ea, + int vport) { uint64_t eba = ether_addr_to_e64(ea); struct eb_list *ebl; @@ -465,6 +466,8 @@ etherbridge_del_addr(struct etherbridge oebe = ebt_find(eb, &key); if (oebe == NULL) error = ESRCH; + else if (oebe->ebe_type == EBE_VPORT && !vport) + error = EOPNOTSUPP; else { KASSERT(eb->eb_num > 0); eb->eb_num--; @@ -572,6 +575,8 @@ etherbridge_flush(struct etherbridge *eb mtx_enter(&eb->eb_lock); /* don't block map too much */ SMR_TAILQ_FOREACH_SAFE_LOCKED(ebe, ebl, ebe_lentry, nebe) { + if (ebe->ebe_type == EBE_VPORT) + continue; if (flags == IFBF_FLUSHDYN && ebe->ebe_type != EBE_DYNAMIC) continue; @@ -639,6 +644,7 @@ etherbridge_rtfind(struct etherbridge *e bareq.ifba_age = MIN(age, 0xff); bareq.ifba_flags = IFBAF_DYNAMIC; break; + case EBE_VPORT: case EBE_STATIC: bareq.ifba_age = 0; bareq.ifba_flags = IFBAF_STATIC; Index: if_etherbridge.h =================================================================== RCS file: /cvs/src/sys/net/if_etherbridge.h,v retrieving revision 1.3 diff -u -p -r1.3 if_etherbridge.h --- if_etherbridge.h 26 Feb 2021 01:28:51 -0000 1.3 +++ if_etherbridge.h 5 Mar 2021 10:34:12 -0000 @@ -47,6 +47,7 @@ struct eb_entry { unsigned int ebe_type; #define EBE_DYNAMIC 0x0 #define EBE_STATIC 0x1 +#define EBE_VPORT 0x2 #define EBE_DEAD 0xdead time_t ebe_age; @@ -97,7 +98,8 @@ int etherbridge_get_tmo(struct etherbri int etherbridge_rtfind(struct etherbridge *, struct ifbaconf *); int etherbridge_add_addr(struct etherbridge *, void *, const struct ether_addr *, unsigned int); -int etherbridge_del_addr(struct etherbridge *, const struct ether_addr *); +int etherbridge_del_addr(struct etherbridge *, + const struct ether_addr *, int); void etherbridge_flush(struct etherbridge *, uint32_t); static inline unsigned int Index: if_gre.c =================================================================== RCS file: /cvs/src/sys/net/if_gre.c,v retrieving revision 1.170 diff -u -p -r1.170 if_gre.c --- if_gre.c 27 Feb 2021 09:21:22 -0000 1.170 +++ if_gre.c 5 Mar 2021 10:34:12 -0000 @@ -3620,7 +3620,7 @@ nvgre_add_addr(struct nvgre_softc *sc, c static int nvgre_del_addr(struct nvgre_softc *sc, const struct ifbareq *ifba) { - return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst)); + return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst, 0)); } static void Index: if_veb.c =================================================================== RCS file: /cvs/src/sys/net/if_veb.c,v retrieving revision 1.15 diff -u -p -r1.15 if_veb.c --- if_veb.c 5 Mar 2021 06:44:09 -0000 1.15 +++ if_veb.c 5 Mar 2021 10:34:12 -0000 @@ -180,6 +180,7 @@ static int veb_iff(struct veb_softc *); static void veb_p_linkch(void *); static void veb_p_detach(void *); static int veb_p_ioctl(struct ifnet *, u_long, caddr_t); +static int veb_vp_ioctl(struct ifnet *, u_long, caddr_t); static int veb_p_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); @@ -1207,6 +1208,11 @@ veb_add_port(struct veb_softc *sc, const if (ifp0 == NULL) return (EINVAL); + if (span && ifp0->if_enqueue == vport_enqueue) { /* vport is special */ + error = ENODEV; + goto put; + } + if (ifp0->if_type != IFT_ETHER) { error = EPROTONOSUPPORT; goto put; @@ -1252,7 +1258,8 @@ veb_add_port(struct veb_softc *sc, const if (error != 0) goto free; - p->p_bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; + if (ifp0->if_enqueue != vport_enqueue) + p->p_bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; p->p_brport.eb_input = veb_port_input; } @@ -1274,7 +1281,9 @@ veb_add_port(struct veb_softc *sc, const port_list->l_count++; ether_brport_set(ifp0, &p->p_brport); - if (ifp0->if_enqueue != vport_enqueue) { /* vport is special */ + if (ifp0->if_enqueue == vport_enqueue) /* vport is special */ + ifp0->if_ioctl = veb_vp_ioctl; + else { ifp0->if_ioctl = veb_p_ioctl; ifp0->if_output = veb_p_output; } @@ -1779,7 +1788,47 @@ veb_add_addr(struct veb_softc *sc, const static int veb_del_addr(struct veb_softc *sc, const struct ifbareq *ifba) { - return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst)); + return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst, 0)); +} + +static int +veb_vp_ioctl(struct ifnet *ifp0, u_long cmd, caddr_t data) +{ + struct ifreq *ifr = (struct ifreq *)data; + const struct ether_brport *eb = ether_brport_get_locked(ifp0); + struct veb_port *p; + struct veb_softc *sc; + struct arpcom *ac0; + int error = 0; + + KASSERTMSG(eb != NULL, + "%s: %s called without an ether_brport set", + ifp0->if_xname, __func__); + KASSERTMSG(eb->eb_input == veb_port_input, + "%s called %s, but eb_input (%p) seems wrong", + ifp0->if_xname, __func__, eb->eb_input); + + p = eb->eb_port; + + switch (cmd) { + case SIOCSIFLLADDR: + /* short circuit the vport ioctl handler */ + /* XXX this knows a lot about the lladdr code in if.c */ + + sc = p->p_veb; + ac0 = (struct arpcom *)ifp0; + + etherbridge_del_addr(&sc->sc_eb, + (struct ether_addr *)ac0->ac_enaddr, 1); + etherbridge_add_addr(&sc->sc_eb, p, + (struct ether_addr *)ifr->ifr_addr.sa_data, EBE_VPORT); + break; + default: + error = (*p->p_ioctl)(ifp0, cmd, data); + break; + } + + return (error); } static int @@ -2069,6 +2118,9 @@ vport_ioctl(struct ifnet *ifp, u_long cm if (ISSET(ifp->if_flags, IFF_RUNNING)) error = vport_down(sc); } + break; + + case SIOCSIFLLADDR: break; case SIOCADDMULTI: