- Make the sack scoreboard logic use the TAILQ macros. This improves
code readability and facilitates some anticipated optimizations in tcp_sack_option(). - Remove tcp_print_holes() and TCP_SACK_DEBUG. Submitted by: Raja Mukerji. Reviewed by: Mohan Srinivasan, Noritoshi Demizu.
This commit is contained in:
parent
a3047bc036
commit
a6235da61e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=145370
@ -295,7 +295,7 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen)
|
||||
{
|
||||
int tmp_olen;
|
||||
u_char *tmp_cp;
|
||||
struct sackhole *cur, *p, *temp;
|
||||
struct sackhole *cur, *temp;
|
||||
|
||||
INP_LOCK_ASSERT(tp->t_inpcb);
|
||||
if (!tp->sack_enable)
|
||||
@ -335,54 +335,47 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen)
|
||||
}
|
||||
if (SEQ_GT(sack.end, tp->snd_max))
|
||||
continue;
|
||||
if (tp->snd_holes == NULL) { /* first hole */
|
||||
if (TAILQ_EMPTY(&tp->snd_holes)) { /* first hole */
|
||||
if (tcp_sack_globalholes >= tcp_sack_globalmaxholes ||
|
||||
tcp_sack_maxholes == 0) {
|
||||
tcpstat.tcps_sack_sboverflow++;
|
||||
continue;
|
||||
}
|
||||
tp->snd_holes = (struct sackhole *)
|
||||
cur = (struct sackhole *)
|
||||
uma_zalloc(sack_hole_zone,M_NOWAIT);
|
||||
if (tp->snd_holes == NULL) {
|
||||
if (cur == NULL) {
|
||||
/* ENOBUFS, so ignore SACKed block for now*/
|
||||
continue;
|
||||
}
|
||||
cur = tp->snd_holes;
|
||||
cur->start = th->th_ack;
|
||||
cur->end = sack.start;
|
||||
cur->rxmit = cur->start;
|
||||
cur->next = NULL;
|
||||
tp->snd_numholes = 1;
|
||||
tcp_sack_globalholes++;
|
||||
tp->rcv_lastsack = sack.end;
|
||||
TAILQ_INSERT_HEAD(&tp->snd_holes, cur, scblink);
|
||||
continue; /* with next sack block */
|
||||
}
|
||||
/* Go thru list of holes: p = previous, cur = current */
|
||||
p = cur = tp->snd_holes;
|
||||
/* Go thru list of holes. */
|
||||
cur = TAILQ_FIRST(&tp->snd_holes);
|
||||
while (cur) {
|
||||
if (SEQ_LEQ(sack.end, cur->start))
|
||||
/* SACKs data before the current hole */
|
||||
break; /* no use going through more holes */
|
||||
if (SEQ_GEQ(sack.start, cur->end)) {
|
||||
/* SACKs data beyond the current hole */
|
||||
p = cur;
|
||||
cur = cur->next;
|
||||
cur = TAILQ_NEXT(cur, scblink);
|
||||
continue;
|
||||
}
|
||||
if (SEQ_LEQ(sack.start, cur->start)) {
|
||||
/* Data acks at least the beginning of hole */
|
||||
if (SEQ_GEQ(sack.end, cur->end)) {
|
||||
/* Acks entire hole, so delete hole */
|
||||
if (p != cur) {
|
||||
p->next = cur->next;
|
||||
uma_zfree(sack_hole_zone, cur);
|
||||
cur = p->next;
|
||||
} else {
|
||||
cur = cur->next;
|
||||
uma_zfree(sack_hole_zone, p);
|
||||
p = cur;
|
||||
tp->snd_holes = p;
|
||||
}
|
||||
temp = cur;
|
||||
cur = TAILQ_NEXT(cur, scblink);
|
||||
TAILQ_REMOVE(&tp->snd_holes,
|
||||
temp, scblink);
|
||||
uma_zfree(sack_hole_zone, temp);
|
||||
tp->snd_numholes--;
|
||||
tcp_sack_globalholes--;
|
||||
continue;
|
||||
@ -390,16 +383,14 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen)
|
||||
/* otherwise, move start of hole forward */
|
||||
cur->start = sack.end;
|
||||
cur->rxmit = SEQ_MAX(cur->rxmit, cur->start);
|
||||
p = cur;
|
||||
cur = cur->next;
|
||||
cur = TAILQ_NEXT(cur, scblink);
|
||||
continue;
|
||||
}
|
||||
/* move end of hole backward */
|
||||
if (SEQ_GEQ(sack.end, cur->end)) {
|
||||
cur->end = sack.start;
|
||||
cur->rxmit = SEQ_MIN(cur->rxmit, cur->end);
|
||||
p = cur;
|
||||
cur = cur->next;
|
||||
cur = TAILQ_NEXT(cur, scblink);
|
||||
continue;
|
||||
}
|
||||
if (SEQ_LT(cur->start, sack.start) &&
|
||||
@ -418,25 +409,21 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen)
|
||||
uma_zalloc(sack_hole_zone,M_NOWAIT);
|
||||
if (temp == NULL)
|
||||
continue; /* ENOBUFS */
|
||||
temp->next = cur->next;
|
||||
temp->start = sack.end;
|
||||
temp->end = cur->end;
|
||||
temp->rxmit = SEQ_MAX(cur->rxmit, temp->start);
|
||||
cur->end = sack.start;
|
||||
cur->rxmit = SEQ_MIN(cur->rxmit, cur->end);
|
||||
cur->next = temp;
|
||||
p = temp;
|
||||
cur = p->next;
|
||||
TAILQ_INSERT_AFTER(&tp->snd_holes,
|
||||
cur, temp, scblink);
|
||||
cur = TAILQ_NEXT(temp, scblink);
|
||||
tp->snd_numholes++;
|
||||
tcp_sack_globalholes++;
|
||||
}
|
||||
}
|
||||
/* At this point, p points to the last hole on the list */
|
||||
/* At this point, we are at the tail of the scoreboard. */
|
||||
if (SEQ_LT(tp->rcv_lastsack, sack.start)) {
|
||||
/*
|
||||
* Need to append new hole at end.
|
||||
* Last hole is p (and it's not NULL).
|
||||
*/
|
||||
/* Need to append new hole at end. */
|
||||
if (tp->snd_numholes >= tcp_sack_maxholes ||
|
||||
tcp_sack_globalholes >= tcp_sack_globalmaxholes) {
|
||||
tcpstat.tcps_sack_sboverflow++;
|
||||
@ -449,11 +436,10 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen)
|
||||
temp->start = tp->rcv_lastsack;
|
||||
temp->end = sack.start;
|
||||
temp->rxmit = temp->start;
|
||||
temp->next = 0;
|
||||
p->next = temp;
|
||||
tp->rcv_lastsack = sack.end;
|
||||
tp->snd_numholes++;
|
||||
tcp_sack_globalholes++;
|
||||
TAILQ_INSERT_TAIL(&tp->snd_holes, temp, scblink);
|
||||
}
|
||||
if (SEQ_LT(tp->rcv_lastsack, sack.end))
|
||||
tp->rcv_lastsack = sack.end;
|
||||
@ -476,12 +462,13 @@ tcp_del_sackholes(tp, th)
|
||||
/* max because this could be an older ack just arrived */
|
||||
tcp_seq lastack = SEQ_GT(th->th_ack, tp->snd_una) ?
|
||||
th->th_ack : tp->snd_una;
|
||||
struct sackhole *cur = tp->snd_holes;
|
||||
struct sackhole *cur = TAILQ_FIRST(&tp->snd_holes);
|
||||
struct sackhole *prev;
|
||||
while (cur)
|
||||
if (SEQ_LEQ(cur->end, lastack)) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
cur = TAILQ_NEXT(cur, scblink);
|
||||
TAILQ_REMOVE(&tp->snd_holes, prev, scblink);
|
||||
uma_zfree(sack_hole_zone, prev);
|
||||
tp->snd_numholes--;
|
||||
tcp_sack_globalholes--;
|
||||
@ -492,24 +479,20 @@ tcp_del_sackholes(tp, th)
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
tp->snd_holes = cur;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tcp_free_sackholes(struct tcpcb *tp)
|
||||
{
|
||||
struct sackhole *p, *q;
|
||||
struct sackhole *q;
|
||||
|
||||
INP_LOCK_ASSERT(tp->t_inpcb);
|
||||
q = tp->snd_holes;
|
||||
while (q != NULL) {
|
||||
p = q;
|
||||
q = q->next;
|
||||
uma_zfree(sack_hole_zone, p);
|
||||
while ((q = TAILQ_FIRST(&tp->snd_holes)) != NULL) {
|
||||
TAILQ_REMOVE(&tp->snd_holes, q, scblink);
|
||||
uma_zfree(sack_hole_zone, q);
|
||||
tcp_sack_globalholes--;
|
||||
}
|
||||
tp->snd_holes = 0;
|
||||
tp->snd_numholes = 0;
|
||||
}
|
||||
|
||||
@ -546,22 +529,6 @@ tcp_sack_partialack(tp, th)
|
||||
(void) tcp_output(tp);
|
||||
}
|
||||
|
||||
#ifdef TCP_SACK_DEBUG
|
||||
void
|
||||
tcp_print_holes(struct tcpcb *tp)
|
||||
{
|
||||
struct sackhole *p = tp->snd_holes;
|
||||
if (p == 0)
|
||||
return;
|
||||
printf("Hole report: start--end dups rxmit\n");
|
||||
while (p) {
|
||||
printf("%x--%x r %x\n", p->start, p->end, p->rxmit);
|
||||
p = p->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif /* TCP_SACK_DEBUG */
|
||||
|
||||
/*
|
||||
* Returns pointer to a sackhole if there are any pending retransmissions;
|
||||
* NULL otherwise.
|
||||
@ -569,21 +536,17 @@ tcp_print_holes(struct tcpcb *tp)
|
||||
struct sackhole *
|
||||
tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt)
|
||||
{
|
||||
struct sackhole *p = NULL;
|
||||
struct sackhole *p;
|
||||
|
||||
INP_LOCK_ASSERT(tp->t_inpcb);
|
||||
if (!tp->sack_enable)
|
||||
return (NULL);
|
||||
*sack_bytes_rexmt = 0;
|
||||
for (p = tp->snd_holes; p ; p = p->next) {
|
||||
TAILQ_FOREACH(p, &tp->snd_holes, scblink) {
|
||||
if (SEQ_LT(p->rxmit, p->end)) {
|
||||
if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */
|
||||
continue;
|
||||
}
|
||||
#ifdef TCP_SACK_DEBUG
|
||||
if (p)
|
||||
tcp_print_holes(tp);
|
||||
#endif
|
||||
*sack_bytes_rexmt += (p->rxmit - p->start);
|
||||
break;
|
||||
}
|
||||
@ -600,7 +563,7 @@ tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt)
|
||||
void
|
||||
tcp_sack_adjust(struct tcpcb *tp)
|
||||
{
|
||||
struct sackhole *cur = tp->snd_holes;
|
||||
struct sackhole *p, *cur = TAILQ_FIRST(&tp->snd_holes);
|
||||
|
||||
INP_LOCK_ASSERT(tp->t_inpcb);
|
||||
if (cur == NULL)
|
||||
@ -612,13 +575,13 @@ tcp_sack_adjust(struct tcpcb *tp)
|
||||
* i) snd_nxt lies between end of one hole and beginning of another
|
||||
* ii) snd_nxt lies between end of last hole and rcv_lastsack
|
||||
*/
|
||||
while (cur->next) {
|
||||
while ((p = TAILQ_NEXT(cur, scblink)) != NULL) {
|
||||
if (SEQ_LT(tp->snd_nxt, cur->end))
|
||||
return;
|
||||
if (SEQ_GEQ(tp->snd_nxt, cur->next->start))
|
||||
cur = cur->next;
|
||||
if (SEQ_GEQ(tp->snd_nxt, p->start))
|
||||
cur = p;
|
||||
else {
|
||||
tp->snd_nxt = cur->next->start;
|
||||
tp->snd_nxt = p->start;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -638,9 +601,9 @@ int
|
||||
tcp_sacked_bytes(struct tcpcb *tp, int *lost_not_rexmitted)
|
||||
{
|
||||
INP_LOCK_ASSERT(tp->t_inpcb);
|
||||
struct sackhole *cur = tp->snd_holes;
|
||||
struct sackhole *cur = TAILQ_FIRST(&tp->snd_holes);
|
||||
int sacked = 0;
|
||||
u_long lost = 0;
|
||||
int lost = 0;
|
||||
|
||||
if (cur == NULL) /* Scoreboard empty. */
|
||||
goto out;
|
||||
@ -650,7 +613,7 @@ tcp_sacked_bytes(struct tcpcb *tp, int *lost_not_rexmitted)
|
||||
while (cur) {
|
||||
lost += (cur->end - cur->rxmit);
|
||||
sacked -= (cur->end - cur->start);
|
||||
cur = cur->next;
|
||||
cur = TAILQ_NEXT(cur, scblink);
|
||||
}
|
||||
out:
|
||||
if (lost_not_rexmitted)
|
||||
|
@ -605,6 +605,8 @@ tcp_newtcpcb(inp)
|
||||
if (tcp_do_rfc1323)
|
||||
tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
|
||||
tp->sack_enable = tcp_do_sack;
|
||||
if (tp->sack_enable)
|
||||
TAILQ_INIT(&tp->snd_holes);
|
||||
tp->t_inpcb = inp; /* XXX */
|
||||
/*
|
||||
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
|
||||
|
@ -605,6 +605,8 @@ tcp_newtcpcb(inp)
|
||||
if (tcp_do_rfc1323)
|
||||
tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
|
||||
tp->sack_enable = tcp_do_sack;
|
||||
if (tp->sack_enable)
|
||||
TAILQ_INIT(&tp->snd_holes);
|
||||
tp->t_inpcb = inp; /* XXX */
|
||||
/*
|
||||
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
|
||||
|
@ -60,7 +60,7 @@ struct sackhole {
|
||||
tcp_seq start; /* start seq no. of hole */
|
||||
tcp_seq end; /* end seq no. */
|
||||
tcp_seq rxmit; /* next seq. no in hole to be retransmitted */
|
||||
struct sackhole *next; /* next in list */
|
||||
TAILQ_ENTRY(sackhole) scblink; /* scoreboard linkage */
|
||||
};
|
||||
|
||||
struct tcptemp {
|
||||
@ -186,7 +186,7 @@ struct tcpcb {
|
||||
/* SACK related state */
|
||||
int sack_enable; /* enable SACK for this connection */
|
||||
int snd_numholes; /* number of holes seen by sender */
|
||||
struct sackhole *snd_holes; /* linked list of holes (sorted) */
|
||||
TAILQ_HEAD(, sackhole) snd_holes; /* SACK scoreboard (sorted) */
|
||||
tcp_seq rcv_lastsack; /* last seq number(+1) sack'd by rcv'r*/
|
||||
int rcv_numsacks; /* # distinct sack blks present */
|
||||
struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */
|
||||
@ -582,9 +582,6 @@ void tcp_sack_partialack(struct tcpcb *, struct tcphdr *);
|
||||
void tcp_free_sackholes(struct tcpcb *tp);
|
||||
int tcp_newreno(struct tcpcb *, struct tcphdr *);
|
||||
u_long tcp_seq_subtract(u_long, u_long );
|
||||
#ifdef TCP_SACK_DEBUG
|
||||
void tcp_print_holes(struct tcpcb *tp);
|
||||
#endif /* TCP_SACK_DEBUG */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user