Apply error and success logic consistently to the function netisr_queue() and
its users. netisr_queue() now returns (0) on success and ERRNO on failure. At the moment ENXIO (netisr queue not functional) and ENOBUFS (netisr queue full) are supported. Previously it would return (1) on success but the return value of IF_HANDOFF() was interpreted wrongly and (0) was actually returned on success. Due to this schednetisr() was never called to kick the scheduling of the isr. However this was masked by other normal packets coming through netisr_dispatch() causing the dequeueing of waiting packets. PR: kern/70988 Found by: MOROHOSHI Akihiko <moro@remus.dti.ne.jp> MFC after: 3 days
This commit is contained in:
parent
3713458b99
commit
3161f583ca
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=134391
@ -480,7 +480,7 @@ fore_recv_drain(fup)
|
||||
/*
|
||||
* Schedule callback
|
||||
*/
|
||||
if (! netisr_queue(NETISR_ATM, mhead)) {
|
||||
if (netisr_queue(NETISR_ATM, mhead)) { /* (0) on success. */
|
||||
fup->fu_stats->st_drv.drv_rv_ifull++;
|
||||
goto free_ent;
|
||||
}
|
||||
|
@ -762,6 +762,5 @@ idt_receive(nicstar_reg_t * idt, struct mbuf * m, int vpi, int vci)
|
||||
/*
|
||||
* Schedule callback
|
||||
*/
|
||||
if (! netisr_queue(NETISR_ATM, m))
|
||||
KB_FREEALL(m);
|
||||
netisr_queue(NETISR_ATM, m); /* mbuf is free'd on failure. */
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ lp_intr (void *arg)
|
||||
if (top) {
|
||||
if (sc->sc_if.if_bpf)
|
||||
lptap(&sc->sc_if, top);
|
||||
netisr_queue(NETISR_IP, top);
|
||||
netisr_queue(NETISR_IP, top); /* mbuf is free'd on failure. */
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
@ -555,7 +555,7 @@ lp_intr (void *arg)
|
||||
if (top) {
|
||||
if (sc->sc_if.if_bpf)
|
||||
lptap(&sc->sc_if, top);
|
||||
netisr_queue(NETISR_IP, top);
|
||||
netisr_queue(NETISR_IP, top); /* mbuf is free'd on failure. */
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
|
@ -881,16 +881,12 @@ ipr_rx_data_rdy(int unit)
|
||||
BPF_MTAP(&sc->sc_if, &mm);
|
||||
}
|
||||
|
||||
if(! netisr_queue(NETISR_IP, m))
|
||||
if(netisr_queue(NETISR_IP, m)) /* (0) on success. */
|
||||
{
|
||||
NDBGL4(L4_IPRDBG, "ipr%d: ipintrq full!", unit);
|
||||
sc->sc_if.if_ierrors++;
|
||||
sc->sc_if.if_iqdrops++;
|
||||
}
|
||||
else
|
||||
{
|
||||
schednetisr(NETISR_IP);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
|
@ -311,7 +311,7 @@ if_simloop(ifp, m, af, hlen)
|
||||
}
|
||||
ifp->if_ipackets++;
|
||||
ifp->if_ibytes += m->m_pkthdr.len;
|
||||
netisr_queue(isr, m);
|
||||
netisr_queue(isr, m); /* mbuf is free'd on failure. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1611,8 +1611,8 @@ ppp_inproc(sc, m)
|
||||
if (isr == -1)
|
||||
rv = IF_HANDOFF(&sc->sc_inq, m, NULL);
|
||||
else
|
||||
rv = netisr_queue(isr, m);
|
||||
if (!rv) {
|
||||
rv = netisr_queue(isr, m); /* (0) on success. */
|
||||
if ((isr == -1 && !rv) || (isr != -1 && rv)) {
|
||||
if (sc->sc_flags & SC_DEBUG)
|
||||
if_printf(ifp, "input queue full\n");
|
||||
ifp->if_iqdrops++;
|
||||
|
@ -960,7 +960,7 @@ slinput(int c, struct tty *tp)
|
||||
m_freem(m);
|
||||
goto newpack;
|
||||
}
|
||||
if (! netisr_queue(NETISR_IP, m)) {
|
||||
if (netisr_queue(NETISR_IP, m)) { /* (0) on success. */
|
||||
sc->sc_if.if_ierrors++;
|
||||
sc->sc_if.if_iqdrops++;
|
||||
}
|
||||
|
@ -715,7 +715,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
|
||||
goto drop;
|
||||
|
||||
/* Check queue. */
|
||||
if (! netisr_queue(isr, m)) {
|
||||
if (netisr_queue(isr, m)) { /* (0) on success. */
|
||||
if (debug)
|
||||
log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n",
|
||||
SPP_ARGS(ifp));
|
||||
|
@ -204,6 +204,8 @@ netisr_dispatch(int num, struct mbuf *m)
|
||||
* Same as above, but always queue.
|
||||
* This is either used in places where we are not confident that
|
||||
* direct dispatch is possible, or where queueing is required.
|
||||
* It returns (0) on success and ERRNO on failure. On failure the
|
||||
* mbuf has been free'd.
|
||||
*/
|
||||
int
|
||||
netisr_queue(int num, struct mbuf *m)
|
||||
@ -216,13 +218,13 @@ netisr_queue(int num, struct mbuf *m)
|
||||
if (ni->ni_queue == NULL) {
|
||||
isrstat.isrs_drop++;
|
||||
m_freem(m);
|
||||
return (1);
|
||||
return (ENXIO);
|
||||
}
|
||||
isrstat.isrs_queued++;
|
||||
if (!IF_HANDOFF(ni->ni_queue, m, NULL))
|
||||
return (0);
|
||||
return (ENOBUFS); /* IF_HANDOFF has free'd the mbuf */
|
||||
schednetisr(num);
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -978,7 +978,7 @@ rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
|
||||
*family = sa ? sa->sa_family : 0;
|
||||
m_tag_prepend(m, tag);
|
||||
}
|
||||
netisr_queue(NETISR_ROUTE, m);
|
||||
netisr_queue(NETISR_ROUTE, m); /* mbuf is free'd on failure. */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -915,7 +915,7 @@ vatmpif_harp_recv_drain(Vatmpif_unit *vup, KBuffer *m,
|
||||
/*
|
||||
* Schedule callback
|
||||
*/
|
||||
if (!netisr_queue(NETISR_ATM, m)) {
|
||||
if ((err = netisr_queue(NETISR_ATM, m))) { /* (0) on success. */
|
||||
/*
|
||||
* queue is full. Unable to pass up to the HARP stack
|
||||
* Update the stats.
|
||||
|
@ -869,7 +869,7 @@ mroute_encap_input(struct mbuf *m, int off)
|
||||
|
||||
m->m_pkthdr.rcvif = last_encap_vif->v_ifp;
|
||||
|
||||
netisr_queue(NETISR_IP, m);
|
||||
netisr_queue(NETISR_IP, m); /* mbuf is free'd on failure. */
|
||||
/*
|
||||
* normally we would need a "schednetisr(NETISR_IP)"
|
||||
* here but we were called by ip_input and it is going
|
||||
|
@ -449,7 +449,7 @@ ah4_input(m, off)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (! netisr_queue(NETISR_IP, m)) {
|
||||
if (netisr_queue(NETISR_IP, m)) { /* (0) on success. */
|
||||
ipsecstat.in_inval++;
|
||||
m = NULL;
|
||||
goto fail;
|
||||
@ -841,7 +841,7 @@ ah6_input(mp, offp, proto)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (! netisr_queue(NETISR_IPV6, m)) {
|
||||
if (netisr_queue(NETISR_IPV6, m)) { /* (0) on success. */
|
||||
ipsec6stat.in_inval++;
|
||||
m = NULL;
|
||||
goto fail;
|
||||
|
@ -389,7 +389,7 @@ esp4_input(m, off)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (! netisr_queue(NETISR_IP, m)) {
|
||||
if (netisr_queue(NETISR_IP, m)) { /* (0) on success. */
|
||||
ipsecstat.in_inval++;
|
||||
m = NULL;
|
||||
goto bad;
|
||||
@ -745,7 +745,7 @@ esp6_input(mp, offp, proto)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (! netisr_queue(NETISR_IPV6, m)) {
|
||||
if (netisr_queue(NETISR_IPV6, m)) { /* (0) on success. */
|
||||
ipsec6stat.in_inval++;
|
||||
m = NULL;
|
||||
goto bad;
|
||||
|
@ -447,13 +447,13 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
|
||||
/*
|
||||
* Re-dispatch via software interrupt.
|
||||
*/
|
||||
if (!netisr_queue(NETISR_IP, m)) {
|
||||
if ((error = netisr_queue(NETISR_IP, m))) {
|
||||
IPSEC_ISTAT(sproto, espstat.esps_qfull, ahstat.ahs_qfull,
|
||||
ipcompstat.ipcomps_qfull);
|
||||
|
||||
DPRINTF(("%s: queue full; proto %u packet dropped\n",
|
||||
__func__, sproto));
|
||||
return ENOBUFS;
|
||||
return error;
|
||||
}
|
||||
return 0;
|
||||
bad:
|
||||
|
@ -376,7 +376,7 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
|
||||
panic("%s: bogus ip version %u", __func__, v>>4);
|
||||
}
|
||||
|
||||
if (!netisr_queue(isr, m)) {
|
||||
if (netisr_queue(isr, m)) { /* (0) on success. */
|
||||
ipipstat.ipips_qfull++;
|
||||
DPRINTF(("%s: packet dropped because of full queue\n",
|
||||
__func__));
|
||||
|
Loading…
Reference in New Issue
Block a user