Hey, so far no problems. //mxb
> On 22 maj 2015, at 16:05, Martin Pieuchot <m...@openbsd.org> wrote: > > Let's take carp(4) out of ether_input(). This is quite similar to what > happened to trunk(4) and vlan(4). > > I appreciate tests of any kind, reviews and oks. > > > Index: net/if_ethersubr.c > =================================================================== > RCS file: /cvs/src/sys/net/if_ethersubr.c,v > retrieving revision 1.199 > diff -u -p -r1.199 if_ethersubr.c > --- net/if_ethersubr.c 19 May 2015 11:09:24 -0000 1.199 > +++ net/if_ethersubr.c 22 May 2015 13:39:44 -0000 > @@ -502,18 +502,6 @@ ether_input(struct mbuf *m, void *hdr) > } > #endif > > -#if NCARP > 0 > - if (ifp->if_carp) { > - if (ifp->if_type != IFT_CARP && (carp_input(ifp, eh, m) == 0)) > - return (1); > - /* clear mcast if received on a carp IP balanced address */ > - else if (ifp->if_type == IFT_CARP && > - m->m_flags & (M_BCAST|M_MCAST) && > - carp_our_mcastaddr(ifp, (u_int8_t *)&eh->ether_dhost)) > - m->m_flags &= ~(M_BCAST|M_MCAST); > - } > -#endif /* NCARP > 0 */ > - > ac = (struct arpcom *)ifp; > > /* > Index: netinet/ip_carp.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_carp.c,v > retrieving revision 1.257 > diff -u -p -r1.257 ip_carp.c > --- netinet/ip_carp.c 21 May 2015 09:17:53 -0000 1.257 > +++ netinet/ip_carp.c 22 May 2015 13:54:30 -0000 > @@ -120,6 +120,7 @@ struct carp_softc { > #define sc_carpdev sc_ac.ac_if.if_carpdev > void *ah_cookie; > void *lh_cookie; > + struct ifih *sc_ifih; > struct ip_moptions sc_imo; > #ifdef INET6 > struct ip6_moptions sc_im6o; > @@ -193,6 +194,7 @@ void carp_hmac_generate(struct carp_vhos > unsigned char *, u_int8_t); > int carp_hmac_verify(struct carp_vhost_entry *, u_int32_t *, > unsigned char *); > +int carp_input(struct mbuf *, void *); > void carp_proto_input_c(struct mbuf *, struct carp_header *, int, > sa_family_t); > void carpattach(int); > @@ -824,6 +826,7 @@ carp_del_all_timeouts(struct carp_softc > void > carpdetach(struct carp_softc *sc) > { > + struct ifnet *ifp; > struct carp_if *cif; > int s; > > @@ -839,20 +842,29 @@ carpdetach(struct carp_softc *sc) > carp_setrun_all(sc, 0); > carp_multicast_cleanup(sc); > > - s = splnet(); > if (sc->ah_cookie != NULL) > hook_disestablish(sc->sc_if.if_addrhooks, sc->ah_cookie); > - if (sc->sc_carpdev != NULL) { > - if (sc->lh_cookie != NULL) > - hook_disestablish(sc->sc_carpdev->if_linkstatehooks, > - sc->lh_cookie); > - cif = (struct carp_if *)sc->sc_carpdev->if_carp; > - TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); > - if (!--cif->vhif_nvrs) { > - ifpromisc(sc->sc_carpdev, 0); > - sc->sc_carpdev->if_carp = NULL; > - free(cif, M_IFADDR, sizeof(*cif)); > - } > + > + ifp = sc->sc_carpdev; > + if (ifp == NULL) > + return; > + > + s = splnet(); > + /* Restore previous input handler. */ > + if (--sc->sc_ifih->ifih_refcnt == 0) { > + SLIST_REMOVE(&ifp->if_inputs, sc->sc_ifih, ifih, ifih_next); > + free(sc->sc_ifih, M_DEVBUF, sizeof(*sc->sc_ifih)); > + } > + > + if (sc->lh_cookie != NULL) > + hook_disestablish(ifp->if_linkstatehooks, > + sc->lh_cookie); > + cif = (struct carp_if *)ifp->if_carp; > + TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); > + if (!--cif->vhif_nvrs) { > + ifpromisc(ifp, 0); > + ifp->if_carp = NULL; > + free(cif, M_IFADDR, sizeof(*cif)); > } > sc->sc_carpdev = NULL; > splx(s); > @@ -1403,27 +1415,21 @@ carp_get_srclladdr(struct ifnet *ifp, u_ > } > > int > -carp_our_mcastaddr(struct ifnet *ifp, u_int8_t *d_enaddr) > -{ > - struct carp_softc *sc = ifp->if_softc; > - > - if (sc->sc_balancing != CARP_BAL_IP) > - return (0); > - > - return (!memcmp(sc->sc_ac.ac_enaddr, d_enaddr, ETHER_ADDR_LEN)); > -} > - > - > -int > -carp_input(struct ifnet *ifp0, struct ether_header *eh0, struct mbuf *m) > +carp_input(struct mbuf *m, void *hdr) > { > + struct carp_softc *sc; > struct ether_header *eh; > - struct carp_if *cif = (struct carp_if *)ifp0->if_carp; > - struct ifnet *ifp; > + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); > + struct carp_if *cif; > + struct ifnet *ifp0, *ifp; > > - ifp = carp_ourether(cif, eh0->ether_dhost); > - if (ifp == NULL && (m->m_flags & (M_BCAST|M_MCAST)) == 0) > - return (1); > + ifp0 = m->m_pkthdr.rcvif; > + eh = mtod(m, struct ether_header *); > + cif = (struct carp_if *)ifp0->if_carp; > + > + ifp = carp_ourether(cif, eh->ether_dhost); > + if (ifp == NULL && !ETHER_IS_MULTICAST(eh->ether_dhost)) > + return (0); > > if (ifp == NULL) { > struct carp_softc *vh; > @@ -1439,41 +1445,33 @@ carp_input(struct ifnet *ifp0, struct et > m0 = m_copym2(m, 0, M_COPYALL, M_DONTWAIT); > if (m0 == NULL) > continue; > - M_PREPEND(m0, sizeof(*eh), M_DONTWAIT); > - if (m0 == NULL) > - continue; > - eh = mtod(m0, struct ether_header *); > - memmove(eh, eh0, sizeof(*eh)); > > - m0->m_pkthdr.rcvif = &vh->sc_if; > -#if NBPFILTER > 0 > - if (vh->sc_if.if_bpf) > - bpf_mtap_ether(vh->sc_if.if_bpf, m0, > - BPF_DIRECTION_IN); > -#endif > + ml_init(&ml); > + ml_enqueue(&ml, m0); > + > + if_input(&vh->sc_if, &ml); > vh->sc_if.if_ipackets++; > - ether_input_mbuf(&vh->sc_if, m0); > } > > - return (1); > + return (0); > } > > - M_PREPEND(m, sizeof(*eh), M_DONTWAIT); > - if (m == NULL) > - return (0); > - eh = mtod(m, struct ether_header *); > - memmove(eh, eh0, sizeof(*eh)); > + ifp0->if_ibytes += m->m_pkthdr.len; > > - m->m_pkthdr.rcvif = ifp; > + /* > + * Clear mcast if received on a carp IP balanced address. > + */ > + sc = ifp->if_softc; > + if (sc->sc_balancing == CARP_BAL_IP && > + ETHER_IS_MULTICAST(eh->ether_dhost)) > + *(eh->ether_dhost) &= ~0x01; > > -#if NBPFILTER > 0 > - if (ifp->if_bpf) > - bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_IN); > -#endif > - ifp->if_ipackets++; > - ether_input_mbuf(ifp, m); > > - return (0); > + ml_enqueue(&ml, m); > + > + if_input(ifp, &ml); > + ifp->if_ipackets++; > + return (1); > } > > int > @@ -1688,6 +1686,18 @@ carp_set_ifp(struct carp_softc *sc, stru > return (EINVAL); > } > > + /* Can we share an ifih between multiple carp(4) instances? */ > + sc->sc_ifih = SLIST_FIRST(&ifp->if_inputs); > + if (sc->sc_ifih->ifih_input != carp_input) { > + sc->sc_ifih = malloc(sizeof(*sc->sc_ifih), M_DEVBUF, M_NOWAIT); > + if (sc->sc_ifih == NULL) { > + free(ncif, M_IFADDR, sizeof(*ncif)); > + return (ENOMEM); > + } > + sc->sc_ifih->ifih_input = carp_input; > + sc->sc_ifih->ifih_refcnt = 0; > + } > + > /* detach from old interface */ > if (sc->sc_carpdev != NULL) > carpdetach(sc); > @@ -1720,9 +1730,15 @@ carp_set_ifp(struct carp_softc *sc, stru > if (sc->sc_naddrs || sc->sc_naddrs6) > sc->sc_if.if_flags |= IFF_UP; > carp_set_enaddr(sc); > - s = splnet(); > + > sc->lh_cookie = hook_establish(ifp->if_linkstatehooks, 1, > carp_carpdev_state, ifp); > + > + s = splnet(); > + /* Change input handler of the physical interface. */ > + if (++sc->sc_ifih->ifih_refcnt == 1) > + SLIST_INSERT_HEAD(&ifp->if_inputs, sc->sc_ifih, ifih_next); > + > carp_carpdev_state(ifp); > splx(s); > > @@ -2261,13 +2277,12 @@ carp_output(struct ifnet *ifp, struct mb > > vhe = sc->cur_vhe ? sc->cur_vhe : LIST_FIRST(&sc->carp_vhosts); > > - if (sc->sc_carpdev != NULL && > - (sc->sc_balancing || vhe->state == MASTER)) > - return (sc->sc_carpdev->if_output(ifp, m, sa, rt)); > - else { > + if (!sc->sc_carpdev || (!sc->sc_balancing && vhe->state != MASTER)) { > m_freem(m); > return (ENETUNREACH); > } > + > + return (sc->sc_carpdev->if_output(ifp, m, sa, rt)); > } > > void > Index: netinet/ip_carp.h > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_carp.h,v > retrieving revision 1.32 > diff -u -p -r1.32 ip_carp.h > --- netinet/ip_carp.h 19 Dec 2014 05:36:28 -0000 1.32 > +++ netinet/ip_carp.h 22 May 2015 13:39:44 -0000 > @@ -172,13 +172,10 @@ int carp_iamatch(struct in_ifaddr *, u > u_int8_t **); > int carp_iamatch6(struct ifnet *, u_char *, struct sockaddr_dl **); > struct ifnet *carp_ourether(void *, u_int8_t *); > -int carp_input(struct ifnet *, struct ether_header *, > - struct mbuf *); > int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *, > struct rtentry *); > int carp_sysctl(int *, u_int, void *, size_t *, void *, size_t); > int carp_lsdrop(struct mbuf *, sa_family_t, u_int32_t *, u_int32_t > *); > u_char *carp_get_srclladdr(struct ifnet *, u_char *); > -int carp_our_mcastaddr(struct ifnet *, u_int8_t *); > #endif /* _KERNEL */ > #endif /* _NETINET_IP_CARP_H_ */ >