blob: ffac2f33fce2b482b8763a8b715c2ad50289f970 [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 {
52 MBR_QUARANTINED,
53 MBR_DISCOVERED,
54 MBR_JOINING,
55 MBR_PUBLISHED,
56 MBR_JOINED,
57 MBR_LEAVING
58};
59
60struct tipc_member {
61 struct rb_node tree_node;
62 struct list_head list;
Jon Maloyb7d42632017-10-13 11:04:26 +020063 struct list_head congested;
Jon Maloyae236fb2017-10-13 11:04:25 +020064 struct sk_buff *event_msg;
Jon Maloyb7d42632017-10-13 11:04:26 +020065 struct tipc_group *group;
Jon Maloy75da2162017-10-13 11:04:23 +020066 u32 node;
67 u32 port;
Jon Maloy31c82a22017-10-13 11:04:24 +020068 u32 instance;
Jon Maloy75da2162017-10-13 11:04:23 +020069 enum mbr_state state;
Jon Maloyb7d42632017-10-13 11:04:26 +020070 u16 advertised;
71 u16 window;
Jon Maloy75da2162017-10-13 11:04:23 +020072 u16 bc_rcv_nxt;
Jon Maloyb7d42632017-10-13 11:04:26 +020073 bool usr_pending;
Jon Maloy75da2162017-10-13 11:04:23 +020074};
75
76struct tipc_group {
77 struct rb_root members;
Jon Maloyb7d42632017-10-13 11:04:26 +020078 struct list_head congested;
Jon Maloy75da2162017-10-13 11:04:23 +020079 struct tipc_nlist dests;
80 struct net *net;
81 int subid;
82 u32 type;
83 u32 instance;
84 u32 domain;
85 u32 scope;
86 u32 portid;
87 u16 member_cnt;
88 u16 bc_snd_nxt;
89 bool loopback;
Jon Maloyae236fb2017-10-13 11:04:25 +020090 bool events;
Jon Maloy75da2162017-10-13 11:04:23 +020091};
92
93static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
94 int mtyp, struct sk_buff_head *xmitq);
95
Jon Maloyb7d42632017-10-13 11:04:26 +020096static int tipc_group_rcvbuf_limit(struct tipc_group *grp)
97{
98 int mcnt = grp->member_cnt + 1;
99
100 /* Scale to bytes, considering worst-case truesize/msgsize ratio */
101 return mcnt * ADV_ACTIVE * FLOWCTL_BLK_SZ * 4;
102}
103
Jon Maloy75da2162017-10-13 11:04:23 +0200104u16 tipc_group_bc_snd_nxt(struct tipc_group *grp)
105{
106 return grp->bc_snd_nxt;
107}
108
Jon Maloyb7d42632017-10-13 11:04:26 +0200109static bool tipc_group_is_enabled(struct tipc_member *m)
110{
111 return m->state != MBR_QUARANTINED && m->state != MBR_LEAVING;
112}
113
Jon Maloy75da2162017-10-13 11:04:23 +0200114static bool tipc_group_is_receiver(struct tipc_member *m)
115{
116 return m && m->state >= MBR_JOINED;
117}
118
Jon Maloyee106d72017-10-13 11:04:28 +0200119u32 tipc_group_exclude(struct tipc_group *grp)
120{
121 if (!grp->loopback)
122 return grp->portid;
123 return 0;
124}
125
Jon Maloy75da2162017-10-13 11:04:23 +0200126int tipc_group_size(struct tipc_group *grp)
127{
128 return grp->member_cnt;
129}
130
131struct tipc_group *tipc_group_create(struct net *net, u32 portid,
132 struct tipc_group_req *mreq)
133{
134 struct tipc_group *grp;
135 u32 type = mreq->type;
136
137 grp = kzalloc(sizeof(*grp), GFP_ATOMIC);
138 if (!grp)
139 return NULL;
140 tipc_nlist_init(&grp->dests, tipc_own_addr(net));
Jon Maloyb7d42632017-10-13 11:04:26 +0200141 INIT_LIST_HEAD(&grp->congested);
Jon Maloy75da2162017-10-13 11:04:23 +0200142 grp->members = RB_ROOT;
143 grp->net = net;
144 grp->portid = portid;
145 grp->domain = addr_domain(net, mreq->scope);
146 grp->type = type;
147 grp->instance = mreq->instance;
148 grp->scope = mreq->scope;
149 grp->loopback = mreq->flags & TIPC_GROUP_LOOPBACK;
Jon Maloyae236fb2017-10-13 11:04:25 +0200150 grp->events = mreq->flags & TIPC_GROUP_MEMBER_EVTS;
Jon Maloy75da2162017-10-13 11:04:23 +0200151 if (tipc_topsrv_kern_subscr(net, portid, type, 0, ~0, &grp->subid))
152 return grp;
153 kfree(grp);
154 return NULL;
155}
156
157void tipc_group_delete(struct net *net, struct tipc_group *grp)
158{
159 struct rb_root *tree = &grp->members;
160 struct tipc_member *m, *tmp;
161 struct sk_buff_head xmitq;
162
163 __skb_queue_head_init(&xmitq);
164
165 rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
166 tipc_group_proto_xmit(grp, m, GRP_LEAVE_MSG, &xmitq);
167 list_del(&m->list);
168 kfree(m);
169 }
170 tipc_node_distr_xmit(net, &xmitq);
171 tipc_nlist_purge(&grp->dests);
172 tipc_topsrv_kern_unsubscr(net, grp->subid);
173 kfree(grp);
174}
175
176struct tipc_member *tipc_group_find_member(struct tipc_group *grp,
177 u32 node, u32 port)
178{
179 struct rb_node *n = grp->members.rb_node;
180 u64 nkey, key = (u64)node << 32 | port;
181 struct tipc_member *m;
182
183 while (n) {
184 m = container_of(n, struct tipc_member, tree_node);
185 nkey = (u64)m->node << 32 | m->port;
186 if (key < nkey)
187 n = n->rb_left;
188 else if (key > nkey)
189 n = n->rb_right;
190 else
191 return m;
192 }
193 return NULL;
194}
195
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200196static struct tipc_member *tipc_group_find_dest(struct tipc_group *grp,
197 u32 node, u32 port)
198{
199 struct tipc_member *m;
200
201 m = tipc_group_find_member(grp, node, port);
202 if (m && tipc_group_is_enabled(m))
203 return m;
204 return NULL;
205}
206
Jon Maloy75da2162017-10-13 11:04:23 +0200207static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
208 u32 node)
209{
210 struct tipc_member *m;
211 struct rb_node *n;
212
213 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
214 m = container_of(n, struct tipc_member, tree_node);
215 if (m->node == node)
216 return m;
217 }
218 return NULL;
219}
220
221static void tipc_group_add_to_tree(struct tipc_group *grp,
222 struct tipc_member *m)
223{
224 u64 nkey, key = (u64)m->node << 32 | m->port;
225 struct rb_node **n, *parent = NULL;
226 struct tipc_member *tmp;
227
228 n = &grp->members.rb_node;
229 while (*n) {
230 tmp = container_of(*n, struct tipc_member, tree_node);
231 parent = *n;
232 tmp = container_of(parent, struct tipc_member, tree_node);
233 nkey = (u64)tmp->node << 32 | tmp->port;
234 if (key < nkey)
235 n = &(*n)->rb_left;
236 else if (key > nkey)
237 n = &(*n)->rb_right;
238 else
239 return;
240 }
241 rb_link_node(&m->tree_node, parent, n);
242 rb_insert_color(&m->tree_node, &grp->members);
243}
244
245static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
246 u32 node, u32 port,
247 int state)
248{
249 struct tipc_member *m;
250
251 m = kzalloc(sizeof(*m), GFP_ATOMIC);
252 if (!m)
253 return NULL;
254 INIT_LIST_HEAD(&m->list);
Jon Maloyb7d42632017-10-13 11:04:26 +0200255 INIT_LIST_HEAD(&m->congested);
256 m->group = grp;
Jon Maloy75da2162017-10-13 11:04:23 +0200257 m->node = node;
258 m->port = port;
259 grp->member_cnt++;
260 tipc_group_add_to_tree(grp, m);
261 tipc_nlist_add(&grp->dests, m->node);
262 m->state = state;
263 return m;
264}
265
266void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port)
267{
268 tipc_group_create_member(grp, node, port, MBR_DISCOVERED);
269}
270
271static void tipc_group_delete_member(struct tipc_group *grp,
272 struct tipc_member *m)
273{
274 rb_erase(&m->tree_node, &grp->members);
275 grp->member_cnt--;
276 list_del_init(&m->list);
Jon Maloyb7d42632017-10-13 11:04:26 +0200277 list_del_init(&m->congested);
Jon Maloy75da2162017-10-13 11:04:23 +0200278
279 /* If last member on a node, remove node from dest list */
280 if (!tipc_group_find_node(grp, m->node))
281 tipc_nlist_del(&grp->dests, m->node);
282
283 kfree(m);
284}
285
286struct tipc_nlist *tipc_group_dests(struct tipc_group *grp)
287{
288 return &grp->dests;
289}
290
291void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
292 int *scope)
293{
294 seq->type = grp->type;
295 seq->lower = grp->instance;
296 seq->upper = grp->instance;
297 *scope = grp->scope;
298}
299
Jon Maloyb7d42632017-10-13 11:04:26 +0200300void tipc_group_update_member(struct tipc_member *m, int len)
Jon Maloy75da2162017-10-13 11:04:23 +0200301{
Jon Maloyb7d42632017-10-13 11:04:26 +0200302 struct tipc_group *grp = m->group;
303 struct tipc_member *_m, *tmp;
304
305 if (!tipc_group_is_enabled(m))
306 return;
307
308 m->window -= len;
309
310 if (m->window >= ADV_IDLE)
311 return;
312
313 if (!list_empty(&m->congested))
314 return;
315
316 /* Sort member into congested members' list */
317 list_for_each_entry_safe(_m, tmp, &grp->congested, congested) {
318 if (m->window > _m->window)
319 continue;
320 list_add_tail(&m->congested, &_m->congested);
321 return;
322 }
323 list_add_tail(&m->congested, &grp->congested);
324}
325
326void tipc_group_update_bc_members(struct tipc_group *grp, int len)
327{
328 struct tipc_member *m;
329 struct rb_node *n;
330
331 for (n = rb_first(&grp->members); n; n = rb_next(n)) {
332 m = container_of(n, struct tipc_member, tree_node);
333 if (tipc_group_is_enabled(m))
334 tipc_group_update_member(m, len);
335 }
Jon Maloy75da2162017-10-13 11:04:23 +0200336 grp->bc_snd_nxt++;
337}
338
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200339bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
340 int len, struct tipc_member **mbr)
341{
342 struct sk_buff_head xmitq;
343 struct tipc_member *m;
344 int adv, state;
345
346 m = tipc_group_find_dest(grp, dnode, dport);
347 *mbr = m;
348 if (!m)
349 return false;
350 if (m->usr_pending)
351 return true;
352 if (m->window >= len)
353 return false;
354 m->usr_pending = true;
355
356 /* If not fully advertised, do it now to prevent mutual blocking */
357 adv = m->advertised;
358 state = m->state;
359 if (state < MBR_JOINED)
360 return true;
361 if (state == MBR_JOINED && adv == ADV_IDLE)
362 return true;
363 skb_queue_head_init(&xmitq);
364 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, &xmitq);
365 tipc_node_distr_xmit(grp->net, &xmitq);
366 return true;
367}
368
Jon Maloyb7d42632017-10-13 11:04:26 +0200369bool tipc_group_bc_cong(struct tipc_group *grp, int len)
370{
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200371 struct tipc_member *m = NULL;
Jon Maloyb7d42632017-10-13 11:04:26 +0200372
373 if (list_empty(&grp->congested))
374 return false;
375
376 m = list_first_entry(&grp->congested, struct tipc_member, congested);
377 if (m->window >= len)
378 return false;
379
Jon Maloy27bd9ec2017-10-13 11:04:27 +0200380 return tipc_group_cong(grp, m->node, m->port, len, &m);
Jon Maloyb7d42632017-10-13 11:04:26 +0200381}
382
Jon Maloy75da2162017-10-13 11:04:23 +0200383/* tipc_group_filter_msg() - determine if we should accept arriving message
384 */
385void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
386 struct sk_buff_head *xmitq)
387{
388 struct sk_buff *skb = __skb_dequeue(inputq);
389 struct tipc_member *m;
390 struct tipc_msg *hdr;
391 u32 node, port;
392 int mtyp;
393
394 if (!skb)
395 return;
396
397 hdr = buf_msg(skb);
398 mtyp = msg_type(hdr);
399 node = msg_orignode(hdr);
400 port = msg_origport(hdr);
401
402 if (!msg_in_group(hdr))
403 goto drop;
404
Jon Maloyae236fb2017-10-13 11:04:25 +0200405 if (mtyp == TIPC_GRP_MEMBER_EVT) {
406 if (!grp->events)
407 goto drop;
408 __skb_queue_tail(inputq, skb);
409 return;
410 }
411
Jon Maloy75da2162017-10-13 11:04:23 +0200412 m = tipc_group_find_member(grp, node, port);
413 if (!tipc_group_is_receiver(m))
414 goto drop;
415
Jon Maloy5b8dddb2017-10-13 11:04:29 +0200416 m->bc_rcv_nxt = msg_grp_bc_seqno(hdr) + 1;
417
418 /* Drop multicast here if not for this member */
419 if (mtyp == TIPC_GRP_MCAST_MSG) {
420 if (msg_nameinst(hdr) != grp->instance) {
421 m->bc_rcv_nxt = msg_grp_bc_seqno(hdr) + 1;
422 tipc_group_update_rcv_win(grp, msg_blocks(hdr),
423 node, port, xmitq);
424 kfree_skb(skb);
425 return;
426 }
427 }
428
Jon Maloy31c82a22017-10-13 11:04:24 +0200429 TIPC_SKB_CB(skb)->orig_member = m->instance;
Jon Maloy75da2162017-10-13 11:04:23 +0200430 __skb_queue_tail(inputq, skb);
431
Jon Maloy75da2162017-10-13 11:04:23 +0200432 return;
433drop:
434 kfree_skb(skb);
435}
436
Jon Maloyb7d42632017-10-13 11:04:26 +0200437void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
438 u32 port, struct sk_buff_head *xmitq)
439{
440 struct tipc_member *m;
441
442 m = tipc_group_find_member(grp, node, port);
443 if (!m)
444 return;
445
446 m->advertised -= blks;
447
448 switch (m->state) {
449 case MBR_JOINED:
450 if (m->advertised <= (ADV_ACTIVE - ADV_UNIT))
451 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
452 break;
453 case MBR_DISCOVERED:
454 case MBR_JOINING:
455 case MBR_LEAVING:
456 default:
457 break;
458 }
459}
460
Jon Maloy75da2162017-10-13 11:04:23 +0200461static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
462 int mtyp, struct sk_buff_head *xmitq)
463{
464 struct tipc_msg *hdr;
465 struct sk_buff *skb;
Jon Maloyb7d42632017-10-13 11:04:26 +0200466 int adv = 0;
Jon Maloy75da2162017-10-13 11:04:23 +0200467
468 skb = tipc_msg_create(GROUP_PROTOCOL, mtyp, INT_H_SIZE, 0,
469 m->node, tipc_own_addr(grp->net),
470 m->port, grp->portid, 0);
471 if (!skb)
472 return;
473
Jon Maloyb7d42632017-10-13 11:04:26 +0200474 if (m->state == MBR_JOINED)
475 adv = ADV_ACTIVE - m->advertised;
476
Jon Maloy75da2162017-10-13 11:04:23 +0200477 hdr = buf_msg(skb);
Jon Maloyb7d42632017-10-13 11:04:26 +0200478
479 if (mtyp == GRP_JOIN_MSG) {
Jon Maloy75da2162017-10-13 11:04:23 +0200480 msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
Jon Maloyb7d42632017-10-13 11:04:26 +0200481 msg_set_adv_win(hdr, adv);
482 m->advertised += adv;
483 } else if (mtyp == GRP_ADV_MSG) {
484 msg_set_adv_win(hdr, adv);
485 m->advertised += adv;
486 }
Jon Maloy75da2162017-10-13 11:04:23 +0200487 __skb_queue_tail(xmitq, skb);
488}
489
Jon Maloyb7d42632017-10-13 11:04:26 +0200490void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
491 struct tipc_msg *hdr, struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200492 struct sk_buff_head *xmitq)
493{
494 u32 node = msg_orignode(hdr);
495 u32 port = msg_origport(hdr);
496 struct tipc_member *m;
497
498 if (!grp)
499 return;
500
501 m = tipc_group_find_member(grp, node, port);
502
503 switch (msg_type(hdr)) {
504 case GRP_JOIN_MSG:
505 if (!m)
506 m = tipc_group_create_member(grp, node, port,
507 MBR_QUARANTINED);
508 if (!m)
509 return;
510 m->bc_rcv_nxt = msg_grp_bc_syncpt(hdr);
Jon Maloyb7d42632017-10-13 11:04:26 +0200511 m->window += msg_adv_win(hdr);
Jon Maloy75da2162017-10-13 11:04:23 +0200512
513 /* Wait until PUBLISH event is received */
Jon Maloyae236fb2017-10-13 11:04:25 +0200514 if (m->state == MBR_DISCOVERED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200515 m->state = MBR_JOINING;
Jon Maloyae236fb2017-10-13 11:04:25 +0200516 } else if (m->state == MBR_PUBLISHED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200517 m->state = MBR_JOINED;
Jon Maloyb7d42632017-10-13 11:04:26 +0200518 *usr_wakeup = true;
519 m->usr_pending = false;
520 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
Jon Maloyae236fb2017-10-13 11:04:25 +0200521 __skb_queue_tail(inputq, m->event_msg);
522 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200523 if (m->window < ADV_IDLE)
524 tipc_group_update_member(m, 0);
525 else
526 list_del_init(&m->congested);
Jon Maloy75da2162017-10-13 11:04:23 +0200527 return;
528 case GRP_LEAVE_MSG:
529 if (!m)
530 return;
531
532 /* Wait until WITHDRAW event is received */
533 if (m->state != MBR_LEAVING) {
534 m->state = MBR_LEAVING;
535 return;
536 }
537 /* Otherwise deliver already received WITHDRAW event */
Jon Maloyae236fb2017-10-13 11:04:25 +0200538 __skb_queue_tail(inputq, m->event_msg);
Jon Maloyb7d42632017-10-13 11:04:26 +0200539 *usr_wakeup = m->usr_pending;
Jon Maloy75da2162017-10-13 11:04:23 +0200540 tipc_group_delete_member(grp, m);
Jon Maloyb7d42632017-10-13 11:04:26 +0200541 list_del_init(&m->congested);
542 return;
543 case GRP_ADV_MSG:
544 if (!m)
545 return;
546 m->window += msg_adv_win(hdr);
547 *usr_wakeup = m->usr_pending;
548 m->usr_pending = false;
549 list_del_init(&m->congested);
Jon Maloy75da2162017-10-13 11:04:23 +0200550 return;
551 default:
552 pr_warn("Received unknown GROUP_PROTO message\n");
553 }
554}
555
Jon Maloyb7d42632017-10-13 11:04:26 +0200556/* tipc_group_member_evt() - receive and handle a member up/down event
557 */
Jon Maloy75da2162017-10-13 11:04:23 +0200558void tipc_group_member_evt(struct tipc_group *grp,
Jon Maloyb7d42632017-10-13 11:04:26 +0200559 bool *usr_wakeup,
560 int *sk_rcvbuf,
Jon Maloy75da2162017-10-13 11:04:23 +0200561 struct sk_buff *skb,
Jon Maloyae236fb2017-10-13 11:04:25 +0200562 struct sk_buff_head *inputq,
Jon Maloy75da2162017-10-13 11:04:23 +0200563 struct sk_buff_head *xmitq)
564{
565 struct tipc_msg *hdr = buf_msg(skb);
566 struct tipc_event *evt = (void *)msg_data(hdr);
Jon Maloyae236fb2017-10-13 11:04:25 +0200567 u32 instance = evt->found_lower;
Jon Maloy75da2162017-10-13 11:04:23 +0200568 u32 node = evt->port.node;
569 u32 port = evt->port.ref;
Jon Maloyae236fb2017-10-13 11:04:25 +0200570 int event = evt->event;
Jon Maloy75da2162017-10-13 11:04:23 +0200571 struct tipc_member *m;
572 struct net *net;
573 u32 self;
574
575 if (!grp)
576 goto drop;
577
578 net = grp->net;
579 self = tipc_own_addr(net);
580 if (!grp->loopback && node == self && port == grp->portid)
581 goto drop;
582
Jon Maloyae236fb2017-10-13 11:04:25 +0200583 /* Convert message before delivery to user */
584 msg_set_hdr_sz(hdr, GROUP_H_SIZE);
585 msg_set_user(hdr, TIPC_CRITICAL_IMPORTANCE);
586 msg_set_type(hdr, TIPC_GRP_MEMBER_EVT);
587 msg_set_origport(hdr, port);
588 msg_set_orignode(hdr, node);
589 msg_set_nametype(hdr, grp->type);
590 msg_set_grp_evt(hdr, event);
591
Jon Maloy75da2162017-10-13 11:04:23 +0200592 m = tipc_group_find_member(grp, node, port);
593
Jon Maloyae236fb2017-10-13 11:04:25 +0200594 if (event == TIPC_PUBLISHED) {
Jon Maloy75da2162017-10-13 11:04:23 +0200595 if (!m)
596 m = tipc_group_create_member(grp, node, port,
597 MBR_DISCOVERED);
598 if (!m)
599 goto drop;
600
Jon Maloyae236fb2017-10-13 11:04:25 +0200601 /* Hold back event if JOIN message not yet received */
602 if (m->state == MBR_DISCOVERED) {
603 m->event_msg = skb;
Jon Maloy75da2162017-10-13 11:04:23 +0200604 m->state = MBR_PUBLISHED;
Jon Maloyae236fb2017-10-13 11:04:25 +0200605 } else {
606 __skb_queue_tail(inputq, skb);
Jon Maloy75da2162017-10-13 11:04:23 +0200607 m->state = MBR_JOINED;
Jon Maloyb7d42632017-10-13 11:04:26 +0200608 *usr_wakeup = true;
609 m->usr_pending = false;
Jon Maloyae236fb2017-10-13 11:04:25 +0200610 }
611 m->instance = instance;
612 TIPC_SKB_CB(skb)->orig_member = m->instance;
Jon Maloy75da2162017-10-13 11:04:23 +0200613 tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
Jon Maloyb7d42632017-10-13 11:04:26 +0200614 if (m->window < ADV_IDLE)
615 tipc_group_update_member(m, 0);
616 else
617 list_del_init(&m->congested);
Jon Maloyae236fb2017-10-13 11:04:25 +0200618 } else if (event == TIPC_WITHDRAWN) {
Jon Maloy75da2162017-10-13 11:04:23 +0200619 if (!m)
620 goto drop;
621
Jon Maloyae236fb2017-10-13 11:04:25 +0200622 TIPC_SKB_CB(skb)->orig_member = m->instance;
623
Jon Maloyb7d42632017-10-13 11:04:26 +0200624 *usr_wakeup = m->usr_pending;
625 m->usr_pending = false;
626
Jon Maloyae236fb2017-10-13 11:04:25 +0200627 /* Hold back event if more messages might be expected */
628 if (m->state != MBR_LEAVING && tipc_node_is_up(net, node)) {
629 m->event_msg = skb;
Jon Maloy75da2162017-10-13 11:04:23 +0200630 m->state = MBR_LEAVING;
Jon Maloyae236fb2017-10-13 11:04:25 +0200631 } else {
632 __skb_queue_tail(inputq, skb);
Jon Maloy75da2162017-10-13 11:04:23 +0200633 tipc_group_delete_member(grp, m);
Jon Maloyae236fb2017-10-13 11:04:25 +0200634 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200635 list_del_init(&m->congested);
Jon Maloy75da2162017-10-13 11:04:23 +0200636 }
Jon Maloyb7d42632017-10-13 11:04:26 +0200637 *sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
Jon Maloyae236fb2017-10-13 11:04:25 +0200638 return;
Jon Maloy75da2162017-10-13 11:04:23 +0200639drop:
640 kfree_skb(skb);
641}