summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_fastfwd.c2
-rw-r--r--sys/netinet/sctp_indata.c69
-rw-r--r--sys/netinet/sctp_input.c2
-rw-r--r--sys/netinet/sctp_structs.h1
4 files changed, 26 insertions, 48 deletions
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 0399393..a1adb85 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -218,7 +218,7 @@ ip_fastforward(struct mbuf *m)
*/
hlen = ip->ip_hl << 2;
if (hlen < sizeof(struct ip)) { /* minimum header length */
- IPSTAT_INC(ips_badlen);
+ IPSTAT_INC(ips_badhlen);
goto drop;
}
if (hlen > m->m_len) {
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 05b40f7..bd484a7 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -3081,14 +3081,17 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
int num_frs = 0;
int chunk_freed;
int non_revocable;
- uint16_t frag_strt, frag_end;
- uint32_t last_frag_high;
+ uint16_t frag_strt, frag_end, prev_frag_end;
- tp1 = NULL;
- last_frag_high = 0;
+ tp1 = TAILQ_FIRST(&asoc->sent_queue);
+ prev_frag_end = 0;
chunk_freed = 0;
for (i = 0; i < (num_seg + num_nr_seg); i++) {
+ if (i == num_seg) {
+ prev_frag_end = 0;
+ tp1 = TAILQ_FIRST(&asoc->sent_queue);
+ }
frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset,
sizeof(struct sctp_gap_ack_block), (uint8_t *) & block);
*offset += sizeof(block);
@@ -3097,58 +3100,29 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
}
frag_strt = ntohs(frag->start);
frag_end = ntohs(frag->end);
- /* some sanity checks on the fragment offsets */
+
if (frag_strt > frag_end) {
- /* this one is malformed, skip */
+ /* This gap report is malformed, skip it. */
continue;
}
- if (compare_with_wrap((frag_end + last_tsn), *biggest_tsn_acked,
- MAX_TSN))
- *biggest_tsn_acked = frag_end + last_tsn;
-
- /* mark acked dgs and find out the highestTSN being acked */
- if (tp1 == NULL) {
+ if (frag_strt <= prev_frag_end) {
+ /* This gap report is not in order, so restart. */
tp1 = TAILQ_FIRST(&asoc->sent_queue);
- /* save the locations of the last frags */
- last_frag_high = frag_end + last_tsn;
- } else {
- /*
- * now lets see if we need to reset the queue due to
- * a out-of-order SACK fragment
- */
- if (compare_with_wrap(frag_strt + last_tsn,
- last_frag_high, MAX_TSN)) {
- /*
- * if the new frag starts after the last TSN
- * frag covered, we are ok and this one is
- * beyond the last one
- */
- ;
- } else {
- /*
- * ok, they have reset us, so we need to
- * reset the queue this will cause extra
- * hunting but hey, they chose the
- * performance hit when they failed to order
- * their gaps
- */
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- }
- last_frag_high = frag_end + last_tsn;
+ }
+ if (compare_with_wrap((last_tsn + frag_end), *biggest_tsn_acked, MAX_TSN)) {
+ *biggest_tsn_acked = last_tsn + frag_end;
}
if (i < num_seg) {
non_revocable = 0;
} else {
non_revocable = 1;
}
- if (i == num_seg) {
- tp1 = NULL;
- }
if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end,
non_revocable, &num_frs, biggest_newly_acked_tsn,
this_sack_lowest_newack, ecn_seg_sums)) {
chunk_freed = 1;
}
+ prev_frag_end = frag_end;
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
if (num_frs)
@@ -4817,7 +4791,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
}
}
/********************************************/
- /* drop the acked chunks from the sendqueue */
+ /* drop the acked chunks from the sentqueue */
/********************************************/
asoc->last_acked_seq = cum_ack;
@@ -4925,9 +4899,10 @@ done_with_it:
* we had some before and now we have NONE.
*/
- if (num_seg)
+ if (num_seg) {
sctp_check_for_revoked(stcb, asoc, cum_ack, biggest_tsn_acked);
- else if (asoc->saw_sack_with_frags) {
+ asoc->saw_sack_with_frags = 1;
+ } else if (asoc->saw_sack_with_frags) {
int cnt_revoked = 0;
tp1 = TAILQ_FIRST(&asoc->sent_queue);
@@ -4963,10 +4938,10 @@ done_with_it:
}
asoc->saw_sack_with_frags = 0;
}
- if (num_seg || num_nr_seg)
- asoc->saw_sack_with_frags = 1;
+ if (num_nr_seg > 0)
+ asoc->saw_sack_with_nr_frags = 1;
else
- asoc->saw_sack_with_frags = 0;
+ asoc->saw_sack_with_nr_frags = 0;
/* JRS - Use the congestion control given in the CC module */
asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index ad4209f..88d67a3 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -4644,6 +4644,7 @@ process_control_chunks:
((compare_with_wrap(cum_ack, stcb->asoc.last_acked_seq, MAX_TSN)) ||
(cum_ack == stcb->asoc.last_acked_seq)) &&
(stcb->asoc.saw_sack_with_frags == 0) &&
+ (stcb->asoc.saw_sack_with_nr_frags == 0) &&
(!TAILQ_EMPTY(&stcb->asoc.sent_queue))
) {
/*
@@ -4737,6 +4738,7 @@ process_control_chunks:
((compare_with_wrap(cum_ack, stcb->asoc.last_acked_seq, MAX_TSN)) ||
(cum_ack == stcb->asoc.last_acked_seq)) &&
(stcb->asoc.saw_sack_with_frags == 0) &&
+ (stcb->asoc.saw_sack_with_nr_frags == 0) &&
(!TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
/*
* We have a SIMPLE sack having no
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 56f4946..94d0395 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -1058,6 +1058,7 @@ struct sctp_association {
uint8_t delayed_connection;
uint8_t ifp_had_enobuf;
uint8_t saw_sack_with_frags;
+ uint8_t saw_sack_with_nr_frags;
uint8_t in_asocid_hash;
uint8_t assoc_up_sent;
uint8_t adaptation_needed;
OpenPOWER on IntegriCloud