blob: 6ca07f0da60c0947174225c2931e2d524db61901 [file] [log] [blame]
Jon Maloy75da2162017-10-13 11:04:23 +02001/*
2 * net/tipc/group.c: TIPC group messaging code
3 *
4 * Copyright (c) 2017, Ericsson AB
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the names of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include "core.h"
37#include "addr.h"
38#include "group.h"
39#include "bcast.h"
40#include "server.h"
41#include "msg.h"
42#include "socket.h"
43#include "node.h"
44#include "name_table.h"
45#include "subscr.h"
46
47#define ADV_UNIT (((MAX_MSG_SIZE + MAX_H_SIZE) / FLOWCTL_BLK_SZ) + 1)
48#define ADV_IDLE ADV_UNIT
Jon Maloyb7d42632017-10-13 11:04:26 +020049#define ADV_ACTIVE (ADV_UNIT * 12)
Jon Maloy75da2162017-10-13 11:04:23 +020050
51enum mbr_state {
Jon Maloy75da2162017-10-13 11:04:23 +020052 MBR_JOINING,
53 MBR_PUBLISHED,
54 MBR_JOINED,
Jon Maloy04d7b572017-10-13 11:04:34 +020055 MBR_PENDING,
56 MBR_ACTIVE,
57 MBR_RECLAIMING,
58 MBR_REMITTED,
Jon Maloy75da2162017-10-13 11:04:23 +020059 MBR_LEAVING
60};
61
62struct tipc_member {
63 struct rb_node tree_node;
64 struct list_head list;
Jon Maloy38266ca2018-01-04 15:20:44 +010065 struct list_head small_win;
Jon Maloyb87a5ea2017-10-13 11:04:30 +020066 struct sk_buff_head deferredq;
Jon Maloyb7d42632017-10-13 11:04:26 +020067 struct tipc_group *group;
Jon Maloy75da2162017-10-13 11:04:23 +020068 u32 node;
69 u32 port;
Jon Maloy31c82a22017-10-13 11:04:24 +020070 u32 instance;
Jon Maloy75da2162017-10-13 11:04:23 +020071 enum mbr_state state;
Jon Maloyb7d42632017-10-13 11:04:26 +020072 u16 advertised;
73 u16 window;
Jon Maloy75da2162017-10-13 11:04:23 +020074 u16 bc_rcv_nxt;
Jon Maloya3bada72017-10-13 11:04:33 +020075 u16 bc_syncpt;
Jon Maloy2f487712017-10-13 11:04:31 +020076 u16 bc_acked;
Jon Maloyb7d42632017-10-13 11:04:26 +020077 bool usr_pending;
Jon Maloy75da2162017-10-13 11:04:23 +020078};
79
80struct tipc_group {
81 struct rb_root members;
Jon Maloy38266ca2018-01-04 15:20:44 +010082 struct list_head small_win;
Jon Maloy04d7b572017-10-13 11:04:34 +020083 struct list_head pending;
84 struct list_head active;
Jon Maloy75da2162017-10-13 11:04:23 +020085 struct tipc_nlist dests;
86 struct net *net;
87 int subid;
88 u32 type;
89 u32 instance;
90 u32 domain;
91 u32 scope;
92 u32 portid;
93 u16 member_cnt;
Jon Maloy04d7b572017-10-13 11:04:34 +020094 u16 active_cnt;
95 u16 max_active;
Jon Maloy75da2162017-10-13 11:04:23 +020096 u16 bc_snd_nxt;
Jon Maloy2f487712017-10-13 11:04:31 +020097 u16 bc_ackers;
Jon Maloy75da2162017-10-13 11:04:23 +020098 bool loopback;
Jon Maloyae236fb2017-10-13 11:04:25 +020099 bool events;
Jon Maloy75da2162017-10-13 11:04:23 +0200100};
101
102static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
103 int mtyp, struct sk_buff_head *xmitq);
104
Jon Maloy04d7b572017-10-13 11:04:34 +0200105static void tipc_group_decr_active(struct tipc_group *grp,
106 struct tipc_member *m)
107{
Jon Maloyf9c935d2017-12-29 19:48:02 +0100108 if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING ||
109 m->state == MBR_REMITTED)
Jon Maloy04d7b572017-10-13 11:04:34 +0200110 grp->active_cnt--;
111}
112
Jon Maloyb7d42632017-10-13 11:04:26 +0200113static int tipc_group_rcvbuf_limit(struct tipc_group *grp)
114{
Jon Maloy04d7b572017-10-13 11:04:34 +0200115 int max_active, active_pool, idle_pool;
Jon Maloyb7d42632017-10-13 11:04:26 +0200116 int mcnt = grp->member_cnt + 1;
117
Jon Maloy04d7b572017-10-13 11:04:34 +0200118 /* Limit simultaneous reception from other members */
119 max_active = min(mcnt / 8, 64);
120 max_active = max(max_active, 16);
121 grp->max_active = max_active;
122
123 /* Reserve blocks for active and idle members */
124 active_pool = max_active * ADV_ACTIVE;
125 idle_pool = (mcnt - max_active) * ADV_IDLE;
126
Jon Maloyb7d42632017-10-13 11:04:26 +0200127 /* Scale to bytes, considering worst-case truesize/msgsize ratio */
Jon Maloy04d7b572017-10-13 11:04:34 +0200128 return (active_pool + idle_pool) * FLOWCTL_BLK_SZ * 4;
Jon Maloyb7d42632017-10-13 11:04:26 +0200129}
130
Jon Maloy75da2162017-10-13 11:04:23 +0200131u16 tipc_group_bc_snd_nxt(struct tipc_group *grp)
132{
133 return grp->bc_snd_nxt;
134}
135
Jon Maloy38266ca2018-01-04 15:20:44 +0100136static bool tipc_group_is_receiver(struct tipc_member *m)
Jon Maloyb7d42632017-10-13 11:04:26 +0200137{
Jon Maloy02334932018-01-08 21:03:25 +0100138 return m && m->state != MBR_JOINING && m->state != MBR_LEAVING;
Jon Maloyb7d42632017-10-13 11:04:26 +0200139}
140
Jon Maloy38266ca2018-01-04 15:20:44 +0100141static bool tipc_group_is_sender(struct tipc_member *m)
Jon Maloy75da2162017-10-13 11:04:23 +0200142{
Jon Maloyd12d2e12018-01-08 21:03:28 +0100143 return m && m->state != MBR_JOINING && m->state != MBR_PUBLISHED;
Jon Maloy75da2162017-10-13 11:04:23 +0200144}
145
Jon Maloyee106d72017-10-13 11:04:28 +0200146u32 tipc_group_exclude(struct tipc_group *grp)
147{
148 if (!grp->loopback)
149 return grp->portid;
150 return 0;
151}
152
Jon Maloy75da2162017-10-13 11:04:23 +0200153int tipc_group_size(struct tipc_group *grp)
154{
155 return grp->member_cnt;
156}
157
158struct tipc_group *tipc_group_create(struct net *net, u32 portid,
159 struct tipc_group_req *mreq)
160{
161 struct tipc_group *grp;
162 u32 type = mreq->type;
163
164 grp = kzalloc(sizeof(*grp), GFP_ATOMIC);
165 if (!grp)
166 return NULL;
167 tipc_nlist_init(&grp->dests, tipc_own_addr(net));
Jon Maloy38266ca2018-01-04 15:20:44 +0100168 INIT_LIST_HEAD(&grp->small_win);
Jon Maloy04d7b572017-10-13 11:04:34 +0200169 INIT_LIST_HEAD(&grp->active);
170 INIT_LIST_HEAD(&grp->pending);
Jon Maloy75da2162017-10-13 11:04:23 +0200171 grp->members = RB_ROOT;
172 grp->net = net;
173 grp->portid = portid;
174 grp->domain = addr_domain(net, mreq->scope);
175 grp->type = type;
176 grp->instance = mreq->instance;
177 grp->scope = mreq->scope;
178 grp->loopback = mreq->flags & TIPC_GROUP_LOOPBACK;
Jon Maloyae236fb2017-10-13 11:04:25 +0200179 grp->events = mreq->flags & TIPC_GROUP_MEMBER_EVTS;
Jon Maloy75da2162017-10-13 11:04:23 +0200180 if (tipc_topsrv_kern_subscr(net, portid, type, 0, ~0, &grp->subid))
181 return grp;
182 kfree(grp);
183 return NULL;
184}
185
Jon Maloyd12d2e12018-01-08 21:03:28 +0100186void 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
Jon Maloy75da2162017-10-13 11:04:23 +0200201void tipc_group_delete(struct net *net, struct tipc_group *grp)
202{
203 struct rb_root *tree = &grp->members;
204 struct tipc_member *m, *tmp;
205 struct sk_buff_head xmitq;
206
207 __skb_queue_head_init(&xmitq);
208
209 rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
210 tipc_group_proto_xmit(grp, m, GRP_LEAVE_MSG, &xmitq);
211 list_del(&m->list);
212 kfree(m);
213 }
214 tipc_node_distr_xmit(net, &xmitq);
215 tipc_nlist_purge(&grp->dests);
216 tipc_topsrv_kern_unsubscr(net, grp->subid);
217 kfree(grp);
218}
219
220struct tipc_member *tipc_group_find_member(struct tipc_group *grp,
221 u32 node, u32 port)
222{
223 struct rb_node *n = grp->members.rb_node;
224 u64 nkey, key = (u64)node << 32 | port;
225 struct tipc_member *m;
226
227 while (n) {
228 m = container_of(n, struct tipc_member, tree_node);
229 nkey = (u64)m->node << 32 | m->port;
230 if (key < nkey)
231 n = n->rb_left;
232 else if (key > nkey)
233 n = n->rb_right;
234 else
235 return m;
236 }
237 return NULL;
238}
239
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200240static struct tipc_member *tipc_group_find_dest(struct tipc_group *grp,
241 u32 node, u32 port)
242{
243 struct tipc_member *m;
244
245 m = tipc_group_find_member(grp, node, port);
Jon Maloy38266ca2018-01-04 15:20:44 +0100246 if (m && tipc_group_is_receiver(m))
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200247 return m;
248 return NULL;
249}
250
Jon Maloy75da2162017-10-13 11:04:23 +0200251static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
252 u32 node)
253{
254 struct tipc_member *m;
255 struct rb_node *n;
256
257 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
258 m = container_of(n, struct tipc_member, tree_node);
259 if (m->node == node)
260 return m;
261 }
262 return NULL;
263}
264
265static void tipc_group_add_to_tree(struct tipc_group *grp,
266 struct tipc_member *m)
267{
268 u64 nkey, key = (u64)m->node << 32 | m->port;
269 struct rb_node **n, *parent = NULL;
270 struct tipc_member *tmp;
271
272 n = &grp->members.rb_node;
273 while (*n) {
274 tmp = container_of(*n, struct tipc_member, tree_node);
275 parent = *n;
276 tmp = container_of(parent, struct tipc_member, tree_node);
277 nkey = (u64)tmp->node << 32 | tmp->port;
278 if (key < nkey)
279 n = &(*n)->rb_left;
280 else if (key > nkey)
281 n = &(*n)->rb_right;
282 else
283 return;
284 }
285 rb_link_node(&m->tree_node, parent, n);
286 rb_insert_color(&m->tree_node, &grp->members);
287}
288
289static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
290 u32 node, u32 port,
Jon Maloyd12d2e12018-01-08 21:03:28 +0100291 u32 instance, int state)
Jon Maloy75da2162017-10-13 11:04:23 +0200292{
293 struct tipc_member *m;
294
295 m = kzalloc(sizeof(*m), GFP_ATOMIC);
296 if (!m)
297 return NULL;
298 INIT_LIST_HEAD(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100299 INIT_LIST_HEAD(&m->small_win);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200300 __skb_queue_head_init(&m->deferredq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200301 m->group = grp;
Jon Maloy75da2162017-10-13 11:04:23 +0200302 m->node = node;
303 m->port = port;
Jon Maloyd12d2e12018-01-08 21:03:28 +0100304 m->instance = instance;
Jon Maloy2f487712017-10-13 11:04:31 +0200305 m->bc_acked = grp->bc_snd_nxt - 1;
Jon Maloy75da2162017-10-13 11:04:23 +0200306 grp->member_cnt++;
307 tipc_group_add_to_tree(grp, m);
308 tipc_nlist_add(&grp->dests, m->node);
309 m->state = state;
310 return m;
311}
312
Jon Maloyd12d2e12018-01-08 21:03:28 +0100313void tipc_group_add_member(struct tipc_group *grp, u32 node,
314 u32 port, u32 instance)
Jon Maloy75da2162017-10-13 11:04:23 +0200315{
Jon Maloyd12d2e12018-01-08 21:03:28 +0100316 tipc_group_create_member(grp, node, port, instance, MBR_PUBLISHED);
Jon Maloy75da2162017-10-13 11:04:23 +0200317}
318
319static void tipc_group_delete_member(struct tipc_group *grp,
320 struct tipc_member *m)
321{
322 rb_erase(&m->tree_node, &grp->members);
323 grp->member_cnt--;
Jon Maloy2f487712017-10-13 11:04:31 +0200324
325 /* Check if we were waiting for replicast ack from this member */
326 if (grp->bc_ackers && less(m->bc_acked, grp->bc_snd_nxt - 1))
327 grp->bc_ackers--;
328
Jon Maloy75da2162017-10-13 11:04:23 +0200329 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100330 list_del_init(&m->small_win);
Jon Maloy04d7b572017-10-13 11:04:34 +0200331 tipc_group_decr_active(grp, m);
Jon Maloy75da2162017-10-13 11:04:23 +0200332
333 /* If last member on a node, remove node from dest list */
334 if (!tipc_group_find_node(grp, m->node))
335 tipc_nlist_del(&grp->dests, m->node);
336
337 kfree(m);
338}
339
340struct tipc_nlist *tipc_group_dests(struct tipc_group *grp)
341{
342 return &grp->dests;
343}
344
345void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
346 int *scope)
347{
348 seq->type = grp->type;
349 seq->lower = grp->instance;
350 seq->upper = grp->instance;
351 *scope = grp->scope;
352}
353
Jon Maloyb7d42632017-10-13 11:04:26 +0200354void tipc_group_update_member(struct tipc_member *m, int len)
Jon Maloy75da2162017-10-13 11:04:23 +0200355{
Jon Maloyb7d42632017-10-13 11:04:26 +0200356 struct tipc_group *grp = m->group;
357 struct tipc_member *_m, *tmp;
358
Jon Maloy38266ca2018-01-04 15:20:44 +0100359 if (!tipc_group_is_receiver(m))
Jon Maloyb7d42632017-10-13 11:04:26 +0200360 return;
361
362 m->window -= len;
363
364 if (m->window >= ADV_IDLE)
365 return;
366
Jon Maloy38266ca2018-01-04 15:20:44 +0100367 list_del_init(&m->small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200368
Jon Maloy38266ca2018-01-04 15:20:44 +0100369 /* Sort member into small_window members' list */
370 list_for_each_entry_safe(_m, tmp, &grp->small_win, small_win) {
Jon Maloyd84d1b32018-01-04 15:20:45 +0100371 if (_m->window > m->window)
372 break;
Jon Maloyb7d42632017-10-13 11:04:26 +0200373 }
Jon Maloyd84d1b32018-01-04 15:20:45 +0100374 list_add_tail(&m->small_win, &_m->small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200375}
376
Jon Maloy2f487712017-10-13 11:04:31 +0200377void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack)
Jon Maloyb7d42632017-10-13 11:04:26 +0200378{
Jon Maloy2f487712017-10-13 11:04:31 +0200379 u16 prev = grp->bc_snd_nxt - 1;
Jon Maloyb7d42632017-10-13 11:04:26 +0200380 struct tipc_member *m;
381 struct rb_node *n;
Jon Maloy0a3d8052017-12-21 13:07:11 +0100382 u16 ackers = 0;
Jon Maloyb7d42632017-10-13 11:04:26 +0200383
384 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
385 m = container_of(n, struct tipc_member, tree_node);
Jon Maloy38266ca2018-01-04 15:20:44 +0100386 if (tipc_group_is_receiver(m)) {
Jon Maloyb7d42632017-10-13 11:04:26 +0200387 tipc_group_update_member(m, len);
Jon Maloy2f487712017-10-13 11:04:31 +0200388 m->bc_acked = prev;
Jon Maloy0a3d8052017-12-21 13:07:11 +0100389 ackers++;
Jon Maloy2f487712017-10-13 11:04:31 +0200390 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200391 }
Jon Maloy2f487712017-10-13 11:04:31 +0200392
393 /* Mark number of acknowledges to expect, if any */
394 if (ack)
Jon Maloy0a3d8052017-12-21 13:07:11 +0100395 grp->bc_ackers = ackers;
Jon Maloy75da2162017-10-13 11:04:23 +0200396 grp->bc_snd_nxt++;
397}
398
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200399bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
400 int len, struct tipc_member **mbr)
401{
402 struct sk_buff_head xmitq;
403 struct tipc_member *m;
404 int adv, state;
405
406 m = tipc_group_find_dest(grp, dnode, dport);
407 *mbr = m;
408 if (!m)
409 return false;
410 if (m->usr_pending)
411 return true;
412 if (m->window >= len)
413 return false;
414 m->usr_pending = true;
415
416 /* If not fully advertised, do it now to prevent mutual blocking */
417 adv = m->advertised;
418 state = m->state;
419 if (state < MBR_JOINED)
420 return true;
421 if (state == MBR_JOINED && adv == ADV_IDLE)
422 return true;
Jon Maloy04d7b572017-10-13 11:04:34 +0200423 if (state == MBR_ACTIVE && adv == ADV_ACTIVE)
424 return true;
425 if (state == MBR_PENDING && adv == ADV_IDLE)
426 return true;
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200427 skb_queue_head_init(&xmitq);
428 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, &xmitq);
429 tipc_node_distr_xmit(grp->net, &xmitq);
430 return true;
431}
432
Jon Maloyb7d42632017-10-13 11:04:26 +0200433bool tipc_group_bc_cong(struct tipc_group *grp, int len)
434{
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200435 struct tipc_member *m = NULL;
Jon Maloyb7d42632017-10-13 11:04:26 +0200436
Jon Maloy2f487712017-10-13 11:04:31 +0200437 /* If prev bcast was replicast, reject until all receivers have acked */
438 if (grp->bc_ackers)
439 return true;
440
Jon Maloy38266ca2018-01-04 15:20:44 +0100441 if (list_empty(&grp->small_win))
Jon Maloyb7d42632017-10-13 11:04:26 +0200442 return false;
443
Jon Maloy38266ca2018-01-04 15:20:44 +0100444 m = list_first_entry(&grp->small_win, struct tipc_member, small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200445 if (m->window >= len)
446 return false;
447
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200448 return tipc_group_cong(grp, m->node, m->port, len, &m);
Jon Maloyb7d42632017-10-13 11:04:26 +0200449}
450
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200451/* tipc_group_sort_msg() - sort msg into queue by bcast sequence number
452 */
453static void tipc_group_sort_msg(struct sk_buff *skb, struct sk_buff_head *defq)
454{
455 struct tipc_msg *_hdr, *hdr = buf_msg(skb);
456 u16 bc_seqno = msg_grp_bc_seqno(hdr);
457 struct sk_buff *_skb, *tmp;
458 int mtyp = msg_type(hdr);
459
Jon Maloya3bada72017-10-13 11:04:33 +0200460 /* Bcast/mcast may be bypassed by ucast or other bcast, - sort it in */
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200461 if (mtyp == TIPC_GRP_BCAST_MSG || mtyp == TIPC_GRP_MCAST_MSG) {
462 skb_queue_walk_safe(defq, _skb, tmp) {
463 _hdr = buf_msg(_skb);
464 if (!less(bc_seqno, msg_grp_bc_seqno(_hdr)))
465 continue;
466 __skb_queue_before(defq, _skb, skb);
467 return;
468 }
469 /* Bcast was not bypassed, - add to tail */
470 }
471 /* Unicasts are never bypassed, - always add to tail */
472 __skb_queue_tail(defq, skb);
473}
474
Jon Maloy75da2162017-10-13 11:04:23 +0200475/* tipc_group_filter_msg() - determine if we should accept arriving message
476 */
477void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
478 struct sk_buff_head *xmitq)
479{
480 struct sk_buff *skb = __skb_dequeue(inputq);
Jon Maloya3bada72017-10-13 11:04:33 +0200481 bool ack, deliver, update, leave = false;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200482 struct sk_buff_head *defq;
Jon Maloy75da2162017-10-13 11:04:23 +0200483 struct tipc_member *m;
484 struct tipc_msg *hdr;
485 u32 node, port;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200486 int mtyp, blks;
Jon Maloy75da2162017-10-13 11:04:23 +0200487
488 if (!skb)
489 return;
490
491 hdr = buf_msg(skb);
Jon Maloy75da2162017-10-13 11:04:23 +0200492 node = msg_orignode(hdr);
493 port = msg_origport(hdr);
494
495 if (!msg_in_group(hdr))
496 goto drop;
497
498 m = tipc_group_find_member(grp, node, port);
Jon Maloy38266ca2018-01-04 15:20:44 +0100499 if (!tipc_group_is_sender(m))
Jon Maloy75da2162017-10-13 11:04:23 +0200500 goto drop;
501
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200502 if (less(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
503 goto drop;
Jon Maloy5b8dddb2017-10-13 11:04:29 +0200504
Jon Maloy31c82a22017-10-13 11:04:24 +0200505 TIPC_SKB_CB(skb)->orig_member = m->instance;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200506 defq = &m->deferredq;
507 tipc_group_sort_msg(skb, defq);
Jon Maloy75da2162017-10-13 11:04:23 +0200508
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200509 while ((skb = skb_peek(defq))) {
510 hdr = buf_msg(skb);
511 mtyp = msg_type(hdr);
Jon Maloy2e724dc2017-11-27 20:13:39 +0100512 blks = msg_blocks(hdr);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200513 deliver = true;
Jon Maloy2f487712017-10-13 11:04:31 +0200514 ack = false;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200515 update = false;
516
517 if (more(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
518 break;
519
520 /* Decide what to do with message */
521 switch (mtyp) {
522 case TIPC_GRP_MCAST_MSG:
523 if (msg_nameinst(hdr) != grp->instance) {
524 update = true;
525 deliver = false;
526 }
527 /* Fall thru */
528 case TIPC_GRP_BCAST_MSG:
529 m->bc_rcv_nxt++;
Jon Maloy2f487712017-10-13 11:04:31 +0200530 ack = msg_grp_bc_ack_req(hdr);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200531 break;
532 case TIPC_GRP_UCAST_MSG:
533 break;
Jon Maloya3bada72017-10-13 11:04:33 +0200534 case TIPC_GRP_MEMBER_EVT:
535 if (m->state == MBR_LEAVING)
536 leave = true;
537 if (!grp->events)
538 deliver = false;
539 break;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200540 default:
541 break;
542 }
543
544 /* Execute decisions */
545 __skb_dequeue(defq);
546 if (deliver)
547 __skb_queue_tail(inputq, skb);
548 else
549 kfree_skb(skb);
550
Jon Maloy2f487712017-10-13 11:04:31 +0200551 if (ack)
552 tipc_group_proto_xmit(grp, m, GRP_ACK_MSG, xmitq);
553
Jon Maloya3bada72017-10-13 11:04:33 +0200554 if (leave) {
Jon Maloya3bada72017-10-13 11:04:33 +0200555 __skb_queue_purge(defq);
Jon Maloye0e853a2017-11-20 21:43:03 +0100556 tipc_group_delete_member(grp, m);
Jon Maloya3bada72017-10-13 11:04:33 +0200557 break;
558 }
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200559 if (!update)
560 continue;
561
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200562 tipc_group_update_rcv_win(grp, blks, node, port, xmitq);
563 }
Jon Maloy75da2162017-10-13 11:04:23 +0200564 return;
565drop:
566 kfree_skb(skb);
567}
568
Jon Maloyb7d42632017-10-13 11:04:26 +0200569void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
570 u32 port, struct sk_buff_head *xmitq)
571{
Jon Maloy04d7b572017-10-13 11:04:34 +0200572 struct list_head *active = &grp->active;
573 int max_active = grp->max_active;
574 int reclaim_limit = max_active * 3 / 4;
575 int active_cnt = grp->active_cnt;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100576 struct tipc_member *m, *rm, *pm;
Jon Maloyb7d42632017-10-13 11:04:26 +0200577
578 m = tipc_group_find_member(grp, node, port);
579 if (!m)
580 return;
581
582 m->advertised -= blks;
583
584 switch (m->state) {
585 case MBR_JOINED:
Jon Maloy4ea5dab2018-01-08 21:03:24 +0100586 /* First, decide if member can go active */
587 if (active_cnt <= max_active) {
588 m->state = MBR_ACTIVE;
589 list_add_tail(&m->list, active);
590 grp->active_cnt++;
591 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
592 } else {
593 m->state = MBR_PENDING;
594 list_add_tail(&m->list, &grp->pending);
595 }
596
597 if (active_cnt < reclaim_limit)
598 break;
599
600 /* Reclaim from oldest active member, if possible */
601 if (!list_empty(active)) {
Jon Maloy04d7b572017-10-13 11:04:34 +0200602 rm = list_first_entry(active, struct tipc_member, list);
603 rm->state = MBR_RECLAIMING;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100604 list_del_init(&rm->list);
Jon Maloy04d7b572017-10-13 11:04:34 +0200605 tipc_group_proto_xmit(grp, rm, GRP_RECLAIM_MSG, xmitq);
Jon Maloy04d7b572017-10-13 11:04:34 +0200606 break;
607 }
Jon Maloy4ea5dab2018-01-08 21:03:24 +0100608 /* Nobody to reclaim from; - revert oldest pending to JOINED */
609 pm = list_first_entry(&grp->pending, struct tipc_member, list);
610 list_del_init(&pm->list);
611 pm->state = MBR_JOINED;
612 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
613 break;
Jon Maloy04d7b572017-10-13 11:04:34 +0200614 case MBR_ACTIVE:
615 if (!list_is_last(&m->list, &grp->active))
616 list_move_tail(&m->list, &grp->active);
617 if (m->advertised > (ADV_ACTIVE * 3 / 4))
618 break;
619 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200620 break;
Jon Maloy04d7b572017-10-13 11:04:34 +0200621 case MBR_REMITTED:
622 if (m->advertised > ADV_IDLE)
623 break;
624 m->state = MBR_JOINED;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100625 grp->active_cnt--;
Jon Maloy04d7b572017-10-13 11:04:34 +0200626 if (m->advertised < ADV_IDLE) {
627 pr_warn_ratelimited("Rcv unexpected msg after REMIT\n");
628 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
629 }
Jon Maloy8d5dee22018-01-08 21:03:23 +0100630
Jon Maloyf9c935d2017-12-29 19:48:02 +0100631 if (list_empty(&grp->pending))
632 return;
633
634 /* Set oldest pending member to active and advertise */
635 pm = list_first_entry(&grp->pending, struct tipc_member, list);
636 pm->state = MBR_ACTIVE;
637 list_move_tail(&pm->list, &grp->active);
638 grp->active_cnt++;
639 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
Jon Maloy04d7b572017-10-13 11:04:34 +0200640 break;
641 case MBR_RECLAIMING:
Jon Maloyb7d42632017-10-13 11:04:26 +0200642 case MBR_JOINING:
643 case MBR_LEAVING:
644 default:
645 break;
646 }
647}
648
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100649static void tipc_group_create_event(struct tipc_group *grp,
650 struct tipc_member *m,
651 u32 event, u16 seqno,
652 struct sk_buff_head *inputq)
653{ u32 dnode = tipc_own_addr(grp->net);
654 struct tipc_event evt;
655 struct sk_buff *skb;
656 struct tipc_msg *hdr;
657
658 evt.event = event;
659 evt.found_lower = m->instance;
660 evt.found_upper = m->instance;
661 evt.port.ref = m->port;
662 evt.port.node = m->node;
663 evt.s.seq.type = grp->type;
664 evt.s.seq.lower = m->instance;
665 evt.s.seq.upper = m->instance;
666
667 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_GRP_MEMBER_EVT,
668 GROUP_H_SIZE, sizeof(evt), dnode, m->node,
669 grp->portid, m->port, 0);
670 if (!skb)
671 return;
672
673 hdr = buf_msg(skb);
674 msg_set_nametype(hdr, grp->type);
675 msg_set_grp_evt(hdr, event);
676 msg_set_dest_droppable(hdr, true);
677 msg_set_grp_bc_seqno(hdr, seqno);
678 memcpy(msg_data(hdr), &evt, sizeof(evt));
679 TIPC_SKB_CB(skb)->orig_member = m->instance;
680 __skb_queue_tail(inputq, skb);
681}
682
Jon Maloy75da2162017-10-13 11:04:23 +0200683static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
684 int mtyp, struct sk_buff_head *xmitq)
685{
686 struct tipc_msg *hdr;
687 struct sk_buff *skb;
Jon Maloyb7d42632017-10-13 11:04:26 +0200688 int adv = 0;
Jon Maloy75da2162017-10-13 11:04:23 +0200689
690 skb = tipc_msg_create(GROUP_PROTOCOL, mtyp, INT_H_SIZE, 0,
691 m->node, tipc_own_addr(grp->net),
692 m->port, grp->portid, 0);
693 if (!skb)
694 return;
695
Jon Maloy04d7b572017-10-13 11:04:34 +0200696 if (m->state == MBR_ACTIVE)
Jon Maloyb7d42632017-10-13 11:04:26 +0200697 adv = ADV_ACTIVE - m->advertised;
Jon Maloy04d7b572017-10-13 11:04:34 +0200698 else if (m->state == MBR_JOINED || m->state == MBR_PENDING)
699 adv = ADV_IDLE - m->advertised;
Jon Maloyb7d42632017-10-13 11:04:26 +0200700
Jon Maloy75da2162017-10-13 11:04:23 +0200701 hdr = buf_msg(skb);
Jon Maloyb7d42632017-10-13 11:04:26 +0200702
703 if (mtyp == GRP_JOIN_MSG) {
Jon Maloy75da2162017-10-13 11:04:23 +0200704 msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
Jon Maloyb7d42632017-10-13 11:04:26 +0200705 msg_set_adv_win(hdr, adv);
706 m->advertised += adv;
Jon Maloya3bada72017-10-13 11:04:33 +0200707 } else if (mtyp == GRP_LEAVE_MSG) {
708 msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
Jon Maloyb7d42632017-10-13 11:04:26 +0200709 } else if (mtyp == GRP_ADV_MSG) {
710 msg_set_adv_win(hdr, adv);
711 m->advertised += adv;
Jon Maloy2f487712017-10-13 11:04:31 +0200712 } else if (mtyp == GRP_ACK_MSG) {
713 msg_set_grp_bc_acked(hdr, m->bc_rcv_nxt);
Jon Maloy04d7b572017-10-13 11:04:34 +0200714 } else if (mtyp == GRP_REMIT_MSG) {
715 msg_set_grp_remitted(hdr, m->window);
Jon Maloyb7d42632017-10-13 11:04:26 +0200716 }
Jon Maloy23483392017-12-18 17:34:16 +0100717 msg_set_dest_droppable(hdr, true);
Jon Maloy75da2162017-10-13 11:04:23 +0200718 __skb_queue_tail(xmitq, skb);
719}
720
Jon Maloyb7d42632017-10-13 11:04:26 +0200721void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
722 struct tipc_msg *hdr, struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200723 struct sk_buff_head *xmitq)
724{
725 u32 node = msg_orignode(hdr);
726 u32 port = msg_origport(hdr);
Jon Maloy04d7b572017-10-13 11:04:34 +0200727 struct tipc_member *m, *pm;
Jon Maloy04d7b572017-10-13 11:04:34 +0200728 u16 remitted, in_flight;
Jon Maloy75da2162017-10-13 11:04:23 +0200729
730 if (!grp)
731 return;
732
733 m = tipc_group_find_member(grp, node, port);
734
735 switch (msg_type(hdr)) {
736 case GRP_JOIN_MSG:
737 if (!m)
738 m = tipc_group_create_member(grp, node, port,
Jon Maloyd12d2e12018-01-08 21:03:28 +0100739 0, MBR_JOINING);
Jon Maloy75da2162017-10-13 11:04:23 +0200740 if (!m)
741 return;
Jon Maloya3bada72017-10-13 11:04:33 +0200742 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
743 m->bc_rcv_nxt = m->bc_syncpt;
Jon Maloyb7d42632017-10-13 11:04:26 +0200744 m->window += msg_adv_win(hdr);
Jon Maloy75da2162017-10-13 11:04:23 +0200745
Jon Maloyd12d2e12018-01-08 21:03:28 +0100746 /* 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;
Jon Maloy38266ca2018-01-04 15:20:44 +0100754 list_del_init(&m->small_win);
Jon Maloybb25c382017-12-20 11:03:15 +0100755 tipc_group_update_member(m, 0);
Jon Maloyd12d2e12018-01-08 21:03:28 +0100756 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
757 tipc_group_create_event(grp, m, TIPC_PUBLISHED,
758 m->bc_syncpt, inputq);
Jon Maloy75da2162017-10-13 11:04:23 +0200759 return;
760 case GRP_LEAVE_MSG:
761 if (!m)
762 return;
Jon Maloya3bada72017-10-13 11:04:33 +0200763 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100764 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100765 list_del_init(&m->small_win);
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100766 *usr_wakeup = true;
Jon Maloyc2b22bc2018-01-08 21:03:27 +0100767 tipc_group_decr_active(grp, m);
768 m->state = MBR_LEAVING;
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100769 tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
770 m->bc_syncpt, inputq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200771 return;
772 case GRP_ADV_MSG:
773 if (!m)
774 return;
775 m->window += msg_adv_win(hdr);
776 *usr_wakeup = m->usr_pending;
777 m->usr_pending = false;
Jon Maloy38266ca2018-01-04 15:20:44 +0100778 list_del_init(&m->small_win);
Jon Maloy75da2162017-10-13 11:04:23 +0200779 return;
Jon Maloy2f487712017-10-13 11:04:31 +0200780 case GRP_ACK_MSG:
781 if (!m)
782 return;
783 m->bc_acked = msg_grp_bc_acked(hdr);
784 if (--grp->bc_ackers)
785 break;
786 *usr_wakeup = true;
787 m->usr_pending = false;
788 return;
Jon Maloy04d7b572017-10-13 11:04:34 +0200789 case GRP_RECLAIM_MSG:
790 if (!m)
791 return;
792 *usr_wakeup = m->usr_pending;
793 m->usr_pending = false;
794 tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq);
795 m->window = ADV_IDLE;
796 return;
797 case GRP_REMIT_MSG:
798 if (!m || m->state != MBR_RECLAIMING)
799 return;
800
Jon Maloy04d7b572017-10-13 11:04:34 +0200801 remitted = msg_grp_remitted(hdr);
802
803 /* Messages preceding the REMIT still in receive queue */
804 if (m->advertised > remitted) {
805 m->state = MBR_REMITTED;
806 in_flight = m->advertised - remitted;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100807 m->advertised = ADV_IDLE + in_flight;
808 return;
Jon Maloy04d7b572017-10-13 11:04:34 +0200809 }
Jon Maloy8d5dee22018-01-08 21:03:23 +0100810 /* This should never happen */
Jon Maloy04d7b572017-10-13 11:04:34 +0200811 if (m->advertised < remitted)
Jon Maloy8d5dee22018-01-08 21:03:23 +0100812 pr_warn_ratelimited("Unexpected REMIT msg\n");
Jon Maloy04d7b572017-10-13 11:04:34 +0200813
Jon Maloy8d5dee22018-01-08 21:03:23 +0100814 /* All messages preceding the REMIT have been read */
815 m->state = MBR_JOINED;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100816 grp->active_cnt--;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100817 m->advertised = ADV_IDLE;
Jon Maloy04d7b572017-10-13 11:04:34 +0200818
819 /* Set oldest pending member to active and advertise */
820 if (list_empty(&grp->pending))
821 return;
822 pm = list_first_entry(&grp->pending, struct tipc_member, list);
823 pm->state = MBR_ACTIVE;
824 list_move_tail(&pm->list, &grp->active);
825 grp->active_cnt++;
826 if (pm->advertised <= (ADV_ACTIVE * 3 / 4))
827 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
828 return;
Jon Maloy75da2162017-10-13 11:04:23 +0200829 default:
830 pr_warn("Received unknown GROUP_PROTO message\n");
831 }
832}
833
Jon Maloyb7d42632017-10-13 11:04:26 +0200834/* tipc_group_member_evt() - receive and handle a member up/down event
835 */
Jon Maloy75da2162017-10-13 11:04:23 +0200836void tipc_group_member_evt(struct tipc_group *grp,
Jon Maloyb7d42632017-10-13 11:04:26 +0200837 bool *usr_wakeup,
838 int *sk_rcvbuf,
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100839 struct tipc_msg *hdr,
Jon Maloyae236fb2017-10-13 11:04:25 +0200840 struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200841 struct sk_buff_head *xmitq)
842{
Jon Maloy75da2162017-10-13 11:04:23 +0200843 struct tipc_event *evt = (void *)msg_data(hdr);
Jon Maloyae236fb2017-10-13 11:04:25 +0200844 u32 instance = evt->found_lower;
Jon Maloy75da2162017-10-13 11:04:23 +0200845 u32 node = evt->port.node;
846 u32 port = evt->port.ref;
Jon Maloyae236fb2017-10-13 11:04:25 +0200847 int event = evt->event;
Jon Maloy75da2162017-10-13 11:04:23 +0200848 struct tipc_member *m;
849 struct net *net;
850 u32 self;
851
852 if (!grp)
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100853 return;
Jon Maloy75da2162017-10-13 11:04:23 +0200854
855 net = grp->net;
856 self = tipc_own_addr(net);
857 if (!grp->loopback && node == self && port == grp->portid)
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100858 return;
Jon Maloyae236fb2017-10-13 11:04:25 +0200859
Jon Maloy75da2162017-10-13 11:04:23 +0200860 m = tipc_group_find_member(grp, node, port);
861
Jon Maloyd12d2e12018-01-08 21:03:28 +0100862 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;
Jon Maloyae236fb2017-10-13 11:04:25 +0200873 }
Jon Maloyd12d2e12018-01-08 21:03:28 +0100874
875 if (m->state != MBR_JOINING)
876 break;
877
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);
Jon Maloyd84d1b32018-01-04 15:20:45 +0100884 tipc_group_update_member(m, 0);
Jon Maloyd12d2e12018-01-08 21:03:28 +0100885 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:
Jon Maloy75da2162017-10-13 11:04:23 +0200890 if (!m)
Jon Maloyd12d2e12018-01-08 21:03:28 +0100891 break;
Jon Maloyae236fb2017-10-13 11:04:25 +0200892
Jon Maloy2f487712017-10-13 11:04:31 +0200893 *usr_wakeup = true;
Jon Maloyb7d42632017-10-13 11:04:26 +0200894 m->usr_pending = false;
Jon Maloyc2b22bc2018-01-08 21:03:27 +0100895 tipc_group_decr_active(grp, m);
896 m->state = MBR_LEAVING;
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100897 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100898 list_del_init(&m->small_win);
Jon Maloyc2b22bc2018-01-08 21:03:27 +0100899
900 /* Only send event if no LEAVE message can be expected */
901 if (!tipc_node_is_up(net, node))
902 tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
903 m->bc_rcv_nxt, inputq);
Jon Maloyd12d2e12018-01-08 21:03:28 +0100904 break;
905 default:
906 break;
Jon Maloy75da2162017-10-13 11:04:23 +0200907 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200908 *sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
Jon Maloy75da2162017-10-13 11:04:23 +0200909}