~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/sctp/chunk.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /net/sctp/chunk.c (Version linux-6.12-rc7) and /net/sctp/chunk.c (Version linux-4.14.336)


  1 // SPDX-License-Identifier: GPL-2.0-or-later   << 
  2 /* SCTP kernel implementation                       1 /* SCTP kernel implementation
  3  * (C) Copyright IBM Corp. 2003, 2004               2  * (C) Copyright IBM Corp. 2003, 2004
  4  *                                                  3  *
  5  * This file is part of the SCTP kernel implem      4  * This file is part of the SCTP kernel implementation
  6  *                                                  5  *
  7  * This file contains the code relating the ch      6  * This file contains the code relating the chunk abstraction.
  8  *                                                  7  *
                                                   >>   8  * This SCTP implementation is free software;
                                                   >>   9  * you can redistribute it and/or modify it under the terms of
                                                   >>  10  * the GNU General Public License as published by
                                                   >>  11  * the Free Software Foundation; either version 2, or (at your option)
                                                   >>  12  * any later version.
                                                   >>  13  *
                                                   >>  14  * This SCTP implementation is distributed in the hope that it
                                                   >>  15  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
                                                   >>  16  *                 ************************
                                                   >>  17  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
                                                   >>  18  * See the GNU General Public License for more details.
                                                   >>  19  *
                                                   >>  20  * You should have received a copy of the GNU General Public License
                                                   >>  21  * along with GNU CC; see the file COPYING.  If not, see
                                                   >>  22  * <http://www.gnu.org/licenses/>.
                                                   >>  23  *
  9  * Please send any bug reports or fixes you ma     24  * Please send any bug reports or fixes you make to the
 10  * email address(es):                              25  * email address(es):
 11  *    lksctp developers <linux-sctp@vger.kerne     26  *    lksctp developers <linux-sctp@vger.kernel.org>
 12  *                                                 27  *
 13  * Written or modified by:                         28  * Written or modified by:
 14  *    Jon Grimm             <jgrimm@us.ibm.com     29  *    Jon Grimm             <jgrimm@us.ibm.com>
 15  *    Sridhar Samudrala     <sri@us.ibm.com>       30  *    Sridhar Samudrala     <sri@us.ibm.com>
 16  */                                                31  */
 17                                                    32 
 18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt        33 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 19                                                    34 
 20 #include <linux/types.h>                           35 #include <linux/types.h>
 21 #include <linux/kernel.h>                          36 #include <linux/kernel.h>
 22 #include <linux/net.h>                             37 #include <linux/net.h>
 23 #include <linux/inet.h>                            38 #include <linux/inet.h>
 24 #include <linux/skbuff.h>                          39 #include <linux/skbuff.h>
 25 #include <linux/slab.h>                            40 #include <linux/slab.h>
 26 #include <net/sock.h>                              41 #include <net/sock.h>
 27 #include <net/sctp/sctp.h>                         42 #include <net/sctp/sctp.h>
 28 #include <net/sctp/sm.h>                           43 #include <net/sctp/sm.h>
 29                                                    44 
 30 /* This file is mostly in anticipation of futu     45 /* This file is mostly in anticipation of future work, but initially
 31  * populate with fragment tracking for an outb     46  * populate with fragment tracking for an outbound message.
 32  */                                                47  */
 33                                                    48 
 34 /* Initialize datamsg from memory. */              49 /* Initialize datamsg from memory. */
 35 static void sctp_datamsg_init(struct sctp_data     50 static void sctp_datamsg_init(struct sctp_datamsg *msg)
 36 {                                                  51 {
 37         refcount_set(&msg->refcnt, 1);             52         refcount_set(&msg->refcnt, 1);
 38         msg->send_failed = 0;                      53         msg->send_failed = 0;
 39         msg->send_error = 0;                       54         msg->send_error = 0;
 40         msg->can_delay = 1;                        55         msg->can_delay = 1;
 41         msg->abandoned = 0;                    << 
 42         msg->expires_at = 0;                       56         msg->expires_at = 0;
 43         INIT_LIST_HEAD(&msg->chunks);              57         INIT_LIST_HEAD(&msg->chunks);
 44 }                                                  58 }
 45                                                    59 
 46 /* Allocate and initialize datamsg. */             60 /* Allocate and initialize datamsg. */
 47 static struct sctp_datamsg *sctp_datamsg_new(g     61 static struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp)
 48 {                                                  62 {
 49         struct sctp_datamsg *msg;                  63         struct sctp_datamsg *msg;
 50         msg = kmalloc(sizeof(struct sctp_datam     64         msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
 51         if (msg) {                                 65         if (msg) {
 52                 sctp_datamsg_init(msg);            66                 sctp_datamsg_init(msg);
 53                 SCTP_DBG_OBJCNT_INC(datamsg);      67                 SCTP_DBG_OBJCNT_INC(datamsg);
 54         }                                          68         }
 55         return msg;                                69         return msg;
 56 }                                                  70 }
 57                                                    71 
 58 void sctp_datamsg_free(struct sctp_datamsg *ms     72 void sctp_datamsg_free(struct sctp_datamsg *msg)
 59 {                                                  73 {
 60         struct sctp_chunk *chunk;                  74         struct sctp_chunk *chunk;
 61                                                    75 
 62         /* This doesn't have to be a _safe vai     76         /* This doesn't have to be a _safe vairant because
 63          * sctp_chunk_free() only drops the re     77          * sctp_chunk_free() only drops the refs.
 64          */                                        78          */
 65         list_for_each_entry(chunk, &msg->chunk     79         list_for_each_entry(chunk, &msg->chunks, frag_list)
 66                 sctp_chunk_free(chunk);            80                 sctp_chunk_free(chunk);
 67                                                    81 
 68         sctp_datamsg_put(msg);                     82         sctp_datamsg_put(msg);
 69 }                                                  83 }
 70                                                    84 
 71 /* Final destructruction of datamsg memory. */     85 /* Final destructruction of datamsg memory. */
 72 static void sctp_datamsg_destroy(struct sctp_d     86 static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
 73 {                                                  87 {
 74         struct sctp_association *asoc = NULL;  << 
 75         struct list_head *pos, *temp;              88         struct list_head *pos, *temp;
 76         struct sctp_chunk *chunk;                  89         struct sctp_chunk *chunk;
                                                   >>  90         struct sctp_sock *sp;
 77         struct sctp_ulpevent *ev;                  91         struct sctp_ulpevent *ev;
 78         int error, sent;                       !!  92         struct sctp_association *asoc = NULL;
                                                   >>  93         int error = 0, notify;
                                                   >>  94 
                                                   >>  95         /* If we failed, we may need to notify. */
                                                   >>  96         notify = msg->send_failed ? -1 : 0;
 79                                                    97 
 80         /* Release all references. */              98         /* Release all references. */
 81         list_for_each_safe(pos, temp, &msg->ch     99         list_for_each_safe(pos, temp, &msg->chunks) {
 82                 list_del_init(pos);               100                 list_del_init(pos);
 83                 chunk = list_entry(pos, struct    101                 chunk = list_entry(pos, struct sctp_chunk, frag_list);
 84                                                !! 102                 /* Check whether we _really_ need to notify. */
 85                 if (!msg->send_failed) {       !! 103                 if (notify < 0) {
 86                         sctp_chunk_put(chunk); !! 104                         asoc = chunk->asoc;
 87                         continue;              !! 105                         if (msg->send_error)
                                                   >> 106                                 error = msg->send_error;
                                                   >> 107                         else
                                                   >> 108                                 error = asoc->outqueue.error;
                                                   >> 109 
                                                   >> 110                         sp = sctp_sk(asoc->base.sk);
                                                   >> 111                         notify = sctp_ulpevent_type_enabled(SCTP_SEND_FAILED,
                                                   >> 112                                                             &sp->subscribe);
 88                 }                                 113                 }
 89                                                   114 
 90                 asoc = chunk->asoc;            !! 115                 /* Generate a SEND FAILED event only if enabled. */
 91                 error = msg->send_error ?: aso !! 116                 if (notify > 0) {
 92                 sent = chunk->has_tsn ? SCTP_D !! 117                         int sent;
                                                   >> 118                         if (chunk->has_tsn)
                                                   >> 119                                 sent = SCTP_DATA_SENT;
                                                   >> 120                         else
                                                   >> 121                                 sent = SCTP_DATA_UNSENT;
 93                                                   122 
 94                 if (sctp_ulpevent_type_enabled << 
 95                                                << 
 96                         ev = sctp_ulpevent_mak    123                         ev = sctp_ulpevent_make_send_failed(asoc, chunk, sent,
 97                                                   124                                                             error, GFP_ATOMIC);
 98                         if (ev)                   125                         if (ev)
 99                                 asoc->stream.s !! 126                                 sctp_ulpq_tail_event(&asoc->ulpq, ev);
100                 }                              << 
101                                                << 
102                 if (sctp_ulpevent_type_enabled << 
103                                                << 
104                         ev = sctp_ulpevent_mak << 
105                                                << 
106                                                << 
107                         if (ev)                << 
108                                 asoc->stream.s << 
109                 }                                 127                 }
110                                                   128 
111                 sctp_chunk_put(chunk);            129                 sctp_chunk_put(chunk);
112         }                                         130         }
113                                                   131 
114         SCTP_DBG_OBJCNT_DEC(datamsg);             132         SCTP_DBG_OBJCNT_DEC(datamsg);
115         kfree(msg);                               133         kfree(msg);
116 }                                                 134 }
117                                                   135 
118 /* Hold a reference. */                           136 /* Hold a reference. */
119 static void sctp_datamsg_hold(struct sctp_data    137 static void sctp_datamsg_hold(struct sctp_datamsg *msg)
120 {                                                 138 {
121         refcount_inc(&msg->refcnt);               139         refcount_inc(&msg->refcnt);
122 }                                                 140 }
123                                                   141 
124 /* Release a reference. */                        142 /* Release a reference. */
125 void sctp_datamsg_put(struct sctp_datamsg *msg    143 void sctp_datamsg_put(struct sctp_datamsg *msg)
126 {                                                 144 {
127         if (refcount_dec_and_test(&msg->refcnt    145         if (refcount_dec_and_test(&msg->refcnt))
128                 sctp_datamsg_destroy(msg);        146                 sctp_datamsg_destroy(msg);
129 }                                                 147 }
130                                                   148 
131 /* Assign a chunk to this datamsg. */             149 /* Assign a chunk to this datamsg. */
132 static void sctp_datamsg_assign(struct sctp_da    150 static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
133 {                                                 151 {
134         sctp_datamsg_hold(msg);                   152         sctp_datamsg_hold(msg);
135         chunk->msg = msg;                         153         chunk->msg = msg;
136 }                                                 154 }
137                                                   155 
138                                                   156 
139 /* A data chunk can have a maximum payload of     157 /* A data chunk can have a maximum payload of (2^16 - 20).  Break
140  * down any such message into smaller chunks.     158  * down any such message into smaller chunks.  Opportunistically, fragment
141  * the chunks down to the current MTU constrai    159  * the chunks down to the current MTU constraints.  We may get refragmented
142  * later if the PMTU changes, but it is _much     160  * later if the PMTU changes, but it is _much better_ to fragment immediately
143  * with a reasonable guess than always doing o    161  * with a reasonable guess than always doing our fragmentation on the
144  * soft-interrupt.                                162  * soft-interrupt.
145  */                                               163  */
146 struct sctp_datamsg *sctp_datamsg_from_user(st    164 struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
147                                             st    165                                             struct sctp_sndrcvinfo *sinfo,
148                                             st    166                                             struct iov_iter *from)
149 {                                                 167 {
150         size_t len, first_len, max_data, remai    168         size_t len, first_len, max_data, remaining;
151         size_t msg_len = iov_iter_count(from);    169         size_t msg_len = iov_iter_count(from);
152         struct sctp_shared_key *shkey = NULL;  << 
153         struct list_head *pos, *temp;             170         struct list_head *pos, *temp;
154         struct sctp_chunk *chunk;                 171         struct sctp_chunk *chunk;
155         struct sctp_datamsg *msg;                 172         struct sctp_datamsg *msg;
156         int err;                                  173         int err;
157                                                   174 
158         msg = sctp_datamsg_new(GFP_KERNEL);       175         msg = sctp_datamsg_new(GFP_KERNEL);
159         if (!msg)                                 176         if (!msg)
160                 return ERR_PTR(-ENOMEM);          177                 return ERR_PTR(-ENOMEM);
161                                                   178 
162         /* Note: Calculate this outside of the    179         /* Note: Calculate this outside of the loop, so that all fragments
163          * have the same expiration.              180          * have the same expiration.
164          */                                       181          */
165         if (asoc->peer.prsctp_capable && sinfo    182         if (asoc->peer.prsctp_capable && sinfo->sinfo_timetolive &&
166             (SCTP_PR_TTL_ENABLED(sinfo->sinfo_    183             (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags) ||
167              !SCTP_PR_POLICY(sinfo->sinfo_flag    184              !SCTP_PR_POLICY(sinfo->sinfo_flags)))
168                 msg->expires_at = jiffies +       185                 msg->expires_at = jiffies +
169                                   msecs_to_jif    186                                   msecs_to_jiffies(sinfo->sinfo_timetolive);
170                                                   187 
171         /* This is the biggest possible DATA c    188         /* This is the biggest possible DATA chunk that can fit into
172          * the packet                             189          * the packet
173          */                                       190          */
174         max_data = asoc->frag_point;           !! 191         max_data = asoc->pathmtu -
175         if (unlikely(!max_data)) {             !! 192                    sctp_sk(asoc->base.sk)->pf->af->net_header_len -
176                 max_data = sctp_min_frag_point !! 193                    sizeof(struct sctphdr) - sizeof(struct sctp_data_chunk);
177                                                !! 194         max_data = SCTP_TRUNC4(max_data);
178                 pr_warn_ratelimited("%s: asoc: << 
179                                     __func__,  << 
180         }                                      << 
181                                                   195 
182         /* If the peer requested that we authe !! 196         /* If the the peer requested that we authenticate DATA chunks
183          * we need to account for bundling of     197          * we need to account for bundling of the AUTH chunks along with
184          * DATA.                                  198          * DATA.
185          */                                       199          */
186         if (sctp_auth_send_cid(SCTP_CID_DATA,     200         if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) {
187                 struct sctp_hmac *hmac_desc =     201                 struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc);
188                                                   202 
189                 if (hmac_desc)                    203                 if (hmac_desc)
190                         max_data -= SCTP_PAD4(    204                         max_data -= SCTP_PAD4(sizeof(struct sctp_auth_chunk) +
191                                                   205                                               hmac_desc->hmac_len);
192                                                << 
193                 if (sinfo->sinfo_tsn &&        << 
194                     sinfo->sinfo_ssn != asoc-> << 
195                         shkey = sctp_auth_get_ << 
196                         if (!shkey) {          << 
197                                 err = -EINVAL; << 
198                                 goto errout;   << 
199                         }                      << 
200                 } else {                       << 
201                         shkey = asoc->shkey;   << 
202                 }                              << 
203         }                                         206         }
204                                                   207 
                                                   >> 208         /* Check what's our max considering the above */
                                                   >> 209         max_data = min_t(size_t, max_data, asoc->frag_point);
                                                   >> 210 
205         /* Set first_len and then account for     211         /* Set first_len and then account for possible bundles on first frag */
206         first_len = max_data;                     212         first_len = max_data;
207                                                   213 
208         /* Check to see if we have a pending S    214         /* Check to see if we have a pending SACK and try to let it be bundled
209          * with this message.  Do this if we d    215          * with this message.  Do this if we don't have any data queued already.
210          * To check that, look at out_qlen and    216          * To check that, look at out_qlen and retransmit list.
211          * NOTE: we will not reduce to account    217          * NOTE: we will not reduce to account for SACK, if the message would
212          * not have been fragmented.              218          * not have been fragmented.
213          */                                       219          */
214         if (timer_pending(&asoc->timers[SCTP_E    220         if (timer_pending(&asoc->timers[SCTP_EVENT_TIMEOUT_SACK]) &&
215             asoc->outqueue.out_qlen == 0 &&       221             asoc->outqueue.out_qlen == 0 &&
216             list_empty(&asoc->outqueue.retrans    222             list_empty(&asoc->outqueue.retransmit) &&
217             msg_len > max_data)                   223             msg_len > max_data)
218                 first_len -= SCTP_PAD4(sizeof(    224                 first_len -= SCTP_PAD4(sizeof(struct sctp_sack_chunk));
219                                                   225 
220         /* Encourage Cookie-ECHO bundling. */     226         /* Encourage Cookie-ECHO bundling. */
221         if (asoc->state < SCTP_STATE_COOKIE_EC    227         if (asoc->state < SCTP_STATE_COOKIE_ECHOED)
222                 first_len -= SCTP_ARBITRARY_CO    228                 first_len -= SCTP_ARBITRARY_COOKIE_ECHO_LEN;
223                                                   229 
224         /* Account for a different sized first    230         /* Account for a different sized first fragment */
225         if (msg_len >= first_len) {               231         if (msg_len >= first_len) {
226                 msg->can_delay = 0;               232                 msg->can_delay = 0;
227                 if (msg_len > first_len)          233                 if (msg_len > first_len)
228                         SCTP_INC_STATS(asoc->b !! 234                         SCTP_INC_STATS(sock_net(asoc->base.sk),
229                                        SCTP_MI    235                                        SCTP_MIB_FRAGUSRMSGS);
230         } else {                                  236         } else {
231                 /* Which may be the only one..    237                 /* Which may be the only one... */
232                 first_len = msg_len;              238                 first_len = msg_len;
233         }                                         239         }
234                                                   240 
235         /* Create chunks for all DATA chunks.     241         /* Create chunks for all DATA chunks. */
236         for (remaining = msg_len; remaining; r    242         for (remaining = msg_len; remaining; remaining -= len) {
237                 u8 frag = SCTP_DATA_MIDDLE_FRA    243                 u8 frag = SCTP_DATA_MIDDLE_FRAG;
238                                                   244 
239                 if (remaining == msg_len) {       245                 if (remaining == msg_len) {
240                         /* First frag, which m    246                         /* First frag, which may also be the last */
241                         frag |= SCTP_DATA_FIRS    247                         frag |= SCTP_DATA_FIRST_FRAG;
242                         len = first_len;          248                         len = first_len;
243                 } else {                          249                 } else {
244                         /* Middle frags */        250                         /* Middle frags */
245                         len = max_data;           251                         len = max_data;
246                 }                                 252                 }
247                                                   253 
248                 if (len >= remaining) {           254                 if (len >= remaining) {
249                         /* Last frag, which ma    255                         /* Last frag, which may also be the first */
250                         len = remaining;          256                         len = remaining;
251                         frag |= SCTP_DATA_LAST    257                         frag |= SCTP_DATA_LAST_FRAG;
252                                                   258 
253                         /* The application req    259                         /* The application requests to set the I-bit of the
254                          * last DATA chunk of     260                          * last DATA chunk of a user message when providing
255                          * the user message to    261                          * the user message to the SCTP implementation.
256                          */                       262                          */
257                         if ((sinfo->sinfo_flag    263                         if ((sinfo->sinfo_flags & SCTP_EOF) ||
258                             (sinfo->sinfo_flag    264                             (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
259                                 frag |= SCTP_D    265                                 frag |= SCTP_DATA_SACK_IMM;
260                 }                                 266                 }
261                                                   267 
262                 chunk = asoc->stream.si->make_ !! 268                 chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag,
263                                                !! 269                                                  0, GFP_KERNEL);
264                 if (!chunk) {                     270                 if (!chunk) {
265                         err = -ENOMEM;            271                         err = -ENOMEM;
266                         goto errout;              272                         goto errout;
267                 }                                 273                 }
268                                                   274 
269                 err = sctp_user_addto_chunk(ch    275                 err = sctp_user_addto_chunk(chunk, len, from);
270                 if (err < 0)                      276                 if (err < 0)
271                         goto errout_chunk_free    277                         goto errout_chunk_free;
272                                                   278 
273                 chunk->shkey = shkey;          << 
274                                                << 
275                 /* Put the chunk->skb back int    279                 /* Put the chunk->skb back into the form expected by send.  */
276                 __skb_pull(chunk->skb, (__u8 *    280                 __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr -
277                                        chunk->    281                                        chunk->skb->data);
278                                                   282 
279                 sctp_datamsg_assign(msg, chunk    283                 sctp_datamsg_assign(msg, chunk);
280                 list_add_tail(&chunk->frag_lis    284                 list_add_tail(&chunk->frag_list, &msg->chunks);
281         }                                         285         }
282                                                   286 
283         return msg;                               287         return msg;
284                                                   288 
285 errout_chunk_free:                                289 errout_chunk_free:
286         sctp_chunk_free(chunk);                   290         sctp_chunk_free(chunk);
287                                                   291 
288 errout:                                           292 errout:
289         list_for_each_safe(pos, temp, &msg->ch    293         list_for_each_safe(pos, temp, &msg->chunks) {
290                 list_del_init(pos);               294                 list_del_init(pos);
291                 chunk = list_entry(pos, struct    295                 chunk = list_entry(pos, struct sctp_chunk, frag_list);
292                 sctp_chunk_free(chunk);           296                 sctp_chunk_free(chunk);
293         }                                         297         }
294         sctp_datamsg_put(msg);                    298         sctp_datamsg_put(msg);
295                                                   299 
296         return ERR_PTR(err);                      300         return ERR_PTR(err);
297 }                                                 301 }
298                                                   302 
299 /* Check whether this message has expired. */     303 /* Check whether this message has expired. */
300 int sctp_chunk_abandoned(struct sctp_chunk *ch    304 int sctp_chunk_abandoned(struct sctp_chunk *chunk)
301 {                                                 305 {
302         if (!chunk->asoc->peer.prsctp_capable)    306         if (!chunk->asoc->peer.prsctp_capable)
303                 return 0;                         307                 return 0;
304                                                   308 
305         if (chunk->msg->abandoned)             << 
306                 return 1;                      << 
307                                                << 
308         if (!chunk->has_tsn &&                 << 
309             !(chunk->chunk_hdr->flags & SCTP_D << 
310                 return 0;                      << 
311                                                << 
312         if (SCTP_PR_TTL_ENABLED(chunk->sinfo.s    309         if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
313             time_after(jiffies, chunk->msg->ex    310             time_after(jiffies, chunk->msg->expires_at)) {
314                 struct sctp_stream_out *stream    311                 struct sctp_stream_out *streamout =
315                         SCTP_SO(&chunk->asoc-> !! 312                         &chunk->asoc->stream.out[chunk->sinfo.sinfo_stream];
316                                 chunk->sinfo.s << 
317                                                   313 
318                 if (chunk->sent_count) {          314                 if (chunk->sent_count) {
319                         chunk->asoc->abandoned    315                         chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
320                         streamout->ext->abando !! 316                         streamout->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
321                 } else {                          317                 } else {
322                         chunk->asoc->abandoned    318                         chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
323                         streamout->ext->abando !! 319                         streamout->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
324                 }                                 320                 }
325                 chunk->msg->abandoned = 1;     << 
326                 return 1;                         321                 return 1;
327         } else if (SCTP_PR_RTX_ENABLED(chunk->    322         } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
328                    chunk->sent_count > chunk->    323                    chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
329                 struct sctp_stream_out *stream    324                 struct sctp_stream_out *streamout =
330                         SCTP_SO(&chunk->asoc-> !! 325                         &chunk->asoc->stream.out[chunk->sinfo.sinfo_stream];
331                                 chunk->sinfo.s << 
332                                                   326 
333                 chunk->asoc->abandoned_sent[SC    327                 chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
334                 streamout->ext->abandoned_sent !! 328                 streamout->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
335                 chunk->msg->abandoned = 1;     << 
336                 return 1;                         329                 return 1;
337         } else if (!SCTP_PR_POLICY(chunk->sinf    330         } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
338                    chunk->msg->expires_at &&      331                    chunk->msg->expires_at &&
339                    time_after(jiffies, chunk->    332                    time_after(jiffies, chunk->msg->expires_at)) {
340                 chunk->msg->abandoned = 1;     << 
341                 return 1;                         333                 return 1;
342         }                                         334         }
343         /* PRIO policy is processed by sendmsg    335         /* PRIO policy is processed by sendmsg, not here */
344                                                   336 
345         return 0;                                 337         return 0;
346 }                                                 338 }
347                                                   339 
348 /* This chunk (and consequently entire message    340 /* This chunk (and consequently entire message) has failed in its sending. */
349 void sctp_chunk_fail(struct sctp_chunk *chunk,    341 void sctp_chunk_fail(struct sctp_chunk *chunk, int error)
350 {                                                 342 {
351         chunk->msg->send_failed = 1;              343         chunk->msg->send_failed = 1;
352         chunk->msg->send_error = error;           344         chunk->msg->send_error = error;
353 }                                                 345 }
354                                                   346 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php