From: dlg Date: Wed, 24 Feb 2021 03:20:48 +0000 (+0000) Subject: add support for adding and deleting mac addr entries on nvgre. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=f90c053440f0f6ef5fa7436278b4d5bb06d40615;p=openbsd add support for adding and deleting mac addr entries on nvgre. the guts of this are in the etherbridge code which i added for veb and used in bpe. there's a bit of boilerplate to make sure that the addresses used for the endpoints will work with the tunnel addresses that have been configured, but it's not too bad. again, this is hard to use because ifconfig doesnt (yet) know how to put ethernet addresses into the "add address" ioctl. these ioctls could be used for things like evpn via bgpd though. not sure if that's interesting to anyone though. it would probably be more useful on vxlan interfaces. --- diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 94e7f7fac67..ec4344e2d6b 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gre.c,v 1.166 2021/02/21 03:46:34 dlg Exp $ */ +/* $OpenBSD: if_gre.c,v 1.167 2021/02/24 03:20:48 dlg Exp $ */ /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -449,6 +449,9 @@ static int nvgre_input(const struct gre_tunnel *, struct mbuf *, int, uint8_t); static void nvgre_send(void *); +static int nvgre_add_addr(struct nvgre_softc *, const struct ifbareq *); +static int nvgre_del_addr(struct nvgre_softc *, const struct ifbareq *); + static int nvgre_eb_port_eq(void *, void *, void *); static void *nvgre_eb_port_take(void *, void *); static void nvgre_eb_port_rele(void *, void *); @@ -2692,6 +2695,12 @@ nvgre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) etherbridge_flush(&sc->sc_eb, ((struct ifbreq *)data)->ifbr_ifsflags); break; + case SIOCBRDGSADDR: + error = nvgre_add_addr(sc, (struct ifbareq *)data); + break; + case SIOCBRDGDADDR: + error = nvgre_del_addr(sc, (struct ifbareq *)data); + break; case SIOCADDMULTI: case SIOCDELMULTI: @@ -3538,6 +3547,85 @@ nvgre_set_parent(struct nvgre_softc *sc, const char *parent) return (0); } +static int +nvgre_add_addr(struct nvgre_softc *sc, const struct ifbareq *ifba) +{ + struct sockaddr_in *sin; +#ifdef INET6 + struct sockaddr_in6 *sin6; + struct sockaddr_in6 src6 = { + .sin6_len = sizeof(src6), + .sin6_family = AF_UNSPEC, + }; + int error; +#endif + union gre_addr endpoint; + unsigned int type; + + /* ignore ifba_ifsname */ + + if (ISSET(ifba->ifba_flags, ~IFBAF_TYPEMASK)) + return (EINVAL); + switch (ifba->ifba_flags & IFBAF_TYPEMASK) { + case IFBAF_DYNAMIC: + type = EBE_DYNAMIC; + break; + case IFBAF_STATIC: + type = EBE_STATIC; + break; + default: + return (EINVAL); + } + + memset(&endpoint, 0, sizeof(endpoint)); + + if (ifba->ifba_dstsa.ss_family != sc->sc_tunnel.t_af) + return (EAFNOSUPPORT); + switch (ifba->ifba_dstsa.ss_family) { + case AF_INET: + sin = (struct sockaddr_in *)&ifba->ifba_dstsa; + if (in_nullhost(sin->sin_addr) || + IN_MULTICAST(sin->sin_addr.s_addr)) + return (EADDRNOTAVAIL); + + endpoint.in4 = sin->sin_addr; + break; + memset(sin6, 0, sizeof(*sin6)); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(*sin6); + +#ifdef INET6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&ifba->ifba_dstsa; + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || + IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + return (EADDRNOTAVAIL); + + in6_recoverscope(&src6, &sc->sc_tunnel.t_src6); + + if (src6.sin6_scope_id != sin6->sin6_scope_id) + return (EADDRNOTAVAIL); + + error = in6_embedscope(&endpoint.in6, sin6, NULL); + if (error != 0) + return (error); + + break; +#endif + default: /* AF_UNSPEC */ + return (EADDRNOTAVAIL); + } + + return (etherbridge_add_addr(&sc->sc_eb, &endpoint, + &ifba->ifba_dst, type)); +} + +static int +nvgre_del_addr(struct nvgre_softc *sc, const struct ifbareq *ifba) +{ + return (etherbridge_del_addr(&sc->sc_eb, &ifba->ifba_dst)); +} + static void nvgre_start(struct ifnet *ifp) {