]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - net/tipc/group.c
16aaaa97a005c810cb20bb1be9992d925fe8ac07
2 * net/tipc/group.c: TIPC group messaging code
4 * Copyright (c) 2017, Ericsson AB
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
44 #include "name_table.h"
47 #define ADV_UNIT (((MAX_MSG_SIZE + MAX_H_SIZE) / FLOWCTL_BLK_SZ) + 1)
48 #define ADV_IDLE ADV_UNIT
49 #define ADV_ACTIVE (ADV_UNIT * 12)
61 struct rb_node tree_node
;
62 struct list_head list
;
63 struct list_head congested
;
64 struct sk_buff
*event_msg
;
65 struct tipc_group
*group
;
77 struct rb_root members
;
78 struct list_head congested
;
79 struct tipc_nlist dests
;
93 static void tipc_group_proto_xmit(struct tipc_group
*grp
, struct tipc_member
*m
,
94 int mtyp
, struct sk_buff_head
*xmitq
);
96 static int tipc_group_rcvbuf_limit(struct tipc_group
*grp
)
98 int mcnt
= grp
->member_cnt
+ 1;
100 /* Scale to bytes, considering worst-case truesize/msgsize ratio */
101 return mcnt
* ADV_ACTIVE
* FLOWCTL_BLK_SZ
* 4;
104 u16
tipc_group_bc_snd_nxt(struct tipc_group
*grp
)
106 return grp
->bc_snd_nxt
;
109 static bool tipc_group_is_enabled(struct tipc_member
*m
)
111 return m
->state
!= MBR_QUARANTINED
&& m
->state
!= MBR_LEAVING
;
114 static bool tipc_group_is_receiver(struct tipc_member
*m
)
116 return m
&& m
->state
>= MBR_JOINED
;
119 u32
tipc_group_exclude(struct tipc_group
*grp
)
126 int tipc_group_size(struct tipc_group
*grp
)
128 return grp
->member_cnt
;
131 struct tipc_group
*tipc_group_create(struct net
*net
, u32 portid
,
132 struct tipc_group_req
*mreq
)
134 struct tipc_group
*grp
;
135 u32 type
= mreq
->type
;
137 grp
= kzalloc(sizeof(*grp
), GFP_ATOMIC
);
140 tipc_nlist_init(&grp
->dests
, tipc_own_addr(net
));
141 INIT_LIST_HEAD(&grp
->congested
);
142 grp
->members
= RB_ROOT
;
144 grp
->portid
= portid
;
145 grp
->domain
= addr_domain(net
, mreq
->scope
);
147 grp
->instance
= mreq
->instance
;
148 grp
->scope
= mreq
->scope
;
149 grp
->loopback
= mreq
->flags
& TIPC_GROUP_LOOPBACK
;
150 grp
->events
= mreq
->flags
& TIPC_GROUP_MEMBER_EVTS
;
151 if (tipc_topsrv_kern_subscr(net
, portid
, type
, 0, ~0, &grp
->subid
))
157 void tipc_group_delete(struct net
*net
, struct tipc_group
*grp
)
159 struct rb_root
*tree
= &grp
->members
;
160 struct tipc_member
*m
, *tmp
;
161 struct sk_buff_head xmitq
;
163 __skb_queue_head_init(&xmitq
);
165 rbtree_postorder_for_each_entry_safe(m
, tmp
, tree
, tree_node
) {
166 tipc_group_proto_xmit(grp
, m
, GRP_LEAVE_MSG
, &xmitq
);
170 tipc_node_distr_xmit(net
, &xmitq
);
171 tipc_nlist_purge(&grp
->dests
);
172 tipc_topsrv_kern_unsubscr(net
, grp
->subid
);
176 struct tipc_member
*tipc_group_find_member(struct tipc_group
*grp
,
179 struct rb_node
*n
= grp
->members
.rb_node
;
180 u64 nkey
, key
= (u64
)node
<< 32 | port
;
181 struct tipc_member
*m
;
184 m
= container_of(n
, struct tipc_member
, tree_node
);
185 nkey
= (u64
)m
->node
<< 32 | m
->port
;
196 static struct tipc_member
*tipc_group_find_dest(struct tipc_group
*grp
,
199 struct tipc_member
*m
;
201 m
= tipc_group_find_member(grp
, node
, port
);
202 if (m
&& tipc_group_is_enabled(m
))
207 static struct tipc_member
*tipc_group_find_node(struct tipc_group
*grp
,
210 struct tipc_member
*m
;
213 for (n
= rb_first(&grp
->members
); n
; n
= rb_next(n
)) {
214 m
= container_of(n
, struct tipc_member
, tree_node
);
221 static void tipc_group_add_to_tree(struct tipc_group
*grp
,
222 struct tipc_member
*m
)
224 u64 nkey
, key
= (u64
)m
->node
<< 32 | m
->port
;
225 struct rb_node
**n
, *parent
= NULL
;
226 struct tipc_member
*tmp
;
228 n
= &grp
->members
.rb_node
;
230 tmp
= container_of(*n
, struct tipc_member
, tree_node
);
232 tmp
= container_of(parent
, struct tipc_member
, tree_node
);
233 nkey
= (u64
)tmp
->node
<< 32 | tmp
->port
;
241 rb_link_node(&m
->tree_node
, parent
, n
);
242 rb_insert_color(&m
->tree_node
, &grp
->members
);
245 static struct tipc_member
*tipc_group_create_member(struct tipc_group
*grp
,
249 struct tipc_member
*m
;
251 m
= kzalloc(sizeof(*m
), GFP_ATOMIC
);
254 INIT_LIST_HEAD(&m
->list
);
255 INIT_LIST_HEAD(&m
->congested
);
260 tipc_group_add_to_tree(grp
, m
);
261 tipc_nlist_add(&grp
->dests
, m
->node
);
266 void tipc_group_add_member(struct tipc_group
*grp
, u32 node
, u32 port
)
268 tipc_group_create_member(grp
, node
, port
, MBR_DISCOVERED
);
271 static void tipc_group_delete_member(struct tipc_group
*grp
,
272 struct tipc_member
*m
)
274 rb_erase(&m
->tree_node
, &grp
->members
);
276 list_del_init(&m
->list
);
277 list_del_init(&m
->congested
);
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
);
286 struct tipc_nlist
*tipc_group_dests(struct tipc_group
*grp
)
291 void tipc_group_self(struct tipc_group
*grp
, struct tipc_name_seq
*seq
,
294 seq
->type
= grp
->type
;
295 seq
->lower
= grp
->instance
;
296 seq
->upper
= grp
->instance
;
300 void tipc_group_update_member(struct tipc_member
*m
, int len
)
302 struct tipc_group
*grp
= m
->group
;
303 struct tipc_member
*_m
, *tmp
;
305 if (!tipc_group_is_enabled(m
))
310 if (m
->window
>= ADV_IDLE
)
313 if (!list_empty(&m
->congested
))
316 /* Sort member into congested members' list */
317 list_for_each_entry_safe(_m
, tmp
, &grp
->congested
, congested
) {
318 if (m
->window
> _m
->window
)
320 list_add_tail(&m
->congested
, &_m
->congested
);
323 list_add_tail(&m
->congested
, &grp
->congested
);
326 void tipc_group_update_bc_members(struct tipc_group
*grp
, int len
)
328 struct tipc_member
*m
;
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
);
339 bool tipc_group_cong(struct tipc_group
*grp
, u32 dnode
, u32 dport
,
340 int len
, struct tipc_member
**mbr
)
342 struct sk_buff_head xmitq
;
343 struct tipc_member
*m
;
346 m
= tipc_group_find_dest(grp
, dnode
, dport
);
352 if (m
->window
>= len
)
354 m
->usr_pending
= true;
356 /* If not fully advertised, do it now to prevent mutual blocking */
359 if (state
< MBR_JOINED
)
361 if (state
== MBR_JOINED
&& adv
== ADV_IDLE
)
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
);
369 bool tipc_group_bc_cong(struct tipc_group
*grp
, int len
)
371 struct tipc_member
*m
= NULL
;
373 if (list_empty(&grp
->congested
))
376 m
= list_first_entry(&grp
->congested
, struct tipc_member
, congested
);
377 if (m
->window
>= len
)
380 return tipc_group_cong(grp
, m
->node
, m
->port
, len
, &m
);
383 /* tipc_group_filter_msg() - determine if we should accept arriving message
385 void tipc_group_filter_msg(struct tipc_group
*grp
, struct sk_buff_head
*inputq
,
386 struct sk_buff_head
*xmitq
)
388 struct sk_buff
*skb
= __skb_dequeue(inputq
);
389 struct tipc_member
*m
;
390 struct tipc_msg
*hdr
;
398 mtyp
= msg_type(hdr
);
399 node
= msg_orignode(hdr
);
400 port
= msg_origport(hdr
);
402 if (!msg_in_group(hdr
))
405 if (mtyp
== TIPC_GRP_MEMBER_EVT
) {
408 __skb_queue_tail(inputq
, skb
);
412 m
= tipc_group_find_member(grp
, node
, port
);
413 if (!tipc_group_is_receiver(m
))
416 TIPC_SKB_CB(skb
)->orig_member
= m
->instance
;
417 __skb_queue_tail(inputq
, skb
);
419 m
->bc_rcv_nxt
= msg_grp_bc_seqno(hdr
) + 1;
425 void tipc_group_update_rcv_win(struct tipc_group
*grp
, int blks
, u32 node
,
426 u32 port
, struct sk_buff_head
*xmitq
)
428 struct tipc_member
*m
;
430 m
= tipc_group_find_member(grp
, node
, port
);
434 m
->advertised
-= blks
;
438 if (m
->advertised
<= (ADV_ACTIVE
- ADV_UNIT
))
439 tipc_group_proto_xmit(grp
, m
, GRP_ADV_MSG
, xmitq
);
449 static void tipc_group_proto_xmit(struct tipc_group
*grp
, struct tipc_member
*m
,
450 int mtyp
, struct sk_buff_head
*xmitq
)
452 struct tipc_msg
*hdr
;
456 skb
= tipc_msg_create(GROUP_PROTOCOL
, mtyp
, INT_H_SIZE
, 0,
457 m
->node
, tipc_own_addr(grp
->net
),
458 m
->port
, grp
->portid
, 0);
462 if (m
->state
== MBR_JOINED
)
463 adv
= ADV_ACTIVE
- m
->advertised
;
467 if (mtyp
== GRP_JOIN_MSG
) {
468 msg_set_grp_bc_syncpt(hdr
, grp
->bc_snd_nxt
);
469 msg_set_adv_win(hdr
, adv
);
470 m
->advertised
+= adv
;
471 } else if (mtyp
== GRP_ADV_MSG
) {
472 msg_set_adv_win(hdr
, adv
);
473 m
->advertised
+= adv
;
475 __skb_queue_tail(xmitq
, skb
);
478 void tipc_group_proto_rcv(struct tipc_group
*grp
, bool *usr_wakeup
,
479 struct tipc_msg
*hdr
, struct sk_buff_head
*inputq
,
480 struct sk_buff_head
*xmitq
)
482 u32 node
= msg_orignode(hdr
);
483 u32 port
= msg_origport(hdr
);
484 struct tipc_member
*m
;
489 m
= tipc_group_find_member(grp
, node
, port
);
491 switch (msg_type(hdr
)) {
494 m
= tipc_group_create_member(grp
, node
, port
,
498 m
->bc_rcv_nxt
= msg_grp_bc_syncpt(hdr
);
499 m
->window
+= msg_adv_win(hdr
);
501 /* Wait until PUBLISH event is received */
502 if (m
->state
== MBR_DISCOVERED
) {
503 m
->state
= MBR_JOINING
;
504 } else if (m
->state
== MBR_PUBLISHED
) {
505 m
->state
= MBR_JOINED
;
507 m
->usr_pending
= false;
508 tipc_group_proto_xmit(grp
, m
, GRP_ADV_MSG
, xmitq
);
509 __skb_queue_tail(inputq
, m
->event_msg
);
511 if (m
->window
< ADV_IDLE
)
512 tipc_group_update_member(m
, 0);
514 list_del_init(&m
->congested
);
520 /* Wait until WITHDRAW event is received */
521 if (m
->state
!= MBR_LEAVING
) {
522 m
->state
= MBR_LEAVING
;
525 /* Otherwise deliver already received WITHDRAW event */
526 __skb_queue_tail(inputq
, m
->event_msg
);
527 *usr_wakeup
= m
->usr_pending
;
528 tipc_group_delete_member(grp
, m
);
529 list_del_init(&m
->congested
);
534 m
->window
+= msg_adv_win(hdr
);
535 *usr_wakeup
= m
->usr_pending
;
536 m
->usr_pending
= false;
537 list_del_init(&m
->congested
);
540 pr_warn("Received unknown GROUP_PROTO message\n");
544 /* tipc_group_member_evt() - receive and handle a member up/down event
546 void tipc_group_member_evt(struct tipc_group
*grp
,
550 struct sk_buff_head
*inputq
,
551 struct sk_buff_head
*xmitq
)
553 struct tipc_msg
*hdr
= buf_msg(skb
);
554 struct tipc_event
*evt
= (void *)msg_data(hdr
);
555 u32 instance
= evt
->found_lower
;
556 u32 node
= evt
->port
.node
;
557 u32 port
= evt
->port
.ref
;
558 int event
= evt
->event
;
559 struct tipc_member
*m
;
567 self
= tipc_own_addr(net
);
568 if (!grp
->loopback
&& node
== self
&& port
== grp
->portid
)
571 /* Convert message before delivery to user */
572 msg_set_hdr_sz(hdr
, GROUP_H_SIZE
);
573 msg_set_user(hdr
, TIPC_CRITICAL_IMPORTANCE
);
574 msg_set_type(hdr
, TIPC_GRP_MEMBER_EVT
);
575 msg_set_origport(hdr
, port
);
576 msg_set_orignode(hdr
, node
);
577 msg_set_nametype(hdr
, grp
->type
);
578 msg_set_grp_evt(hdr
, event
);
580 m
= tipc_group_find_member(grp
, node
, port
);
582 if (event
== TIPC_PUBLISHED
) {
584 m
= tipc_group_create_member(grp
, node
, port
,
589 /* Hold back event if JOIN message not yet received */
590 if (m
->state
== MBR_DISCOVERED
) {
592 m
->state
= MBR_PUBLISHED
;
594 __skb_queue_tail(inputq
, skb
);
595 m
->state
= MBR_JOINED
;
597 m
->usr_pending
= false;
599 m
->instance
= instance
;
600 TIPC_SKB_CB(skb
)->orig_member
= m
->instance
;
601 tipc_group_proto_xmit(grp
, m
, GRP_JOIN_MSG
, xmitq
);
602 if (m
->window
< ADV_IDLE
)
603 tipc_group_update_member(m
, 0);
605 list_del_init(&m
->congested
);
606 } else if (event
== TIPC_WITHDRAWN
) {
610 TIPC_SKB_CB(skb
)->orig_member
= m
->instance
;
612 *usr_wakeup
= m
->usr_pending
;
613 m
->usr_pending
= false;
615 /* Hold back event if more messages might be expected */
616 if (m
->state
!= MBR_LEAVING
&& tipc_node_is_up(net
, node
)) {
618 m
->state
= MBR_LEAVING
;
620 __skb_queue_tail(inputq
, skb
);
621 tipc_group_delete_member(grp
, m
);
623 list_del_init(&m
->congested
);
625 *sk_rcvbuf
= tipc_group_rcvbuf_limit(grp
);