Re-implement LQM, this time according to the rfc.
PR: 11293 MFC after: 4 weeks
This commit is contained in:
parent
6e7a069c00
commit
a57095e7f7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=131327
@ -85,14 +85,14 @@ acf_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto)
|
|||||||
/* We expect the packet not to be compressed */
|
/* We expect the packet not to be compressed */
|
||||||
bp = mbuf_Read(bp, cp, 2);
|
bp = mbuf_Read(bp, cp, 2);
|
||||||
if (cp[0] != HDLC_ADDR) {
|
if (cp[0] != HDLC_ADDR) {
|
||||||
p->hdlc.lqm.SaveInErrors++;
|
p->hdlc.lqm.ifInErrors++;
|
||||||
p->hdlc.stats.badaddr++;
|
p->hdlc.stats.badaddr++;
|
||||||
log_Printf(LogDEBUG, "acf_LayerPull: addr 0x%02x\n", cp[0]);
|
log_Printf(LogDEBUG, "acf_LayerPull: addr 0x%02x\n", cp[0]);
|
||||||
m_freem(bp);
|
m_freem(bp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (cp[1] != HDLC_UI) {
|
if (cp[1] != HDLC_UI) {
|
||||||
p->hdlc.lqm.SaveInErrors++;
|
p->hdlc.lqm.ifInErrors++;
|
||||||
p->hdlc.stats.badcommand++;
|
p->hdlc.stats.badcommand++;
|
||||||
log_Printf(LogDEBUG, "acf_LayerPull: control 0x%02x\n", cp[1]);
|
log_Printf(LogDEBUG, "acf_LayerPull: control 0x%02x\n", cp[1]);
|
||||||
m_freem(bp);
|
m_freem(bp);
|
||||||
|
@ -106,6 +106,7 @@ async_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp,
|
|||||||
struct physical *p = link2physical(l);
|
struct physical *p = link2physical(l);
|
||||||
u_char *cp, *sp, *ep;
|
u_char *cp, *sp, *ep;
|
||||||
struct mbuf *wp;
|
struct mbuf *wp;
|
||||||
|
size_t oldcnt;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
if (!p || m_length(bp) > HDLCSIZE) {
|
if (!p || m_length(bp) > HDLCSIZE) {
|
||||||
@ -113,6 +114,8 @@ async_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldcnt = m_length(bp);
|
||||||
|
|
||||||
cp = p->async.xbuff;
|
cp = p->async.xbuff;
|
||||||
ep = cp + HDLCSIZE - 10;
|
ep = cp + HDLCSIZE - 10;
|
||||||
wp = bp;
|
wp = bp;
|
||||||
@ -134,6 +137,7 @@ async_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp,
|
|||||||
m_freem(bp);
|
m_freem(bp);
|
||||||
bp = m_get(cnt, MB_ASYNCOUT);
|
bp = m_get(cnt, MB_ASYNCOUT);
|
||||||
memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt);
|
memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt);
|
||||||
|
bp->priv = cnt - oldcnt;
|
||||||
log_DumpBp(LogASYNC, "Write", bp);
|
log_DumpBp(LogASYNC, "Write", bp);
|
||||||
|
|
||||||
return bp;
|
return bp;
|
||||||
|
@ -318,22 +318,26 @@ hdlc_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp,
|
|||||||
|
|
||||||
log_DumpBp(LogHDLC, "hdlc_LayerPull:", bp);
|
log_DumpBp(LogHDLC, "hdlc_LayerPull:", bp);
|
||||||
|
|
||||||
fcs = hdlc_Fcs(MBUF_CTOP(bp), bp->m_len);
|
bp = m_pullup(bp);
|
||||||
|
len = m_length(bp);
|
||||||
|
fcs = hdlc_Fcs(MBUF_CTOP(bp), len);
|
||||||
|
|
||||||
log_Printf(LogDEBUG, "%s: hdlc_LayerPull: fcs = %04x (%s)\n",
|
log_Printf(LogDEBUG, "%s: hdlc_LayerPull: fcs = %04x (%s)\n",
|
||||||
p->link.name, fcs, (fcs == GOODFCS) ? "good" : "BAD!");
|
p->link.name, fcs, (fcs == GOODFCS) ? "good" : "BAD!");
|
||||||
|
|
||||||
|
p->hdlc.lqm.ifInOctets += len + 1; /* plus 1 flag octet! */
|
||||||
|
|
||||||
if (fcs != GOODFCS) {
|
if (fcs != GOODFCS) {
|
||||||
p->hdlc.lqm.SaveInErrors++;
|
p->hdlc.lqm.ifInErrors++;
|
||||||
p->hdlc.stats.badfcs++;
|
p->hdlc.stats.badfcs++;
|
||||||
m_freem(bp);
|
m_freem(bp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->hdlc.lqm.SaveInOctets += bp->m_len + 1;
|
/* Either done here or by the sync layer */
|
||||||
p->hdlc.lqm.SaveInPackets++;
|
p->hdlc.lqm.lqr.InGoodOctets += len + 1; /* plus 1 flag octet! */
|
||||||
|
p->hdlc.lqm.ifInUniPackets++;
|
||||||
|
|
||||||
len = m_length(bp);
|
|
||||||
if (len < 4) { /* rfc1662 section 4.3 */
|
if (len < 4) { /* rfc1662 section 4.3 */
|
||||||
m_freem(bp);
|
m_freem(bp);
|
||||||
bp = NULL;
|
bp = NULL;
|
||||||
|
@ -73,16 +73,21 @@ struct hdlc {
|
|||||||
struct pppTimer timer; /* When to send */
|
struct pppTimer timer; /* When to send */
|
||||||
int method; /* bit-mask for LQM_* from lqr.h */
|
int method; /* bit-mask for LQM_* from lqr.h */
|
||||||
|
|
||||||
u_int32_t OutPackets; /* Packets sent by me */
|
u_int32_t ifOutUniPackets; /* Packets sent by me */
|
||||||
u_int32_t OutOctets; /* Octets sent by me */
|
u_int32_t ifOutOctets; /* Octets sent by me */
|
||||||
u_int32_t SaveInPackets; /* Packets received from peer */
|
u_int32_t ifInUniPackets; /* Packets received from peer */
|
||||||
u_int32_t SaveInDiscards; /* Discards */
|
u_int32_t ifInDiscards; /* Discards */
|
||||||
u_int32_t SaveInErrors; /* Errors */
|
u_int32_t ifInErrors; /* Errors */
|
||||||
u_int32_t SaveInOctets; /* Octets received from peer */
|
u_int32_t ifInOctets; /* Octets received from peer (unused) */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
u_int32_t InGoodOctets; /* Good octets received from peer */
|
||||||
u_int32_t OutLQRs; /* LQRs sent by me */
|
u_int32_t OutLQRs; /* LQRs sent by me */
|
||||||
u_int32_t SaveInLQRs; /* LQRs received from peer */
|
u_int32_t InLQRs; /* LQRs received from peer */
|
||||||
|
|
||||||
|
struct lqrsavedata Save; /* Our last LQR */
|
||||||
|
struct lqrsavedata prevSave; /* Our last-but-one LQR (analysis) */
|
||||||
|
|
||||||
struct lqrdata peer; /* Last LQR from peer */
|
struct lqrdata peer; /* Last LQR from peer */
|
||||||
int peer_timeout; /* peers max lqr timeout */
|
int peer_timeout; /* peers max lqr timeout */
|
||||||
int resent; /* Resent last packet `resent' times */
|
int resent; /* Resent last packet `resent' times */
|
||||||
|
@ -147,6 +147,34 @@ link_QueueBytes(struct link *l)
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
link_PendingLowPriorityData(struct link *l, size_t *pkts, size_t *octets)
|
||||||
|
{
|
||||||
|
struct mqueue *queue, *highest;
|
||||||
|
struct mbuf *m;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is all rfc1989 stuff... because our LQR packet is going to bypass
|
||||||
|
* everything that's not in the highest priority queue, we must be able to
|
||||||
|
* subtract that data from our outgoing packet/octet counts. However,
|
||||||
|
* we've already async-encoded our data at this point, but the async
|
||||||
|
* encodings MUSTn't be a part of the LQR-reported payload :( So, we have
|
||||||
|
* the async layer record how much it's padded the packet in the mbuf's
|
||||||
|
* priv field, and when we calculate our outgoing LQR values we subtract
|
||||||
|
* this value for each packet from the octet count sent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
highest = LINK_HIGHQ(l);
|
||||||
|
*pkts = *octets = 0;
|
||||||
|
for (queue = l->Queue; queue < highest; queue++) {
|
||||||
|
len = queue->len;
|
||||||
|
*pkts += len;
|
||||||
|
for (m = queue->top; len--; m = m->m_nextpkt)
|
||||||
|
*octets += m_length(m) - m->priv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct mbuf *
|
struct mbuf *
|
||||||
link_Dequeue(struct link *l)
|
link_Dequeue(struct link *l)
|
||||||
{
|
{
|
||||||
@ -232,6 +260,7 @@ link_PushPacket(struct link *l, struct mbuf *bp, struct bundle *b, int pri,
|
|||||||
if(pri < 0 || pri >= LINK_QUEUES(l))
|
if(pri < 0 || pri >= LINK_QUEUES(l))
|
||||||
pri = 0;
|
pri = 0;
|
||||||
|
|
||||||
|
bp->priv = 0; /* Adjusted by the async layer ! */
|
||||||
for (layer = l->nlayers; layer && bp; layer--)
|
for (layer = l->nlayers; layer && bp; layer--)
|
||||||
if (l->layer[layer - 1]->push != NULL)
|
if (l->layer[layer - 1]->push != NULL)
|
||||||
bp = (*l->layer[layer - 1]->push)(b, l, bp, pri, &proto);
|
bp = (*l->layer[layer - 1]->push)(b, l, bp, pri, &proto);
|
||||||
@ -360,7 +389,7 @@ Despatch(struct bundle *bundle, struct link *l, struct mbuf *bp, u_short proto)
|
|||||||
bp = m_pullup(proto_Prepend(bp, proto, 0, 0));
|
bp = m_pullup(proto_Prepend(bp, proto, 0, 0));
|
||||||
lcp_SendProtoRej(&l->lcp, MBUF_CTOP(bp), bp->m_len);
|
lcp_SendProtoRej(&l->lcp, MBUF_CTOP(bp), bp->m_len);
|
||||||
if (p) {
|
if (p) {
|
||||||
p->hdlc.lqm.SaveInDiscards++;
|
p->hdlc.lqm.ifInDiscards++;
|
||||||
p->hdlc.stats.unknownproto++;
|
p->hdlc.stats.unknownproto++;
|
||||||
}
|
}
|
||||||
m_freem(bp);
|
m_freem(bp);
|
||||||
|
@ -65,6 +65,7 @@ extern void link_SequenceQueue(struct link *);
|
|||||||
extern void link_DeleteQueue(struct link *);
|
extern void link_DeleteQueue(struct link *);
|
||||||
extern size_t link_QueueLen(struct link *);
|
extern size_t link_QueueLen(struct link *);
|
||||||
extern size_t link_QueueBytes(struct link *);
|
extern size_t link_QueueBytes(struct link *);
|
||||||
|
extern void link_PendingLowPriorityData(struct link *, size_t *, size_t *);
|
||||||
extern struct mbuf *link_Dequeue(struct link *);
|
extern struct mbuf *link_Dequeue(struct link *);
|
||||||
|
|
||||||
extern void link_PushPacket(struct link *, struct mbuf *, struct bundle *,
|
extern void link_PushPacket(struct link *, struct mbuf *, struct bundle *,
|
||||||
|
@ -146,6 +146,14 @@ SendLqrData(struct lcp *lcp)
|
|||||||
bp = m_get(sizeof(struct lqrdata) + extra, MB_LQROUT);
|
bp = m_get(sizeof(struct lqrdata) + extra, MB_LQROUT);
|
||||||
bp->m_len -= extra;
|
bp->m_len -= extra;
|
||||||
bp->m_offset += extra;
|
bp->m_offset += extra;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send on the highest priority queue. We send garbage - the real data
|
||||||
|
* is written by lqr_LayerPush() where we know how to fill in all the
|
||||||
|
* fields. Note, lqr_LayerPush() ``knows'' that we're pushing onto the
|
||||||
|
* highest priority queue, and factors out packet & octet values from
|
||||||
|
* other queues!
|
||||||
|
*/
|
||||||
link_PushPacket(lcp->fsm.link, bp, lcp->fsm.bundle,
|
link_PushPacket(lcp->fsm.link, bp, lcp->fsm.bundle,
|
||||||
LINK_QUEUES(lcp->fsm.link) - 1, PROTO_LQR);
|
LINK_QUEUES(lcp->fsm.link) - 1, PROTO_LQR);
|
||||||
}
|
}
|
||||||
@ -202,8 +210,6 @@ lqr_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->hdlc.lqm.lqr.SaveInLQRs++;
|
|
||||||
|
|
||||||
len = m_length(bp);
|
len = m_length(bp);
|
||||||
if (len != sizeof(struct lqrdata))
|
if (len != sizeof(struct lqrdata))
|
||||||
log_Printf(LogWARN, "lqr_Input: Got packet size %d, expecting %ld !\n",
|
log_Printf(LogWARN, "lqr_Input: Got packet size %d, expecting %ld !\n",
|
||||||
@ -213,7 +219,6 @@ lqr_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
|||||||
lcp_SendProtoRej(lcp, MBUF_CTOP(bp), bp->m_len);
|
lcp_SendProtoRej(lcp, MBUF_CTOP(bp), bp->m_len);
|
||||||
} else {
|
} else {
|
||||||
struct lqrdata *lqr;
|
struct lqrdata *lqr;
|
||||||
u_int32_t lastLQR;
|
|
||||||
|
|
||||||
bp = m_pullup(bp);
|
bp = m_pullup(bp);
|
||||||
lqr = (struct lqrdata *)MBUF_CTOP(bp);
|
lqr = (struct lqrdata *)MBUF_CTOP(bp);
|
||||||
@ -222,27 +227,32 @@ lqr_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
|||||||
" expecting 0x%08lx\n",
|
" expecting 0x%08lx\n",
|
||||||
(u_long)ntohl(lqr->MagicNumber), (u_long)lcp->his_magic);
|
(u_long)ntohl(lqr->MagicNumber), (u_long)lcp->his_magic);
|
||||||
else {
|
else {
|
||||||
/*
|
struct lqrdata lastlqr;
|
||||||
* Remember our PeerInLQRs, then convert byte order and save
|
|
||||||
*/
|
|
||||||
lastLQR = p->hdlc.lqm.lqr.peer.PeerInLQRs;
|
|
||||||
|
|
||||||
|
memcpy(&lastlqr, &p->hdlc.lqm.lqr.peer, sizeof lastlqr);
|
||||||
lqr_ChangeOrder(lqr, &p->hdlc.lqm.lqr.peer);
|
lqr_ChangeOrder(lqr, &p->hdlc.lqm.lqr.peer);
|
||||||
lqr_Dump(l->name, "Input", &p->hdlc.lqm.lqr.peer);
|
lqr_Dump(l->name, "Input", &p->hdlc.lqm.lqr.peer);
|
||||||
/* we have received an LQR from peer */
|
/* we have received an LQR from our peer */
|
||||||
p->hdlc.lqm.lqr.resent = 0;
|
p->hdlc.lqm.lqr.resent = 0;
|
||||||
|
|
||||||
|
/* Snapshot our state when the LQR packet was received */
|
||||||
|
memcpy(&p->hdlc.lqm.lqr.prevSave, &p->hdlc.lqm.lqr.Save,
|
||||||
|
sizeof p->hdlc.lqm.lqr.prevSave);
|
||||||
|
p->hdlc.lqm.lqr.Save.InLQRs = ++p->hdlc.lqm.lqr.InLQRs;
|
||||||
|
p->hdlc.lqm.lqr.Save.InPackets = p->hdlc.lqm.ifInUniPackets;
|
||||||
|
p->hdlc.lqm.lqr.Save.InDiscards = p->hdlc.lqm.ifInDiscards;
|
||||||
|
p->hdlc.lqm.lqr.Save.InErrors = p->hdlc.lqm.ifInErrors;
|
||||||
|
p->hdlc.lqm.lqr.Save.InOctets = p->hdlc.lqm.lqr.InGoodOctets;
|
||||||
|
|
||||||
|
lqr_Analyse(&p->hdlc, &lastlqr, &p->hdlc.lqm.lqr.peer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate an LQR response if we're not running an LQR timer OR
|
* Generate an LQR response if we're not running an LQR timer OR
|
||||||
* two successive LQR's PeerInLQRs are the same OR we're not going to
|
* two successive LQR's PeerInLQRs are the same.
|
||||||
* send our next one before the peers max timeout.
|
|
||||||
*/
|
*/
|
||||||
if (p->hdlc.lqm.timer.load == 0 ||
|
if (p->hdlc.lqm.timer.load == 0 || !(p->hdlc.lqm.method & LQM_LQR) ||
|
||||||
!(p->hdlc.lqm.method & LQM_LQR) ||
|
(lastlqr.PeerInLQRs &&
|
||||||
(lastLQR && lastLQR == p->hdlc.lqm.lqr.peer.PeerInLQRs) ||
|
lastlqr.PeerInLQRs == p->hdlc.lqm.lqr.peer.PeerInLQRs))
|
||||||
(p->hdlc.lqm.lqr.peer_timeout &&
|
|
||||||
p->hdlc.lqm.timer.rest * 100 / SECTICKS >
|
|
||||||
p->hdlc.lqm.lqr.peer_timeout))
|
|
||||||
SendLqrData(lcp);
|
SendLqrData(lcp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,12 +365,57 @@ lqr_Dump(const char *link, const char *message, const struct lqrdata *lqr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lqr_Analyse(const struct hdlc *hdlc, const struct lqrdata *oldlqr,
|
||||||
|
const struct lqrdata *newlqr)
|
||||||
|
{
|
||||||
|
u_int32_t LQRs, transitLQRs, pkts, octets, disc, err;
|
||||||
|
|
||||||
|
if (!newlqr->PeerInLQRs) /* No analysis possible yet! */
|
||||||
|
return;
|
||||||
|
|
||||||
|
log_Printf(LogLQM, "Analysis:\n");
|
||||||
|
|
||||||
|
LQRs = (newlqr->LastOutLQRs - oldlqr->LastOutLQRs) -
|
||||||
|
(newlqr->PeerInLQRs - oldlqr->PeerInLQRs);
|
||||||
|
transitLQRs = hdlc->lqm.lqr.OutLQRs - newlqr->LastOutLQRs;
|
||||||
|
pkts = (newlqr->LastOutPackets - oldlqr->LastOutPackets) -
|
||||||
|
(newlqr->PeerInPackets - oldlqr->PeerInPackets);
|
||||||
|
octets = (newlqr->LastOutOctets - oldlqr->LastOutOctets) -
|
||||||
|
(newlqr->PeerInOctets - oldlqr->PeerInOctets);
|
||||||
|
log_Printf(LogLQM, " Outbound lossage: %d LQR%s (%d en route), %d packet%s,"
|
||||||
|
" %d octet%s\n", (int)LQRs, LQRs == 1 ? "" : "s", (int)transitLQRs,
|
||||||
|
(int)pkts, pkts == 1 ? "" : "s",
|
||||||
|
(int)octets, octets == 1 ? "" : "s");
|
||||||
|
|
||||||
|
pkts = (newlqr->PeerOutPackets - oldlqr->PeerOutPackets) -
|
||||||
|
(hdlc->lqm.lqr.Save.InPackets - hdlc->lqm.lqr.prevSave.InPackets);
|
||||||
|
octets = (newlqr->PeerOutOctets - oldlqr->PeerOutOctets) -
|
||||||
|
(hdlc->lqm.lqr.Save.InOctets - hdlc->lqm.lqr.prevSave.InOctets);
|
||||||
|
log_Printf(LogLQM, " Inbound lossage: %d packet%s, %d octet%s\n",
|
||||||
|
(int)pkts, pkts == 1 ? "" : "s",
|
||||||
|
(int)octets, octets == 1 ? "" : "s");
|
||||||
|
|
||||||
|
disc = newlqr->PeerInDiscards - oldlqr->PeerInDiscards;
|
||||||
|
err = newlqr->PeerInErrors - oldlqr->PeerInErrors;
|
||||||
|
if (disc && err)
|
||||||
|
log_Printf(LogLQM, " Likely due to both peer congestion"
|
||||||
|
" and physical errors\n");
|
||||||
|
else if (disc)
|
||||||
|
log_Printf(LogLQM, " Likely due to peer congestion\n");
|
||||||
|
else if (err)
|
||||||
|
log_Printf(LogLQM, " Likely due to physical errors\n");
|
||||||
|
else if (pkts)
|
||||||
|
log_Printf(LogLQM, " Likely due to transport "
|
||||||
|
"congestion\n");
|
||||||
|
}
|
||||||
|
|
||||||
static struct mbuf *
|
static struct mbuf *
|
||||||
lqr_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp,
|
lqr_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp,
|
||||||
int pri, u_short *proto)
|
int pri, u_short *proto)
|
||||||
{
|
{
|
||||||
struct physical *p = link2physical(l);
|
struct physical *p = link2physical(l);
|
||||||
int len;
|
int len, layer, extra_async_bytes;
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
/* Oops - can't happen :-] */
|
/* Oops - can't happen :-] */
|
||||||
@ -368,7 +423,10 @@ lqr_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
bp = m_pullup(bp);
|
||||||
|
len = m_length(bp);
|
||||||
|
|
||||||
|
/*-
|
||||||
* From rfc1989:
|
* From rfc1989:
|
||||||
*
|
*
|
||||||
* All octets which are included in the FCS calculation MUST be counted,
|
* All octets which are included in the FCS calculation MUST be counted,
|
||||||
@ -377,50 +435,72 @@ lqr_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp,
|
|||||||
* MUST be counted. All other octets (such as additional flag
|
* MUST be counted. All other octets (such as additional flag
|
||||||
* sequences, and escape bits or octets) MUST NOT be counted.
|
* sequences, and escape bits or octets) MUST NOT be counted.
|
||||||
*
|
*
|
||||||
* As we're stacked before the HDLC layer (otherwise HDLC wouldn't be
|
* As we're stacked higher than the HDLC layer (otherwise HDLC wouldn't be
|
||||||
* able to calculate the FCS), we must not forget about these additional
|
* able to calculate the FCS), we must not forget about these additional
|
||||||
* bytes when we're asynchronous.
|
* bytes when we're asynchronous.
|
||||||
*
|
*
|
||||||
* We're also expecting to be stacked *before* the proto and acf layers.
|
* We're also expecting to be stacked *before* the likes of the proto and
|
||||||
* If we were after these, it makes alignment more of a pain, and we
|
* acf layers (to avoid alignment issues), so deal with this too.
|
||||||
* don't do LQR without these layers.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bp = m_pullup(bp);
|
extra_async_bytes = 0;
|
||||||
len = m_length(bp);
|
p->hdlc.lqm.ifOutUniPackets++;
|
||||||
|
p->hdlc.lqm.ifOutOctets += len + 1; /* plus 1 flag octet! */
|
||||||
if (!physical_IsSync(p))
|
for (layer = 0; layer < l->nlayers; layer++)
|
||||||
p->hdlc.lqm.OutOctets += hdlc_WrapperOctets(&l->lcp, *proto);
|
switch (l->layer[layer]->type) {
|
||||||
p->hdlc.lqm.OutOctets += acf_WrapperOctets(&l->lcp, *proto) +
|
case LAYER_ACF:
|
||||||
proto_WrapperOctets(&l->lcp, *proto) + len + 1;
|
p->hdlc.lqm.ifOutOctets += acf_WrapperOctets(&l->lcp, *proto);
|
||||||
p->hdlc.lqm.OutPackets++;
|
break;
|
||||||
|
case LAYER_ASYNC:
|
||||||
|
/* Not included - see rfc1989 */
|
||||||
|
break;
|
||||||
|
case LAYER_HDLC:
|
||||||
|
p->hdlc.lqm.ifOutOctets += hdlc_WrapperOctets(&l->lcp, *proto);
|
||||||
|
break;
|
||||||
|
case LAYER_LQR:
|
||||||
|
layer = l->nlayers;
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO:
|
||||||
|
p->hdlc.lqm.ifOutOctets += proto_WrapperOctets(&l->lcp, *proto);
|
||||||
|
break;
|
||||||
|
case LAYER_SYNC:
|
||||||
|
/* Nothing to add on */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_Printf(LogWARN, "Oops, don't know how to do octets for %s layer\n",
|
||||||
|
l->layer[layer]->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (*proto == PROTO_LQR) {
|
if (*proto == PROTO_LQR) {
|
||||||
/* Overwrite the entire packet (created in SendLqrData()) */
|
/* Overwrite the entire packet (created in SendLqrData()) */
|
||||||
struct lqrdata lqr;
|
struct lqrdata lqr;
|
||||||
|
size_t pending_pkts, pending_octets;
|
||||||
|
|
||||||
|
p->hdlc.lqm.lqr.OutLQRs++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to compensate for the fact that we're pushing our data
|
||||||
|
* onto the highest priority queue by factoring out packet & octet
|
||||||
|
* values from other queues!
|
||||||
|
*/
|
||||||
|
link_PendingLowPriorityData(l, &pending_pkts, &pending_octets);
|
||||||
|
|
||||||
|
memset(&lqr, '\0', sizeof lqr);
|
||||||
lqr.MagicNumber = p->link.lcp.want_magic;
|
lqr.MagicNumber = p->link.lcp.want_magic;
|
||||||
lqr.LastOutLQRs = p->hdlc.lqm.lqr.peer.PeerOutLQRs;
|
lqr.LastOutLQRs = p->hdlc.lqm.lqr.peer.PeerOutLQRs;
|
||||||
lqr.LastOutPackets = p->hdlc.lqm.lqr.peer.PeerOutPackets;
|
lqr.LastOutPackets = p->hdlc.lqm.lqr.peer.PeerOutPackets;
|
||||||
lqr.LastOutOctets = p->hdlc.lqm.lqr.peer.PeerOutOctets;
|
lqr.LastOutOctets = p->hdlc.lqm.lqr.peer.PeerOutOctets;
|
||||||
lqr.PeerInLQRs = p->hdlc.lqm.lqr.SaveInLQRs;
|
lqr.PeerInLQRs = p->hdlc.lqm.lqr.Save.InLQRs;
|
||||||
lqr.PeerInPackets = p->hdlc.lqm.SaveInPackets;
|
lqr.PeerInPackets = p->hdlc.lqm.lqr.Save.InPackets;
|
||||||
lqr.PeerInDiscards = p->hdlc.lqm.SaveInDiscards;
|
lqr.PeerInDiscards = p->hdlc.lqm.lqr.Save.InDiscards;
|
||||||
lqr.PeerInErrors = p->hdlc.lqm.SaveInErrors;
|
lqr.PeerInErrors = p->hdlc.lqm.lqr.Save.InErrors;
|
||||||
lqr.PeerInOctets = p->hdlc.lqm.SaveInOctets;
|
lqr.PeerInOctets = p->hdlc.lqm.lqr.Save.InOctets;
|
||||||
lqr.PeerOutPackets = p->hdlc.lqm.OutPackets;
|
|
||||||
lqr.PeerOutOctets = p->hdlc.lqm.OutOctets;
|
|
||||||
if (p->hdlc.lqm.lqr.peer.LastOutLQRs == p->hdlc.lqm.lqr.OutLQRs) {
|
|
||||||
/*
|
|
||||||
* only increment if it's the first time or we've got a reply
|
|
||||||
* from the last one
|
|
||||||
*/
|
|
||||||
lqr.PeerOutLQRs = ++p->hdlc.lqm.lqr.OutLQRs;
|
|
||||||
lqr_Dump(l->name, "Output", &lqr);
|
|
||||||
} else {
|
|
||||||
lqr.PeerOutLQRs = p->hdlc.lqm.lqr.OutLQRs;
|
lqr.PeerOutLQRs = p->hdlc.lqm.lqr.OutLQRs;
|
||||||
lqr_Dump(l->name, "Output (again)", &lqr);
|
lqr.PeerOutPackets = p->hdlc.lqm.ifOutUniPackets - pending_pkts;
|
||||||
}
|
/* Don't forget our ``flag'' octets.... */
|
||||||
|
lqr.PeerOutOctets = p->hdlc.lqm.ifOutOctets - pending_octets - pending_pkts;
|
||||||
|
lqr_Dump(l->name, "Output", &lqr);
|
||||||
lqr_ChangeOrder(&lqr, (struct lqrdata *)MBUF_CTOP(bp));
|
lqr_ChangeOrder(&lqr, (struct lqrdata *)MBUF_CTOP(bp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,9 +511,11 @@ static struct mbuf *
|
|||||||
lqr_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto)
|
lqr_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We mark the packet as ours but don't do anything 'till it's dispatched
|
* This is the ``Rx'' process from rfc1989, although a part of it is
|
||||||
* to lqr_Input()
|
* actually performed by sync_LayerPull() & hdlc_LayerPull() so that
|
||||||
|
* our octet counts are correct.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (*proto == PROTO_LQR)
|
if (*proto == PROTO_LQR)
|
||||||
m_settype(bp, MB_LQRIN);
|
m_settype(bp, MB_LQRIN);
|
||||||
return bp;
|
return bp;
|
||||||
|
@ -46,6 +46,14 @@ struct lqrdata {
|
|||||||
u_int32_t PeerOutOctets; /* Peers OutOctets (hdlc.h) */
|
u_int32_t PeerOutOctets; /* Peers OutOctets (hdlc.h) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct lqrsavedata { /* Saved on receipt of an LQR */
|
||||||
|
u_int32_t InLQRs; /* From ifInLQRs */
|
||||||
|
u_int32_t InPackets; /* From ifInPackets */
|
||||||
|
u_int32_t InDiscards; /* From ifInDiscards */
|
||||||
|
u_int32_t InErrors; /* From ifInErrors */
|
||||||
|
u_int32_t InOctets; /* From InGoodOctets ! */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We support LQR and ECHO as LQM method
|
* We support LQR and ECHO as LQM method
|
||||||
*/
|
*/
|
||||||
@ -56,10 +64,13 @@ struct mbuf;
|
|||||||
struct physical;
|
struct physical;
|
||||||
struct lcp;
|
struct lcp;
|
||||||
struct fsm;
|
struct fsm;
|
||||||
|
struct hdlc;
|
||||||
struct link;
|
struct link;
|
||||||
struct bundle;
|
struct bundle;
|
||||||
|
|
||||||
extern void lqr_Dump(const char *, const char *, const struct lqrdata *);
|
extern void lqr_Dump(const char *, const char *, const struct lqrdata *);
|
||||||
|
extern void lqr_Analyse(const struct hdlc *, const struct lqrdata *,
|
||||||
|
const struct lqrdata *);
|
||||||
extern void lqr_ChangeOrder(struct lqrdata *, struct lqrdata *);
|
extern void lqr_ChangeOrder(struct lqrdata *, struct lqrdata *);
|
||||||
extern void lqr_Start(struct lcp *);
|
extern void lqr_Start(struct lcp *);
|
||||||
extern void lqr_reStart(struct lcp *);
|
extern void lqr_reStart(struct lcp *);
|
||||||
|
@ -35,6 +35,7 @@ struct mbuf {
|
|||||||
short m_type; /* MB_* below */
|
short m_type; /* MB_* below */
|
||||||
struct mbuf *m_next; /* link to next mbuf */
|
struct mbuf *m_next; /* link to next mbuf */
|
||||||
struct mbuf *m_nextpkt; /* link to next packet */
|
struct mbuf *m_nextpkt; /* link to next packet */
|
||||||
|
unsigned long priv; /* private data - holds HDLC escape count */
|
||||||
/* buffer space is malloc()d directly after the header */
|
/* buffer space is malloc()d directly after the header */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ sync_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp,
|
|||||||
{
|
{
|
||||||
log_DumpBp(LogSYNC, "Write", bp);
|
log_DumpBp(LogSYNC, "Write", bp);
|
||||||
m_settype(bp, MB_SYNCOUT);
|
m_settype(bp, MB_SYNCOUT);
|
||||||
|
bp->priv = 0;
|
||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ sync_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp,
|
|||||||
u_short *proto)
|
u_short *proto)
|
||||||
{
|
{
|
||||||
struct physical *p = link2physical(l);
|
struct physical *p = link2physical(l);
|
||||||
|
int len;
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
log_Printf(LogERROR, "Can't Pull a sync packet from a logical link\n");
|
log_Printf(LogERROR, "Can't Pull a sync packet from a logical link\n");
|
||||||
@ -69,8 +71,10 @@ sync_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp,
|
|||||||
log_DumpBp(LogSYNC, "Read", bp);
|
log_DumpBp(LogSYNC, "Read", bp);
|
||||||
|
|
||||||
/* Either done here or by the HDLC layer */
|
/* Either done here or by the HDLC layer */
|
||||||
p->hdlc.lqm.SaveInOctets += m_length(bp) + 1;
|
len = m_length(bp);
|
||||||
p->hdlc.lqm.SaveInPackets++;
|
p->hdlc.lqm.ifInOctets += len + 1; /* plus 1 flag octet! */
|
||||||
|
p->hdlc.lqm.lqr.InGoodOctets += len + 1; /* plus 1 flag octet! */
|
||||||
|
p->hdlc.lqm.ifInUniPackets++;
|
||||||
m_settype(bp, MB_SYNCIN);
|
m_settype(bp, MB_SYNCIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user