blob: a352e098f0e757b42ba06b0c7e50af19f6d212e4 [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_DISCOVERED,
53 MBR_JOINING,
54 MBR_PUBLISHED,
55 MBR_JOINED,
Jon Maloy04d7b572017-10-13 11:04:34 +020056 MBR_PENDING,
57 MBR_ACTIVE,
58 MBR_RECLAIMING,
59 MBR_REMITTED,
Jon Maloy75da2162017-10-13 11:04:23 +020060 MBR_LEAVING
61};
62
63struct tipc_member {
64 struct rb_node tree_node;
65 struct list_head list;
Jon Maloy38266ca2018-01-04 15:20:44 +010066 struct list_head small_win;
Jon Maloyae236fb2017-10-13 11:04:25 +020067 struct sk_buff *event_msg;
Jon Maloyb87a5ea2017-10-13 11:04:30 +020068 struct sk_buff_head deferredq;
Jon Maloyb7d42632017-10-13 11:04:26 +020069 struct tipc_group *group;
Jon Maloy75da2162017-10-13 11:04:23 +020070 u32 node;
71 u32 port;
Jon Maloy31c82a22017-10-13 11:04:24 +020072 u32 instance;
Jon Maloy75da2162017-10-13 11:04:23 +020073 enum mbr_state state;
Jon Maloyb7d42632017-10-13 11:04:26 +020074 u16 advertised;
75 u16 window;
Jon Maloy75da2162017-10-13 11:04:23 +020076 u16 bc_rcv_nxt;
Jon Maloya3bada72017-10-13 11:04:33 +020077 u16 bc_syncpt;
Jon Maloy2f487712017-10-13 11:04:31 +020078 u16 bc_acked;
Jon Maloyb7d42632017-10-13 11:04:26 +020079 bool usr_pending;
Jon Maloy75da2162017-10-13 11:04:23 +020080};
81
82struct tipc_group {
83 struct rb_root members;
Jon Maloy38266ca2018-01-04 15:20:44 +010084 struct list_head small_win;
Jon Maloy04d7b572017-10-13 11:04:34 +020085 struct list_head pending;
86 struct list_head active;
Jon Maloy75da2162017-10-13 11:04:23 +020087 struct tipc_nlist dests;
88 struct net *net;
89 int subid;
90 u32 type;
91 u32 instance;
92 u32 domain;
93 u32 scope;
94 u32 portid;
95 u16 member_cnt;
Jon Maloy04d7b572017-10-13 11:04:34 +020096 u16 active_cnt;
97 u16 max_active;
Jon Maloy75da2162017-10-13 11:04:23 +020098 u16 bc_snd_nxt;
Jon Maloy2f487712017-10-13 11:04:31 +020099 u16 bc_ackers;
Jon Maloy75da2162017-10-13 11:04:23 +0200100 bool loopback;
Jon Maloyae236fb2017-10-13 11:04:25 +0200101 bool events;
Jon Maloy75da2162017-10-13 11:04:23 +0200102};
103
104static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
105 int mtyp, struct sk_buff_head *xmitq);
106
Jon Maloy04d7b572017-10-13 11:04:34 +0200107static void tipc_group_decr_active(struct tipc_group *grp,
108 struct tipc_member *m)
109{
Jon Maloyf9c935d2017-12-29 19:48:02 +0100110 if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING ||
111 m->state == MBR_REMITTED)
Jon Maloy04d7b572017-10-13 11:04:34 +0200112 grp->active_cnt--;
113}
114
Jon Maloyb7d42632017-10-13 11:04:26 +0200115static int tipc_group_rcvbuf_limit(struct tipc_group *grp)
116{
Jon Maloy04d7b572017-10-13 11:04:34 +0200117 int max_active, active_pool, idle_pool;
Jon Maloyb7d42632017-10-13 11:04:26 +0200118 int mcnt = grp->member_cnt + 1;
119
Jon Maloy04d7b572017-10-13 11:04:34 +0200120 /* Limit simultaneous reception from other members */
121 max_active = min(mcnt / 8, 64);
122 max_active = max(max_active, 16);
123 grp->max_active = max_active;
124
125 /* Reserve blocks for active and idle members */
126 active_pool = max_active * ADV_ACTIVE;
127 idle_pool = (mcnt - max_active) * ADV_IDLE;
128
Jon Maloyb7d42632017-10-13 11:04:26 +0200129 /* Scale to bytes, considering worst-case truesize/msgsize ratio */
Jon Maloy04d7b572017-10-13 11:04:34 +0200130 return (active_pool + idle_pool) * FLOWCTL_BLK_SZ * 4;
Jon Maloyb7d42632017-10-13 11:04:26 +0200131}
132
Jon Maloy75da2162017-10-13 11:04:23 +0200133u16 tipc_group_bc_snd_nxt(struct tipc_group *grp)
134{
135 return grp->bc_snd_nxt;
136}
137
Jon Maloy38266ca2018-01-04 15:20:44 +0100138static bool tipc_group_is_receiver(struct tipc_member *m)
Jon Maloyb7d42632017-10-13 11:04:26 +0200139{
Jon Maloy02334932018-01-08 21:03:25 +0100140 return m && m->state != MBR_JOINING && m->state != MBR_LEAVING;
Jon Maloyb7d42632017-10-13 11:04:26 +0200141}
142
Jon Maloy38266ca2018-01-04 15:20:44 +0100143static bool tipc_group_is_sender(struct tipc_member *m)
Jon Maloy75da2162017-10-13 11:04:23 +0200144{
145 return m && m->state >= MBR_JOINED;
146}
147
Jon Maloyee106d72017-10-13 11:04:28 +0200148u32 tipc_group_exclude(struct tipc_group *grp)
149{
150 if (!grp->loopback)
151 return grp->portid;
152 return 0;
153}
154
Jon Maloy75da2162017-10-13 11:04:23 +0200155int tipc_group_size(struct tipc_group *grp)
156{
157 return grp->member_cnt;
158}
159
160struct tipc_group *tipc_group_create(struct net *net, u32 portid,
161 struct tipc_group_req *mreq)
162{
163 struct tipc_group *grp;
164 u32 type = mreq->type;
165
166 grp = kzalloc(sizeof(*grp), GFP_ATOMIC);
167 if (!grp)
168 return NULL;
169 tipc_nlist_init(&grp->dests, tipc_own_addr(net));
Jon Maloy38266ca2018-01-04 15:20:44 +0100170 INIT_LIST_HEAD(&grp->small_win);
Jon Maloy04d7b572017-10-13 11:04:34 +0200171 INIT_LIST_HEAD(&grp->active);
172 INIT_LIST_HEAD(&grp->pending);
Jon Maloy75da2162017-10-13 11:04:23 +0200173 grp->members = RB_ROOT;
174 grp->net = net;
175 grp->portid = portid;
176 grp->domain = addr_domain(net, mreq->scope);
177 grp->type = type;
178 grp->instance = mreq->instance;
179 grp->scope = mreq->scope;
180 grp->loopback = mreq->flags & TIPC_GROUP_LOOPBACK;
Jon Maloyae236fb2017-10-13 11:04:25 +0200181 grp->events = mreq->flags & TIPC_GROUP_MEMBER_EVTS;
Jon Maloy75da2162017-10-13 11:04:23 +0200182 if (tipc_topsrv_kern_subscr(net, portid, type, 0, ~0, &grp->subid))
183 return grp;
184 kfree(grp);
185 return NULL;
186}
187
188void tipc_group_delete(struct net *net, struct tipc_group *grp)
189{
190 struct rb_root *tree = &grp->members;
191 struct tipc_member *m, *tmp;
192 struct sk_buff_head xmitq;
193
194 __skb_queue_head_init(&xmitq);
195
196 rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
197 tipc_group_proto_xmit(grp, m, GRP_LEAVE_MSG, &xmitq);
198 list_del(&m->list);
199 kfree(m);
200 }
201 tipc_node_distr_xmit(net, &xmitq);
202 tipc_nlist_purge(&grp->dests);
203 tipc_topsrv_kern_unsubscr(net, grp->subid);
204 kfree(grp);
205}
206
207struct tipc_member *tipc_group_find_member(struct tipc_group *grp,
208 u32 node, u32 port)
209{
210 struct rb_node *n = grp->members.rb_node;
211 u64 nkey, key = (u64)node << 32 | port;
212 struct tipc_member *m;
213
214 while (n) {
215 m = container_of(n, struct tipc_member, tree_node);
216 nkey = (u64)m->node << 32 | m->port;
217 if (key < nkey)
218 n = n->rb_left;
219 else if (key > nkey)
220 n = n->rb_right;
221 else
222 return m;
223 }
224 return NULL;
225}
226
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200227static struct tipc_member *tipc_group_find_dest(struct tipc_group *grp,
228 u32 node, u32 port)
229{
230 struct tipc_member *m;
231
232 m = tipc_group_find_member(grp, node, port);
Jon Maloy38266ca2018-01-04 15:20:44 +0100233 if (m && tipc_group_is_receiver(m))
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200234 return m;
235 return NULL;
236}
237
Jon Maloy75da2162017-10-13 11:04:23 +0200238static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
239 u32 node)
240{
241 struct tipc_member *m;
242 struct rb_node *n;
243
244 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
245 m = container_of(n, struct tipc_member, tree_node);
246 if (m->node == node)
247 return m;
248 }
249 return NULL;
250}
251
252static void tipc_group_add_to_tree(struct tipc_group *grp,
253 struct tipc_member *m)
254{
255 u64 nkey, key = (u64)m->node << 32 | m->port;
256 struct rb_node **n, *parent = NULL;
257 struct tipc_member *tmp;
258
259 n = &grp->members.rb_node;
260 while (*n) {
261 tmp = container_of(*n, struct tipc_member, tree_node);
262 parent = *n;
263 tmp = container_of(parent, struct tipc_member, tree_node);
264 nkey = (u64)tmp->node << 32 | tmp->port;
265 if (key < nkey)
266 n = &(*n)->rb_left;
267 else if (key > nkey)
268 n = &(*n)->rb_right;
269 else
270 return;
271 }
272 rb_link_node(&m->tree_node, parent, n);
273 rb_insert_color(&m->tree_node, &grp->members);
274}
275
276static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
277 u32 node, u32 port,
278 int state)
279{
280 struct tipc_member *m;
281
282 m = kzalloc(sizeof(*m), GFP_ATOMIC);
283 if (!m)
284 return NULL;
285 INIT_LIST_HEAD(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100286 INIT_LIST_HEAD(&m->small_win);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200287 __skb_queue_head_init(&m->deferredq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200288 m->group = grp;
Jon Maloy75da2162017-10-13 11:04:23 +0200289 m->node = node;
290 m->port = port;
Jon Maloy2f487712017-10-13 11:04:31 +0200291 m->bc_acked = grp->bc_snd_nxt - 1;
Jon Maloy75da2162017-10-13 11:04:23 +0200292 grp->member_cnt++;
293 tipc_group_add_to_tree(grp, m);
294 tipc_nlist_add(&grp->dests, m->node);
295 m->state = state;
296 return m;
297}
298
299void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port)
300{
301 tipc_group_create_member(grp, node, port, MBR_DISCOVERED);
302}
303
304static void tipc_group_delete_member(struct tipc_group *grp,
305 struct tipc_member *m)
306{
307 rb_erase(&m->tree_node, &grp->members);
308 grp->member_cnt--;
Jon Maloy2f487712017-10-13 11:04:31 +0200309
310 /* Check if we were waiting for replicast ack from this member */
311 if (grp->bc_ackers && less(m->bc_acked, grp->bc_snd_nxt - 1))
312 grp->bc_ackers--;
313
Jon Maloy75da2162017-10-13 11:04:23 +0200314 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100315 list_del_init(&m->small_win);
Jon Maloy04d7b572017-10-13 11:04:34 +0200316 tipc_group_decr_active(grp, m);
Jon Maloy75da2162017-10-13 11:04:23 +0200317
318 /* If last member on a node, remove node from dest list */
319 if (!tipc_group_find_node(grp, m->node))
320 tipc_nlist_del(&grp->dests, m->node);
321
322 kfree(m);
323}
324
325struct tipc_nlist *tipc_group_dests(struct tipc_group *grp)
326{
327 return &grp->dests;
328}
329
330void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
331 int *scope)
332{
333 seq->type = grp->type;
334 seq->lower = grp->instance;
335 seq->upper = grp->instance;
336 *scope = grp->scope;
337}
338
Jon Maloyb7d42632017-10-13 11:04:26 +0200339void tipc_group_update_member(struct tipc_member *m, int len)
Jon Maloy75da2162017-10-13 11:04:23 +0200340{
Jon Maloyb7d42632017-10-13 11:04:26 +0200341 struct tipc_group *grp = m->group;
342 struct tipc_member *_m, *tmp;
343
Jon Maloy38266ca2018-01-04 15:20:44 +0100344 if (!tipc_group_is_receiver(m))
Jon Maloyb7d42632017-10-13 11:04:26 +0200345 return;
346
347 m->window -= len;
348
349 if (m->window >= ADV_IDLE)
350 return;
351
Jon Maloy38266ca2018-01-04 15:20:44 +0100352 list_del_init(&m->small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200353
Jon Maloy38266ca2018-01-04 15:20:44 +0100354 /* Sort member into small_window members' list */
355 list_for_each_entry_safe(_m, tmp, &grp->small_win, small_win) {
Jon Maloyd84d1b32018-01-04 15:20:45 +0100356 if (_m->window > m->window)
357 break;
Jon Maloyb7d42632017-10-13 11:04:26 +0200358 }
Jon Maloyd84d1b32018-01-04 15:20:45 +0100359 list_add_tail(&m->small_win, &_m->small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200360}
361
Jon Maloy2f487712017-10-13 11:04:31 +0200362void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack)
Jon Maloyb7d42632017-10-13 11:04:26 +0200363{
Jon Maloy2f487712017-10-13 11:04:31 +0200364 u16 prev = grp->bc_snd_nxt - 1;
Jon Maloyb7d42632017-10-13 11:04:26 +0200365 struct tipc_member *m;
366 struct rb_node *n;
Jon Maloy0a3d8052017-12-21 13:07:11 +0100367 u16 ackers = 0;
Jon Maloyb7d42632017-10-13 11:04:26 +0200368
369 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
370 m = container_of(n, struct tipc_member, tree_node);
Jon Maloy38266ca2018-01-04 15:20:44 +0100371 if (tipc_group_is_receiver(m)) {
Jon Maloyb7d42632017-10-13 11:04:26 +0200372 tipc_group_update_member(m, len);
Jon Maloy2f487712017-10-13 11:04:31 +0200373 m->bc_acked = prev;
Jon Maloy0a3d8052017-12-21 13:07:11 +0100374 ackers++;
Jon Maloy2f487712017-10-13 11:04:31 +0200375 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200376 }
Jon Maloy2f487712017-10-13 11:04:31 +0200377
378 /* Mark number of acknowledges to expect, if any */
379 if (ack)
Jon Maloy0a3d8052017-12-21 13:07:11 +0100380 grp->bc_ackers = ackers;
Jon Maloy75da2162017-10-13 11:04:23 +0200381 grp->bc_snd_nxt++;
382}
383
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200384bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
385 int len, struct tipc_member **mbr)
386{
387 struct sk_buff_head xmitq;
388 struct tipc_member *m;
389 int adv, state;
390
391 m = tipc_group_find_dest(grp, dnode, dport);
392 *mbr = m;
393 if (!m)
394 return false;
395 if (m->usr_pending)
396 return true;
397 if (m->window >= len)
398 return false;
399 m->usr_pending = true;
400
401 /* If not fully advertised, do it now to prevent mutual blocking */
402 adv = m->advertised;
403 state = m->state;
404 if (state < MBR_JOINED)
405 return true;
406 if (state == MBR_JOINED && adv == ADV_IDLE)
407 return true;
Jon Maloy04d7b572017-10-13 11:04:34 +0200408 if (state == MBR_ACTIVE && adv == ADV_ACTIVE)
409 return true;
410 if (state == MBR_PENDING && adv == ADV_IDLE)
411 return true;
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200412 skb_queue_head_init(&xmitq);
413 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, &xmitq);
414 tipc_node_distr_xmit(grp->net, &xmitq);
415 return true;
416}
417
Jon Maloyb7d42632017-10-13 11:04:26 +0200418bool tipc_group_bc_cong(struct tipc_group *grp, int len)
419{
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200420 struct tipc_member *m = NULL;
Jon Maloyb7d42632017-10-13 11:04:26 +0200421
Jon Maloy2f487712017-10-13 11:04:31 +0200422 /* If prev bcast was replicast, reject until all receivers have acked */
423 if (grp->bc_ackers)
424 return true;
425
Jon Maloy38266ca2018-01-04 15:20:44 +0100426 if (list_empty(&grp->small_win))
Jon Maloyb7d42632017-10-13 11:04:26 +0200427 return false;
428
Jon Maloy38266ca2018-01-04 15:20:44 +0100429 m = list_first_entry(&grp->small_win, struct tipc_member, small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200430 if (m->window >= len)
431 return false;
432
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200433 return tipc_group_cong(grp, m->node, m->port, len, &m);
Jon Maloyb7d42632017-10-13 11:04:26 +0200434}
435
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200436/* tipc_group_sort_msg() - sort msg into queue by bcast sequence number
437 */
438static void tipc_group_sort_msg(struct sk_buff *skb, struct sk_buff_head *defq)
439{
440 struct tipc_msg *_hdr, *hdr = buf_msg(skb);
441 u16 bc_seqno = msg_grp_bc_seqno(hdr);
442 struct sk_buff *_skb, *tmp;
443 int mtyp = msg_type(hdr);
444
Jon Maloya3bada72017-10-13 11:04:33 +0200445 /* Bcast/mcast may be bypassed by ucast or other bcast, - sort it in */
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200446 if (mtyp == TIPC_GRP_BCAST_MSG || mtyp == TIPC_GRP_MCAST_MSG) {
447 skb_queue_walk_safe(defq, _skb, tmp) {
448 _hdr = buf_msg(_skb);
449 if (!less(bc_seqno, msg_grp_bc_seqno(_hdr)))
450 continue;
451 __skb_queue_before(defq, _skb, skb);
452 return;
453 }
454 /* Bcast was not bypassed, - add to tail */
455 }
456 /* Unicasts are never bypassed, - always add to tail */
457 __skb_queue_tail(defq, skb);
458}
459
Jon Maloy75da2162017-10-13 11:04:23 +0200460/* tipc_group_filter_msg() - determine if we should accept arriving message
461 */
462void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
463 struct sk_buff_head *xmitq)
464{
465 struct sk_buff *skb = __skb_dequeue(inputq);
Jon Maloya3bada72017-10-13 11:04:33 +0200466 bool ack, deliver, update, leave = false;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200467 struct sk_buff_head *defq;
Jon Maloy75da2162017-10-13 11:04:23 +0200468 struct tipc_member *m;
469 struct tipc_msg *hdr;
470 u32 node, port;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200471 int mtyp, blks;
Jon Maloy75da2162017-10-13 11:04:23 +0200472
473 if (!skb)
474 return;
475
476 hdr = buf_msg(skb);
Jon Maloy75da2162017-10-13 11:04:23 +0200477 node = msg_orignode(hdr);
478 port = msg_origport(hdr);
479
480 if (!msg_in_group(hdr))
481 goto drop;
482
483 m = tipc_group_find_member(grp, node, port);
Jon Maloy38266ca2018-01-04 15:20:44 +0100484 if (!tipc_group_is_sender(m))
Jon Maloy75da2162017-10-13 11:04:23 +0200485 goto drop;
486
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200487 if (less(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
488 goto drop;
Jon Maloy5b8dddb2017-10-13 11:04:29 +0200489
Jon Maloy31c82a22017-10-13 11:04:24 +0200490 TIPC_SKB_CB(skb)->orig_member = m->instance;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200491 defq = &m->deferredq;
492 tipc_group_sort_msg(skb, defq);
Jon Maloy75da2162017-10-13 11:04:23 +0200493
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200494 while ((skb = skb_peek(defq))) {
495 hdr = buf_msg(skb);
496 mtyp = msg_type(hdr);
Jon Maloy2e724dc2017-11-27 20:13:39 +0100497 blks = msg_blocks(hdr);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200498 deliver = true;
Jon Maloy2f487712017-10-13 11:04:31 +0200499 ack = false;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200500 update = false;
501
502 if (more(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
503 break;
504
505 /* Decide what to do with message */
506 switch (mtyp) {
507 case TIPC_GRP_MCAST_MSG:
508 if (msg_nameinst(hdr) != grp->instance) {
509 update = true;
510 deliver = false;
511 }
512 /* Fall thru */
513 case TIPC_GRP_BCAST_MSG:
514 m->bc_rcv_nxt++;
Jon Maloy2f487712017-10-13 11:04:31 +0200515 ack = msg_grp_bc_ack_req(hdr);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200516 break;
517 case TIPC_GRP_UCAST_MSG:
518 break;
Jon Maloya3bada72017-10-13 11:04:33 +0200519 case TIPC_GRP_MEMBER_EVT:
520 if (m->state == MBR_LEAVING)
521 leave = true;
522 if (!grp->events)
523 deliver = false;
524 break;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200525 default:
526 break;
527 }
528
529 /* Execute decisions */
530 __skb_dequeue(defq);
531 if (deliver)
532 __skb_queue_tail(inputq, skb);
533 else
534 kfree_skb(skb);
535
Jon Maloy2f487712017-10-13 11:04:31 +0200536 if (ack)
537 tipc_group_proto_xmit(grp, m, GRP_ACK_MSG, xmitq);
538
Jon Maloya3bada72017-10-13 11:04:33 +0200539 if (leave) {
Jon Maloya3bada72017-10-13 11:04:33 +0200540 __skb_queue_purge(defq);
Jon Maloye0e853a2017-11-20 21:43:03 +0100541 tipc_group_delete_member(grp, m);
Jon Maloya3bada72017-10-13 11:04:33 +0200542 break;
543 }
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200544 if (!update)
545 continue;
546
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200547 tipc_group_update_rcv_win(grp, blks, node, port, xmitq);
548 }
Jon Maloy75da2162017-10-13 11:04:23 +0200549 return;
550drop:
551 kfree_skb(skb);
552}
553
Jon Maloyb7d42632017-10-13 11:04:26 +0200554void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
555 u32 port, struct sk_buff_head *xmitq)
556{
Jon Maloy04d7b572017-10-13 11:04:34 +0200557 struct list_head *active = &grp->active;
558 int max_active = grp->max_active;
559 int reclaim_limit = max_active * 3 / 4;
560 int active_cnt = grp->active_cnt;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100561 struct tipc_member *m, *rm, *pm;
Jon Maloyb7d42632017-10-13 11:04:26 +0200562
563 m = tipc_group_find_member(grp, node, port);
564 if (!m)
565 return;
566
567 m->advertised -= blks;
568
569 switch (m->state) {
570 case MBR_JOINED:
Jon Maloy4ea5dab2018-01-08 21:03:24 +0100571 /* First, decide if member can go active */
572 if (active_cnt <= max_active) {
573 m->state = MBR_ACTIVE;
574 list_add_tail(&m->list, active);
575 grp->active_cnt++;
576 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
577 } else {
578 m->state = MBR_PENDING;
579 list_add_tail(&m->list, &grp->pending);
580 }
581
582 if (active_cnt < reclaim_limit)
583 break;
584
585 /* Reclaim from oldest active member, if possible */
586 if (!list_empty(active)) {
Jon Maloy04d7b572017-10-13 11:04:34 +0200587 rm = list_first_entry(active, struct tipc_member, list);
588 rm->state = MBR_RECLAIMING;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100589 list_del_init(&rm->list);
Jon Maloy04d7b572017-10-13 11:04:34 +0200590 tipc_group_proto_xmit(grp, rm, GRP_RECLAIM_MSG, xmitq);
Jon Maloy04d7b572017-10-13 11:04:34 +0200591 break;
592 }
Jon Maloy4ea5dab2018-01-08 21:03:24 +0100593 /* Nobody to reclaim from; - revert oldest pending to JOINED */
594 pm = list_first_entry(&grp->pending, struct tipc_member, list);
595 list_del_init(&pm->list);
596 pm->state = MBR_JOINED;
597 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
598 break;
Jon Maloy04d7b572017-10-13 11:04:34 +0200599 case MBR_ACTIVE:
600 if (!list_is_last(&m->list, &grp->active))
601 list_move_tail(&m->list, &grp->active);
602 if (m->advertised > (ADV_ACTIVE * 3 / 4))
603 break;
604 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200605 break;
Jon Maloy04d7b572017-10-13 11:04:34 +0200606 case MBR_REMITTED:
607 if (m->advertised > ADV_IDLE)
608 break;
609 m->state = MBR_JOINED;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100610 grp->active_cnt--;
Jon Maloy04d7b572017-10-13 11:04:34 +0200611 if (m->advertised < ADV_IDLE) {
612 pr_warn_ratelimited("Rcv unexpected msg after REMIT\n");
613 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
614 }
Jon Maloy8d5dee22018-01-08 21:03:23 +0100615
Jon Maloyf9c935d2017-12-29 19:48:02 +0100616 if (list_empty(&grp->pending))
617 return;
618
619 /* Set oldest pending member to active and advertise */
620 pm = list_first_entry(&grp->pending, struct tipc_member, list);
621 pm->state = MBR_ACTIVE;
622 list_move_tail(&pm->list, &grp->active);
623 grp->active_cnt++;
624 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
Jon Maloy04d7b572017-10-13 11:04:34 +0200625 break;
626 case MBR_RECLAIMING:
Jon Maloyb7d42632017-10-13 11:04:26 +0200627 case MBR_DISCOVERED:
628 case MBR_JOINING:
629 case MBR_LEAVING:
630 default:
631 break;
632 }
633}
634
Jon Maloy75da2162017-10-13 11:04:23 +0200635static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
636 int mtyp, struct sk_buff_head *xmitq)
637{
638 struct tipc_msg *hdr;
639 struct sk_buff *skb;
Jon Maloyb7d42632017-10-13 11:04:26 +0200640 int adv = 0;
Jon Maloy75da2162017-10-13 11:04:23 +0200641
642 skb = tipc_msg_create(GROUP_PROTOCOL, mtyp, INT_H_SIZE, 0,
643 m->node, tipc_own_addr(grp->net),
644 m->port, grp->portid, 0);
645 if (!skb)
646 return;
647
Jon Maloy04d7b572017-10-13 11:04:34 +0200648 if (m->state == MBR_ACTIVE)
Jon Maloyb7d42632017-10-13 11:04:26 +0200649 adv = ADV_ACTIVE - m->advertised;
Jon Maloy04d7b572017-10-13 11:04:34 +0200650 else if (m->state == MBR_JOINED || m->state == MBR_PENDING)
651 adv = ADV_IDLE - m->advertised;
Jon Maloyb7d42632017-10-13 11:04:26 +0200652
Jon Maloy75da2162017-10-13 11:04:23 +0200653 hdr = buf_msg(skb);
Jon Maloyb7d42632017-10-13 11:04:26 +0200654
655 if (mtyp == GRP_JOIN_MSG) {
Jon Maloy75da2162017-10-13 11:04:23 +0200656 msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
Jon Maloyb7d42632017-10-13 11:04:26 +0200657 msg_set_adv_win(hdr, adv);
658 m->advertised += adv;
Jon Maloya3bada72017-10-13 11:04:33 +0200659 } else if (mtyp == GRP_LEAVE_MSG) {
660 msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
Jon Maloyb7d42632017-10-13 11:04:26 +0200661 } else if (mtyp == GRP_ADV_MSG) {
662 msg_set_adv_win(hdr, adv);
663 m->advertised += adv;
Jon Maloy2f487712017-10-13 11:04:31 +0200664 } else if (mtyp == GRP_ACK_MSG) {
665 msg_set_grp_bc_acked(hdr, m->bc_rcv_nxt);
Jon Maloy04d7b572017-10-13 11:04:34 +0200666 } else if (mtyp == GRP_REMIT_MSG) {
667 msg_set_grp_remitted(hdr, m->window);
Jon Maloyb7d42632017-10-13 11:04:26 +0200668 }
Jon Maloy23483392017-12-18 17:34:16 +0100669 msg_set_dest_droppable(hdr, true);
Jon Maloy75da2162017-10-13 11:04:23 +0200670 __skb_queue_tail(xmitq, skb);
671}
672
Jon Maloyb7d42632017-10-13 11:04:26 +0200673void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
674 struct tipc_msg *hdr, struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200675 struct sk_buff_head *xmitq)
676{
677 u32 node = msg_orignode(hdr);
678 u32 port = msg_origport(hdr);
Jon Maloy04d7b572017-10-13 11:04:34 +0200679 struct tipc_member *m, *pm;
Jon Maloya3bada72017-10-13 11:04:33 +0200680 struct tipc_msg *ehdr;
Jon Maloy04d7b572017-10-13 11:04:34 +0200681 u16 remitted, in_flight;
Jon Maloy75da2162017-10-13 11:04:23 +0200682
683 if (!grp)
684 return;
685
686 m = tipc_group_find_member(grp, node, port);
687
688 switch (msg_type(hdr)) {
689 case GRP_JOIN_MSG:
690 if (!m)
691 m = tipc_group_create_member(grp, node, port,
Jon Maloy02334932018-01-08 21:03:25 +0100692 MBR_JOINING);
Jon Maloy75da2162017-10-13 11:04:23 +0200693 if (!m)
694 return;
Jon Maloya3bada72017-10-13 11:04:33 +0200695 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
696 m->bc_rcv_nxt = m->bc_syncpt;
Jon Maloyb7d42632017-10-13 11:04:26 +0200697 m->window += msg_adv_win(hdr);
Jon Maloy75da2162017-10-13 11:04:23 +0200698
699 /* Wait until PUBLISH event is received */
Jon Maloyae236fb2017-10-13 11:04:25 +0200700 if (m->state == MBR_DISCOVERED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200701 m->state = MBR_JOINING;
Jon Maloyae236fb2017-10-13 11:04:25 +0200702 } else if (m->state == MBR_PUBLISHED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200703 m->state = MBR_JOINED;
Jon Maloyb7d42632017-10-13 11:04:26 +0200704 *usr_wakeup = true;
705 m->usr_pending = false;
706 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
Jon Maloya3bada72017-10-13 11:04:33 +0200707 ehdr = buf_msg(m->event_msg);
708 msg_set_grp_bc_seqno(ehdr, m->bc_syncpt);
Jon Maloyae236fb2017-10-13 11:04:25 +0200709 __skb_queue_tail(inputq, m->event_msg);
710 }
Jon Maloy38266ca2018-01-04 15:20:44 +0100711 list_del_init(&m->small_win);
Jon Maloybb25c382017-12-20 11:03:15 +0100712 tipc_group_update_member(m, 0);
Jon Maloy75da2162017-10-13 11:04:23 +0200713 return;
714 case GRP_LEAVE_MSG:
715 if (!m)
716 return;
Jon Maloya3bada72017-10-13 11:04:33 +0200717 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100718 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100719 list_del_init(&m->small_win);
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100720 *usr_wakeup = true;
Jon Maloy75da2162017-10-13 11:04:23 +0200721
722 /* Wait until WITHDRAW event is received */
723 if (m->state != MBR_LEAVING) {
Jon Maloy04d7b572017-10-13 11:04:34 +0200724 tipc_group_decr_active(grp, m);
Jon Maloy75da2162017-10-13 11:04:23 +0200725 m->state = MBR_LEAVING;
726 return;
727 }
728 /* Otherwise deliver already received WITHDRAW event */
Jon Maloya3bada72017-10-13 11:04:33 +0200729 ehdr = buf_msg(m->event_msg);
730 msg_set_grp_bc_seqno(ehdr, m->bc_syncpt);
Jon Maloyae236fb2017-10-13 11:04:25 +0200731 __skb_queue_tail(inputq, m->event_msg);
Jon Maloyb7d42632017-10-13 11:04:26 +0200732 return;
733 case GRP_ADV_MSG:
734 if (!m)
735 return;
736 m->window += msg_adv_win(hdr);
737 *usr_wakeup = m->usr_pending;
738 m->usr_pending = false;
Jon Maloy38266ca2018-01-04 15:20:44 +0100739 list_del_init(&m->small_win);
Jon Maloy75da2162017-10-13 11:04:23 +0200740 return;
Jon Maloy2f487712017-10-13 11:04:31 +0200741 case GRP_ACK_MSG:
742 if (!m)
743 return;
744 m->bc_acked = msg_grp_bc_acked(hdr);
745 if (--grp->bc_ackers)
746 break;
747 *usr_wakeup = true;
748 m->usr_pending = false;
749 return;
Jon Maloy04d7b572017-10-13 11:04:34 +0200750 case GRP_RECLAIM_MSG:
751 if (!m)
752 return;
753 *usr_wakeup = m->usr_pending;
754 m->usr_pending = false;
755 tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq);
756 m->window = ADV_IDLE;
757 return;
758 case GRP_REMIT_MSG:
759 if (!m || m->state != MBR_RECLAIMING)
760 return;
761
Jon Maloy04d7b572017-10-13 11:04:34 +0200762 remitted = msg_grp_remitted(hdr);
763
764 /* Messages preceding the REMIT still in receive queue */
765 if (m->advertised > remitted) {
766 m->state = MBR_REMITTED;
767 in_flight = m->advertised - remitted;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100768 m->advertised = ADV_IDLE + in_flight;
769 return;
Jon Maloy04d7b572017-10-13 11:04:34 +0200770 }
Jon Maloy8d5dee22018-01-08 21:03:23 +0100771 /* This should never happen */
Jon Maloy04d7b572017-10-13 11:04:34 +0200772 if (m->advertised < remitted)
Jon Maloy8d5dee22018-01-08 21:03:23 +0100773 pr_warn_ratelimited("Unexpected REMIT msg\n");
Jon Maloy04d7b572017-10-13 11:04:34 +0200774
Jon Maloy8d5dee22018-01-08 21:03:23 +0100775 /* All messages preceding the REMIT have been read */
776 m->state = MBR_JOINED;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100777 grp->active_cnt--;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100778 m->advertised = ADV_IDLE;
Jon Maloy04d7b572017-10-13 11:04:34 +0200779
780 /* Set oldest pending member to active and advertise */
781 if (list_empty(&grp->pending))
782 return;
783 pm = list_first_entry(&grp->pending, struct tipc_member, list);
784 pm->state = MBR_ACTIVE;
785 list_move_tail(&pm->list, &grp->active);
786 grp->active_cnt++;
787 if (pm->advertised <= (ADV_ACTIVE * 3 / 4))
788 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
789 return;
Jon Maloy75da2162017-10-13 11:04:23 +0200790 default:
791 pr_warn("Received unknown GROUP_PROTO message\n");
792 }
793}
794
Jon Maloyb7d42632017-10-13 11:04:26 +0200795/* tipc_group_member_evt() - receive and handle a member up/down event
796 */
Jon Maloy75da2162017-10-13 11:04:23 +0200797void tipc_group_member_evt(struct tipc_group *grp,
Jon Maloyb7d42632017-10-13 11:04:26 +0200798 bool *usr_wakeup,
799 int *sk_rcvbuf,
Jon Maloy75da2162017-10-13 11:04:23 +0200800 struct sk_buff *skb,
Jon Maloyae236fb2017-10-13 11:04:25 +0200801 struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200802 struct sk_buff_head *xmitq)
803{
804 struct tipc_msg *hdr = buf_msg(skb);
805 struct tipc_event *evt = (void *)msg_data(hdr);
Jon Maloyae236fb2017-10-13 11:04:25 +0200806 u32 instance = evt->found_lower;
Jon Maloy75da2162017-10-13 11:04:23 +0200807 u32 node = evt->port.node;
808 u32 port = evt->port.ref;
Jon Maloyae236fb2017-10-13 11:04:25 +0200809 int event = evt->event;
Jon Maloy75da2162017-10-13 11:04:23 +0200810 struct tipc_member *m;
811 struct net *net;
Jon Maloya3bada72017-10-13 11:04:33 +0200812 bool node_up;
Jon Maloy75da2162017-10-13 11:04:23 +0200813 u32 self;
814
815 if (!grp)
816 goto drop;
817
818 net = grp->net;
819 self = tipc_own_addr(net);
820 if (!grp->loopback && node == self && port == grp->portid)
821 goto drop;
822
Jon Maloyae236fb2017-10-13 11:04:25 +0200823 /* Convert message before delivery to user */
824 msg_set_hdr_sz(hdr, GROUP_H_SIZE);
825 msg_set_user(hdr, TIPC_CRITICAL_IMPORTANCE);
826 msg_set_type(hdr, TIPC_GRP_MEMBER_EVT);
827 msg_set_origport(hdr, port);
828 msg_set_orignode(hdr, node);
829 msg_set_nametype(hdr, grp->type);
830 msg_set_grp_evt(hdr, event);
831
Jon Maloy75da2162017-10-13 11:04:23 +0200832 m = tipc_group_find_member(grp, node, port);
833
Jon Maloyae236fb2017-10-13 11:04:25 +0200834 if (event == TIPC_PUBLISHED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200835 if (!m)
836 m = tipc_group_create_member(grp, node, port,
837 MBR_DISCOVERED);
838 if (!m)
839 goto drop;
840
Jon Maloyae236fb2017-10-13 11:04:25 +0200841 /* Hold back event if JOIN message not yet received */
842 if (m->state == MBR_DISCOVERED) {
843 m->event_msg = skb;
Jon Maloy75da2162017-10-13 11:04:23 +0200844 m->state = MBR_PUBLISHED;
Jon Maloyae236fb2017-10-13 11:04:25 +0200845 } else {
Jon Maloya3bada72017-10-13 11:04:33 +0200846 msg_set_grp_bc_seqno(hdr, m->bc_syncpt);
Jon Maloyae236fb2017-10-13 11:04:25 +0200847 __skb_queue_tail(inputq, skb);
Jon Maloy75da2162017-10-13 11:04:23 +0200848 m->state = MBR_JOINED;
Jon Maloyb7d42632017-10-13 11:04:26 +0200849 *usr_wakeup = true;
850 m->usr_pending = false;
Jon Maloyae236fb2017-10-13 11:04:25 +0200851 }
852 m->instance = instance;
853 TIPC_SKB_CB(skb)->orig_member = m->instance;
Jon Maloy75da2162017-10-13 11:04:23 +0200854 tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
Jon Maloyd84d1b32018-01-04 15:20:45 +0100855 tipc_group_update_member(m, 0);
Jon Maloyae236fb2017-10-13 11:04:25 +0200856 } else if (event == TIPC_WITHDRAWN) {
Jon Maloy75da2162017-10-13 11:04:23 +0200857 if (!m)
858 goto drop;
859
Jon Maloyae236fb2017-10-13 11:04:25 +0200860 TIPC_SKB_CB(skb)->orig_member = m->instance;
861
Jon Maloy2f487712017-10-13 11:04:31 +0200862 *usr_wakeup = true;
Jon Maloyb7d42632017-10-13 11:04:26 +0200863 m->usr_pending = false;
Jon Maloya3bada72017-10-13 11:04:33 +0200864 node_up = tipc_node_is_up(net, node);
Jon Maloy3a33a192017-12-21 14:36:34 +0100865 m->event_msg = NULL;
Jon Maloyb7d42632017-10-13 11:04:26 +0200866
Jon Maloy3a33a192017-12-21 14:36:34 +0100867 if (node_up) {
868 /* Hold back event if a LEAVE msg should be expected */
869 if (m->state != MBR_LEAVING) {
870 m->event_msg = skb;
871 tipc_group_decr_active(grp, m);
872 m->state = MBR_LEAVING;
873 } else {
Jon Maloya3bada72017-10-13 11:04:33 +0200874 msg_set_grp_bc_seqno(hdr, m->bc_syncpt);
Jon Maloy3a33a192017-12-21 14:36:34 +0100875 __skb_queue_tail(inputq, skb);
876 }
877 } else {
878 if (m->state != MBR_LEAVING) {
879 tipc_group_decr_active(grp, m);
880 m->state = MBR_LEAVING;
Jon Maloya3bada72017-10-13 11:04:33 +0200881 msg_set_grp_bc_seqno(hdr, m->bc_rcv_nxt);
Jon Maloy3a33a192017-12-21 14:36:34 +0100882 } else {
883 msg_set_grp_bc_seqno(hdr, m->bc_syncpt);
884 }
Jon Maloyae236fb2017-10-13 11:04:25 +0200885 __skb_queue_tail(inputq, skb);
Jon Maloyae236fb2017-10-13 11:04:25 +0200886 }
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100887 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100888 list_del_init(&m->small_win);
Jon Maloy75da2162017-10-13 11:04:23 +0200889 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200890 *sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
Jon Maloyae236fb2017-10-13 11:04:25 +0200891 return;
Jon Maloy75da2162017-10-13 11:04:23 +0200892drop:
893 kfree_skb(skb);
894}