Commit d12d2e12cec2d66eab6cd58f592dad9fd386b97d

Authored by Jon Maloy
Committed by David S. Miller
1 parent c2b22bcf2e

tipc: send out join messages as soon as new member is discovered

When a socket is joining a group, we look up in the binding table to
find if there are already other members of the group present. This is
used for being able to return EAGAIN instead of EHOSTUNREACH if the
user proceeds directly to a send attempt.

However, the information in the binding table can be used to directly
set the created member in state MBR_PUBLISHED and send a JOIN message
to the peer, instead of waiting for a topology PUBLISH event to do this.
When there are many members in a group, the propagation time for such
events can be significant, and we can save time during the join
operation if we use the initial lookup result fully.

In this commit, we eliminate the member state MBR_DISCOVERED which has
been the result of the initial lookup, and do instead go directly to
MBR_PUBLISHED, which initiates the setup.

After this change, the tipc_member FSM looks as follows:

     +-----------+
---->| PUBLISHED |-----------------------------------------------+
PUB- +-----------+                                 LEAVE/WITHRAW |
LISH       |JOIN                                                 |
           |     +-------------------------------------------+   |
           |     |                            LEAVE/WITHDRAW |   |
           |     |                +------------+             |   |
           |     |   +----------->|  PENDING   |---------+   |   |
           |     |   |msg/maxactv +-+---+------+  LEAVE/ |   |   |
           |     |   |              |   |       WITHDRAW |   |   |
           |     |   |   +----------+   |                |   |   |
           |     |   |   |revert/maxactv|                |   |   |
           |     |   |   V              V                V   V   V
           |   +----------+  msg  +------------+       +-----------+
           +-->|  JOINED  |------>|   ACTIVE   |------>|  LEAVING  |--->
           |   +----------+       +--- -+------+ LEAVE/+-----------+DOWN
           |        A   A               |      WITHDRAW A   A    A   EVT
           |        |   |               |RECLAIM        |   |    |
           |        |   |REMIT          V               |   |    |
           |        |   |== adv   +------------+        |   |    |
           |        |   +---------| RECLAIMING |--------+   |    |
           |        |             +-----+------+  LEAVE/    |    |
           |        |                   |REMIT   WITHDRAW   |    |
           |        |                   |< adv              |    |
           |        |msg/               V            LEAVE/ |    |
           |        |adv==ADV_IDLE+------------+   WITHDRAW |    |
           |        +-------------|  REMITTED  |------------+    |
           |                      +------------+                 |
           |PUBLISH                                              |
JOIN +-----------+                                LEAVE/WITHDRAW |
---->|  JOINING  |-----------------------------------------------+
     +-----------+

Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 4 changed files with 68 additions and 42 deletions Side-by-side Diff

... ... @@ -49,7 +49,6 @@
49 49 #define ADV_ACTIVE (ADV_UNIT * 12)
50 50  
51 51 enum mbr_state {
52   - MBR_DISCOVERED,
53 52 MBR_JOINING,
54 53 MBR_PUBLISHED,
55 54 MBR_JOINED,
... ... @@ -141,7 +140,7 @@
141 140  
142 141 static bool tipc_group_is_sender(struct tipc_member *m)
143 142 {
144   - return m && m->state >= MBR_JOINED;
  143 + return m && m->state != MBR_JOINING && m->state != MBR_PUBLISHED;
145 144 }
146 145  
147 146 u32 tipc_group_exclude(struct tipc_group *grp)
... ... @@ -184,6 +183,21 @@
184 183 return NULL;
185 184 }
186 185  
  186 +void tipc_group_join(struct net *net, struct tipc_group *grp, int *sk_rcvbuf)
  187 +{
  188 + struct rb_root *tree = &grp->members;
  189 + struct tipc_member *m, *tmp;
  190 + struct sk_buff_head xmitq;
  191 +
  192 + skb_queue_head_init(&xmitq);
  193 + rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
  194 + tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, &xmitq);
  195 + tipc_group_update_member(m, 0);
  196 + }
  197 + tipc_node_distr_xmit(net, &xmitq);
  198 + *sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
  199 +}
  200 +
187 201 void tipc_group_delete(struct net *net, struct tipc_group *grp)
188 202 {
189 203 struct rb_root *tree = &grp->members;
... ... @@ -274,7 +288,7 @@
274 288  
275 289 static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
276 290 u32 node, u32 port,
277   - int state)
  291 + u32 instance, int state)
278 292 {
279 293 struct tipc_member *m;
280 294  
... ... @@ -287,6 +301,7 @@
287 301 m->group = grp;
288 302 m->node = node;
289 303 m->port = port;
  304 + m->instance = instance;
290 305 m->bc_acked = grp->bc_snd_nxt - 1;
291 306 grp->member_cnt++;
292 307 tipc_group_add_to_tree(grp, m);
293 308  
... ... @@ -295,9 +310,10 @@
295 310 return m;
296 311 }
297 312  
298   -void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port)
  313 +void tipc_group_add_member(struct tipc_group *grp, u32 node,
  314 + u32 port, u32 instance)
299 315 {
300   - tipc_group_create_member(grp, node, port, MBR_DISCOVERED);
  316 + tipc_group_create_member(grp, node, port, instance, MBR_PUBLISHED);
301 317 }
302 318  
303 319 static void tipc_group_delete_member(struct tipc_group *grp,
... ... @@ -623,7 +639,6 @@
623 639 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
624 640 break;
625 641 case MBR_RECLAIMING:
626   - case MBR_DISCOVERED:
627 642 case MBR_JOINING:
628 643 case MBR_LEAVING:
629 644 default:
630 645  
631 646  
... ... @@ -721,26 +736,26 @@
721 736 case GRP_JOIN_MSG:
722 737 if (!m)
723 738 m = tipc_group_create_member(grp, node, port,
724   - MBR_JOINING);
  739 + 0, MBR_JOINING);
725 740 if (!m)
726 741 return;
727 742 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
728 743 m->bc_rcv_nxt = m->bc_syncpt;
729 744 m->window += msg_adv_win(hdr);
730 745  
731   - /* Wait until PUBLISH event is received */
732   - if (m->state == MBR_DISCOVERED) {
733   - m->state = MBR_JOINING;
734   - } else if (m->state == MBR_PUBLISHED) {
735   - m->state = MBR_JOINED;
736   - *usr_wakeup = true;
737   - m->usr_pending = false;
738   - tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
739   - tipc_group_create_event(grp, m, TIPC_PUBLISHED,
740   - m->bc_syncpt, inputq);
741   - }
  746 + /* Wait until PUBLISH event is received if necessary */
  747 + if (m->state != MBR_PUBLISHED)
  748 + return;
  749 +
  750 + /* Member can be taken into service */
  751 + m->state = MBR_JOINED;
  752 + *usr_wakeup = true;
  753 + m->usr_pending = false;
742 754 list_del_init(&m->small_win);
743 755 tipc_group_update_member(m, 0);
  756 + tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
  757 + tipc_group_create_event(grp, m, TIPC_PUBLISHED,
  758 + m->bc_syncpt, inputq);
744 759 return;
745 760 case GRP_LEAVE_MSG:
746 761 if (!m)
747 762  
748 763  
749 764  
750 765  
... ... @@ -844,30 +859,36 @@
844 859  
845 860 m = tipc_group_find_member(grp, node, port);
846 861  
847   - if (event == TIPC_PUBLISHED) {
848   - if (!m)
849   - m = tipc_group_create_member(grp, node, port,
850   - MBR_DISCOVERED);
851   - if (!m)
852   - return;
  862 + switch (event) {
  863 + case TIPC_PUBLISHED:
  864 + /* Send and wait for arrival of JOIN message if necessary */
  865 + if (!m) {
  866 + m = tipc_group_create_member(grp, node, port, instance,
  867 + MBR_PUBLISHED);
  868 + if (!m)
  869 + break;
  870 + tipc_group_update_member(m, 0);
  871 + tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
  872 + break;
  873 + }
853 874  
854   - m->instance = instance;
  875 + if (m->state != MBR_JOINING)
  876 + break;
855 877  
856   - /* Hold back event if JOIN message not yet received */
857   - if (m->state == MBR_DISCOVERED) {
858   - m->state = MBR_PUBLISHED;
859   - } else {
860   - tipc_group_create_event(grp, m, TIPC_PUBLISHED,
861   - m->bc_syncpt, inputq);
862   - m->state = MBR_JOINED;
863   - *usr_wakeup = true;
864   - m->usr_pending = false;
865   - }
866   - tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
  878 + /* Member can be taken into service */
  879 + m->instance = instance;
  880 + m->state = MBR_JOINED;
  881 + *usr_wakeup = true;
  882 + m->usr_pending = false;
  883 + list_del_init(&m->small_win);
867 884 tipc_group_update_member(m, 0);
868   - } else if (event == TIPC_WITHDRAWN) {
  885 + tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
  886 + tipc_group_create_event(grp, m, TIPC_PUBLISHED,
  887 + m->bc_syncpt, inputq);
  888 + break;
  889 + case TIPC_WITHDRAWN:
869 890 if (!m)
870   - return;
  891 + break;
871 892  
872 893 *usr_wakeup = true;
873 894 m->usr_pending = false;
... ... @@ -880,6 +901,9 @@
880 901 if (!tipc_node_is_up(net, node))
881 902 tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
882 903 m->bc_rcv_nxt, inputq);
  904 + break;
  905 + default:
  906 + break;
883 907 }
884 908 *sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
885 909 }
... ... @@ -44,8 +44,10 @@
44 44  
45 45 struct tipc_group *tipc_group_create(struct net *net, u32 portid,
46 46 struct tipc_group_req *mreq);
  47 +void tipc_group_join(struct net *net, struct tipc_group *grp, int *sk_rcv_buf);
47 48 void tipc_group_delete(struct net *net, struct tipc_group *grp);
48   -void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port);
  49 +void tipc_group_add_member(struct tipc_group *grp, u32 node,
  50 + u32 port, u32 instance);
49 51 struct tipc_nlist *tipc_group_dests(struct tipc_group *grp);
50 52 void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
51 53 int *scope);
net/tipc/name_table.c
... ... @@ -732,7 +732,7 @@
732 732 list_for_each_entry(p, &info->zone_list, zone_list) {
733 733 if (!tipc_in_scope(domain, p->node))
734 734 continue;
735   - tipc_group_add_member(grp, p->node, p->ref);
  735 + tipc_group_add_member(grp, p->node, p->ref, p->lower);
736 736 }
737 737 }
738 738 spin_unlock_bh(&seq->lock);
... ... @@ -2757,10 +2757,10 @@
2757 2757 tipc_group_delete(net, grp);
2758 2758 tsk->group = NULL;
2759 2759 }
2760   -
2761   - /* Eliminate any risk that a broadcast overtakes the sent JOIN */
  2760 + /* Eliminate any risk that a broadcast overtakes sent JOINs */
2762 2761 tsk->mc_method.rcast = true;
2763 2762 tsk->mc_method.mandatory = true;
  2763 + tipc_group_join(net, grp, &tsk->sk.sk_rcvbuf);
2764 2764 return rc;
2765 2765 }
2766 2766