diff options
author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-08-23 21:50:06 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 16:04:31 -0700 |
commit | 7ad07e7cf343181002c10c39d3f57a88e4903d4f (patch) | |
tree | c22067f3f443faebdcd3403fa8ce7c5c89662c60 /net/dccp/output.c | |
parent | 58e45131dc269eff0983c6d44494f9e687686900 (diff) | |
download | op-kernel-dev-7ad07e7cf343181002c10c39d3f57a88e4903d4f.zip op-kernel-dev-7ad07e7cf343181002c10c39d3f57a88e4903d4f.tar.gz |
[DCCP]: Implement the CLOSING timer
So that we retransmit CLOSE/CLOSEREQ packets till they elicit an
answer or we hit a timeout.
Most of the machinery uses TCP approaches, this code has to be
polished & audited, but this is better than we had before.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r-- | net/dccp/output.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c index 708fc3c..630ca77 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -96,8 +96,7 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr, inet->daddr); - if (dcb->dccpd_type == DCCP_PKT_ACK || - dcb->dccpd_type == DCCP_PKT_DATAACK) + if (set_ack) dccp_event_ack_sent(sk); DCCP_INC_STATS(DCCP_MIB_OUTSEGS); @@ -429,18 +428,15 @@ void dccp_send_sync(struct sock *sk, const u64 seq, * cannot be allowed to fail queueing a DCCP_PKT_CLOSE/CLOSEREQ frame under * any circumstances. */ -void dccp_send_close(struct sock *sk) +void dccp_send_close(struct sock *sk, const int active) { struct dccp_sock *dp = dccp_sk(sk); struct sk_buff *skb; + const unsigned int prio = active ? GFP_KERNEL : GFP_ATOMIC; - /* Socket is locked, keep trying until memory is available. */ - for (;;) { - skb = alloc_skb(sk->sk_prot->max_header, GFP_KERNEL); - if (skb != NULL) - break; - yield(); - } + skb = alloc_skb(sk->sk_prot->max_header, prio); + if (skb == NULL) + return; /* Reserve space for headers and prepare control bits. */ skb_reserve(skb, sk->sk_prot->max_header); @@ -449,7 +445,12 @@ void dccp_send_close(struct sock *sk) DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; skb_set_owner_w(skb, sk); - dccp_transmit_skb(sk, skb); + if (active) { + BUG_TRAP(sk->sk_send_head == NULL); + sk->sk_send_head = skb; + dccp_transmit_skb(sk, skb_clone(skb, prio)); + } else + dccp_transmit_skb(sk, skb); ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); |