linux/net/sctp/outqueue.c

// SPDX-License-Identifier: GPL-2.0-or-later
/* SCTP kernel implementation
 * (C) Copyright IBM Corp. 2001, 2004
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
 * Copyright (c) 2001-2003 Intel Corp.
 *
 * This file is part of the SCTP kernel implementation
 *
 * These functions implement the sctp_outq class.   The outqueue handles
 * bundling and queueing of outgoing SCTP chunks.
 *
 * Please send any bug reports or fixes you make to the
 * email address(es):
 *    lksctp developers <[email protected]>
 *
 * Written or modified by:
 *    La Monte H.P. Yarroll <[email protected]>
 *    Karl Knutson          <[email protected]>
 *    Perry Melange         <[email protected]>
 *    Xingang Guo           <[email protected]>
 *    Hui Huang 	    <[email protected]>
 *    Sridhar Samudrala     <[email protected]>
 *    Jon Grimm             <[email protected]>
 */

#define pr_fmt(fmt)

#include <linux/types.h>
#include <linux/list.h>   /* For struct list_head */
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/slab.h>
#include <net/sock.h>	  /* For skb_set_owner_w */

#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
#include <net/sctp/stream_sched.h>
#include <trace/events/sctp.h>

/* Declare internal functions here.  */
static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
static void sctp_check_transmitted(struct sctp_outq *q,
				   struct list_head *transmitted_queue,
				   struct sctp_transport *transport,
				   union sctp_addr *saddr,
				   struct sctp_sackhdr *sack,
				   __u32 *highest_new_tsn);

static void sctp_mark_missing(struct sctp_outq *q,
			      struct list_head *transmitted_queue,
			      struct sctp_transport *transport,
			      __u32 highest_new_tsn,
			      int count_of_newacks);

static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp);

/* Add data to the front of the queue. */
static inline void sctp_outq_head_data(struct sctp_outq *q,
				       struct sctp_chunk *ch)
{}

/* Take data from the front of the queue. */
static inline struct sctp_chunk *sctp_outq_dequeue_data(struct sctp_outq *q)
{}

/* Add data chunk to the end of the queue. */
static inline void sctp_outq_tail_data(struct sctp_outq *q,
				       struct sctp_chunk *ch)
{}

/*
 * SFR-CACC algorithm:
 * D) If count_of_newacks is greater than or equal to 2
 * and t was not sent to the current primary then the
 * sender MUST NOT increment missing report count for t.
 */
static inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary,
				       struct sctp_transport *transport,
				       int count_of_newacks)
{}

/*
 * SFR-CACC algorithm:
 * F) If count_of_newacks is less than 2, let d be the
 * destination to which t was sent. If cacc_saw_newack
 * is 0 for destination d, then the sender MUST NOT
 * increment missing report count for t.
 */
static inline int sctp_cacc_skip_3_1_f(struct sctp_transport *transport,
				       int count_of_newacks)
{}

/*
 * SFR-CACC algorithm:
 * 3.1) If CYCLING_CHANGEOVER is 0, the sender SHOULD
 * execute steps C, D, F.
 *
 * C has been implemented in sctp_outq_sack
 */
static inline int sctp_cacc_skip_3_1(struct sctp_transport *primary,
				     struct sctp_transport *transport,
				     int count_of_newacks)
{}

/*
 * SFR-CACC algorithm:
 * 3.2) Else if CYCLING_CHANGEOVER is 1, and t is less
 * than next_tsn_at_change of the current primary, then
 * the sender MUST NOT increment missing report count
 * for t.
 */
static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn)
{}

/*
 * SFR-CACC algorithm:
 * 3) If the missing report count for TSN t is to be
 * incremented according to [RFC2960] and
 * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set,
 * then the sender MUST further execute steps 3.1 and
 * 3.2 to determine if the missing report count for
 * TSN t SHOULD NOT be incremented.
 *
 * 3.3) If 3.1 and 3.2 do not dictate that the missing
 * report count for t should not be incremented, then
 * the sender SHOULD increment missing report count for
 * t (according to [RFC2960] and [SCTP_STEWART_2002]).
 */
static inline int sctp_cacc_skip(struct sctp_transport *primary,
				 struct sctp_transport *transport,
				 int count_of_newacks,
				 __u32 tsn)
{}

/* Initialize an existing sctp_outq.  This does the boring stuff.
 * You still need to define handlers if you really want to DO
 * something with this structure...
 */
void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
{}

/* Free the outqueue structure and any related pending chunks.
 */
static void __sctp_outq_teardown(struct sctp_outq *q)
{}

void sctp_outq_teardown(struct sctp_outq *q)
{}

/* Free the outqueue structure and any related pending chunks.  */
void sctp_outq_free(struct sctp_outq *q)
{}

/* Put a new chunk in an sctp_outq.  */
void sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk, gfp_t gfp)
{}

/* Insert a chunk into the sorted list based on the TSNs.  The retransmit list
 * and the abandoned list are in ascending order.
 */
static void sctp_insert_list(struct list_head *head, struct list_head *new)
{}

static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
				  struct sctp_sndrcvinfo *sinfo,
				  struct list_head *queue, int msg_len)
{}

static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
				    struct sctp_sndrcvinfo *sinfo, int msg_len)
{}

/* Abandon the chunks according their priorities */
void sctp_prsctp_prune(struct sctp_association *asoc,
		       struct sctp_sndrcvinfo *sinfo, int msg_len)
{}

/* Mark all the eligible packets on a transport for retransmission.  */
void sctp_retransmit_mark(struct sctp_outq *q,
			  struct sctp_transport *transport,
			  __u8 reason)
{}

/* Mark all the eligible packets on a transport for retransmission and force
 * one packet out.
 */
void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
		     enum sctp_retransmit_reason reason)
{}

/*
 * Transmit DATA chunks on the retransmit queue.  Upon return from
 * __sctp_outq_flush_rtx() the packet 'pkt' may contain chunks which
 * need to be transmitted by the caller.
 * We assume that pkt->transport has already been set.
 *
 * The return value is a normal kernel error return value.
 */
static int __sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
				 int rtx_timeout, int *start_timer, gfp_t gfp)
{}

/* Cork the outqueue so queued chunks are really queued. */
void sctp_outq_uncork(struct sctp_outq *q, gfp_t gfp)
{}

static int sctp_packet_singleton(struct sctp_transport *transport,
				 struct sctp_chunk *chunk, gfp_t gfp)
{}

/* Struct to hold the context during sctp outq flush */
struct sctp_flush_ctx {};

/* transport: current transport */
static void sctp_outq_select_transport(struct sctp_flush_ctx *ctx,
				       struct sctp_chunk *chunk)
{}

static void sctp_outq_flush_ctrl(struct sctp_flush_ctx *ctx)
{}

/* Returns false if new data shouldn't be sent */
static bool sctp_outq_flush_rtx(struct sctp_flush_ctx *ctx,
				int rtx_timeout)
{}

static void sctp_outq_flush_data(struct sctp_flush_ctx *ctx,
				 int rtx_timeout)
{}

static void sctp_outq_flush_transports(struct sctp_flush_ctx *ctx)
{}

/* Try to flush an outqueue.
 *
 * Description: Send everything in q which we legally can, subject to
 * congestion limitations.
 * * Note: This function can be called from multiple contexts so appropriate
 * locking concerns must be made.  Today we use the sock lock to protect
 * this function.
 */

static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
{}

/* Update unack_data based on the incoming SACK chunk */
static void sctp_sack_update_unack_data(struct sctp_association *assoc,
					struct sctp_sackhdr *sack)
{}

/* This is where we REALLY process a SACK.
 *
 * Process the SACK against the outqueue.  Mostly, this just frees
 * things off the transmitted queue.
 */
int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
{}

/* Is the outqueue empty?
 * The queue is empty when we have not pending data, no in-flight data
 * and nothing pending retransmissions.
 */
int sctp_outq_is_empty(const struct sctp_outq *q)
{}

/********************************************************************
 * 2nd Level Abstractions
 ********************************************************************/

/* Go through a transport's transmitted list or the association's retransmit
 * list and move chunks that are acked by the Cumulative TSN Ack to q->sacked.
 * The retransmit list will not have an associated transport.
 *
 * I added coherent debug information output.	--xguo
 *
 * Instead of printing 'sacked' or 'kept' for each TSN on the
 * transmitted_queue, we print a range: SACKED: TSN1-TSN2, TSN3, TSN4-TSN5.
 * KEPT TSN6-TSN7, etc.
 */
static void sctp_check_transmitted(struct sctp_outq *q,
				   struct list_head *transmitted_queue,
				   struct sctp_transport *transport,
				   union sctp_addr *saddr,
				   struct sctp_sackhdr *sack,
				   __u32 *highest_new_tsn_in_sack)
{}

/* Mark chunks as missing and consequently may get retransmitted. */
static void sctp_mark_missing(struct sctp_outq *q,
			      struct list_head *transmitted_queue,
			      struct sctp_transport *transport,
			      __u32 highest_new_tsn_in_sack,
			      int count_of_newacks)
{}

/* Is the given TSN acked by this packet?  */
static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn)
{}

static inline int sctp_get_skip_pos(struct sctp_fwdtsn_skip *skiplist,
				    int nskips, __be16 stream)
{}

/* Create and add a fwdtsn chunk to the outq's control queue if needed. */
void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
{}