From 047b33af8370aa8e8a14264fc6d1d90c8966e523 Mon Sep 17 00:00:00 2001 From: dlg Date: Wed, 31 May 2017 05:14:51 +0000 Subject: [PATCH] make vlan use their parents lladdr all the time, not just when theyre up. krw@ has been having issues with dhclient on vlan interfaces because i made them only configure the lladdr when they were brought up. dhclient likes to read the mac address and then bring them up. this makes vlan copy the parents lladdr onto the vlan interface when the parent is configured. this probably helps with v6 addresses on vlan interfaces too. the new code still supports configuring a custom lladdr on a vlan interface. this can be done both before and after a parent is configured, and if a parent is removed. while here, if the parent is reconfigured while the vlan is up, dont error if the new parent is the same as the current one. this should make running netstart again less noisy. ok krw@ --- sys/net/if_vlan.c | 121 +++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 49 deletions(-) diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index a049a46eeaa..733b005ea39 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan.c,v 1.172 2017/05/29 06:44:54 mpi Exp $ */ +/* $OpenBSD: if_vlan.c,v 1.173 2017/05/31 05:14:51 dlg Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology @@ -97,6 +97,8 @@ void vlan_link_hook(void *); void vlan_link_state(struct ifvlan *, u_char, u_int64_t); int vlan_set_vnetid(struct ifvlan *, uint16_t); +int vlan_set_parent(struct ifvlan *, const char *); +int vlan_del_parent(struct ifvlan *); int vlan_inuse(uint16_t, unsigned int, uint16_t); int vlan_inuse_locked(uint16_t, unsigned int, uint16_t); @@ -472,8 +474,6 @@ vlan_up(struct ifvlan *ifv) /* parent is fine, let's prepare the ifv to handle packets */ ifp->if_hardmtu = hardmtu; SET(ifp->if_flags, ifp0->if_flags & IFF_SIMPLEX); - if (!ISSET(ifv->ifv_flags, IFVF_LLADDR)) - if_setlladdr(ifp, LLADDR(ifp0->if_sadl)); if (ifv->ifv_type != ETHERTYPE_VLAN) { /* @@ -525,8 +525,6 @@ leave: rw_exit(&vlan_tagh_lk); scrub: ifp->if_capabilities = 0; - if (!ISSET(ifv->ifv_flags, IFVF_LLADDR)) - if_setlladdr(ifp, etheranyaddr); CLR(ifp->if_flags, IFF_SIMPLEX); ifp->if_hardmtu = 0xffff; put: @@ -568,8 +566,6 @@ vlan_down(struct ifvlan *ifv) rw_exit_write(&vlan_tagh_lk); ifp->if_capabilities = 0; - if (!ISSET(ifv->ifv_flags, IFVF_LLADDR)) - if_setlladdr(ifp, etheranyaddr); CLR(ifp->if_flags, IFF_SIMPLEX); ifp->if_hardmtu = 0xffff; @@ -674,32 +670,7 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSIFPARENT: - if (ISSET(ifp->if_flags, IFF_RUNNING)) { - error = EBUSY; - break; - } - - ifp0 = ifunit(parent->ifp_parent); - if (ifp0 == NULL) { - error = EINVAL; - break; - } - - if (ifv->ifv_ifp0 == ifp0->if_index) { - /* nop */ - break; - } - - if (ifp0->if_type != IFT_ETHER) { - error = EPROTONOSUPPORT; - break; - } - - error = vlan_inuse(ifv->ifv_type, ifp0->if_index, ifv->ifv_tag); - if (error != 0) - break; - - ifv->ifv_ifp0 = ifp0->if_index; + error = vlan_set_parent(ifv, parent->ifp_parent); break; case SIOCGIFPARENT: @@ -714,12 +685,7 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCDIFPARENT: - if (ISSET(ifp->if_flags, IFF_RUNNING)) { - error = EBUSY; - break; - } - - ifv->ifv_ifp0 = 0; + error = vlan_del_parent(ifv); break; case SIOCADDMULTI: @@ -796,23 +762,30 @@ vlan_setlladdr(struct ifvlan *ifv, struct ifreq *ifr) { struct ifnet *ifp = &ifv->ifv_if;; struct ifnet *ifp0; - int flag = IFVF_LLADDR; - - /* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */ - if (memcmp(ifr->ifr_addr.sa_data, etheranyaddr, ETHER_ADDR_LEN) == 0) - flag = 0; + uint8_t lladdr[ETHER_ADDR_LEN]; + int flag; - if (ISSET(ifv->ifv_flags, IFVF_LLADDR) == flag) - return (0); + memcpy(lladdr, ifr->ifr_addr.sa_data, sizeof(lladdr)); - /* if we're up and the mac is reset, inherit the parents mac */ - if (ISSET(ifp->if_flags, IFF_RUNNING) && flag == 0) { + /* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */ + if (memcmp(lladdr, etheranyaddr, sizeof(lladdr)) == 0) { ifp0 = if_get(ifv->ifv_ifp0); if (ifp0 != NULL) - if_setlladdr(ifp, LLADDR(ifp0->if_sadl)); + memcpy(lladdr, LLADDR(ifp0->if_sadl), sizeof(lladdr)); if_put(ifp0); + + flag = 0; + } else + flag = IFVF_LLADDR; + + if (memcmp(lladdr, LLADDR(ifp->if_sadl), sizeof(lladdr)) == 0 && + ISSET(ifv->ifv_flags, IFVF_LLADDR) == flag) { + /* nop */ + return (0); } + /* commit */ + if_setlladdr(ifp, lladdr); CLR(ifv->ifv_flags, IFVF_LLADDR); SET(ifv->ifv_flags, flag); @@ -861,6 +834,56 @@ unlock: return (error); } +int +vlan_set_parent(struct ifvlan *ifv, const char *parent) +{ + struct ifnet *ifp = &ifv->ifv_if; + struct ifnet *ifp0; + int error = 0; + + ifp0 = ifunit(parent); /* doesn't need an if_put */ + if (ifp0 == NULL) + return (EINVAL); + + if (ifp0->if_type != IFT_ETHER) + return (EPROTONOSUPPORT); + + if (ifv->ifv_ifp0 == ifp0->if_index) { + /* nop */ + return (0); + } + + if (ISSET(ifp->if_flags, IFF_RUNNING)) + return (EBUSY); + + error = vlan_inuse(ifv->ifv_type, ifp0->if_index, ifv->ifv_tag); + if (error != 0) + return (error); + + /* commit */ + ifv->ifv_ifp0 = ifp0->if_index; + if (!ISSET(ifv->ifv_flags, IFVF_LLADDR)) + if_setlladdr(ifp, LLADDR(ifp0->if_sadl)); + + return (0); +} + +int +vlan_del_parent(struct ifvlan *ifv) +{ + struct ifnet *ifp = &ifv->ifv_if; + + if (ISSET(ifp->if_flags, IFF_RUNNING)) + return (EBUSY); + + /* commit */ + ifv->ifv_ifp0 = 0; + if (!ISSET(ifv->ifv_flags, IFVF_LLADDR)) + if_setlladdr(ifp, etheranyaddr); + + return (0); +} + int vlan_set_compat(struct ifnet *ifp, struct ifreq *ifr) { -- 2.20.1