link.c 79.2 KB
Newer Older
Per Liden's avatar
Per Liden committed
1
2
/*
 * net/tipc/link.c: TIPC link code
3
 *
4
 * Copyright (c) 1996-2007, 2012, Ericsson AB
5
 * Copyright (c) 2004-2007, 2010-2011, Wind River Systems
Per Liden's avatar
Per Liden committed
6
7
 * All rights reserved.
 *
Per Liden's avatar
Per Liden committed
8
 * Redistribution and use in source and binary forms, with or without
Per Liden's avatar
Per Liden committed
9
10
 * modification, are permitted provided that the following conditions are met:
 *
Per Liden's avatar
Per Liden committed
11
12
13
14
15
16
17
18
 * 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.
Per Liden's avatar
Per Liden committed
19
 *
Per Liden's avatar
Per Liden committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * 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
Per Liden's avatar
Per Liden committed
34
35
36
37
38
39
40
41
42
43
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "core.h"
#include "link.h"
#include "port.h"
#include "name_distr.h"
#include "discover.h"
#include "config.h"

44
45
46
47
48
49
/*
 * Error message prefixes
 */
static const char *link_co_err = "Link changeover error, ";
static const char *link_rst_msg = "Resetting link ";
static const char *link_unk_evt = "Unknown link event ";
Per Liden's avatar
Per Liden committed
50

51
52
53
54
55
/*
 * Out-of-range value for link session numbers
 */
#define INVALID_SESSION 0x10000

56
57
/*
 * Link state events:
Per Liden's avatar
Per Liden committed
58
59
60
61
62
 */
#define  STARTING_EVT    856384768	/* link processing trigger */
#define  TRAFFIC_MSG_EVT 560815u	/* rx'd ??? */
#define  TIMEOUT_EVT     560817u	/* link timer expired */

63
64
65
/*
 * The following two 'message types' is really just implementation
 * data conveniently stored in the message header.
Per Liden's avatar
Per Liden committed
66
67
68
69
70
 * They must not be considered part of the protocol
 */
#define OPEN_MSG   0
#define CLOSED_MSG 1

71
/*
Per Liden's avatar
Per Liden committed
72
73
74
75
76
 * State value stored in 'exp_msg_count'
 */
#define START_CHANGEOVER 100000u

/**
77
 * struct tipc_link_name - deconstructed link name
Per Liden's avatar
Per Liden committed
78
79
80
81
82
 * @addr_local: network address of node at this end
 * @if_local: name of interface at this end
 * @addr_peer: network address of node at far end
 * @if_peer: name of interface at far end
 */
83
struct tipc_link_name {
Per Liden's avatar
Per Liden committed
84
85
86
87
88
89
	u32 addr_local;
	char if_local[TIPC_MAX_IF_NAME];
	u32 addr_peer;
	char if_peer[TIPC_MAX_IF_NAME];
};

90
static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
Per Liden's avatar
Per Liden committed
91
				       struct sk_buff *buf);
92
93
94
95
static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf);
static int  link_recv_changeover_msg(struct tipc_link **l_ptr,
				     struct sk_buff **buf);
static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance);
96
static int  link_send_sections_long(struct tipc_port *sender,
Per Liden's avatar
Per Liden committed
97
				    struct iovec const *msg_sect,
98
99
				    u32 num_sect, unsigned int total_len,
				    u32 destnode);
100
101
102
103
104
static void link_state_event(struct tipc_link *l_ptr, u32 event);
static void link_reset_statistics(struct tipc_link *l_ptr);
static void link_print(struct tipc_link *l_ptr, const char *str);
static void link_start(struct tipc_link *l_ptr);
static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
105
106
static void tipc_link_send_sync(struct tipc_link *l);
static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf);
107

Per Liden's avatar
Per Liden committed
108
/*
Sam Ravnborg's avatar
Sam Ravnborg committed
109
 *  Simple link routines
Per Liden's avatar
Per Liden committed
110
 */
Sam Ravnborg's avatar
Sam Ravnborg committed
111
static unsigned int align(unsigned int i)
Per Liden's avatar
Per Liden committed
112
113
114
115
{
	return (i + 3) & ~3u;
}

116
static void link_init_max_pkt(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
117
118
{
	u32 max_pkt;
119

120
	max_pkt = (l_ptr->b_ptr->mtu & ~3);
Per Liden's avatar
Per Liden committed
121
122
123
	if (max_pkt > MAX_MSG_SIZE)
		max_pkt = MAX_MSG_SIZE;

124
	l_ptr->max_pkt_target = max_pkt;
Per Liden's avatar
Per Liden committed
125
126
	if (l_ptr->max_pkt_target < MAX_PKT_DEFAULT)
		l_ptr->max_pkt = l_ptr->max_pkt_target;
127
	else
Per Liden's avatar
Per Liden committed
128
129
		l_ptr->max_pkt = MAX_PKT_DEFAULT;

130
	l_ptr->max_pkt_probes = 0;
Per Liden's avatar
Per Liden committed
131
132
}

133
static u32 link_next_sent(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
134
135
{
	if (l_ptr->next_out)
136
		return buf_seqno(l_ptr->next_out);
Per Liden's avatar
Per Liden committed
137
138
139
	return mod(l_ptr->next_out_no);
}

140
static u32 link_last_sent(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
141
142
143
144
145
{
	return mod(link_next_sent(l_ptr) - 1);
}

/*
Sam Ravnborg's avatar
Sam Ravnborg committed
146
 *  Simple non-static link routines (i.e. referenced outside this file)
Per Liden's avatar
Per Liden committed
147
 */
148
int tipc_link_is_up(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
149
150
151
{
	if (!l_ptr)
		return 0;
Eric Dumazet's avatar
Eric Dumazet committed
152
	return link_working_working(l_ptr) || link_working_unknown(l_ptr);
Per Liden's avatar
Per Liden committed
153
154
}

155
int tipc_link_is_active(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
156
{
Eric Dumazet's avatar
Eric Dumazet committed
157
158
	return	(l_ptr->owner->active_links[0] == l_ptr) ||
		(l_ptr->owner->active_links[1] == l_ptr);
Per Liden's avatar
Per Liden committed
159
160
161
}

/**
162
 * link_name_validate - validate & (optionally) deconstruct tipc_link name
163
164
 * @name: ptr to link name string
 * @name_parts: ptr to area for link name components (or NULL if not needed)
165
 *
Per Liden's avatar
Per Liden committed
166
167
 * Returns 1 if link name is valid, otherwise 0.
 */
168
169
static int link_name_validate(const char *name,
				struct tipc_link_name *name_parts)
Per Liden's avatar
Per Liden committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
{
	char name_copy[TIPC_MAX_LINK_NAME];
	char *addr_local;
	char *if_local;
	char *addr_peer;
	char *if_peer;
	char dummy;
	u32 z_local, c_local, n_local;
	u32 z_peer, c_peer, n_peer;
	u32 if_local_len;
	u32 if_peer_len;

	/* copy link name & ensure length is OK */
	name_copy[TIPC_MAX_LINK_NAME - 1] = 0;
	/* need above in case non-Posix strncpy() doesn't pad with nulls */
	strncpy(name_copy, name, TIPC_MAX_LINK_NAME);
	if (name_copy[TIPC_MAX_LINK_NAME - 1] != 0)
		return 0;

	/* ensure all component parts of link name are present */
	addr_local = name_copy;
191
192
	if_local = strchr(addr_local, ':');
	if (if_local == NULL)
Per Liden's avatar
Per Liden committed
193
194
		return 0;
	*(if_local++) = 0;
195
196
	addr_peer = strchr(if_local, '-');
	if (addr_peer == NULL)
Per Liden's avatar
Per Liden committed
197
198
199
		return 0;
	*(addr_peer++) = 0;
	if_local_len = addr_peer - if_local;
200
201
	if_peer = strchr(addr_peer, ':');
	if (if_peer == NULL)
Per Liden's avatar
Per Liden committed
202
203
204
205
206
207
208
209
210
211
212
		return 0;
	*(if_peer++) = 0;
	if_peer_len = strlen(if_peer) + 1;

	/* validate component parts of link name */
	if ((sscanf(addr_local, "%u.%u.%u%c",
		    &z_local, &c_local, &n_local, &dummy) != 3) ||
	    (sscanf(addr_peer, "%u.%u.%u%c",
		    &z_peer, &c_peer, &n_peer, &dummy) != 3) ||
	    (z_local > 255) || (c_local > 4095) || (n_local > 4095) ||
	    (z_peer  > 255) || (c_peer  > 4095) || (n_peer  > 4095) ||
213
	    (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) ||
214
	    (if_peer_len  <= 1) || (if_peer_len  > TIPC_MAX_IF_NAME))
Per Liden's avatar
Per Liden committed
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
		return 0;

	/* return link name components, if necessary */
	if (name_parts) {
		name_parts->addr_local = tipc_addr(z_local, c_local, n_local);
		strcpy(name_parts->if_local, if_local);
		name_parts->addr_peer = tipc_addr(z_peer, c_peer, n_peer);
		strcpy(name_parts->if_peer, if_peer);
	}
	return 1;
}

/**
 * link_timeout - handle expiration of link timer
 * @l_ptr: pointer to link
230
 *
231
232
233
234
 * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict
 * with tipc_link_delete().  (There is no risk that the node will be deleted by
 * another thread because tipc_link_delete() always cancels the link timer before
 * tipc_node_delete() is called.)
Per Liden's avatar
Per Liden committed
235
 */
236
static void link_timeout(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
237
{
238
	tipc_node_lock(l_ptr->owner);
Per Liden's avatar
Per Liden committed
239
240
241
242
243
244
245
246
247

	/* update counters used in statistical profiling of send traffic */
	l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size;
	l_ptr->stats.queue_sz_counts++;

	if (l_ptr->first_out) {
		struct tipc_msg *msg = buf_msg(l_ptr->first_out);
		u32 length = msg_size(msg);

248
249
		if ((msg_user(msg) == MSG_FRAGMENTER) &&
		    (msg_type(msg) == FIRST_FRAGMENT)) {
Per Liden's avatar
Per Liden committed
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
			length = msg_size(msg_get_wrapped(msg));
		}
		if (length) {
			l_ptr->stats.msg_lengths_total += length;
			l_ptr->stats.msg_length_counts++;
			if (length <= 64)
				l_ptr->stats.msg_length_profile[0]++;
			else if (length <= 256)
				l_ptr->stats.msg_length_profile[1]++;
			else if (length <= 1024)
				l_ptr->stats.msg_length_profile[2]++;
			else if (length <= 4096)
				l_ptr->stats.msg_length_profile[3]++;
			else if (length <= 16384)
				l_ptr->stats.msg_length_profile[4]++;
			else if (length <= 32768)
				l_ptr->stats.msg_length_profile[5]++;
			else
				l_ptr->stats.msg_length_profile[6]++;
		}
	}

	/* do all other link processing performed on a periodic basis */

	link_state_event(l_ptr, TIMEOUT_EVT);

	if (l_ptr->next_out)
277
		tipc_link_push_queue(l_ptr);
Per Liden's avatar
Per Liden committed
278

279
	tipc_node_unlock(l_ptr->owner);
Per Liden's avatar
Per Liden committed
280
281
}

282
static void link_set_timer(struct tipc_link *l_ptr, u32 time)
Per Liden's avatar
Per Liden committed
283
284
285
286
287
{
	k_start_timer(&l_ptr->timer, time);
}

/**
288
 * tipc_link_create - create a new link
289
 * @n_ptr: pointer to associated node
Per Liden's avatar
Per Liden committed
290
291
 * @b_ptr: pointer to associated bearer
 * @media_addr: media address to use when sending messages over link
292
 *
Per Liden's avatar
Per Liden committed
293
294
 * Returns pointer to link.
 */
295
struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
296
			      struct tipc_bearer *b_ptr,
297
			      const struct tipc_media_addr *media_addr)
Per Liden's avatar
Per Liden committed
298
{
299
	struct tipc_link *l_ptr;
Per Liden's avatar
Per Liden committed
300
301
	struct tipc_msg *msg;
	char *if_name;
302
303
304
305
306
	char addr_string[16];
	u32 peer = n_ptr->addr;

	if (n_ptr->link_cnt >= 2) {
		tipc_addr_string_fill(addr_string, n_ptr->addr);
307
		pr_err("Attempt to establish third link to %s\n", addr_string);
308
309
310
311
312
		return NULL;
	}

	if (n_ptr->links[b_ptr->identity]) {
		tipc_addr_string_fill(addr_string, n_ptr->addr);
313
314
		pr_err("Attempt to establish second link on <%s> to %s\n",
		       b_ptr->name, addr_string);
315
316
		return NULL;
	}
Per Liden's avatar
Per Liden committed
317

318
	l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC);
Per Liden's avatar
Per Liden committed
319
	if (!l_ptr) {
320
		pr_warn("Link creation failed, no memory\n");
Per Liden's avatar
Per Liden committed
321
322
323
324
		return NULL;
	}

	l_ptr->addr = peer;
325
	if_name = strchr(b_ptr->name, ':') + 1;
326
	sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown",
Per Liden's avatar
Per Liden committed
327
		tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
328
		tipc_node(tipc_own_addr),
Per Liden's avatar
Per Liden committed
329
330
		if_name,
		tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
331
		/* note: peer i/f name is updated by reset/activate message */
Per Liden's avatar
Per Liden committed
332
	memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
333
	l_ptr->owner = n_ptr;
Per Liden's avatar
Per Liden committed
334
	l_ptr->checkpoint = 1;
335
	l_ptr->peer_session = INVALID_SESSION;
Per Liden's avatar
Per Liden committed
336
	l_ptr->b_ptr = b_ptr;
337
	link_set_supervision_props(l_ptr, b_ptr->tolerance);
Per Liden's avatar
Per Liden committed
338
339
340
341
	l_ptr->state = RESET_UNKNOWN;

	l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;
	msg = l_ptr->pmsg;
342
	tipc_msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr);
Per Liden's avatar
Per Liden committed
343
	msg_set_size(msg, sizeof(l_ptr->proto_msg));
344
	msg_set_session(msg, (tipc_random & 0xffff));
Per Liden's avatar
Per Liden committed
345
346
347
348
	msg_set_bearer_id(msg, b_ptr->identity);
	strcpy((char *)msg_data(msg), if_name);

	l_ptr->priority = b_ptr->priority;
349
	tipc_link_set_queue_limits(l_ptr, b_ptr->window);
Per Liden's avatar
Per Liden committed
350
351
352
353
354
355
356
357

	link_init_max_pkt(l_ptr);

	l_ptr->next_out_no = 1;
	INIT_LIST_HEAD(&l_ptr->waiting_ports);

	link_reset_statistics(l_ptr);

358
	tipc_node_attach_link(n_ptr, l_ptr);
Per Liden's avatar
Per Liden committed
359

360
361
	k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
	list_add_tail(&l_ptr->link_list, &b_ptr->links);
362
	tipc_k_signal((Handler)link_start, (unsigned long)l_ptr);
Per Liden's avatar
Per Liden committed
363
364
365
366

	return l_ptr;
}

367
/**
368
 * tipc_link_delete - delete a link
Per Liden's avatar
Per Liden committed
369
 * @l_ptr: pointer to link
370
 *
371
 * Note: 'tipc_net_lock' is write_locked, bearer is locked.
Per Liden's avatar
Per Liden committed
372
 * This routine must not grab the node lock until after link timer cancellation
373
 * to avoid a potential deadlock situation.
Per Liden's avatar
Per Liden committed
374
 */
375
void tipc_link_delete(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
376
377
{
	if (!l_ptr) {
378
		pr_err("Attempt to delete non-existent link\n");
Per Liden's avatar
Per Liden committed
379
380
381
382
		return;
	}

	k_cancel_timer(&l_ptr->timer);
383

384
385
386
387
	tipc_node_lock(l_ptr->owner);
	tipc_link_reset(l_ptr);
	tipc_node_detach_link(l_ptr->owner, l_ptr);
	tipc_link_stop(l_ptr);
Per Liden's avatar
Per Liden committed
388
	list_del_init(&l_ptr->link_list);
389
	tipc_node_unlock(l_ptr->owner);
Per Liden's avatar
Per Liden committed
390
391
392
393
	k_term_timer(&l_ptr->timer);
	kfree(l_ptr);
}

394
static void link_start(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
395
{
396
	tipc_node_lock(l_ptr->owner);
Per Liden's avatar
Per Liden committed
397
	link_state_event(l_ptr, STARTING_EVT);
398
	tipc_node_unlock(l_ptr->owner);
Per Liden's avatar
Per Liden committed
399
400
401
}

/**
402
 * link_schedule_port - schedule port for deferred sending
Per Liden's avatar
Per Liden committed
403
404
405
 * @l_ptr: pointer to link
 * @origport: reference to sending port
 * @sz: amount of data to be sent
406
407
 *
 * Schedules port for renewed sending of messages after link congestion
Per Liden's avatar
Per Liden committed
408
409
 * has abated.
 */
410
static int link_schedule_port(struct tipc_link *l_ptr, u32 origport, u32 sz)
Per Liden's avatar
Per Liden committed
411
{
412
	struct tipc_port *p_ptr;
Per Liden's avatar
Per Liden committed
413

414
415
	spin_lock_bh(&tipc_port_list_lock);
	p_ptr = tipc_port_lock(origport);
Per Liden's avatar
Per Liden committed
416
417
418
419
420
	if (p_ptr) {
		if (!p_ptr->wakeup)
			goto exit;
		if (!list_empty(&p_ptr->wait_list))
			goto exit;
421
		p_ptr->congested = 1;
422
		p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt);
Per Liden's avatar
Per Liden committed
423
424
425
		list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);
		l_ptr->stats.link_congs++;
exit:
426
		tipc_port_unlock(p_ptr);
Per Liden's avatar
Per Liden committed
427
	}
428
	spin_unlock_bh(&tipc_port_list_lock);
Per Liden's avatar
Per Liden committed
429
430
431
	return -ELINKCONG;
}

432
void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all)
Per Liden's avatar
Per Liden committed
433
{
434
435
	struct tipc_port *p_ptr;
	struct tipc_port *temp_p_ptr;
Per Liden's avatar
Per Liden committed
436
437
438
439
440
441
	int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size;

	if (all)
		win = 100000;
	if (win <= 0)
		return;
442
	if (!spin_trylock_bh(&tipc_port_list_lock))
Per Liden's avatar
Per Liden committed
443
444
445
		return;
	if (link_congested(l_ptr))
		goto exit;
446
	list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports,
Per Liden's avatar
Per Liden committed
447
448
449
450
				 wait_list) {
		if (win <= 0)
			break;
		list_del_init(&p_ptr->wait_list);
451
452
453
		spin_lock_bh(p_ptr->lock);
		p_ptr->congested = 0;
		p_ptr->wakeup(p_ptr);
Per Liden's avatar
Per Liden committed
454
		win -= p_ptr->waiting_pkts;
455
		spin_unlock_bh(p_ptr->lock);
Per Liden's avatar
Per Liden committed
456
457
458
	}

exit:
459
	spin_unlock_bh(&tipc_port_list_lock);
Per Liden's avatar
Per Liden committed
460
461
}

462
/**
Per Liden's avatar
Per Liden committed
463
464
465
 * link_release_outqueue - purge link's outbound message queue
 * @l_ptr: pointer to link
 */
466
static void link_release_outqueue(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
467
468
469
470
471
472
{
	struct sk_buff *buf = l_ptr->first_out;
	struct sk_buff *next;

	while (buf) {
		next = buf->next;
473
		kfree_skb(buf);
Per Liden's avatar
Per Liden committed
474
475
476
477
478
479
480
		buf = next;
	}
	l_ptr->first_out = NULL;
	l_ptr->out_queue_size = 0;
}

/**
481
 * tipc_link_reset_fragments - purge link's inbound message fragments queue
Per Liden's avatar
Per Liden committed
482
483
 * @l_ptr: pointer to link
 */
484
void tipc_link_reset_fragments(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
485
486
487
488
489
490
{
	struct sk_buff *buf = l_ptr->defragm_buf;
	struct sk_buff *next;

	while (buf) {
		next = buf->next;
491
		kfree_skb(buf);
Per Liden's avatar
Per Liden committed
492
493
494
495
496
		buf = next;
	}
	l_ptr->defragm_buf = NULL;
}

497
/**
498
 * tipc_link_stop - purge all inbound and outbound messages associated with link
Per Liden's avatar
Per Liden committed
499
500
 * @l_ptr: pointer to link
 */
501
void tipc_link_stop(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
502
503
504
505
506
507
508
{
	struct sk_buff *buf;
	struct sk_buff *next;

	buf = l_ptr->oldest_deferred_in;
	while (buf) {
		next = buf->next;
509
		kfree_skb(buf);
Per Liden's avatar
Per Liden committed
510
511
512
513
514
515
		buf = next;
	}

	buf = l_ptr->first_out;
	while (buf) {
		next = buf->next;
516
		kfree_skb(buf);
Per Liden's avatar
Per Liden committed
517
518
519
		buf = next;
	}

520
	tipc_link_reset_fragments(l_ptr);
Per Liden's avatar
Per Liden committed
521

522
	kfree_skb(l_ptr->proto_msg_queue);
Per Liden's avatar
Per Liden committed
523
524
525
	l_ptr->proto_msg_queue = NULL;
}

526
void tipc_link_reset(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
527
528
529
530
{
	struct sk_buff *buf;
	u32 prev_state = l_ptr->state;
	u32 checkpoint = l_ptr->next_in_no;
531
	int was_active_link = tipc_link_is_active(l_ptr);
532

533
	msg_set_session(l_ptr->pmsg, ((msg_session(l_ptr->pmsg) + 1) & 0xffff));
Per Liden's avatar
Per Liden committed
534

535
536
	/* Link is down, accept any session */
	l_ptr->peer_session = INVALID_SESSION;
Per Liden's avatar
Per Liden committed
537

538
	/* Prepare for max packet size negotiation */
Per Liden's avatar
Per Liden committed
539
	link_init_max_pkt(l_ptr);
540

Per Liden's avatar
Per Liden committed
541
542
543
544
545
	l_ptr->state = RESET_UNKNOWN;

	if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET))
		return;

546
547
	tipc_node_link_down(l_ptr->owner, l_ptr);
	tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
548

549
	if (was_active_link && tipc_node_active_links(l_ptr->owner) &&
Per Liden's avatar
Per Liden committed
550
551
552
553
554
555
556
	    l_ptr->owner->permit_changeover) {
		l_ptr->reset_checkpoint = checkpoint;
		l_ptr->exp_msg_count = START_CHANGEOVER;
	}

	/* Clean up all queues: */
	link_release_outqueue(l_ptr);
557
	kfree_skb(l_ptr->proto_msg_queue);
Per Liden's avatar
Per Liden committed
558
559
560
561
	l_ptr->proto_msg_queue = NULL;
	buf = l_ptr->oldest_deferred_in;
	while (buf) {
		struct sk_buff *next = buf->next;
562
		kfree_skb(buf);
Per Liden's avatar
Per Liden committed
563
564
565
		buf = next;
	}
	if (!list_empty(&l_ptr->waiting_ports))
566
		tipc_link_wakeup_ports(l_ptr, 1);
Per Liden's avatar
Per Liden committed
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

	l_ptr->retransm_queue_head = 0;
	l_ptr->retransm_queue_size = 0;
	l_ptr->last_out = NULL;
	l_ptr->first_out = NULL;
	l_ptr->next_out = NULL;
	l_ptr->unacked_window = 0;
	l_ptr->checkpoint = 1;
	l_ptr->next_out_no = 1;
	l_ptr->deferred_inqueue_sz = 0;
	l_ptr->oldest_deferred_in = NULL;
	l_ptr->newest_deferred_in = NULL;
	l_ptr->fsm_msg_cnt = 0;
	l_ptr->stale_count = 0;
	link_reset_statistics(l_ptr);
}


585
static void link_activate(struct tipc_link *l_ptr)
Per Liden's avatar
Per Liden committed
586
{
587
	l_ptr->next_in_no = l_ptr->stats.recv_info = 1;
588
589
	tipc_node_link_up(l_ptr->owner, l_ptr);
	tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
Per Liden's avatar
Per Liden committed
590
591
592
593
594
595
596
}

/**
 * link_state_event - link finite state machine
 * @l_ptr: pointer to link
 * @event: state machine event to process
 */
597
static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
Per Liden's avatar
Per Liden committed
598
{
599
	struct tipc_link *other;
Per Liden's avatar
Per Liden committed
600
601
602
603
604
605
	u32 cont_intv = l_ptr->continuity_interval;

	if (!l_ptr->started && (event != STARTING_EVT))
		return;		/* Not yet. */

	if (link_blocked(l_ptr)) {
606
		if (event == TIMEOUT_EVT)
Per Liden's avatar
Per Liden committed
607
608
609
610
611
612
613
614
615
616
617
618
619
			link_set_timer(l_ptr, cont_intv);
		return;	  /* Changeover going on */
	}

	switch (l_ptr->state) {
	case WORKING_WORKING:
		switch (event) {
		case TRAFFIC_MSG_EVT:
		case ACTIVATE_MSG:
			break;
		case TIMEOUT_EVT:
			if (l_ptr->next_in_no != l_ptr->checkpoint) {
				l_ptr->checkpoint = l_ptr->next_in_no;
620
				if (tipc_bclink_acks_missing(l_ptr->owner)) {
621
					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
622
								 0, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
623
624
					l_ptr->fsm_msg_cnt++;
				} else if (l_ptr->max_pkt < l_ptr->max_pkt_target) {
625
					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
626
								 1, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
627
628
629
630
631
632
633
					l_ptr->fsm_msg_cnt++;
				}
				link_set_timer(l_ptr, cont_intv);
				break;
			}
			l_ptr->state = WORKING_UNKNOWN;
			l_ptr->fsm_msg_cnt = 0;
634
			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
635
636
637
638
			l_ptr->fsm_msg_cnt++;
			link_set_timer(l_ptr, cont_intv / 4);
			break;
		case RESET_MSG:
639
640
			pr_info("%s<%s>, requested by peer\n", link_rst_msg,
				l_ptr->name);
641
			tipc_link_reset(l_ptr);
Per Liden's avatar
Per Liden committed
642
643
			l_ptr->state = RESET_RESET;
			l_ptr->fsm_msg_cnt = 0;
644
			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
645
646
647
648
			l_ptr->fsm_msg_cnt++;
			link_set_timer(l_ptr, cont_intv);
			break;
		default:
649
			pr_err("%s%u in WW state\n", link_unk_evt, event);
Per Liden's avatar
Per Liden committed
650
651
652
653
654
655
656
657
658
659
660
		}
		break;
	case WORKING_UNKNOWN:
		switch (event) {
		case TRAFFIC_MSG_EVT:
		case ACTIVATE_MSG:
			l_ptr->state = WORKING_WORKING;
			l_ptr->fsm_msg_cnt = 0;
			link_set_timer(l_ptr, cont_intv);
			break;
		case RESET_MSG:
661
662
			pr_info("%s<%s>, requested by peer while probing\n",
				link_rst_msg, l_ptr->name);
663
			tipc_link_reset(l_ptr);
Per Liden's avatar
Per Liden committed
664
665
			l_ptr->state = RESET_RESET;
			l_ptr->fsm_msg_cnt = 0;
666
			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
667
668
669
670
671
672
673
674
			l_ptr->fsm_msg_cnt++;
			link_set_timer(l_ptr, cont_intv);
			break;
		case TIMEOUT_EVT:
			if (l_ptr->next_in_no != l_ptr->checkpoint) {
				l_ptr->state = WORKING_WORKING;
				l_ptr->fsm_msg_cnt = 0;
				l_ptr->checkpoint = l_ptr->next_in_no;
675
676
677
				if (tipc_bclink_acks_missing(l_ptr->owner)) {
					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
								 0, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
678
679
680
681
					l_ptr->fsm_msg_cnt++;
				}
				link_set_timer(l_ptr, cont_intv);
			} else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) {
682
				tipc_link_send_proto_msg(l_ptr, STATE_MSG,
683
							 1, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
684
685
686
				l_ptr->fsm_msg_cnt++;
				link_set_timer(l_ptr, cont_intv / 4);
			} else {	/* Link has failed */
687
688
				pr_warn("%s<%s>, peer not responding\n",
					link_rst_msg, l_ptr->name);
689
				tipc_link_reset(l_ptr);
Per Liden's avatar
Per Liden committed
690
691
				l_ptr->state = RESET_UNKNOWN;
				l_ptr->fsm_msg_cnt = 0;
692
693
				tipc_link_send_proto_msg(l_ptr, RESET_MSG,
							 0, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
694
695
696
697
698
				l_ptr->fsm_msg_cnt++;
				link_set_timer(l_ptr, cont_intv);
			}
			break;
		default:
699
			pr_err("%s%u in WU state\n", link_unk_evt, event);
Per Liden's avatar
Per Liden committed
700
701
702
703
704
705
706
707
		}
		break;
	case RESET_UNKNOWN:
		switch (event) {
		case TRAFFIC_MSG_EVT:
			break;
		case ACTIVATE_MSG:
			other = l_ptr->owner->active_links[0];
708
			if (other && link_working_unknown(other))
Per Liden's avatar
Per Liden committed
709
710
711
712
				break;
			l_ptr->state = WORKING_WORKING;
			l_ptr->fsm_msg_cnt = 0;
			link_activate(l_ptr);
713
			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
714
			l_ptr->fsm_msg_cnt++;
715
716
			if (l_ptr->owner->working_links == 1)
				tipc_link_send_sync(l_ptr);
Per Liden's avatar
Per Liden committed
717
718
719
720
721
			link_set_timer(l_ptr, cont_intv);
			break;
		case RESET_MSG:
			l_ptr->state = RESET_RESET;
			l_ptr->fsm_msg_cnt = 0;
722
			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
723
724
725
726
727
728
729
			l_ptr->fsm_msg_cnt++;
			link_set_timer(l_ptr, cont_intv);
			break;
		case STARTING_EVT:
			l_ptr->started = 1;
			/* fall through */
		case TIMEOUT_EVT:
730
			tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
731
732
733
734
			l_ptr->fsm_msg_cnt++;
			link_set_timer(l_ptr, cont_intv);
			break;
		default:
735
			pr_err("%s%u in RU state\n", link_unk_evt, event);
Per Liden's avatar
Per Liden committed
736
737
738
739
740
741
742
		}
		break;
	case RESET_RESET:
		switch (event) {
		case TRAFFIC_MSG_EVT:
		case ACTIVATE_MSG:
			other = l_ptr->owner->active_links[0];
743
			if (other && link_working_unknown(other))
Per Liden's avatar
Per Liden committed
744
745
746
747
				break;
			l_ptr->state = WORKING_WORKING;
			l_ptr->fsm_msg_cnt = 0;
			link_activate(l_ptr);
748
			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
749
			l_ptr->fsm_msg_cnt++;
750
751
			if (l_ptr->owner->working_links == 1)
				tipc_link_send_sync(l_ptr);
Per Liden's avatar
Per Liden committed
752
753
754
755
756
			link_set_timer(l_ptr, cont_intv);
			break;
		case RESET_MSG:
			break;
		case TIMEOUT_EVT:
757
			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
Per Liden's avatar
Per Liden committed
758
759
760
761
			l_ptr->fsm_msg_cnt++;
			link_set_timer(l_ptr, cont_intv);
			break;
		default:
762
			pr_err("%s%u in RR state\n", link_unk_evt, event);
Per Liden's avatar
Per Liden committed
763
764
765
		}
		break;
	default:
766
		pr_err("Unknown link state %u/%u\n", l_ptr->state, event);
Per Liden's avatar
Per Liden committed
767
768
769
770
771
	}
}

/*
 * link_bundle_buf(): Append contents of a buffer to
772
 * the tail of an existing one.
Per Liden's avatar
Per Liden committed
773
 */
774
static int link_bundle_buf(struct tipc_link *l_ptr,
775
			   struct sk_buff *bundler,
Per Liden's avatar
Per Liden committed
776
777
778
779
780
			   struct sk_buff *buf)
{
	struct tipc_msg *bundler_msg = buf_msg(bundler);
	struct tipc_msg *msg = buf_msg(buf);
	u32 size = msg_size(msg);
781
782
783
	u32 bundle_size = msg_size(bundler_msg);
	u32 to_pos = align(bundle_size);
	u32 pad = to_pos - bundle_size;
Per Liden's avatar
Per Liden committed
784
785
786
787
788

	if (msg_user(bundler_msg) != MSG_BUNDLER)
		return 0;
	if (msg_type(bundler_msg) != OPEN_MSG)
		return 0;
789
	if (skb_tailroom(bundler) < (pad + size))
Per Liden's avatar
Per Liden committed
790
		return 0;
791
	if (l_ptr->max_pkt < (to_pos + size))
792
		return 0;
Per Liden's avatar
Per Liden committed
793

794
	skb_put(bundler, pad + size);
795
	skb_copy_to_linear_data_offset(bundler, to_pos, buf->data, size);
Per Liden's avatar
Per Liden committed
796
797
	msg_set_size(bundler_msg, to_pos + size);
	msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1);
798
	kfree_skb(buf);
Per Liden's avatar
Per Liden committed
799
800
801
802
	l_ptr->stats.sent_bundled++;
	return 1;
}

803
static void link_add_to_outqueue(struct tipc_link *l_ptr,
Sam Ravnborg's avatar
Sam Ravnborg committed
804
805
				 struct sk_buff *buf,
				 struct tipc_msg *msg)
Per Liden's avatar
Per Liden committed
806
807
808
809
810
811
812
813
814
815
816
817
{
	u32 ack = mod(l_ptr->next_in_no - 1);
	u32 seqno = mod(l_ptr->next_out_no++);

	msg_set_word(msg, 2, ((ack << 16) | seqno));
	msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
	buf->next = NULL;
	if (l_ptr->first_out) {
		l_ptr->last_out->next = buf;
		l_ptr->last_out = buf;
	} else
		l_ptr->first_out = l_ptr->last_out = buf;
818

Per Liden's avatar
Per Liden committed
819
	l_ptr->out_queue_size++;
820
821
	if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz)
		l_ptr->stats.max_queue_sz = l_ptr->out_queue_size;
Per Liden's avatar
Per Liden committed
822
823
}

824
static void link_add_chain_to_outqueue(struct tipc_link *l_ptr,
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
				       struct sk_buff *buf_chain,
				       u32 long_msgno)
{
	struct sk_buff *buf;
	struct tipc_msg *msg;

	if (!l_ptr->next_out)
		l_ptr->next_out = buf_chain;
	while (buf_chain) {
		buf = buf_chain;
		buf_chain = buf_chain->next;

		msg = buf_msg(buf);
		msg_set_long_msgno(msg, long_msgno);
		link_add_to_outqueue(l_ptr, buf, msg);
	}
}

843
844
/*
 * tipc_link_send_buf() is the 'full path' for messages, called from
Per Liden's avatar
Per Liden committed
845
846
847
 * inside TIPC when the 'fast path' in tipc_send_buf
 * has failed, and from link_send()
 */
848
int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
Per Liden's avatar
Per Liden committed
849
850
851
852
853
{
	struct tipc_msg *msg = buf_msg(buf);
	u32 size = msg_size(msg);
	u32 dsz = msg_data_sz(msg);
	u32 queue_size = l_ptr->out_queue_size;
854
	u32 imp = tipc_msg_tot_importance(msg);
Per Liden's avatar
Per Liden committed
855
	u32 queue_limit = l_ptr->queue_limit[imp];
856
	u32 max_packet = l_ptr->max_pkt;
Per Liden's avatar
Per Liden committed
857
858
859
860

	/* Match msg importance against queue limits: */
	if (unlikely(queue_size >= queue_limit)) {
		if (imp <= TIPC_CRITICAL_IMPORTANCE) {
861
			link_schedule_port(l_ptr, msg_origport(msg), size);
862
			kfree_skb(buf);
863
			return -ELINKCONG;
Per Liden's avatar
Per Liden committed
864
		}
865
		kfree_skb(buf);
Per Liden's avatar
Per Liden committed
866
		if (imp > CONN_MANAGER) {
867
868
			pr_warn("%s<%s>, send queue full", link_rst_msg,
				l_ptr->name);
869
			tipc_link_reset(l_ptr);
Per Liden's avatar
Per Liden committed
870
871
872
873
874
875
		}
		return dsz;
	}

	/* Fragmentation needed ? */
	if (size > max_packet)
876
		return link_send_long_buf(l_ptr, buf);
Per Liden's avatar
Per Liden committed
877

878
	/* Packet can be queued or sent. */
879
	if (likely(!tipc_bearer_blocked(l_ptr->b_ptr) &&
Per Liden's avatar
Per Liden committed
880
881
882
		   !link_congested(l_ptr))) {
		link_add_to_outqueue(l_ptr, buf, msg);

883
884
		tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
		l_ptr->unacked_window = 0;
Per Liden's avatar
Per Liden committed
885
886
		return dsz;
	}
887
	/* Congestion: can message be bundled ? */
Per Liden's avatar
Per Liden committed
888
889
890
891
	if ((msg_user(msg) != CHANGEOVER_PROTOCOL) &&
	    (msg_user(msg) != MSG_FRAGMENTER)) {

		/* Try adding message to an existing bundle */
892
		if (l_ptr->next_out &&
893
		    link_bundle_buf(l_ptr, l_ptr->last_out, buf))
Per Liden's avatar
Per Liden committed
894
895
896
897
			return dsz;

		/* Try creating a new bundle */
		if (size <= max_packet * 2 / 3) {
898
			struct sk_buff *bundler = tipc_buf_acquire(max_packet);
Per Liden's avatar
Per Liden committed
899
900
901
			struct tipc_msg bundler_hdr;

			if (bundler) {
902
				tipc_msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG,
903
					 INT_H_SIZE, l_ptr->addr);
904
905
				skb_copy_to_linear_data(bundler, &bundler_hdr,
							INT_H_SIZE);
Per Liden's avatar
Per Liden committed
906
907
908
909
910
911
912
913
914
915
916
917
918
919
				skb_trim(bundler, INT_H_SIZE);
				link_bundle_buf(l_ptr, bundler, buf);
				buf = bundler;
				msg = buf_msg(buf);
				l_ptr->stats.sent_bundles++;
			}
		}
	}
	if (!l_ptr->next_out)
		l_ptr->next_out = buf;
	link_add_to_outqueue(l_ptr, buf, msg);
	return dsz;
}

920
921
/*
 * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has
Per Liden's avatar
Per Liden committed
922
923
924
 * not been selected yet, and the the owner node is not locked
 * Called by TIPC internal users, e.g. the name distributor
 */
925
int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
Per Liden's avatar
Per Liden committed
926
{
927
	struct tipc_link *l_ptr;
928
	struct tipc_node *n_ptr;
Per Liden's avatar
Per Liden committed
929
930
	int res = -ELINKCONG;

931
	read_lock_bh(&tipc_net_lock);
932
	n_ptr = tipc_node_find(dest);
Per Liden's avatar
Per Liden committed
933
	if (n_ptr) {
934
		tipc_node_lock(n_ptr);
Per Liden's avatar
Per Liden committed
935
		l_ptr = n_ptr->active_links[selector & 1];
936
		if (l_ptr)
937
			res = tipc_link_send_buf(l_ptr, buf);
938
		else
939
			kfree_skb(buf);
940
		tipc_node_unlock(n_ptr);
Per Liden's avatar
Per Liden committed
941
	} else {
942
		kfree_skb(buf);
Per Liden's avatar
Per Liden committed
943
	}
944
	read_unlock_bh(&tipc_net_lock);
Per Liden's avatar
Per Liden committed
945
946
947
	return res;
}

948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
/*
 * tipc_link_send_sync - synchronize broadcast link endpoints.
 *
 * Give a newly added peer node the sequence number where it should
 * start receiving and acking broadcast packets.
 *
 * Called with node locked
 */
static void tipc_link_send_sync(struct tipc_link *l)
{
	struct sk_buff *buf;
	struct tipc_msg *msg;

	buf = tipc_buf_acquire(INT_H_SIZE);
	if (!buf)
		return;

	msg = buf_msg(buf);
	tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, l->addr);
	msg_set_last_bcast(msg, l->owner->bclink.acked);
	link_add_chain_to_outqueue(l, buf, 0);
	tipc_link_push_queue(l);
}

/*
 * tipc_link_recv_sync - synchronize broadcast link endpoints.
 * Receive the sequence number where we should start receiving and
 * acking broadcast packets from a newly added peer node, and open
 * up for reception of such packets.
 *
 * Called with node locked
 */
static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf)
{
	struct tipc_msg *msg = buf_msg(buf);

	n->bclink.last_sent = n->bclink.last_in = msg_last_bcast(msg);
	n->bclink.recv_permitted = true;
	kfree_skb(buf);
}

/*
990
991
992
993
994
995
996
997
998
999
1000
 * tipc_link_send_names - send name table entries to new neighbor
 *
 * Send routine for bulk delivery of name table messages when contact
 * with a new neighbor occurs. No link congestion checking is performed
 * because name table messages *must* be delivered. The messages must be
 * small enough not to require fragmentation.
 * Called without any locks held.
 */
void tipc_link_send_names(struct list_head *message_list, u32 dest)
{
	struct tipc_node *n_ptr;