Blame view

net/tipc/group.c 23.7 KB
75da2163d   Jon Maloy   tipc: introduce c...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  /*
   * net/tipc/group.c: TIPC group messaging code
   *
   * Copyright (c) 2017, Ericsson AB
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the names of the copyright holders nor the names of its
   *    contributors may be used to endorse or promote products derived from
   *    this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   */
  
  #include "core.h"
  #include "addr.h"
  #include "group.h"
  #include "bcast.h"
026321c6d   Jon Maloy   tipc: rename tipc...
40
  #include "topsrv.h"
75da2163d   Jon Maloy   tipc: introduce c...
41
42
43
44
45
46
47
48
  #include "msg.h"
  #include "socket.h"
  #include "node.h"
  #include "name_table.h"
  #include "subscr.h"
  
  #define ADV_UNIT (((MAX_MSG_SIZE + MAX_H_SIZE) / FLOWCTL_BLK_SZ) + 1)
  #define ADV_IDLE ADV_UNIT
b7d426355   Jon Maloy   tipc: introduce f...
49
  #define ADV_ACTIVE (ADV_UNIT * 12)
75da2163d   Jon Maloy   tipc: introduce c...
50
51
  
  enum mbr_state {
75da2163d   Jon Maloy   tipc: introduce c...
52
53
54
  	MBR_JOINING,
  	MBR_PUBLISHED,
  	MBR_JOINED,
04d7b574b   Jon Maloy   tipc: add multipo...
55
56
57
58
  	MBR_PENDING,
  	MBR_ACTIVE,
  	MBR_RECLAIMING,
  	MBR_REMITTED,
75da2163d   Jon Maloy   tipc: introduce c...
59
60
61
62
63
64
  	MBR_LEAVING
  };
  
  struct tipc_member {
  	struct rb_node tree_node;
  	struct list_head list;
38266ca17   Jon Maloy   tipc: some clarif...
65
  	struct list_head small_win;
b87a5ea31   Jon Maloy   tipc: guarantee g...
66
  	struct sk_buff_head deferredq;
b7d426355   Jon Maloy   tipc: introduce f...
67
  	struct tipc_group *group;
75da2163d   Jon Maloy   tipc: introduce c...
68
69
  	u32 node;
  	u32 port;
31c82a2d9   Jon Maloy   tipc: add second ...
70
  	u32 instance;
75da2163d   Jon Maloy   tipc: introduce c...
71
  	enum mbr_state state;
b7d426355   Jon Maloy   tipc: introduce f...
72
73
  	u16 advertised;
  	u16 window;
75da2163d   Jon Maloy   tipc: introduce c...
74
  	u16 bc_rcv_nxt;
a3bada706   Jon Maloy   tipc: guarantee d...
75
  	u16 bc_syncpt;
2f487712b   Jon Maloy   tipc: guarantee t...
76
  	u16 bc_acked;
75da2163d   Jon Maloy   tipc: introduce c...
77
78
79
80
  };
  
  struct tipc_group {
  	struct rb_root members;
38266ca17   Jon Maloy   tipc: some clarif...
81
  	struct list_head small_win;
04d7b574b   Jon Maloy   tipc: add multipo...
82
83
  	struct list_head pending;
  	struct list_head active;
75da2163d   Jon Maloy   tipc: introduce c...
84
85
86
87
88
  	struct tipc_nlist dests;
  	struct net *net;
  	int subid;
  	u32 type;
  	u32 instance;
75da2163d   Jon Maloy   tipc: introduce c...
89
90
91
  	u32 scope;
  	u32 portid;
  	u16 member_cnt;
04d7b574b   Jon Maloy   tipc: add multipo...
92
93
  	u16 active_cnt;
  	u16 max_active;
75da2163d   Jon Maloy   tipc: introduce c...
94
  	u16 bc_snd_nxt;
2f487712b   Jon Maloy   tipc: guarantee t...
95
  	u16 bc_ackers;
60c253069   Jon Maloy   tipc: fix race be...
96
  	bool *open;
75da2163d   Jon Maloy   tipc: introduce c...
97
  	bool loopback;
ae236fb20   Jon Maloy   tipc: receive gro...
98
  	bool events;
75da2163d   Jon Maloy   tipc: introduce c...
99
100
101
102
  };
  
  static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
  				  int mtyp, struct sk_buff_head *xmitq);
eb929a91b   Jon Maloy   tipc: improve pol...
103
104
105
106
107
108
  static void tipc_group_open(struct tipc_member *m, bool *wakeup)
  {
  	*wakeup = false;
  	if (list_empty(&m->small_win))
  		return;
  	list_del_init(&m->small_win);
60c253069   Jon Maloy   tipc: fix race be...
109
  	*m->group->open = true;
eb929a91b   Jon Maloy   tipc: improve pol...
110
111
  	*wakeup = true;
  }
04d7b574b   Jon Maloy   tipc: add multipo...
112
113
114
  static void tipc_group_decr_active(struct tipc_group *grp,
  				   struct tipc_member *m)
  {
f9c935db8   Jon Maloy   tipc: fix problem...
115
116
  	if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING ||
  	    m->state == MBR_REMITTED)
04d7b574b   Jon Maloy   tipc: add multipo...
117
118
  		grp->active_cnt--;
  }
b7d426355   Jon Maloy   tipc: introduce f...
119
120
  static int tipc_group_rcvbuf_limit(struct tipc_group *grp)
  {
04d7b574b   Jon Maloy   tipc: add multipo...
121
  	int max_active, active_pool, idle_pool;
b7d426355   Jon Maloy   tipc: introduce f...
122
  	int mcnt = grp->member_cnt + 1;
04d7b574b   Jon Maloy   tipc: add multipo...
123
124
125
126
127
128
129
130
  	/* Limit simultaneous reception from other members */
  	max_active = min(mcnt / 8, 64);
  	max_active = max(max_active, 16);
  	grp->max_active = max_active;
  
  	/* Reserve blocks for active and idle members */
  	active_pool = max_active * ADV_ACTIVE;
  	idle_pool = (mcnt - max_active) * ADV_IDLE;
b7d426355   Jon Maloy   tipc: introduce f...
131
  	/* Scale to bytes, considering worst-case truesize/msgsize ratio */
04d7b574b   Jon Maloy   tipc: add multipo...
132
  	return (active_pool + idle_pool) * FLOWCTL_BLK_SZ * 4;
b7d426355   Jon Maloy   tipc: introduce f...
133
  }
75da2163d   Jon Maloy   tipc: introduce c...
134
135
136
137
  u16 tipc_group_bc_snd_nxt(struct tipc_group *grp)
  {
  	return grp->bc_snd_nxt;
  }
38266ca17   Jon Maloy   tipc: some clarif...
138
  static bool tipc_group_is_receiver(struct tipc_member *m)
b7d426355   Jon Maloy   tipc: introduce f...
139
  {
0233493a5   Jon Maloy   tipc: adjustment ...
140
  	return m && m->state != MBR_JOINING && m->state != MBR_LEAVING;
b7d426355   Jon Maloy   tipc: introduce f...
141
  }
38266ca17   Jon Maloy   tipc: some clarif...
142
  static bool tipc_group_is_sender(struct tipc_member *m)
75da2163d   Jon Maloy   tipc: introduce c...
143
  {
d12d2e12c   Jon Maloy   tipc: send out jo...
144
  	return m && m->state != MBR_JOINING && m->state != MBR_PUBLISHED;
75da2163d   Jon Maloy   tipc: introduce c...
145
  }
ee106d7f9   Jon Maloy   tipc: introduce g...
146
147
148
149
150
151
  u32 tipc_group_exclude(struct tipc_group *grp)
  {
  	if (!grp->loopback)
  		return grp->portid;
  	return 0;
  }
75da2163d   Jon Maloy   tipc: introduce c...
152
  struct tipc_group *tipc_group_create(struct net *net, u32 portid,
60c253069   Jon Maloy   tipc: fix race be...
153
154
  				     struct tipc_group_req *mreq,
  				     bool *group_is_open)
75da2163d   Jon Maloy   tipc: introduce c...
155
  {
232d07b74   Jon Maloy   tipc: improve gro...
156
157
  	u32 filter = TIPC_SUB_PORTS | TIPC_SUB_NO_STATUS;
  	bool global = mreq->scope != TIPC_NODE_SCOPE;
75da2163d   Jon Maloy   tipc: introduce c...
158
159
160
161
162
163
164
  	struct tipc_group *grp;
  	u32 type = mreq->type;
  
  	grp = kzalloc(sizeof(*grp), GFP_ATOMIC);
  	if (!grp)
  		return NULL;
  	tipc_nlist_init(&grp->dests, tipc_own_addr(net));
38266ca17   Jon Maloy   tipc: some clarif...
165
  	INIT_LIST_HEAD(&grp->small_win);
04d7b574b   Jon Maloy   tipc: add multipo...
166
167
  	INIT_LIST_HEAD(&grp->active);
  	INIT_LIST_HEAD(&grp->pending);
75da2163d   Jon Maloy   tipc: introduce c...
168
169
170
  	grp->members = RB_ROOT;
  	grp->net = net;
  	grp->portid = portid;
75da2163d   Jon Maloy   tipc: introduce c...
171
172
173
174
  	grp->type = type;
  	grp->instance = mreq->instance;
  	grp->scope = mreq->scope;
  	grp->loopback = mreq->flags & TIPC_GROUP_LOOPBACK;
ae236fb20   Jon Maloy   tipc: receive gro...
175
  	grp->events = mreq->flags & TIPC_GROUP_MEMBER_EVTS;
60c253069   Jon Maloy   tipc: fix race be...
176
  	grp->open = group_is_open;
1b22bcad7   Jon Maloy   tipc: correct ini...
177
  	*grp->open = false;
232d07b74   Jon Maloy   tipc: improve gro...
178
179
180
  	filter |= global ? TIPC_SUB_CLUSTER_SCOPE : TIPC_SUB_NODE_SCOPE;
  	if (tipc_topsrv_kern_subscr(net, portid, type, 0, ~0,
  				    filter, &grp->subid))
75da2163d   Jon Maloy   tipc: introduce c...
181
182
183
184
  		return grp;
  	kfree(grp);
  	return NULL;
  }
d12d2e12c   Jon Maloy   tipc: send out jo...
185
186
187
188
189
  void tipc_group_join(struct net *net, struct tipc_group *grp, int *sk_rcvbuf)
  {
  	struct rb_root *tree = &grp->members;
  	struct tipc_member *m, *tmp;
  	struct sk_buff_head xmitq;
e654f9f53   Jon Maloy   tipc: clean up sk...
190
  	__skb_queue_head_init(&xmitq);
d12d2e12c   Jon Maloy   tipc: send out jo...
191
192
193
194
195
196
197
  	rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
  		tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, &xmitq);
  		tipc_group_update_member(m, 0);
  	}
  	tipc_node_distr_xmit(net, &xmitq);
  	*sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
  }
75da2163d   Jon Maloy   tipc: introduce c...
198
199
200
201
202
203
204
205
206
207
  void tipc_group_delete(struct net *net, struct tipc_group *grp)
  {
  	struct rb_root *tree = &grp->members;
  	struct tipc_member *m, *tmp;
  	struct sk_buff_head xmitq;
  
  	__skb_queue_head_init(&xmitq);
  
  	rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
  		tipc_group_proto_xmit(grp, m, GRP_LEAVE_MSG, &xmitq);
5cf02612b   Xin Long   tipc: purge defer...
208
  		__skb_queue_purge(&m->deferredq);
75da2163d   Jon Maloy   tipc: introduce c...
209
210
211
212
213
214
215
216
  		list_del(&m->list);
  		kfree(m);
  	}
  	tipc_node_distr_xmit(net, &xmitq);
  	tipc_nlist_purge(&grp->dests);
  	tipc_topsrv_kern_unsubscr(net, grp->subid);
  	kfree(grp);
  }
e064cce13   YueHaibing   tipc: make some f...
217
218
  static struct tipc_member *tipc_group_find_member(struct tipc_group *grp,
  						  u32 node, u32 port)
75da2163d   Jon Maloy   tipc: introduce c...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  {
  	struct rb_node *n = grp->members.rb_node;
  	u64 nkey, key = (u64)node << 32 | port;
  	struct tipc_member *m;
  
  	while (n) {
  		m = container_of(n, struct tipc_member, tree_node);
  		nkey = (u64)m->node << 32 | m->port;
  		if (key < nkey)
  			n = n->rb_left;
  		else if (key > nkey)
  			n = n->rb_right;
  		else
  			return m;
  	}
  	return NULL;
  }
27bd9ec02   Jon Maloy   tipc: introduce g...
236
237
238
239
240
241
  static struct tipc_member *tipc_group_find_dest(struct tipc_group *grp,
  						u32 node, u32 port)
  {
  	struct tipc_member *m;
  
  	m = tipc_group_find_member(grp, node, port);
38266ca17   Jon Maloy   tipc: some clarif...
242
  	if (m && tipc_group_is_receiver(m))
27bd9ec02   Jon Maloy   tipc: introduce g...
243
244
245
  		return m;
  	return NULL;
  }
75da2163d   Jon Maloy   tipc: introduce c...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
  						u32 node)
  {
  	struct tipc_member *m;
  	struct rb_node *n;
  
  	for (n = rb_first(&grp->members); n; n = rb_next(n)) {
  		m = container_of(n, struct tipc_member, tree_node);
  		if (m->node == node)
  			return m;
  	}
  	return NULL;
  }
  
  static void tipc_group_add_to_tree(struct tipc_group *grp,
  				   struct tipc_member *m)
  {
  	u64 nkey, key = (u64)m->node << 32 | m->port;
  	struct rb_node **n, *parent = NULL;
  	struct tipc_member *tmp;
  
  	n = &grp->members.rb_node;
  	while (*n) {
  		tmp = container_of(*n, struct tipc_member, tree_node);
  		parent = *n;
  		tmp = container_of(parent, struct tipc_member, tree_node);
  		nkey = (u64)tmp->node << 32 | tmp->port;
  		if (key < nkey)
  			n = &(*n)->rb_left;
  		else if (key > nkey)
  			n = &(*n)->rb_right;
  		else
  			return;
  	}
  	rb_link_node(&m->tree_node, parent, n);
  	rb_insert_color(&m->tree_node, &grp->members);
  }
  
  static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
  						    u32 node, u32 port,
d12d2e12c   Jon Maloy   tipc: send out jo...
286
  						    u32 instance, int state)
75da2163d   Jon Maloy   tipc: introduce c...
287
288
289
290
291
292
293
  {
  	struct tipc_member *m;
  
  	m = kzalloc(sizeof(*m), GFP_ATOMIC);
  	if (!m)
  		return NULL;
  	INIT_LIST_HEAD(&m->list);
38266ca17   Jon Maloy   tipc: some clarif...
294
  	INIT_LIST_HEAD(&m->small_win);
b87a5ea31   Jon Maloy   tipc: guarantee g...
295
  	__skb_queue_head_init(&m->deferredq);
b7d426355   Jon Maloy   tipc: introduce f...
296
  	m->group = grp;
75da2163d   Jon Maloy   tipc: introduce c...
297
298
  	m->node = node;
  	m->port = port;
d12d2e12c   Jon Maloy   tipc: send out jo...
299
  	m->instance = instance;
2f487712b   Jon Maloy   tipc: guarantee t...
300
  	m->bc_acked = grp->bc_snd_nxt - 1;
75da2163d   Jon Maloy   tipc: introduce c...
301
302
303
304
305
306
  	grp->member_cnt++;
  	tipc_group_add_to_tree(grp, m);
  	tipc_nlist_add(&grp->dests, m->node);
  	m->state = state;
  	return m;
  }
d12d2e12c   Jon Maloy   tipc: send out jo...
307
308
  void tipc_group_add_member(struct tipc_group *grp, u32 node,
  			   u32 port, u32 instance)
75da2163d   Jon Maloy   tipc: introduce c...
309
  {
d12d2e12c   Jon Maloy   tipc: send out jo...
310
  	tipc_group_create_member(grp, node, port, instance, MBR_PUBLISHED);
75da2163d   Jon Maloy   tipc: introduce c...
311
312
313
314
315
316
317
  }
  
  static void tipc_group_delete_member(struct tipc_group *grp,
  				     struct tipc_member *m)
  {
  	rb_erase(&m->tree_node, &grp->members);
  	grp->member_cnt--;
2f487712b   Jon Maloy   tipc: guarantee t...
318
319
320
321
  
  	/* Check if we were waiting for replicast ack from this member */
  	if (grp->bc_ackers && less(m->bc_acked, grp->bc_snd_nxt - 1))
  		grp->bc_ackers--;
75da2163d   Jon Maloy   tipc: introduce c...
322
  	list_del_init(&m->list);
38266ca17   Jon Maloy   tipc: some clarif...
323
  	list_del_init(&m->small_win);
04d7b574b   Jon Maloy   tipc: add multipo...
324
  	tipc_group_decr_active(grp, m);
75da2163d   Jon Maloy   tipc: introduce c...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  
  	/* If last member on a node, remove node from dest list */
  	if (!tipc_group_find_node(grp, m->node))
  		tipc_nlist_del(&grp->dests, m->node);
  
  	kfree(m);
  }
  
  struct tipc_nlist *tipc_group_dests(struct tipc_group *grp)
  {
  	return &grp->dests;
  }
  
  void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
  		     int *scope)
  {
  	seq->type = grp->type;
  	seq->lower = grp->instance;
  	seq->upper = grp->instance;
  	*scope = grp->scope;
  }
b7d426355   Jon Maloy   tipc: introduce f...
346
347
348
349
  void tipc_group_update_member(struct tipc_member *m, int len)
  {
  	struct tipc_group *grp = m->group;
  	struct tipc_member *_m, *tmp;
38266ca17   Jon Maloy   tipc: some clarif...
350
  	if (!tipc_group_is_receiver(m))
b7d426355   Jon Maloy   tipc: introduce f...
351
352
353
354
355
356
  		return;
  
  	m->window -= len;
  
  	if (m->window >= ADV_IDLE)
  		return;
38266ca17   Jon Maloy   tipc: some clarif...
357
  	list_del_init(&m->small_win);
b7d426355   Jon Maloy   tipc: introduce f...
358

38266ca17   Jon Maloy   tipc: some clarif...
359
360
  	/* Sort member into small_window members' list */
  	list_for_each_entry_safe(_m, tmp, &grp->small_win, small_win) {
d84d1b3b6   Jon Maloy   tipc: simplify sm...
361
362
  		if (_m->window > m->window)
  			break;
b7d426355   Jon Maloy   tipc: introduce f...
363
  	}
d84d1b3b6   Jon Maloy   tipc: simplify sm...
364
  	list_add_tail(&m->small_win, &_m->small_win);
b7d426355   Jon Maloy   tipc: introduce f...
365
  }
2f487712b   Jon Maloy   tipc: guarantee t...
366
  void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack)
75da2163d   Jon Maloy   tipc: introduce c...
367
  {
2f487712b   Jon Maloy   tipc: guarantee t...
368
  	u16 prev = grp->bc_snd_nxt - 1;
b7d426355   Jon Maloy   tipc: introduce f...
369
370
  	struct tipc_member *m;
  	struct rb_node *n;
0a3d805c9   Jon Maloy   tipc: base group ...
371
  	u16 ackers = 0;
b7d426355   Jon Maloy   tipc: introduce f...
372
373
374
  
  	for (n = rb_first(&grp->members); n; n = rb_next(n)) {
  		m = container_of(n, struct tipc_member, tree_node);
38266ca17   Jon Maloy   tipc: some clarif...
375
  		if (tipc_group_is_receiver(m)) {
b7d426355   Jon Maloy   tipc: introduce f...
376
  			tipc_group_update_member(m, len);
2f487712b   Jon Maloy   tipc: guarantee t...
377
  			m->bc_acked = prev;
0a3d805c9   Jon Maloy   tipc: base group ...
378
  			ackers++;
2f487712b   Jon Maloy   tipc: guarantee t...
379
  		}
b7d426355   Jon Maloy   tipc: introduce f...
380
  	}
2f487712b   Jon Maloy   tipc: guarantee t...
381
382
383
  
  	/* Mark number of acknowledges to expect, if any */
  	if (ack)
0a3d805c9   Jon Maloy   tipc: base group ...
384
  		grp->bc_ackers = ackers;
75da2163d   Jon Maloy   tipc: introduce c...
385
386
  	grp->bc_snd_nxt++;
  }
27bd9ec02   Jon Maloy   tipc: introduce g...
387
388
  bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
  		     int len, struct tipc_member **mbr)
b7d426355   Jon Maloy   tipc: introduce f...
389
  {
27bd9ec02   Jon Maloy   tipc: introduce g...
390
  	struct sk_buff_head xmitq;
b7d426355   Jon Maloy   tipc: introduce f...
391
  	struct tipc_member *m;
27bd9ec02   Jon Maloy   tipc: introduce g...
392
393
394
  	int adv, state;
  
  	m = tipc_group_find_dest(grp, dnode, dport);
eb929a91b   Jon Maloy   tipc: improve pol...
395
396
  	if (!tipc_group_is_receiver(m)) {
  		*mbr = NULL;
27bd9ec02   Jon Maloy   tipc: introduce g...
397
  		return false;
eb929a91b   Jon Maloy   tipc: improve pol...
398
399
  	}
  	*mbr = m;
27bd9ec02   Jon Maloy   tipc: introduce g...
400
401
  	if (m->window >= len)
  		return false;
eb929a91b   Jon Maloy   tipc: improve pol...
402

60c253069   Jon Maloy   tipc: fix race be...
403
  	*grp->open = false;
27bd9ec02   Jon Maloy   tipc: introduce g...
404
405
406
407
  
  	/* If not fully advertised, do it now to prevent mutual blocking */
  	adv = m->advertised;
  	state = m->state;
27bd9ec02   Jon Maloy   tipc: introduce g...
408
409
  	if (state == MBR_JOINED && adv == ADV_IDLE)
  		return true;
04d7b574b   Jon Maloy   tipc: add multipo...
410
411
412
413
  	if (state == MBR_ACTIVE && adv == ADV_ACTIVE)
  		return true;
  	if (state == MBR_PENDING && adv == ADV_IDLE)
  		return true;
e654f9f53   Jon Maloy   tipc: clean up sk...
414
  	__skb_queue_head_init(&xmitq);
27bd9ec02   Jon Maloy   tipc: introduce g...
415
416
417
418
419
420
421
422
  	tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, &xmitq);
  	tipc_node_distr_xmit(grp->net, &xmitq);
  	return true;
  }
  
  bool tipc_group_bc_cong(struct tipc_group *grp, int len)
  {
  	struct tipc_member *m = NULL;
b7d426355   Jon Maloy   tipc: introduce f...
423

2f487712b   Jon Maloy   tipc: guarantee t...
424
  	/* If prev bcast was replicast, reject until all receivers have acked */
eb929a91b   Jon Maloy   tipc: improve pol...
425
  	if (grp->bc_ackers) {
60c253069   Jon Maloy   tipc: fix race be...
426
  		*grp->open = false;
2f487712b   Jon Maloy   tipc: guarantee t...
427
  		return true;
eb929a91b   Jon Maloy   tipc: improve pol...
428
  	}
38266ca17   Jon Maloy   tipc: some clarif...
429
  	if (list_empty(&grp->small_win))
b7d426355   Jon Maloy   tipc: introduce f...
430
  		return false;
38266ca17   Jon Maloy   tipc: some clarif...
431
  	m = list_first_entry(&grp->small_win, struct tipc_member, small_win);
b7d426355   Jon Maloy   tipc: introduce f...
432
433
  	if (m->window >= len)
  		return false;
27bd9ec02   Jon Maloy   tipc: introduce g...
434
  	return tipc_group_cong(grp, m->node, m->port, len, &m);
b7d426355   Jon Maloy   tipc: introduce f...
435
  }
b87a5ea31   Jon Maloy   tipc: guarantee g...
436
437
438
439
440
441
442
443
  /* tipc_group_sort_msg() - sort msg into queue by bcast sequence number
   */
  static void tipc_group_sort_msg(struct sk_buff *skb, struct sk_buff_head *defq)
  {
  	struct tipc_msg *_hdr, *hdr = buf_msg(skb);
  	u16 bc_seqno = msg_grp_bc_seqno(hdr);
  	struct sk_buff *_skb, *tmp;
  	int mtyp = msg_type(hdr);
a3bada706   Jon Maloy   tipc: guarantee d...
444
  	/* Bcast/mcast may be bypassed by ucast or other bcast, - sort it in */
b87a5ea31   Jon Maloy   tipc: guarantee g...
445
446
447
448
449
450
451
452
453
454
455
456
457
  	if (mtyp == TIPC_GRP_BCAST_MSG || mtyp == TIPC_GRP_MCAST_MSG) {
  		skb_queue_walk_safe(defq, _skb, tmp) {
  			_hdr = buf_msg(_skb);
  			if (!less(bc_seqno, msg_grp_bc_seqno(_hdr)))
  				continue;
  			__skb_queue_before(defq, _skb, skb);
  			return;
  		}
  		/* Bcast was not bypassed, - add to tail */
  	}
  	/* Unicasts are never bypassed, - always add to tail */
  	__skb_queue_tail(defq, skb);
  }
75da2163d   Jon Maloy   tipc: introduce c...
458
459
460
461
462
463
  /* tipc_group_filter_msg() - determine if we should accept arriving message
   */
  void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
  			   struct sk_buff_head *xmitq)
  {
  	struct sk_buff *skb = __skb_dequeue(inputq);
a3bada706   Jon Maloy   tipc: guarantee d...
464
  	bool ack, deliver, update, leave = false;
b87a5ea31   Jon Maloy   tipc: guarantee g...
465
  	struct sk_buff_head *defq;
75da2163d   Jon Maloy   tipc: introduce c...
466
467
468
  	struct tipc_member *m;
  	struct tipc_msg *hdr;
  	u32 node, port;
b87a5ea31   Jon Maloy   tipc: guarantee g...
469
  	int mtyp, blks;
75da2163d   Jon Maloy   tipc: introduce c...
470
471
472
473
474
  
  	if (!skb)
  		return;
  
  	hdr = buf_msg(skb);
75da2163d   Jon Maloy   tipc: introduce c...
475
476
477
478
479
480
481
  	node =  msg_orignode(hdr);
  	port = msg_origport(hdr);
  
  	if (!msg_in_group(hdr))
  		goto drop;
  
  	m = tipc_group_find_member(grp, node, port);
38266ca17   Jon Maloy   tipc: some clarif...
482
  	if (!tipc_group_is_sender(m))
75da2163d   Jon Maloy   tipc: introduce c...
483
  		goto drop;
b87a5ea31   Jon Maloy   tipc: guarantee g...
484
485
  	if (less(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
  		goto drop;
5b8dddb63   Jon Maloy   tipc: introduce g...
486

b87a5ea31   Jon Maloy   tipc: guarantee g...
487
488
489
490
491
492
493
  	TIPC_SKB_CB(skb)->orig_member = m->instance;
  	defq = &m->deferredq;
  	tipc_group_sort_msg(skb, defq);
  
  	while ((skb = skb_peek(defq))) {
  		hdr = buf_msg(skb);
  		mtyp = msg_type(hdr);
2e724dca7   Jon Maloy   tipc: eliminate a...
494
  		blks = msg_blocks(hdr);
b87a5ea31   Jon Maloy   tipc: guarantee g...
495
  		deliver = true;
2f487712b   Jon Maloy   tipc: guarantee t...
496
  		ack = false;
b87a5ea31   Jon Maloy   tipc: guarantee g...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  		update = false;
  
  		if (more(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
  			break;
  
  		/* Decide what to do with message */
  		switch (mtyp) {
  		case TIPC_GRP_MCAST_MSG:
  			if (msg_nameinst(hdr) != grp->instance) {
  				update = true;
  				deliver = false;
  			}
  			/* Fall thru */
  		case TIPC_GRP_BCAST_MSG:
  			m->bc_rcv_nxt++;
2f487712b   Jon Maloy   tipc: guarantee t...
512
  			ack = msg_grp_bc_ack_req(hdr);
b87a5ea31   Jon Maloy   tipc: guarantee g...
513
514
515
  			break;
  		case TIPC_GRP_UCAST_MSG:
  			break;
a3bada706   Jon Maloy   tipc: guarantee d...
516
517
518
519
520
521
  		case TIPC_GRP_MEMBER_EVT:
  			if (m->state == MBR_LEAVING)
  				leave = true;
  			if (!grp->events)
  				deliver = false;
  			break;
b87a5ea31   Jon Maloy   tipc: guarantee g...
522
523
  		default:
  			break;
5b8dddb63   Jon Maloy   tipc: introduce g...
524
  		}
5b8dddb63   Jon Maloy   tipc: introduce g...
525

b87a5ea31   Jon Maloy   tipc: guarantee g...
526
527
528
529
530
531
  		/* Execute decisions */
  		__skb_dequeue(defq);
  		if (deliver)
  			__skb_queue_tail(inputq, skb);
  		else
  			kfree_skb(skb);
2f487712b   Jon Maloy   tipc: guarantee t...
532
533
  		if (ack)
  			tipc_group_proto_xmit(grp, m, GRP_ACK_MSG, xmitq);
a3bada706   Jon Maloy   tipc: guarantee d...
534
  		if (leave) {
a3bada706   Jon Maloy   tipc: guarantee d...
535
  			__skb_queue_purge(defq);
e0e853ac0   Jon Maloy   tipc: fix access ...
536
  			tipc_group_delete_member(grp, m);
a3bada706   Jon Maloy   tipc: guarantee d...
537
538
  			break;
  		}
b87a5ea31   Jon Maloy   tipc: guarantee g...
539
540
  		if (!update)
  			continue;
75da2163d   Jon Maloy   tipc: introduce c...
541

b87a5ea31   Jon Maloy   tipc: guarantee g...
542
543
  		tipc_group_update_rcv_win(grp, blks, node, port, xmitq);
  	}
75da2163d   Jon Maloy   tipc: introduce c...
544
545
546
547
  	return;
  drop:
  	kfree_skb(skb);
  }
b7d426355   Jon Maloy   tipc: introduce f...
548
549
550
  void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
  			       u32 port, struct sk_buff_head *xmitq)
  {
04d7b574b   Jon Maloy   tipc: add multipo...
551
552
553
554
  	struct list_head *active = &grp->active;
  	int max_active = grp->max_active;
  	int reclaim_limit = max_active * 3 / 4;
  	int active_cnt = grp->active_cnt;
f9c935db8   Jon Maloy   tipc: fix problem...
555
  	struct tipc_member *m, *rm, *pm;
b7d426355   Jon Maloy   tipc: introduce f...
556
557
558
559
560
561
562
563
564
  
  	m = tipc_group_find_member(grp, node, port);
  	if (!m)
  		return;
  
  	m->advertised -= blks;
  
  	switch (m->state) {
  	case MBR_JOINED:
4ea5dab54   Jon Maloy   tipc: let group m...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
  		/* First, decide if member can go active */
  		if (active_cnt <= max_active) {
  			m->state = MBR_ACTIVE;
  			list_add_tail(&m->list, active);
  			grp->active_cnt++;
  			tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
  		} else {
  			m->state = MBR_PENDING;
  			list_add_tail(&m->list, &grp->pending);
  		}
  
  		if (active_cnt < reclaim_limit)
  			break;
  
  		/* Reclaim from oldest active member, if possible */
  		if (!list_empty(active)) {
04d7b574b   Jon Maloy   tipc: add multipo...
581
582
  			rm = list_first_entry(active, struct tipc_member, list);
  			rm->state = MBR_RECLAIMING;
8d5dee21f   Jon Maloy   tipc: a couple of...
583
  			list_del_init(&rm->list);
04d7b574b   Jon Maloy   tipc: add multipo...
584
  			tipc_group_proto_xmit(grp, rm, GRP_RECLAIM_MSG, xmitq);
04d7b574b   Jon Maloy   tipc: add multipo...
585
586
  			break;
  		}
4ea5dab54   Jon Maloy   tipc: let group m...
587
588
589
590
591
592
  		/* Nobody to reclaim from; - revert oldest pending to JOINED */
  		pm = list_first_entry(&grp->pending, struct tipc_member, list);
  		list_del_init(&pm->list);
  		pm->state = MBR_JOINED;
  		tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
  		break;
04d7b574b   Jon Maloy   tipc: add multipo...
593
594
595
596
597
598
599
600
601
602
603
  	case MBR_ACTIVE:
  		if (!list_is_last(&m->list, &grp->active))
  			list_move_tail(&m->list, &grp->active);
  		if (m->advertised > (ADV_ACTIVE * 3 / 4))
  			break;
  		tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
  		break;
  	case MBR_REMITTED:
  		if (m->advertised > ADV_IDLE)
  			break;
  		m->state = MBR_JOINED;
8d5dee21f   Jon Maloy   tipc: a couple of...
604
  		grp->active_cnt--;
04d7b574b   Jon Maloy   tipc: add multipo...
605
606
607
  		if (m->advertised < ADV_IDLE) {
  			pr_warn_ratelimited("Rcv unexpected msg after REMIT
  ");
b7d426355   Jon Maloy   tipc: introduce f...
608
  			tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
04d7b574b   Jon Maloy   tipc: add multipo...
609
  		}
8d5dee21f   Jon Maloy   tipc: a couple of...
610

f9c935db8   Jon Maloy   tipc: fix problem...
611
612
613
614
615
616
617
618
619
  		if (list_empty(&grp->pending))
  			return;
  
  		/* Set oldest pending member to active and advertise */
  		pm = list_first_entry(&grp->pending, struct tipc_member, list);
  		pm->state = MBR_ACTIVE;
  		list_move_tail(&pm->list, &grp->active);
  		grp->active_cnt++;
  		tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
b7d426355   Jon Maloy   tipc: introduce f...
620
  		break;
04d7b574b   Jon Maloy   tipc: add multipo...
621
  	case MBR_RECLAIMING:
b7d426355   Jon Maloy   tipc: introduce f...
622
623
624
625
626
627
  	case MBR_JOINING:
  	case MBR_LEAVING:
  	default:
  		break;
  	}
  }
7ad32bcb7   Jon Maloy   tipc: create grou...
628
629
630
631
632
633
634
635
  static void tipc_group_create_event(struct tipc_group *grp,
  				    struct tipc_member *m,
  				    u32 event, u16 seqno,
  				    struct sk_buff_head *inputq)
  {	u32 dnode = tipc_own_addr(grp->net);
  	struct tipc_event evt;
  	struct sk_buff *skb;
  	struct tipc_msg *hdr;
b06f9d9f1   Jon Maloy   tipc: fix info le...
636
  	memset(&evt, 0, sizeof(evt));
7ad32bcb7   Jon Maloy   tipc: create grou...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
  	evt.event = event;
  	evt.found_lower = m->instance;
  	evt.found_upper = m->instance;
  	evt.port.ref = m->port;
  	evt.port.node = m->node;
  	evt.s.seq.type = grp->type;
  	evt.s.seq.lower = m->instance;
  	evt.s.seq.upper = m->instance;
  
  	skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_GRP_MEMBER_EVT,
  			      GROUP_H_SIZE, sizeof(evt), dnode, m->node,
  			      grp->portid, m->port, 0);
  	if (!skb)
  		return;
  
  	hdr = buf_msg(skb);
  	msg_set_nametype(hdr, grp->type);
  	msg_set_grp_evt(hdr, event);
  	msg_set_dest_droppable(hdr, true);
  	msg_set_grp_bc_seqno(hdr, seqno);
  	memcpy(msg_data(hdr), &evt, sizeof(evt));
  	TIPC_SKB_CB(skb)->orig_member = m->instance;
  	__skb_queue_tail(inputq, skb);
  }
75da2163d   Jon Maloy   tipc: introduce c...
661
662
663
664
665
  static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
  				  int mtyp, struct sk_buff_head *xmitq)
  {
  	struct tipc_msg *hdr;
  	struct sk_buff *skb;
b7d426355   Jon Maloy   tipc: introduce f...
666
  	int adv = 0;
75da2163d   Jon Maloy   tipc: introduce c...
667
668
669
670
671
672
  
  	skb = tipc_msg_create(GROUP_PROTOCOL, mtyp, INT_H_SIZE, 0,
  			      m->node, tipc_own_addr(grp->net),
  			      m->port, grp->portid, 0);
  	if (!skb)
  		return;
04d7b574b   Jon Maloy   tipc: add multipo...
673
  	if (m->state == MBR_ACTIVE)
b7d426355   Jon Maloy   tipc: introduce f...
674
  		adv = ADV_ACTIVE - m->advertised;
04d7b574b   Jon Maloy   tipc: add multipo...
675
676
  	else if (m->state == MBR_JOINED || m->state == MBR_PENDING)
  		adv = ADV_IDLE - m->advertised;
b7d426355   Jon Maloy   tipc: introduce f...
677

75da2163d   Jon Maloy   tipc: introduce c...
678
  	hdr = buf_msg(skb);
b7d426355   Jon Maloy   tipc: introduce f...
679
680
  
  	if (mtyp == GRP_JOIN_MSG) {
75da2163d   Jon Maloy   tipc: introduce c...
681
  		msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
b7d426355   Jon Maloy   tipc: introduce f...
682
683
  		msg_set_adv_win(hdr, adv);
  		m->advertised += adv;
a3bada706   Jon Maloy   tipc: guarantee d...
684
685
  	} else if (mtyp == GRP_LEAVE_MSG) {
  		msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
b7d426355   Jon Maloy   tipc: introduce f...
686
687
688
  	} else if (mtyp == GRP_ADV_MSG) {
  		msg_set_adv_win(hdr, adv);
  		m->advertised += adv;
2f487712b   Jon Maloy   tipc: guarantee t...
689
690
  	} else if (mtyp == GRP_ACK_MSG) {
  		msg_set_grp_bc_acked(hdr, m->bc_rcv_nxt);
04d7b574b   Jon Maloy   tipc: add multipo...
691
692
  	} else if (mtyp == GRP_REMIT_MSG) {
  		msg_set_grp_remitted(hdr, m->window);
b7d426355   Jon Maloy   tipc: introduce f...
693
  	}
234833991   Jon Maloy   tipc: fix lost me...
694
  	msg_set_dest_droppable(hdr, true);
75da2163d   Jon Maloy   tipc: introduce c...
695
696
  	__skb_queue_tail(xmitq, skb);
  }
b7d426355   Jon Maloy   tipc: introduce f...
697
698
  void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
  			  struct tipc_msg *hdr, struct sk_buff_head *inputq,
75da2163d   Jon Maloy   tipc: introduce c...
699
700
701
702
  			  struct sk_buff_head *xmitq)
  {
  	u32 node = msg_orignode(hdr);
  	u32 port = msg_origport(hdr);
04d7b574b   Jon Maloy   tipc: add multipo...
703
  	struct tipc_member *m, *pm;
04d7b574b   Jon Maloy   tipc: add multipo...
704
  	u16 remitted, in_flight;
75da2163d   Jon Maloy   tipc: introduce c...
705
706
707
  
  	if (!grp)
  		return;
232d07b74   Jon Maloy   tipc: improve gro...
708
709
  	if (grp->scope == TIPC_NODE_SCOPE && node != tipc_own_addr(grp->net))
  		return;
75da2163d   Jon Maloy   tipc: introduce c...
710
711
712
713
714
715
  	m = tipc_group_find_member(grp, node, port);
  
  	switch (msg_type(hdr)) {
  	case GRP_JOIN_MSG:
  		if (!m)
  			m = tipc_group_create_member(grp, node, port,
d12d2e12c   Jon Maloy   tipc: send out jo...
716
  						     0, MBR_JOINING);
75da2163d   Jon Maloy   tipc: introduce c...
717
718
  		if (!m)
  			return;
a3bada706   Jon Maloy   tipc: guarantee d...
719
720
  		m->bc_syncpt = msg_grp_bc_syncpt(hdr);
  		m->bc_rcv_nxt = m->bc_syncpt;
b7d426355   Jon Maloy   tipc: introduce f...
721
  		m->window += msg_adv_win(hdr);
75da2163d   Jon Maloy   tipc: introduce c...
722

d12d2e12c   Jon Maloy   tipc: send out jo...
723
724
725
726
727
728
  		/* Wait until PUBLISH event is received if necessary */
  		if (m->state != MBR_PUBLISHED)
  			return;
  
  		/* Member can be taken into service */
  		m->state = MBR_JOINED;
eb929a91b   Jon Maloy   tipc: improve pol...
729
  		tipc_group_open(m, usr_wakeup);
bb25c3855   Jon Maloy   tipc: remove join...
730
  		tipc_group_update_member(m, 0);
d12d2e12c   Jon Maloy   tipc: send out jo...
731
732
733
  		tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
  		tipc_group_create_event(grp, m, TIPC_PUBLISHED,
  					m->bc_syncpt, inputq);
75da2163d   Jon Maloy   tipc: introduce c...
734
735
736
737
  		return;
  	case GRP_LEAVE_MSG:
  		if (!m)
  			return;
a3bada706   Jon Maloy   tipc: guarantee d...
738
  		m->bc_syncpt = msg_grp_bc_syncpt(hdr);
3f42f5fe3   Jon Maloy   tipc: remove leav...
739
  		list_del_init(&m->list);
eb929a91b   Jon Maloy   tipc: improve pol...
740
  		tipc_group_open(m, usr_wakeup);
c2b22bcf2   Jon Maloy   tipc: simplify gr...
741
742
  		tipc_group_decr_active(grp, m);
  		m->state = MBR_LEAVING;
7ad32bcb7   Jon Maloy   tipc: create grou...
743
744
  		tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
  					m->bc_syncpt, inputq);
b7d426355   Jon Maloy   tipc: introduce f...
745
746
747
748
749
  		return;
  	case GRP_ADV_MSG:
  		if (!m)
  			return;
  		m->window += msg_adv_win(hdr);
eb929a91b   Jon Maloy   tipc: improve pol...
750
  		tipc_group_open(m, usr_wakeup);
75da2163d   Jon Maloy   tipc: introduce c...
751
  		return;
2f487712b   Jon Maloy   tipc: guarantee t...
752
753
754
755
756
  	case GRP_ACK_MSG:
  		if (!m)
  			return;
  		m->bc_acked = msg_grp_bc_acked(hdr);
  		if (--grp->bc_ackers)
eb929a91b   Jon Maloy   tipc: improve pol...
757
758
  			return;
  		list_del_init(&m->small_win);
60c253069   Jon Maloy   tipc: fix race be...
759
  		*m->group->open = true;
2f487712b   Jon Maloy   tipc: guarantee t...
760
  		*usr_wakeup = true;
eb929a91b   Jon Maloy   tipc: improve pol...
761
  		tipc_group_update_member(m, 0);
2f487712b   Jon Maloy   tipc: guarantee t...
762
  		return;
04d7b574b   Jon Maloy   tipc: add multipo...
763
764
765
  	case GRP_RECLAIM_MSG:
  		if (!m)
  			return;
04d7b574b   Jon Maloy   tipc: add multipo...
766
767
  		tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq);
  		m->window = ADV_IDLE;
eb929a91b   Jon Maloy   tipc: improve pol...
768
  		tipc_group_open(m, usr_wakeup);
04d7b574b   Jon Maloy   tipc: add multipo...
769
770
771
772
  		return;
  	case GRP_REMIT_MSG:
  		if (!m || m->state != MBR_RECLAIMING)
  			return;
04d7b574b   Jon Maloy   tipc: add multipo...
773
774
775
776
777
778
  		remitted = msg_grp_remitted(hdr);
  
  		/* Messages preceding the REMIT still in receive queue */
  		if (m->advertised > remitted) {
  			m->state = MBR_REMITTED;
  			in_flight = m->advertised - remitted;
f9c935db8   Jon Maloy   tipc: fix problem...
779
780
  			m->advertised = ADV_IDLE + in_flight;
  			return;
04d7b574b   Jon Maloy   tipc: add multipo...
781
  		}
8d5dee21f   Jon Maloy   tipc: a couple of...
782
  		/* This should never happen */
04d7b574b   Jon Maloy   tipc: add multipo...
783
  		if (m->advertised < remitted)
8d5dee21f   Jon Maloy   tipc: a couple of...
784
785
  			pr_warn_ratelimited("Unexpected REMIT msg
  ");
04d7b574b   Jon Maloy   tipc: add multipo...
786

8d5dee21f   Jon Maloy   tipc: a couple of...
787
788
  		/* All messages preceding the REMIT have been read */
  		m->state = MBR_JOINED;
f9c935db8   Jon Maloy   tipc: fix problem...
789
  		grp->active_cnt--;
8d5dee21f   Jon Maloy   tipc: a couple of...
790
  		m->advertised = ADV_IDLE;
04d7b574b   Jon Maloy   tipc: add multipo...
791
792
793
794
795
796
797
798
799
800
801
  
  		/* Set oldest pending member to active and advertise */
  		if (list_empty(&grp->pending))
  			return;
  		pm = list_first_entry(&grp->pending, struct tipc_member, list);
  		pm->state = MBR_ACTIVE;
  		list_move_tail(&pm->list, &grp->active);
  		grp->active_cnt++;
  		if (pm->advertised <= (ADV_ACTIVE * 3 / 4))
  			tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
  		return;
75da2163d   Jon Maloy   tipc: introduce c...
802
803
804
805
806
  	default:
  		pr_warn("Received unknown GROUP_PROTO message
  ");
  	}
  }
b7d426355   Jon Maloy   tipc: introduce f...
807
808
  /* tipc_group_member_evt() - receive and handle a member up/down event
   */
75da2163d   Jon Maloy   tipc: introduce c...
809
  void tipc_group_member_evt(struct tipc_group *grp,
b7d426355   Jon Maloy   tipc: introduce f...
810
811
  			   bool *usr_wakeup,
  			   int *sk_rcvbuf,
7ad32bcb7   Jon Maloy   tipc: create grou...
812
  			   struct tipc_msg *hdr,
ae236fb20   Jon Maloy   tipc: receive gro...
813
  			   struct sk_buff_head *inputq,
75da2163d   Jon Maloy   tipc: introduce c...
814
815
  			   struct sk_buff_head *xmitq)
  {
75da2163d   Jon Maloy   tipc: introduce c...
816
  	struct tipc_event *evt = (void *)msg_data(hdr);
ae236fb20   Jon Maloy   tipc: receive gro...
817
  	u32 instance = evt->found_lower;
75da2163d   Jon Maloy   tipc: introduce c...
818
819
  	u32 node = evt->port.node;
  	u32 port = evt->port.ref;
ae236fb20   Jon Maloy   tipc: receive gro...
820
  	int event = evt->event;
75da2163d   Jon Maloy   tipc: introduce c...
821
822
823
824
825
  	struct tipc_member *m;
  	struct net *net;
  	u32 self;
  
  	if (!grp)
7ad32bcb7   Jon Maloy   tipc: create grou...
826
  		return;
75da2163d   Jon Maloy   tipc: introduce c...
827
828
829
830
  
  	net = grp->net;
  	self = tipc_own_addr(net);
  	if (!grp->loopback && node == self && port == grp->portid)
7ad32bcb7   Jon Maloy   tipc: create grou...
831
  		return;
ae236fb20   Jon Maloy   tipc: receive gro...
832

75da2163d   Jon Maloy   tipc: introduce c...
833
  	m = tipc_group_find_member(grp, node, port);
d12d2e12c   Jon Maloy   tipc: send out jo...
834
835
836
837
838
839
840
841
842
843
844
845
  	switch (event) {
  	case TIPC_PUBLISHED:
  		/* Send and wait for arrival of JOIN message if necessary */
  		if (!m) {
  			m = tipc_group_create_member(grp, node, port, instance,
  						     MBR_PUBLISHED);
  			if (!m)
  				break;
  			tipc_group_update_member(m, 0);
  			tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
  			break;
  		}
7ad32bcb7   Jon Maloy   tipc: create grou...
846

d12d2e12c   Jon Maloy   tipc: send out jo...
847
848
  		if (m->state != MBR_JOINING)
  			break;
75da2163d   Jon Maloy   tipc: introduce c...
849

d12d2e12c   Jon Maloy   tipc: send out jo...
850
851
852
  		/* Member can be taken into service */
  		m->instance = instance;
  		m->state = MBR_JOINED;
eb929a91b   Jon Maloy   tipc: improve pol...
853
  		tipc_group_open(m, usr_wakeup);
d84d1b3b6   Jon Maloy   tipc: simplify sm...
854
  		tipc_group_update_member(m, 0);
d12d2e12c   Jon Maloy   tipc: send out jo...
855
856
857
858
859
  		tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
  		tipc_group_create_event(grp, m, TIPC_PUBLISHED,
  					m->bc_syncpt, inputq);
  		break;
  	case TIPC_WITHDRAWN:
75da2163d   Jon Maloy   tipc: introduce c...
860
  		if (!m)
d12d2e12c   Jon Maloy   tipc: send out jo...
861
  			break;
ae236fb20   Jon Maloy   tipc: receive gro...
862

c2b22bcf2   Jon Maloy   tipc: simplify gr...
863
864
  		tipc_group_decr_active(grp, m);
  		m->state = MBR_LEAVING;
3f42f5fe3   Jon Maloy   tipc: remove leav...
865
  		list_del_init(&m->list);
eb929a91b   Jon Maloy   tipc: improve pol...
866
  		tipc_group_open(m, usr_wakeup);
c2b22bcf2   Jon Maloy   tipc: simplify gr...
867
868
869
870
871
  
  		/* Only send event if no LEAVE message can be expected */
  		if (!tipc_node_is_up(net, node))
  			tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
  						m->bc_rcv_nxt, inputq);
d12d2e12c   Jon Maloy   tipc: send out jo...
872
873
874
  		break;
  	default:
  		break;
75da2163d   Jon Maloy   tipc: introduce c...
875
  	}
b7d426355   Jon Maloy   tipc: introduce f...
876
  	*sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
75da2163d   Jon Maloy   tipc: introduce c...
877
  }
a1be5a20f   GhantaKrishnamurthy MohanKrishna   tipc: extend sock...
878
879
880
  
  int tipc_group_fill_sock_diag(struct tipc_group *grp, struct sk_buff *skb)
  {
ae0be8de9   Michal Kubecek   netlink: make nla...
881
  	struct nlattr *group = nla_nest_start_noflag(skb, TIPC_NLA_SOCK_GROUP);
a1be5a20f   GhantaKrishnamurthy MohanKrishna   tipc: extend sock...
882

4589e28db   Kangjie Lu   net: tipc: fix a ...
883
884
  	if (!group)
  		return -EMSGSIZE;
a1be5a20f   GhantaKrishnamurthy MohanKrishna   tipc: extend sock...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
  	if (nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_ID,
  			grp->type) ||
  	    nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_INSTANCE,
  			grp->instance) ||
  	    nla_put_u32(skb, TIPC_NLA_SOCK_GROUP_BC_SEND_NEXT,
  			grp->bc_snd_nxt))
  		goto group_msg_cancel;
  
  	if (grp->scope == TIPC_NODE_SCOPE)
  		if (nla_put_flag(skb, TIPC_NLA_SOCK_GROUP_NODE_SCOPE))
  			goto group_msg_cancel;
  
  	if (grp->scope == TIPC_CLUSTER_SCOPE)
  		if (nla_put_flag(skb, TIPC_NLA_SOCK_GROUP_CLUSTER_SCOPE))
  			goto group_msg_cancel;
  
  	if (*grp->open)
  		if (nla_put_flag(skb, TIPC_NLA_SOCK_GROUP_OPEN))
  			goto group_msg_cancel;
  
  	nla_nest_end(skb, group);
  	return 0;
  
  group_msg_cancel:
  	nla_nest_cancel(skb, group);
  	return -1;
  }