This diff is a cleanup needed for upcoming bridge(4) changes but has two
nice side effects on its own.
By moving the Ethernet header rewrite logic into carp_start(), it is now
possible to tcpdump(8) output packets on a carp(4) interface and we get
rid of the "#if NCARP > 0" in ether_output().
Moving such logic into carp_start() is the best solution I came with.
It works with all our pseudo-drivers in a unified way, will allow me
to fix some bridge(4) bugs and does not require a complex change in
the network stack like if_input().
Ok?
Index: net/if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.202
diff -u -p -r1.202 if_ethersubr.c
--- net/if_ethersubr.c 2 Jun 2015 09:38:24 -0000 1.202
+++ net/if_ethersubr.c 2 Jun 2015 10:05:31 -0000
@@ -113,11 +113,6 @@ didn't get a copy, you may request one f
#include <net/if_vlan_var.h>
#endif /* NVLAN > 0 */
-#include "carp.h"
-#if NCARP > 0
-#include <netinet/ip_carp.h>
-#endif
-
#include "pppoe.h"
#if NPPPOE > 0
#include <net/if_pppoe.h>
@@ -243,18 +238,17 @@ ether_addheader(struct mbuf **m, struct
* Assumes that ifp is actually pointer to arpcom structure.
*/
int
-ether_output(struct ifnet *ifp0, struct mbuf *m0, struct sockaddr *dst,
+ether_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
struct rtentry *rt)
{
u_int16_t etype;
- int len, error = 0;
u_char edst[ETHER_ADDR_LEN];
u_char *esrc;
struct mbuf *m = m0;
struct mbuf *mcopy = NULL;
struct ether_header *eh;
- struct arpcom *ac = (struct arpcom *)ifp0;
- struct ifnet *ifp = ifp0;
+ struct arpcom *ac = (struct arpcom *)ifp;
+ int error = 0;
#ifdef DIAGNOSTIC
if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
@@ -267,20 +261,6 @@ ether_output(struct ifnet *ifp0, struct
esrc = ac->ac_enaddr;
-#if NCARP > 0
- if (ifp->if_type == IFT_CARP) {
- ifp = ifp->if_carpdev;
- ac = (struct arpcom *)ifp;
-
- if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
- (IFF_UP|IFF_RUNNING))
- senderr(ENETDOWN);
- }
-
- if (ifp0 != ifp && ifp0->if_type == IFT_CARP)
- esrc = carp_get_srclladdr(ifp0, esrc);
-#endif /* NCARP > 0 */
-
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
@@ -402,14 +382,7 @@ ether_output(struct ifnet *ifp0, struct
}
#endif
- len = m->m_pkthdr.len;
-
- error = if_output(ifp, m);
-#if NCARP > 0
- if (!error && ifp != ifp0)
- ifp0->if_obytes += len;
-#endif /* NCARP > 0 */
- return (error);
+ return (if_output(ifp, m));
bad:
if (m)
m_freem(m);
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.258
diff -u -p -r1.258 ip_carp.c
--- netinet/ip_carp.c 2 Jun 2015 09:38:24 -0000 1.258
+++ netinet/ip_carp.c 2 Jun 2015 10:05:31 -0000
@@ -745,7 +745,7 @@ 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;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, 1);
IFQ_SET_READY(&ifp->if_snd);
if_attach(ifp);
ether_ifattach(ifp);
@@ -2257,15 +2257,52 @@ carp_ifgattr_ioctl(struct ifnet *ifp, u_
carp_vhe_send_ad_all(sc);
}
-/*
- * Start output on carp interface. This function should never be called.
- */
void
carp_start(struct ifnet *ifp)
{
-#ifdef DEBUG
- printf("%s: start called\n", ifp->if_xname);
-#endif
+ struct carp_softc *sc = ifp->if_softc;
+ struct mbuf *m;
+
+ for (;;) {
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif /* NBPFILTER > 0 */
+
+ if ((ifp->if_carpdev->if_flags & (IFF_UP|IFF_RUNNING)) !=
+ (IFF_UP|IFF_RUNNING)) {
+ IF_DROP(&ifp->if_carpdev->if_snd);
+ ifp->if_oerrors++;
+ m_freem(m);
+ continue;
+ }
+
+ /*
+ * Do not leak the multicast address when sending
+ * advertisements in 'ip' and 'ip-stealth' balacing
+ * modes.
+ */
+ if (sc->sc_balancing != CARP_BAL_IPSTEALTH &&
+ sc->sc_balancing != CARP_BAL_IP &&
+ (sc->cur_vhe && !sc->cur_vhe->vhe_leader)) {
+ struct ether_header *eh;
+ uint8_t *esrc;
+
+ eh = mtod(m, struct ether_header *);
+ esrc = sc->cur_vhe->vhe_enaddr;
+ memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
+ }
+
+ if (if_output(ifp->if_carpdev, m)) {
+ ifp->if_oerrors++;
+ continue;
+ }
+ ifp->if_opackets++;
+ }
}
int
@@ -2283,7 +2320,7 @@ carp_output(struct ifnet *ifp, struct mb
return (ENETUNREACH);
}
- return (sc->sc_carpdev->if_output(ifp, m, sa, rt));
+ return (ether_output(ifp, m, sa, rt));
}
void