Index: ip_carp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.342 diff -u -p -r1.342 ip_carp.c --- ip_carp.c 8 Nov 2019 07:51:41 -0000 1.342 +++ ip_carp.c 27 Apr 2020 10:16:07 -0000 @@ -233,6 +233,8 @@ int carp_check_dup_vhids(struct carp_sof void carp_ifgroup_ioctl(struct ifnet *, u_long, caddr_t); void carp_ifgattr_ioctl(struct ifnet *, u_long, caddr_t); void carp_start(struct ifnet *); +int carp_enqueue(struct ifnet *, struct mbuf *); +void carp_transmit(struct carp_softc *, struct ifnet *, struct mbuf *); void carp_setrun_all(struct carp_softc *, sa_family_t); void carp_setrun(struct carp_vhost_entry *, sa_family_t); void carp_set_state_all(struct carp_softc *, int); @@ -636,8 +638,8 @@ carp_proto_input_c(struct ifnet *ifp, st } getmicrotime(&sc->sc_if.if_lastchange); - sc->sc_if.if_ipackets++; - sc->sc_if.if_ibytes += m->m_pkthdr.len; + //sc->sc_if.if_ipackets++; + //sc->sc_if.if_ibytes += m->m_pkthdr.len; /* verify the CARP version. */ if (ch->carp_version != CARP_VERSION) { @@ -830,8 +832,8 @@ carp_clone_create(struct if_clone *ifc, ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = carp_ioctl; ifp->if_start = carp_start; + ifp->if_enqueue = carp_enqueue; ifp->if_xflags = IFXF_CLONED; - IFQ_SET_MAXLEN(&ifp->if_snd, 1); if_counters_alloc(ifp); if_attach(ifp); ether_ifattach(ifp); @@ -1135,8 +1137,8 @@ carp_send_ad(struct carp_vhost_entry *vh m->m_data -= sizeof(*ip); getmicrotime(&sc->sc_if.if_lastchange); - sc->sc_if.if_opackets++; - sc->sc_if.if_obytes += len; + //sc->sc_if.if_opackets++; + //sc->sc_if.if_obytes += len; carpstat_inc(carps_opackets); error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, @@ -1223,8 +1225,8 @@ carp_send_ad(struct carp_vhost_entry *vh m->m_data -= sizeof(*ip6); getmicrotime(&sc->sc_if.if_lastchange); - sc->sc_if.if_opackets++; - sc->sc_if.if_obytes += len; + //sc->sc_if.if_opackets++; + //sc->sc_if.if_obytes += len; carpstat_inc(carps_opackets6); error = ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL); @@ -1437,16 +1439,18 @@ carp_input(struct ifnet *ifp0, struct mb * for each CARP interface _before_ copying. */ SRPL_FOREACH(sc, &sr, cif, sc_list) { + struct ifnet *ifp = &sc->sc_if; struct mbuf *m0; - if (!(sc->sc_if.if_flags & IFF_UP)) + if (!ISSET(ifp->if_flags, IFF_UP) || + !LINK_STATE_IS_UP(ifp->if_link_state)) continue; m0 = m_dup_pkt(m, ETHER_ALIGN, M_DONTWAIT); if (m0 == NULL) continue; - if_vinput(&sc->sc_if, m0); + if_vinput(ifp, m0); } SRPL_LEAVE(&sr); @@ -1825,23 +1829,6 @@ carp_addr_updated(void *v) sc->sc_naddrs = new_naddrs; sc->sc_naddrs6 = new_naddrs6; - /* Re-establish multicast membership removed by in_control */ - if (IN_MULTICAST(sc->sc_peer.s_addr)) { - if (!in_hasmulti(&sc->sc_peer, &sc->sc_if)) { - struct in_multi **imm = - sc->sc_imo.imo_membership; - u_int16_t maxmem = - sc->sc_imo.imo_max_memberships; - - memset(&sc->sc_imo, 0, sizeof(sc->sc_imo)); - sc->sc_imo.imo_membership = imm; - sc->sc_imo.imo_max_memberships = maxmem; - - if (sc->sc_carpdev != NULL && sc->sc_naddrs > 0) - carp_join_multicast(sc); - } - } - if (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0) { sc->sc_if.if_flags &= ~IFF_UP; carp_set_state_all(sc, INIT); @@ -1877,6 +1864,7 @@ carp_set_addr(struct carp_softc *sc, str int carp_join_multicast(struct carp_softc *sc) { + struct ifnet *ifp0 = sc->sc_carpdev; struct ip_moptions *imo = &sc->sc_imo; struct in_multi *imm; struct in_addr addr; @@ -1885,12 +1873,12 @@ carp_join_multicast(struct carp_softc *s return (0); addr.s_addr = sc->sc_peer.s_addr; - if ((imm = in_addmulti(&addr, &sc->sc_if)) == NULL) + if ((imm = in_addmulti(&addr, ifp0)) == NULL) return (ENOBUFS); imo->imo_membership[0] = imm; imo->imo_num_memberships = 1; - imo->imo_ifidx = sc->sc_if.if_index; + imo->imo_ifidx = ifp0->if_index; imo->imo_ttl = CARP_DFLTTL; imo->imo_loop = 0; return (0); @@ -1921,6 +1909,7 @@ carp_set_addr6(struct carp_softc *sc, st int carp_join_multicast6(struct carp_softc *sc) { + struct ifnet *ifp0 = sc->sc_carpdev; struct in6_multi_mship *imm, *imm2; struct ip6_moptions *im6o = &sc->sc_im6o; struct sockaddr_in6 addr6; @@ -1931,28 +1920,28 @@ carp_join_multicast6(struct carp_softc * addr6.sin6_family = AF_INET6; addr6.sin6_len = sizeof(addr6); addr6.sin6_addr.s6_addr16[0] = htons(0xff02); - addr6.sin6_addr.s6_addr16[1] = htons(sc->sc_if.if_index); + addr6.sin6_addr.s6_addr16[1] = htons(ifp0->if_index); addr6.sin6_addr.s6_addr8[15] = 0x12; - if ((imm = in6_joingroup(&sc->sc_if, + if ((imm = in6_joingroup(ifp0, &addr6.sin6_addr, &error)) == NULL) { return (error); } /* join solicited multicast address */ memset(&addr6.sin6_addr, 0, sizeof(addr6.sin6_addr)); addr6.sin6_addr.s6_addr16[0] = htons(0xff02); - addr6.sin6_addr.s6_addr16[1] = htons(sc->sc_if.if_index); + addr6.sin6_addr.s6_addr16[1] = htons(ifp0->if_index); addr6.sin6_addr.s6_addr32[1] = 0; addr6.sin6_addr.s6_addr32[2] = htonl(1); addr6.sin6_addr.s6_addr32[3] = 0; addr6.sin6_addr.s6_addr8[12] = 0xff; - if ((imm2 = in6_joingroup(&sc->sc_if, + if ((imm2 = in6_joingroup(ifp0, &addr6.sin6_addr, &error)) == NULL) { in6_leavegroup(imm); return (error); } /* apply v6 multicast membership */ - im6o->im6o_ifidx = sc->sc_if.if_index; + im6o->im6o_ifidx = ifp0->if_index; if (imm) LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); @@ -1984,12 +1973,10 @@ carp_ioctl(struct ifnet *ifp, u_long cmd switch (ifa->ifa_addr->sa_family) { case AF_INET: - sc->sc_if.if_flags |= IFF_UP; error = carp_set_addr(sc, satosin(ifa->ifa_addr)); break; #ifdef INET6 case AF_INET6: - sc->sc_if.if_flags |= IFF_UP; error = carp_set_addr6(sc, satosin6(ifa->ifa_addr)); break; #endif /* INET6 */ @@ -2263,65 +2250,87 @@ void carp_start(struct ifnet *ifp) { struct carp_softc *sc = ifp->if_softc; + struct ifnet *ifp0 = sc->sc_carpdev; struct mbuf *m; - for (;;) { - IFQ_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; + if (ifp0 == NULL) { + ifq_purge(&ifp->if_snd); + return; + } -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); -#endif /* NBPFILTER > 0 */ + while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) + carp_transmit(sc, ifp0, m); +} - if ((ifp->if_carpdev->if_flags & (IFF_UP|IFF_RUNNING)) != - (IFF_UP|IFF_RUNNING)) { - ifp->if_oerrors++; - m_freem(m); - continue; - } +void +carp_transmit(struct carp_softc *sc, struct ifnet *ifp0, struct mbuf *m) +{ + struct ifnet *ifp = &sc->sc_if; - /* - * Do not leak the multicast address when sending - * advertisements in 'ip' and 'ip-stealth' balacing - * modes. - */ - if (sc->sc_balancing == CARP_BAL_IP || - sc->sc_balancing == CARP_BAL_IPSTEALTH) { - struct ether_header *eh; - uint8_t *esrc; - - eh = mtod(m, struct ether_header *); - esrc = ((struct arpcom*)ifp->if_carpdev)->ac_enaddr; - memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost)); +#if NBPFILTER > 0 + { + caddr_t if_bpf = ifp->if_bpf; + if (if_bpf) { + if (bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_OUT)) + m_freem(m); } + } +#endif /* NBPFILTER > 0 */ - if (if_enqueue(ifp->if_carpdev, m)) { - ifp->if_oerrors++; - continue; - } - ifp->if_opackets++; + if (!ISSET(ifp0->if_flags, IFF_RUNNING)) { + counters_inc(ifp->if_counters, ifc_oerrors); + m_freem(m); + return; } + + /* + * Do not leak the multicast address when sending + * advertisements in 'ip' and 'ip-stealth' balacing + * modes. + */ + if (sc->sc_balancing == CARP_BAL_IP || + sc->sc_balancing == CARP_BAL_IPSTEALTH) { + struct ether_header *eh = mtod(m, struct ether_header *); + memcpy(eh->ether_shost, sc->sc_ac.ac_enaddr, + sizeof(eh->ether_shost)); + } + + if (if_enqueue(ifp0, m)) + counters_inc(ifp->if_counters, ifc_oerrors); } int -carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, - struct rtentry *rt) +carp_enqueue(struct ifnet *ifp, struct mbuf *m) { - struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc); - struct carp_vhost_entry *vhe; - struct srp_ref sr; - int ismaster; + struct carp_softc *sc = ifp->if_softc; + struct ifnet *ifp0 = sc->sc_carpdev;; + + /* no ifq_is_priq, cos hfsc on carp doesn't make sense */ /* * If the parent of this carp(4) got destroyed while * `m' was being processed, silently drop it. */ - if (sc->sc_carpdev == NULL) { + if (ifp0 == NULL) { m_freem(m); return (0); } + + counters_pkt(ifp->if_counters, + ifc_opackets, ifc_obytes, m->m_pkthdr.len); + carp_transmit(sc, ifp0, m); + + return (0); +} + +int +carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, + struct rtentry *rt) +{ + struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc); + struct carp_vhost_entry *vhe; + struct srp_ref sr; + int ismaster; if (sc->cur_vhe == NULL) { vhe = SRPL_FIRST(&sr, &sc->carp_vhosts);