/* * Transmitter has finished outputting some stuff; * remember to call sc->sc_start later at splsoftnet. */ void ppp_restart(struct ppp_softc *sc) { crit_enter(); sc->sc_flags &= ~SC_TBUSY; schednetisr(NETISR_PPP); crit_exit(); }
/* * Transmitter has finished outputting some stuff; * remember to call sc->sc_start later at splsoftnet. */ void ppp_restart(struct ppp_softc *sc) { int s = splnet(); sc->sc_flags &= ~SC_TBUSY; schednetisr(NETISR_PPP); splx(s); }
/* * icintr() */ static void icintr (device_t dev, int event, char *ptr) { struct ic_softc *sc = (struct ic_softc *)device_get_softc(dev); int unit = device_get_unit(dev); int s, len; struct mbuf *top; s = splhigh(); switch (event) { case INTR_GENERAL: case INTR_START: sc->ic_cp = sc->ic_ifbuf; sc->ic_xfercnt = 0; break; case INTR_STOP: /* if any error occured during transfert, * drop the packet */ if (sc->ic_iferrs) goto err; if ((len = sc->ic_xfercnt) == 0) break; /* ignore */ if (len <= ICHDRLEN) goto err; len -= ICHDRLEN; sc->ic_if.if_ipackets ++; sc->ic_if.if_ibytes += len; BPF_TAP(&sc->ic_if, sc->ic_ifbuf, len + ICHDRLEN); top = m_devget(sc->ic_ifbuf + ICHDRLEN, len, 0, &sc->ic_if, 0); if (top) { if (IF_HANDOFF(&ipintrq, top, NULL)) schednetisr(NETISR_IP); } break; err: printf("ic%d: errors (%d)!\n", unit, sc->ic_iferrs); sc->ic_iferrs = 0; /* reset error count */ sc->ic_if.if_ierrors ++; break; case INTR_RECEIVE: if (sc->ic_xfercnt >= sc->ic_if.if_mtu+ICHDRLEN) { sc->ic_iferrs ++; } else { *sc->ic_cp++ = *ptr; sc->ic_xfercnt ++; } break; case INTR_NOACK: /* xfer terminated by master */ break; case INTR_TRANSMIT: *ptr = 0xff; /* XXX */ break; case INTR_ERROR: sc->ic_iferrs ++; break; default: panic("%s: unknown event (%d)!", __func__, event); } splx(s); return; }
static void lostart(struct ifnet *ifp) { for (;;) { pktqueue_t *pktq = NULL; struct ifqueue *ifq = NULL; struct mbuf *m; size_t pktlen; uint32_t af; int s, isr = 0; IFQ_DEQUEUE(&ifp->if_snd, m); if (m == NULL) return; af = *(mtod(m, uint32_t *)); m_adj(m, sizeof(uint32_t)); switch (af) { #ifdef INET case AF_INET: pktq = ip_pktq; break; #endif #ifdef INET6 case AF_INET6: m->m_flags |= M_LOOP; pktq = ip6_pktq; break; #endif #ifdef IPX case AF_IPX: ifq = &ipxintrq; isr = NETISR_IPX; break; #endif #ifdef NETATALK case AF_APPLETALK: ifq = &atintrq2; isr = NETISR_ATALK; break; #endif default: printf("%s: can't handle af%d\n", ifp->if_xname, af); m_freem(m); return; } pktlen = m->m_pkthdr.len; s = splnet(); if (__predict_true(pktq)) { if (__predict_false(pktq_enqueue(pktq, m, 0))) { m_freem(m); splx(s); return; } ifp->if_ipackets++; ifp->if_ibytes += pktlen; splx(s); continue; } if (IF_QFULL(ifq)) { IF_DROP(ifq); splx(s); m_freem(m); return; } IF_ENQUEUE(ifq, m); schednetisr(isr); ifp->if_ipackets++; ifp->if_ibytes += pktlen; splx(s); } }
int looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct rtentry *rt) { pktqueue_t *pktq = NULL; struct ifqueue *ifq = NULL; int s, isr = -1; int csum_flags; size_t pktlen; MCLAIM(m, ifp->if_mowner); KASSERT(KERNEL_LOCKED_P()); if ((m->m_flags & M_PKTHDR) == 0) panic("looutput: no header mbuf"); if (ifp->if_flags & IFF_LOOPBACK) bpf_mtap_af(ifp, dst->sa_family, m); m->m_pkthdr.rcvif = ifp; if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { m_freem(m); return (rt->rt_flags & RTF_BLACKHOLE ? 0 : rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); } pktlen = m->m_pkthdr.len; ifp->if_opackets++; ifp->if_obytes += pktlen; #ifdef ALTQ /* * ALTQ on the loopback interface is just for debugging. It's * used only for loopback interfaces, not for a simplex interface. */ if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) && ifp->if_start == lostart) { struct altq_pktattr pktattr; int error; /* * If the queueing discipline needs packet classification, * do it before prepending the link headers. */ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); if (m == NULL) return (ENOBUFS); *(mtod(m, uint32_t *)) = dst->sa_family; s = splnet(); IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error); (*ifp->if_start)(ifp); splx(s); return (error); } #endif /* ALTQ */ m_tag_delete_nonpersistent(m); #ifdef MPLS if (rt != NULL && rt_gettag(rt) != NULL && rt_gettag(rt)->sa_family == AF_MPLS && (m->m_flags & (M_MCAST | M_BCAST)) == 0) { union mpls_shim msh; msh.s_addr = MPLS_GETSADDR(rt); if (msh.shim.label != MPLS_LABEL_IMPLNULL) { ifq = &mplsintrq; isr = NETISR_MPLS; } } if (isr != NETISR_MPLS) #endif switch (dst->sa_family) { #ifdef INET case AF_INET: csum_flags = m->m_pkthdr.csum_flags; KASSERT((csum_flags & ~(M_CSUM_IPv4|M_CSUM_UDPv4)) == 0); if (csum_flags != 0 && IN_LOOPBACK_NEED_CHECKSUM(csum_flags)) { ip_undefer_csum(m, 0, csum_flags); } m->m_pkthdr.csum_flags = 0; pktq = ip_pktq; break; #endif #ifdef INET6 case AF_INET6: csum_flags = m->m_pkthdr.csum_flags; KASSERT((csum_flags & ~M_CSUM_UDPv6) == 0); if (csum_flags != 0 && IN6_LOOPBACK_NEED_CHECKSUM(csum_flags)) { ip6_undefer_csum(m, 0, csum_flags); } m->m_pkthdr.csum_flags = 0; m->m_flags |= M_LOOP; pktq = ip6_pktq; break; #endif #ifdef IPX case AF_IPX: ifq = &ipxintrq; isr = NETISR_IPX; break; #endif #ifdef NETATALK case AF_APPLETALK: ifq = &atintrq2; isr = NETISR_ATALK; break; #endif default: printf("%s: can't handle af%d\n", ifp->if_xname, dst->sa_family); m_freem(m); return (EAFNOSUPPORT); } s = splnet(); if (__predict_true(pktq)) { int error = 0; if (__predict_true(pktq_enqueue(pktq, m, 0))) { ifp->if_ipackets++; ifp->if_ibytes += pktlen; } else { m_freem(m); error = ENOBUFS; } splx(s); return error; } if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(ifq, m); schednetisr(isr); ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; splx(s); return (0); }
static void lostart(struct ifnet *ifp) { struct ifqueue *ifq; struct mbuf *m; uint32_t af; int s, isr; for (;;) { IFQ_DEQUEUE(&ifp->if_snd, m); if (m == NULL) return; af = *(mtod(m, uint32_t *)); m_adj(m, sizeof(uint32_t)); switch (af) { #ifdef INET case AF_INET: ifq = &ipintrq; isr = NETISR_IP; break; #endif #ifdef INET6 case AF_INET6: m->m_flags |= M_LOOP; ifq = &ip6intrq; isr = NETISR_IPV6; break; #endif #ifdef IPX case AF_IPX: ifq = &ipxintrq; isr = NETISR_IPX; break; #endif #ifdef ISO case AF_ISO: ifq = &clnlintrq; isr = NETISR_ISO; break; #endif #ifdef NETATALK case AF_APPLETALK: ifq = &atintrq2; isr = NETISR_ATALK; break; #endif default: printf("%s: can't handle af%d\n", ifp->if_xname, af); m_freem(m); return; } s = splnet(); if (IF_QFULL(ifq)) { IF_DROP(ifq); splx(s); m_freem(m); return; } IF_ENQUEUE(ifq, m); schednetisr(isr); ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; splx(s); } }
static int gre_input2(struct mbuf *m ,int hlen, u_char proto) { struct greip *gip = mtod(m, struct greip *); int s; struct ifqueue *ifq; struct gre_softc *sc; u_short flags; if ((sc = gre_lookup(m, proto)) == NULL) { /* No matching tunnel or tunnel is down. */ return (0); } sc->sc_if.if_ipackets++; sc->sc_if.if_ibytes += m->m_pkthdr.len; switch (proto) { case IPPROTO_GRE: hlen += sizeof (struct gre_h); /* process GRE flags as packet can be of variable len */ flags = ntohs(gip->gi_flags); /* Checksum & Offset are present */ if ((flags & GRE_CP) | (flags & GRE_RP)) hlen += 4; /* We don't support routing fields (variable length) */ if (flags & GRE_RP) return(0); if (flags & GRE_KP) hlen += 4; if (flags & GRE_SP) hlen +=4; switch (ntohs(gip->gi_ptype)) { /* ethertypes */ case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */ case WCCP_PROTOCOL_TYPE: /* we are in ip_input */ ifq = &ipintrq; break; #ifdef NS case ETHERTYPE_NS: ifq = &nsintrq; schednetisr(NETISR_NS); break; #endif #ifdef NETATALK case ETHERTYPE_ATALK: ifq = &atintrq1; schednetisr(NETISR_ATALK); break; #endif case ETHERTYPE_IPV6: /* FALLTHROUGH */ default: /* others not yet supported */ return(0); } break; default: /* others not yet supported */ return(0); } m->m_data += hlen; m->m_len -= hlen; m->m_pkthdr.len -= hlen; if (sc->sc_if.if_bpf) { struct mbuf m0; u_int32_t af = AF_INET; m0.m_next = m; m0.m_len = 4; m0.m_data = (char *)⁡ BPF_MTAP(&(sc->sc_if), &m0); } m->m_pkthdr.rcvif = &sc->sc_if; s = splnet(); /* possible */ if (_IF_QFULL(ifq)) { _IF_DROP(ifq); m_freem(m); } else { IF_ENQUEUE(ifq,m); } splx(s); return(1); /* packet is done, no further processing needed */ }
int looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct rtentry *rt) { int s, isr; struct ifqueue *ifq = NULL; MCLAIM(m, ifp->if_mowner); if ((m->m_flags & M_PKTHDR) == 0) panic("looutput: no header mbuf"); #if NBPFILTER > 0 if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK)) bpf_mtap_af(ifp->if_bpf, dst->sa_family, m); #endif m->m_pkthdr.rcvif = ifp; if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { m_freem(m); return (rt->rt_flags & RTF_BLACKHOLE ? 0 : rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); } ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; #ifdef ALTQ /* * ALTQ on the loopback interface is just for debugging. It's * used only for loopback interfaces, not for a simplex interface. */ if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) && ifp->if_start == lostart) { struct altq_pktattr pktattr; int error; /* * If the queueing discipline needs packet classification, * do it before prepending the link headers. */ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT); if (m == NULL) return (ENOBUFS); *(mtod(m, uint32_t *)) = dst->sa_family; s = splnet(); IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error); (*ifp->if_start)(ifp); splx(s); return (error); } #endif /* ALTQ */ m_tag_delete_nonpersistent(m); switch (dst->sa_family) { #ifdef INET case AF_INET: ifq = &ipintrq; isr = NETISR_IP; break; #endif #ifdef INET6 case AF_INET6: m->m_flags |= M_LOOP; ifq = &ip6intrq; isr = NETISR_IPV6; break; #endif #ifdef ISO case AF_ISO: ifq = &clnlintrq; isr = NETISR_ISO; break; #endif #ifdef IPX case AF_IPX: ifq = &ipxintrq; isr = NETISR_IPX; break; #endif #ifdef NETATALK case AF_APPLETALK: ifq = &atintrq2; isr = NETISR_ATALK; break; #endif default: #if !defined(T2EX) || defined(DEBUG) printf("%s: can't handle af%d\n", ifp->if_xname, dst->sa_family); #endif m_freem(m); return (EAFNOSUPPORT); } s = splnet(); if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(ifq, m); schednetisr(isr); ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; splx(s); return (0); }
int looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { int s, isr; struct ifqueue *ifq = 0; if ((m->m_flags & M_PKTHDR) == 0) panic("looutput: no header mbuf"); #if NBPFILTER > 0 /* * only send packets to bpf if they are real loopback packets; * looutput() is also called for SIMPLEX interfaces to duplicate * packets for local use. But don't dup them to bpf. */ if (ifp->if_bpf && (ifp->if_flags & IFF_LOOPBACK)) bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT); #endif m->m_pkthdr.rcvif = ifp; if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { m_freem(m); return (rt->rt_flags & RTF_BLACKHOLE ? 0 : rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); } ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; switch (dst->sa_family) { #ifdef INET case AF_INET: ifq = &ipintrq; isr = NETISR_IP; break; #endif #ifdef INET6 case AF_INET6: ifq = &ip6intrq; isr = NETISR_IPV6; break; #endif /* INET6 */ #ifdef MPLS case AF_MPLS: ifq = &mplsintrq; isr = NETISR_MPLS; break; #endif /* MPLS */ default: printf("%s: can't handle af%d\n", ifp->if_xname, dst->sa_family); m_freem(m); return (EAFNOSUPPORT); } s = splnet(); if (IF_QFULL(ifq)) { IF_DROP(ifq); m_freem(m); splx(s); return (ENOBUFS); } IF_ENQUEUE(ifq, m); schednetisr(isr); ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; splx(s); return (0); }