blob: bdc54be9c07e675ff29ea34b5da8cf078149edb9 [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 Maloyb87a5ea2017-10-13 11:04:30 +020067 struct sk_buff_head deferredq;
Jon Maloyb7d42632017-10-13 11:04:26 +020068 struct tipc_group *group;
Jon Maloy75da2162017-10-13 11:04:23 +020069 u32 node;
70 u32 port;
Jon Maloy31c82a22017-10-13 11:04:24 +020071 u32 instance;
Jon Maloy75da2162017-10-13 11:04:23 +020072 enum mbr_state state;
Jon Maloyb7d42632017-10-13 11:04:26 +020073 u16 advertised;
74 u16 window;
Jon Maloy75da2162017-10-13 11:04:23 +020075 u16 bc_rcv_nxt;
Jon Maloya3bada72017-10-13 11:04:33 +020076 u16 bc_syncpt;
Jon Maloy2f487712017-10-13 11:04:31 +020077 u16 bc_acked;
Jon Maloyb7d42632017-10-13 11:04:26 +020078 bool usr_pending;
Jon Maloy75da2162017-10-13 11:04:23 +020079};
80
81struct tipc_group {
82 struct rb_root members;
Jon Maloy38266ca2018-01-04 15:20:44 +010083 struct list_head small_win;
Jon Maloy04d7b572017-10-13 11:04:34 +020084 struct list_head pending;
85 struct list_head active;
Jon Maloy75da2162017-10-13 11:04:23 +020086 struct tipc_nlist dests;
87 struct net *net;
88 int subid;
89 u32 type;
90 u32 instance;
91 u32 domain;
92 u32 scope;
93 u32 portid;
94 u16 member_cnt;
Jon Maloy04d7b572017-10-13 11:04:34 +020095 u16 active_cnt;
96 u16 max_active;
Jon Maloy75da2162017-10-13 11:04:23 +020097 u16 bc_snd_nxt;
Jon Maloy2f487712017-10-13 11:04:31 +020098 u16 bc_ackers;
Jon Maloy75da2162017-10-13 11:04:23 +020099 bool loopback;
Jon Maloyae236fb2017-10-13 11:04:25 +0200100 bool events;
Jon Maloy75da2162017-10-13 11:04:23 +0200101};
102
103static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
104 int mtyp, struct sk_buff_head *xmitq);
105
Jon Maloy04d7b572017-10-13 11:04:34 +0200106static void tipc_group_decr_active(struct tipc_group *grp,
107 struct tipc_member *m)
108{
Jon Maloyf9c935d2017-12-29 19:48:02 +0100109 if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING ||
110 m->state == MBR_REMITTED)
Jon Maloy04d7b572017-10-13 11:04:34 +0200111 grp->active_cnt--;
112}
113
Jon Maloyb7d42632017-10-13 11:04:26 +0200114static int tipc_group_rcvbuf_limit(struct tipc_group *grp)
115{
Jon Maloy04d7b572017-10-13 11:04:34 +0200116 int max_active, active_pool, idle_pool;
Jon Maloyb7d42632017-10-13 11:04:26 +0200117 int mcnt = grp->member_cnt + 1;
118
Jon Maloy04d7b572017-10-13 11:04:34 +0200119 /* Limit simultaneous reception from other members */
120 max_active = min(mcnt / 8, 64);
121 max_active = max(max_active, 16);
122 grp->max_active = max_active;
123
124 /* Reserve blocks for active and idle members */
125 active_pool = max_active * ADV_ACTIVE;
126 idle_pool = (mcnt - max_active) * ADV_IDLE;
127
Jon Maloyb7d42632017-10-13 11:04:26 +0200128 /* Scale to bytes, considering worst-case truesize/msgsize ratio */
Jon Maloy04d7b572017-10-13 11:04:34 +0200129 return (active_pool + idle_pool) * FLOWCTL_BLK_SZ * 4;
Jon Maloyb7d42632017-10-13 11:04:26 +0200130}
131
Jon Maloy75da2162017-10-13 11:04:23 +0200132u16 tipc_group_bc_snd_nxt(struct tipc_group *grp)
133{
134 return grp->bc_snd_nxt;
135}
136
Jon Maloy38266ca2018-01-04 15:20:44 +0100137static bool tipc_group_is_receiver(struct tipc_member *m)
Jon Maloyb7d42632017-10-13 11:04:26 +0200138{
Jon Maloy02334932018-01-08 21:03:25 +0100139 return m && m->state != MBR_JOINING && m->state != MBR_LEAVING;
Jon Maloyb7d42632017-10-13 11:04:26 +0200140}
141
Jon Maloy38266ca2018-01-04 15:20:44 +0100142static bool tipc_group_is_sender(struct tipc_member *m)
Jon Maloy75da2162017-10-13 11:04:23 +0200143{
144 return m && m->state >= MBR_JOINED;
145}
146
Jon Maloyee106d72017-10-13 11:04:28 +0200147u32 tipc_group_exclude(struct tipc_group *grp)
148{
149 if (!grp->loopback)
150 return grp->portid;
151 return 0;
152}
153
Jon Maloy75da2162017-10-13 11:04:23 +0200154int tipc_group_size(struct tipc_group *grp)
155{
156 return grp->member_cnt;
157}
158
159struct tipc_group *tipc_group_create(struct net *net, u32 portid,
160 struct tipc_group_req *mreq)
161{
162 struct tipc_group *grp;
163 u32 type = mreq->type;
164
165 grp = kzalloc(sizeof(*grp), GFP_ATOMIC);
166 if (!grp)
167 return NULL;
168 tipc_nlist_init(&grp->dests, tipc_own_addr(net));
Jon Maloy38266ca2018-01-04 15:20:44 +0100169 INIT_LIST_HEAD(&grp->small_win);
Jon Maloy04d7b572017-10-13 11:04:34 +0200170 INIT_LIST_HEAD(&grp->active);
171 INIT_LIST_HEAD(&grp->pending);
Jon Maloy75da2162017-10-13 11:04:23 +0200172 grp->members = RB_ROOT;
173 grp->net = net;
174 grp->portid = portid;
175 grp->domain = addr_domain(net, mreq->scope);
176 grp->type = type;
177 grp->instance = mreq->instance;
178 grp->scope = mreq->scope;
179 grp->loopback = mreq->flags & TIPC_GROUP_LOOPBACK;
Jon Maloyae236fb2017-10-13 11:04:25 +0200180 grp->events = mreq->flags & TIPC_GROUP_MEMBER_EVTS;
Jon Maloy75da2162017-10-13 11:04:23 +0200181 if (tipc_topsrv_kern_subscr(net, portid, type, 0, ~0, &grp->subid))
182 return grp;
183 kfree(grp);
184 return NULL;
185}
186
187void tipc_group_delete(struct net *net, struct tipc_group *grp)
188{
189 struct rb_root *tree = &grp->members;
190 struct tipc_member *m, *tmp;
191 struct sk_buff_head xmitq;
192
193 __skb_queue_head_init(&xmitq);
194
195 rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
196 tipc_group_proto_xmit(grp, m, GRP_LEAVE_MSG, &xmitq);
197 list_del(&m->list);
198 kfree(m);
199 }
200 tipc_node_distr_xmit(net, &xmitq);
201 tipc_nlist_purge(&grp->dests);
202 tipc_topsrv_kern_unsubscr(net, grp->subid);
203 kfree(grp);
204}
205
206struct tipc_member *tipc_group_find_member(struct tipc_group *grp,
207 u32 node, u32 port)
208{
209 struct rb_node *n = grp->members.rb_node;
210 u64 nkey, key = (u64)node << 32 | port;
211 struct tipc_member *m;
212
213 while (n) {
214 m = container_of(n, struct tipc_member, tree_node);
215 nkey = (u64)m->node << 32 | m->port;
216 if (key < nkey)
217 n = n->rb_left;
218 else if (key > nkey)
219 n = n->rb_right;
220 else
221 return m;
222 }
223 return NULL;
224}
225
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200226static struct tipc_member *tipc_group_find_dest(struct tipc_group *grp,
227 u32 node, u32 port)
228{
229 struct tipc_member *m;
230
231 m = tipc_group_find_member(grp, node, port);
Jon Maloy38266ca2018-01-04 15:20:44 +0100232 if (m && tipc_group_is_receiver(m))
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200233 return m;
234 return NULL;
235}
236
Jon Maloy75da2162017-10-13 11:04:23 +0200237static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
238 u32 node)
239{
240 struct tipc_member *m;
241 struct rb_node *n;
242
243 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
244 m = container_of(n, struct tipc_member, tree_node);
245 if (m->node == node)
246 return m;
247 }
248 return NULL;
249}
250
251static void tipc_group_add_to_tree(struct tipc_group *grp,
252 struct tipc_member *m)
253{
254 u64 nkey, key = (u64)m->node << 32 | m->port;
255 struct rb_node **n, *parent = NULL;
256 struct tipc_member *tmp;
257
258 n = &grp->members.rb_node;
259 while (*n) {
260 tmp = container_of(*n, struct tipc_member, tree_node);
261 parent = *n;
262 tmp = container_of(parent, struct tipc_member, tree_node);
263 nkey = (u64)tmp->node << 32 | tmp->port;
264 if (key < nkey)
265 n = &(*n)->rb_left;
266 else if (key > nkey)
267 n = &(*n)->rb_right;
268 else
269 return;
270 }
271 rb_link_node(&m->tree_node, parent, n);
272 rb_insert_color(&m->tree_node, &grp->members);
273}
274
275static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
276 u32 node, u32 port,
277 int state)
278{
279 struct tipc_member *m;
280
281 m = kzalloc(sizeof(*m), GFP_ATOMIC);
282 if (!m)
283 return NULL;
284 INIT_LIST_HEAD(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100285 INIT_LIST_HEAD(&m->small_win);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200286 __skb_queue_head_init(&m->deferredq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200287 m->group = grp;
Jon Maloy75da2162017-10-13 11:04:23 +0200288 m->node = node;
289 m->port = port;
Jon Maloy2f487712017-10-13 11:04:31 +0200290 m->bc_acked = grp->bc_snd_nxt - 1;
Jon Maloy75da2162017-10-13 11:04:23 +0200291 grp->member_cnt++;
292 tipc_group_add_to_tree(grp, m);
293 tipc_nlist_add(&grp->dests, m->node);
294 m->state = state;
295 return m;
296}
297
298void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port)
299{
300 tipc_group_create_member(grp, node, port, MBR_DISCOVERED);
301}
302
303static void tipc_group_delete_member(struct tipc_group *grp,
304 struct tipc_member *m)
305{
306 rb_erase(&m->tree_node, &grp->members);
307 grp->member_cnt--;
Jon Maloy2f487712017-10-13 11:04:31 +0200308
309 /* Check if we were waiting for replicast ack from this member */
310 if (grp->bc_ackers && less(m->bc_acked, grp->bc_snd_nxt - 1))
311 grp->bc_ackers--;
312
Jon Maloy75da2162017-10-13 11:04:23 +0200313 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100314 list_del_init(&m->small_win);
Jon Maloy04d7b572017-10-13 11:04:34 +0200315 tipc_group_decr_active(grp, m);
Jon Maloy75da2162017-10-13 11:04:23 +0200316
317 /* If last member on a node, remove node from dest list */
318 if (!tipc_group_find_node(grp, m->node))
319 tipc_nlist_del(&grp->dests, m->node);
320
321 kfree(m);
322}
323
324struct tipc_nlist *tipc_group_dests(struct tipc_group *grp)
325{
326 return &grp->dests;
327}
328
329void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
330 int *scope)
331{
332 seq->type = grp->type;
333 seq->lower = grp->instance;
334 seq->upper = grp->instance;
335 *scope = grp->scope;
336}
337
Jon Maloyb7d42632017-10-13 11:04:26 +0200338void tipc_group_update_member(struct tipc_member *m, int len)
Jon Maloy75da2162017-10-13 11:04:23 +0200339{
Jon Maloyb7d42632017-10-13 11:04:26 +0200340 struct tipc_group *grp = m->group;
341 struct tipc_member *_m, *tmp;
342
Jon Maloy38266ca2018-01-04 15:20:44 +0100343 if (!tipc_group_is_receiver(m))
Jon Maloyb7d42632017-10-13 11:04:26 +0200344 return;
345
346 m->window -= len;
347
348 if (m->window >= ADV_IDLE)
349 return;
350
Jon Maloy38266ca2018-01-04 15:20:44 +0100351 list_del_init(&m->small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200352
Jon Maloy38266ca2018-01-04 15:20:44 +0100353 /* Sort member into small_window members' list */
354 list_for_each_entry_safe(_m, tmp, &grp->small_win, small_win) {
Jon Maloyd84d1b32018-01-04 15:20:45 +0100355 if (_m->window > m->window)
356 break;
Jon Maloyb7d42632017-10-13 11:04:26 +0200357 }
Jon Maloyd84d1b32018-01-04 15:20:45 +0100358 list_add_tail(&m->small_win, &_m->small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200359}
360
Jon Maloy2f487712017-10-13 11:04:31 +0200361void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack)
Jon Maloyb7d42632017-10-13 11:04:26 +0200362{
Jon Maloy2f487712017-10-13 11:04:31 +0200363 u16 prev = grp->bc_snd_nxt - 1;
Jon Maloyb7d42632017-10-13 11:04:26 +0200364 struct tipc_member *m;
365 struct rb_node *n;
Jon Maloy0a3d8052017-12-21 13:07:11 +0100366 u16 ackers = 0;
Jon Maloyb7d42632017-10-13 11:04:26 +0200367
368 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
369 m = container_of(n, struct tipc_member, tree_node);
Jon Maloy38266ca2018-01-04 15:20:44 +0100370 if (tipc_group_is_receiver(m)) {
Jon Maloyb7d42632017-10-13 11:04:26 +0200371 tipc_group_update_member(m, len);
Jon Maloy2f487712017-10-13 11:04:31 +0200372 m->bc_acked = prev;
Jon Maloy0a3d8052017-12-21 13:07:11 +0100373 ackers++;
Jon Maloy2f487712017-10-13 11:04:31 +0200374 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200375 }
Jon Maloy2f487712017-10-13 11:04:31 +0200376
377 /* Mark number of acknowledges to expect, if any */
378 if (ack)
Jon Maloy0a3d8052017-12-21 13:07:11 +0100379 grp->bc_ackers = ackers;
Jon Maloy75da2162017-10-13 11:04:23 +0200380 grp->bc_snd_nxt++;
381}
382
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200383bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
384 int len, struct tipc_member **mbr)
385{
386 struct sk_buff_head xmitq;
387 struct tipc_member *m;
388 int adv, state;
389
390 m = tipc_group_find_dest(grp, dnode, dport);
391 *mbr = m;
392 if (!m)
393 return false;
394 if (m->usr_pending)
395 return true;
396 if (m->window >= len)
397 return false;
398 m->usr_pending = true;
399
400 /* If not fully advertised, do it now to prevent mutual blocking */
401 adv = m->advertised;
402 state = m->state;
403 if (state < MBR_JOINED)
404 return true;
405 if (state == MBR_JOINED && adv == ADV_IDLE)
406 return true;
Jon Maloy04d7b572017-10-13 11:04:34 +0200407 if (state == MBR_ACTIVE && adv == ADV_ACTIVE)
408 return true;
409 if (state == MBR_PENDING && adv == ADV_IDLE)
410 return true;
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200411 skb_queue_head_init(&xmitq);
412 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, &xmitq);
413 tipc_node_distr_xmit(grp->net, &xmitq);
414 return true;
415}
416
Jon Maloyb7d42632017-10-13 11:04:26 +0200417bool tipc_group_bc_cong(struct tipc_group *grp, int len)
418{
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200419 struct tipc_member *m = NULL;
Jon Maloyb7d42632017-10-13 11:04:26 +0200420
Jon Maloy2f487712017-10-13 11:04:31 +0200421 /* If prev bcast was replicast, reject until all receivers have acked */
422 if (grp->bc_ackers)
423 return true;
424
Jon Maloy38266ca2018-01-04 15:20:44 +0100425 if (list_empty(&grp->small_win))
Jon Maloyb7d42632017-10-13 11:04:26 +0200426 return false;
427
Jon Maloy38266ca2018-01-04 15:20:44 +0100428 m = list_first_entry(&grp->small_win, struct tipc_member, small_win);
Jon Maloyb7d42632017-10-13 11:04:26 +0200429 if (m->window >= len)
430 return false;
431
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200432 return tipc_group_cong(grp, m->node, m->port, len, &m);
Jon Maloyb7d42632017-10-13 11:04:26 +0200433}
434
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200435/* tipc_group_sort_msg() - sort msg into queue by bcast sequence number
436 */
437static void tipc_group_sort_msg(struct sk_buff *skb, struct sk_buff_head *defq)
438{
439 struct tipc_msg *_hdr, *hdr = buf_msg(skb);
440 u16 bc_seqno = msg_grp_bc_seqno(hdr);
441 struct sk_buff *_skb, *tmp;
442 int mtyp = msg_type(hdr);
443
Jon Maloya3bada72017-10-13 11:04:33 +0200444 /* Bcast/mcast may be bypassed by ucast or other bcast, - sort it in */
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200445 if (mtyp == TIPC_GRP_BCAST_MSG || mtyp == TIPC_GRP_MCAST_MSG) {
446 skb_queue_walk_safe(defq, _skb, tmp) {
447 _hdr = buf_msg(_skb);
448 if (!less(bc_seqno, msg_grp_bc_seqno(_hdr)))
449 continue;
450 __skb_queue_before(defq, _skb, skb);
451 return;
452 }
453 /* Bcast was not bypassed, - add to tail */
454 }
455 /* Unicasts are never bypassed, - always add to tail */
456 __skb_queue_tail(defq, skb);
457}
458
Jon Maloy75da2162017-10-13 11:04:23 +0200459/* tipc_group_filter_msg() - determine if we should accept arriving message
460 */
461void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
462 struct sk_buff_head *xmitq)
463{
464 struct sk_buff *skb = __skb_dequeue(inputq);
Jon Maloya3bada72017-10-13 11:04:33 +0200465 bool ack, deliver, update, leave = false;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200466 struct sk_buff_head *defq;
Jon Maloy75da2162017-10-13 11:04:23 +0200467 struct tipc_member *m;
468 struct tipc_msg *hdr;
469 u32 node, port;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200470 int mtyp, blks;
Jon Maloy75da2162017-10-13 11:04:23 +0200471
472 if (!skb)
473 return;
474
475 hdr = buf_msg(skb);
Jon Maloy75da2162017-10-13 11:04:23 +0200476 node = msg_orignode(hdr);
477 port = msg_origport(hdr);
478
479 if (!msg_in_group(hdr))
480 goto drop;
481
482 m = tipc_group_find_member(grp, node, port);
Jon Maloy38266ca2018-01-04 15:20:44 +0100483 if (!tipc_group_is_sender(m))
Jon Maloy75da2162017-10-13 11:04:23 +0200484 goto drop;
485
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200486 if (less(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
487 goto drop;
Jon Maloy5b8dddb2017-10-13 11:04:29 +0200488
Jon Maloy31c82a22017-10-13 11:04:24 +0200489 TIPC_SKB_CB(skb)->orig_member = m->instance;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200490 defq = &m->deferredq;
491 tipc_group_sort_msg(skb, defq);
Jon Maloy75da2162017-10-13 11:04:23 +0200492
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200493 while ((skb = skb_peek(defq))) {
494 hdr = buf_msg(skb);
495 mtyp = msg_type(hdr);
Jon Maloy2e724dc2017-11-27 20:13:39 +0100496 blks = msg_blocks(hdr);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200497 deliver = true;
Jon Maloy2f487712017-10-13 11:04:31 +0200498 ack = false;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200499 update = false;
500
501 if (more(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
502 break;
503
504 /* Decide what to do with message */
505 switch (mtyp) {
506 case TIPC_GRP_MCAST_MSG:
507 if (msg_nameinst(hdr) != grp->instance) {
508 update = true;
509 deliver = false;
510 }
511 /* Fall thru */
512 case TIPC_GRP_BCAST_MSG:
513 m->bc_rcv_nxt++;
Jon Maloy2f487712017-10-13 11:04:31 +0200514 ack = msg_grp_bc_ack_req(hdr);
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200515 break;
516 case TIPC_GRP_UCAST_MSG:
517 break;
Jon Maloya3bada72017-10-13 11:04:33 +0200518 case TIPC_GRP_MEMBER_EVT:
519 if (m->state == MBR_LEAVING)
520 leave = true;
521 if (!grp->events)
522 deliver = false;
523 break;
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200524 default:
525 break;
526 }
527
528 /* Execute decisions */
529 __skb_dequeue(defq);
530 if (deliver)
531 __skb_queue_tail(inputq, skb);
532 else
533 kfree_skb(skb);
534
Jon Maloy2f487712017-10-13 11:04:31 +0200535 if (ack)
536 tipc_group_proto_xmit(grp, m, GRP_ACK_MSG, xmitq);
537
Jon Maloya3bada72017-10-13 11:04:33 +0200538 if (leave) {
Jon Maloya3bada72017-10-13 11:04:33 +0200539 __skb_queue_purge(defq);
Jon Maloye0e853a2017-11-20 21:43:03 +0100540 tipc_group_delete_member(grp, m);
Jon Maloya3bada72017-10-13 11:04:33 +0200541 break;
542 }
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200543 if (!update)
544 continue;
545
Jon Maloyb87a5ea2017-10-13 11:04:30 +0200546 tipc_group_update_rcv_win(grp, blks, node, port, xmitq);
547 }
Jon Maloy75da2162017-10-13 11:04:23 +0200548 return;
549drop:
550 kfree_skb(skb);
551}
552
Jon Maloyb7d42632017-10-13 11:04:26 +0200553void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
554 u32 port, struct sk_buff_head *xmitq)
555{
Jon Maloy04d7b572017-10-13 11:04:34 +0200556 struct list_head *active = &grp->active;
557 int max_active = grp->max_active;
558 int reclaim_limit = max_active * 3 / 4;
559 int active_cnt = grp->active_cnt;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100560 struct tipc_member *m, *rm, *pm;
Jon Maloyb7d42632017-10-13 11:04:26 +0200561
562 m = tipc_group_find_member(grp, node, port);
563 if (!m)
564 return;
565
566 m->advertised -= blks;
567
568 switch (m->state) {
569 case MBR_JOINED:
Jon Maloy4ea5dab2018-01-08 21:03:24 +0100570 /* First, decide if member can go active */
571 if (active_cnt <= max_active) {
572 m->state = MBR_ACTIVE;
573 list_add_tail(&m->list, active);
574 grp->active_cnt++;
575 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
576 } else {
577 m->state = MBR_PENDING;
578 list_add_tail(&m->list, &grp->pending);
579 }
580
581 if (active_cnt < reclaim_limit)
582 break;
583
584 /* Reclaim from oldest active member, if possible */
585 if (!list_empty(active)) {
Jon Maloy04d7b572017-10-13 11:04:34 +0200586 rm = list_first_entry(active, struct tipc_member, list);
587 rm->state = MBR_RECLAIMING;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100588 list_del_init(&rm->list);
Jon Maloy04d7b572017-10-13 11:04:34 +0200589 tipc_group_proto_xmit(grp, rm, GRP_RECLAIM_MSG, xmitq);
Jon Maloy04d7b572017-10-13 11:04:34 +0200590 break;
591 }
Jon Maloy4ea5dab2018-01-08 21:03:24 +0100592 /* Nobody to reclaim from; - revert oldest pending to JOINED */
593 pm = list_first_entry(&grp->pending, struct tipc_member, list);
594 list_del_init(&pm->list);
595 pm->state = MBR_JOINED;
596 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
597 break;
Jon Maloy04d7b572017-10-13 11:04:34 +0200598 case MBR_ACTIVE:
599 if (!list_is_last(&m->list, &grp->active))
600 list_move_tail(&m->list, &grp->active);
601 if (m->advertised > (ADV_ACTIVE * 3 / 4))
602 break;
603 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200604 break;
Jon Maloy04d7b572017-10-13 11:04:34 +0200605 case MBR_REMITTED:
606 if (m->advertised > ADV_IDLE)
607 break;
608 m->state = MBR_JOINED;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100609 grp->active_cnt--;
Jon Maloy04d7b572017-10-13 11:04:34 +0200610 if (m->advertised < ADV_IDLE) {
611 pr_warn_ratelimited("Rcv unexpected msg after REMIT\n");
612 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
613 }
Jon Maloy8d5dee22018-01-08 21:03:23 +0100614
Jon Maloyf9c935d2017-12-29 19:48:02 +0100615 if (list_empty(&grp->pending))
616 return;
617
618 /* Set oldest pending member to active and advertise */
619 pm = list_first_entry(&grp->pending, struct tipc_member, list);
620 pm->state = MBR_ACTIVE;
621 list_move_tail(&pm->list, &grp->active);
622 grp->active_cnt++;
623 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
Jon Maloy04d7b572017-10-13 11:04:34 +0200624 break;
625 case MBR_RECLAIMING:
Jon Maloyb7d42632017-10-13 11:04:26 +0200626 case MBR_DISCOVERED:
627 case MBR_JOINING:
628 case MBR_LEAVING:
629 default:
630 break;
631 }
632}
633
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100634static void tipc_group_create_event(struct tipc_group *grp,
635 struct tipc_member *m,
636 u32 event, u16 seqno,
637 struct sk_buff_head *inputq)
638{ u32 dnode = tipc_own_addr(grp->net);
639 struct tipc_event evt;
640 struct sk_buff *skb;
641 struct tipc_msg *hdr;
642
643 evt.event = event;
644 evt.found_lower = m->instance;
645 evt.found_upper = m->instance;
646 evt.port.ref = m->port;
647 evt.port.node = m->node;
648 evt.s.seq.type = grp->type;
649 evt.s.seq.lower = m->instance;
650 evt.s.seq.upper = m->instance;
651
652 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_GRP_MEMBER_EVT,
653 GROUP_H_SIZE, sizeof(evt), dnode, m->node,
654 grp->portid, m->port, 0);
655 if (!skb)
656 return;
657
658 hdr = buf_msg(skb);
659 msg_set_nametype(hdr, grp->type);
660 msg_set_grp_evt(hdr, event);
661 msg_set_dest_droppable(hdr, true);
662 msg_set_grp_bc_seqno(hdr, seqno);
663 memcpy(msg_data(hdr), &evt, sizeof(evt));
664 TIPC_SKB_CB(skb)->orig_member = m->instance;
665 __skb_queue_tail(inputq, skb);
666}
667
Jon Maloy75da2162017-10-13 11:04:23 +0200668static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
669 int mtyp, struct sk_buff_head *xmitq)
670{
671 struct tipc_msg *hdr;
672 struct sk_buff *skb;
Jon Maloyb7d42632017-10-13 11:04:26 +0200673 int adv = 0;
Jon Maloy75da2162017-10-13 11:04:23 +0200674
675 skb = tipc_msg_create(GROUP_PROTOCOL, mtyp, INT_H_SIZE, 0,
676 m->node, tipc_own_addr(grp->net),
677 m->port, grp->portid, 0);
678 if (!skb)
679 return;
680
Jon Maloy04d7b572017-10-13 11:04:34 +0200681 if (m->state == MBR_ACTIVE)
Jon Maloyb7d42632017-10-13 11:04:26 +0200682 adv = ADV_ACTIVE - m->advertised;
Jon Maloy04d7b572017-10-13 11:04:34 +0200683 else if (m->state == MBR_JOINED || m->state == MBR_PENDING)
684 adv = ADV_IDLE - m->advertised;
Jon Maloyb7d42632017-10-13 11:04:26 +0200685
Jon Maloy75da2162017-10-13 11:04:23 +0200686 hdr = buf_msg(skb);
Jon Maloyb7d42632017-10-13 11:04:26 +0200687
688 if (mtyp == GRP_JOIN_MSG) {
Jon Maloy75da2162017-10-13 11:04:23 +0200689 msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
Jon Maloyb7d42632017-10-13 11:04:26 +0200690 msg_set_adv_win(hdr, adv);
691 m->advertised += adv;
Jon Maloya3bada72017-10-13 11:04:33 +0200692 } else if (mtyp == GRP_LEAVE_MSG) {
693 msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
Jon Maloyb7d42632017-10-13 11:04:26 +0200694 } else if (mtyp == GRP_ADV_MSG) {
695 msg_set_adv_win(hdr, adv);
696 m->advertised += adv;
Jon Maloy2f487712017-10-13 11:04:31 +0200697 } else if (mtyp == GRP_ACK_MSG) {
698 msg_set_grp_bc_acked(hdr, m->bc_rcv_nxt);
Jon Maloy04d7b572017-10-13 11:04:34 +0200699 } else if (mtyp == GRP_REMIT_MSG) {
700 msg_set_grp_remitted(hdr, m->window);
Jon Maloyb7d42632017-10-13 11:04:26 +0200701 }
Jon Maloy23483392017-12-18 17:34:16 +0100702 msg_set_dest_droppable(hdr, true);
Jon Maloy75da2162017-10-13 11:04:23 +0200703 __skb_queue_tail(xmitq, skb);
704}
705
Jon Maloyb7d42632017-10-13 11:04:26 +0200706void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
707 struct tipc_msg *hdr, struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200708 struct sk_buff_head *xmitq)
709{
710 u32 node = msg_orignode(hdr);
711 u32 port = msg_origport(hdr);
Jon Maloy04d7b572017-10-13 11:04:34 +0200712 struct tipc_member *m, *pm;
Jon Maloy04d7b572017-10-13 11:04:34 +0200713 u16 remitted, in_flight;
Jon Maloy75da2162017-10-13 11:04:23 +0200714
715 if (!grp)
716 return;
717
718 m = tipc_group_find_member(grp, node, port);
719
720 switch (msg_type(hdr)) {
721 case GRP_JOIN_MSG:
722 if (!m)
723 m = tipc_group_create_member(grp, node, port,
Jon Maloy02334932018-01-08 21:03:25 +0100724 MBR_JOINING);
Jon Maloy75da2162017-10-13 11:04:23 +0200725 if (!m)
726 return;
Jon Maloya3bada72017-10-13 11:04:33 +0200727 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
728 m->bc_rcv_nxt = m->bc_syncpt;
Jon Maloyb7d42632017-10-13 11:04:26 +0200729 m->window += msg_adv_win(hdr);
Jon Maloy75da2162017-10-13 11:04:23 +0200730
731 /* Wait until PUBLISH event is received */
Jon Maloyae236fb2017-10-13 11:04:25 +0200732 if (m->state == MBR_DISCOVERED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200733 m->state = MBR_JOINING;
Jon Maloyae236fb2017-10-13 11:04:25 +0200734 } else if (m->state == MBR_PUBLISHED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200735 m->state = MBR_JOINED;
Jon Maloyb7d42632017-10-13 11:04:26 +0200736 *usr_wakeup = true;
737 m->usr_pending = false;
738 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100739 tipc_group_create_event(grp, m, TIPC_PUBLISHED,
740 m->bc_syncpt, inputq);
Jon Maloyae236fb2017-10-13 11:04:25 +0200741 }
Jon Maloy38266ca2018-01-04 15:20:44 +0100742 list_del_init(&m->small_win);
Jon Maloybb25c382017-12-20 11:03:15 +0100743 tipc_group_update_member(m, 0);
Jon Maloy75da2162017-10-13 11:04:23 +0200744 return;
745 case GRP_LEAVE_MSG:
746 if (!m)
747 return;
Jon Maloya3bada72017-10-13 11:04:33 +0200748 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100749 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100750 list_del_init(&m->small_win);
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100751 *usr_wakeup = true;
Jon Maloyc2b22bc2018-01-08 21:03:27 +0100752 tipc_group_decr_active(grp, m);
753 m->state = MBR_LEAVING;
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100754 tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
755 m->bc_syncpt, inputq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200756 return;
757 case GRP_ADV_MSG:
758 if (!m)
759 return;
760 m->window += msg_adv_win(hdr);
761 *usr_wakeup = m->usr_pending;
762 m->usr_pending = false;
Jon Maloy38266ca2018-01-04 15:20:44 +0100763 list_del_init(&m->small_win);
Jon Maloy75da2162017-10-13 11:04:23 +0200764 return;
Jon Maloy2f487712017-10-13 11:04:31 +0200765 case GRP_ACK_MSG:
766 if (!m)
767 return;
768 m->bc_acked = msg_grp_bc_acked(hdr);
769 if (--grp->bc_ackers)
770 break;
771 *usr_wakeup = true;
772 m->usr_pending = false;
773 return;
Jon Maloy04d7b572017-10-13 11:04:34 +0200774 case GRP_RECLAIM_MSG:
775 if (!m)
776 return;
777 *usr_wakeup = m->usr_pending;
778 m->usr_pending = false;
779 tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq);
780 m->window = ADV_IDLE;
781 return;
782 case GRP_REMIT_MSG:
783 if (!m || m->state != MBR_RECLAIMING)
784 return;
785
Jon Maloy04d7b572017-10-13 11:04:34 +0200786 remitted = msg_grp_remitted(hdr);
787
788 /* Messages preceding the REMIT still in receive queue */
789 if (m->advertised > remitted) {
790 m->state = MBR_REMITTED;
791 in_flight = m->advertised - remitted;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100792 m->advertised = ADV_IDLE + in_flight;
793 return;
Jon Maloy04d7b572017-10-13 11:04:34 +0200794 }
Jon Maloy8d5dee22018-01-08 21:03:23 +0100795 /* This should never happen */
Jon Maloy04d7b572017-10-13 11:04:34 +0200796 if (m->advertised < remitted)
Jon Maloy8d5dee22018-01-08 21:03:23 +0100797 pr_warn_ratelimited("Unexpected REMIT msg\n");
Jon Maloy04d7b572017-10-13 11:04:34 +0200798
Jon Maloy8d5dee22018-01-08 21:03:23 +0100799 /* All messages preceding the REMIT have been read */
800 m->state = MBR_JOINED;
Jon Maloyf9c935d2017-12-29 19:48:02 +0100801 grp->active_cnt--;
Jon Maloy8d5dee22018-01-08 21:03:23 +0100802 m->advertised = ADV_IDLE;
Jon Maloy04d7b572017-10-13 11:04:34 +0200803
804 /* Set oldest pending member to active and advertise */
805 if (list_empty(&grp->pending))
806 return;
807 pm = list_first_entry(&grp->pending, struct tipc_member, list);
808 pm->state = MBR_ACTIVE;
809 list_move_tail(&pm->list, &grp->active);
810 grp->active_cnt++;
811 if (pm->advertised <= (ADV_ACTIVE * 3 / 4))
812 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
813 return;
Jon Maloy75da2162017-10-13 11:04:23 +0200814 default:
815 pr_warn("Received unknown GROUP_PROTO message\n");
816 }
817}
818
Jon Maloyb7d42632017-10-13 11:04:26 +0200819/* tipc_group_member_evt() - receive and handle a member up/down event
820 */
Jon Maloy75da2162017-10-13 11:04:23 +0200821void tipc_group_member_evt(struct tipc_group *grp,
Jon Maloyb7d42632017-10-13 11:04:26 +0200822 bool *usr_wakeup,
823 int *sk_rcvbuf,
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100824 struct tipc_msg *hdr,
Jon Maloyae236fb2017-10-13 11:04:25 +0200825 struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200826 struct sk_buff_head *xmitq)
827{
Jon Maloy75da2162017-10-13 11:04:23 +0200828 struct tipc_event *evt = (void *)msg_data(hdr);
Jon Maloyae236fb2017-10-13 11:04:25 +0200829 u32 instance = evt->found_lower;
Jon Maloy75da2162017-10-13 11:04:23 +0200830 u32 node = evt->port.node;
831 u32 port = evt->port.ref;
Jon Maloyae236fb2017-10-13 11:04:25 +0200832 int event = evt->event;
Jon Maloy75da2162017-10-13 11:04:23 +0200833 struct tipc_member *m;
834 struct net *net;
835 u32 self;
836
837 if (!grp)
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100838 return;
Jon Maloy75da2162017-10-13 11:04:23 +0200839
840 net = grp->net;
841 self = tipc_own_addr(net);
842 if (!grp->loopback && node == self && port == grp->portid)
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100843 return;
Jon Maloyae236fb2017-10-13 11:04:25 +0200844
Jon Maloy75da2162017-10-13 11:04:23 +0200845 m = tipc_group_find_member(grp, node, port);
846
Jon Maloyae236fb2017-10-13 11:04:25 +0200847 if (event == TIPC_PUBLISHED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200848 if (!m)
849 m = tipc_group_create_member(grp, node, port,
850 MBR_DISCOVERED);
851 if (!m)
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100852 return;
853
854 m->instance = instance;
Jon Maloy75da2162017-10-13 11:04:23 +0200855
Jon Maloyae236fb2017-10-13 11:04:25 +0200856 /* Hold back event if JOIN message not yet received */
857 if (m->state == MBR_DISCOVERED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200858 m->state = MBR_PUBLISHED;
Jon Maloyae236fb2017-10-13 11:04:25 +0200859 } else {
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100860 tipc_group_create_event(grp, m, TIPC_PUBLISHED,
861 m->bc_syncpt, inputq);
Jon Maloy75da2162017-10-13 11:04:23 +0200862 m->state = MBR_JOINED;
Jon Maloyb7d42632017-10-13 11:04:26 +0200863 *usr_wakeup = true;
864 m->usr_pending = false;
Jon Maloyae236fb2017-10-13 11:04:25 +0200865 }
Jon Maloy75da2162017-10-13 11:04:23 +0200866 tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
Jon Maloyd84d1b32018-01-04 15:20:45 +0100867 tipc_group_update_member(m, 0);
Jon Maloyae236fb2017-10-13 11:04:25 +0200868 } else if (event == TIPC_WITHDRAWN) {
Jon Maloy75da2162017-10-13 11:04:23 +0200869 if (!m)
Jon Maloy7ad32bc2018-01-08 21:03:26 +0100870 return;
Jon Maloyae236fb2017-10-13 11:04:25 +0200871
Jon Maloy2f487712017-10-13 11:04:31 +0200872 *usr_wakeup = true;
Jon Maloyb7d42632017-10-13 11:04:26 +0200873 m->usr_pending = false;
Jon Maloyc2b22bc2018-01-08 21:03:27 +0100874 tipc_group_decr_active(grp, m);
875 m->state = MBR_LEAVING;
Jon Maloy3f42f5f2017-12-18 18:13:34 +0100876 list_del_init(&m->list);
Jon Maloy38266ca2018-01-04 15:20:44 +0100877 list_del_init(&m->small_win);
Jon Maloyc2b22bc2018-01-08 21:03:27 +0100878
879 /* Only send event if no LEAVE message can be expected */
880 if (!tipc_node_is_up(net, node))
881 tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
882 m->bc_rcv_nxt, inputq);
Jon Maloy75da2162017-10-13 11:04:23 +0200883 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200884 *sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
Jon Maloy75da2162017-10-13 11:04:23 +0200885}