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; 89df2729c3SXin Long struct sock *sk; 901da177e4SLinus Torvalds 91bb33381dSDaniel Borkmann pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); 921da177e4SLinus Torvalds packet->vtag = vtag; 931da177e4SLinus Torvalds 94df2729c3SXin Long /* do the following jobs only once for a flush schedule */ 95df2729c3SXin Long if (!sctp_packet_empty(packet)) 96df2729c3SXin Long return; 9790017accSMarcelo Ricardo Leitner 98df2729c3SXin Long /* set packet max_size with pathmtu */ 99df2729c3SXin Long packet->max_size = tp->pathmtu; 100df2729c3SXin Long if (!asoc) 101df2729c3SXin Long return; 102df2729c3SXin Long 103df2729c3SXin Long /* update dst or transport pathmtu if in need */ 104df2729c3SXin Long sk = asoc->base.sk; 105df2729c3SXin Long if (!sctp_transport_dst_check(tp)) { 106df2729c3SXin Long sctp_transport_route(tp, NULL, sctp_sk(sk)); 107df2729c3SXin Long if (asoc->param_flags & SPP_PMTUD_ENABLE) 1083ebfdf08SXin Long sctp_assoc_sync_pmtu(asoc); 109df2729c3SXin Long } else if (!sctp_transport_pmtu_check(tp)) { 110df2729c3SXin Long if (asoc->param_flags & SPP_PMTUD_ENABLE) 1113ebfdf08SXin Long sctp_assoc_sync_pmtu(asoc); 112df2729c3SXin Long } 113df2729c3SXin Long 114df2729c3SXin Long /* If there a is a prepend chunk stick it on the list before 115df2729c3SXin Long * any other chunks get appended. 116df2729c3SXin Long */ 117df2729c3SXin Long if (ecn_capable) { 118df2729c3SXin Long struct sctp_chunk *chunk = sctp_get_ecne_prepend(asoc); 119df2729c3SXin Long 120df2729c3SXin Long if (chunk) 121df2729c3SXin Long sctp_packet_append_chunk(packet, chunk); 122df2729c3SXin Long } 123df2729c3SXin Long 124df2729c3SXin Long if (!tp->dst) 125df2729c3SXin Long return; 126df2729c3SXin Long 127df2729c3SXin Long /* set packet max_size with gso_max_size if gso is enabled*/ 12890017accSMarcelo Ricardo Leitner rcu_read_lock(); 12990017accSMarcelo Ricardo Leitner if (__sk_dst_get(sk) != tp->dst) { 13090017accSMarcelo Ricardo Leitner dst_hold(tp->dst); 13190017accSMarcelo Ricardo Leitner sk_setup_caps(sk, tp->dst); 13290017accSMarcelo Ricardo Leitner } 133df2729c3SXin Long packet->max_size = sk_can_gso(sk) ? tp->dst->dev->gso_max_size 134df2729c3SXin Long : asoc->pathmtu; 13590017accSMarcelo Ricardo Leitner rcu_read_unlock(); 1361da177e4SLinus Torvalds } 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds /* Initialize the packet structure. */ 13966b91d2cSMarcelo Ricardo Leitner void sctp_packet_init(struct sctp_packet *packet, 1401da177e4SLinus Torvalds struct sctp_transport *transport, 1411da177e4SLinus Torvalds __u16 sport, __u16 dport) 1421da177e4SLinus Torvalds { 1431da177e4SLinus Torvalds struct sctp_association *asoc = transport->asoc; 1441da177e4SLinus Torvalds size_t overhead; 1451da177e4SLinus Torvalds 146bb33381dSDaniel Borkmann pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport); 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds packet->transport = transport; 1491da177e4SLinus Torvalds packet->source_port = sport; 1501da177e4SLinus Torvalds packet->destination_port = dport; 15179af02c2SDavid S. Miller INIT_LIST_HEAD(&packet->chunk_list); 1521da177e4SLinus Torvalds if (asoc) { 1531da177e4SLinus Torvalds struct sctp_sock *sp = sctp_sk(asoc->base.sk); 1541da177e4SLinus Torvalds overhead = sp->pf->af->net_header_len; 1551da177e4SLinus Torvalds } else { 1561da177e4SLinus Torvalds overhead = sizeof(struct ipv6hdr); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds overhead += sizeof(struct sctphdr); 1591da177e4SLinus Torvalds packet->overhead = overhead; 160be297143SWei Yongjun sctp_packet_reset(packet); 1611da177e4SLinus Torvalds packet->vtag = 0; 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds /* Free a packet. */ 1651da177e4SLinus Torvalds void sctp_packet_free(struct sctp_packet *packet) 1661da177e4SLinus Torvalds { 16779af02c2SDavid S. Miller struct sctp_chunk *chunk, *tmp; 1681da177e4SLinus Torvalds 169bb33381dSDaniel Borkmann pr_debug("%s: packet:%p\n", __func__, packet); 1701da177e4SLinus Torvalds 17179af02c2SDavid S. Miller list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { 17279af02c2SDavid S. Miller list_del_init(&chunk->list); 1731da177e4SLinus Torvalds sctp_chunk_free(chunk); 17479af02c2SDavid S. Miller } 1751da177e4SLinus Torvalds } 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds /* This routine tries to append the chunk to the offered packet. If adding 1781da177e4SLinus Torvalds * the chunk causes the packet to exceed the path MTU and COOKIE_ECHO chunk 1791da177e4SLinus Torvalds * is not present in the packet, it transmits the input packet. 1801da177e4SLinus Torvalds * Data can be bundled with a packet containing a COOKIE_ECHO chunk as long 1811da177e4SLinus Torvalds * as it can fit in the packet, but any more data that does not fit in this 1821da177e4SLinus Torvalds * packet can be sent only after receiving the COOKIE_ACK. 1831da177e4SLinus Torvalds */ 1841da177e4SLinus Torvalds sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, 1852e3216cdSVlad Yasevich struct sctp_chunk *chunk, 186cea8768fSMarcelo Ricardo Leitner int one_packet, gfp_t gfp) 1871da177e4SLinus Torvalds { 1881da177e4SLinus Torvalds sctp_xmit_t retval; 1891da177e4SLinus Torvalds 1905b5e0928SAlexey Dobriyan pr_debug("%s: packet:%p size:%zu chunk:%p size:%d\n", __func__, 191942b3235SMarcelo Ricardo Leitner packet, packet->size, chunk, chunk->skb ? chunk->skb->len : -1); 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds switch ((retval = (sctp_packet_append_chunk(packet, chunk)))) { 1941da177e4SLinus Torvalds case SCTP_XMIT_PMTU_FULL: 1951da177e4SLinus Torvalds if (!packet->has_cookie_echo) { 19664519440SXin Long int error = 0; 19764519440SXin Long 198cea8768fSMarcelo Ricardo Leitner error = sctp_packet_transmit(packet, gfp); 1991da177e4SLinus Torvalds if (error < 0) 2001da177e4SLinus Torvalds chunk->skb->sk->sk_err = -error; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds /* If we have an empty packet, then we can NOT ever 2031da177e4SLinus Torvalds * return PMTU_FULL. 2041da177e4SLinus Torvalds */ 2052e3216cdSVlad Yasevich if (!one_packet) 2062e3216cdSVlad Yasevich retval = sctp_packet_append_chunk(packet, 2072e3216cdSVlad Yasevich chunk); 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds break; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds case SCTP_XMIT_RWND_FULL: 2121da177e4SLinus Torvalds case SCTP_XMIT_OK: 213526cbef7SDavid Laight case SCTP_XMIT_DELAY: 2141da177e4SLinus Torvalds break; 2153ff50b79SStephen Hemminger } 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds return retval; 2181da177e4SLinus Torvalds } 2191da177e4SLinus Torvalds 2204cd57c80SVlad Yasevich /* Try to bundle an auth chunk into the packet. */ 2214cd57c80SVlad Yasevich static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt, 2224cd57c80SVlad Yasevich struct sctp_chunk *chunk) 2234cd57c80SVlad Yasevich { 2244cd57c80SVlad Yasevich struct sctp_association *asoc = pkt->transport->asoc; 2254cd57c80SVlad Yasevich struct sctp_chunk *auth; 2264cd57c80SVlad Yasevich sctp_xmit_t retval = SCTP_XMIT_OK; 2274cd57c80SVlad Yasevich 2284cd57c80SVlad Yasevich /* if we don't have an association, we can't do authentication */ 2294cd57c80SVlad Yasevich if (!asoc) 2304cd57c80SVlad Yasevich return retval; 2314cd57c80SVlad Yasevich 2324cd57c80SVlad Yasevich /* See if this is an auth chunk we are bundling or if 2334cd57c80SVlad Yasevich * auth is already bundled. 2344cd57c80SVlad Yasevich */ 2354007cc88SVlad Yasevich if (chunk->chunk_hdr->type == SCTP_CID_AUTH || pkt->has_auth) 2364cd57c80SVlad Yasevich return retval; 2374cd57c80SVlad Yasevich 2384cd57c80SVlad Yasevich /* if the peer did not request this chunk to be authenticated, 2394cd57c80SVlad Yasevich * don't do it 2404cd57c80SVlad Yasevich */ 2414cd57c80SVlad Yasevich if (!chunk->auth) 2424cd57c80SVlad Yasevich return retval; 2434cd57c80SVlad Yasevich 2444cd57c80SVlad Yasevich auth = sctp_make_auth(asoc); 2454cd57c80SVlad Yasevich if (!auth) 2464cd57c80SVlad Yasevich return retval; 2474cd57c80SVlad Yasevich 248ed106277SNeil Horman retval = __sctp_packet_append_chunk(pkt, auth); 249ed106277SNeil Horman 250ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 251ed106277SNeil Horman sctp_chunk_free(auth); 2524cd57c80SVlad Yasevich 2534cd57c80SVlad Yasevich return retval; 2544cd57c80SVlad Yasevich } 2554cd57c80SVlad Yasevich 2561da177e4SLinus Torvalds /* Try to bundle a SACK with the packet. */ 2571da177e4SLinus Torvalds static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, 2581da177e4SLinus Torvalds struct sctp_chunk *chunk) 2591da177e4SLinus Torvalds { 2601da177e4SLinus Torvalds sctp_xmit_t retval = SCTP_XMIT_OK; 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds /* If sending DATA and haven't aleady bundled a SACK, try to 2631da177e4SLinus Torvalds * bundle one in to the packet. 2641da177e4SLinus Torvalds */ 2651da177e4SLinus Torvalds if (sctp_chunk_is_data(chunk) && !pkt->has_sack && 2661da177e4SLinus Torvalds !pkt->has_cookie_echo) { 2671da177e4SLinus Torvalds struct sctp_association *asoc; 268af87b823SDoug Graham struct timer_list *timer; 2691da177e4SLinus Torvalds asoc = pkt->transport->asoc; 270af87b823SDoug Graham timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK]; 2711da177e4SLinus Torvalds 272af87b823SDoug Graham /* If the SACK timer is running, we have a pending SACK */ 273af87b823SDoug Graham if (timer_pending(timer)) { 2741da177e4SLinus Torvalds struct sctp_chunk *sack; 2754244854dSNeil Horman 2764244854dSNeil Horman if (pkt->transport->sack_generation != 2774244854dSNeil Horman pkt->transport->asoc->peer.sack_generation) 2784244854dSNeil Horman return retval; 2794244854dSNeil Horman 2801da177e4SLinus Torvalds asoc->a_rwnd = asoc->rwnd; 2811da177e4SLinus Torvalds sack = sctp_make_sack(asoc); 2821da177e4SLinus Torvalds if (sack) { 283ed106277SNeil Horman retval = __sctp_packet_append_chunk(pkt, sack); 284ed106277SNeil Horman if (retval != SCTP_XMIT_OK) { 285ed106277SNeil Horman sctp_chunk_free(sack); 286ed106277SNeil Horman goto out; 287ed106277SNeil Horman } 2881da177e4SLinus Torvalds asoc->peer.sack_needed = 0; 289af87b823SDoug Graham if (del_timer(timer)) 2901da177e4SLinus Torvalds sctp_association_put(asoc); 2911da177e4SLinus Torvalds } 2921da177e4SLinus Torvalds } 2931da177e4SLinus Torvalds } 294ed106277SNeil Horman out: 2951da177e4SLinus Torvalds return retval; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 298ed106277SNeil Horman 2991da177e4SLinus Torvalds /* Append a chunk to the offered packet reporting back any inability to do 3001da177e4SLinus Torvalds * so. 3011da177e4SLinus Torvalds */ 302ed106277SNeil Horman static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, 3031da177e4SLinus Torvalds struct sctp_chunk *chunk) 3041da177e4SLinus Torvalds { 3051da177e4SLinus Torvalds sctp_xmit_t retval = SCTP_XMIT_OK; 306e2f036a9SMarcelo Ricardo Leitner __u16 chunk_len = SCTP_PAD4(ntohs(chunk->chunk_hdr->length)); 3071da177e4SLinus Torvalds 308e83963b7SVlad Yasevich /* Check to see if this chunk will fit into the packet */ 309e83963b7SVlad Yasevich retval = sctp_packet_will_fit(packet, chunk, chunk_len); 310e83963b7SVlad Yasevich if (retval != SCTP_XMIT_OK) 3111da177e4SLinus Torvalds goto finish; 3121da177e4SLinus Torvalds 313e83963b7SVlad Yasevich /* We believe that this chunk is OK to add to the packet */ 3144cd57c80SVlad Yasevich switch (chunk->chunk_hdr->type) { 3154cd57c80SVlad Yasevich case SCTP_CID_DATA: 316e83963b7SVlad Yasevich /* Account for the data being in the packet */ 317e83963b7SVlad Yasevich sctp_packet_append_data(packet, chunk); 3181da177e4SLinus Torvalds /* Disallow SACK bundling after DATA. */ 3191da177e4SLinus Torvalds packet->has_sack = 1; 3204cd57c80SVlad Yasevich /* Disallow AUTH bundling after DATA */ 3214cd57c80SVlad Yasevich packet->has_auth = 1; 3224cd57c80SVlad Yasevich /* Let it be knows that packet has DATA in it */ 3234cd57c80SVlad Yasevich packet->has_data = 1; 324759af00eSVlad Yasevich /* timestamp the chunk for rtx purposes */ 325759af00eSVlad Yasevich chunk->sent_at = jiffies; 326a6c2f792SXin Long /* Mainly used for prsctp RTX policy */ 327a6c2f792SXin Long chunk->sent_count++; 3284cd57c80SVlad Yasevich break; 3294cd57c80SVlad Yasevich case SCTP_CID_COOKIE_ECHO: 3301da177e4SLinus Torvalds packet->has_cookie_echo = 1; 3314cd57c80SVlad Yasevich break; 3324cd57c80SVlad Yasevich 3334cd57c80SVlad Yasevich case SCTP_CID_SACK: 3341da177e4SLinus Torvalds packet->has_sack = 1; 335196d6759SMichele Baldessari if (chunk->asoc) 336196d6759SMichele Baldessari chunk->asoc->stats.osacks++; 3374cd57c80SVlad Yasevich break; 3384cd57c80SVlad Yasevich 3394cd57c80SVlad Yasevich case SCTP_CID_AUTH: 3404cd57c80SVlad Yasevich packet->has_auth = 1; 3414cd57c80SVlad Yasevich packet->auth = chunk; 3424cd57c80SVlad Yasevich break; 3434cd57c80SVlad Yasevich } 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds /* It is OK to send this chunk. */ 34679af02c2SDavid S. Miller list_add_tail(&chunk->list, &packet->chunk_list); 3471da177e4SLinus Torvalds packet->size += chunk_len; 3481da177e4SLinus Torvalds chunk->transport = packet->transport; 3491da177e4SLinus Torvalds finish: 3501da177e4SLinus Torvalds return retval; 3511da177e4SLinus Torvalds } 3521da177e4SLinus Torvalds 353ed106277SNeil Horman /* Append a chunk to the offered packet reporting back any inability to do 354ed106277SNeil Horman * so. 355ed106277SNeil Horman */ 356ed106277SNeil Horman sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, 357ed106277SNeil Horman struct sctp_chunk *chunk) 358ed106277SNeil Horman { 359ed106277SNeil Horman sctp_xmit_t retval = SCTP_XMIT_OK; 360ed106277SNeil Horman 361bb33381dSDaniel Borkmann pr_debug("%s: packet:%p chunk:%p\n", __func__, packet, chunk); 362ed106277SNeil Horman 363ed106277SNeil Horman /* Data chunks are special. Before seeing what else we can 364ed106277SNeil Horman * bundle into this packet, check to see if we are allowed to 365ed106277SNeil Horman * send this DATA. 366ed106277SNeil Horman */ 367ed106277SNeil Horman if (sctp_chunk_is_data(chunk)) { 368ed106277SNeil Horman retval = sctp_packet_can_append_data(packet, chunk); 369ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 370ed106277SNeil Horman goto finish; 371ed106277SNeil Horman } 372ed106277SNeil Horman 373ed106277SNeil Horman /* Try to bundle AUTH chunk */ 374ed106277SNeil Horman retval = sctp_packet_bundle_auth(packet, chunk); 375ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 376ed106277SNeil Horman goto finish; 377ed106277SNeil Horman 378ed106277SNeil Horman /* Try to bundle SACK chunk */ 379ed106277SNeil Horman retval = sctp_packet_bundle_sack(packet, chunk); 380ed106277SNeil Horman if (retval != SCTP_XMIT_OK) 381ed106277SNeil Horman goto finish; 382ed106277SNeil Horman 383ed106277SNeil Horman retval = __sctp_packet_append_chunk(packet, chunk); 384ed106277SNeil Horman 385ed106277SNeil Horman finish: 386ed106277SNeil Horman return retval; 387ed106277SNeil Horman } 388ed106277SNeil Horman 3894c3a5bdaSThomas Graf static void sctp_packet_release_owner(struct sk_buff *skb) 3904c3a5bdaSThomas Graf { 3914c3a5bdaSThomas Graf sk_free(skb->sk); 3924c3a5bdaSThomas Graf } 3934c3a5bdaSThomas Graf 3944c3a5bdaSThomas Graf static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk) 3954c3a5bdaSThomas Graf { 3964c3a5bdaSThomas Graf skb_orphan(skb); 3974c3a5bdaSThomas Graf skb->sk = sk; 3984c3a5bdaSThomas Graf skb->destructor = sctp_packet_release_owner; 3994c3a5bdaSThomas Graf 4004c3a5bdaSThomas Graf /* 4014c3a5bdaSThomas Graf * The data chunks have already been accounted for in sctp_sendmsg(), 4024c3a5bdaSThomas Graf * therefore only reserve a single byte to keep socket around until 4034c3a5bdaSThomas Graf * the packet has been transmitted. 4044c3a5bdaSThomas Graf */ 405*14afee4bSReshetova, Elena refcount_inc(&sk->sk_wmem_alloc); 4064c3a5bdaSThomas Graf } 4074c3a5bdaSThomas Graf 408e4ff952aSXin Long static int sctp_packet_pack(struct sctp_packet *packet, 409e4ff952aSXin Long struct sk_buff *head, int gso, gfp_t gfp) 4101da177e4SLinus Torvalds { 4111da177e4SLinus Torvalds struct sctp_transport *tp = packet->transport; 412e4ff952aSXin Long struct sctp_auth_chunk *auth = NULL; 41379af02c2SDavid S. Miller struct sctp_chunk *chunk, *tmp; 414e4ff952aSXin Long int pkt_count = 0, pkt_size; 415e4ff952aSXin Long struct sock *sk = head->sk; 416e4ff952aSXin Long struct sk_buff *nskb; 417ecc515d7SXin Long int auth_len = 0; 4181da177e4SLinus Torvalds 41990017accSMarcelo Ricardo Leitner if (gso) { 42090017accSMarcelo Ricardo Leitner skb_shinfo(head)->gso_type = sk->sk_gso_type; 421e4ff952aSXin Long NAPI_GRO_CB(head)->last = head; 422e4ff952aSXin Long } else { 423e4ff952aSXin Long nskb = head; 424e4ff952aSXin Long pkt_size = packet->size; 425e4ff952aSXin Long goto merge; 42690017accSMarcelo Ricardo Leitner } 4271da177e4SLinus Torvalds 42890017accSMarcelo Ricardo Leitner do { 429e4ff952aSXin Long /* calculate the pkt_size and alloc nskb */ 43090017accSMarcelo Ricardo Leitner pkt_size = packet->overhead; 431e4ff952aSXin Long list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, 432e4ff952aSXin Long list) { 433e2f036a9SMarcelo Ricardo Leitner int padded = SCTP_PAD4(chunk->skb->len); 43490017accSMarcelo Ricardo Leitner 435ecc515d7SXin Long if (chunk == packet->auth) 436ecc515d7SXin Long auth_len = padded; 437ecc515d7SXin Long else if (auth_len + padded + packet->overhead > 438ecc515d7SXin Long tp->pathmtu) 439e4ff952aSXin Long return 0; 440ecc515d7SXin Long else if (pkt_size + padded > tp->pathmtu) 44190017accSMarcelo Ricardo Leitner break; 44290017accSMarcelo Ricardo Leitner pkt_size += padded; 44390017accSMarcelo Ricardo Leitner } 44490017accSMarcelo Ricardo Leitner nskb = alloc_skb(pkt_size + MAX_HEADER, gfp); 44590017accSMarcelo Ricardo Leitner if (!nskb) 446e4ff952aSXin Long return 0; 44790017accSMarcelo Ricardo Leitner skb_reserve(nskb, packet->overhead + MAX_HEADER); 4481da177e4SLinus Torvalds 449e4ff952aSXin Long merge: 450e4ff952aSXin Long /* merge chunks into nskb and append nskb into head list */ 45190017accSMarcelo Ricardo Leitner pkt_size -= packet->overhead; 45279af02c2SDavid S. Miller list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { 453e4ff952aSXin Long int padding; 454e4ff952aSXin Long 45579af02c2SDavid S. Miller list_del_init(&chunk->list); 4561da177e4SLinus Torvalds if (sctp_chunk_is_data(chunk)) { 457cc6ac9bcSXin Long if (!sctp_chunk_retransmitted(chunk) && 458cc6ac9bcSXin Long !tp->rto_pending) { 4591da177e4SLinus Torvalds chunk->rtt_in_progress = 1; 4601da177e4SLinus Torvalds tp->rto_pending = 1; 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds } 4631da177e4SLinus Torvalds 464e2f036a9SMarcelo Ricardo Leitner padding = SCTP_PAD4(chunk->skb->len) - chunk->skb->len; 4651da177e4SLinus Torvalds if (padding) 466b080db58SJohannes Berg skb_put_zero(chunk->skb, padding); 4671da177e4SLinus Torvalds 4684cd57c80SVlad Yasevich if (chunk == packet->auth) 469e4ff952aSXin Long auth = (struct sctp_auth_chunk *) 470e4ff952aSXin Long skb_tail_pointer(nskb); 4714cd57c80SVlad Yasevich 47259ae1d12SJohannes Berg skb_put_data(nskb, chunk->skb->data, chunk->skb->len); 4731da177e4SLinus Torvalds 47490017accSMarcelo Ricardo Leitner pr_debug("*** Chunk:%p[%s] %s 0x%x, length:%d, chunk->skb->len:%d, rtt_in_progress:%d\n", 47590017accSMarcelo Ricardo Leitner chunk, 476bb33381dSDaniel Borkmann sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)), 4771da177e4SLinus Torvalds chunk->has_tsn ? "TSN" : "No TSN", 478bb33381dSDaniel Borkmann chunk->has_tsn ? ntohl(chunk->subh.data_hdr->tsn) : 0, 479bb33381dSDaniel Borkmann ntohs(chunk->chunk_hdr->length), chunk->skb->len, 480bb33381dSDaniel Borkmann chunk->rtt_in_progress); 4811da177e4SLinus Torvalds 482e2f036a9SMarcelo Ricardo Leitner pkt_size -= SCTP_PAD4(chunk->skb->len); 48390017accSMarcelo Ricardo Leitner 484f1533cceSMarcelo Ricardo Leitner if (!sctp_chunk_is_data(chunk) && chunk != packet->auth) 4851da177e4SLinus Torvalds sctp_chunk_free(chunk); 48690017accSMarcelo Ricardo Leitner 48790017accSMarcelo Ricardo Leitner if (!pkt_size) 48890017accSMarcelo Ricardo Leitner break; 4891da177e4SLinus Torvalds } 4901da177e4SLinus Torvalds 491e4ff952aSXin Long if (auth) { 492e4ff952aSXin Long sctp_auth_calculate_hmac(tp->asoc, nskb, auth, gfp); 493e4ff952aSXin Long /* free auth if no more chunks, or add it back */ 494e4ff952aSXin Long if (list_empty(&packet->chunk_list)) 495e4ff952aSXin Long sctp_chunk_free(packet->auth); 496e4ff952aSXin Long else 4971aa25ec2SXin Long list_add(&packet->auth->list, 4981aa25ec2SXin Long &packet->chunk_list); 499f1533cceSMarcelo Ricardo Leitner } 5001da177e4SLinus Torvalds 50190017accSMarcelo Ricardo Leitner if (gso) { 502e4ff952aSXin Long if (skb_gro_receive(&head, nskb)) { 503e4ff952aSXin Long kfree_skb(nskb); 504e4ff952aSXin Long return 0; 505e4ff952aSXin Long } 506e4ff952aSXin Long if (WARN_ON_ONCE(skb_shinfo(head)->gso_segs >= 507e4ff952aSXin Long sk->sk_gso_max_segs)) 508e4ff952aSXin Long return 0; 509e4ff952aSXin Long } 510e4ff952aSXin Long 511e4ff952aSXin Long pkt_count++; 512e4ff952aSXin Long } while (!list_empty(&packet->chunk_list)); 513e4ff952aSXin Long 514e4ff952aSXin Long if (gso) { 51590017accSMarcelo Ricardo Leitner memset(head->cb, 0, max(sizeof(struct inet_skb_parm), 51690017accSMarcelo Ricardo Leitner sizeof(struct inet6_skb_parm))); 517e4ff952aSXin Long skb_shinfo(head)->gso_segs = pkt_count; 51890017accSMarcelo Ricardo Leitner skb_shinfo(head)->gso_size = GSO_BY_FRAGS; 51990017accSMarcelo Ricardo Leitner rcu_read_lock(); 520e4ff952aSXin Long if (skb_dst(head) != tp->dst) { 52190017accSMarcelo Ricardo Leitner dst_hold(tp->dst); 52290017accSMarcelo Ricardo Leitner sk_setup_caps(sk, tp->dst); 52390017accSMarcelo Ricardo Leitner } 52490017accSMarcelo Ricardo Leitner rcu_read_unlock(); 525e4ff952aSXin Long goto chksum; 526e4ff952aSXin Long } 527e4ff952aSXin Long 528e4ff952aSXin Long if (sctp_checksum_disable) 529e4ff952aSXin Long return 1; 530e4ff952aSXin Long 531e4ff952aSXin Long if (!(skb_dst(head)->dev->features & NETIF_F_SCTP_CRC) || 532e4ff952aSXin Long dst_xfrm(skb_dst(head)) || packet->ipfragok) { 533e4ff952aSXin Long struct sctphdr *sh = 534e4ff952aSXin Long (struct sctphdr *)skb_transport_header(head); 535e4ff952aSXin Long 536e4ff952aSXin Long sh->checksum = sctp_compute_cksum(head, 0); 537e4ff952aSXin Long } else { 538e4ff952aSXin Long chksum: 539e4ff952aSXin Long head->ip_summed = CHECKSUM_PARTIAL; 540dba00306SDavide Caratti head->csum_not_inet = 1; 541e4ff952aSXin Long head->csum_start = skb_transport_header(head) - head->head; 542e4ff952aSXin Long head->csum_offset = offsetof(struct sctphdr, checksum); 543e4ff952aSXin Long } 544e4ff952aSXin Long 545e4ff952aSXin Long return pkt_count; 546e4ff952aSXin Long } 547e4ff952aSXin Long 548e4ff952aSXin Long /* All packets are sent to the network through this function from 549e4ff952aSXin Long * sctp_outq_tail(). 550e4ff952aSXin Long * 551e4ff952aSXin Long * The return value is always 0 for now. 552e4ff952aSXin Long */ 553e4ff952aSXin Long int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) 554e4ff952aSXin Long { 555e4ff952aSXin Long struct sctp_transport *tp = packet->transport; 556e4ff952aSXin Long struct sctp_association *asoc = tp->asoc; 557e4ff952aSXin Long struct sctp_chunk *chunk, *tmp; 558e4ff952aSXin Long int pkt_count, gso = 0; 559e4ff952aSXin Long struct dst_entry *dst; 560e4ff952aSXin Long struct sk_buff *head; 561e4ff952aSXin Long struct sctphdr *sh; 562e4ff952aSXin Long struct sock *sk; 563e4ff952aSXin Long 564e4ff952aSXin Long pr_debug("%s: packet:%p\n", __func__, packet); 565e4ff952aSXin Long if (list_empty(&packet->chunk_list)) 566e4ff952aSXin Long return 0; 567e4ff952aSXin Long chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list); 568e4ff952aSXin Long sk = chunk->skb->sk; 569e4ff952aSXin Long 570e4ff952aSXin Long /* check gso */ 571e4ff952aSXin Long if (packet->size > tp->pathmtu && !packet->ipfragok) { 572e4ff952aSXin Long if (!sk_can_gso(sk)) { 573e4ff952aSXin Long pr_err_once("Trying to GSO but underlying device doesn't support it."); 574e4ff952aSXin Long goto out; 575e4ff952aSXin Long } 576e4ff952aSXin Long gso = 1; 577e4ff952aSXin Long } 578e4ff952aSXin Long 579e4ff952aSXin Long /* alloc head skb */ 580e4ff952aSXin Long head = alloc_skb((gso ? packet->overhead : packet->size) + 581e4ff952aSXin Long MAX_HEADER, gfp); 582e4ff952aSXin Long if (!head) 583e4ff952aSXin Long goto out; 584e4ff952aSXin Long skb_reserve(head, packet->overhead + MAX_HEADER); 585e4ff952aSXin Long sctp_packet_set_owner_w(head, sk); 586e4ff952aSXin Long 587e4ff952aSXin Long /* set sctp header */ 588d58ff351SJohannes Berg sh = skb_push(head, sizeof(struct sctphdr)); 589e4ff952aSXin Long skb_reset_transport_header(head); 590e4ff952aSXin Long sh->source = htons(packet->source_port); 591e4ff952aSXin Long sh->dest = htons(packet->destination_port); 592e4ff952aSXin Long sh->vtag = htonl(packet->vtag); 593e4ff952aSXin Long sh->checksum = 0; 594e4ff952aSXin Long 595df2729c3SXin Long /* drop packet if no dst */ 596e4ff952aSXin Long dst = dst_clone(tp->dst); 597e4ff952aSXin Long if (!dst) { 598e4ff952aSXin Long IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); 599e4ff952aSXin Long kfree_skb(head); 600e4ff952aSXin Long goto out; 601e4ff952aSXin Long } 602e4ff952aSXin Long skb_dst_set(head, dst); 603e4ff952aSXin Long 604e4ff952aSXin Long /* pack up chunks */ 605e4ff952aSXin Long pkt_count = sctp_packet_pack(packet, head, gso, gfp); 606e4ff952aSXin Long if (!pkt_count) { 607e4ff952aSXin Long kfree_skb(head); 608e4ff952aSXin Long goto out; 609e4ff952aSXin Long } 610e4ff952aSXin Long pr_debug("***sctp_transmit_packet*** skb->len:%d\n", head->len); 611e4ff952aSXin Long 612e4ff952aSXin Long /* start autoclose timer */ 613e4ff952aSXin Long if (packet->has_data && sctp_state(asoc, ESTABLISHED) && 614e4ff952aSXin Long asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { 615e4ff952aSXin Long struct timer_list *timer = 616e4ff952aSXin Long &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; 617e4ff952aSXin Long unsigned long timeout = 618e4ff952aSXin Long asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; 619e4ff952aSXin Long 620e4ff952aSXin Long if (!mod_timer(timer, jiffies + timeout)) 621e4ff952aSXin Long sctp_association_hold(asoc); 622e4ff952aSXin Long } 623e4ff952aSXin Long 624e4ff952aSXin Long /* sctp xmit */ 625e4ff952aSXin Long tp->af_specific->ecn_capable(sk); 626e4ff952aSXin Long if (asoc) { 627e4ff952aSXin Long asoc->stats.opackets += pkt_count; 628e4ff952aSXin Long if (asoc->peer.last_sent_to != tp) 629e4ff952aSXin Long asoc->peer.last_sent_to = tp; 63090017accSMarcelo Ricardo Leitner } 63190017accSMarcelo Ricardo Leitner head->ignore_df = packet->ipfragok; 632486a43dbSXin Long if (tp->dst_pending_confirm) 633c86a773cSJulian Anastasov skb_set_dst_pending_confirm(head, 1); 634c86a773cSJulian Anastasov /* neighbour should be confirmed on successful transmission or 635c86a773cSJulian Anastasov * positive error 636c86a773cSJulian Anastasov */ 637486a43dbSXin Long if (tp->af_specific->sctp_xmit(head, tp) >= 0 && 638486a43dbSXin Long tp->dst_pending_confirm) 639c86a773cSJulian Anastasov tp->dst_pending_confirm = 0; 6401da177e4SLinus Torvalds 641e4ff952aSXin Long out: 64279af02c2SDavid S. Miller list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { 64379af02c2SDavid S. Miller list_del_init(&chunk->list); 6441da177e4SLinus Torvalds if (!sctp_chunk_is_data(chunk)) 6451da177e4SLinus Torvalds sctp_chunk_free(chunk); 6461da177e4SLinus Torvalds } 64741001fafSXin Long sctp_packet_reset(packet); 648e4ff952aSXin Long return 0; 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds /******************************************************************** 6521da177e4SLinus Torvalds * 2nd Level Abstractions 6531da177e4SLinus Torvalds ********************************************************************/ 6541da177e4SLinus Torvalds 655e83963b7SVlad Yasevich /* This private function check to see if a chunk can be added */ 656e83963b7SVlad Yasevich static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, 6571da177e4SLinus Torvalds struct sctp_chunk *chunk) 6581da177e4SLinus Torvalds { 659e83963b7SVlad Yasevich size_t datasize, rwnd, inflight, flight_size; 6601da177e4SLinus Torvalds struct sctp_transport *transport = packet->transport; 6611da177e4SLinus Torvalds struct sctp_association *asoc = transport->asoc; 6621da177e4SLinus Torvalds struct sctp_outq *q = &asoc->outqueue; 6631da177e4SLinus Torvalds 6641da177e4SLinus Torvalds /* RFC 2960 6.1 Transmission of DATA Chunks 6651da177e4SLinus Torvalds * 6661da177e4SLinus Torvalds * A) At any given time, the data sender MUST NOT transmit new data to 6671da177e4SLinus Torvalds * any destination transport address if its peer's rwnd indicates 6681da177e4SLinus Torvalds * that the peer has no buffer space (i.e. rwnd is 0, see Section 6691da177e4SLinus Torvalds * 6.2.1). However, regardless of the value of rwnd (including if it 6701da177e4SLinus Torvalds * is 0), the data sender can always have one DATA chunk in flight to 6711da177e4SLinus Torvalds * the receiver if allowed by cwnd (see rule B below). This rule 6721da177e4SLinus Torvalds * allows the sender to probe for a change in rwnd that the sender 6731da177e4SLinus Torvalds * missed due to the SACK having been lost in transit from the data 6741da177e4SLinus Torvalds * receiver to the data sender. 6751da177e4SLinus Torvalds */ 6761da177e4SLinus Torvalds 6771da177e4SLinus Torvalds rwnd = asoc->peer.rwnd; 678e83963b7SVlad Yasevich inflight = q->outstanding_bytes; 679e83963b7SVlad Yasevich flight_size = transport->flight_size; 6801da177e4SLinus Torvalds 6811da177e4SLinus Torvalds datasize = sctp_data_size(chunk); 6821da177e4SLinus Torvalds 683723189faSDavid Laight if (datasize > rwnd && inflight > 0) 6841da177e4SLinus Torvalds /* We have (at least) one data chunk in flight, 6851da177e4SLinus Torvalds * so we can't fall back to rule 6.1 B). 6861da177e4SLinus Torvalds */ 687723189faSDavid Laight return SCTP_XMIT_RWND_FULL; 6881da177e4SLinus Torvalds 6891da177e4SLinus Torvalds /* RFC 2960 6.1 Transmission of DATA Chunks 6901da177e4SLinus Torvalds * 6911da177e4SLinus Torvalds * B) At any given time, the sender MUST NOT transmit new data 6921da177e4SLinus Torvalds * to a given transport address if it has cwnd or more bytes 6931da177e4SLinus Torvalds * of data outstanding to that transport address. 6941da177e4SLinus Torvalds */ 6951da177e4SLinus Torvalds /* RFC 7.2.4 & the Implementers Guide 2.8. 6961da177e4SLinus Torvalds * 6971da177e4SLinus Torvalds * 3) ... 6981da177e4SLinus Torvalds * When a Fast Retransmit is being performed the sender SHOULD 6991da177e4SLinus Torvalds * ignore the value of cwnd and SHOULD NOT delay retransmission. 7001da177e4SLinus Torvalds */ 701723189faSDavid Laight if (chunk->fast_retransmit != SCTP_NEED_FRTX && 702723189faSDavid Laight flight_size >= transport->cwnd) 703723189faSDavid Laight return SCTP_XMIT_RWND_FULL; 7041da177e4SLinus Torvalds 7051da177e4SLinus Torvalds /* Nagle's algorithm to solve small-packet problem: 7061da177e4SLinus Torvalds * Inhibit the sending of new chunks when new outgoing data arrives 7071da177e4SLinus Torvalds * if any previously transmitted data on the connection remains 7081da177e4SLinus Torvalds * unacknowledged. 7091da177e4SLinus Torvalds */ 7101da177e4SLinus Torvalds 7114ea0c32fSXin Long if ((sctp_sk(asoc->base.sk)->nodelay || inflight == 0) && 712f9ba3501SXin Long !asoc->force_delay) 7134ea0c32fSXin Long /* Nothing unacked */ 714723189faSDavid Laight return SCTP_XMIT_OK; 715723189faSDavid Laight 716723189faSDavid Laight if (!sctp_packet_empty(packet)) 717723189faSDavid Laight /* Append to packet */ 718723189faSDavid Laight return SCTP_XMIT_OK; 719723189faSDavid Laight 720723189faSDavid Laight if (!sctp_state(asoc, ESTABLISHED)) 721723189faSDavid Laight return SCTP_XMIT_OK; 722723189faSDavid Laight 723723189faSDavid Laight /* Check whether this chunk and all the rest of pending data will fit 724723189faSDavid Laight * or delay in hopes of bundling a full sized packet. 7251da177e4SLinus Torvalds */ 726e43569e6SMarcelo Ricardo Leitner if (chunk->skb->len + q->out_qlen > 727e43569e6SMarcelo Ricardo Leitner transport->pathmtu - packet->overhead - sizeof(sctp_data_chunk_t) - 4) 728723189faSDavid Laight /* Enough data queued to fill a packet */ 729723189faSDavid Laight return SCTP_XMIT_OK; 7301da177e4SLinus Torvalds 731723189faSDavid Laight /* Don't delay large message writes that may have been fragmented */ 732723189faSDavid Laight if (!chunk->msg->can_delay) 733723189faSDavid Laight return SCTP_XMIT_OK; 734723189faSDavid Laight 735723189faSDavid Laight /* Defer until all data acked or packet full */ 736526cbef7SDavid Laight return SCTP_XMIT_DELAY; 737e83963b7SVlad Yasevich } 738e83963b7SVlad Yasevich 739e83963b7SVlad Yasevich /* This private function does management things when adding DATA chunk */ 740e83963b7SVlad Yasevich static void sctp_packet_append_data(struct sctp_packet *packet, 741e83963b7SVlad Yasevich struct sctp_chunk *chunk) 742e83963b7SVlad Yasevich { 743e83963b7SVlad Yasevich struct sctp_transport *transport = packet->transport; 744e83963b7SVlad Yasevich size_t datasize = sctp_data_size(chunk); 745e83963b7SVlad Yasevich struct sctp_association *asoc = transport->asoc; 746e83963b7SVlad Yasevich u32 rwnd = asoc->peer.rwnd; 747e83963b7SVlad Yasevich 7481da177e4SLinus Torvalds /* Keep track of how many bytes are in flight over this transport. */ 7491da177e4SLinus Torvalds transport->flight_size += datasize; 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds /* Keep track of how many bytes are in flight to the receiver. */ 7521da177e4SLinus Torvalds asoc->outqueue.outstanding_bytes += datasize; 7531da177e4SLinus Torvalds 754a76c0adfSThomas Graf /* Update our view of the receiver's rwnd. */ 7551da177e4SLinus Torvalds if (datasize < rwnd) 7561da177e4SLinus Torvalds rwnd -= datasize; 7571da177e4SLinus Torvalds else 7581da177e4SLinus Torvalds rwnd = 0; 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds asoc->peer.rwnd = rwnd; 761d8dd1578SNeil Horman sctp_chunk_assign_tsn(chunk); 762d8dd1578SNeil Horman sctp_chunk_assign_ssn(chunk); 763e83963b7SVlad Yasevich } 7641da177e4SLinus Torvalds 765e83963b7SVlad Yasevich static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet, 766e83963b7SVlad Yasevich struct sctp_chunk *chunk, 767e83963b7SVlad Yasevich u16 chunk_len) 768e83963b7SVlad Yasevich { 7697303a147SMarcelo Ricardo Leitner size_t psize, pmtu, maxsize; 770e83963b7SVlad Yasevich sctp_xmit_t retval = SCTP_XMIT_OK; 771e83963b7SVlad Yasevich 772e83963b7SVlad Yasevich psize = packet->size; 77390017accSMarcelo Ricardo Leitner if (packet->transport->asoc) 77490017accSMarcelo Ricardo Leitner pmtu = packet->transport->asoc->pathmtu; 77590017accSMarcelo Ricardo Leitner else 77690017accSMarcelo Ricardo Leitner pmtu = packet->transport->pathmtu; 777e83963b7SVlad Yasevich 778e83963b7SVlad Yasevich /* Decide if we need to fragment or resubmit later. */ 77990017accSMarcelo Ricardo Leitner if (psize + chunk_len > pmtu) { 78090017accSMarcelo Ricardo Leitner /* It's OK to fragment at IP level if any one of the following 781e83963b7SVlad Yasevich * is true: 782e83963b7SVlad Yasevich * 1. The packet is empty (meaning this chunk is greater 783e83963b7SVlad Yasevich * the MTU) 78490017accSMarcelo Ricardo Leitner * 2. The packet doesn't have any data in it yet and data 785e83963b7SVlad Yasevich * requires authentication. 786e83963b7SVlad Yasevich */ 78790017accSMarcelo Ricardo Leitner if (sctp_packet_empty(packet) || 788e83963b7SVlad Yasevich (!packet->has_data && chunk->auth)) { 789e83963b7SVlad Yasevich /* We no longer do re-fragmentation. 790e83963b7SVlad Yasevich * Just fragment at the IP layer, if we 791e83963b7SVlad Yasevich * actually hit this condition 792e83963b7SVlad Yasevich */ 793e83963b7SVlad Yasevich packet->ipfragok = 1; 79490017accSMarcelo Ricardo Leitner goto out; 795e83963b7SVlad Yasevich } 796e83963b7SVlad Yasevich 7977303a147SMarcelo Ricardo Leitner /* Similarly, if this chunk was built before a PMTU 7987303a147SMarcelo Ricardo Leitner * reduction, we have to fragment it at IP level now. So 7997303a147SMarcelo Ricardo Leitner * if the packet already contains something, we need to 8007303a147SMarcelo Ricardo Leitner * flush. 8017303a147SMarcelo Ricardo Leitner */ 8027303a147SMarcelo Ricardo Leitner maxsize = pmtu - packet->overhead; 8037303a147SMarcelo Ricardo Leitner if (packet->auth) 804e2f036a9SMarcelo Ricardo Leitner maxsize -= SCTP_PAD4(packet->auth->skb->len); 8057303a147SMarcelo Ricardo Leitner if (chunk_len > maxsize) 8067303a147SMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 8077303a147SMarcelo Ricardo Leitner 80890017accSMarcelo Ricardo Leitner /* It is also okay to fragment if the chunk we are 80990017accSMarcelo Ricardo Leitner * adding is a control chunk, but only if current packet 81090017accSMarcelo Ricardo Leitner * is not a GSO one otherwise it causes fragmentation of 81190017accSMarcelo Ricardo Leitner * a large frame. So in this case we allow the 81290017accSMarcelo Ricardo Leitner * fragmentation by forcing it to be in a new packet. 81390017accSMarcelo Ricardo Leitner */ 81490017accSMarcelo Ricardo Leitner if (!sctp_chunk_is_data(chunk) && packet->has_data) 81590017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 81690017accSMarcelo Ricardo Leitner 81790017accSMarcelo Ricardo Leitner if (psize + chunk_len > packet->max_size) 81890017accSMarcelo Ricardo Leitner /* Hit GSO/PMTU limit, gotta flush */ 81990017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 82090017accSMarcelo Ricardo Leitner 82190017accSMarcelo Ricardo Leitner if (!packet->transport->burst_limited && 82290017accSMarcelo Ricardo Leitner psize + chunk_len > (packet->transport->cwnd >> 1)) 82390017accSMarcelo Ricardo Leitner /* Do not allow a single GSO packet to use more 82490017accSMarcelo Ricardo Leitner * than half of cwnd. 82590017accSMarcelo Ricardo Leitner */ 82690017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 82790017accSMarcelo Ricardo Leitner 82890017accSMarcelo Ricardo Leitner if (packet->transport->burst_limited && 82990017accSMarcelo Ricardo Leitner psize + chunk_len > (packet->transport->burst_limited >> 1)) 83090017accSMarcelo Ricardo Leitner /* Do not allow a single GSO packet to use more 83190017accSMarcelo Ricardo Leitner * than half of original cwnd. 83290017accSMarcelo Ricardo Leitner */ 83390017accSMarcelo Ricardo Leitner retval = SCTP_XMIT_PMTU_FULL; 83490017accSMarcelo Ricardo Leitner /* Otherwise it will fit in the GSO packet */ 83590017accSMarcelo Ricardo Leitner } 83690017accSMarcelo Ricardo Leitner 83790017accSMarcelo Ricardo Leitner out: 8381da177e4SLinus Torvalds return retval; 8391da177e4SLinus Torvalds } 840