160c778b2SVlad Yasevich /* SCTP kernel implementation 21da177e4SLinus Torvalds * (C) Copyright IBM Corp. 2001, 2004 31da177e4SLinus Torvalds * Copyright (c) 1999-2000 Cisco, Inc. 41da177e4SLinus Torvalds * Copyright (c) 1999-2001 Motorola, Inc. 51da177e4SLinus Torvalds * 660c778b2SVlad Yasevich * This file is part of the SCTP kernel implementation 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * These functions handle output processing. 91da177e4SLinus Torvalds * 1060c778b2SVlad Yasevich * This SCTP implementation is free software; 111da177e4SLinus Torvalds * you can redistribute it and/or modify it under the terms of 121da177e4SLinus Torvalds * the GNU General Public License as published by 131da177e4SLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 141da177e4SLinus Torvalds * any later version. 151da177e4SLinus Torvalds * 1660c778b2SVlad Yasevich * This SCTP implementation is distributed in the hope that it 171da177e4SLinus Torvalds * will be useful, but WITHOUT ANY WARRANTY; without even the implied 181da177e4SLinus Torvalds * ************************ 191da177e4SLinus Torvalds * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 201da177e4SLinus Torvalds * See the GNU General Public License for more details. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 234b2f13a2SJeff Kirsher * along with GNU CC; see the file COPYING. If not, see 244b2f13a2SJeff Kirsher * <http://www.gnu.org/licenses/>. 251da177e4SLinus Torvalds * 261da177e4SLinus Torvalds * Please send any bug reports or fixes you make to the 271da177e4SLinus Torvalds * email address(es): 2891705c61SDaniel Borkmann * lksctp developers <linux-sctp@vger.kernel.org> 291da177e4SLinus Torvalds * 301da177e4SLinus Torvalds * Written or modified by: 311da177e4SLinus Torvalds * La Monte H.P. Yarroll <piggy@acm.org> 321da177e4SLinus Torvalds * Karl Knutson <karl@athena.chicago.il.us> 331da177e4SLinus Torvalds * Jon Grimm <jgrimm@austin.ibm.com> 341da177e4SLinus Torvalds * Sridhar Samudrala <sri@us.ibm.com> 351da177e4SLinus Torvalds */ 361da177e4SLinus Torvalds 37145ce502SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 38145ce502SJoe Perches 391da177e4SLinus Torvalds #include <linux/types.h> 401da177e4SLinus Torvalds #include <linux/kernel.h> 411da177e4SLinus Torvalds #include <linux/wait.h> 421da177e4SLinus Torvalds #include <linux/time.h> 431da177e4SLinus Torvalds #include <linux/ip.h> 441da177e4SLinus Torvalds #include <linux/ipv6.h> 451da177e4SLinus Torvalds #include <linux/init.h> 465a0e3ad6STejun Heo #include <linux/slab.h> 471da177e4SLinus Torvalds #include <net/inet_ecn.h> 488d2f9e81SVlad Yasevich #include <net/ip.h> 491da177e4SLinus Torvalds #include <net/icmp.h> 507c73a6faSPavel Emelyanov #include <net/net_namespace.h> 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds #include <linux/socket.h> /* for sa_family_t */ 531da177e4SLinus Torvalds #include <net/sock.h> 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds #include <net/sctp/sctp.h> 561da177e4SLinus Torvalds #include <net/sctp/sm.h> 579ad0977fSVlad Yasevich #include <net/sctp/checksum.h> 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds /* Forward declarations for private helpers. */ 60ed106277SNeil Horman static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, 61ed106277SNeil Horman struct sctp_chunk *chunk); 62e83963b7SVlad Yasevich static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, 631da177e4SLinus Torvalds struct sctp_chunk *chunk); 64e83963b7SVlad Yasevich static void sctp_packet_append_data(struct sctp_packet *packet, 65e83963b7SVlad Yasevich struct sctp_chunk *chunk); 66e83963b7SVlad Yasevich static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet, 67e83963b7SVlad Yasevich struct sctp_chunk *chunk, 68e83963b7SVlad Yasevich u16 chunk_len); 691da177e4SLinus Torvalds 70be297143SWei Yongjun static void sctp_packet_reset(struct sctp_packet *packet) 71be297143SWei Yongjun { 72be297143SWei Yongjun packet->size = packet->overhead; 73be297143SWei Yongjun packet->has_cookie_echo = 0; 74be297143SWei Yongjun packet->has_sack = 0; 75be297143SWei Yongjun packet->has_data = 0; 76be297143SWei Yongjun packet->has_auth = 0; 77be297143SWei Yongjun packet->ipfragok = 0; 78be297143SWei Yongjun packet->auth = NULL; 79be297143SWei Yongjun } 80be297143SWei Yongjun 811da177e4SLinus Torvalds /* Config a packet. 821da177e4SLinus Torvalds * This appears to be a followup set of initializations. 831da177e4SLinus Torvalds */ 8466b91d2cSMarcelo Ricardo Leitner void sctp_packet_config(struct sctp_packet *packet, __u32 vtag, 8566b91d2cSMarcelo Ricardo Leitner int ecn_capable) 861da177e4SLinus Torvalds { 8790017accSMarcelo Ricardo Leitner struct sctp_transport *tp = packet->transport; 8890017accSMarcelo Ricardo Leitner struct sctp_association *asoc = tp->asoc; 891da177e4SLinus Torvalds 90bb33381dSDaniel Borkmann pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds packet->vtag = vtag; 931da177e4SLinus Torvalds 9490017accSMarcelo Ricardo Leitner if (asoc && tp->dst) { 9590017accSMarcelo Ricardo Leitner struct sock *sk = asoc->base.sk; 9690017accSMarcelo Ricardo Leitner 9790017accSMarcelo Ricardo Leitner rcu_read_lock(); 9890017accSMarcelo Ricardo Leitner if (__sk_dst_get(sk) != tp->dst) { 9990017accSMarcelo Ricardo Leitner dst_hold(tp->dst); 10090017accSMarcelo Ricardo Leitner sk_setup_caps(sk, tp->dst); 10190017accSMarcelo Ricardo Leitner } 10290017accSMarcelo Ricardo Leitner 10390017accSMarcelo Ricardo Leitner if (sk_can_gso(sk)) { 10490017accSMarcelo Ricardo Leitner struct net_device *dev = tp->dst->dev; 10590017accSMarcelo Ricardo Leitner 10690017accSMarcelo Ricardo Leitner packet->max_size = dev->gso_max_size; 10790017accSMarcelo Ricardo Leitner } else { 10890017accSMarcelo Ricardo Leitner packet->max_size = asoc->pathmtu; 10990017accSMarcelo Ricardo Leitner } 11090017accSMarcelo Ricardo Leitner rcu_read_unlock(); 11190017accSMarcelo Ricardo Leitner 11290017accSMarcelo Ricardo Leitner } else { 11390017accSMarcelo Ricardo Leitner packet->max_size = tp->pathmtu; 11490017accSMarcelo Ricardo Leitner } 11590017accSMarcelo Ricardo Leitner 1161da177e4SLinus Torvalds if (ecn_capable && sctp_packet_empty(packet)) { 11790017accSMarcelo Ricardo Leitner struct sctp_chunk *chunk; 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds /* If there a is a prepend chunk stick it on the list before 1201da177e4SLinus Torvalds * any other chunks get appended. 1211da177e4SLinus Torvalds */ 12290017accSMarcelo Ricardo Leitner chunk = sctp_get_ecne_prepend(asoc); 1231da177e4SLinus Torvalds if (chunk) 1241da177e4SLinus Torvalds sctp_packet_append_chunk(packet, chunk); 1251da177e4SLinus Torvalds } 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds /* Initialize the packet structure. */ 12966b91d2cSMarcelo Ricardo Leitner void sctp_packet_init(struct sctp_packet *packet, 1301da177e4SLinus Torvalds struct sctp_transport *transport, 1311da177e4SLinus Torvalds __u16 sport, __u16 dport) 1321da177e4SLinus Torvalds { 1331da177e4SLinus Torvalds struct sctp_association *asoc = transport->asoc; 1341da177e4SLinus Torvalds size_t overhead; 1351da177e4SLinus Torvalds 136bb33381dSDaniel Borkmann pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport); 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds packet->transport = transport; 1391da177e4SLinus Torvalds packet->source_port = sport; 1401da177e4SLinus Torvalds packet->destination_port = dport; 14179af02c2SDavid S. Miller INIT_LIST_HEAD(&packet->chunk_list); 1421da177e4SLinus Torvalds if (asoc) { 1431da177e4SLinus Torvalds struct sctp_sock *sp = sctp_sk(asoc->base.sk); 1441da177e4SLinus Torvalds overhead = sp->pf->af->net_header_len; 1451da177e4SLinus Torvalds } else { 1461da177e4SLinus Torvalds overhead = sizeof(struct ipv6hdr); 1471da177e4SLinus Torvalds } 1481da177e4SLinus Torvalds overhead += sizeof(struct sctphdr); 1491da177e4SLinus Torvalds packet->overhead = overhead; 150be297143SWei Yongjun sctp_packet_reset(packet); 1511da177e4SLinus Torvalds packet->vtag = 0; 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds /* Free a packet. */ 1551da177e4SLinus Torvalds void sctp_packet_free(struct sctp_packet *packet) 1561da177e4SLinus Torvalds { 15779af02c2SDavid S. Miller struct sctp_chunk *chunk, *tmp; 1581da177e4SLinus Torvalds 159bb33381dSDaniel Borkmann pr_debug("%s: packet:%p\n", __func__, packet); 1601da177e4SLinus Torvalds 16179af02c2SDavid S. Miller list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { 16279af02c2SDavid S. Miller list_del_init(&chunk->list); 1631da177e4SLinus Torvalds sctp_chunk_free(chunk); 16479af02c2SDavid S. Miller } 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /* This routine tries to append the chunk to the offered packet. If adding 1681da177e4SLinus Torvalds * the chunk causes the packet to exceed the path MTU and COOKIE_ECHO chunk 1691da177e4SLinus Torvalds * is not present in the packet, it transmits the input packet. 1701da177e4SLinus Torvalds * Data can be bundled with a packet containing a COOKIE_ECHO chunk as long 1711da177e4SLinus Torvalds * as it can fit in the packet, but any more data that does not fit in this 1721da177e4SLinus Torvalds * packet can be sent only after receiving the COOKIE_ACK. 1731da177e4SLinus Torvalds */ 1741da177e4SLinus Torvalds sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, 1752e3216cdSVlad Yasevich struct sctp_chunk *chunk, 176cea8768fSMarcelo Ricardo Leitner int one_packet, gfp_t gfp) 1771da177e4SLinus Torvalds { 1781da177e4SLinus Torvalds sctp_xmit_t retval; 1791da177e4SLinus Torvalds 1803b55a537SDavid S. Miller pr_debug("%s: packet:%p size:%Zu chunk:%p size:%d\n", __func__, 181942b3235SMarcelo Ricardo Leitner packet, packet->size, chunk, chunk->skb ? chunk->skb->len : -1); 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds switch ((retval = (sctp_packet_append_chunk(packet, chunk)))) { 1841da177e4SLinus Torvalds case SCTP_XMIT_PMTU_FULL: 1851da177e4SLinus Torvalds if (!packet->has_cookie_echo) { 18664519440SXin Long int error = 0; 18764519440SXin Long 188cea8768fSMarcelo Ricardo Leitner error = sctp_packet_transmit(packet, gfp); 1891da177e4SLinus Torvalds if (error < 0) 1901da177e4SLinus Torvalds chunk->skb->sk->sk_err = -error; 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds /* If we have an empty packet, then we can NOT ever 1931da177e4SLinus Torvalds * return PMTU_FULL. 1941da177e4SLinus Torvalds */ 1952e3216cdSVlad Yasevich if (!one_packet) 1962e3216cdSVlad Yasevich retval = sctp_packet_append_chunk(packet, 1972e3216cdSVlad Yasevich chunk); 1981da177e4SLinus Torvalds } 1991da177e4SLinus Torvalds break; 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds case SCTP_XMIT_RWND_FULL: 2021da177e4SLinus Torvalds case SCTP_XMIT_OK: 203526cbef7SDavid Laight case SCTP_XMIT_DELAY: 2041da177e4SLinus Torvalds break; 2053ff50b79SStephen Hemminger } 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds return retval; 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds 2104cd57c80SVlad Yasevich /* Try to bundle an auth chunk into the packet. */ 2114cd57c80SVlad Yasevich static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt, 2124cd57c80SVlad Yasevich struct sctp_chunk *chunk) 2134cd57c80SVlad Yasevich { 2144cd57c80SVlad Yasevich struct sctp_association *asoc = pkt->transport->asoc; 2154cd57c80SVlad Yasevich struct sctp_chunk *auth; 2164cd57c80SVlad Yasevich sctp_xmit_t retval = SCTP_XMIT_OK; 2174cd57c80SVlad Yasevich 2184cd57c80SVlad Yasevich /* if we don't have an association, we can't do authentication */ 2194cd57c80SVlad Yasevich if (!asoc) 2204cd57c80SVlad Yasevich return retval; 2214cd57c80SVlad Yasevich 2224cd57c80SVlad Yasevich /* See if this is an auth chunk we are bundling or if 2234cd57c80SVlad Yasevich * auth is already bundled. 2244cd57c80SVlad Yasevich */ 2254007cc88SVlad Yasevich if (chunk->chunk_hdr->type == SCTP_CID_AUTH || pkt->has_auth) 2264cd57c80SVlad Yasevich return retval; 2274cd57c80SVlad Yasevich 2284cd57c80SVlad Yasevich /* if the peer did not request this chunk to be authenticated, 2294cd57c80SVlad Yasevich * don't do it 2304cd57c80SVlad Yasevich */ 2314cd57c80SVlad Yasevich if (!chunk->auth) 2324cd57c80SVlad Yasevich return retval; 2334cd57c80SVlad Yasevich 2344cd57c80SVlad Yasevich auth = sctp_make_auth(asoc); 2354cd57c80SVlad Yasevich if (!auth) 2364cd57c80SVlad Yasevich return retval; 2374cd57c80SVlad Yasevich 238ed106277SNeil Horman retval = __sctp_packet_append_chunk(pkt, auth); 239ed106277SNeil Horman 240ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 241ed106277SNeil Horman sctp_chunk_free(auth); 2424cd57c80SVlad Yasevich 2434cd57c80SVlad Yasevich return retval; 2444cd57c80SVlad Yasevich } 2454cd57c80SVlad Yasevich 2461da177e4SLinus Torvalds /* Try to bundle a SACK with the packet. */ 2471da177e4SLinus Torvalds static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, 2481da177e4SLinus Torvalds struct sctp_chunk *chunk) 2491da177e4SLinus Torvalds { 2501da177e4SLinus Torvalds sctp_xmit_t retval = SCTP_XMIT_OK; 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds /* If sending DATA and haven't aleady bundled a SACK, try to 2531da177e4SLinus Torvalds * bundle one in to the packet. 2541da177e4SLinus Torvalds */ 2551da177e4SLinus Torvalds if (sctp_chunk_is_data(chunk) && !pkt->has_sack && 2561da177e4SLinus Torvalds !pkt->has_cookie_echo) { 2571da177e4SLinus Torvalds struct sctp_association *asoc; 258af87b823SDoug Graham struct timer_list *timer; 2591da177e4SLinus Torvalds asoc = pkt->transport->asoc; 260af87b823SDoug Graham timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK]; 2611da177e4SLinus Torvalds 262af87b823SDoug Graham /* If the SACK timer is running, we have a pending SACK */ 263af87b823SDoug Graham if (timer_pending(timer)) { 2641da177e4SLinus Torvalds struct sctp_chunk *sack; 2654244854dSNeil Horman 2664244854dSNeil Horman if (pkt->transport->sack_generation != 2674244854dSNeil Horman pkt->transport->asoc->peer.sack_generation) 2684244854dSNeil Horman return retval; 2694244854dSNeil Horman 2701da177e4SLinus Torvalds asoc->a_rwnd = asoc->rwnd; 2711da177e4SLinus Torvalds sack = sctp_make_sack(asoc); 2721da177e4SLinus Torvalds if (sack) { 273ed106277SNeil Horman retval = __sctp_packet_append_chunk(pkt, sack); 274ed106277SNeil Horman if (retval != SCTP_XMIT_OK) { 275ed106277SNeil Horman sctp_chunk_free(sack); 276ed106277SNeil Horman goto out; 277ed106277SNeil Horman } 2781da177e4SLinus Torvalds asoc->peer.sack_needed = 0; 279af87b823SDoug Graham if (del_timer(timer)) 2801da177e4SLinus Torvalds sctp_association_put(asoc); 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds } 284ed106277SNeil Horman out: 2851da177e4SLinus Torvalds return retval; 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds 288ed106277SNeil Horman 2891da177e4SLinus Torvalds /* Append a chunk to the offered packet reporting back any inability to do 2901da177e4SLinus Torvalds * so. 2911da177e4SLinus Torvalds */ 292ed106277SNeil Horman static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, 2931da177e4SLinus Torvalds struct sctp_chunk *chunk) 2941da177e4SLinus Torvalds { 2951da177e4SLinus Torvalds sctp_xmit_t retval = SCTP_XMIT_OK; 296e2f036a9SMarcelo Ricardo Leitner __u16 chunk_len = SCTP_PAD4(ntohs(chunk->chunk_hdr->length)); 2971da177e4SLinus Torvalds 298e83963b7SVlad Yasevich /* Check to see if this chunk will fit into the packet */ 299e83963b7SVlad Yasevich retval = sctp_packet_will_fit(packet, chunk, chunk_len); 300e83963b7SVlad Yasevich if (retval != SCTP_XMIT_OK) 3011da177e4SLinus Torvalds goto finish; 3021da177e4SLinus Torvalds 303e83963b7SVlad Yasevich /* We believe that this chunk is OK to add to the packet */ 3044cd57c80SVlad Yasevich switch (chunk->chunk_hdr->type) { 3054cd57c80SVlad Yasevich case SCTP_CID_DATA: 306e83963b7SVlad Yasevich /* Account for the data being in the packet */ 307e83963b7SVlad Yasevich sctp_packet_append_data(packet, chunk); 3081da177e4SLinus Torvalds /* Disallow SACK bundling after DATA. */ 3091da177e4SLinus Torvalds packet->has_sack = 1; 3104cd57c80SVlad Yasevich /* Disallow AUTH bundling after DATA */ 3114cd57c80SVlad Yasevich packet->has_auth = 1; 3124cd57c80SVlad Yasevich /* Let it be knows that packet has DATA in it */ 3134cd57c80SVlad Yasevich packet->has_data = 1; 314759af00eSVlad Yasevich /* timestamp the chunk for rtx purposes */ 315759af00eSVlad Yasevich chunk->sent_at = jiffies; 316a6c2f792SXin Long /* Mainly used for prsctp RTX policy */ 317a6c2f792SXin Long chunk->sent_count++; 3184cd57c80SVlad Yasevich break; 3194cd57c80SVlad Yasevich case SCTP_CID_COOKIE_ECHO: 3201da177e4SLinus Torvalds packet->has_cookie_echo = 1; 3214cd57c80SVlad Yasevich break; 3224cd57c80SVlad Yasevich 3234cd57c80SVlad Yasevich case SCTP_CID_SACK: 3241da177e4SLinus Torvalds packet->has_sack = 1; 325196d6759SMichele Baldessari if (chunk->asoc) 326196d6759SMichele Baldessari chunk->asoc->stats.osacks++; 3274cd57c80SVlad Yasevich break; 3284cd57c80SVlad Yasevich 3294cd57c80SVlad Yasevich case SCTP_CID_AUTH: 3304cd57c80SVlad Yasevich packet->has_auth = 1; 3314cd57c80SVlad Yasevich packet->auth = chunk; 3324cd57c80SVlad Yasevich break; 3334cd57c80SVlad Yasevich } 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds /* It is OK to send this chunk. */ 33679af02c2SDavid S. Miller list_add_tail(&chunk->list, &packet->chunk_list); 3371da177e4SLinus Torvalds packet->size += chunk_len; 3381da177e4SLinus Torvalds chunk->transport = packet->transport; 3391da177e4SLinus Torvalds finish: 3401da177e4SLinus Torvalds return retval; 3411da177e4SLinus Torvalds } 3421da177e4SLinus Torvalds 343ed106277SNeil Horman /* Append a chunk to the offered packet reporting back any inability to do 344ed106277SNeil Horman * so. 345ed106277SNeil Horman */ 346ed106277SNeil Horman sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, 347ed106277SNeil Horman struct sctp_chunk *chunk) 348ed106277SNeil Horman { 349ed106277SNeil Horman sctp_xmit_t retval = SCTP_XMIT_OK; 350ed106277SNeil Horman 351bb33381dSDaniel Borkmann pr_debug("%s: packet:%p chunk:%p\n", __func__, packet, chunk); 352ed106277SNeil Horman 353ed106277SNeil Horman /* Data chunks are special. Before seeing what else we can 354ed106277SNeil Horman * bundle into this packet, check to see if we are allowed to 355ed106277SNeil Horman * send this DATA. 356ed106277SNeil Horman */ 357ed106277SNeil Horman if (sctp_chunk_is_data(chunk)) { 358ed106277SNeil Horman retval = sctp_packet_can_append_data(packet, chunk); 359ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 360ed106277SNeil Horman goto finish; 361ed106277SNeil Horman } 362ed106277SNeil Horman 363ed106277SNeil Horman /* Try to bundle AUTH chunk */ 364ed106277SNeil Horman retval = sctp_packet_bundle_auth(packet, chunk); 365ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 366ed106277SNeil Horman goto finish; 367ed106277SNeil Horman 368ed106277SNeil Horman /* Try to bundle SACK chunk */ 369ed106277SNeil Horman retval = sctp_packet_bundle_sack(packet, chunk); 370ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 371ed106277SNeil Horman goto finish; 372ed106277SNeil Horman 373ed106277SNeil Horman retval = __sctp_packet_append_chunk(packet, chunk); 374ed106277SNeil Horman 375ed106277SNeil Horman finish: 376ed106277SNeil Horman return retval; 377ed106277SNeil Horman } 378ed106277SNeil Horman 3794c3a5bdaSThomas Graf static void sctp_packet_release_owner(struct sk_buff *skb) 3804c3a5bdaSThomas Graf { 3814c3a5bdaSThomas Graf sk_free(skb->sk); 3824c3a5bdaSThomas Graf } 3834c3a5bdaSThomas Graf 3844c3a5bdaSThomas Graf static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk) 3854c3a5bdaSThomas Graf { 3864c3a5bdaSThomas Graf skb_orphan(skb); 3874c3a5bdaSThomas Graf skb->sk = sk; 3884c3a5bdaSThomas Graf skb->destructor = sctp_packet_release_owner; 3894c3a5bdaSThomas Graf 3904c3a5bdaSThomas Graf /* 3914c3a5bdaSThomas Graf * The data chunks have already been accounted for in sctp_sendmsg(), 3924c3a5bdaSThomas Graf * therefore only reserve a single byte to keep socket around until 3934c3a5bdaSThomas Graf * the packet has been transmitted. 3944c3a5bdaSThomas Graf */ 3954c3a5bdaSThomas Graf atomic_inc(&sk->sk_wmem_alloc); 3964c3a5bdaSThomas Graf } 3974c3a5bdaSThomas Graf 398e4ff952aSXin Long static int sctp_packet_pack(struct sctp_packet *packet, 399e4ff952aSXin Long struct sk_buff *head, int gso, gfp_t gfp) 4001da177e4SLinus Torvalds { 4011da177e4SLinus Torvalds struct sctp_transport *tp = packet->transport; 402e4ff952aSXin Long struct sctp_auth_chunk *auth = NULL; 40379af02c2SDavid S. Miller struct sctp_chunk *chunk, *tmp; 404e4ff952aSXin Long int pkt_count = 0, pkt_size; 405e4ff952aSXin Long struct sock *sk = head->sk; 406e4ff952aSXin Long struct sk_buff *nskb; 407ecc515d7SXin Long int auth_len = 0; 4081da177e4SLinus Torvalds 40990017accSMarcelo Ricardo Leitner if (gso) { 41090017accSMarcelo Ricardo Leitner skb_shinfo(head)->gso_type = sk->sk_gso_type; 411e4ff952aSXin Long NAPI_GRO_CB(head)->last = head; 412e4ff952aSXin Long } else { 413e4ff952aSXin Long nskb = head; 414e4ff952aSXin Long pkt_size = packet->size; 415e4ff952aSXin Long goto merge; 41690017accSMarcelo Ricardo Leitner } 4171da177e4SLinus Torvalds 41890017accSMarcelo Ricardo Leitner do { 419e4ff952aSXin Long /* calculate the pkt_size and alloc nskb */ 42090017accSMarcelo Ricardo Leitner pkt_size = packet->overhead; 421e4ff952aSXin Long list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, 422e4ff952aSXin Long list) { 423e2f036a9SMarcelo Ricardo Leitner int padded = SCTP_PAD4(chunk->skb->len); 42490017accSMarcelo Ricardo Leitner 425ecc515d7SXin Long if (chunk == packet->auth) 426ecc515d7SXin Long auth_len = padded; 427ecc515d7SXin Long else if (auth_len + padded + packet->overhead > 428ecc515d7SXin Long tp->pathmtu) 429e4ff952aSXin Long return 0; 430ecc515d7SXin Long else if (pkt_size + padded > tp->pathmtu) 43190017accSMarcelo Ricardo Leitner break; 43290017accSMarcelo Ricardo Leitner pkt_size += padded; 43390017accSMarcelo Ricardo Leitner } 43490017accSMarcelo Ricardo Leitner nskb = alloc_skb(pkt_size + MAX_HEADER, gfp); 43590017accSMarcelo Ricardo Leitner if (!nskb) 436e4ff952aSXin Long return 0; 43790017accSMarcelo Ricardo Leitner skb_reserve(nskb, packet->overhead + MAX_HEADER); 4381da177e4SLinus Torvalds 439e4ff952aSXin Long merge: 440e4ff952aSXin Long /* merge chunks into nskb and append nskb into head list */ 44190017accSMarcelo Ricardo Leitner pkt_size -= packet->overhead; 44279af02c2SDavid S. Miller list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { 443e4ff952aSXin Long int padding; 444e4ff952aSXin Long 44579af02c2SDavid S. Miller list_del_init(&chunk->list); 4461da177e4SLinus Torvalds if (sctp_chunk_is_data(chunk)) { 447cc6ac9bcSXin Long if (!sctp_chunk_retransmitted(chunk) && 448cc6ac9bcSXin Long !tp->rto_pending) { 4491da177e4SLinus Torvalds chunk->rtt_in_progress = 1; 4501da177e4SLinus Torvalds tp->rto_pending = 1; 4511da177e4SLinus Torvalds } 4521da177e4SLinus Torvalds } 4531da177e4SLinus Torvalds 454e2f036a9SMarcelo Ricardo Leitner padding = SCTP_PAD4(chunk->skb->len) - chunk->skb->len; 4551da177e4SLinus Torvalds if (padding) 4561da177e4SLinus Torvalds memset(skb_put(chunk->skb, padding), 0, padding); 4571da177e4SLinus Torvalds 4584cd57c80SVlad Yasevich if (chunk == packet->auth) 459e4ff952aSXin Long auth = (struct sctp_auth_chunk *) 460e4ff952aSXin Long skb_tail_pointer(nskb); 4614cd57c80SVlad Yasevich 462e4ff952aSXin Long memcpy(skb_put(nskb, chunk->skb->len), chunk->skb->data, 463e4ff952aSXin Long chunk->skb->len); 4641da177e4SLinus Torvalds 46590017accSMarcelo Ricardo Leitner pr_debug("*** Chunk:%p[%s] %s 0x%x, length:%d, chunk->skb->len:%d, rtt_in_progress:%d\n", 46690017accSMarcelo Ricardo Leitner chunk, 467bb33381dSDaniel Borkmann sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)), 4681da177e4SLinus Torvalds chunk->has_tsn ? "TSN" : "No TSN", 469bb33381dSDaniel Borkmann chunk->has_tsn ? ntohl(chunk->subh.data_hdr->tsn) : 0, 470bb33381dSDaniel Borkmann ntohs(chunk->chunk_hdr->length), chunk->skb->len, 471bb33381dSDaniel Borkmann chunk->rtt_in_progress); 4721da177e4SLinus Torvalds 473e2f036a9SMarcelo Ricardo Leitner pkt_size -= SCTP_PAD4(chunk->skb->len); 47490017accSMarcelo Ricardo Leitner 475f1533cceSMarcelo Ricardo Leitner if (!sctp_chunk_is_data(chunk) && chunk != packet->auth) 4761da177e4SLinus Torvalds sctp_chunk_free(chunk); 47790017accSMarcelo Ricardo Leitner 47890017accSMarcelo Ricardo Leitner if (!pkt_size) 47990017accSMarcelo Ricardo Leitner break; 4801da177e4SLinus Torvalds } 4811da177e4SLinus Torvalds 482e4ff952aSXin Long if (auth) { 483e4ff952aSXin Long sctp_auth_calculate_hmac(tp->asoc, nskb, auth, gfp); 484e4ff952aSXin Long /* free auth if no more chunks, or add it back */ 485e4ff952aSXin Long if (list_empty(&packet->chunk_list)) 486e4ff952aSXin Long sctp_chunk_free(packet->auth); 487e4ff952aSXin Long else 4881aa25ec2SXin Long list_add(&packet->auth->list, 4891aa25ec2SXin Long &packet->chunk_list); 490f1533cceSMarcelo Ricardo Leitner } 4911da177e4SLinus Torvalds 49290017accSMarcelo Ricardo Leitner if (gso) { 493e4ff952aSXin Long if (skb_gro_receive(&head, nskb)) { 494e4ff952aSXin Long kfree_skb(nskb); 495e4ff952aSXin Long return 0; 496e4ff952aSXin Long } 497e4ff952aSXin Long if (WARN_ON_ONCE(skb_shinfo(head)->gso_segs >= 498e4ff952aSXin Long sk->sk_gso_max_segs)) 499e4ff952aSXin Long return 0; 500e4ff952aSXin Long } 501e4ff952aSXin Long 502e4ff952aSXin Long pkt_count++; 503e4ff952aSXin Long } while (!list_empty(&packet->chunk_list)); 504e4ff952aSXin Long 505e4ff952aSXin Long if (gso) { 50690017accSMarcelo Ricardo Leitner memset(head->cb, 0, max(sizeof(struct inet_skb_parm), 50790017accSMarcelo Ricardo Leitner sizeof(struct inet6_skb_parm))); 508e4ff952aSXin Long skb_shinfo(head)->gso_segs = pkt_count; 50990017accSMarcelo Ricardo Leitner skb_shinfo(head)->gso_size = GSO_BY_FRAGS; 51090017accSMarcelo Ricardo Leitner rcu_read_lock(); 511e4ff952aSXin Long if (skb_dst(head) != tp->dst) { 51290017accSMarcelo Ricardo Leitner dst_hold(tp->dst); 51390017accSMarcelo Ricardo Leitner sk_setup_caps(sk, tp->dst); 51490017accSMarcelo Ricardo Leitner } 51590017accSMarcelo Ricardo Leitner rcu_read_unlock(); 516e4ff952aSXin Long goto chksum; 517e4ff952aSXin Long } 518e4ff952aSXin Long 519e4ff952aSXin Long if (sctp_checksum_disable) 520e4ff952aSXin Long return 1; 521e4ff952aSXin Long 522e4ff952aSXin Long if (!(skb_dst(head)->dev->features & NETIF_F_SCTP_CRC) || 523e4ff952aSXin Long dst_xfrm(skb_dst(head)) || packet->ipfragok) { 524e4ff952aSXin Long struct sctphdr *sh = 525e4ff952aSXin Long (struct sctphdr *)skb_transport_header(head); 526e4ff952aSXin Long 527e4ff952aSXin Long sh->checksum = sctp_compute_cksum(head, 0); 528e4ff952aSXin Long } else { 529e4ff952aSXin Long chksum: 530e4ff952aSXin Long head->ip_summed = CHECKSUM_PARTIAL; 531e4ff952aSXin Long head->csum_start = skb_transport_header(head) - head->head; 532e4ff952aSXin Long head->csum_offset = offsetof(struct sctphdr, checksum); 533e4ff952aSXin Long } 534e4ff952aSXin Long 535e4ff952aSXin Long return pkt_count; 536e4ff952aSXin Long } 537e4ff952aSXin Long 538e4ff952aSXin Long /* All packets are sent to the network through this function from 539e4ff952aSXin Long * sctp_outq_tail(). 540e4ff952aSXin Long * 541e4ff952aSXin Long * The return value is always 0 for now. 542e4ff952aSXin Long */ 543e4ff952aSXin Long int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) 544e4ff952aSXin Long { 545e4ff952aSXin Long struct sctp_transport *tp = packet->transport; 546e4ff952aSXin Long struct sctp_association *asoc = tp->asoc; 547e4ff952aSXin Long struct sctp_chunk *chunk, *tmp; 548e4ff952aSXin Long int pkt_count, gso = 0; 549*c86a773cSJulian Anastasov int confirm; 550e4ff952aSXin Long struct dst_entry *dst; 551e4ff952aSXin Long struct sk_buff *head; 552e4ff952aSXin Long struct sctphdr *sh; 553e4ff952aSXin Long struct sock *sk; 554e4ff952aSXin Long 555e4ff952aSXin Long pr_debug("%s: packet:%p\n", __func__, packet); 556e4ff952aSXin Long if (list_empty(&packet->chunk_list)) 557e4ff952aSXin Long return 0; 558e4ff952aSXin Long chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list); 559e4ff952aSXin Long sk = chunk->skb->sk; 560e4ff952aSXin Long 561e4ff952aSXin Long /* check gso */ 562e4ff952aSXin Long if (packet->size > tp->pathmtu && !packet->ipfragok) { 563e4ff952aSXin Long if (!sk_can_gso(sk)) { 564e4ff952aSXin Long pr_err_once("Trying to GSO but underlying device doesn't support it."); 565e4ff952aSXin Long goto out; 566e4ff952aSXin Long } 567e4ff952aSXin Long gso = 1; 568e4ff952aSXin Long } 569e4ff952aSXin Long 570e4ff952aSXin Long /* alloc head skb */ 571e4ff952aSXin Long head = alloc_skb((gso ? packet->overhead : packet->size) + 572e4ff952aSXin Long MAX_HEADER, gfp); 573e4ff952aSXin Long if (!head) 574e4ff952aSXin Long goto out; 575e4ff952aSXin Long skb_reserve(head, packet->overhead + MAX_HEADER); 576e4ff952aSXin Long sctp_packet_set_owner_w(head, sk); 577e4ff952aSXin Long 578e4ff952aSXin Long /* set sctp header */ 579e4ff952aSXin Long sh = (struct sctphdr *)skb_push(head, sizeof(struct sctphdr)); 580e4ff952aSXin Long skb_reset_transport_header(head); 581e4ff952aSXin Long sh->source = htons(packet->source_port); 582e4ff952aSXin Long sh->dest = htons(packet->destination_port); 583e4ff952aSXin Long sh->vtag = htonl(packet->vtag); 584e4ff952aSXin Long sh->checksum = 0; 585e4ff952aSXin Long 586e4ff952aSXin Long /* update dst if in need */ 587e4ff952aSXin Long if (!sctp_transport_dst_check(tp)) { 588e4ff952aSXin Long sctp_transport_route(tp, NULL, sctp_sk(sk)); 589e4ff952aSXin Long if (asoc && asoc->param_flags & SPP_PMTUD_ENABLE) 590e4ff952aSXin Long sctp_assoc_sync_pmtu(sk, asoc); 591e4ff952aSXin Long } 592e4ff952aSXin Long dst = dst_clone(tp->dst); 593e4ff952aSXin Long if (!dst) { 594e4ff952aSXin Long IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); 595e4ff952aSXin Long kfree_skb(head); 596e4ff952aSXin Long goto out; 597e4ff952aSXin Long } 598e4ff952aSXin Long skb_dst_set(head, dst); 599e4ff952aSXin Long 600e4ff952aSXin Long /* pack up chunks */ 601e4ff952aSXin Long pkt_count = sctp_packet_pack(packet, head, gso, gfp); 602e4ff952aSXin Long if (!pkt_count) { 603e4ff952aSXin Long kfree_skb(head); 604e4ff952aSXin Long goto out; 605e4ff952aSXin Long } 606e4ff952aSXin Long pr_debug("***sctp_transmit_packet*** skb->len:%d\n", head->len); 607e4ff952aSXin Long 608e4ff952aSXin Long /* start autoclose timer */ 609e4ff952aSXin Long if (packet->has_data && sctp_state(asoc, ESTABLISHED) && 610e4ff952aSXin Long asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { 611e4ff952aSXin Long struct timer_list *timer = 612e4ff952aSXin Long &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; 613e4ff952aSXin Long unsigned long timeout = 614e4ff952aSXin Long asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; 615e4ff952aSXin Long 616e4ff952aSXin Long if (!mod_timer(timer, jiffies + timeout)) 617e4ff952aSXin Long sctp_association_hold(asoc); 618e4ff952aSXin Long } 619e4ff952aSXin Long 620e4ff952aSXin Long /* sctp xmit */ 621e4ff952aSXin Long tp->af_specific->ecn_capable(sk); 622e4ff952aSXin Long if (asoc) { 623e4ff952aSXin Long asoc->stats.opackets += pkt_count; 624e4ff952aSXin Long if (asoc->peer.last_sent_to != tp) 625e4ff952aSXin Long asoc->peer.last_sent_to = tp; 62690017accSMarcelo Ricardo Leitner } 62790017accSMarcelo Ricardo Leitner head->ignore_df = packet->ipfragok; 628*c86a773cSJulian Anastasov confirm = tp->dst_pending_confirm; 629*c86a773cSJulian Anastasov if (confirm) 630*c86a773cSJulian Anastasov skb_set_dst_pending_confirm(head, 1); 631*c86a773cSJulian Anastasov /* neighbour should be confirmed on successful transmission or 632*c86a773cSJulian Anastasov * positive error 633*c86a773cSJulian Anastasov */ 634*c86a773cSJulian Anastasov if (tp->af_specific->sctp_xmit(head, tp) >= 0 && confirm) 635*c86a773cSJulian Anastasov tp->dst_pending_confirm = 0; 6361da177e4SLinus Torvalds 637e4ff952aSXin Long out: 63879af02c2SDavid S. Miller list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { 63979af02c2SDavid S. Miller list_del_init(&chunk->list); 6401da177e4SLinus Torvalds if (!sctp_chunk_is_data(chunk)) 6411da177e4SLinus Torvalds sctp_chunk_free(chunk); 6421da177e4SLinus Torvalds } 64341001fafSXin Long sctp_packet_reset(packet); 644e4ff952aSXin Long return 0; 6451da177e4SLinus Torvalds } 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds /******************************************************************** 6481da177e4SLinus Torvalds * 2nd Level Abstractions 6491da177e4SLinus Torvalds ********************************************************************/ 6501da177e4SLinus Torvalds 651e83963b7SVlad Yasevich /* This private function check to see if a chunk can be added */ 652e83963b7SVlad Yasevich static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, 6531da177e4SLinus Torvalds struct sctp_chunk *chunk) 6541da177e4SLinus Torvalds { 655e83963b7SVlad Yasevich size_t datasize, rwnd, inflight, flight_size; 6561da177e4SLinus Torvalds struct sctp_transport *transport = packet->transport; 6571da177e4SLinus Torvalds struct sctp_association *asoc = transport->asoc; 6581da177e4SLinus Torvalds struct sctp_outq *q = &asoc->outqueue; 6591da177e4SLinus Torvalds 6601da177e4SLinus Torvalds /* RFC 2960 6.1 Transmission of DATA Chunks 6611da177e4SLinus Torvalds * 6621da177e4SLinus Torvalds * A) At any given time, the data sender MUST NOT transmit new data to 6631da177e4SLinus Torvalds * any destination transport address if its peer's rwnd indicates 6641da177e4SLinus Torvalds * that the peer has no buffer space (i.e. rwnd is 0, see Section 6651da177e4SLinus Torvalds * 6.2.1). However, regardless of the value of rwnd (including if it 6661da177e4SLinus Torvalds * is 0), the data sender can always have one DATA chunk in flight to 6671da177e4SLinus Torvalds * the receiver if allowed by cwnd (see rule B below). This rule 6681da177e4SLinus Torvalds * allows the sender to probe for a change in rwnd that the sender 6691da177e4SLinus Torvalds * missed due to the SACK having been lost in transit from the data 6701da177e4SLinus Torvalds * receiver to the data sender. 6711da177e4SLinus Torvalds */ 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds rwnd = asoc->peer.rwnd; 674e83963b7SVlad Yasevich inflight = q->outstanding_bytes; 675e83963b7SVlad Yasevich flight_size = transport->flight_size; 6761da177e4SLinus Torvalds 6771da177e4SLinus Torvalds datasize = sctp_data_size(chunk); 6781da177e4SLinus Torvalds 679723189faSDavid Laight if (datasize > rwnd && inflight > 0) 6801da177e4SLinus Torvalds /* We have (at least) one data chunk in flight, 6811da177e4SLinus Torvalds * so we can't fall back to rule 6.1 B). 6821da177e4SLinus Torvalds */ 683723189faSDavid Laight return SCTP_XMIT_RWND_FULL; 6841da177e4SLinus Torvalds 6851da177e4SLinus Torvalds /* RFC 2960 6.1 Transmission of DATA Chunks 6861da177e4SLinus Torvalds * 6871da177e4SLinus Torvalds * B) At any given time, the sender MUST NOT transmit new data 6881da177e4SLinus Torvalds * to a given transport address if it has cwnd or more bytes 6891da177e4SLinus Torvalds * of data outstanding to that transport address. 6901da177e4SLinus Torvalds */ 6911da177e4SLinus Torvalds /* RFC 7.2.4 & the Implementers Guide 2.8. 6921da177e4SLinus Torvalds * 6931da177e4SLinus Torvalds * 3) ... 6941da177e4SLinus Torvalds * When a Fast Retransmit is being performed the sender SHOULD 6951da177e4SLinus Torvalds * ignore the value of cwnd and SHOULD NOT delay retransmission. 6961da177e4SLinus Torvalds */ 697723189faSDavid Laight if (chunk->fast_retransmit != SCTP_NEED_FRTX && 698723189faSDavid Laight flight_size >= transport->cwnd) 699723189faSDavid Laight return SCTP_XMIT_RWND_FULL; 7001da177e4SLinus Torvalds 7011da177e4SLinus Torvalds /* Nagle's algorithm to solve small-packet problem: 7021da177e4SLinus Torvalds * Inhibit the sending of new chunks when new outgoing data arrives 7031da177e4SLinus Torvalds * if any previously transmitted data on the connection remains 7041da177e4SLinus Torvalds * unacknowledged. 7051da177e4SLinus Torvalds */ 7061da177e4SLinus Torvalds 707723189faSDavid Laight if (sctp_sk(asoc->base.sk)->nodelay) 708723189faSDavid Laight /* Nagle disabled */ 709723189faSDavid Laight return SCTP_XMIT_OK; 710723189faSDavid Laight 711723189faSDavid Laight if (!sctp_packet_empty(packet)) 712723189faSDavid Laight /* Append to packet */ 713723189faSDavid Laight return SCTP_XMIT_OK; 714723189faSDavid Laight 715723189faSDavid Laight if (inflight == 0) 716723189faSDavid Laight /* Nothing unacked */ 717723189faSDavid Laight return SCTP_XMIT_OK; 718723189faSDavid Laight 719723189faSDavid Laight if (!sctp_state(asoc, ESTABLISHED)) 720723189faSDavid Laight return SCTP_XMIT_OK; 721723189faSDavid Laight 722723189faSDavid Laight /* Check whether this chunk and all the rest of pending data will fit 723723189faSDavid Laight * or delay in hopes of bundling a full sized packet. 7241da177e4SLinus Torvalds */ 725e43569e6SMarcelo Ricardo Leitner if (chunk->skb->len + q->out_qlen > 726e43569e6SMarcelo Ricardo Leitner transport->pathmtu - packet->overhead - sizeof(sctp_data_chunk_t) - 4) 727723189faSDavid Laight /* Enough data queued to fill a packet */ 728723189faSDavid Laight return SCTP_XMIT_OK; 7291da177e4SLinus Torvalds 730723189faSDavid Laight /* Don't delay large message writes that may have been fragmented */ 731723189faSDavid Laight if (!chunk->msg->can_delay) 732723189faSDavid Laight return SCTP_XMIT_OK; 733723189faSDavid Laight 734723189faSDavid Laight /* Defer until all data acked or packet full */ 735526cbef7SDavid Laight return SCTP_XMIT_DELAY; 736e83963b7SVlad Yasevich } 737e83963b7SVlad Yasevich 738e83963b7SVlad Yasevich /* This private function does management things when adding DATA chunk */ 739e83963b7SVlad Yasevich static void sctp_packet_append_data(struct sctp_packet *packet, 740e83963b7SVlad Yasevich struct sctp_chunk *chunk) 741e83963b7SVlad Yasevich { 742e83963b7SVlad Yasevich struct sctp_transport *transport = packet->transport; 743e83963b7SVlad Yasevich size_t datasize = sctp_data_size(chunk); 744e83963b7SVlad Yasevich struct sctp_association *asoc = transport->asoc; 745e83963b7SVlad Yasevich u32 rwnd = asoc->peer.rwnd; 746e83963b7SVlad Yasevich 7471da177e4SLinus Torvalds /* Keep track of how many bytes are in flight over this transport. */ 7481da177e4SLinus Torvalds transport->flight_size += datasize; 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds /* Keep track of how many bytes are in flight to the receiver. */ 7511da177e4SLinus Torvalds asoc->outqueue.outstanding_bytes += datasize; 7521da177e4SLinus Torvalds 753a76c0adfSThomas Graf /* Update our view of the receiver's rwnd. */ 7541da177e4SLinus Torvalds if (datasize < rwnd) 7551da177e4SLinus Torvalds rwnd -= datasize; 7561da177e4SLinus Torvalds else 7571da177e4SLinus Torvalds rwnd = 0; 7581da177e4SLinus Torvalds 7591da177e4SLinus Torvalds asoc->peer.rwnd = rwnd; 760d8dd1578SNeil Horman sctp_chunk_assign_tsn(chunk); 761d8dd1578SNeil Horman sctp_chunk_assign_ssn(chunk); 762e83963b7SVlad Yasevich } 7631da177e4SLinus Torvalds 764e83963b7SVlad Yasevich static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet, 765e83963b7SVlad Yasevich struct sctp_chunk *chunk, 766e83963b7SVlad Yasevich u16 chunk_len) 767e83963b7SVlad Yasevich { 7687303a147SMarcelo Ricardo Leitner size_t psize, pmtu, maxsize; 769e83963b7SVlad Yasevich sctp_xmit_t retval = SCTP_XMIT_OK; 770e83963b7SVlad Yasevich 771e83963b7SVlad Yasevich psize = packet->size; 77290017accSMarcelo Ricardo Leitner if (packet->transport->asoc) 77390017accSMarcelo Ricardo Leitner pmtu = packet->transport->asoc->pathmtu; 77490017accSMarcelo Ricardo Leitner else 77590017accSMarcelo Ricardo Leitner pmtu = packet->transport->pathmtu; 776e83963b7SVlad Yasevich 777e83963b7SVlad Yasevich /* Decide if we need to fragment or resubmit later. */ 77890017accSMarcelo Ricardo Leitner if (psize + chunk_len > pmtu) { 77990017accSMarcelo Ricardo Leitner /* It's OK to fragment at IP level if any one of the following 780e83963b7SVlad Yasevich * is true: 781e83963b7SVlad Yasevich * 1. The packet is empty (meaning this chunk is greater 782e83963b7SVlad Yasevich * the MTU) 78390017accSMarcelo Ricardo Leitner * 2. The packet doesn't have any data in it yet and data 784e83963b7SVlad Yasevich * requires authentication. 785e83963b7SVlad Yasevich */ 78690017accSMarcelo Ricardo Leitner if (sctp_packet_empty(packet) || 787e83963b7SVlad Yasevich (!packet->has_data && chunk->auth)) { 788e83963b7SVlad Yasevich /* We no longer do re-fragmentation. 789e83963b7SVlad Yasevich * Just fragment at the IP layer, if we 790e83963b7SVlad Yasevich * actually hit this condition 791e83963b7SVlad Yasevich */ 792e83963b7SVlad Yasevich packet->ipfragok = 1; 79390017accSMarcelo Ricardo Leitner goto out; 794e83963b7SVlad Yasevich } 795e83963b7SVlad Yasevich 7967303a147SMarcelo Ricardo Leitner /* Similarly, if this chunk was built before a PMTU 7977303a147SMarcelo Ricardo Leitner * reduction, we have to fragment it at IP level now. So 7987303a147SMarcelo Ricardo Leitner * if the packet already contains something, we need to 7997303a147SMarcelo Ricardo Leitner * flush. 8007303a147SMarcelo Ricardo Leitner */ 8017303a147SMarcelo Ricardo Leitner maxsize = pmtu - packet->overhead; 8027303a147SMarcelo Ricardo Leitner if (packet->auth) 803e2f036a9SMarcelo Ricardo Leitner maxsize -= SCTP_PAD4(packet->auth->skb->len); 8047303a147SMarcelo Ricardo Leitner if (chunk_len > maxsize) 8057303a147SMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 8067303a147SMarcelo Ricardo Leitner 80790017accSMarcelo Ricardo Leitner /* It is also okay to fragment if the chunk we are 80890017accSMarcelo Ricardo Leitner * adding is a control chunk, but only if current packet 80990017accSMarcelo Ricardo Leitner * is not a GSO one otherwise it causes fragmentation of 81090017accSMarcelo Ricardo Leitner * a large frame. So in this case we allow the 81190017accSMarcelo Ricardo Leitner * fragmentation by forcing it to be in a new packet. 81290017accSMarcelo Ricardo Leitner */ 81390017accSMarcelo Ricardo Leitner if (!sctp_chunk_is_data(chunk) && packet->has_data) 81490017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 81590017accSMarcelo Ricardo Leitner 81690017accSMarcelo Ricardo Leitner if (psize + chunk_len > packet->max_size) 81790017accSMarcelo Ricardo Leitner /* Hit GSO/PMTU limit, gotta flush */ 81890017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 81990017accSMarcelo Ricardo Leitner 82090017accSMarcelo Ricardo Leitner if (!packet->transport->burst_limited && 82190017accSMarcelo Ricardo Leitner psize + chunk_len > (packet->transport->cwnd >> 1)) 82290017accSMarcelo Ricardo Leitner /* Do not allow a single GSO packet to use more 82390017accSMarcelo Ricardo Leitner * than half of cwnd. 82490017accSMarcelo Ricardo Leitner */ 82590017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 82690017accSMarcelo Ricardo Leitner 82790017accSMarcelo Ricardo Leitner if (packet->transport->burst_limited && 82890017accSMarcelo Ricardo Leitner psize + chunk_len > (packet->transport->burst_limited >> 1)) 82990017accSMarcelo Ricardo Leitner /* Do not allow a single GSO packet to use more 83090017accSMarcelo Ricardo Leitner * than half of original cwnd. 83190017accSMarcelo Ricardo Leitner */ 83290017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 83390017accSMarcelo Ricardo Leitner /* Otherwise it will fit in the GSO packet */ 83490017accSMarcelo Ricardo Leitner } 83590017accSMarcelo Ricardo Leitner 83690017accSMarcelo Ricardo Leitner out: 8371da177e4SLinus Torvalds return retval; 8381da177e4SLinus Torvalds } 839