⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_make_chunk.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
 *  RFC 2481 details a specific bit for a sender to send in the header of *  its next outbound TCP segment to indicate to its peer that it has *  reduced its congestion window.  This is termed the CWR bit.  For *  SCTP the same indication is made by including the CWR chunk. *  This chunk contains one data element, i.e. the TSN number that *  was sent in the ECNE chunk.  This element represents the lowest *  TSN number in the datagram that was originally marked with the *  CE bit. * *     0                   1                   2                   3 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *    | Chunk Type=13 | Flags=00000000|    Chunk Length = 8           | *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *    |                      Lowest TSN Number                        | *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * *     Note: The CWR is considered a Control chunk. */struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc,			    const __u32 lowest_tsn,			    const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	sctp_cwrhdr_t cwr;	cwr.lowest_tsn = htonl(lowest_tsn);	retval = sctp_make_chunk(asoc, SCTP_CID_ECN_CWR, 0,				 sizeof(sctp_cwrhdr_t));	if (!retval)		goto nodata;	retval->subh.ecn_cwr_hdr =		sctp_addto_chunk(retval, sizeof(cwr), &cwr);	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,	 * HEARTBEAT ACK, * etc.) to the same destination transport	 * address from which it * received the DATA or control chunk	 * to which it is replying.	 *	 * [Report a reduced congestion window back to where the ECNE	 * came from.]	 */	if (chunk)		retval->transport = chunk->transport;nodata:	return retval;}/* Make an ECNE chunk.  This is a congestion experienced report.  */struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc,			     const __u32 lowest_tsn){	struct sctp_chunk *retval;	sctp_ecnehdr_t ecne;	ecne.lowest_tsn = htonl(lowest_tsn);	retval = sctp_make_chunk(asoc, SCTP_CID_ECN_ECNE, 0,				 sizeof(sctp_ecnehdr_t));	if (!retval)		goto nodata;	retval->subh.ecne_hdr =		sctp_addto_chunk(retval, sizeof(ecne), &ecne);nodata:	return retval;}/* Make a DATA chunk for the given association from the provided * parameters.  However, do not populate the data payload. */struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,				       const struct sctp_sndrcvinfo *sinfo,				       int data_len, __u8 flags, __u16 ssn){	struct sctp_chunk *retval;	struct sctp_datahdr dp;	int chunk_len;	/* We assign the TSN as LATE as possible, not here when	 * creating the chunk.	 */	dp.tsn = 0;	dp.stream = htons(sinfo->sinfo_stream);	dp.ppid   = sinfo->sinfo_ppid;	/* Set the flags for an unordered send.  */	if (sinfo->sinfo_flags & MSG_UNORDERED) {		flags |= SCTP_DATA_UNORDERED;		dp.ssn = 0;	} else		dp.ssn = htons(ssn);	chunk_len = sizeof(dp) + data_len;	retval = sctp_make_chunk(asoc, SCTP_CID_DATA, flags, chunk_len);	if (!retval)		goto nodata;	retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);	memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));nodata:	return retval;}/* Make a DATA chunk for the given association.  Populate the data * payload. */struct sctp_chunk *sctp_make_datafrag(struct sctp_association *asoc,				 const struct sctp_sndrcvinfo *sinfo,				 int data_len, const __u8 *data,				 __u8 flags, __u16 ssn){	struct sctp_chunk *retval;	retval = sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, ssn);	if (retval)		sctp_addto_chunk(retval, data_len, data);	return retval;}/* Make a DATA chunk for the given association to ride on stream id * 'stream', with a payload id of 'payload', and a body of 'data'. */struct sctp_chunk *sctp_make_data(struct sctp_association *asoc,			     const struct sctp_sndrcvinfo *sinfo,			     int data_len, const __u8 *data){	struct sctp_chunk *retval = NULL;	retval = sctp_make_data_empty(asoc, sinfo, data_len);	if (retval)		sctp_addto_chunk(retval, data_len, data);        return retval;}/* Make a DATA chunk for the given association to ride on stream id * 'stream', with a payload id of 'payload', and a body big enough to * hold 'data_len' octets of data.  We use this version when we need * to build the message AFTER allocating memory. */struct sctp_chunk *sctp_make_data_empty(struct sctp_association *asoc,				   const struct sctp_sndrcvinfo *sinfo,				   int data_len){	__u8 flags = SCTP_DATA_NOT_FRAG;	return sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, 0);}/* Create a selective ackowledgement (SACK) for the given * association.  This reports on which TSN's we've seen to date, * including duplicates and gaps. */struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc){	struct sctp_chunk *retval;	struct sctp_sackhdr sack;	int len;	__u32 ctsn;	__u16 num_gabs, num_dup_tsns;	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;	ctsn = sctp_tsnmap_get_ctsn(map);	SCTP_DEBUG_PRINTK("sackCTSNAck sent:  0x%x.\n", ctsn);	/* How much room is needed in the chunk? */	num_gabs = sctp_tsnmap_num_gabs(map);	num_dup_tsns = sctp_tsnmap_num_dups(map);	/* Initialize the SACK header.  */	sack.cum_tsn_ack	    = htonl(ctsn);	sack.a_rwnd 		    = htonl(asoc->a_rwnd);	sack.num_gap_ack_blocks     = htons(num_gabs);	sack.num_dup_tsns           = htons(num_dup_tsns);	len = sizeof(sack)		+ sizeof(struct sctp_gap_ack_block) * num_gabs		+ sizeof(__u32) * num_dup_tsns;	/* Create the chunk.  */	retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, len);	if (!retval)		goto nodata;	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,	 * HEARTBEAT ACK, etc.) to the same destination transport	 * address from which it received the DATA or control chunk to	 * which it is replying.  This rule should also be followed if	 * the endpoint is bundling DATA chunks together with the	 * reply chunk.	 *	 * However, when acknowledging multiple DATA chunks received	 * in packets from different source addresses in a single	 * SACK, the SACK chunk may be transmitted to one of the	 * destination transport addresses from which the DATA or	 * control chunks being acknowledged were received.	 *	 * [BUG:  We do not implement the following paragraph.	 * Perhaps we should remember the last transport we used for a	 * SACK and avoid that (if possible) if we have seen any	 * duplicates. --piggy]	 *	 * When a receiver of a duplicate DATA chunk sends a SACK to a	 * multi- homed endpoint it MAY be beneficial to vary the	 * destination address and not use the source address of the	 * DATA chunk.  The reason being that receiving a duplicate	 * from a multi-homed endpoint might indicate that the return	 * path (as specified in the source address of the DATA chunk)	 * for the SACK is broken.	 *	 * [Send to the address from which we last received a DATA chunk.]	 */	retval->transport = asoc->peer.last_data_from;	retval->subh.sack_hdr =		sctp_addto_chunk(retval, sizeof(sack), &sack);	/* Add the gap ack block information.   */	if (num_gabs)		sctp_addto_chunk(retval, sizeof(__u32) * num_gabs,				 sctp_tsnmap_get_gabs(map));	/* Add the duplicate TSN information.  */	if (num_dup_tsns)		sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,				 sctp_tsnmap_get_dups(map));nodata:	return retval;}/* Make a SHUTDOWN chunk. */struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,				      const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	sctp_shutdownhdr_t shut;	__u32 ctsn;	ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);	shut.cum_tsn_ack = htonl(ctsn);	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN, 0,				 sizeof(sctp_shutdownhdr_t));	if (!retval)		goto nodata;	retval->subh.shutdown_hdr =		sctp_addto_chunk(retval, sizeof(shut), &shut);	if (chunk)		retval->transport = chunk->transport;nodata:	return retval;}struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,				     const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0);	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,	 * HEARTBEAT ACK, * etc.) to the same destination transport	 * address from which it * received the DATA or control chunk	 * to which it is replying.	 *	 * [ACK back to where the SHUTDOWN came from.]	 */	if (retval && chunk)		retval->transport = chunk->transport;	return retval;}struct sctp_chunk *sctp_make_shutdown_complete(	const struct sctp_association *asoc,	const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	__u8 flags = 0;	/* Maybe set the T-bit if we have no association. */	flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0);	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,	 * HEARTBEAT ACK, * etc.) to the same destination transport	 * address from which it * received the DATA or control chunk	 * to which it is replying.	 *	 * [Report SHUTDOWN COMPLETE back to where the SHUTDOWN ACK	 * came from.]	 */	if (retval && chunk)		retval->transport = chunk->transport;        return retval;}/* Create an ABORT.  Note that we set the T bit if we have no * association. */struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc,			      const struct sctp_chunk *chunk,			      const size_t hint){	struct sctp_chunk *retval;	__u8 flags = 0;	/* Maybe set the T-bit if we have no association.  */	flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;	retval = sctp_make_chunk(asoc, SCTP_CID_ABORT, flags, hint);	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,	 * HEARTBEAT ACK, * etc.) to the same destination transport	 * address from which it * received the DATA or control chunk	 * to which it is replying.	 *	 * [ABORT back to where the offender came from.]	 */	if (retval && chunk)		retval->transport = chunk->transport;	return retval;}/* Helper to create ABORT with a NO_USER_DATA error.  */struct sctp_chunk *sctp_make_abort_no_data(	const struct sctp_association *asoc,	const struct sctp_chunk *chunk, __u32 tsn){	struct sctp_chunk *retval;	__u32 payload;	retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t)				 + sizeof(tsn));	if (!retval)		goto no_mem;	/* Put the tsn back into network byte order.  */	payload = htonl(tsn);	sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload,			sizeof(payload));	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,	 * HEARTBEAT ACK, * etc.) to the same destination transport	 * address from which it * received the DATA or control chunk	 * to which it is replying.	 *	 * [ABORT back to where the offender came from.]	 */	if (chunk)		retval->transport = chunk->transport;no_mem:	return retval;}/* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error.  */struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,				   const struct sctp_chunk *chunk,				   const struct msghdr *msg){	struct sctp_chunk *retval;	void *payload = NULL, *payoff;	size_t paylen = 0;	struct iovec *iov = NULL;	int iovlen = 0;	if (msg) {		iov = msg->msg_iov;		iovlen = msg->msg_iovlen;		paylen = get_user_iov_size(iov, iovlen);	}	retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen);	if (!retval)		goto err_chunk;	if (paylen) {		/* Put the msg_iov together into payload.  */		payload = kmalloc(paylen, GFP_ATOMIC);		if (!payload)			goto err_payload;		payoff = payload;		for (; iovlen > 0; --iovlen) {			if (copy_from_user(payoff, iov->iov_base,iov->iov_len))				goto err_copy;			payoff += iov->iov_len;			iov++;		}	}	sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);	if (paylen)		kfree(payload);	return retval;err_copy:	kfree(payload);err_payload:	sctp_chunk_free(retval);	retval = NULL;err_chunk:	return retval;}/* Make a HEARTBEAT chunk.  */struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,				  const struct sctp_transport *transport,				  const void *payload, const size_t paylen){	struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT,						    0, paylen);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -