group.c 22.1 KB
Newer Older
J
Jon Maloy 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/*
 * net/tipc/group.c: TIPC group messaging code
 *
 * Copyright (c) 2017, Ericsson AB
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "core.h"
#include "addr.h"
#include "group.h"
#include "bcast.h"
#include "server.h"
#include "msg.h"
#include "socket.h"
#include "node.h"
#include "name_table.h"
#include "subscr.h"

#define ADV_UNIT (((MAX_MSG_SIZE + MAX_H_SIZE) / FLOWCTL_BLK_SZ) + 1)
#define ADV_IDLE ADV_UNIT
49
#define ADV_ACTIVE (ADV_UNIT * 12)
J
Jon Maloy 已提交
50 51 52 53 54 55 56

enum mbr_state {
	MBR_QUARANTINED,
	MBR_DISCOVERED,
	MBR_JOINING,
	MBR_PUBLISHED,
	MBR_JOINED,
57 58 59 60
	MBR_PENDING,
	MBR_ACTIVE,
	MBR_RECLAIMING,
	MBR_REMITTED,
J
Jon Maloy 已提交
61 62 63 64 65 66
	MBR_LEAVING
};

struct tipc_member {
	struct rb_node tree_node;
	struct list_head list;
J
Jon Maloy 已提交
67
	struct list_head small_win;
68
	struct sk_buff *event_msg;
69
	struct sk_buff_head deferredq;
70
	struct tipc_group *group;
J
Jon Maloy 已提交
71 72
	u32 node;
	u32 port;
73
	u32 instance;
J
Jon Maloy 已提交
74
	enum mbr_state state;
75 76
	u16 advertised;
	u16 window;
J
Jon Maloy 已提交
77
	u16 bc_rcv_nxt;
78
	u16 bc_syncpt;
79
	u16 bc_acked;
80
	bool usr_pending;
J
Jon Maloy 已提交
81 82 83 84
};

struct tipc_group {
	struct rb_root members;
J
Jon Maloy 已提交
85
	struct list_head small_win;
86 87
	struct list_head pending;
	struct list_head active;
J
Jon Maloy 已提交
88 89 90 91 92 93 94 95 96
	struct tipc_nlist dests;
	struct net *net;
	int subid;
	u32 type;
	u32 instance;
	u32 domain;
	u32 scope;
	u32 portid;
	u16 member_cnt;
97 98
	u16 active_cnt;
	u16 max_active;
J
Jon Maloy 已提交
99
	u16 bc_snd_nxt;
100
	u16 bc_ackers;
J
Jon Maloy 已提交
101
	bool loopback;
102
	bool events;
J
Jon Maloy 已提交
103 104 105 106 107
};

static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
				  int mtyp, struct sk_buff_head *xmitq);

108 109 110
static void tipc_group_decr_active(struct tipc_group *grp,
				   struct tipc_member *m)
{
111 112
	if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING ||
	    m->state == MBR_REMITTED)
113 114 115
		grp->active_cnt--;
}

116 117
static int tipc_group_rcvbuf_limit(struct tipc_group *grp)
{
118
	int max_active, active_pool, idle_pool;
119 120
	int mcnt = grp->member_cnt + 1;

121 122 123 124 125 126 127 128 129
	/* Limit simultaneous reception from other members */
	max_active = min(mcnt / 8, 64);
	max_active = max(max_active, 16);
	grp->max_active = max_active;

	/* Reserve blocks for active and idle members */
	active_pool = max_active * ADV_ACTIVE;
	idle_pool = (mcnt - max_active) * ADV_IDLE;

130
	/* Scale to bytes, considering worst-case truesize/msgsize ratio */
131
	return (active_pool + idle_pool) * FLOWCTL_BLK_SZ * 4;
132 133
}

J
Jon Maloy 已提交
134 135 136 137 138
u16 tipc_group_bc_snd_nxt(struct tipc_group *grp)
{
	return grp->bc_snd_nxt;
}

J
Jon Maloy 已提交
139
static bool tipc_group_is_receiver(struct tipc_member *m)
140 141 142 143
{
	return m->state != MBR_QUARANTINED && m->state != MBR_LEAVING;
}

J
Jon Maloy 已提交
144
static bool tipc_group_is_sender(struct tipc_member *m)
J
Jon Maloy 已提交
145 146 147 148
{
	return m && m->state >= MBR_JOINED;
}

149 150 151 152 153 154 155
u32 tipc_group_exclude(struct tipc_group *grp)
{
	if (!grp->loopback)
		return grp->portid;
	return 0;
}

J
Jon Maloy 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
int tipc_group_size(struct tipc_group *grp)
{
	return grp->member_cnt;
}

struct tipc_group *tipc_group_create(struct net *net, u32 portid,
				     struct tipc_group_req *mreq)
{
	struct tipc_group *grp;
	u32 type = mreq->type;

	grp = kzalloc(sizeof(*grp), GFP_ATOMIC);
	if (!grp)
		return NULL;
	tipc_nlist_init(&grp->dests, tipc_own_addr(net));
J
Jon Maloy 已提交
171
	INIT_LIST_HEAD(&grp->small_win);
172 173
	INIT_LIST_HEAD(&grp->active);
	INIT_LIST_HEAD(&grp->pending);
J
Jon Maloy 已提交
174 175 176 177 178 179 180 181
	grp->members = RB_ROOT;
	grp->net = net;
	grp->portid = portid;
	grp->domain = addr_domain(net, mreq->scope);
	grp->type = type;
	grp->instance = mreq->instance;
	grp->scope = mreq->scope;
	grp->loopback = mreq->flags & TIPC_GROUP_LOOPBACK;
182
	grp->events = mreq->flags & TIPC_GROUP_MEMBER_EVTS;
J
Jon Maloy 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	if (tipc_topsrv_kern_subscr(net, portid, type, 0, ~0, &grp->subid))
		return grp;
	kfree(grp);
	return NULL;
}

void tipc_group_delete(struct net *net, struct tipc_group *grp)
{
	struct rb_root *tree = &grp->members;
	struct tipc_member *m, *tmp;
	struct sk_buff_head xmitq;

	__skb_queue_head_init(&xmitq);

	rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
		tipc_group_proto_xmit(grp, m, GRP_LEAVE_MSG, &xmitq);
		list_del(&m->list);
		kfree(m);
	}
	tipc_node_distr_xmit(net, &xmitq);
	tipc_nlist_purge(&grp->dests);
	tipc_topsrv_kern_unsubscr(net, grp->subid);
	kfree(grp);
}

struct tipc_member *tipc_group_find_member(struct tipc_group *grp,
					   u32 node, u32 port)
{
	struct rb_node *n = grp->members.rb_node;
	u64 nkey, key = (u64)node << 32 | port;
	struct tipc_member *m;

	while (n) {
		m = container_of(n, struct tipc_member, tree_node);
		nkey = (u64)m->node << 32 | m->port;
		if (key < nkey)
			n = n->rb_left;
		else if (key > nkey)
			n = n->rb_right;
		else
			return m;
	}
	return NULL;
}

228 229 230 231 232 233
static struct tipc_member *tipc_group_find_dest(struct tipc_group *grp,
						u32 node, u32 port)
{
	struct tipc_member *m;

	m = tipc_group_find_member(grp, node, port);
J
Jon Maloy 已提交
234
	if (m && tipc_group_is_receiver(m))
235 236 237 238
		return m;
	return NULL;
}

J
Jon Maloy 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
						u32 node)
{
	struct tipc_member *m;
	struct rb_node *n;

	for (n = rb_first(&grp->members); n; n = rb_next(n)) {
		m = container_of(n, struct tipc_member, tree_node);
		if (m->node == node)
			return m;
	}
	return NULL;
}

static void tipc_group_add_to_tree(struct tipc_group *grp,
				   struct tipc_member *m)
{
	u64 nkey, key = (u64)m->node << 32 | m->port;
	struct rb_node **n, *parent = NULL;
	struct tipc_member *tmp;

	n = &grp->members.rb_node;
	while (*n) {
		tmp = container_of(*n, struct tipc_member, tree_node);
		parent = *n;
		tmp = container_of(parent, struct tipc_member, tree_node);
		nkey = (u64)tmp->node << 32 | tmp->port;
		if (key < nkey)
			n = &(*n)->rb_left;
		else if (key > nkey)
			n = &(*n)->rb_right;
		else
			return;
	}
	rb_link_node(&m->tree_node, parent, n);
	rb_insert_color(&m->tree_node, &grp->members);
}

static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
						    u32 node, u32 port,
						    int state)
{
	struct tipc_member *m;

	m = kzalloc(sizeof(*m), GFP_ATOMIC);
	if (!m)
		return NULL;
	INIT_LIST_HEAD(&m->list);
J
Jon Maloy 已提交
287
	INIT_LIST_HEAD(&m->small_win);
288
	__skb_queue_head_init(&m->deferredq);
289
	m->group = grp;
J
Jon Maloy 已提交
290 291
	m->node = node;
	m->port = port;
292
	m->bc_acked = grp->bc_snd_nxt - 1;
J
Jon Maloy 已提交
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
	grp->member_cnt++;
	tipc_group_add_to_tree(grp, m);
	tipc_nlist_add(&grp->dests, m->node);
	m->state = state;
	return m;
}

void tipc_group_add_member(struct tipc_group *grp, u32 node, u32 port)
{
	tipc_group_create_member(grp, node, port, MBR_DISCOVERED);
}

static void tipc_group_delete_member(struct tipc_group *grp,
				     struct tipc_member *m)
{
	rb_erase(&m->tree_node, &grp->members);
	grp->member_cnt--;
310 311 312 313 314

	/* Check if we were waiting for replicast ack from this member */
	if (grp->bc_ackers && less(m->bc_acked, grp->bc_snd_nxt - 1))
		grp->bc_ackers--;

J
Jon Maloy 已提交
315
	list_del_init(&m->list);
J
Jon Maloy 已提交
316
	list_del_init(&m->small_win);
317
	tipc_group_decr_active(grp, m);
J
Jon Maloy 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339

	/* If last member on a node, remove node from dest list */
	if (!tipc_group_find_node(grp, m->node))
		tipc_nlist_del(&grp->dests, m->node);

	kfree(m);
}

struct tipc_nlist *tipc_group_dests(struct tipc_group *grp)
{
	return &grp->dests;
}

void tipc_group_self(struct tipc_group *grp, struct tipc_name_seq *seq,
		     int *scope)
{
	seq->type = grp->type;
	seq->lower = grp->instance;
	seq->upper = grp->instance;
	*scope = grp->scope;
}

340 341 342 343 344
void tipc_group_update_member(struct tipc_member *m, int len)
{
	struct tipc_group *grp = m->group;
	struct tipc_member *_m, *tmp;

J
Jon Maloy 已提交
345
	if (!tipc_group_is_receiver(m))
346 347 348 349 350 351 352
		return;

	m->window -= len;

	if (m->window >= ADV_IDLE)
		return;

J
Jon Maloy 已提交
353
	list_del_init(&m->small_win);
354

J
Jon Maloy 已提交
355 356
	/* Sort member into small_window members' list */
	list_for_each_entry_safe(_m, tmp, &grp->small_win, small_win) {
357 358
		if (_m->window > m->window)
			break;
359
	}
360
	list_add_tail(&m->small_win, &_m->small_win);
361 362
}

363
void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack)
J
Jon Maloy 已提交
364
{
365
	u16 prev = grp->bc_snd_nxt - 1;
366 367
	struct tipc_member *m;
	struct rb_node *n;
368
	u16 ackers = 0;
369 370 371

	for (n = rb_first(&grp->members); n; n = rb_next(n)) {
		m = container_of(n, struct tipc_member, tree_node);
J
Jon Maloy 已提交
372
		if (tipc_group_is_receiver(m)) {
373
			tipc_group_update_member(m, len);
374
			m->bc_acked = prev;
375
			ackers++;
376
		}
377
	}
378 379 380

	/* Mark number of acknowledges to expect, if any */
	if (ack)
381
		grp->bc_ackers = ackers;
J
Jon Maloy 已提交
382 383 384
	grp->bc_snd_nxt++;
}

385 386
bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
		     int len, struct tipc_member **mbr)
387
{
388
	struct sk_buff_head xmitq;
389
	struct tipc_member *m;
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
	int adv, state;

	m = tipc_group_find_dest(grp, dnode, dport);
	*mbr = m;
	if (!m)
		return false;
	if (m->usr_pending)
		return true;
	if (m->window >= len)
		return false;
	m->usr_pending = true;

	/* If not fully advertised, do it now to prevent mutual blocking */
	adv = m->advertised;
	state = m->state;
	if (state < MBR_JOINED)
		return true;
	if (state == MBR_JOINED && adv == ADV_IDLE)
		return true;
409 410 411 412
	if (state == MBR_ACTIVE && adv == ADV_ACTIVE)
		return true;
	if (state == MBR_PENDING && adv == ADV_IDLE)
		return true;
413 414 415 416 417 418 419 420 421
	skb_queue_head_init(&xmitq);
	tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, &xmitq);
	tipc_node_distr_xmit(grp->net, &xmitq);
	return true;
}

bool tipc_group_bc_cong(struct tipc_group *grp, int len)
{
	struct tipc_member *m = NULL;
422

423 424 425 426
	/* If prev bcast was replicast, reject until all receivers have acked */
	if (grp->bc_ackers)
		return true;

J
Jon Maloy 已提交
427
	if (list_empty(&grp->small_win))
428 429
		return false;

J
Jon Maloy 已提交
430
	m = list_first_entry(&grp->small_win, struct tipc_member, small_win);
431 432 433
	if (m->window >= len)
		return false;

434
	return tipc_group_cong(grp, m->node, m->port, len, &m);
435 436
}

437 438 439 440 441 442 443 444 445
/* tipc_group_sort_msg() - sort msg into queue by bcast sequence number
 */
static void tipc_group_sort_msg(struct sk_buff *skb, struct sk_buff_head *defq)
{
	struct tipc_msg *_hdr, *hdr = buf_msg(skb);
	u16 bc_seqno = msg_grp_bc_seqno(hdr);
	struct sk_buff *_skb, *tmp;
	int mtyp = msg_type(hdr);

446
	/* Bcast/mcast may be bypassed by ucast or other bcast, - sort it in */
447 448 449 450 451 452 453 454 455 456 457 458 459 460
	if (mtyp == TIPC_GRP_BCAST_MSG || mtyp == TIPC_GRP_MCAST_MSG) {
		skb_queue_walk_safe(defq, _skb, tmp) {
			_hdr = buf_msg(_skb);
			if (!less(bc_seqno, msg_grp_bc_seqno(_hdr)))
				continue;
			__skb_queue_before(defq, _skb, skb);
			return;
		}
		/* Bcast was not bypassed, - add to tail */
	}
	/* Unicasts are never bypassed, - always add to tail */
	__skb_queue_tail(defq, skb);
}

J
Jon Maloy 已提交
461 462 463 464 465 466
/* tipc_group_filter_msg() - determine if we should accept arriving message
 */
void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
			   struct sk_buff_head *xmitq)
{
	struct sk_buff *skb = __skb_dequeue(inputq);
467
	bool ack, deliver, update, leave = false;
468
	struct sk_buff_head *defq;
J
Jon Maloy 已提交
469 470 471
	struct tipc_member *m;
	struct tipc_msg *hdr;
	u32 node, port;
472
	int mtyp, blks;
J
Jon Maloy 已提交
473 474 475 476 477 478 479 480 481 482 483 484

	if (!skb)
		return;

	hdr = buf_msg(skb);
	node =  msg_orignode(hdr);
	port = msg_origport(hdr);

	if (!msg_in_group(hdr))
		goto drop;

	m = tipc_group_find_member(grp, node, port);
J
Jon Maloy 已提交
485
	if (!tipc_group_is_sender(m))
J
Jon Maloy 已提交
486 487
		goto drop;

488 489
	if (less(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
		goto drop;
490

491 492 493 494 495 496 497
	TIPC_SKB_CB(skb)->orig_member = m->instance;
	defq = &m->deferredq;
	tipc_group_sort_msg(skb, defq);

	while ((skb = skb_peek(defq))) {
		hdr = buf_msg(skb);
		mtyp = msg_type(hdr);
498
		blks = msg_blocks(hdr);
499
		deliver = true;
500
		ack = false;
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
		update = false;

		if (more(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
			break;

		/* Decide what to do with message */
		switch (mtyp) {
		case TIPC_GRP_MCAST_MSG:
			if (msg_nameinst(hdr) != grp->instance) {
				update = true;
				deliver = false;
			}
			/* Fall thru */
		case TIPC_GRP_BCAST_MSG:
			m->bc_rcv_nxt++;
516
			ack = msg_grp_bc_ack_req(hdr);
517 518 519
			break;
		case TIPC_GRP_UCAST_MSG:
			break;
520 521 522 523 524 525
		case TIPC_GRP_MEMBER_EVT:
			if (m->state == MBR_LEAVING)
				leave = true;
			if (!grp->events)
				deliver = false;
			break;
526 527
		default:
			break;
528 529
		}

530 531 532 533 534 535 536
		/* Execute decisions */
		__skb_dequeue(defq);
		if (deliver)
			__skb_queue_tail(inputq, skb);
		else
			kfree_skb(skb);

537 538 539
		if (ack)
			tipc_group_proto_xmit(grp, m, GRP_ACK_MSG, xmitq);

540 541
		if (leave) {
			__skb_queue_purge(defq);
J
Jon Maloy 已提交
542
			tipc_group_delete_member(grp, m);
543 544
			break;
		}
545 546
		if (!update)
			continue;
J
Jon Maloy 已提交
547

548 549
		tipc_group_update_rcv_win(grp, blks, node, port, xmitq);
	}
J
Jon Maloy 已提交
550 551 552 553 554
	return;
drop:
	kfree_skb(skb);
}

555 556 557
void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
			       u32 port, struct sk_buff_head *xmitq)
{
558 559 560 561
	struct list_head *active = &grp->active;
	int max_active = grp->max_active;
	int reclaim_limit = max_active * 3 / 4;
	int active_cnt = grp->active_cnt;
562
	struct tipc_member *m, *rm, *pm;
563 564 565 566 567 568 569 570 571

	m = tipc_group_find_member(grp, node, port);
	if (!m)
		return;

	m->advertised -= blks;

	switch (m->state) {
	case MBR_JOINED:
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
		/* First, decide if member can go active */
		if (active_cnt <= max_active) {
			m->state = MBR_ACTIVE;
			list_add_tail(&m->list, active);
			grp->active_cnt++;
			tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
		} else {
			m->state = MBR_PENDING;
			list_add_tail(&m->list, &grp->pending);
		}

		if (active_cnt < reclaim_limit)
			break;

		/* Reclaim from oldest active member, if possible */
		if (!list_empty(active)) {
588 589
			rm = list_first_entry(active, struct tipc_member, list);
			rm->state = MBR_RECLAIMING;
J
Jon Maloy 已提交
590
			list_del_init(&rm->list);
591 592 593
			tipc_group_proto_xmit(grp, rm, GRP_RECLAIM_MSG, xmitq);
			break;
		}
594 595 596 597 598 599
		/* Nobody to reclaim from; - revert oldest pending to JOINED */
		pm = list_first_entry(&grp->pending, struct tipc_member, list);
		list_del_init(&pm->list);
		pm->state = MBR_JOINED;
		tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
		break;
600 601 602 603 604 605 606 607 608 609 610
	case MBR_ACTIVE:
		if (!list_is_last(&m->list, &grp->active))
			list_move_tail(&m->list, &grp->active);
		if (m->advertised > (ADV_ACTIVE * 3 / 4))
			break;
		tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
		break;
	case MBR_REMITTED:
		if (m->advertised > ADV_IDLE)
			break;
		m->state = MBR_JOINED;
J
Jon Maloy 已提交
611
		grp->active_cnt--;
612 613
		if (m->advertised < ADV_IDLE) {
			pr_warn_ratelimited("Rcv unexpected msg after REMIT\n");
614
			tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
615
		}
J
Jon Maloy 已提交
616

617 618 619 620 621 622 623 624 625
		if (list_empty(&grp->pending))
			return;

		/* Set oldest pending member to active and advertise */
		pm = list_first_entry(&grp->pending, struct tipc_member, list);
		pm->state = MBR_ACTIVE;
		list_move_tail(&pm->list, &grp->active);
		grp->active_cnt++;
		tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
626
		break;
627
	case MBR_RECLAIMING:
628 629 630 631 632 633 634 635
	case MBR_DISCOVERED:
	case MBR_JOINING:
	case MBR_LEAVING:
	default:
		break;
	}
}

J
Jon Maloy 已提交
636 637 638 639 640
static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
				  int mtyp, struct sk_buff_head *xmitq)
{
	struct tipc_msg *hdr;
	struct sk_buff *skb;
641
	int adv = 0;
J
Jon Maloy 已提交
642 643 644 645 646 647 648

	skb = tipc_msg_create(GROUP_PROTOCOL, mtyp, INT_H_SIZE, 0,
			      m->node, tipc_own_addr(grp->net),
			      m->port, grp->portid, 0);
	if (!skb)
		return;

649
	if (m->state == MBR_ACTIVE)
650
		adv = ADV_ACTIVE - m->advertised;
651 652
	else if (m->state == MBR_JOINED || m->state == MBR_PENDING)
		adv = ADV_IDLE - m->advertised;
653

J
Jon Maloy 已提交
654
	hdr = buf_msg(skb);
655 656

	if (mtyp == GRP_JOIN_MSG) {
J
Jon Maloy 已提交
657
		msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
658 659
		msg_set_adv_win(hdr, adv);
		m->advertised += adv;
660 661
	} else if (mtyp == GRP_LEAVE_MSG) {
		msg_set_grp_bc_syncpt(hdr, grp->bc_snd_nxt);
662 663 664
	} else if (mtyp == GRP_ADV_MSG) {
		msg_set_adv_win(hdr, adv);
		m->advertised += adv;
665 666
	} else if (mtyp == GRP_ACK_MSG) {
		msg_set_grp_bc_acked(hdr, m->bc_rcv_nxt);
667 668
	} else if (mtyp == GRP_REMIT_MSG) {
		msg_set_grp_remitted(hdr, m->window);
669
	}
J
Jon Maloy 已提交
670
	msg_set_dest_droppable(hdr, true);
J
Jon Maloy 已提交
671 672 673
	__skb_queue_tail(xmitq, skb);
}

674 675
void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
			  struct tipc_msg *hdr, struct sk_buff_head *inputq,
J
Jon Maloy 已提交
676 677 678 679
			  struct sk_buff_head *xmitq)
{
	u32 node = msg_orignode(hdr);
	u32 port = msg_origport(hdr);
680
	struct tipc_member *m, *pm;
681
	struct tipc_msg *ehdr;
682
	u16 remitted, in_flight;
J
Jon Maloy 已提交
683 684 685 686 687 688 689 690 691 692 693 694 695

	if (!grp)
		return;

	m = tipc_group_find_member(grp, node, port);

	switch (msg_type(hdr)) {
	case GRP_JOIN_MSG:
		if (!m)
			m = tipc_group_create_member(grp, node, port,
						     MBR_QUARANTINED);
		if (!m)
			return;
696 697
		m->bc_syncpt = msg_grp_bc_syncpt(hdr);
		m->bc_rcv_nxt = m->bc_syncpt;
698
		m->window += msg_adv_win(hdr);
J
Jon Maloy 已提交
699 700

		/* Wait until PUBLISH event is received */
701
		if (m->state == MBR_DISCOVERED) {
J
Jon Maloy 已提交
702
			m->state = MBR_JOINING;
703
		} else if (m->state == MBR_PUBLISHED) {
J
Jon Maloy 已提交
704
			m->state = MBR_JOINED;
705 706 707
			*usr_wakeup = true;
			m->usr_pending = false;
			tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
708 709
			ehdr = buf_msg(m->event_msg);
			msg_set_grp_bc_seqno(ehdr, m->bc_syncpt);
710 711
			__skb_queue_tail(inputq, m->event_msg);
		}
J
Jon Maloy 已提交
712
		list_del_init(&m->small_win);
713
		tipc_group_update_member(m, 0);
J
Jon Maloy 已提交
714 715 716 717
		return;
	case GRP_LEAVE_MSG:
		if (!m)
			return;
718
		m->bc_syncpt = msg_grp_bc_syncpt(hdr);
719
		list_del_init(&m->list);
J
Jon Maloy 已提交
720
		list_del_init(&m->small_win);
721
		*usr_wakeup = true;
J
Jon Maloy 已提交
722 723 724

		/* Wait until WITHDRAW event is received */
		if (m->state != MBR_LEAVING) {
725
			tipc_group_decr_active(grp, m);
J
Jon Maloy 已提交
726 727 728 729
			m->state = MBR_LEAVING;
			return;
		}
		/* Otherwise deliver already received WITHDRAW event */
730 731
		ehdr = buf_msg(m->event_msg);
		msg_set_grp_bc_seqno(ehdr, m->bc_syncpt);
732
		__skb_queue_tail(inputq, m->event_msg);
733 734 735 736 737 738 739
		return;
	case GRP_ADV_MSG:
		if (!m)
			return;
		m->window += msg_adv_win(hdr);
		*usr_wakeup = m->usr_pending;
		m->usr_pending = false;
J
Jon Maloy 已提交
740
		list_del_init(&m->small_win);
J
Jon Maloy 已提交
741
		return;
742 743 744 745 746 747 748 749 750
	case GRP_ACK_MSG:
		if (!m)
			return;
		m->bc_acked = msg_grp_bc_acked(hdr);
		if (--grp->bc_ackers)
			break;
		*usr_wakeup = true;
		m->usr_pending = false;
		return;
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
	case GRP_RECLAIM_MSG:
		if (!m)
			return;
		*usr_wakeup = m->usr_pending;
		m->usr_pending = false;
		tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq);
		m->window = ADV_IDLE;
		return;
	case GRP_REMIT_MSG:
		if (!m || m->state != MBR_RECLAIMING)
			return;

		remitted = msg_grp_remitted(hdr);

		/* Messages preceding the REMIT still in receive queue */
		if (m->advertised > remitted) {
			m->state = MBR_REMITTED;
			in_flight = m->advertised - remitted;
769 770
			m->advertised = ADV_IDLE + in_flight;
			return;
771
		}
J
Jon Maloy 已提交
772
		/* This should never happen */
773
		if (m->advertised < remitted)
J
Jon Maloy 已提交
774
			pr_warn_ratelimited("Unexpected REMIT msg\n");
775

J
Jon Maloy 已提交
776 777
		/* All messages preceding the REMIT have been read */
		m->state = MBR_JOINED;
778
		grp->active_cnt--;
J
Jon Maloy 已提交
779
		m->advertised = ADV_IDLE;
780 781 782 783 784 785 786 787 788 789 790

		/* Set oldest pending member to active and advertise */
		if (list_empty(&grp->pending))
			return;
		pm = list_first_entry(&grp->pending, struct tipc_member, list);
		pm->state = MBR_ACTIVE;
		list_move_tail(&pm->list, &grp->active);
		grp->active_cnt++;
		if (pm->advertised <= (ADV_ACTIVE * 3 / 4))
			tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
		return;
J
Jon Maloy 已提交
791 792 793 794 795
	default:
		pr_warn("Received unknown GROUP_PROTO message\n");
	}
}

796 797
/* tipc_group_member_evt() - receive and handle a member up/down event
 */
J
Jon Maloy 已提交
798
void tipc_group_member_evt(struct tipc_group *grp,
799 800
			   bool *usr_wakeup,
			   int *sk_rcvbuf,
J
Jon Maloy 已提交
801
			   struct sk_buff *skb,
802
			   struct sk_buff_head *inputq,
J
Jon Maloy 已提交
803 804 805 806
			   struct sk_buff_head *xmitq)
{
	struct tipc_msg *hdr = buf_msg(skb);
	struct tipc_event *evt = (void *)msg_data(hdr);
807
	u32 instance = evt->found_lower;
J
Jon Maloy 已提交
808 809
	u32 node = evt->port.node;
	u32 port = evt->port.ref;
810
	int event = evt->event;
J
Jon Maloy 已提交
811 812
	struct tipc_member *m;
	struct net *net;
813
	bool node_up;
J
Jon Maloy 已提交
814 815 816 817 818 819 820 821 822 823
	u32 self;

	if (!grp)
		goto drop;

	net = grp->net;
	self = tipc_own_addr(net);
	if (!grp->loopback && node == self && port == grp->portid)
		goto drop;

824 825 826 827 828 829 830 831 832
	/* Convert message before delivery to user */
	msg_set_hdr_sz(hdr, GROUP_H_SIZE);
	msg_set_user(hdr, TIPC_CRITICAL_IMPORTANCE);
	msg_set_type(hdr, TIPC_GRP_MEMBER_EVT);
	msg_set_origport(hdr, port);
	msg_set_orignode(hdr, node);
	msg_set_nametype(hdr, grp->type);
	msg_set_grp_evt(hdr, event);

J
Jon Maloy 已提交
833 834
	m = tipc_group_find_member(grp, node, port);

835
	if (event == TIPC_PUBLISHED) {
J
Jon Maloy 已提交
836 837 838 839 840 841
		if (!m)
			m = tipc_group_create_member(grp, node, port,
						     MBR_DISCOVERED);
		if (!m)
			goto drop;

842 843 844
		/* Hold back event if JOIN message not yet received */
		if (m->state == MBR_DISCOVERED) {
			m->event_msg = skb;
J
Jon Maloy 已提交
845
			m->state = MBR_PUBLISHED;
846
		} else {
847
			msg_set_grp_bc_seqno(hdr, m->bc_syncpt);
848
			__skb_queue_tail(inputq, skb);
J
Jon Maloy 已提交
849
			m->state = MBR_JOINED;
850 851
			*usr_wakeup = true;
			m->usr_pending = false;
852 853 854
		}
		m->instance = instance;
		TIPC_SKB_CB(skb)->orig_member = m->instance;
J
Jon Maloy 已提交
855
		tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
856
		tipc_group_update_member(m, 0);
857
	} else if (event == TIPC_WITHDRAWN) {
J
Jon Maloy 已提交
858 859 860
		if (!m)
			goto drop;

861 862
		TIPC_SKB_CB(skb)->orig_member = m->instance;

863
		*usr_wakeup = true;
864
		m->usr_pending = false;
865
		node_up = tipc_node_is_up(net, node);
866 867 868 869 870 871 872 873 874
		m->event_msg = NULL;

		if (node_up) {
			/* Hold back event if a LEAVE msg should be expected */
			if (m->state != MBR_LEAVING) {
				m->event_msg = skb;
				tipc_group_decr_active(grp, m);
				m->state = MBR_LEAVING;
			} else {
875
				msg_set_grp_bc_seqno(hdr, m->bc_syncpt);
876 877 878 879 880 881
				__skb_queue_tail(inputq, skb);
			}
		} else {
			if (m->state != MBR_LEAVING) {
				tipc_group_decr_active(grp, m);
				m->state = MBR_LEAVING;
882
				msg_set_grp_bc_seqno(hdr, m->bc_rcv_nxt);
883 884 885
			} else {
				msg_set_grp_bc_seqno(hdr, m->bc_syncpt);
			}
886 887
			__skb_queue_tail(inputq, skb);
		}
888
		list_del_init(&m->list);
J
Jon Maloy 已提交
889
		list_del_init(&m->small_win);
J
Jon Maloy 已提交
890
	}
891
	*sk_rcvbuf = tipc_group_rcvbuf_limit(grp);
892
	return;
J
Jon Maloy 已提交
893 894 895
drop:
	kfree_skb(skb);
}