aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/dccp.txt2
-rw-r--r--net/dccp/input.c27
-rw-r--r--net/dccp/proto.c2
3 files changed, 23 insertions, 8 deletions
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index afb66f9a8aff..f771034e8f27 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -72,6 +72,8 @@ DCCP_SOCKOPT_CCID_TX_INFO
72 Returns a `struct tfrc_tx_info' in optval; the buffer for optval and 72 Returns a `struct tfrc_tx_info' in optval; the buffer for optval and
73 optlen must be set to at least sizeof(struct tfrc_tx_info). 73 optlen must be set to at least sizeof(struct tfrc_tx_info).
74 74
75On unidirectional connections it is useful to close the unused half-connection
76via shutdown (SHUT_WR or SHUT_RD): this will reduce per-packet processing costs.
75 77
76Sysctl variables 78Sysctl variables
77================ 79================
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 1ce101062824..df0fb2c149a6 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -103,6 +103,21 @@ static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
103 DCCP_SKB_CB(skb)->dccpd_ack_seq); 103 DCCP_SKB_CB(skb)->dccpd_ack_seq);
104} 104}
105 105
106static void dccp_deliver_input_to_ccids(struct sock *sk, struct sk_buff *skb)
107{
108 const struct dccp_sock *dp = dccp_sk(sk);
109
110 /* Don't deliver to RX CCID when node has shut down read end. */
111 if (!(sk->sk_shutdown & RCV_SHUTDOWN))
112 ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
113 /*
114 * Until the TX queue has been drained, we can not honour SHUT_WR, since
115 * we need received feedback as input to adjust congestion control.
116 */
117 if (sk->sk_write_queue.qlen > 0 || !(sk->sk_shutdown & SEND_SHUTDOWN))
118 ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
119}
120
106static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) 121static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
107{ 122{
108 const struct dccp_hdr *dh = dccp_hdr(skb); 123 const struct dccp_hdr *dh = dccp_hdr(skb);
@@ -209,8 +224,9 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
209 case DCCP_PKT_DATAACK: 224 case DCCP_PKT_DATAACK:
210 case DCCP_PKT_DATA: 225 case DCCP_PKT_DATA:
211 /* 226 /*
212 * FIXME: check if sk_receive_queue is full, schedule DATA_DROPPED 227 * FIXME: schedule DATA_DROPPED (RFC 4340, 11.7.2) if and when
213 * option if it is. 228 * - sk_shutdown == RCV_SHUTDOWN, use Code 1, "Not Listening"
229 * - sk_receive_queue is full, use Code 2, "Receive Buffer"
214 */ 230 */
215 __skb_pull(skb, dh->dccph_doff * 4); 231 __skb_pull(skb, dh->dccph_doff * 4);
216 __skb_queue_tail(&sk->sk_receive_queue, skb); 232 __skb_queue_tail(&sk->sk_receive_queue, skb);
@@ -300,9 +316,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
300 DCCP_SKB_CB(skb)->dccpd_seq, 316 DCCP_SKB_CB(skb)->dccpd_seq,
301 DCCP_ACKVEC_STATE_RECEIVED)) 317 DCCP_ACKVEC_STATE_RECEIVED))
302 goto discard; 318 goto discard;
303 319 dccp_deliver_input_to_ccids(sk, skb);
304 ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
305 ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
306 320
307 return __dccp_rcv_established(sk, skb, dh, len); 321 return __dccp_rcv_established(sk, skb, dh, len);
308discard: 322discard:
@@ -543,8 +557,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
543 DCCP_ACKVEC_STATE_RECEIVED)) 557 DCCP_ACKVEC_STATE_RECEIVED))
544 goto discard; 558 goto discard;
545 559
546 ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); 560 dccp_deliver_input_to_ccids(sk, skb);
547 ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
548 } 561 }
549 562
550 /* 563 /*
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 7a3bea9c28c1..0aec73592124 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -981,7 +981,7 @@ EXPORT_SYMBOL_GPL(dccp_close);
981 981
982void dccp_shutdown(struct sock *sk, int how) 982void dccp_shutdown(struct sock *sk, int how)
983{ 983{
984 dccp_pr_debug("entry\n"); 984 dccp_pr_debug("called shutdown(%x)\n", how);
985} 985}
986 986
987EXPORT_SYMBOL_GPL(dccp_shutdown); 987EXPORT_SYMBOL_GPL(dccp_shutdown);