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

📄 output.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  net/dccp/output.c * *  An implementation of the DCCP protocol *  Arnaldo Carvalho de Melo <acme@conectiva.com.br> * *	This program is free software; you can redistribute it and/or *	modify it under the terms of the GNU General Public License *	as published by the Free Software Foundation; either version *	2 of the License, or (at your option) any later version. */#include <linux/dccp.h>#include <linux/kernel.h>#include <linux/skbuff.h>#include <net/inet_sock.h>#include <net/sock.h>#include "ackvec.h"#include "ccid.h"#include "dccp.h"static inline void dccp_event_ack_sent(struct sock *sk){	inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);}static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb){	skb_set_owner_w(skb, sk);	WARN_ON(sk->sk_send_head);	sk->sk_send_head = skb;}/* * All SKB's seen here are completely headerless. It is our * job to build the DCCP header, and pass the packet down to * IP so it can do the same plus pass the packet off to the * device. */static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb){	if (likely(skb != NULL)) {		const struct inet_sock *inet = inet_sk(sk);		const struct inet_connection_sock *icsk = inet_csk(sk);		struct dccp_sock *dp = dccp_sk(sk);		struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);		struct dccp_hdr *dh;		/* XXX For now we're using only 48 bits sequence numbers */		const u32 dccp_header_size = sizeof(*dh) +					     sizeof(struct dccp_hdr_ext) +					  dccp_packet_hdr_len(dcb->dccpd_type);		int err, set_ack = 1;		u64 ackno = dp->dccps_gsr;		dccp_inc_seqno(&dp->dccps_gss);		switch (dcb->dccpd_type) {		case DCCP_PKT_DATA:			set_ack = 0;			/* fall through */		case DCCP_PKT_DATAACK:		case DCCP_PKT_RESET:			break;		case DCCP_PKT_REQUEST:			set_ack = 0;			/* fall through */		case DCCP_PKT_SYNC:		case DCCP_PKT_SYNCACK:			ackno = dcb->dccpd_ack_seq;			/* fall through */		default:			/*			 * Set owner/destructor: some skbs are allocated via			 * alloc_skb (e.g. when retransmission may happen).			 * Only Data, DataAck, and Reset packets should come			 * through here with skb->sk set.			 */			WARN_ON(skb->sk);			skb_set_owner_w(skb, sk);			break;		}		dcb->dccpd_seq = dp->dccps_gss;		if (dccp_insert_options(sk, skb)) {			kfree_skb(skb);			return -EPROTO;		}		/* Build DCCP header and checksum it. */		dh = dccp_zeroed_hdr(skb, dccp_header_size);		dh->dccph_type	= dcb->dccpd_type;		dh->dccph_sport	= inet->sport;		dh->dccph_dport	= inet->dport;		dh->dccph_doff	= (dccp_header_size + dcb->dccpd_opt_len) / 4;		dh->dccph_ccval	= dcb->dccpd_ccval;		dh->dccph_cscov = dp->dccps_pcslen;		/* XXX For now we're using only 48 bits sequence numbers */		dh->dccph_x	= 1;		dp->dccps_awh = dp->dccps_gss;		dccp_hdr_set_seq(dh, dp->dccps_gss);		if (set_ack)			dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);		switch (dcb->dccpd_type) {		case DCCP_PKT_REQUEST:			dccp_hdr_request(skb)->dccph_req_service =							dp->dccps_service;			break;		case DCCP_PKT_RESET:			dccp_hdr_reset(skb)->dccph_reset_code =							dcb->dccpd_reset_code;			break;		}		icsk->icsk_af_ops->send_check(sk, 0, skb);		if (set_ack)			dccp_event_ack_sent(sk);		DCCP_INC_STATS(DCCP_MIB_OUTSEGS);		memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));		err = icsk->icsk_af_ops->queue_xmit(skb, 0);		return net_xmit_eval(err);	}	return -ENOBUFS;}unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu){	struct inet_connection_sock *icsk = inet_csk(sk);	struct dccp_sock *dp = dccp_sk(sk);	int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len -		       sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext));	/* Now subtract optional transport overhead */	mss_now -= icsk->icsk_ext_hdr_len;	/*	 * FIXME: this should come from the CCID infrastructure, where, say,	 * TFRC will say it wants TIMESTAMPS, ELAPSED time, etc, for now lets	 * put a rough estimate for NDP + TIMESTAMP + TIMESTAMP_ECHO + ELAPSED	 * TIME + TFRC_OPT_LOSS_EVENT_RATE + TFRC_OPT_RECEIVE_RATE + padding to	 * make it a multiple of 4	 */	mss_now -= ((5 + 6 + 10 + 6 + 6 + 6 + 3) / 4) * 4;	/* And store cached results */	icsk->icsk_pmtu_cookie = pmtu;	dp->dccps_mss_cache = mss_now;	return mss_now;}EXPORT_SYMBOL_GPL(dccp_sync_mss);void dccp_write_space(struct sock *sk){	read_lock(&sk->sk_callback_lock);	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))		wake_up_interruptible(sk->sk_sleep);	/* Should agree with poll, otherwise some programs break */	if (sock_writeable(sk))		sk_wake_async(sk, 2, POLL_OUT);	read_unlock(&sk->sk_callback_lock);}/** * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet * @sk:    socket to wait for * @skb:   current skb to pass on for waiting * @delay: sleep timeout in milliseconds (> 0) * This function is called by default when the socket is closed, and * when a non-zero linger time is set on the socket. For consistency */static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay){	struct dccp_sock *dp = dccp_sk(sk);	DEFINE_WAIT(wait);	unsigned long jiffdelay;	int rc;	do {		dccp_pr_debug("delayed send by %d msec\n", delay);		jiffdelay = msecs_to_jiffies(delay);		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);		sk->sk_write_pending++;		release_sock(sk);		schedule_timeout(jiffdelay);		lock_sock(sk);		sk->sk_write_pending--;		if (sk->sk_err)			goto do_error;		if (signal_pending(current))			goto do_interrupted;		rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);	} while ((delay = rc) > 0);out:	finish_wait(sk->sk_sleep, &wait);	return rc;do_error:	rc = -EPIPE;	goto out;do_interrupted:	rc = -EINTR;	goto out;}void dccp_write_xmit(struct sock *sk, int block){	struct dccp_sock *dp = dccp_sk(sk);	struct sk_buff *skb;	while ((skb = skb_peek(&sk->sk_write_queue))) {		int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);		if (err > 0) {			if (!block) {				sk_reset_timer(sk, &dp->dccps_xmit_timer,						msecs_to_jiffies(err)+jiffies);				break;			} else				err = dccp_wait_for_ccid(sk, skb, err);			if (err && err != -EINTR)				DCCP_BUG("err=%d after dccp_wait_for_ccid", err);		}		skb_dequeue(&sk->sk_write_queue);		if (err == 0) {			struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);			const int len = skb->len;			if (sk->sk_state == DCCP_PARTOPEN) {				/* See 8.1.5.  Handshake Completion */				inet_csk_schedule_ack(sk);				inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,						  inet_csk(sk)->icsk_rto,						  DCCP_RTO_MAX);				dcb->dccpd_type = DCCP_PKT_DATAACK;			} else if (dccp_ack_pending(sk))				dcb->dccpd_type = DCCP_PKT_DATAACK;			else				dcb->dccpd_type = DCCP_PKT_DATA;			err = dccp_transmit_skb(sk, skb);			ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);			if (err)				DCCP_BUG("err=%d after ccid_hc_tx_packet_sent",					 err);		} else {			dccp_pr_debug("packet discarded due to err=%d\n", err);			kfree_skb(skb);		}	}}int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb){	if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)		return -EHOSTUNREACH; /* Routing failure or similar. */	return dccp_transmit_skb(sk, (skb_cloned(skb) ?				      pskb_copy(skb, GFP_ATOMIC):				      skb_clone(skb, GFP_ATOMIC)));}struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,				   struct request_sock *req){	struct dccp_hdr *dh;	struct dccp_request_sock *dreq;	const u32 dccp_header_size = sizeof(struct dccp_hdr) +				     sizeof(struct dccp_hdr_ext) +				     sizeof(struct dccp_hdr_response);	struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1,					   GFP_ATOMIC);

⌨️ 快捷键说明

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