aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-09-30 02:07:10 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-30 02:07:10 -0400
commit75b005b949d3dc93b526c3da0a750fd1fc9a703a (patch)
tree859152992bd65e3da93767dbda6fbdf7e011e69c
parent1b0ff89852d79354e8a091c81a88df21f5aa9f0a (diff)
parentbe4947bf46cb0e7a7d089e03c61bab35f1e695ce (diff)
Merge branch 'sctp-fixes'
Xin Long says: ==================== sctp: a bunch of fixes for prsctp polices This patchset is to fix 2 issues for prsctp polices: 1. patch 1 and 2 fix "netperf-Throughput_Mbps -37.2% regression" issue when overloading the CPU. 2. patch 3 fix "prsctp polices should check both sides' prsctp_capable, instead of only local side". ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/structs.h13
-rw-r--r--net/sctp/chunk.c11
-rw-r--r--net/sctp/outqueue.c12
-rw-r--r--net/sctp/sm_make_chunk.c15
4 files changed, 17 insertions, 34 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ce93c4b10d26..ced0df374e60 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -554,6 +554,9 @@ struct sctp_chunk {
554 554
555 atomic_t refcnt; 555 atomic_t refcnt;
556 556
557 /* How many times this chunk have been sent, for prsctp RTX policy */
558 int sent_count;
559
557 /* This is our link to the per-transport transmitted list. */ 560 /* This is our link to the per-transport transmitted list. */
558 struct list_head transmitted_list; 561 struct list_head transmitted_list;
559 562
@@ -603,16 +606,6 @@ struct sctp_chunk {
603 /* This needs to be recoverable for SCTP_SEND_FAILED events. */ 606 /* This needs to be recoverable for SCTP_SEND_FAILED events. */
604 struct sctp_sndrcvinfo sinfo; 607 struct sctp_sndrcvinfo sinfo;
605 608
606 /* We use this field to record param for prsctp policies,
607 * for TTL policy, it is the time_to_drop of this chunk,
608 * for RTX policy, it is the max_sent_count of this chunk,
609 * for PRIO policy, it is the priority of this chunk.
610 */
611 unsigned long prsctp_param;
612
613 /* How many times this chunk have been sent, for prsctp RTX policy */
614 int sent_count;
615
616 /* Which association does this belong to? */ 609 /* Which association does this belong to? */
617 struct sctp_association *asoc; 610 struct sctp_association *asoc;
618 611
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index a55e54738b81..0a3dbec0a8fb 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -179,6 +179,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
179 msg, msg->expires_at, jiffies); 179 msg, msg->expires_at, jiffies);
180 } 180 }
181 181
182 if (asoc->peer.prsctp_capable &&
183 SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags))
184 msg->expires_at =
185 jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive);
186
182 /* This is the biggest possible DATA chunk that can fit into 187 /* This is the biggest possible DATA chunk that can fit into
183 * the packet 188 * the packet
184 */ 189 */
@@ -335,7 +340,7 @@ errout:
335/* Check whether this message has expired. */ 340/* Check whether this message has expired. */
336int sctp_chunk_abandoned(struct sctp_chunk *chunk) 341int sctp_chunk_abandoned(struct sctp_chunk *chunk)
337{ 342{
338 if (!chunk->asoc->prsctp_enable || 343 if (!chunk->asoc->peer.prsctp_capable ||
339 !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) { 344 !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) {
340 struct sctp_datamsg *msg = chunk->msg; 345 struct sctp_datamsg *msg = chunk->msg;
341 346
@@ -349,14 +354,14 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
349 } 354 }
350 355
351 if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && 356 if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
352 time_after(jiffies, chunk->prsctp_param)) { 357 time_after(jiffies, chunk->msg->expires_at)) {
353 if (chunk->sent_count) 358 if (chunk->sent_count)
354 chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++; 359 chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
355 else 360 else
356 chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; 361 chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
357 return 1; 362 return 1;
358 } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && 363 } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
359 chunk->sent_count > chunk->prsctp_param) { 364 chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
360 chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; 365 chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
361 return 1; 366 return 1;
362 } 367 }
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 72e54a416af6..107233da5cc9 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -326,7 +326,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk, gfp_t gfp)
326 326
327 sctp_chunk_hold(chunk); 327 sctp_chunk_hold(chunk);
328 sctp_outq_tail_data(q, chunk); 328 sctp_outq_tail_data(q, chunk);
329 if (chunk->asoc->prsctp_enable && 329 if (chunk->asoc->peer.prsctp_capable &&
330 SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) 330 SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags))
331 chunk->asoc->sent_cnt_removable++; 331 chunk->asoc->sent_cnt_removable++;
332 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) 332 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
@@ -383,7 +383,7 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
383 383
384 list_for_each_entry_safe(chk, temp, queue, transmitted_list) { 384 list_for_each_entry_safe(chk, temp, queue, transmitted_list) {
385 if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || 385 if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
386 chk->prsctp_param <= sinfo->sinfo_timetolive) 386 chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
387 continue; 387 continue;
388 388
389 list_del_init(&chk->transmitted_list); 389 list_del_init(&chk->transmitted_list);
@@ -418,7 +418,7 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
418 418
419 list_for_each_entry_safe(chk, temp, queue, list) { 419 list_for_each_entry_safe(chk, temp, queue, list) {
420 if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || 420 if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
421 chk->prsctp_param <= sinfo->sinfo_timetolive) 421 chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
422 continue; 422 continue;
423 423
424 list_del_init(&chk->list); 424 list_del_init(&chk->list);
@@ -442,7 +442,7 @@ void sctp_prsctp_prune(struct sctp_association *asoc,
442{ 442{
443 struct sctp_transport *transport; 443 struct sctp_transport *transport;
444 444
445 if (!asoc->prsctp_enable || !asoc->sent_cnt_removable) 445 if (!asoc->peer.prsctp_capable || !asoc->sent_cnt_removable)
446 return; 446 return;
447 447
448 msg_len = sctp_prsctp_prune_sent(asoc, sinfo, 448 msg_len = sctp_prsctp_prune_sent(asoc, sinfo,
@@ -1055,7 +1055,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
1055 1055
1056 /* Mark as failed send. */ 1056 /* Mark as failed send. */
1057 sctp_chunk_fail(chunk, SCTP_ERROR_INV_STRM); 1057 sctp_chunk_fail(chunk, SCTP_ERROR_INV_STRM);
1058 if (asoc->prsctp_enable && 1058 if (asoc->peer.prsctp_capable &&
1059 SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) 1059 SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags))
1060 asoc->sent_cnt_removable--; 1060 asoc->sent_cnt_removable--;
1061 sctp_chunk_free(chunk); 1061 sctp_chunk_free(chunk);
@@ -1347,7 +1347,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
1347 tsn = ntohl(tchunk->subh.data_hdr->tsn); 1347 tsn = ntohl(tchunk->subh.data_hdr->tsn);
1348 if (TSN_lte(tsn, ctsn)) { 1348 if (TSN_lte(tsn, ctsn)) {
1349 list_del_init(&tchunk->transmitted_list); 1349 list_del_init(&tchunk->transmitted_list);
1350 if (asoc->prsctp_enable && 1350 if (asoc->peer.prsctp_capable &&
1351 SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) 1351 SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags))
1352 asoc->sent_cnt_removable--; 1352 asoc->sent_cnt_removable--;
1353 sctp_chunk_free(tchunk); 1353 sctp_chunk_free(tchunk);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 8c77b87a8565..46ffecc57214 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -706,20 +706,6 @@ nodata:
706 return retval; 706 return retval;
707} 707}
708 708
709static void sctp_set_prsctp_policy(struct sctp_chunk *chunk,
710 const struct sctp_sndrcvinfo *sinfo)
711{
712 if (!chunk->asoc->prsctp_enable)
713 return;
714
715 if (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags))
716 chunk->prsctp_param =
717 jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive);
718 else if (SCTP_PR_RTX_ENABLED(sinfo->sinfo_flags) ||
719 SCTP_PR_PRIO_ENABLED(sinfo->sinfo_flags))
720 chunk->prsctp_param = sinfo->sinfo_timetolive;
721}
722
723/* Make a DATA chunk for the given association from the provided 709/* Make a DATA chunk for the given association from the provided
724 * parameters. However, do not populate the data payload. 710 * parameters. However, do not populate the data payload.
725 */ 711 */
@@ -753,7 +739,6 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
753 739
754 retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp); 740 retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
755 memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo)); 741 memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
756 sctp_set_prsctp_policy(retval, sinfo);
757 742
758nodata: 743nodata:
759 return retval; 744 return retval;