Index: ip_carp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.343 diff -u -p -r1.343 ip_carp.c --- ip_carp.c 29 Apr 2020 07:04:32 -0000 1.343 +++ ip_carp.c 29 Apr 2020 09:49:57 -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); @@ -830,8 +809,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 +1114,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 +1202,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); @@ -2263,65 +2226,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);