From owner-tech+M42254=david=gwynne.id.au@openbsd.org Thu May 28 19:19:48 2015 Delivered-To: david@gwynne.id.au Received: by 10.194.186.241 with SMTP id fn17csp847750wjc; Thu, 28 May 2015 02:19:48 -0700 (PDT) X-Received: by 10.52.112.36 with SMTP id in4mr1554355vdb.3.1432804788148; Thu, 28 May 2015 02:19:48 -0700 (PDT) Return-Path: Received: from shear.ucar.edu (lists.openbsd.org. [192.43.244.163]) by mx.google.com with ESMTPS id 8si1994895vdz.65.2015.05.28.02.19.47 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 May 2015 02:19:48 -0700 (PDT) Received-SPF: pass (google.com: domain of owner-tech+M42254=david=gwynne.id.au@openbsd.org designates 192.43.244.163 as permitted sender) client-ip=192.43.244.163; Authentication-Results: mx.google.com; spf=pass (google.com: domain of owner-tech+M42254=david=gwynne.id.au@openbsd.org designates 192.43.244.163 as permitted sender) smtp.mail=owner-tech+M42254=david=gwynne.id.au@openbsd.org Received: from openbsd.org (localhost [127.0.0.1]) by shear.ucar.edu (8.14.7/8.14.7) with ESMTP id t4S9JbpL013904 for ; Thu, 28 May 2015 03:19:43 -0600 (MDT) Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by shear.ucar.edu (8.14.7/8.14.7) with ESMTP id t4S9JQvZ030835 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES256-SHA bits=256 verify=NO) for ; Thu, 28 May 2015 03:19:28 -0600 (MDT) Received: from mfilter14-d.gandi.net (mfilter14-d.gandi.net [217.70.178.142]) by relay4-d.mail.gandi.net (Postfix) with ESMTP id 5FF9C172144; Thu, 28 May 2015 11:19:26 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at mfilter14-d.gandi.net Received: from relay4-d.mail.gandi.net ([217.70.183.196]) by mfilter14-d.gandi.net (mfilter14-d.gandi.net [10.0.15.180]) (amavisd-new, port 10024) with ESMTP id eYV2zu7Zjn6p; Thu, 28 May 2015 11:19:06 +0200 (CEST) X-Originating-IP: 195.132.27.120 Received: from figo.nolizard.org (195-132-27-120.rev.numericable.fr [195.132.27.120]) (Authenticated sender: mpieuchot@nolizard.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id AE7CC1720D1; Thu, 28 May 2015 11:19:05 +0200 (CEST) Received: from localhost (figo.nolizard.org [local]); by figo.nolizard.org (OpenSMTPD) with ESMTPA id 857d0e50; Thu, 28 May 2015 11:19:05 +0200 (CEST) Date: Thu, 28 May 2015 11:19:05 +0200 From: Martin Pieuchot To: mxb Cc: tech@openbsd.org Subject: Re: carp(4) is out Message-ID: <20150528091905.GB21491@figo.nolizard.org> Mail-Followup-To: mxb , tech@openbsd.org References: <20150522140533.GH4348@figo.nolizard.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.23 (2014-03-12) List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Loop: tech@openbsd.org Precedence: list Sender: owner-tech@openbsd.org Status: RO Content-Length: 8106 Lines: 284 On 23/05/15(Sat) 19:08, mxb wrote: > [...] > so far no problems. Here's an updated version to match recent changes. It also includes a nitpick fix from bluhm@. Tests and oks welcome. Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.201 diff -u -p -r1.201 if_ethersubr.c --- net/if_ethersubr.c 26 May 2015 11:39:07 -0000 1.201 +++ net/if_ethersubr.c 28 May 2015 08:05:02 -0000 @@ -490,18 +490,6 @@ ether_input(struct mbuf *m) } #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 28 May 2015 09:06:00 -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 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) { + 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,13 @@ 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 == NULL) || + (!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 28 May 2015 08:05:02 -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_ */