diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-24 13:01:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-24 13:01:50 -0400 |
commit | 3c4cfadef6a1665d9cd02a543782d03d3e6740c6 (patch) | |
tree | 3df72faaacd494d5ac8c9668df4f529b1b5e4457 /net/sctp | |
parent | e017507f37d5cb8b541df165a824958bc333bec3 (diff) | |
parent | 320f5ea0cedc08ef65d67e056bcb9d181386ef2c (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David S Miller:
1) Remove the ipv4 routing cache. Now lookups go directly into the FIB
trie and use prebuilt routes cached there.
No more garbage collection, no more rDOS attacks on the routing
cache. Instead we now get predictable and consistent performance,
no matter what the pattern of traffic we service.
This has been almost 2 years in the making. Special thanks to
Julian Anastasov, Eric Dumazet, Steffen Klassert, and others who
have helped along the way.
I'm sure that with a change of this magnitude there will be some
kind of fallout, but such things ought the be simple to fix at this
point. Luckily I'm not European so I'll be around all of August to
fix things :-)
The major stages of this work here are each fronted by a forced
merge commit whose commit message contains a top-level description
of the motivations and implementation issues.
2) Pre-demux of established ipv4 TCP sockets, saves a route demux on
input.
3) TCP SYN/ACK performance tweaks from Eric Dumazet.
4) Add namespace support for netfilter L4 conntrack helpers, from Gao
Feng.
5) Add config mechanism for Energy Efficient Ethernet to ethtool, from
Yuval Mintz.
6) Remove quadratic behavior from /proc/net/unix, from Eric Dumazet.
7) Support for connection tracker helpers in userspace, from Pablo
Neira Ayuso.
8) Allow userspace driven TX load balancing functions in TEAM driver,
from Jiri Pirko.
9) Kill off NLMSG_PUT and RTA_PUT macros, more gross stuff with
embedded gotos.
10) TCP Small Queues, essentially minimize the amount of TCP data queued
up in the packet scheduler layer. Whereas the existing BQL (Byte
Queue Limits) limits the pkt_sched --> netdevice queuing levels,
this controls the TCP --> pkt_sched queueing levels.
From Eric Dumazet.
11) Reduce the number of get_page/put_page ops done on SKB fragments,
from Alexander Duyck.
12) Implement protection against blind resets in TCP (RFC 5961), from
Eric Dumazet.
13) Support the client side of TCP Fast Open, basically the ability to
send data in the SYN exchange, from Yuchung Cheng.
Basically, the sender queues up data with a sendmsg() call using
MSG_FASTOPEN, then they do the connect() which emits the queued up
fastopen data.
14) Avoid all the problems we get into in TCP when timers or PMTU events
hit a locked socket. The TCP Small Queues changes added a
tcp_release_cb() that allows us to queue work up to the
release_sock() caller, and that's what we use here too. From Eric
Dumazet.
15) Zero copy on TX support for TUN driver, from Michael S. Tsirkin.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1870 commits)
genetlink: define lockdep_genl_is_held() when CONFIG_LOCKDEP
r8169: revert "add byte queue limit support".
ipv4: Change rt->rt_iif encoding.
net: Make skb->skb_iif always track skb->dev
ipv4: Prepare for change of rt->rt_iif encoding.
ipv4: Remove all RTCF_DIRECTSRC handliing.
ipv4: Really ignore ICMP address requests/replies.
decnet: Don't set RTCF_DIRECTSRC.
net/ipv4/ip_vti.c: Fix __rcu warnings detected by sparse.
ipv4: Remove redundant assignment
rds: set correct msg_namelen
openvswitch: potential NULL deref in sample()
tcp: dont drop MTU reduction indications
bnx2x: Add new 57840 device IDs
tcp: avoid oops in tcp_metrics and reset tcpm_stamp
niu: Change niu_rbr_fill() to use unlikely() to check niu_rbr_add_page() return value
niu: Fix to check for dma mapping errors.
net: Fix references to out-of-scope variables in put_cmsg_compat()
net: ethernet: davinci_emac: add pm_runtime support
net: ethernet: davinci_emac: Remove unnecessary #include
...
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 41 | ||||
-rw-r--r-- | net/sctp/input.c | 20 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 3 | ||||
-rw-r--r-- | net/sctp/output.c | 81 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 6 | ||||
-rw-r--r-- | net/sctp/protocol.c | 2 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 2 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 33 | ||||
-rw-r--r-- | net/sctp/socket.c | 107 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 9 | ||||
-rw-r--r-- | net/sctp/transport.c | 20 |
11 files changed, 269 insertions, 55 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index b16517ee1aaf..ebaef3ed6065 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -124,6 +124,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
124 | * socket values. | 124 | * socket values. |
125 | */ | 125 | */ |
126 | asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; | 126 | asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; |
127 | asoc->pf_retrans = sctp_pf_retrans; | ||
128 | |||
127 | asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial); | 129 | asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial); |
128 | asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max); | 130 | asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max); |
129 | asoc->rto_min = msecs_to_jiffies(sp->rtoinfo.srto_min); | 131 | asoc->rto_min = msecs_to_jiffies(sp->rtoinfo.srto_min); |
@@ -686,6 +688,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
686 | /* Set the path max_retrans. */ | 688 | /* Set the path max_retrans. */ |
687 | peer->pathmaxrxt = asoc->pathmaxrxt; | 689 | peer->pathmaxrxt = asoc->pathmaxrxt; |
688 | 690 | ||
691 | /* And the partial failure retrnas threshold */ | ||
692 | peer->pf_retrans = asoc->pf_retrans; | ||
693 | |||
689 | /* Initialize the peer's SACK delay timeout based on the | 694 | /* Initialize the peer's SACK delay timeout based on the |
690 | * association configured value. | 695 | * association configured value. |
691 | */ | 696 | */ |
@@ -841,6 +846,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
841 | struct sctp_ulpevent *event; | 846 | struct sctp_ulpevent *event; |
842 | struct sockaddr_storage addr; | 847 | struct sockaddr_storage addr; |
843 | int spc_state = 0; | 848 | int spc_state = 0; |
849 | bool ulp_notify = true; | ||
844 | 850 | ||
845 | /* Record the transition on the transport. */ | 851 | /* Record the transition on the transport. */ |
846 | switch (command) { | 852 | switch (command) { |
@@ -854,6 +860,14 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
854 | spc_state = SCTP_ADDR_CONFIRMED; | 860 | spc_state = SCTP_ADDR_CONFIRMED; |
855 | else | 861 | else |
856 | spc_state = SCTP_ADDR_AVAILABLE; | 862 | spc_state = SCTP_ADDR_AVAILABLE; |
863 | /* Don't inform ULP about transition from PF to | ||
864 | * active state and set cwnd to 1, see SCTP | ||
865 | * Quick failover draft section 5.1, point 5 | ||
866 | */ | ||
867 | if (transport->state == SCTP_PF) { | ||
868 | ulp_notify = false; | ||
869 | transport->cwnd = 1; | ||
870 | } | ||
857 | transport->state = SCTP_ACTIVE; | 871 | transport->state = SCTP_ACTIVE; |
858 | break; | 872 | break; |
859 | 873 | ||
@@ -872,6 +886,11 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
872 | spc_state = SCTP_ADDR_UNREACHABLE; | 886 | spc_state = SCTP_ADDR_UNREACHABLE; |
873 | break; | 887 | break; |
874 | 888 | ||
889 | case SCTP_TRANSPORT_PF: | ||
890 | transport->state = SCTP_PF; | ||
891 | ulp_notify = false; | ||
892 | break; | ||
893 | |||
875 | default: | 894 | default: |
876 | return; | 895 | return; |
877 | } | 896 | } |
@@ -879,12 +898,15 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
879 | /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the | 898 | /* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the |
880 | * user. | 899 | * user. |
881 | */ | 900 | */ |
882 | memset(&addr, 0, sizeof(struct sockaddr_storage)); | 901 | if (ulp_notify) { |
883 | memcpy(&addr, &transport->ipaddr, transport->af_specific->sockaddr_len); | 902 | memset(&addr, 0, sizeof(struct sockaddr_storage)); |
884 | event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, | 903 | memcpy(&addr, &transport->ipaddr, |
885 | 0, spc_state, error, GFP_ATOMIC); | 904 | transport->af_specific->sockaddr_len); |
886 | if (event) | 905 | event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, |
887 | sctp_ulpq_tail_event(&asoc->ulpq, event); | 906 | 0, spc_state, error, GFP_ATOMIC); |
907 | if (event) | ||
908 | sctp_ulpq_tail_event(&asoc->ulpq, event); | ||
909 | } | ||
888 | 910 | ||
889 | /* Select new active and retran paths. */ | 911 | /* Select new active and retran paths. */ |
890 | 912 | ||
@@ -900,7 +922,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
900 | transports) { | 922 | transports) { |
901 | 923 | ||
902 | if ((t->state == SCTP_INACTIVE) || | 924 | if ((t->state == SCTP_INACTIVE) || |
903 | (t->state == SCTP_UNCONFIRMED)) | 925 | (t->state == SCTP_UNCONFIRMED) || |
926 | (t->state == SCTP_PF)) | ||
904 | continue; | 927 | continue; |
905 | if (!first || t->last_time_heard > first->last_time_heard) { | 928 | if (!first || t->last_time_heard > first->last_time_heard) { |
906 | second = first; | 929 | second = first; |
@@ -1360,7 +1383,7 @@ struct sctp_transport *sctp_assoc_choose_alter_transport( | |||
1360 | /* Update the association's pmtu and frag_point by going through all the | 1383 | /* Update the association's pmtu and frag_point by going through all the |
1361 | * transports. This routine is called when a transport's PMTU has changed. | 1384 | * transports. This routine is called when a transport's PMTU has changed. |
1362 | */ | 1385 | */ |
1363 | void sctp_assoc_sync_pmtu(struct sctp_association *asoc) | 1386 | void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc) |
1364 | { | 1387 | { |
1365 | struct sctp_transport *t; | 1388 | struct sctp_transport *t; |
1366 | __u32 pmtu = 0; | 1389 | __u32 pmtu = 0; |
@@ -1372,7 +1395,7 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc) | |||
1372 | list_for_each_entry(t, &asoc->peer.transport_addr_list, | 1395 | list_for_each_entry(t, &asoc->peer.transport_addr_list, |
1373 | transports) { | 1396 | transports) { |
1374 | if (t->pmtu_pending && t->dst) { | 1397 | if (t->pmtu_pending && t->dst) { |
1375 | sctp_transport_update_pmtu(t, dst_mtu(t->dst)); | 1398 | sctp_transport_update_pmtu(sk, t, dst_mtu(t->dst)); |
1376 | t->pmtu_pending = 0; | 1399 | t->pmtu_pending = 0; |
1377 | } | 1400 | } |
1378 | if (!pmtu || (t->pathmtu < pmtu)) | 1401 | if (!pmtu || (t->pathmtu < pmtu)) |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 8b9b6790a3df..e64d5210ed13 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -408,10 +408,10 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | |||
408 | 408 | ||
409 | if (t->param_flags & SPP_PMTUD_ENABLE) { | 409 | if (t->param_flags & SPP_PMTUD_ENABLE) { |
410 | /* Update transports view of the MTU */ | 410 | /* Update transports view of the MTU */ |
411 | sctp_transport_update_pmtu(t, pmtu); | 411 | sctp_transport_update_pmtu(sk, t, pmtu); |
412 | 412 | ||
413 | /* Update association pmtu. */ | 413 | /* Update association pmtu. */ |
414 | sctp_assoc_sync_pmtu(asoc); | 414 | sctp_assoc_sync_pmtu(sk, asoc); |
415 | } | 415 | } |
416 | 416 | ||
417 | /* Retransmit with the new pmtu setting. | 417 | /* Retransmit with the new pmtu setting. |
@@ -423,6 +423,18 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | |||
423 | sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD); | 423 | sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD); |
424 | } | 424 | } |
425 | 425 | ||
426 | void sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t, | ||
427 | struct sk_buff *skb) | ||
428 | { | ||
429 | struct dst_entry *dst; | ||
430 | |||
431 | if (!t) | ||
432 | return; | ||
433 | dst = sctp_transport_dst_check(t); | ||
434 | if (dst) | ||
435 | dst->ops->redirect(dst, sk, skb); | ||
436 | } | ||
437 | |||
426 | /* | 438 | /* |
427 | * SCTP Implementer's Guide, 2.37 ICMP handling procedures | 439 | * SCTP Implementer's Guide, 2.37 ICMP handling procedures |
428 | * | 440 | * |
@@ -628,6 +640,10 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
628 | 640 | ||
629 | err = EHOSTUNREACH; | 641 | err = EHOSTUNREACH; |
630 | break; | 642 | break; |
643 | case ICMP_REDIRECT: | ||
644 | sctp_icmp_redirect(sk, transport, skb); | ||
645 | err = 0; | ||
646 | break; | ||
631 | default: | 647 | default: |
632 | goto out_unlock; | 648 | goto out_unlock; |
633 | } | 649 | } |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 91f479121c55..ed7139ea7978 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -185,6 +185,9 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
185 | goto out_unlock; | 185 | goto out_unlock; |
186 | } | 186 | } |
187 | break; | 187 | break; |
188 | case NDISC_REDIRECT: | ||
189 | sctp_icmp_redirect(sk, transport, skb); | ||
190 | break; | ||
188 | default: | 191 | default: |
189 | break; | 192 | break; |
190 | } | 193 | } |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 6ae47acaaec6..838e18b4d7ea 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -64,6 +64,8 @@ | |||
64 | #include <net/sctp/checksum.h> | 64 | #include <net/sctp/checksum.h> |
65 | 65 | ||
66 | /* Forward declarations for private helpers. */ | 66 | /* Forward declarations for private helpers. */ |
67 | static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, | ||
68 | struct sctp_chunk *chunk); | ||
67 | static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | 69 | static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, |
68 | struct sctp_chunk *chunk); | 70 | struct sctp_chunk *chunk); |
69 | static void sctp_packet_append_data(struct sctp_packet *packet, | 71 | static void sctp_packet_append_data(struct sctp_packet *packet, |
@@ -224,7 +226,10 @@ static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt, | |||
224 | if (!auth) | 226 | if (!auth) |
225 | return retval; | 227 | return retval; |
226 | 228 | ||
227 | retval = sctp_packet_append_chunk(pkt, auth); | 229 | retval = __sctp_packet_append_chunk(pkt, auth); |
230 | |||
231 | if (retval != SCTP_XMIT_OK) | ||
232 | sctp_chunk_free(auth); | ||
228 | 233 | ||
229 | return retval; | 234 | return retval; |
230 | } | 235 | } |
@@ -256,48 +261,31 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, | |||
256 | asoc->a_rwnd = asoc->rwnd; | 261 | asoc->a_rwnd = asoc->rwnd; |
257 | sack = sctp_make_sack(asoc); | 262 | sack = sctp_make_sack(asoc); |
258 | if (sack) { | 263 | if (sack) { |
259 | retval = sctp_packet_append_chunk(pkt, sack); | 264 | retval = __sctp_packet_append_chunk(pkt, sack); |
265 | if (retval != SCTP_XMIT_OK) { | ||
266 | sctp_chunk_free(sack); | ||
267 | goto out; | ||
268 | } | ||
260 | asoc->peer.sack_needed = 0; | 269 | asoc->peer.sack_needed = 0; |
261 | if (del_timer(timer)) | 270 | if (del_timer(timer)) |
262 | sctp_association_put(asoc); | 271 | sctp_association_put(asoc); |
263 | } | 272 | } |
264 | } | 273 | } |
265 | } | 274 | } |
275 | out: | ||
266 | return retval; | 276 | return retval; |
267 | } | 277 | } |
268 | 278 | ||
279 | |||
269 | /* Append a chunk to the offered packet reporting back any inability to do | 280 | /* Append a chunk to the offered packet reporting back any inability to do |
270 | * so. | 281 | * so. |
271 | */ | 282 | */ |
272 | sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, | 283 | static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet, |
273 | struct sctp_chunk *chunk) | 284 | struct sctp_chunk *chunk) |
274 | { | 285 | { |
275 | sctp_xmit_t retval = SCTP_XMIT_OK; | 286 | sctp_xmit_t retval = SCTP_XMIT_OK; |
276 | __u16 chunk_len = WORD_ROUND(ntohs(chunk->chunk_hdr->length)); | 287 | __u16 chunk_len = WORD_ROUND(ntohs(chunk->chunk_hdr->length)); |
277 | 288 | ||
278 | SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, packet, | ||
279 | chunk); | ||
280 | |||
281 | /* Data chunks are special. Before seeing what else we can | ||
282 | * bundle into this packet, check to see if we are allowed to | ||
283 | * send this DATA. | ||
284 | */ | ||
285 | if (sctp_chunk_is_data(chunk)) { | ||
286 | retval = sctp_packet_can_append_data(packet, chunk); | ||
287 | if (retval != SCTP_XMIT_OK) | ||
288 | goto finish; | ||
289 | } | ||
290 | |||
291 | /* Try to bundle AUTH chunk */ | ||
292 | retval = sctp_packet_bundle_auth(packet, chunk); | ||
293 | if (retval != SCTP_XMIT_OK) | ||
294 | goto finish; | ||
295 | |||
296 | /* Try to bundle SACK chunk */ | ||
297 | retval = sctp_packet_bundle_sack(packet, chunk); | ||
298 | if (retval != SCTP_XMIT_OK) | ||
299 | goto finish; | ||
300 | |||
301 | /* Check to see if this chunk will fit into the packet */ | 289 | /* Check to see if this chunk will fit into the packet */ |
302 | retval = sctp_packet_will_fit(packet, chunk, chunk_len); | 290 | retval = sctp_packet_will_fit(packet, chunk, chunk_len); |
303 | if (retval != SCTP_XMIT_OK) | 291 | if (retval != SCTP_XMIT_OK) |
@@ -339,6 +327,43 @@ finish: | |||
339 | return retval; | 327 | return retval; |
340 | } | 328 | } |
341 | 329 | ||
330 | /* Append a chunk to the offered packet reporting back any inability to do | ||
331 | * so. | ||
332 | */ | ||
333 | sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, | ||
334 | struct sctp_chunk *chunk) | ||
335 | { | ||
336 | sctp_xmit_t retval = SCTP_XMIT_OK; | ||
337 | |||
338 | SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, packet, | ||
339 | chunk); | ||
340 | |||
341 | /* Data chunks are special. Before seeing what else we can | ||
342 | * bundle into this packet, check to see if we are allowed to | ||
343 | * send this DATA. | ||
344 | */ | ||
345 | if (sctp_chunk_is_data(chunk)) { | ||
346 | retval = sctp_packet_can_append_data(packet, chunk); | ||
347 | if (retval != SCTP_XMIT_OK) | ||
348 | goto finish; | ||
349 | } | ||
350 | |||
351 | /* Try to bundle AUTH chunk */ | ||
352 | retval = sctp_packet_bundle_auth(packet, chunk); | ||
353 | if (retval != SCTP_XMIT_OK) | ||
354 | goto finish; | ||
355 | |||
356 | /* Try to bundle SACK chunk */ | ||
357 | retval = sctp_packet_bundle_sack(packet, chunk); | ||
358 | if (retval != SCTP_XMIT_OK) | ||
359 | goto finish; | ||
360 | |||
361 | retval = __sctp_packet_append_chunk(packet, chunk); | ||
362 | |||
363 | finish: | ||
364 | return retval; | ||
365 | } | ||
366 | |||
342 | /* All packets are sent to the network through this function from | 367 | /* All packets are sent to the network through this function from |
343 | * sctp_outq_tail(). | 368 | * sctp_outq_tail(). |
344 | * | 369 | * |
@@ -385,7 +410,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
385 | if (!sctp_transport_dst_check(tp)) { | 410 | if (!sctp_transport_dst_check(tp)) { |
386 | sctp_transport_route(tp, NULL, sctp_sk(sk)); | 411 | sctp_transport_route(tp, NULL, sctp_sk(sk)); |
387 | if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) { | 412 | if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) { |
388 | sctp_assoc_sync_pmtu(asoc); | 413 | sctp_assoc_sync_pmtu(sk, asoc); |
389 | } | 414 | } |
390 | } | 415 | } |
391 | dst = dst_clone(tp->dst); | 416 | dst = dst_clone(tp->dst); |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index a0fa19f5650c..e7aa177c9522 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -792,7 +792,8 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
792 | if (!new_transport) | 792 | if (!new_transport) |
793 | new_transport = asoc->peer.active_path; | 793 | new_transport = asoc->peer.active_path; |
794 | } else if ((new_transport->state == SCTP_INACTIVE) || | 794 | } else if ((new_transport->state == SCTP_INACTIVE) || |
795 | (new_transport->state == SCTP_UNCONFIRMED)) { | 795 | (new_transport->state == SCTP_UNCONFIRMED) || |
796 | (new_transport->state == SCTP_PF)) { | ||
796 | /* If the chunk is Heartbeat or Heartbeat Ack, | 797 | /* If the chunk is Heartbeat or Heartbeat Ack, |
797 | * send it to chunk->transport, even if it's | 798 | * send it to chunk->transport, even if it's |
798 | * inactive. | 799 | * inactive. |
@@ -987,7 +988,8 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
987 | new_transport = chunk->transport; | 988 | new_transport = chunk->transport; |
988 | if (!new_transport || | 989 | if (!new_transport || |
989 | ((new_transport->state == SCTP_INACTIVE) || | 990 | ((new_transport->state == SCTP_INACTIVE) || |
990 | (new_transport->state == SCTP_UNCONFIRMED))) | 991 | (new_transport->state == SCTP_UNCONFIRMED) || |
992 | (new_transport->state == SCTP_PF))) | ||
991 | new_transport = asoc->peer.active_path; | 993 | new_transport = asoc->peer.active_path; |
992 | if (new_transport->state == SCTP_UNCONFIRMED) | 994 | if (new_transport->state == SCTP_UNCONFIRMED) |
993 | continue; | 995 | continue; |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 9c90811d1134..1f89c4e69645 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -568,7 +568,7 @@ static void sctp_v4_get_saddr(struct sctp_sock *sk, | |||
568 | /* What interface did this skb arrive on? */ | 568 | /* What interface did this skb arrive on? */ |
569 | static int sctp_v4_skb_iif(const struct sk_buff *skb) | 569 | static int sctp_v4_skb_iif(const struct sk_buff *skb) |
570 | { | 570 | { |
571 | return skb_rtable(skb)->rt_iif; | 571 | return inet_iif(skb); |
572 | } | 572 | } |
573 | 573 | ||
574 | /* Was this packet marked by Explicit Congestion Notification? */ | 574 | /* Was this packet marked by Explicit Congestion Notification? */ |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b6de71efb140..479a70ef6ff8 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -132,7 +132,7 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, | |||
132 | * abort chunk. Differs from sctp_init_cause in that it won't oops | 132 | * abort chunk. Differs from sctp_init_cause in that it won't oops |
133 | * if there isn't enough space in the op error chunk | 133 | * if there isn't enough space in the op error chunk |
134 | */ | 134 | */ |
135 | int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, | 135 | static int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, |
136 | size_t paylen) | 136 | size_t paylen) |
137 | { | 137 | { |
138 | sctp_errhdr_t err; | 138 | sctp_errhdr_t err; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 8716da1a8592..fe99628e1257 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -76,6 +76,8 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, | |||
76 | sctp_cmd_seq_t *commands, | 76 | sctp_cmd_seq_t *commands, |
77 | gfp_t gfp); | 77 | gfp_t gfp); |
78 | 78 | ||
79 | static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds, | ||
80 | struct sctp_transport *t); | ||
79 | /******************************************************************** | 81 | /******************************************************************** |
80 | * Helper functions | 82 | * Helper functions |
81 | ********************************************************************/ | 83 | ********************************************************************/ |
@@ -470,7 +472,8 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = { | |||
470 | * notification SHOULD be sent to the upper layer. | 472 | * notification SHOULD be sent to the upper layer. |
471 | * | 473 | * |
472 | */ | 474 | */ |
473 | static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | 475 | static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, |
476 | struct sctp_association *asoc, | ||
474 | struct sctp_transport *transport, | 477 | struct sctp_transport *transport, |
475 | int is_hb) | 478 | int is_hb) |
476 | { | 479 | { |
@@ -495,6 +498,23 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
495 | transport->error_count++; | 498 | transport->error_count++; |
496 | } | 499 | } |
497 | 500 | ||
501 | /* If the transport error count is greater than the pf_retrans | ||
502 | * threshold, and less than pathmaxrtx, then mark this transport | ||
503 | * as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1, | ||
504 | * point 1 | ||
505 | */ | ||
506 | if ((transport->state != SCTP_PF) && | ||
507 | (asoc->pf_retrans < transport->pathmaxrxt) && | ||
508 | (transport->error_count > asoc->pf_retrans)) { | ||
509 | |||
510 | sctp_assoc_control_transport(asoc, transport, | ||
511 | SCTP_TRANSPORT_PF, | ||
512 | 0); | ||
513 | |||
514 | /* Update the hb timer to resend a heartbeat every rto */ | ||
515 | sctp_cmd_hb_timer_update(commands, transport); | ||
516 | } | ||
517 | |||
498 | if (transport->state != SCTP_INACTIVE && | 518 | if (transport->state != SCTP_INACTIVE && |
499 | (transport->error_count > transport->pathmaxrxt)) { | 519 | (transport->error_count > transport->pathmaxrxt)) { |
500 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", | 520 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", |
@@ -699,6 +719,10 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
699 | SCTP_HEARTBEAT_SUCCESS); | 719 | SCTP_HEARTBEAT_SUCCESS); |
700 | } | 720 | } |
701 | 721 | ||
722 | if (t->state == SCTP_PF) | ||
723 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | ||
724 | SCTP_HEARTBEAT_SUCCESS); | ||
725 | |||
702 | /* The receiver of the HEARTBEAT ACK should also perform an | 726 | /* The receiver of the HEARTBEAT ACK should also perform an |
703 | * RTT measurement for that destination transport address | 727 | * RTT measurement for that destination transport address |
704 | * using the time value carried in the HEARTBEAT ACK chunk. | 728 | * using the time value carried in the HEARTBEAT ACK chunk. |
@@ -1565,8 +1589,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1565 | 1589 | ||
1566 | case SCTP_CMD_STRIKE: | 1590 | case SCTP_CMD_STRIKE: |
1567 | /* Mark one strike against a transport. */ | 1591 | /* Mark one strike against a transport. */ |
1568 | sctp_do_8_2_transport_strike(asoc, cmd->obj.transport, | 1592 | sctp_do_8_2_transport_strike(commands, asoc, |
1569 | 0); | 1593 | cmd->obj.transport, 0); |
1570 | break; | 1594 | break; |
1571 | 1595 | ||
1572 | case SCTP_CMD_TRANSPORT_IDLE: | 1596 | case SCTP_CMD_TRANSPORT_IDLE: |
@@ -1576,7 +1600,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1576 | 1600 | ||
1577 | case SCTP_CMD_TRANSPORT_HB_SENT: | 1601 | case SCTP_CMD_TRANSPORT_HB_SENT: |
1578 | t = cmd->obj.transport; | 1602 | t = cmd->obj.transport; |
1579 | sctp_do_8_2_transport_strike(asoc, t, 1); | 1603 | sctp_do_8_2_transport_strike(commands, asoc, |
1604 | t, 1); | ||
1580 | t->hb_sent = 1; | 1605 | t->hb_sent = 1; |
1581 | break; | 1606 | break; |
1582 | 1607 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 31c7bfcd9b58..5e259817a7f3 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1859,7 +1859,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1859 | } | 1859 | } |
1860 | 1860 | ||
1861 | if (asoc->pmtu_pending) | 1861 | if (asoc->pmtu_pending) |
1862 | sctp_assoc_pending_pmtu(asoc); | 1862 | sctp_assoc_pending_pmtu(sk, asoc); |
1863 | 1863 | ||
1864 | /* If fragmentation is disabled and the message length exceeds the | 1864 | /* If fragmentation is disabled and the message length exceeds the |
1865 | * association fragmentation point, return EMSGSIZE. The I-D | 1865 | * association fragmentation point, return EMSGSIZE. The I-D |
@@ -2373,7 +2373,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2373 | if ((params->spp_flags & SPP_PMTUD_DISABLE) && params->spp_pathmtu) { | 2373 | if ((params->spp_flags & SPP_PMTUD_DISABLE) && params->spp_pathmtu) { |
2374 | if (trans) { | 2374 | if (trans) { |
2375 | trans->pathmtu = params->spp_pathmtu; | 2375 | trans->pathmtu = params->spp_pathmtu; |
2376 | sctp_assoc_sync_pmtu(asoc); | 2376 | sctp_assoc_sync_pmtu(sctp_opt2sk(sp), asoc); |
2377 | } else if (asoc) { | 2377 | } else if (asoc) { |
2378 | asoc->pathmtu = params->spp_pathmtu; | 2378 | asoc->pathmtu = params->spp_pathmtu; |
2379 | sctp_frag_point(asoc, params->spp_pathmtu); | 2379 | sctp_frag_point(asoc, params->spp_pathmtu); |
@@ -2390,7 +2390,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2390 | (trans->param_flags & ~SPP_PMTUD) | pmtud_change; | 2390 | (trans->param_flags & ~SPP_PMTUD) | pmtud_change; |
2391 | if (update) { | 2391 | if (update) { |
2392 | sctp_transport_pmtu(trans, sctp_opt2sk(sp)); | 2392 | sctp_transport_pmtu(trans, sctp_opt2sk(sp)); |
2393 | sctp_assoc_sync_pmtu(asoc); | 2393 | sctp_assoc_sync_pmtu(sctp_opt2sk(sp), asoc); |
2394 | } | 2394 | } |
2395 | } else if (asoc) { | 2395 | } else if (asoc) { |
2396 | asoc->param_flags = | 2396 | asoc->param_flags = |
@@ -3478,6 +3478,56 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, | |||
3478 | } | 3478 | } |
3479 | 3479 | ||
3480 | 3480 | ||
3481 | /* | ||
3482 | * SCTP_PEER_ADDR_THLDS | ||
3483 | * | ||
3484 | * This option allows us to alter the partially failed threshold for one or all | ||
3485 | * transports in an association. See Section 6.1 of: | ||
3486 | * http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt | ||
3487 | */ | ||
3488 | static int sctp_setsockopt_paddr_thresholds(struct sock *sk, | ||
3489 | char __user *optval, | ||
3490 | unsigned int optlen) | ||
3491 | { | ||
3492 | struct sctp_paddrthlds val; | ||
3493 | struct sctp_transport *trans; | ||
3494 | struct sctp_association *asoc; | ||
3495 | |||
3496 | if (optlen < sizeof(struct sctp_paddrthlds)) | ||
3497 | return -EINVAL; | ||
3498 | if (copy_from_user(&val, (struct sctp_paddrthlds __user *)optval, | ||
3499 | sizeof(struct sctp_paddrthlds))) | ||
3500 | return -EFAULT; | ||
3501 | |||
3502 | |||
3503 | if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) { | ||
3504 | asoc = sctp_id2assoc(sk, val.spt_assoc_id); | ||
3505 | if (!asoc) | ||
3506 | return -ENOENT; | ||
3507 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, | ||
3508 | transports) { | ||
3509 | if (val.spt_pathmaxrxt) | ||
3510 | trans->pathmaxrxt = val.spt_pathmaxrxt; | ||
3511 | trans->pf_retrans = val.spt_pathpfthld; | ||
3512 | } | ||
3513 | |||
3514 | if (val.spt_pathmaxrxt) | ||
3515 | asoc->pathmaxrxt = val.spt_pathmaxrxt; | ||
3516 | asoc->pf_retrans = val.spt_pathpfthld; | ||
3517 | } else { | ||
3518 | trans = sctp_addr_id2transport(sk, &val.spt_address, | ||
3519 | val.spt_assoc_id); | ||
3520 | if (!trans) | ||
3521 | return -ENOENT; | ||
3522 | |||
3523 | if (val.spt_pathmaxrxt) | ||
3524 | trans->pathmaxrxt = val.spt_pathmaxrxt; | ||
3525 | trans->pf_retrans = val.spt_pathpfthld; | ||
3526 | } | ||
3527 | |||
3528 | return 0; | ||
3529 | } | ||
3530 | |||
3481 | /* API 6.2 setsockopt(), getsockopt() | 3531 | /* API 6.2 setsockopt(), getsockopt() |
3482 | * | 3532 | * |
3483 | * Applications use setsockopt() and getsockopt() to set or retrieve | 3533 | * Applications use setsockopt() and getsockopt() to set or retrieve |
@@ -3627,6 +3677,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3627 | case SCTP_AUTO_ASCONF: | 3677 | case SCTP_AUTO_ASCONF: |
3628 | retval = sctp_setsockopt_auto_asconf(sk, optval, optlen); | 3678 | retval = sctp_setsockopt_auto_asconf(sk, optval, optlen); |
3629 | break; | 3679 | break; |
3680 | case SCTP_PEER_ADDR_THLDS: | ||
3681 | retval = sctp_setsockopt_paddr_thresholds(sk, optval, optlen); | ||
3682 | break; | ||
3630 | default: | 3683 | default: |
3631 | retval = -ENOPROTOOPT; | 3684 | retval = -ENOPROTOOPT; |
3632 | break; | 3685 | break; |
@@ -5498,6 +5551,51 @@ static int sctp_getsockopt_assoc_ids(struct sock *sk, int len, | |||
5498 | return 0; | 5551 | return 0; |
5499 | } | 5552 | } |
5500 | 5553 | ||
5554 | /* | ||
5555 | * SCTP_PEER_ADDR_THLDS | ||
5556 | * | ||
5557 | * This option allows us to fetch the partially failed threshold for one or all | ||
5558 | * transports in an association. See Section 6.1 of: | ||
5559 | * http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt | ||
5560 | */ | ||
5561 | static int sctp_getsockopt_paddr_thresholds(struct sock *sk, | ||
5562 | char __user *optval, | ||
5563 | int len, | ||
5564 | int __user *optlen) | ||
5565 | { | ||
5566 | struct sctp_paddrthlds val; | ||
5567 | struct sctp_transport *trans; | ||
5568 | struct sctp_association *asoc; | ||
5569 | |||
5570 | if (len < sizeof(struct sctp_paddrthlds)) | ||
5571 | return -EINVAL; | ||
5572 | len = sizeof(struct sctp_paddrthlds); | ||
5573 | if (copy_from_user(&val, (struct sctp_paddrthlds __user *)optval, len)) | ||
5574 | return -EFAULT; | ||
5575 | |||
5576 | if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) { | ||
5577 | asoc = sctp_id2assoc(sk, val.spt_assoc_id); | ||
5578 | if (!asoc) | ||
5579 | return -ENOENT; | ||
5580 | |||
5581 | val.spt_pathpfthld = asoc->pf_retrans; | ||
5582 | val.spt_pathmaxrxt = asoc->pathmaxrxt; | ||
5583 | } else { | ||
5584 | trans = sctp_addr_id2transport(sk, &val.spt_address, | ||
5585 | val.spt_assoc_id); | ||
5586 | if (!trans) | ||
5587 | return -ENOENT; | ||
5588 | |||
5589 | val.spt_pathmaxrxt = trans->pathmaxrxt; | ||
5590 | val.spt_pathpfthld = trans->pf_retrans; | ||
5591 | } | ||
5592 | |||
5593 | if (put_user(len, optlen) || copy_to_user(optval, &val, len)) | ||
5594 | return -EFAULT; | ||
5595 | |||
5596 | return 0; | ||
5597 | } | ||
5598 | |||
5501 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5599 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
5502 | char __user *optval, int __user *optlen) | 5600 | char __user *optval, int __user *optlen) |
5503 | { | 5601 | { |
@@ -5636,6 +5734,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5636 | case SCTP_AUTO_ASCONF: | 5734 | case SCTP_AUTO_ASCONF: |
5637 | retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen); | 5735 | retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen); |
5638 | break; | 5736 | break; |
5737 | case SCTP_PEER_ADDR_THLDS: | ||
5738 | retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen); | ||
5739 | break; | ||
5639 | default: | 5740 | default: |
5640 | retval = -ENOPROTOOPT; | 5741 | retval = -ENOPROTOOPT; |
5641 | break; | 5742 | break; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index e5fe639c89e7..2b2bfe933ff1 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -141,6 +141,15 @@ static ctl_table sctp_table[] = { | |||
141 | .extra2 = &int_max | 141 | .extra2 = &int_max |
142 | }, | 142 | }, |
143 | { | 143 | { |
144 | .procname = "pf_retrans", | ||
145 | .data = &sctp_pf_retrans, | ||
146 | .maxlen = sizeof(int), | ||
147 | .mode = 0644, | ||
148 | .proc_handler = proc_dointvec_minmax, | ||
149 | .extra1 = &zero, | ||
150 | .extra2 = &int_max | ||
151 | }, | ||
152 | { | ||
144 | .procname = "max_init_retransmits", | 153 | .procname = "max_init_retransmits", |
145 | .data = &sctp_max_retrans_init, | 154 | .data = &sctp_max_retrans_init, |
146 | .maxlen = sizeof(int), | 155 | .maxlen = sizeof(int), |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 1dcceb6e0ce6..c97472b248a2 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -87,6 +87,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
87 | 87 | ||
88 | /* Initialize the default path max_retrans. */ | 88 | /* Initialize the default path max_retrans. */ |
89 | peer->pathmaxrxt = sctp_max_retrans_path; | 89 | peer->pathmaxrxt = sctp_max_retrans_path; |
90 | peer->pf_retrans = sctp_pf_retrans; | ||
90 | 91 | ||
91 | INIT_LIST_HEAD(&peer->transmitted); | 92 | INIT_LIST_HEAD(&peer->transmitted); |
92 | INIT_LIST_HEAD(&peer->send_ready); | 93 | INIT_LIST_HEAD(&peer->send_ready); |
@@ -216,7 +217,7 @@ void sctp_transport_set_owner(struct sctp_transport *transport, | |||
216 | void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) | 217 | void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) |
217 | { | 218 | { |
218 | /* If we don't have a fresh route, look one up */ | 219 | /* If we don't have a fresh route, look one up */ |
219 | if (!transport->dst || transport->dst->obsolete > 1) { | 220 | if (!transport->dst || transport->dst->obsolete) { |
220 | dst_release(transport->dst); | 221 | dst_release(transport->dst); |
221 | transport->af_specific->get_dst(transport, &transport->saddr, | 222 | transport->af_specific->get_dst(transport, &transport->saddr, |
222 | &transport->fl, sk); | 223 | &transport->fl, sk); |
@@ -228,7 +229,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) | |||
228 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; | 229 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; |
229 | } | 230 | } |
230 | 231 | ||
231 | void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) | 232 | void sctp_transport_update_pmtu(struct sock *sk, struct sctp_transport *t, u32 pmtu) |
232 | { | 233 | { |
233 | struct dst_entry *dst; | 234 | struct dst_entry *dst; |
234 | 235 | ||
@@ -245,8 +246,16 @@ void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) | |||
245 | } | 246 | } |
246 | 247 | ||
247 | dst = sctp_transport_dst_check(t); | 248 | dst = sctp_transport_dst_check(t); |
248 | if (dst) | 249 | if (!dst) |
249 | dst->ops->update_pmtu(dst, pmtu); | 250 | t->af_specific->get_dst(t, &t->saddr, &t->fl, sk); |
251 | |||
252 | if (dst) { | ||
253 | dst->ops->update_pmtu(dst, sk, NULL, pmtu); | ||
254 | |||
255 | dst = sctp_transport_dst_check(t); | ||
256 | if (!dst) | ||
257 | t->af_specific->get_dst(t, &t->saddr, &t->fl, sk); | ||
258 | } | ||
250 | } | 259 | } |
251 | 260 | ||
252 | /* Caches the dst entry and source address for a transport's destination | 261 | /* Caches the dst entry and source address for a transport's destination |
@@ -587,7 +596,8 @@ unsigned long sctp_transport_timeout(struct sctp_transport *t) | |||
587 | { | 596 | { |
588 | unsigned long timeout; | 597 | unsigned long timeout; |
589 | timeout = t->rto + sctp_jitter(t->rto); | 598 | timeout = t->rto + sctp_jitter(t->rto); |
590 | if (t->state != SCTP_UNCONFIRMED) | 599 | if ((t->state != SCTP_UNCONFIRMED) && |
600 | (t->state != SCTP_PF)) | ||
591 | timeout += t->hbinterval; | 601 | timeout += t->hbinterval; |
592 | timeout += jiffies; | 602 | timeout += jiffies; |
593 | return timeout; | 603 | return timeout; |