summaryrefslogtreecommitdiffstats
path: root/net/tipc/group.c
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2018-01-08 15:03:28 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-09 12:35:58 -0500
commitd12d2e12cec2d66eab6cd58f592dad9fd386b97d (patch)
tree2a127edfb12677a9ec6e995e1f8345ed9962b7d6 /net/tipc/group.c
parentc2b22bcf2e18a279afd80a8c57e936014acf3348 (diff)
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>
Diffstat (limited to 'net/tipc/group.c')
-rw-r--r--net/tipc/group.c100
1 files changed, 62 insertions, 38 deletions
diff --git a/net/tipc/group.c b/net/tipc/group.c
index bdc54be9c07e..6ca07f0da60c 100644
--- a/net/tipc/group.c
+++ b/net/tipc/group.c
@@ -49,7 +49,6 @@
49#define ADV_ACTIVE (ADV_UNIT * 12) 49#define ADV_ACTIVE (ADV_UNIT * 12)
50 50
51enum mbr_state { 51enum mbr_state {
52 MBR_DISCOVERED,
53 MBR_JOINING, 52 MBR_JOINING,
54 MBR_PUBLISHED, 53 MBR_PUBLISHED,
55 MBR_JOINED, 54 MBR_JOINED,
@@ -141,7 +140,7 @@ static bool tipc_group_is_receiver(struct tipc_member *m)
141 140
142static bool tipc_group_is_sender(struct tipc_member *m) 141static 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
147u32 tipc_group_exclude(struct tipc_group *grp) 146u32 tipc_group_exclude(struct tipc_group *grp)
@@ -184,6 +183,21 @@ struct tipc_group *tipc_group_create(struct net *net, u32 portid,
184 return NULL; 183 return NULL;
185} 184}
186 185
186void 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
187void tipc_group_delete(struct net *net, struct tipc_group *grp) 201void tipc_group_delete(struct net *net, struct tipc_group *grp)
188{ 202{
189 struct rb_root *tree = &grp->members; 203 struct rb_root *tree = &grp->members;
@@ -274,7 +288,7 @@ static void tipc_group_add_to_tree(struct tipc_group *grp,
274 288
275static struct tipc_member *tipc_group_create_member(struct tipc_group *grp, 289static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
276 u32 node, u32 port, 290 u32 node, u32 port,
277 int state) 291 u32 instance, int state)
278{ 292{
279 struct tipc_member *m; 293 struct tipc_member *m;
280 294
@@ -287,6 +301,7 @@ static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
287 m->group = grp; 301 m->group = grp;
288 m->node = node; 302 m->node = node;
289 m->port = port; 303 m->port = port;
304 m->instance = instance;
290 m->bc_acked = grp->bc_snd_nxt - 1; 305 m->bc_acked = grp->bc_snd_nxt - 1;
291 grp->member_cnt++; 306 grp->member_cnt++;
292 tipc_group_add_to_tree(grp, m); 307 tipc_group_add_to_tree(grp, m);
@@ -295,9 +310,10 @@ static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
295 return m; 310 return m;
296} 311}
297 312
298void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port) 313void 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
303static void tipc_group_delete_member(struct tipc_group *grp, 319static void tipc_group_delete_member(struct tipc_group *grp,
@@ -623,7 +639,6 @@ void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
623 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq); 639 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
624 break; 640 break;
625 case MBR_RECLAIMING: 641 case MBR_RECLAIMING:
626 case MBR_DISCOVERED:
627 case MBR_JOINING: 642 case MBR_JOINING:
628 case MBR_LEAVING: 643 case MBR_LEAVING:
629 default: 644 default:
@@ -721,26 +736,26 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
721 case GRP_JOIN_MSG: 736 case GRP_JOIN_MSG:
722 if (!m) 737 if (!m)
723 m = tipc_group_create_member(grp, node, port, 738 m = tipc_group_create_member(grp, node, port,
724 MBR_JOINING); 739 0, MBR_JOINING);
725 if (!m) 740 if (!m)
726 return; 741 return;
727 m->bc_syncpt = msg_grp_bc_syncpt(hdr); 742 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
728 m->bc_rcv_nxt = m->bc_syncpt; 743 m->bc_rcv_nxt = m->bc_syncpt;
729 m->window += msg_adv_win(hdr); 744 m->window += msg_adv_win(hdr);
730 745
731 /* Wait until PUBLISH event is received */ 746 /* Wait until PUBLISH event is received if necessary */
732 if (m->state == MBR_DISCOVERED) { 747 if (m->state != MBR_PUBLISHED)
733 m->state = MBR_JOINING; 748 return;
734 } else if (m->state == MBR_PUBLISHED) { 749
735 m->state = MBR_JOINED; 750 /* Member can be taken into service */
736 *usr_wakeup = true; 751 m->state = MBR_JOINED;
737 m->usr_pending = false; 752 *usr_wakeup = true;
738 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq); 753 m->usr_pending = false;
739 tipc_group_create_event(grp, m, TIPC_PUBLISHED,
740 m->bc_syncpt, inputq);
741 }
742 list_del_init(&m->small_win); 754 list_del_init(&m->small_win);
743 tipc_group_update_member(m, 0); 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 return; 759 return;
745 case GRP_LEAVE_MSG: 760 case GRP_LEAVE_MSG:
746 if (!m) 761 if (!m)
@@ -844,30 +859,36 @@ void tipc_group_member_evt(struct tipc_group *grp,
844 859
845 m = tipc_group_find_member(grp, node, port); 860 m = tipc_group_find_member(grp, node, port);
846 861
847 if (event == TIPC_PUBLISHED) { 862 switch (event) {
848 if (!m) 863 case TIPC_PUBLISHED:
849 m = tipc_group_create_member(grp, node, port, 864 /* Send and wait for arrival of JOIN message if necessary */
850 MBR_DISCOVERED); 865 if (!m) {
851 if (!m) 866 m = tipc_group_create_member(grp, node, port, instance,
852 return; 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 */ 878 /* Member can be taken into service */
857 if (m->state == MBR_DISCOVERED) { 879 m->instance = instance;
858 m->state = MBR_PUBLISHED; 880 m->state = MBR_JOINED;
859 } else { 881 *usr_wakeup = true;
860 tipc_group_create_event(grp, m, TIPC_PUBLISHED, 882 m->usr_pending = false;
861 m->bc_syncpt, inputq); 883 list_del_init(&m->small_win);
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);
867 tipc_group_update_member(m, 0); 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 if (!m) 890 if (!m)
870 return; 891 break;
871 892
872 *usr_wakeup = true; 893 *usr_wakeup = true;
873 m->usr_pending = false; 894 m->usr_pending = false;
@@ -880,6 +901,9 @@ void tipc_group_member_evt(struct tipc_group *grp,
880 if (!tipc_node_is_up(net, node)) 901 if (!tipc_node_is_up(net, node))
881 tipc_group_create_event(grp, m, TIPC_WITHDRAWN, 902 tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
882 m->bc_rcv_nxt, inputq); 903 m->bc_rcv_nxt, inputq);
904 break;
905 default:
906 break;
883 } 907 }
884 *sk_rcvbuf = tipc_group_rcvbuf_limit(grp); 908 *sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
885} 909}