size_t ipv6cp_QueueLen(struct ipv6cp *ipv6cp) { struct mqueue *q; size_t result; result = 0; for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) result += q->len; return result; }
/* * Enqueue a packet of the given address family. Nothing will make it * down to the physical link level 'till ncp_FillPhysicalQueues() is used. */ void ncp_Enqueue(struct ncp *ncp, int af, unsigned pri, char *ptr, int count) { #ifndef NOINET6 struct ipv6cp *ipv6cp = &ncp->ipv6cp; #endif struct ipcp *ipcp = &ncp->ipcp; struct mbuf *bp; /* * We allocate an extra 6 bytes, four at the front and two at the end. * This is an optimisation so that we need to do less work in * m_prepend() in acf_LayerPush() and proto_LayerPush() and * appending in hdlc_LayerPush(). */ switch (af) { case AF_INET: if (pri >= IPCP_QUEUES(ipcp)) { log_Printf(LogERROR, "Can't store in ip queue %u\n", pri); break; } bp = m_get(count + 6, MB_IPOUT); bp->m_offset += 4; bp->m_len -= 6; memcpy(MBUF_CTOP(bp), ptr, count); m_enqueue(ipcp->Queue + pri, bp); break; #ifndef NOINET6 case AF_INET6: if (pri >= IPV6CP_QUEUES(ipcp)) { log_Printf(LogERROR, "Can't store in ipv6 queue %u\n", pri); break; } bp = m_get(count + 6, MB_IPOUT); bp->m_offset += 4; bp->m_len -= 6; memcpy(MBUF_CTOP(bp), ptr, count); m_enqueue(ipv6cp->Queue + pri, bp); break; #endif default: log_Printf(LogERROR, "Can't enqueue protocol family %d\n", af); } }
int ipv6cp_PushPacket(struct ipv6cp *ipv6cp, struct link *l) { struct bundle *bundle = ipv6cp->fsm.bundle; struct mqueue *queue; struct mbuf *bp; int m_len; u_int32_t secs = 0; unsigned alivesecs = 0; if (ipv6cp->fsm.state != ST_OPENED) return 0; /* * If ccp is not open but is required, do nothing. */ if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); return 0; } queue = ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp) - 1; do { if (queue->top) { bp = m_dequeue(queue); bp = mbuf_Read(bp, &secs, sizeof secs); bp = m_pullup(bp); m_len = m_length(bp); if (!FilterCheck(MBUF_CTOP(bp), AF_INET6, &bundle->filter.alive, &alivesecs)) { if (secs == 0) secs = alivesecs; bundle_StartIdleTimer(bundle, secs); } link_PushPacket(l, bp, bundle, 0, PROTO_IPV6); ipv6cp_AddOutOctets(ipv6cp, m_len); return 1; } } while (queue-- != ipv6cp->Queue); return 0; }
/* * Ditch all queued packets. This is usually done after our choked timer * has fired - which happens because we couldn't send any traffic over * any links for some time. */ void ncp_DeleteQueues(struct ncp *ncp) { #ifndef NOINET6 struct ipv6cp *ipv6cp = &ncp->ipv6cp; #endif struct ipcp *ipcp = &ncp->ipcp; struct mp *mp = &ncp->mp; struct mqueue *q; for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) while (q->top) m_freem(m_dequeue(q)); #ifndef NOINET6 for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) while (q->top) m_freem(m_dequeue(q)); #endif link_DeleteQueue(&mp->link); /* Usually empty anyway */ }