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_ */
> 

Reply via email to