? net/if_mobileip.c ? net/if_mobileip.h ? netinet/ip_etherip.c ? netinet/ip_etherip.h ? netinet/ip_gif.c ? netinet/ip_gif.h ? netinet/ip_mobileip.c ? netinet/ip_mobileip.h ? netinet/ip_tunnel.c Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.536 diff -u -p -r1.536 if.c --- net/if.c 9 Jan 2018 17:50:57 -0000 1.536 +++ net/if.c 10 Jan 2018 03:48:08 -0000 @@ -1007,7 +1007,7 @@ if_deactivate(struct ifnet *ifp) #if NCARP > 0 /* Remove the interface from any carp group it is a part of. */ - if (ifp->if_carp && ifp->if_type != IFT_CARP) + if (ifp->if_type != IFT_CARP && !SRPL_EMPTY_LOCKED(&ifp->if_carp)) carp_ifdetach(ifp); #endif NET_UNLOCK(); Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.300 diff -u -p -r1.300 if_bridge.c --- net/if_bridge.c 9 Jan 2018 15:24:24 -0000 1.300 +++ net/if_bridge.c 10 Jan 2018 03:48:08 -0000 @@ -1108,8 +1108,8 @@ bridge_process(struct ifnet *ifp, struct ac = (struct arpcom *)ifl->ifp; if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0 #if NCARP > 0 - || (ifl->ifp->if_carp && carp_ourether(ifl->ifp->if_carp, - (u_int8_t *)&eh->ether_dhost) != NULL) + || (!SRPL_EMPTY_LOCKED(&ifl->ifp->if_carp) && + !carp_ourether(ifl->ifp, eh->ether_dhost)) #endif ) { if (srcifl->bif_flags & IFBIF_LEARNING) @@ -1131,8 +1131,8 @@ bridge_process(struct ifnet *ifp, struct } if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0 #if NCARP > 0 - || (ifl->ifp->if_carp && carp_ourether(ifl->ifp->if_carp, - (u_int8_t *)&eh->ether_shost) != NULL) + || (!SRPL_EMPTY_LOCKED(&ifl->ifp->if_carp) && + !carp_ourether(ifl->ifp, eh->ether_shost)) #endif ) { m_freem(m); Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.250 diff -u -p -r1.250 if_ethersubr.c --- net/if_ethersubr.c 10 Jan 2018 00:14:38 -0000 1.250 +++ net/if_ethersubr.c 10 Jan 2018 03:48:08 -0000 @@ -108,6 +108,16 @@ didn't get a copy, you may request one f #include #endif +#include "vlan.h" +#if NVLAN > 0 +#include +#endif + +#include "carp.h" +#if NCARP > 0 +#include +#endif + #ifdef INET6 #include #include @@ -127,6 +137,8 @@ u_int8_t etheranyaddr[ETHER_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define senderr(e) { error = (e); goto bad;} +void ether_input_m(struct ifnet *, struct mbuf_list *, struct mbuf *); + int ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data) { @@ -306,70 +318,111 @@ bad: return (error); } -/* - * Process a received Ethernet packet; - * the packet is in the mbuf chain m without - * the ether header, which is provided separately. - */ +void +ether_enqueue(struct ifnet *ifp, struct mbuf_list *ml, struct mbuf *m) +{ +#if NBPFILTER > 0 + caddr_t if_bpf; +#endif + + m->m_pkthdr.ph_ifidx = ifp->if_index; + m->m_pkthdr.ph_rtableid = ifp->if_rdomain; + + /* XXX lock */ + ifp->if_ipackets++; + ifp->if_ibytes += m->m_pkthdr.len; + +#if NBPFILTER > 0 + if_bpf = ifp->if_bpf; + if (if_bpf) { + if (bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_IN)) { + m_freem(m); + return; + } + } +#endif + + ml_enqueue(ml, m); +} + int ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie) { + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + + /* Drop short frames */ + if (m->m_len < ETHER_HDR_LEN) { + m_freem(m); + return (1); + } + + /* We have a reference to the parent's ifp already */ + ether_input_m(ifp, &ml, m); + + /* Run the packet through any child interfaces */ + while ((m = ml_dequeue(&ml)) != NULL) { + ifp = if_get(m->m_pkthdr.ph_ifidx); + if (ifp != NULL) + ether_input_m(ifp, &ml, m); + if_put(ifp); + } + + return (1); +} + +void +ether_input_m(struct ifnet *ifp, struct mbuf_list *ml, struct mbuf *m) +{ struct ether_header *eh; void (*input)(struct ifnet *, struct mbuf *); u_int16_t etype; struct arpcom *ac; - /* Drop short frames */ - if (m->m_len < ETHER_HDR_LEN) - goto dropanyway; + eh = mtod(m, struct ether_header *); + etype = ntohs(eh->ether_type); + + if (ISSET(m->m_flags, M_VLANTAG) || + etype == ETHERTYPE_VLAN || + etype == ETHERTYPE_QINQ) { +#if NVLAN > 0 + vlan_input(ifp, ml, m); +#else + /* noproto++ ? */ + m_freem(m); +#endif + return; + } ac = (struct arpcom *)ifp; - eh = mtod(m, struct ether_header *); - if (ETHER_IS_MULTICAST(eh->ether_dhost)) { - /* - * If this is not a simplex interface, drop the packet - * if it came from us. - */ - if ((ifp->if_flags & IFF_SIMPLEX) == 0) { - if (memcmp(ac->ac_enaddr, eh->ether_shost, - ETHER_ADDR_LEN) == 0) { - m_freem(m); - return (1); - } + if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) != 0) { + /* The packet doesn't match the ether addr on this iface */ + +#if NCARP > 0 + /* It may be addressed to a child carp iface */ + if (ifp->if_type != IFT_CARP && + !SRPL_EMPTY_LOCKED(&ifp->if_carp) && + carp_input(ifp, ml, m)) { + /* carp_input has consumed the packet */ + return; } +#endif - if (memcmp(etherbroadcastaddr, eh->ether_dhost, - sizeof(etherbroadcastaddr)) == 0) - m->m_flags |= M_BCAST; - else - m->m_flags |= M_MCAST; - ifp->if_imcasts++; - } + /* It must be multicast if it isn't for us or a child carp */ + if (!ETHER_IS_MULTICAST(eh->ether_dhost)) + goto dropanyway; - /* - * HW vlan tagged packets that were not collected by vlan(4) must - * be dropped now. - */ - if (m->m_flags & M_VLANTAG) { - m_freem(m); - return (1); - } + /* Drop it if it came from us in the first place */ + if (!ISSET(ifp->if_flags, IFF_SIMPLEX) && + memcmp(ac->ac_enaddr, eh->ether_shost, + ETHER_ADDR_LEN) == 0) + goto dropanyway; - /* - * If packet is unicast, make sure it is for us. Drop otherwise. - * This check is required in promiscous mode, and for some hypervisors - * where the MAC filter is 'best effort' only. - */ - if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) { - if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) { - m_freem(m); - return (1); - } + SET(m->m_flags, (memcmp(etherbroadcastaddr, eh->ether_dhost, + ETHER_ADDR_LEN) == 0) ? M_BCAST : M_MCAST); + ifp->if_imcasts++; /* XXX atomic? */ } - etype = ntohs(eh->ether_type); - switch (etype) { case ETHERTYPE_IP: input = ipv4_input; @@ -406,7 +459,7 @@ ether_input(struct ifnet *ifp, struct mb if ((session = pipex_pppoe_lookup_session(m)) != NULL) { pipex_pppoe_input(m, session); - return (1); + return; } } #endif @@ -414,7 +467,7 @@ ether_input(struct ifnet *ifp, struct mb niq_enqueue(&pppoediscinq, m); else niq_enqueue(&pppoeinq, m); - return (1); + return; #endif #ifdef MPLS case ETHERTYPE_MPLS: @@ -428,10 +481,10 @@ ether_input(struct ifnet *ifp, struct mb m_adj(m, sizeof(*eh)); (*input)(ifp, m); - return (1); + return; dropanyway: m_freem(m); - return (1); + return; } /* Index: net/if_gif.c =================================================================== RCS file: /cvs/src/sys/net/if_gif.c,v retrieving revision 1.107 diff -u -p -r1.107 if_gif.c --- net/if_gif.c 9 Jan 2018 15:24:24 -0000 1.107 +++ net/if_gif.c 10 Jan 2018 03:48:08 -0000 @@ -175,55 +175,16 @@ gif_start(struct ifnet *ifp) #if NBPFILTER > 0 if (ifp->if_bpf) { - int offset; - sa_family_t family; - u_int8_t proto; - - /* must decapsulate outer header for bpf */ - switch (sc->gif_psrc->sa_family) { - case AF_INET: - offset = sizeof(struct ip); - proto = mtod(m, struct ip *)->ip_p; - break; -#ifdef INET6 - case AF_INET6: - offset = sizeof(struct ip6_hdr); - proto = mtod(m, struct ip6_hdr *)->ip6_nxt; - break; -#endif - default: - proto = 0; - break; - } - switch (proto) { - case IPPROTO_IPV4: - family = AF_INET; - break; - case IPPROTO_IPV6: - family = AF_INET6; - break; - case IPPROTO_ETHERIP: - family = AF_LINK; - offset += sizeof(struct etherip_header); - break; - case IPPROTO_MPLS: - family = AF_MPLS; - break; - default: - offset = 0; - family = sc->gif_psrc->sa_family; - break; - } - m->m_data += offset; - m->m_len -= offset; - m->m_pkthdr.len -= offset; - bpf_mtap_af(ifp->if_bpf, family, m, BPF_DIRECTION_OUT); - m->m_data -= offset; - m->m_len += offset; - m->m_pkthdr.len += offset; + bpf_mtap_af(ifp->if_bpf, m->m_pkthdr.ph_family, m, + BPF_DIRECTION_OUT); } #endif + if (gif_encap(ifp, &m, m->m_pkthdr.ph_family) != 0) { + m_freem(m); + continue; + } + /* XXX we should cache the outgoing route */ switch (sc->gif_psrc->sa_family) { @@ -294,9 +255,7 @@ gif_output(struct ifnet *ifp, struct mbu goto end; } - error = gif_encap(ifp, &m, dst->sa_family); - if (error) - goto end; + m->m_pkthdr.ph_family = dst->sa_family; error = if_enqueue(ifp, m); Index: net/if_mpw.c =================================================================== RCS file: /cvs/src/sys/net/if_mpw.c,v retrieving revision 1.23 diff -u -p -r1.23 if_mpw.c --- net/if_mpw.c 9 Jan 2018 15:24:24 -0000 1.23 +++ net/if_mpw.c 10 Jan 2018 03:48:08 -0000 @@ -45,7 +45,8 @@ #endif struct mpw_softc { - struct ifnet sc_if; + struct arpcom sc_ac; +#define sc_if sc_ac.ac_if struct ifaddr sc_ifa; struct sockaddr_mpls sc_smpls; /* Local label */ @@ -87,30 +88,17 @@ mpw_clone_create(struct if_clone *ifc, i ifp = &sc->sc_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "mpw%d", unit); ifp->if_softc = sc; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_POINTOPOINT; ifp->if_xflags = IFXF_CLONED; ifp->if_ioctl = mpw_ioctl; - ifp->if_output = mpw_output; ifp->if_start = mpw_start; - ifp->if_type = IFT_MPLSTUNNEL; - ifp->if_hdrlen = ETHER_HDR_LEN; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); if_attach(ifp); - if_alloc_sadl(ifp); + ether_ifattach(ifp); - sc->sc_ifa.ifa_ifp = ifp; - sc->sc_ifa.ifa_addr = sdltosa(ifp->if_sadl); sc->sc_smpls.smpls_len = sizeof(sc->sc_smpls); sc->sc_smpls.smpls_family = AF_MPLS; - if_ih_insert(ifp, mpw_input, NULL); - -#if NBPFILTER > 0 - bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN); -#endif /* NBFILTER */ - return (0); } @@ -119,15 +107,12 @@ mpw_clone_destroy(struct ifnet *ifp) { struct mpw_softc *sc = ifp->if_softc; - ifp->if_flags &= ~IFF_RUNNING; - if (sc->sc_smpls.smpls_label) { rt_ifa_del(&sc->sc_ifa, RTF_MPLS, smplstosa(&sc->sc_smpls)); } - if_ih_remove(ifp, mpw_input, NULL); - + ether_ifdetach(ifp); if_detach(ifp); free(sc, M_DEVBUF, sizeof(*sc)); @@ -135,17 +120,9 @@ mpw_clone_destroy(struct ifnet *ifp) } int -mpw_input(struct ifnet *ifp, struct mbuf *m, void *cookie) -{ - /* Don't have local broadcast. */ - m_freem(m); - return (1); -} - -int mpw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { - struct ifreq *ifr = (struct ifreq *) data; + struct ifreq *ifr = (struct ifreq *)data; struct mpw_softc *sc = ifp->if_softc; struct sockaddr_in *sin; struct sockaddr_in *sin_nexthop; @@ -250,111 +227,13 @@ mpw_ioctl(struct ifnet *ifp, u_long cmd, break; default: - error = ENOTTY; + error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; } return (error); } -int -mpw_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, - struct rtentry *rt) -{ - struct mpw_softc *sc = ifp->if_softc; - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); - struct ether_header *eh, ehc; - struct shim_hdr *shim; - - if (sc->sc_type == IMR_TYPE_NONE) { - m_freem(m); - return (EHOSTUNREACH); - } - - if (sc->sc_flags & IMR_FLAG_CONTROLWORD) { - shim = mtod(m, struct shim_hdr *); - m_adj(m, MPLS_HDRLEN); - - /* - * The first 4 bits identifies that this packet is a - * control word. If the control word is configured and - * we received an IP datagram we shall drop it. - */ - if (shim->shim_label & CW_ZERO_MASK) { - ifp->if_ierrors++; - m_freem(m); - return (EINVAL); - } - - /* We don't support fragmentation just yet. */ - if (shim->shim_label & CW_FRAG_MASK) { - ifp->if_ierrors++; - m_freem(m); - return (EINVAL); - } - } - - if (sc->sc_type == IMR_TYPE_ETHERNET_TAGGED) { - m_copydata(m, 0, sizeof(ehc), (caddr_t) &ehc); - m_adj(m, ETHER_HDR_LEN); - - /* Ethernet tagged expects at least 2 VLANs */ - if (ntohs(ehc.ether_type) != ETHERTYPE_QINQ) { - ifp->if_ierrors++; - m_freem(m); - return (EINVAL); - } - - /* Remove dummy VLAN and update ethertype */ - if (EVL_VLANOFTAG(*mtod(m, uint16_t *)) == 0) { - m_adj(m, EVL_ENCAPLEN); - ehc.ether_type = htons(ETHERTYPE_VLAN); - } - - M_PREPEND(m, sizeof(*eh), M_NOWAIT); - if (m == NULL) - return (ENOMEM); - - eh = mtod(m, struct ether_header *); - memcpy(eh, &ehc, sizeof(*eh)); - } - - ml_enqueue(&ml, m); - if_input(ifp, &ml); - - return (0); -} - -#if NVLAN > 0 -extern void vlan_start(struct ifqueue *); - -/* - * This routine handles VLAN tag reinsertion in packets flowing through - * the pseudowire. Also it does the necessary modifications to the VLANs - * to respect the RFC. - */ -struct mbuf * -mpw_vlan_handle(struct mbuf *m, struct mpw_softc *sc) -{ - struct ifnet *ifp; - struct ifvlan *ifv; - - uint16_t type = ETHERTYPE_QINQ; - uint16_t tag = 0; - - ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp != NULL && ifp->if_qstart == vlan_start && - ISSET(ifp->if_flags, IFF_RUNNING)) { - ifv = ifp->if_softc; - type = ifv->ifv_type; - tag = ifv->ifv_tag; - } - if_put(ifp); - - return (vlan_inject(m, type, tag)); -} -#endif /* NVLAN */ - void mpw_start(struct ifnet *ifp) { @@ -397,22 +276,8 @@ mpw_start(struct ifnet *ifp) bpf_mtap(sc->sc_if.if_bpf, m, BPF_DIRECTION_OUT); #endif /* NBPFILTER */ - if (sc->sc_type == IMR_TYPE_ETHERNET_TAGGED) { - #if NVLAN > 0 - m = mpw_vlan_handle(m, sc); - if (m == NULL) { - ifp->if_oerrors++; - continue; - } - #else - /* Ethernet tagged doesn't work without VLANs'*/ - m_freem(m); - continue; - #endif /* NVLAN */ - } - if (sc->sc_flags & IMR_FLAG_CONTROLWORD) { - M_PREPEND(m, sizeof(*shim), M_NOWAIT); + m = m_prepend(m, sizeof(*shim), M_NOWAIT); if (m == NULL) continue; @@ -420,7 +285,7 @@ mpw_start(struct ifnet *ifp) memset(shim, 0, sizeof(*shim)); } - M_PREPEND(m, sizeof(*shim), M_NOWAIT); + m = m_prepend(m, sizeof(*shim), M_NOWAIT); if (m == NULL) continue; Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.88 diff -u -p -r1.88 if_var.h --- net/if_var.h 8 Jan 2018 23:05:21 -0000 1.88 +++ net/if_var.h 10 Jan 2018 03:48:08 -0000 @@ -134,7 +134,7 @@ struct ifnet { /* and the entries */ caddr_t if_mcast6; /* used by IPv6 multicast code */ caddr_t if_pf_kif; /* pf interface abstraction */ union { - caddr_t carp_s; /* carp structure (used by !carp ifs) */ + struct srpl carp_s; /* carp if list (used by !carp ifs) */ struct ifnet *carp_d; /* ptr to carpdev (used by carp ifs) */ } if_carp_ptr; #define if_carp if_carp_ptr.carp_s Index: net/if_vlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vlan.c,v retrieving revision 1.175 diff -u -p -r1.175 if_vlan.c --- net/if_vlan.c 9 Jan 2018 15:24:24 -0000 1.175 +++ net/if_vlan.c 10 Jan 2018 03:48:08 -0000 @@ -84,7 +84,7 @@ void vlanattach(int count); int vlan_clone_create(struct if_clone *, int); int vlan_clone_destroy(struct ifnet *); -int vlan_input(struct ifnet *, struct mbuf *, void *); +void vlan_input(struct ifnet *, struct mbuf_list *, struct mbuf *); void vlan_start(struct ifqueue *ifq); int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); @@ -325,11 +325,8 @@ vlan_inject(struct mbuf *m, uint16_t typ return (m); } -/* - * vlan_input() returns 1 if it has consumed the packet, 0 otherwise. - */ -int -vlan_input(struct ifnet *ifp0, struct mbuf *m, void *cookie) +void +vlan_input(struct ifnet *ifp0, struct mbuf_list *ml, struct mbuf *m) { struct ifvlan *ifv; struct ether_vlan_header *evl; @@ -337,28 +334,23 @@ vlan_input(struct ifnet *ifp0, struct mb SRPL_HEAD(, ifvlan) *tagh, *list; struct srp_ref sr; u_int tag; - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); u_int16_t etype; - eh = mtod(m, struct ether_header *); - etype = ntohs(eh->ether_type); - if (m->m_flags & M_VLANTAG) { etype = ETHERTYPE_VLAN; tagh = vlan_tagh; - } else if ((etype == ETHERTYPE_VLAN) || (etype == ETHERTYPE_QINQ)) { + } else { + etype = ntohs(eh->ether_type); if (m->m_len < sizeof(*evl) && (m = m_pullup(m, sizeof(*evl))) == NULL) { ifp0->if_ierrors++; - return (1); + return; } evl = mtod(m, struct ether_vlan_header *); m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag); + etype = ntohs(evl->evl_encap_proto); tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh; - } else { - /* Skip non-VLAN packets. */ - return (0); } /* From now on ether_vtag is fine */ @@ -376,15 +368,11 @@ vlan_input(struct ifnet *ifp0, struct mb break; } - if (ifv == NULL) { + if (ifv == NULL || !ISSET(ifv->ifv_if.if_flags, IFF_RUNNING)) { ifp0->if_noproto++; goto drop; } - if ((ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) != - (IFF_UP|IFF_RUNNING)) - goto drop; - /* * Having found a valid vlan interface corresponding to * the given source interface and vlan tag, remove the @@ -393,20 +381,19 @@ vlan_input(struct ifnet *ifp0, struct mb if (m->m_flags & M_VLANTAG) { m->m_flags &= ~M_VLANTAG; } else { + eh = mtod(m, struct ether_header *); eh->ether_type = evl->evl_proto; memmove((char *)eh + EVL_ENCAPLEN, eh, sizeof(*eh)); m_adj(m, EVL_ENCAPLEN); } - ml_enqueue(&ml, m); - if_input(&ifv->ifv_if, &ml); + ether_enqueue(&ifv->ifv_if, ml, m); SRPL_LEAVE(&sr); - return (1); + return; drop: SRPL_LEAVE(&sr); m_freem(m); - return (1); } int @@ -430,8 +417,6 @@ vlan_parent_up(struct ifvlan *ifv, struc vlan_multi_apply(ifv, ifp0, SIOCADDMULTI); - if_ih_insert(ifp0, vlan_input, NULL); - return (0); } @@ -549,7 +534,6 @@ vlan_down(struct ifvlan *ifv) ifp0 = if_get(ifv->ifv_ifp0); if (ifp0 != NULL) { - if_ih_remove(ifp0, vlan_input, NULL); if (ISSET(ifv->ifv_flags, IFVF_PROMISC)) ifpromisc(ifp0, 0); vlan_multi_apply(ifv, ifp0, SIOCDELMULTI); Index: net/if_vlan_var.h =================================================================== RCS file: /cvs/src/sys/net/if_vlan_var.h,v retrieving revision 1.37 diff -u -p -r1.37 if_vlan_var.h --- net/if_vlan_var.h 24 Jan 2017 10:08:30 -0000 1.37 +++ net/if_vlan_var.h 10 Jan 2018 03:48:08 -0000 @@ -85,6 +85,7 @@ struct ifvlan { #define IFVF_LLADDR 0x02 /* don't inherit the parents mac */ struct mbuf *vlan_inject(struct mbuf *, uint16_t, uint16_t); +void vlan_input(struct ifnet *, struct mbuf_list *, struct mbuf *); #endif /* _KERNEL */ #endif /* _NET_IF_VLAN_VAR_H_ */ Index: netinet/if_ether.h =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.h,v retrieving revision 1.73 diff -u -p -r1.73 if_ether.h --- netinet/if_ether.h 29 Nov 2016 10:09:57 -0000 1.73 +++ netinet/if_ether.h 10 Jan 2018 03:48:08 -0000 @@ -240,6 +240,7 @@ void ether_ifattach(struct ifnet *); void ether_ifdetach(struct ifnet *); int ether_ioctl(struct ifnet *, struct arpcom *, u_long, caddr_t); int ether_input(struct ifnet *, struct mbuf *, void *); +void ether_enqueue(struct ifnet *, struct mbuf_list *, struct mbuf *); int ether_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); void ether_rtrequest(struct ifnet *, int, struct rtentry *); Index: netinet/ip_carp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.321 diff -u -p -r1.321 ip_carp.c --- netinet/ip_carp.c 9 Jan 2018 15:24:24 -0000 1.321 +++ netinet/ip_carp.c 10 Jan 2018 03:48:08 -0000 @@ -188,10 +188,6 @@ struct cpumem *carpcounters; int carp_send_all_recur = 0; -struct carp_if { - struct srpl vhif_vrs; -}; - #define CARP_LOG(l, sc, s) \ do { \ if (carp_opts[CARPCTL_LOG] >= l) { \ @@ -211,7 +207,6 @@ 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 ifnet *, struct mbuf *, void *); void carp_proto_input_c(struct ifnet *, struct mbuf *, struct carp_header *, int, sa_family_t); int carp_proto_input_if(struct ifnet *, struct mbuf **, int *, int); @@ -231,7 +226,7 @@ void carp_timer_down(void *); void carp_master_down(struct carp_vhost_entry *); int carp_ioctl(struct ifnet *, u_long, caddr_t); int carp_vhids_ioctl(struct carp_softc *, struct carpreq *); -int carp_check_dup_vhids(struct carp_softc *, struct carp_if *, +int carp_check_dup_vhids(struct carp_softc *, struct srpl *, struct carpreq *); void carp_ifgroup_ioctl(struct ifnet *, u_long, caddr_t); void carp_ifgattr_ioctl(struct ifnet *, u_long, caddr_t); @@ -454,8 +449,7 @@ carp_proto_input_if(struct ifnet *ifp, s ismulti = IN_MULTICAST(ip->ip_dst.s_addr); /* check if received on a valid carp interface */ - if (!(ifp->if_type == IFT_CARP || - (ifp->if_type != IFT_CARP && !ismulti && ifp->if_carp != NULL))) { + if (ifp->if_type != IFT_CARP) { carpstat_inc(carps_badif); CARP_LOG(LOG_INFO, sc, ("packet received on non-carp interface: %s", @@ -596,15 +590,15 @@ carp_proto_input_c(struct ifnet *ifp, st struct carp_softc *sc; struct carp_vhost_entry *vhe; struct timeval sc_tv, ch_tv; - struct carp_if *cif; + struct srpl *cif; if (ifp->if_type == IFT_CARP) - cif = (struct carp_if *)ifp->if_carpdev->if_carp; + cif = &ifp->if_carpdev->if_carp; else - cif = (struct carp_if *)ifp->if_carp; + cif = &ifp->if_carp; - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs + carp_vhosts */ - SRPL_FOREACH_LOCKED(sc, &cif->vhif_vrs, sc_list) { + KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ + SRPL_FOREACH_LOCKED(sc, cif, sc_list) { if (af == AF_INET && ismulti != IN_MULTICAST(sc->sc_peer.s_addr)) continue; @@ -909,7 +903,7 @@ void carpdetach(struct carp_softc *sc) { struct ifnet *ifp0; - struct carp_if *cif; + struct srpl *cif; carp_del_all_timeouts(sc); @@ -927,23 +921,16 @@ carpdetach(struct carp_softc *sc) if (ifp0 == NULL) return; - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs */ - - cif = (struct carp_if *)ifp0->if_carp; + KERNEL_ASSERT_LOCKED(); /* touching if_carp */ - /* Restore previous input handler. */ - if_ih_remove(ifp0, carp_input, cif); + cif = &ifp0->if_carp; if (sc->lh_cookie != NULL) hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie); - SRPL_REMOVE_LOCKED(&carp_sc_rc, &cif->vhif_vrs, sc, - carp_softc, sc_list); - if (SRPL_EMPTY_LOCKED(&cif->vhif_vrs)) { + SRPL_REMOVE_LOCKED(&carp_sc_rc, cif, sc, carp_softc, sc_list); + if (SRPL_EMPTY_LOCKED(cif)) ifpromisc(ifp0, 0); - ifp0->if_carp = NULL; - free(cif, M_IFADDR, sizeof(*cif)); - } sc->sc_carpdev = NULL; } @@ -952,11 +939,11 @@ void carp_ifdetach(struct ifnet *ifp0) { struct carp_softc *sc, *nextsc; - struct carp_if *cif = (struct carp_if *)ifp0->if_carp; + struct srpl *cif = &ifp0->if_carp; - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs */ + KERNEL_ASSERT_LOCKED(); /* touching if_carp */ - SRPL_FOREACH_SAFE_LOCKED(sc, &cif->vhif_vrs, sc_list, nextsc) + SRPL_FOREACH_SAFE_LOCKED(sc, cif, sc_list, nextsc) carpdetach(sc); /* this can free cif */ } @@ -1001,20 +988,20 @@ void carp_send_ad_all(void) { struct ifnet *ifp0; - struct carp_if *cif; + struct srpl *cif; struct carp_softc *vh; - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs */ + KERNEL_ASSERT_LOCKED(); /* touching if_carp */ if (carp_send_all_recur > 0) return; ++carp_send_all_recur; TAILQ_FOREACH(ifp0, &ifnet, if_list) { - if (ifp0->if_carp == NULL || ifp0->if_type == IFT_CARP) + if (ifp0->if_type == IFT_CARP) continue; - cif = (struct carp_if *)ifp0->if_carp; - SRPL_FOREACH_LOCKED(vh, &cif->vhif_vrs, sc_list) { + cif = &ifp0->if_carp; + SRPL_FOREACH_LOCKED(vh, cif, sc_list) { if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) { carp_vhe_send_ad_all(vh); @@ -1349,15 +1336,15 @@ carp_iamatch(struct ifnet *ifp) return (match); } -struct ifnet * -carp_ourether(void *v, u_int8_t *ena) +int +carp_ourether(struct ifnet *ifp0, u_int8_t *ena) { - struct carp_if *cif = (struct carp_if *)v; + struct srpl *cif = &ifp0->if_carp; struct carp_softc *vh; - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs + carp_vhosts */ + KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ - SRPL_FOREACH_LOCKED(vh, &cif->vhif_vrs, sc_list) { + SRPL_FOREACH_LOCKED(vh, cif, sc_list) { struct carp_vhost_entry *vhe; if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) @@ -1365,9 +1352,9 @@ carp_ourether(void *v, u_int8_t *ena) vhe = SRPL_FIRST_LOCKED(&vh->carp_vhosts); if ((vhe->state == MASTER || vh->sc_balancing >= CARP_BAL_IP) && !memcmp(ena, vh->sc_ac.ac_enaddr, ETHER_ADDR_LEN)) - return (&vh->sc_if); + return (1); } - return (NULL); + return (0); } int @@ -1386,89 +1373,56 @@ carp_vhe_match(struct carp_softc *sc, ui } int -carp_input(struct ifnet *ifp0, struct mbuf *m, void *cookie) +carp_input(struct ifnet *ifp0, struct mbuf_list *ml, struct mbuf *m) { struct ether_header *eh; - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); - struct carp_if *cif; + struct srpl *cif; struct carp_softc *sc; + struct ifnet *ifp; struct srp_ref sr; -#if NVLAN > 0 - /* - * If the underlying interface removed the VLAN header itself, - * it's not for us. - */ - if (ISSET(m->m_flags, M_VLANTAG)) - return (0); -#endif - eh = mtod(m, struct ether_header *); - cif = (struct carp_if *)cookie; - KASSERT(cif == (struct carp_if *)ifp0->if_carp); + cif = &ifp0->if_carp; - SRPL_FOREACH(sc, &sr, &cif->vhif_vrs, sc_list) { - if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != - (IFF_UP|IFF_RUNNING)) + SRPL_FOREACH(sc, &sr, cif, sc_list) { + ifp = &sc->sc_if; + + if (!ISSET(ifp->if_flags, IFF_RUNNING)) continue; if (carp_vhe_match(sc, eh->ether_dhost)) { - /* - * These packets look like layer 2 multicast but they - * are unicast at layer 3. With help of the tag the - * mbuf's M_MCAST flag can be removed by carp_lsdrop() - * after we have passed layer 2. - */ - if (sc->sc_balancing == CARP_BAL_IP) { - struct m_tag *mtag; - mtag = m_tag_get(PACKET_TAG_CARP_BAL_IP, 0, - M_NOWAIT); - if (mtag == NULL) { - m_freem(m); - goto out; - } - m_tag_prepend(m, mtag); - } - break; + ether_enqueue(ifp, ml, m); + SRPL_LEAVE(&sr); + return (1); } } + SRPL_LEAVE(&sr); - if (sc == NULL) { - SRPL_LEAVE(&sr); - - if (!ETHER_IS_MULTICAST(eh->ether_dhost)) - return (0); - + if (ETHER_IS_MULTICAST(eh->ether_dhost)) { /* * XXX Should really check the list of multicast addresses * for each CARP interface _before_ copying. */ - SRPL_FOREACH(sc, &sr, &cif->vhif_vrs, sc_list) { + SRPL_FOREACH(sc, &sr, cif, sc_list) { struct mbuf *m0; - if (!(sc->sc_if.if_flags & IFF_UP)) + ifp = &sc->sc_if; + + if (!ISSET(ifp->if_flags, IFF_RUNNING)) continue; + /* carp_vhe_match? */ + m0 = m_dup_pkt(m, ETHER_ALIGN, M_DONTWAIT); if (m0 == NULL) continue; - ml_init(&ml); - ml_enqueue(&ml, m0); - - if_input(&sc->sc_if, &ml); + ether_enqueue(ifp, ml, m0); } SRPL_LEAVE(&sr); - - return (0); } - ml_enqueue(&ml, m); - if_input(&sc->sc_if, &ml); -out: - SRPL_LEAVE(&sr); - - return (1); + return (0); } int @@ -1692,12 +1646,12 @@ carp_multicast_cleanup(struct carp_softc int carp_set_ifp(struct carp_softc *sc, struct ifnet *ifp0) { - struct carp_if *cif, *ncif = NULL; + struct srpl *cif; struct carp_softc *vr, *last = NULL, *after = NULL; - int myself = 0, error = 0; + int myself = 0, error; KASSERT(ifp0 != sc->sc_carpdev); - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs */ + KERNEL_ASSERT_LOCKED(); /* touching if_carp */ if ((ifp0->if_flags & IFF_MULTICAST) == 0) return (EADDRNOTAVAIL); @@ -1705,34 +1659,22 @@ carp_set_ifp(struct carp_softc *sc, stru if (ifp0->if_type == IFT_CARP) return (EINVAL); - if (ifp0->if_carp == NULL) { - ncif = malloc(sizeof(*cif), M_IFADDR, M_NOWAIT|M_ZERO); - if (ncif == NULL) - return (ENOBUFS); - if ((error = ifpromisc(ifp0, 1))) { - free(ncif, M_IFADDR, sizeof(*ncif)); + cif = &ifp0->if_carp; + if (SRPL_EMPTY_LOCKED(cif)) { + error = ifpromisc(ifp0, 1); + if (error) return (error); - } - - SRPL_INIT(&ncif->vhif_vrs); - } else { - cif = (struct carp_if *)ifp0->if_carp; - if (carp_check_dup_vhids(sc, cif, NULL)) - return (EINVAL); - } + } else if (carp_check_dup_vhids(sc, cif, NULL)) + return (EINVAL); /* detach from old interface */ if (sc->sc_carpdev != NULL) carpdetach(sc); - /* attach carp interface to physical interface */ - if (ncif != NULL) - ifp0->if_carp = (caddr_t)ncif; sc->sc_carpdev = ifp0; sc->sc_if.if_capabilities = ifp0->if_capabilities & IFCAP_CSUM_MASK; - cif = (struct carp_if *)ifp0->if_carp; - SRPL_FOREACH_LOCKED(vr, &cif->vhif_vrs, sc_list) { + SRPL_FOREACH_LOCKED(vr, cif, sc_list) { struct carp_vhost_entry *vrhead, *schead; last = vr; @@ -1748,7 +1690,7 @@ carp_set_ifp(struct carp_softc *sc, stru if (!myself) { /* We're trying to keep things in order */ if (last == NULL) { - SRPL_INSERT_HEAD_LOCKED(&carp_sc_rc, &cif->vhif_vrs, + SRPL_INSERT_HEAD_LOCKED(&carp_sc_rc, cif, sc, sc_list); } else if (after == NULL) { SRPL_INSERT_AFTER_LOCKED(&carp_sc_rc, last, @@ -1765,9 +1707,6 @@ carp_set_ifp(struct carp_softc *sc, stru sc->lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1, carp_carpdev_state, ifp0); - /* Change input handler of the physical interface. */ - if_ih_insert(ifp0, carp_input, cif); - carp_carpdev_state(ifp0); return (0); @@ -2171,16 +2110,16 @@ carp_ioctl(struct ifnet *ifp, u_long cmd } int -carp_check_dup_vhids(struct carp_softc *sc, struct carp_if *cif, +carp_check_dup_vhids(struct carp_softc *sc, struct srpl *cif, struct carpreq *carpr) { struct carp_softc *vr; struct carp_vhost_entry *vhe, *vhe0; int i; - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs + carp_vhosts */ + KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ - SRPL_FOREACH_LOCKED(vr, &cif->vhif_vrs, sc_list) { + SRPL_FOREACH_LOCKED(vr, cif, sc_list) { if (vr == sc) continue; SRPL_FOREACH_LOCKED(vhe, &vr->carp_vhosts, vhost_entries) { @@ -2217,8 +2156,7 @@ carp_vhids_ioctl(struct carp_softc *sc, taken_vhids[carpr->carpr_vhids[i]] = 1; if (sc->sc_carpdev) { - struct carp_if *cif; - cif = (struct carp_if *)sc->sc_carpdev->if_carp; + struct srpl *cif = & sc->sc_carpdev->if_carp; if (carp_check_dup_vhids(sc, cif, carpr)) return (EINVAL); } @@ -2483,18 +2421,18 @@ carp_group_demote_count(struct carp_soft void carp_carpdev_state(void *v) { - struct carp_if *cif; + struct srpl *cif; struct carp_softc *sc; struct ifnet *ifp0 = v; if (ifp0->if_type == IFT_CARP) return; - cif = (struct carp_if *)ifp0->if_carp; + cif = &ifp0->if_carp; - KERNEL_ASSERT_LOCKED(); /* touching vhif_vrs */ + KERNEL_ASSERT_LOCKED(); /* touching if_carp */ - SRPL_FOREACH_LOCKED(sc, &cif->vhif_vrs, sc_list) { + SRPL_FOREACH_LOCKED(sc, cif, sc_list) { int suppressed = sc->sc_suppress; if (sc->sc_carpdev->if_link_state == LINK_STATE_DOWN || Index: netinet/ip_carp.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.h,v retrieving revision 1.44 diff -u -p -r1.44 ip_carp.h --- netinet/ip_carp.h 23 Nov 2017 13:32:25 -0000 1.44 +++ netinet/ip_carp.h 10 Jan 2018 03:48:08 -0000 @@ -194,12 +194,13 @@ carpstat_inc(enum carpstat_counters c) } void carp_ifdetach (struct ifnet *); +int carp_input(struct ifnet *, struct mbuf_list *, struct mbuf *); int carp_proto_input(struct mbuf **, int *, int, int); void carp_carpdev_state(void *); void carp_group_demote_adj(struct ifnet *, int, char *); int carp6_proto_input(struct mbuf **, int *, int, int); int carp_iamatch(struct ifnet *); -struct ifnet *carp_ourether(void *, u_int8_t *); +int carp_ourether(struct ifnet *, u_int8_t *); int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int carp_sysctl(int *, u_int, void *, size_t *, void *, size_t);