diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2017-05-31 05:14:52 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2017-05-31 05:14:52 +0000 |
commit | 474cf127cf8dfb7403003ff3af230d19461f4583 (patch) | |
tree | 728d14dca0c6193769378eaf40cda7c219636166 /sys/net | |
parent | 31e8a91326313061e933c6358fa777d843653de2 (diff) |
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@
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_vlan.c | 121 |
1 files 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); @@ -862,6 +835,56 @@ unlock: } 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) { struct vlanreq vlr; |