Commit ad8fec1720e000ba2384de6408076a60fc92a981

Authored by Sridhar Samudrala
Committed by David S. Miller
1 parent cfdeef3282

[SCTP]: Verify all the paths to a peer via heartbeat before using them.

This patch implements Path Initialization procedure as described in
Sec 2.36 of RFC4460.

Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 8 changed files with 60 additions and 19 deletions Side-by-side Diff

include/net/sctp/structs.h
... ... @@ -445,6 +445,7 @@
445 445 struct sctp_paramhdr param_hdr;
446 446 union sctp_addr daddr;
447 447 unsigned long sent_at;
  448 + __u64 hb_nonce;
448 449 } __attribute__((packed)) sctp_sender_hb_info_t;
449 450  
450 451 /*
... ... @@ -984,6 +985,9 @@
984 985 */
985 986 char cacc_saw_newack;
986 987 } cacc;
  988 +
  989 + /* 64-bit random number sent with heartbeat. */
  990 + __u64 hb_nonce;
987 991 };
988 992  
989 993 struct sctp_transport *sctp_transport_new(const union sctp_addr *,
include/net/sctp/user.h
... ... @@ -560,9 +560,18 @@
560 560 } __attribute__((packed, aligned(4)));
561 561  
562 562 /* Peer addresses's state. */
  563 +/* UNKNOWN: Peer address passed by the upper layer in sendmsg or connect[x]
  564 + * calls.
  565 + * UNCONFIRMED: Peer address received in INIT/INIT-ACK address parameters.
  566 + * Not yet confirmed by a heartbeat and not available for data
  567 + * transfers.
  568 + * ACTIVE : Peer address confirmed, active and available for data transfers.
  569 + * INACTIVE: Peer address inactive and not available for data transfers.
  570 + */
563 571 enum sctp_spinfo_state {
564 572 SCTP_INACTIVE,
565 573 SCTP_ACTIVE,
  574 + SCTP_UNCONFIRMED,
566 575 SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */
567 576 };
568 577  
net/sctp/associola.c
... ... @@ -441,7 +441,8 @@
441 441 /* If the primary path is changing, assume that the
442 442 * user wants to use this new path.
443 443 */
444   - if (transport->state != SCTP_INACTIVE)
  444 + if ((transport->state == SCTP_ACTIVE) ||
  445 + (transport->state == SCTP_UNKNOWN))
445 446 asoc->peer.active_path = transport;
446 447  
447 448 /*
448 449  
... ... @@ -532,11 +533,11 @@
532 533 port = addr->v4.sin_port;
533 534  
534 535 SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
535   - " port: %d state:%s\n",
  536 + " port: %d state:%d\n",
536 537 asoc,
537 538 addr,
538 539 addr->v4.sin_port,
539   - peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
  540 + peer_state);
540 541  
541 542 /* Set the port if it has not been set yet. */
542 543 if (0 == asoc->peer.port)
... ... @@ -545,9 +546,12 @@
545 546 /* Check to see if this is a duplicate. */
546 547 peer = sctp_assoc_lookup_paddr(asoc, addr);
547 548 if (peer) {
548   - if (peer_state == SCTP_ACTIVE &&
549   - peer->state == SCTP_UNKNOWN)
550   - peer->state = SCTP_ACTIVE;
  549 + if (peer->state == SCTP_UNKNOWN) {
  550 + if (peer_state == SCTP_ACTIVE)
  551 + peer->state = SCTP_ACTIVE;
  552 + if (peer_state == SCTP_UNCONFIRMED)
  553 + peer->state = SCTP_UNCONFIRMED;
  554 + }
551 555 return peer;
552 556 }
553 557  
... ... @@ -739,7 +743,8 @@
739 743 list_for_each(pos, &asoc->peer.transport_addr_list) {
740 744 t = list_entry(pos, struct sctp_transport, transports);
741 745  
742   - if (t->state == SCTP_INACTIVE)
  746 + if ((t->state == SCTP_INACTIVE) ||
  747 + (t->state == SCTP_UNCONFIRMED))
743 748 continue;
744 749 if (!first || t->last_time_heard > first->last_time_heard) {
745 750 second = first;
... ... @@ -759,7 +764,8 @@
759 764 * [If the primary is active but not most recent, bump the most
760 765 * recently used transport.]
761 766 */
762   - if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
  767 + if (((asoc->peer.primary_path->state == SCTP_ACTIVE) ||
  768 + (asoc->peer.primary_path->state == SCTP_UNKNOWN)) &&
763 769 first != asoc->peer.primary_path) {
764 770 second = first;
765 771 first = asoc->peer.primary_path;
... ... @@ -1054,7 +1060,7 @@
1054 1060 transports);
1055 1061 if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
1056 1062 sctp_assoc_add_peer(asoc, &trans->ipaddr,
1057   - GFP_ATOMIC, SCTP_ACTIVE);
  1063 + GFP_ATOMIC, trans->state);
1058 1064 }
1059 1065  
1060 1066 asoc->ctsn_ack_point = asoc->next_tsn - 1;
... ... @@ -1094,7 +1100,8 @@
1094 1100  
1095 1101 /* Try to find an active transport. */
1096 1102  
1097   - if (t->state != SCTP_INACTIVE) {
  1103 + if ((t->state == SCTP_ACTIVE) ||
  1104 + (t->state == SCTP_UNKNOWN)) {
1098 1105 break;
1099 1106 } else {
1100 1107 /* Keep track of the next transport in case
... ... @@ -691,7 +691,8 @@
691 691  
692 692 if (!new_transport) {
693 693 new_transport = asoc->peer.active_path;
694   - } else if (new_transport->state == SCTP_INACTIVE) {
  694 + } else if ((new_transport->state == SCTP_INACTIVE) ||
  695 + (new_transport->state == SCTP_UNCONFIRMED)) {
695 696 /* If the chunk is Heartbeat or Heartbeat Ack,
696 697 * send it to chunk->transport, even if it's
697 698 * inactive.
... ... @@ -848,7 +849,8 @@
848 849 */
849 850 new_transport = chunk->transport;
850 851 if (!new_transport ||
851   - new_transport->state == SCTP_INACTIVE)
  852 + ((new_transport->state == SCTP_INACTIVE) ||
  853 + (new_transport->state == SCTP_UNCONFIRMED)))
852 854 new_transport = asoc->peer.active_path;
853 855  
854 856 /* Change packets if necessary. */
... ... @@ -1464,7 +1466,8 @@
1464 1466 /* Mark the destination transport address as
1465 1467 * active if it is not so marked.
1466 1468 */
1467   - if (transport->state == SCTP_INACTIVE) {
  1469 + if ((transport->state == SCTP_INACTIVE) ||
  1470 + (transport->state == SCTP_UNCONFIRMED)) {
1468 1471 sctp_assoc_control_transport(
1469 1472 transport->asoc,
1470 1473 transport,
net/sctp/sm_make_chunk.c
... ... @@ -2017,7 +2017,7 @@
2017 2017 af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
2018 2018 scope = sctp_scope(peer_addr);
2019 2019 if (sctp_in_scope(&addr, scope))
2020   - if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
  2020 + if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
2021 2021 return 0;
2022 2022 break;
2023 2023  
... ... @@ -2418,7 +2418,7 @@
2418 2418 * Due to Resource Shortage'.
2419 2419 */
2420 2420  
2421   - peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE);
  2421 + peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
2422 2422 if (!peer)
2423 2423 return SCTP_ERROR_RSRC_LOW;
2424 2424  
net/sctp/sm_sideeffect.c
... ... @@ -430,7 +430,11 @@
430 430 /* The check for association's overall error counter exceeding the
431 431 * threshold is done in the state function.
432 432 */
433   - asoc->overall_error_count++;
  433 + /* When probing UNCONFIRMED addresses, the association overall
  434 + * error count is NOT incremented
  435 + */
  436 + if (transport->state != SCTP_UNCONFIRMED)
  437 + asoc->overall_error_count++;
434 438  
435 439 if (transport->state != SCTP_INACTIVE &&
436 440 (transport->error_count++ >= transport->pathmaxrxt)) {
... ... @@ -610,7 +614,7 @@
610 614 /* Mark the destination transport address as active if it is not so
611 615 * marked.
612 616 */
613   - if (t->state == SCTP_INACTIVE)
  617 + if ((t->state == SCTP_INACTIVE) || (t->state == SCTP_UNCONFIRMED))
614 618 sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
615 619 SCTP_HEARTBEAT_SUCCESS);
616 620  
... ... @@ -620,6 +624,10 @@
620 624 */
621 625 hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
622 626 sctp_transport_update_rto(t, (jiffies - hbinfo->sent_at));
  627 +
  628 + /* Update the heartbeat timer. */
  629 + if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t)))
  630 + sctp_transport_hold(t);
623 631 }
624 632  
625 633 /* Helper function to do a transport reset at the expiry of the hearbeat
net/sctp/sm_statefuns.c
... ... @@ -846,6 +846,7 @@
846 846 hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t));
847 847 hbinfo.daddr = transport->ipaddr;
848 848 hbinfo.sent_at = jiffies;
  849 + hbinfo.hb_nonce = transport->hb_nonce;
849 850  
850 851 /* Send a heartbeat to our peer. */
851 852 paylen = sizeof(sctp_sender_hb_info_t);
... ... @@ -1047,6 +1048,10 @@
1047 1048 }
1048 1049 return SCTP_DISPOSITION_DISCARD;
1049 1050 }
  1051 +
  1052 + /* Validate the 64-bit random nonce. */
  1053 + if (hbinfo->hb_nonce != link->hb_nonce)
  1054 + return SCTP_DISPOSITION_DISCARD;
1050 1055  
1051 1056 max_interval = link->hbinterval + link->rto;
1052 1057  
net/sctp/transport.c
... ... @@ -49,6 +49,7 @@
49 49 */
50 50  
51 51 #include <linux/types.h>
  52 +#include <linux/random.h>
52 53 #include <net/sctp/sctp.h>
53 54 #include <net/sctp/sm.h>
54 55  
... ... @@ -85,7 +86,6 @@
85 86  
86 87 peer->init_sent_count = 0;
87 88  
88   - peer->state = SCTP_ACTIVE;
89 89 peer->param_flags = SPP_HB_DISABLE |
90 90 SPP_PMTUD_ENABLE |
91 91 SPP_SACKDELAY_ENABLE;
... ... @@ -109,6 +109,9 @@
109 109 peer->hb_timer.function = sctp_generate_heartbeat_event;
110 110 peer->hb_timer.data = (unsigned long)peer;
111 111  
  112 + /* Initialize the 64-bit random nonce sent with heartbeat. */
  113 + get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
  114 +
112 115 atomic_set(&peer->refcnt, 1);
113 116 peer->dead = 0;
114 117  
... ... @@ -517,7 +520,9 @@
517 520 unsigned long sctp_transport_timeout(struct sctp_transport *t)
518 521 {
519 522 unsigned long timeout;
520   - timeout = t->hbinterval + t->rto + sctp_jitter(t->rto);
  523 + timeout = t->rto + sctp_jitter(t->rto);
  524 + if (t->state != SCTP_UNCONFIRMED)
  525 + timeout += t->hbinterval;
521 526 timeout += jiffies;
522 527 return timeout;
523 528 }