sctp: implement prsctp TTL policy
authorXin Long <lucien.xin@gmail.com>
Sat, 9 Jul 2016 11:47:43 +0000 (19:47 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 11 Jul 2016 20:25:39 +0000 (13:25 -0700)
prsctp TTL policy is a policy to abandon chunks when they expire
at the specific time in local stack. It's similar with expires_at
in struct sctp_datamsg.

This patch uses sinfo->sinfo_timetolive to set the specific time for
TTL policy. sinfo->sinfo_timetolive is also used for msg->expires_at.
So if prsctp_enable or TTL policy is not enabled, msg->expires_at
still works as before.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sctp/structs.h
net/sctp/chunk.c
net/sctp/output.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c

index d8e464a..6bcda71 100644 (file)
@@ -602,6 +602,16 @@ struct sctp_chunk {
        /* This needs to be recoverable for SCTP_SEND_FAILED events. */
        struct sctp_sndrcvinfo sinfo;
 
+       /* We use this field to record param for prsctp policies,
+        * for TTL policy, it is the time_to_drop of this chunk,
+        * for RTX policy, it is the max_sent_count of this chunk,
+        * for PRIO policy, it is the priority of this chunk.
+        */
+       unsigned long prsctp_param;
+
+       /* How many times this chunk have been sent, for prsctp RTX policy */
+       int sent_count;
+
        /* Which association does this belong to?  */
        struct sctp_association *asoc;
 
index 1eb94bf..2698d12 100644 (file)
@@ -335,13 +335,27 @@ errout:
 /* Check whether this message has expired. */
 int sctp_chunk_abandoned(struct sctp_chunk *chunk)
 {
-       struct sctp_datamsg *msg = chunk->msg;
+       if (!chunk->asoc->prsctp_enable ||
+           !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) {
+               struct sctp_datamsg *msg = chunk->msg;
+
+               if (!msg->can_abandon)
+                       return 0;
+
+               if (time_after(jiffies, msg->expires_at))
+                       return 1;
 
-       if (!msg->can_abandon)
                return 0;
+       }
 
-       if (time_after(jiffies, msg->expires_at))
+       if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
+           time_after(jiffies, chunk->prsctp_param)) {
+               if (chunk->sent_count)
+                       chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
+               else
+                       chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
                return 1;
+       }
 
        return 0;
 }
index 2e9223b..7425f6c 100644 (file)
@@ -316,6 +316,8 @@ static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet,
                packet->has_data = 1;
                /* timestamp the chunk for rtx purposes */
                chunk->sent_at = jiffies;
+               /* Mainly used for prsctp RTX policy */
+               chunk->sent_count++;
                break;
        case SCTP_CID_COOKIE_ECHO:
                packet->has_cookie_echo = 1;
index 0e3045e..2c431ee 100644 (file)
@@ -711,6 +711,17 @@ nodata:
        return retval;
 }
 
+static void sctp_set_prsctp_policy(struct sctp_chunk *chunk,
+                                  const struct sctp_sndrcvinfo *sinfo)
+{
+       if (!chunk->asoc->prsctp_enable)
+               return;
+
+       if (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags))
+               chunk->prsctp_param =
+                       jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive);
+}
+
 /* Make a DATA chunk for the given association from the provided
  * parameters.  However, do not populate the data payload.
  */
@@ -744,6 +755,7 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
 
        retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
        memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
+       sctp_set_prsctp_policy(retval, sinfo);
 
 nodata:
        return retval;
index c3167c4..0861429 100644 (file)
@@ -7099,7 +7099,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
 
                        if (cmsgs->srinfo->sinfo_flags &
                            ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
-                             SCTP_SACK_IMMEDIATELY |
+                             SCTP_SACK_IMMEDIATELY | SCTP_PR_SCTP_MASK |
                              SCTP_ABORT | SCTP_EOF))
                                return -EINVAL;
                        break;
@@ -7123,7 +7123,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
 
                        if (cmsgs->sinfo->snd_flags &
                            ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
-                             SCTP_SACK_IMMEDIATELY |
+                             SCTP_SACK_IMMEDIATELY | SCTP_PR_SCTP_MASK |
                              SCTP_ABORT | SCTP_EOF))
                                return -EINVAL;
                        break;