diff options
-rw-r--r-- | Documentation/networking/dccp.txt | 2 | ||||
-rw-r--r-- | net/dccp/input.c | 27 | ||||
-rw-r--r-- | net/dccp/proto.c | 2 |
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 | ||
75 | On unidirectional connections it is useful to close the unused half-connection | ||
76 | via shutdown (SHUT_WR or SHUT_RD): this will reduce per-packet processing costs. | ||
75 | 77 | ||
76 | Sysctl variables | 78 | Sysctl 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 | ||
106 | static 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 | |||
106 | static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) | 121 | static 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); |
308 | discard: | 322 | discard: |
@@ -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 | ||
982 | void dccp_shutdown(struct sock *sk, int how) | 982 | void 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 | ||
987 | EXPORT_SYMBOL_GPL(dccp_shutdown); | 987 | EXPORT_SYMBOL_GPL(dccp_shutdown); |