aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 13:01:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 13:01:50 -0400
commit3c4cfadef6a1665d9cd02a543782d03d3e6740c6 (patch)
tree3df72faaacd494d5ac8c9668df4f529b1b5e4457 /net/sctp
parente017507f37d5cb8b541df165a824958bc333bec3 (diff)
parent320f5ea0cedc08ef65d67e056bcb9d181386ef2c (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.c41
-rw-r--r--net/sctp/input.c20
-rw-r--r--net/sctp/ipv6.c3
-rw-r--r--net/sctp/output.c81
-rw-r--r--net/sctp/outqueue.c6
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/sctp/sm_make_chunk.c2
-rw-r--r--net/sctp/sm_sideeffect.c33
-rw-r--r--net/sctp/socket.c107
-rw-r--r--net/sctp/sysctl.c9
-rw-r--r--net/sctp/transport.c20
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 */
1363void sctp_assoc_sync_pmtu(struct sctp_association *asoc) 1386void 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
426void 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. */
67static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet,
68 struct sctp_chunk *chunk);
67static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, 69static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
68 struct sctp_chunk *chunk); 70 struct sctp_chunk *chunk);
69static void sctp_packet_append_data(struct sctp_packet *packet, 71static 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 }
275out:
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 */
272sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, 283static 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 */
333sctp_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
363finish:
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? */
569static int sctp_v4_skb_iif(const struct sk_buff *skb) 569static 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 */
135int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, 135static 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
79static 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 */
473static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, 475static 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 */
3488static 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 */
5561static 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
5501SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, 5599SCTP_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,
216void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) 217void 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
231void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) 232void 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;