Blame view

net/tipc/link.c 56.6 KB
b97bf3fd8   Per Liden   [TIPC] Initial merge
1
2
  /*
   * net/tipc/link.c: TIPC link code
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
3
   *
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
4
   * Copyright (c) 1996-2007, 2012-2016, Ericsson AB
198d73b82   Ying Xue   tipc: delete code...
5
   * Copyright (c) 2004-2007, 2010-2013, Wind River Systems
b97bf3fd8   Per Liden   [TIPC] Initial merge
6
7
   * All rights reserved.
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
8
   * Redistribution and use in source and binary forms, with or without
b97bf3fd8   Per Liden   [TIPC] Initial merge
9
10
   * modification, are permitted provided that the following conditions are met:
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
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.
b97bf3fd8   Per Liden   [TIPC] Initial merge
19
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
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
b97bf3fd8   Per Liden   [TIPC] Initial merge
34
35
36
37
   * POSSIBILITY OF SUCH DAMAGE.
   */
  
  #include "core.h"
e3eea1eb4   Jon Paul Maloy   tipc: clean up ha...
38
  #include "subscr.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
39
  #include "link.h"
7be57fc69   Richard Alpe   tipc: add link ge...
40
  #include "bcast.h"
9816f0615   Jon Paul Maloy   tipc: merge port ...
41
  #include "socket.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
42
  #include "name_distr.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
43
  #include "discover.h"
0655f6a86   Richard Alpe   tipc: add bearer ...
44
  #include "netlink.h"
35c55c987   Jon Paul Maloy   tipc: add neighbo...
45
  #include "monitor.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
46

796c75d0d   Ying Xue   tipc: enhance pri...
47
  #include <linux/pkt_sched.h>
38206d593   Jon Paul Maloy   tipc: narrow down...
48
  struct tipc_stats {
959011224   Jon Paul Maloy   tipc: fix link st...
49
50
  	u32 sent_pkts;
  	u32 recv_pkts;
38206d593   Jon Paul Maloy   tipc: narrow down...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  	u32 sent_states;
  	u32 recv_states;
  	u32 sent_probes;
  	u32 recv_probes;
  	u32 sent_nacks;
  	u32 recv_nacks;
  	u32 sent_acks;
  	u32 sent_bundled;
  	u32 sent_bundles;
  	u32 recv_bundled;
  	u32 recv_bundles;
  	u32 retransmitted;
  	u32 sent_fragmented;
  	u32 sent_fragments;
  	u32 recv_fragmented;
  	u32 recv_fragments;
  	u32 link_congs;		/* # port sends blocked by congestion */
  	u32 deferred_recv;
  	u32 duplicates;
  	u32 max_queue_sz;	/* send queue size high water mark */
  	u32 accu_queue_sz;	/* used for send queue size profiling */
  	u32 queue_sz_counts;	/* used for send queue size profiling */
  	u32 msg_length_counts;	/* used for message length profiling */
  	u32 msg_lengths_total;	/* used for message length profiling */
  	u32 msg_length_profile[7]; /* used for msg. length profiling */
  };
  
  /**
   * struct tipc_link - TIPC link data structure
   * @addr: network address of link's peer node
   * @name: link name character string
   * @media_addr: media address to use when sending messages over link
   * @timer: link timer
   * @net: pointer to namespace struct
   * @refcnt: reference counter for permanent references (owner node & timer)
   * @peer_session: link session # being used by peer end of link
   * @peer_bearer_id: bearer id used by link's peer endpoint
   * @bearer_id: local bearer id used by link
   * @tolerance: minimum link continuity loss needed to reset link [in ms]
38206d593   Jon Paul Maloy   tipc: narrow down...
90
91
92
93
94
95
96
97
   * @abort_limit: # of unacknowledged continuity probes needed to reset link
   * @state: current state of link FSM
   * @peer_caps: bitmap describing capabilities of peer node
   * @silent_intv_cnt: # of timer intervals without any reception from peer
   * @proto_msg: template for control messages generated by link
   * @pmsg: convenience pointer to "proto_msg" field
   * @priority: current link priority
   * @net_plane: current link network plane ('A' through 'H')
35c55c987   Jon Paul Maloy   tipc: add neighbo...
98
   * @mon_state: cookie with information needed by link monitor
38206d593   Jon Paul Maloy   tipc: narrow down...
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
   * @backlog_limit: backlog queue congestion thresholds (indexed by importance)
   * @exp_msg_count: # of tunnelled messages expected during link changeover
   * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset
   * @mtu: current maximum packet size for this link
   * @advertised_mtu: advertised own mtu when link is being established
   * @transmitq: queue for sent, non-acked messages
   * @backlogq: queue for messages waiting to be sent
   * @snt_nxt: next sequence number to use for outbound messages
   * @last_retransmitted: sequence number of most recently retransmitted message
   * @stale_count: # of identical retransmit requests made by peer
   * @ackers: # of peers that needs to ack each packet before it can be released
   * @acked: # last packet acked by a certain peer. Used for broadcast.
   * @rcv_nxt: next sequence number to expect for inbound messages
   * @deferred_queue: deferred queue saved OOS b'cast message received from node
   * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
   * @inputq: buffer queue for messages to be delivered upwards
   * @namedq: buffer queue for name table messages to be delivered upwards
   * @next_out: ptr to first unsent outbound message in queue
   * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate
   * @long_msg_seq_no: next identifier to use for outbound fragmented messages
   * @reasm_buf: head of partially reassembled inbound message fragments
   * @bc_rcvr: marks that this is a broadcast receiver link
   * @stats: collects statistics regarding link activity
   */
  struct tipc_link {
  	u32 addr;
  	char name[TIPC_MAX_LINK_NAME];
38206d593   Jon Paul Maloy   tipc: narrow down...
126
127
128
129
  	struct net *net;
  
  	/* Management and link supervision data */
  	u32 peer_session;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
130
  	u32 session;
38206d593   Jon Paul Maloy   tipc: narrow down...
131
132
133
  	u32 peer_bearer_id;
  	u32 bearer_id;
  	u32 tolerance;
38206d593   Jon Paul Maloy   tipc: narrow down...
134
135
136
137
138
  	u32 abort_limit;
  	u32 state;
  	u16 peer_caps;
  	bool active;
  	u32 silent_intv_cnt;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
139
  	char if_name[TIPC_MAX_IF_NAME];
38206d593   Jon Paul Maloy   tipc: narrow down...
140
141
  	u32 priority;
  	char net_plane;
35c55c987   Jon Paul Maloy   tipc: add neighbo...
142
  	struct tipc_mon_state mon_state;
88e8ac700   Jon Paul Maloy   tipc: reduce tran...
143
  	u16 rst_cnt;
38206d593   Jon Paul Maloy   tipc: narrow down...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  
  	/* Failover/synch */
  	u16 drop_point;
  	struct sk_buff *failover_reasm_skb;
  
  	/* Max packet negotiation */
  	u16 mtu;
  	u16 advertised_mtu;
  
  	/* Sending */
  	struct sk_buff_head transmq;
  	struct sk_buff_head backlogq;
  	struct {
  		u16 len;
  		u16 limit;
  	} backlog[5];
  	u16 snd_nxt;
  	u16 last_retransm;
  	u16 window;
  	u32 stale_count;
  
  	/* Reception */
  	u16 rcv_nxt;
  	u32 rcv_unacked;
  	struct sk_buff_head deferdq;
  	struct sk_buff_head *inputq;
  	struct sk_buff_head *namedq;
  
  	/* Congestion handling */
  	struct sk_buff_head wakeupq;
  
  	/* Fragmentation/reassembly */
  	struct sk_buff *reasm_buf;
  
  	/* Broadcast */
  	u16 ackers;
  	u16 acked;
  	struct tipc_link *bc_rcvlink;
  	struct tipc_link *bc_sndlink;
7c4a54b96   Jon Paul Maloy   tipc: rate limit ...
183
184
185
186
  	unsigned long prev_retr;
  	u16 prev_from;
  	u16 prev_to;
  	u8 nack_state;
38206d593   Jon Paul Maloy   tipc: narrow down...
187
188
189
190
191
  	bool bc_peer_is_up;
  
  	/* Statistics */
  	struct tipc_stats stats;
  };
2cf8aa19f   Erik Hugne   tipc: use standar...
192
193
194
  /*
   * Error message prefixes
   */
6e498158a   Jon Paul Maloy   tipc: move link s...
195
  static const char *link_co_err = "Link tunneling error, ";
2cf8aa19f   Erik Hugne   tipc: use standar...
196
  static const char *link_rst_msg = "Resetting link ";
7be57fc69   Richard Alpe   tipc: add link ge...
197

526669866   Jon Paul Maloy   tipc: let broadca...
198
199
200
201
202
203
204
  /* Send states for broadcast NACKs
   */
  enum {
  	BC_NACK_SND_CONDITIONAL,
  	BC_NACK_SND_UNCONDITIONAL,
  	BC_NACK_SND_SUPPRESS,
  };
7c4a54b96   Jon Paul Maloy   tipc: rate limit ...
205
  #define TIPC_BC_RETR_LIMIT 10   /* [ms] */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
206
  /*
d999297c3   Jon Paul Maloy   tipc: reduce lock...
207
208
209
   * Interval between NACKs when packets arrive out of order
   */
  #define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2)
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
210
211
212
  
  /* Wildcard value for link session numbers. When it is known that
   * peer endpoint is down, any session number must be accepted.
a686e6859   Allan Stephens   tipc: Fix minor b...
213
   */
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
214
  #define ANY_SESSION 0x10000
a686e6859   Allan Stephens   tipc: Fix minor b...
215

662921cd0   Jon Paul Maloy   tipc: merge link-...
216
  /* Link FSM states:
b97bf3fd8   Per Liden   [TIPC] Initial merge
217
   */
d3504c344   Jon Paul Maloy   tipc: clean up de...
218
  enum {
662921cd0   Jon Paul Maloy   tipc: merge link-...
219
220
221
222
223
224
225
  	LINK_ESTABLISHED     = 0xe,
  	LINK_ESTABLISHING    = 0xe  << 4,
  	LINK_RESET           = 0x1  << 8,
  	LINK_RESETTING       = 0x2  << 12,
  	LINK_PEER_RESET      = 0xd  << 16,
  	LINK_FAILINGOVER     = 0xf  << 20,
  	LINK_SYNCHING        = 0xc  << 24
d3504c344   Jon Paul Maloy   tipc: clean up de...
226
227
228
229
  };
  
  /* Link FSM state checking routines
   */
662921cd0   Jon Paul Maloy   tipc: merge link-...
230
  static int link_is_up(struct tipc_link *l)
d3504c344   Jon Paul Maloy   tipc: clean up de...
231
  {
662921cd0   Jon Paul Maloy   tipc: merge link-...
232
  	return l->state & (LINK_ESTABLISHED | LINK_SYNCHING);
d3504c344   Jon Paul Maloy   tipc: clean up de...
233
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
234

d999297c3   Jon Paul Maloy   tipc: reduce lock...
235
236
  static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
  			       struct sk_buff_head *xmitq);
426cc2b86   Jon Paul Maloy   tipc: introduce n...
237
238
239
  static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
  				      u16 rcvgap, int tolerance, int priority,
  				      struct sk_buff_head *xmitq);
1a90632da   Jon Paul Maloy   tipc: eliminate r...
240
  static void link_print(struct tipc_link *l, const char *str);
e0a05ebe2   Jon Paul Maloy   tipc: send broadc...
241
242
  static int tipc_link_build_nack_msg(struct tipc_link *l,
  				    struct sk_buff_head *xmitq);
526669866   Jon Paul Maloy   tipc: let broadca...
243
244
245
  static void tipc_link_build_bc_init_msg(struct tipc_link *l,
  					struct sk_buff_head *xmitq);
  static bool tipc_link_release_pkts(struct tipc_link *l, u16 to);
8b4ed8634   Jon Paul Maloy   tipc: eliminate r...
246

b97bf3fd8   Per Liden   [TIPC] Initial merge
247
  /*
05790c645   Sam Ravnborg   [TIPC]: Remove in...
248
   *  Simple non-static link routines (i.e. referenced outside this file)
b97bf3fd8   Per Liden   [TIPC] Initial merge
249
   */
662921cd0   Jon Paul Maloy   tipc: merge link-...
250
  bool tipc_link_is_up(struct tipc_link *l)
b97bf3fd8   Per Liden   [TIPC] Initial merge
251
  {
662921cd0   Jon Paul Maloy   tipc: merge link-...
252
253
  	return link_is_up(l);
  }
c81993009   Jon Paul Maloy   tipc: update node...
254
255
256
257
  bool tipc_link_peer_is_down(struct tipc_link *l)
  {
  	return l->state == LINK_PEER_RESET;
  }
662921cd0   Jon Paul Maloy   tipc: merge link-...
258
259
260
261
  bool tipc_link_is_reset(struct tipc_link *l)
  {
  	return l->state & (LINK_RESET | LINK_FAILINGOVER | LINK_ESTABLISHING);
  }
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
262
263
264
265
  bool tipc_link_is_establishing(struct tipc_link *l)
  {
  	return l->state == LINK_ESTABLISHING;
  }
662921cd0   Jon Paul Maloy   tipc: merge link-...
266
267
268
269
270
271
272
273
274
275
276
277
278
  bool tipc_link_is_synching(struct tipc_link *l)
  {
  	return l->state == LINK_SYNCHING;
  }
  
  bool tipc_link_is_failingover(struct tipc_link *l)
  {
  	return l->state == LINK_FAILINGOVER;
  }
  
  bool tipc_link_is_blocked(struct tipc_link *l)
  {
  	return l->state & (LINK_RESETTING | LINK_PEER_RESET | LINK_FAILINGOVER);
b97bf3fd8   Per Liden   [TIPC] Initial merge
279
  }
742e03833   Wu Fengguang   tipc: link_is_bc_...
280
  static bool link_is_bc_sndlink(struct tipc_link *l)
526669866   Jon Paul Maloy   tipc: let broadca...
281
282
283
  {
  	return !l->bc_sndlink;
  }
742e03833   Wu Fengguang   tipc: link_is_bc_...
284
  static bool link_is_bc_rcvlink(struct tipc_link *l)
526669866   Jon Paul Maloy   tipc: let broadca...
285
286
287
  {
  	return ((l->bc_rcvlink == l) && !link_is_bc_sndlink(l));
  }
9d13ec65e   Jon Paul Maloy   tipc: introduce l...
288
  int tipc_link_is_active(struct tipc_link *l)
b97bf3fd8   Per Liden   [TIPC] Initial merge
289
  {
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
290
291
  	return l->active;
  }
9d13ec65e   Jon Paul Maloy   tipc: introduce l...
292

c72fa872a   Jon Paul Maloy   tipc: eliminate l...
293
294
295
  void tipc_link_set_active(struct tipc_link *l, bool active)
  {
  	l->active = active;
b97bf3fd8   Per Liden   [TIPC] Initial merge
296
  }
38206d593   Jon Paul Maloy   tipc: narrow down...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  u32 tipc_link_id(struct tipc_link *l)
  {
  	return l->peer_bearer_id << 16 | l->bearer_id;
  }
  
  int tipc_link_window(struct tipc_link *l)
  {
  	return l->window;
  }
  
  int tipc_link_prio(struct tipc_link *l)
  {
  	return l->priority;
  }
  
  unsigned long tipc_link_tolerance(struct tipc_link *l)
  {
  	return l->tolerance;
  }
  
  struct sk_buff_head *tipc_link_inputq(struct tipc_link *l)
  {
  	return l->inputq;
  }
  
  char tipc_link_plane(struct tipc_link *l)
  {
  	return l->net_plane;
  }
526669866   Jon Paul Maloy   tipc: let broadca...
326
327
328
  void tipc_link_add_bc_peer(struct tipc_link *snd_l,
  			   struct tipc_link *uc_l,
  			   struct sk_buff_head *xmitq)
2f5661245   Jon Paul Maloy   tipc: let broadca...
329
  {
526669866   Jon Paul Maloy   tipc: let broadca...
330
331
332
333
  	struct tipc_link *rcv_l = uc_l->bc_rcvlink;
  
  	snd_l->ackers++;
  	rcv_l->acked = snd_l->snd_nxt - 1;
9a6508382   Jon Paul Maloy   tipc: correct set...
334
  	snd_l->state = LINK_ESTABLISHED;
526669866   Jon Paul Maloy   tipc: let broadca...
335
  	tipc_link_build_bc_init_msg(uc_l, xmitq);
2f5661245   Jon Paul Maloy   tipc: let broadca...
336
  }
526669866   Jon Paul Maloy   tipc: let broadca...
337
338
339
  void tipc_link_remove_bc_peer(struct tipc_link *snd_l,
  			      struct tipc_link *rcv_l,
  			      struct sk_buff_head *xmitq)
2f5661245   Jon Paul Maloy   tipc: let broadca...
340
  {
526669866   Jon Paul Maloy   tipc: let broadca...
341
342
343
  	u16 ack = snd_l->snd_nxt - 1;
  
  	snd_l->ackers--;
a71eb7203   Jon Paul Maloy   tipc: ensure corr...
344
345
  	rcv_l->bc_peer_is_up = true;
  	rcv_l->state = LINK_ESTABLISHED;
526669866   Jon Paul Maloy   tipc: let broadca...
346
347
348
349
350
  	tipc_link_bc_ack_rcv(rcv_l, ack, xmitq);
  	tipc_link_reset(rcv_l);
  	rcv_l->state = LINK_RESET;
  	if (!snd_l->ackers) {
  		tipc_link_reset(snd_l);
9a6508382   Jon Paul Maloy   tipc: correct set...
351
  		snd_l->state = LINK_RESET;
526669866   Jon Paul Maloy   tipc: let broadca...
352
353
  		__skb_queue_purge(xmitq);
  	}
2f5661245   Jon Paul Maloy   tipc: let broadca...
354
355
356
357
358
359
  }
  
  int tipc_link_bc_peers(struct tipc_link *l)
  {
  	return l->ackers;
  }
02d11ca20   Jon Paul Maloy   tipc: transfer br...
360
361
362
363
364
365
366
367
368
369
370
  u16 link_bc_rcv_gap(struct tipc_link *l)
  {
  	struct sk_buff *skb = skb_peek(&l->deferdq);
  	u16 gap = 0;
  
  	if (more(l->snd_nxt, l->rcv_nxt))
  		gap = l->snd_nxt - l->rcv_nxt;
  	if (skb)
  		gap = buf_seqno(skb) - l->rcv_nxt;
  	return gap;
  }
959e1781a   Jon Paul Maloy   tipc: introduce j...
371
372
373
374
375
376
377
378
379
  void tipc_link_set_mtu(struct tipc_link *l, int mtu)
  {
  	l->mtu = mtu;
  }
  
  int tipc_link_mtu(struct tipc_link *l)
  {
  	return l->mtu;
  }
38206d593   Jon Paul Maloy   tipc: narrow down...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  u16 tipc_link_rcv_nxt(struct tipc_link *l)
  {
  	return l->rcv_nxt;
  }
  
  u16 tipc_link_acked(struct tipc_link *l)
  {
  	return l->acked;
  }
  
  char *tipc_link_name(struct tipc_link *l)
  {
  	return l->name;
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
394
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
395
   * tipc_link_create - create a new link
440d8963c   Jon Paul Maloy   tipc: clean up li...
396
   * @n: pointer to associated node
0e05498e9   Jon Paul Maloy   tipc: make link i...
397
398
399
400
401
402
403
404
   * @if_name: associated interface name
   * @bearer_id: id (index) of associated bearer
   * @tolerance: link tolerance to be used by link
   * @net_plane: network plane (A,B,c..) this link belongs to
   * @mtu: mtu to be advertised by link
   * @priority: priority to be used by link
   * @window: send window to be used by link
   * @session: session to be used by link
440d8963c   Jon Paul Maloy   tipc: clean up li...
405
   * @ownnode: identity of own node
0e05498e9   Jon Paul Maloy   tipc: make link i...
406
   * @peer: node id of peer node
fd556f209   Jon Paul Maloy   tipc: introduce c...
407
   * @peer_caps: bitmap describing peer node capabilities
526669866   Jon Paul Maloy   tipc: let broadca...
408
409
   * @bc_sndlink: the namespace global link used for broadcast sending
   * @bc_rcvlink: the peer specific link used for broadcast reception
440d8963c   Jon Paul Maloy   tipc: clean up li...
410
411
412
   * @inputq: queue to put messages ready for delivery
   * @namedq: queue to put binding table update messages ready for delivery
   * @link: return value, pointer to put the created link
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
413
   *
440d8963c   Jon Paul Maloy   tipc: clean up li...
414
   * Returns true if link was created, otherwise false
b97bf3fd8   Per Liden   [TIPC] Initial merge
415
   */
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
416
  bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
0e05498e9   Jon Paul Maloy   tipc: make link i...
417
418
  		      int tolerance, char net_plane, u32 mtu, int priority,
  		      int window, u32 session, u32 ownnode, u32 peer,
526669866   Jon Paul Maloy   tipc: let broadca...
419
  		      u16 peer_caps,
526669866   Jon Paul Maloy   tipc: let broadca...
420
421
422
423
  		      struct tipc_link *bc_sndlink,
  		      struct tipc_link *bc_rcvlink,
  		      struct sk_buff_head *inputq,
  		      struct sk_buff_head *namedq,
440d8963c   Jon Paul Maloy   tipc: clean up li...
424
  		      struct tipc_link **link)
b97bf3fd8   Per Liden   [TIPC] Initial merge
425
  {
440d8963c   Jon Paul Maloy   tipc: clean up li...
426
  	struct tipc_link *l;
37b9c08a8   Allan Stephens   tipc: Optimizatio...
427

440d8963c   Jon Paul Maloy   tipc: clean up li...
428
429
430
431
  	l = kzalloc(sizeof(*l), GFP_ATOMIC);
  	if (!l)
  		return false;
  	*link = l;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
432
  	l->session = session;
37b9c08a8   Allan Stephens   tipc: Optimizatio...
433

440d8963c   Jon Paul Maloy   tipc: clean up li...
434
  	/* Note: peer i/f name is completed by reset/activate message */
440d8963c   Jon Paul Maloy   tipc: clean up li...
435
436
437
  	sprintf(l->name, "%u.%u.%u:%s-%u.%u.%u:unknown",
  		tipc_zone(ownnode), tipc_cluster(ownnode), tipc_node(ownnode),
  		if_name, tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
438
  	strcpy(l->if_name, if_name);
440d8963c   Jon Paul Maloy   tipc: clean up li...
439
  	l->addr = peer;
fd556f209   Jon Paul Maloy   tipc: introduce c...
440
  	l->peer_caps = peer_caps;
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
441
  	l->net = net;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
442
  	l->peer_session = ANY_SESSION;
0e05498e9   Jon Paul Maloy   tipc: make link i...
443
444
445
446
447
448
449
  	l->bearer_id = bearer_id;
  	l->tolerance = tolerance;
  	l->net_plane = net_plane;
  	l->advertised_mtu = mtu;
  	l->mtu = mtu;
  	l->priority = priority;
  	tipc_link_set_queue_limits(l, window);
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
450
  	l->ackers = 1;
526669866   Jon Paul Maloy   tipc: let broadca...
451
452
  	l->bc_sndlink = bc_sndlink;
  	l->bc_rcvlink = bc_rcvlink;
440d8963c   Jon Paul Maloy   tipc: clean up li...
453
454
455
  	l->inputq = inputq;
  	l->namedq = namedq;
  	l->state = LINK_RESETTING;
440d8963c   Jon Paul Maloy   tipc: clean up li...
456
457
458
459
460
461
  	__skb_queue_head_init(&l->transmq);
  	__skb_queue_head_init(&l->backlogq);
  	__skb_queue_head_init(&l->deferdq);
  	skb_queue_head_init(&l->wakeupq);
  	skb_queue_head_init(l->inputq);
  	return true;
b97bf3fd8   Per Liden   [TIPC] Initial merge
462
  }
323019069   Jon Paul Maloy   tipc: use explici...
463
464
465
466
467
468
469
470
471
472
473
  /**
   * tipc_link_bc_create - create new link to be used for broadcast
   * @n: pointer to associated node
   * @mtu: mtu to be used
   * @window: send window to be used
   * @inputq: queue to put messages ready for delivery
   * @namedq: queue to put binding table update messages ready for delivery
   * @link: return value, pointer to put the created link
   *
   * Returns true if link was created, otherwise false
   */
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
474
  bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
526669866   Jon Paul Maloy   tipc: let broadca...
475
  			 int mtu, int window, u16 peer_caps,
323019069   Jon Paul Maloy   tipc: use explici...
476
477
  			 struct sk_buff_head *inputq,
  			 struct sk_buff_head *namedq,
526669866   Jon Paul Maloy   tipc: let broadca...
478
  			 struct tipc_link *bc_sndlink,
323019069   Jon Paul Maloy   tipc: use explici...
479
480
481
  			 struct tipc_link **link)
  {
  	struct tipc_link *l;
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
482
  	if (!tipc_link_create(net, "", MAX_BEARERS, 0, 'Z', mtu, 0, window,
2af5ae372   Jon Paul Maloy   tipc: clean up un...
483
  			      0, ownnode, peer, peer_caps, bc_sndlink,
526669866   Jon Paul Maloy   tipc: let broadca...
484
  			      NULL, inputq, namedq, link))
323019069   Jon Paul Maloy   tipc: use explici...
485
486
487
488
489
  		return false;
  
  	l = *link;
  	strcpy(l->name, tipc_bclink_name);
  	tipc_link_reset(l);
526669866   Jon Paul Maloy   tipc: let broadca...
490
  	l->state = LINK_RESET;
2f5661245   Jon Paul Maloy   tipc: let broadca...
491
  	l->ackers = 0;
526669866   Jon Paul Maloy   tipc: let broadca...
492
  	l->bc_rcvlink = l;
323019069   Jon Paul Maloy   tipc: use explici...
493

526669866   Jon Paul Maloy   tipc: let broadca...
494
495
496
  	/* Broadcast send link is always up */
  	if (link_is_bc_sndlink(l))
  		l->state = LINK_ESTABLISHED;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
497

01fd12bb1   Jon Paul Maloy   tipc: make replic...
498
499
500
  	/* Disable replicast if even a single peer doesn't support it */
  	if (link_is_bc_rcvlink(l) && !(peer_caps & TIPC_BCAST_RCAST))
  		tipc_bcast_disable_rcast(net);
526669866   Jon Paul Maloy   tipc: let broadca...
501
  	return true;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
502
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
503
  /**
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
504
505
506
   * tipc_link_fsm_evt - link finite state machine
   * @l: pointer to link
   * @evt: state machine event to be processed
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
507
   */
662921cd0   Jon Paul Maloy   tipc: merge link-...
508
  int tipc_link_fsm_evt(struct tipc_link *l, int evt)
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
509
  {
5045f7b90   Jon Paul Maloy   tipc: move protoc...
510
  	int rc = 0;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
511
512
  
  	switch (l->state) {
662921cd0   Jon Paul Maloy   tipc: merge link-...
513
  	case LINK_RESETTING:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
514
  		switch (evt) {
662921cd0   Jon Paul Maloy   tipc: merge link-...
515
516
  		case LINK_PEER_RESET_EVT:
  			l->state = LINK_PEER_RESET;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
517
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  		case LINK_RESET_EVT:
  			l->state = LINK_RESET;
  			break;
  		case LINK_FAILURE_EVT:
  		case LINK_FAILOVER_BEGIN_EVT:
  		case LINK_ESTABLISH_EVT:
  		case LINK_FAILOVER_END_EVT:
  		case LINK_SYNCH_BEGIN_EVT:
  		case LINK_SYNCH_END_EVT:
  		default:
  			goto illegal_evt;
  		}
  		break;
  	case LINK_RESET:
  		switch (evt) {
  		case LINK_PEER_RESET_EVT:
  			l->state = LINK_ESTABLISHING;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
535
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
536
537
538
539
540
541
  		case LINK_FAILOVER_BEGIN_EVT:
  			l->state = LINK_FAILINGOVER;
  		case LINK_FAILURE_EVT:
  		case LINK_RESET_EVT:
  		case LINK_ESTABLISH_EVT:
  		case LINK_FAILOVER_END_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
542
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
543
544
  		case LINK_SYNCH_BEGIN_EVT:
  		case LINK_SYNCH_END_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
545
  		default:
662921cd0   Jon Paul Maloy   tipc: merge link-...
546
  			goto illegal_evt;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
547
548
  		}
  		break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
549
  	case LINK_PEER_RESET:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
550
  		switch (evt) {
662921cd0   Jon Paul Maloy   tipc: merge link-...
551
552
  		case LINK_RESET_EVT:
  			l->state = LINK_ESTABLISHING;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
553
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
554
555
556
  		case LINK_PEER_RESET_EVT:
  		case LINK_ESTABLISH_EVT:
  		case LINK_FAILURE_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
557
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
558
559
560
561
562
563
564
565
566
567
568
569
  		case LINK_SYNCH_BEGIN_EVT:
  		case LINK_SYNCH_END_EVT:
  		case LINK_FAILOVER_BEGIN_EVT:
  		case LINK_FAILOVER_END_EVT:
  		default:
  			goto illegal_evt;
  		}
  		break;
  	case LINK_FAILINGOVER:
  		switch (evt) {
  		case LINK_FAILOVER_END_EVT:
  			l->state = LINK_RESET;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
570
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
571
572
573
574
575
576
577
578
  		case LINK_PEER_RESET_EVT:
  		case LINK_RESET_EVT:
  		case LINK_ESTABLISH_EVT:
  		case LINK_FAILURE_EVT:
  			break;
  		case LINK_FAILOVER_BEGIN_EVT:
  		case LINK_SYNCH_BEGIN_EVT:
  		case LINK_SYNCH_END_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
579
  		default:
662921cd0   Jon Paul Maloy   tipc: merge link-...
580
  			goto illegal_evt;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
581
582
  		}
  		break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
583
  	case LINK_ESTABLISHING:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
584
  		switch (evt) {
662921cd0   Jon Paul Maloy   tipc: merge link-...
585
586
  		case LINK_ESTABLISH_EVT:
  			l->state = LINK_ESTABLISHED;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
587
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
588
589
590
  		case LINK_FAILOVER_BEGIN_EVT:
  			l->state = LINK_FAILINGOVER;
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
591
  		case LINK_RESET_EVT:
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
592
593
  			l->state = LINK_RESET;
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
594
  		case LINK_FAILURE_EVT:
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
595
  		case LINK_PEER_RESET_EVT:
662921cd0   Jon Paul Maloy   tipc: merge link-...
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
  		case LINK_SYNCH_BEGIN_EVT:
  		case LINK_FAILOVER_END_EVT:
  			break;
  		case LINK_SYNCH_END_EVT:
  		default:
  			goto illegal_evt;
  		}
  		break;
  	case LINK_ESTABLISHED:
  		switch (evt) {
  		case LINK_PEER_RESET_EVT:
  			l->state = LINK_PEER_RESET;
  			rc |= TIPC_LINK_DOWN_EVT;
  			break;
  		case LINK_FAILURE_EVT:
  			l->state = LINK_RESETTING;
  			rc |= TIPC_LINK_DOWN_EVT;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
613
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
614
615
  		case LINK_RESET_EVT:
  			l->state = LINK_RESET;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
616
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
617
  		case LINK_ESTABLISH_EVT:
5ae2f8e68   Jon Paul Maloy   tipc: interrupt l...
618
  		case LINK_SYNCH_END_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
619
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
620
621
622
  		case LINK_SYNCH_BEGIN_EVT:
  			l->state = LINK_SYNCHING;
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
623
624
  		case LINK_FAILOVER_BEGIN_EVT:
  		case LINK_FAILOVER_END_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
625
  		default:
662921cd0   Jon Paul Maloy   tipc: merge link-...
626
  			goto illegal_evt;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
627
628
  		}
  		break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
629
  	case LINK_SYNCHING:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
630
  		switch (evt) {
662921cd0   Jon Paul Maloy   tipc: merge link-...
631
632
633
634
635
636
637
  		case LINK_PEER_RESET_EVT:
  			l->state = LINK_PEER_RESET;
  			rc |= TIPC_LINK_DOWN_EVT;
  			break;
  		case LINK_FAILURE_EVT:
  			l->state = LINK_RESETTING;
  			rc |= TIPC_LINK_DOWN_EVT;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
638
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
639
640
  		case LINK_RESET_EVT:
  			l->state = LINK_RESET;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
641
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
642
643
  		case LINK_ESTABLISH_EVT:
  		case LINK_SYNCH_BEGIN_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
644
  			break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
645
646
647
648
649
  		case LINK_SYNCH_END_EVT:
  			l->state = LINK_ESTABLISHED;
  			break;
  		case LINK_FAILOVER_BEGIN_EVT:
  		case LINK_FAILOVER_END_EVT:
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
650
  		default:
662921cd0   Jon Paul Maloy   tipc: merge link-...
651
  			goto illegal_evt;
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
652
653
654
  		}
  		break;
  	default:
662921cd0   Jon Paul Maloy   tipc: merge link-...
655
656
  		pr_err("Unknown FSM state %x in %s
  ", l->state, l->name);
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
657
  	}
662921cd0   Jon Paul Maloy   tipc: merge link-...
658
659
660
661
662
  	return rc;
  illegal_evt:
  	pr_err("Illegal FSM event %x in state %x on link %s
  ",
  	       evt, l->state, l->name);
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
663
664
  	return rc;
  }
333ef69ed   Jon Paul Maloy   tipc: simplify li...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
  /* link_profile_stats - update statistical profiling of traffic
   */
  static void link_profile_stats(struct tipc_link *l)
  {
  	struct sk_buff *skb;
  	struct tipc_msg *msg;
  	int length;
  
  	/* Update counters used in statistical profiling of send traffic */
  	l->stats.accu_queue_sz += skb_queue_len(&l->transmq);
  	l->stats.queue_sz_counts++;
  
  	skb = skb_peek(&l->transmq);
  	if (!skb)
  		return;
  	msg = buf_msg(skb);
  	length = msg_size(msg);
  
  	if (msg_user(msg) == MSG_FRAGMENTER) {
  		if (msg_type(msg) != FIRST_FRAGMENT)
  			return;
  		length = msg_size(msg_get_wrapped(msg));
  	}
  	l->stats.msg_lengths_total += length;
  	l->stats.msg_length_counts++;
  	if (length <= 64)
  		l->stats.msg_length_profile[0]++;
  	else if (length <= 256)
  		l->stats.msg_length_profile[1]++;
  	else if (length <= 1024)
  		l->stats.msg_length_profile[2]++;
  	else if (length <= 4096)
  		l->stats.msg_length_profile[3]++;
  	else if (length <= 16384)
  		l->stats.msg_length_profile[4]++;
  	else if (length <= 32768)
  		l->stats.msg_length_profile[5]++;
  	else
  		l->stats.msg_length_profile[6]++;
  }
  
  /* tipc_link_timeout - perform periodic task as instructed from node timeout
   */
  int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq)
  {
c91522f86   Ying Xue   tipc: eliminate u...
710
711
  	int mtyp = 0;
  	int rc = 0;
42b18f605   Jon Paul Maloy   tipc: refactor fu...
712
713
714
  	bool state = false;
  	bool probe = false;
  	bool setup = false;
526669866   Jon Paul Maloy   tipc: let broadca...
715
716
  	u16 bc_snt = l->bc_sndlink->snd_nxt - 1;
  	u16 bc_acked = l->bc_rcvlink->acked;
35c55c987   Jon Paul Maloy   tipc: add neighbo...
717
  	struct tipc_mon_state *mstate = &l->mon_state;
5045f7b90   Jon Paul Maloy   tipc: move protoc...
718

662921cd0   Jon Paul Maloy   tipc: merge link-...
719
720
721
  	switch (l->state) {
  	case LINK_ESTABLISHED:
  	case LINK_SYNCHING:
42b18f605   Jon Paul Maloy   tipc: refactor fu...
722
  		mtyp = STATE_MSG;
35c55c987   Jon Paul Maloy   tipc: add neighbo...
723
724
725
726
  		link_profile_stats(l);
  		tipc_mon_get_state(l->net, l->addr, mstate, l->bearer_id);
  		if (mstate->reset || (l->silent_intv_cnt > l->abort_limit))
  			return tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
42b18f605   Jon Paul Maloy   tipc: refactor fu...
727
  		state = bc_acked != bc_snt;
35c55c987   Jon Paul Maloy   tipc: add neighbo...
728
729
730
731
732
733
734
735
  		state |= l->bc_rcvlink->rcv_unacked;
  		state |= l->rcv_unacked;
  		state |= !skb_queue_empty(&l->transmq);
  		state |= !skb_queue_empty(&l->deferdq);
  		probe = mstate->probing;
  		probe |= l->silent_intv_cnt;
  		if (probe || mstate->monitoring)
  			l->silent_intv_cnt++;
662921cd0   Jon Paul Maloy   tipc: merge link-...
736
737
  		break;
  	case LINK_RESET:
42b18f605   Jon Paul Maloy   tipc: refactor fu...
738
739
  		setup = l->rst_cnt++ <= 4;
  		setup |= !(l->rst_cnt % 16);
5045f7b90   Jon Paul Maloy   tipc: move protoc...
740
  		mtyp = RESET_MSG;
662921cd0   Jon Paul Maloy   tipc: merge link-...
741
742
  		break;
  	case LINK_ESTABLISHING:
42b18f605   Jon Paul Maloy   tipc: refactor fu...
743
  		setup = true;
5045f7b90   Jon Paul Maloy   tipc: move protoc...
744
  		mtyp = ACTIVATE_MSG;
662921cd0   Jon Paul Maloy   tipc: merge link-...
745
  		break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
746
  	case LINK_PEER_RESET:
598411d70   Jon Paul Maloy   tipc: make resett...
747
  	case LINK_RESETTING:
662921cd0   Jon Paul Maloy   tipc: merge link-...
748
749
750
751
  	case LINK_FAILINGOVER:
  		break;
  	default:
  		break;
5045f7b90   Jon Paul Maloy   tipc: move protoc...
752
  	}
662921cd0   Jon Paul Maloy   tipc: merge link-...
753

42b18f605   Jon Paul Maloy   tipc: refactor fu...
754
755
  	if (state || probe || setup)
  		tipc_link_build_proto_msg(l, mtyp, probe, 0, 0, 0, xmitq);
5045f7b90   Jon Paul Maloy   tipc: move protoc...
756

333ef69ed   Jon Paul Maloy   tipc: simplify li...
757
758
  	return rc;
  }
6ab30f9cb   Jon Paul Maloy   tipc: improve lin...
759
  /**
3127a0200   Jon Paul Maloy   tipc: clean up ha...
760
   * link_schedule_user - schedule a message sender for wakeup after congestion
365ad353c   Jon Paul Maloy   tipc: reduce risk...
761
762
   * @l: congested link
   * @hdr: header of message that is being sent
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
763
   * Create pseudo msg to send back to user when congestion abates
b97bf3fd8   Per Liden   [TIPC] Initial merge
764
   */
365ad353c   Jon Paul Maloy   tipc: reduce risk...
765
  static int link_schedule_user(struct tipc_link *l, struct tipc_msg *hdr)
b97bf3fd8   Per Liden   [TIPC] Initial merge
766
  {
365ad353c   Jon Paul Maloy   tipc: reduce risk...
767
768
  	u32 dnode = tipc_own_addr(l->net);
  	u32 dport = msg_origport(hdr);
3127a0200   Jon Paul Maloy   tipc: clean up ha...
769
  	struct sk_buff *skb;
3127a0200   Jon Paul Maloy   tipc: clean up ha...
770
771
  	/* Create and schedule wakeup pseudo message */
  	skb = tipc_msg_create(SOCK_WAKEUP, 0, INT_H_SIZE, 0,
365ad353c   Jon Paul Maloy   tipc: reduce risk...
772
  			      dnode, l->addr, dport, 0, 0);
3127a0200   Jon Paul Maloy   tipc: clean up ha...
773
  	if (!skb)
22d85c794   Jon Paul Maloy   tipc: change sk_b...
774
  		return -ENOBUFS;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
775
776
777
778
  	msg_set_dest_droppable(buf_msg(skb), true);
  	TIPC_SKB_CB(skb)->chain_imp = msg_importance(hdr);
  	skb_queue_tail(&l->wakeupq, skb);
  	l->stats.link_congs++;
3127a0200   Jon Paul Maloy   tipc: clean up ha...
779
  	return -ELINKCONG;
b97bf3fd8   Per Liden   [TIPC] Initial merge
780
  }
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
781
782
  /**
   * link_prepare_wakeup - prepare users for wakeup after congestion
365ad353c   Jon Paul Maloy   tipc: reduce risk...
783
784
785
   * @l: congested link
   * Wake up a number of waiting users, as permitted by available space
   * in the send queue
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
786
   */
1f66d161a   Jon Paul Maloy   tipc: introduce s...
787
  void link_prepare_wakeup(struct tipc_link *l)
b97bf3fd8   Per Liden   [TIPC] Initial merge
788
  {
58d78b328   Ying Xue   tipc: use skb_que...
789
  	struct sk_buff *skb, *tmp;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
790
  	int imp, i = 0;
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
791

1f66d161a   Jon Paul Maloy   tipc: introduce s...
792
793
  	skb_queue_walk_safe(&l->wakeupq, skb, tmp) {
  		imp = TIPC_SKB_CB(skb)->chain_imp;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
794
795
796
797
  		if (l->backlog[imp].len < l->backlog[imp].limit) {
  			skb_unlink(skb, &l->wakeupq);
  			skb_queue_tail(l->inputq, skb);
  		} else if (i++ > 10) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
798
  			break;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
799
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
800
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
801
  }
6e498158a   Jon Paul Maloy   tipc: move link s...
802
  void tipc_link_reset(struct tipc_link *l)
b97bf3fd8   Per Liden   [TIPC] Initial merge
803
  {
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
804
805
  	l->peer_session = ANY_SESSION;
  	l->session++;
6e498158a   Jon Paul Maloy   tipc: move link s...
806
  	l->mtu = l->advertised_mtu;
6e498158a   Jon Paul Maloy   tipc: move link s...
807
808
  	__skb_queue_purge(&l->transmq);
  	__skb_queue_purge(&l->deferdq);
23d8335d7   Jon Paul Maloy   tipc: remove impl...
809
  	skb_queue_splice_init(&l->wakeupq, l->inputq);
2af5ae372   Jon Paul Maloy   tipc: clean up un...
810
811
812
813
814
815
  	__skb_queue_purge(&l->backlogq);
  	l->backlog[TIPC_LOW_IMPORTANCE].len = 0;
  	l->backlog[TIPC_MEDIUM_IMPORTANCE].len = 0;
  	l->backlog[TIPC_HIGH_IMPORTANCE].len = 0;
  	l->backlog[TIPC_CRITICAL_IMPORTANCE].len = 0;
  	l->backlog[TIPC_SYSTEM_IMPORTANCE].len = 0;
6e498158a   Jon Paul Maloy   tipc: move link s...
816
817
818
819
820
821
822
  	kfree_skb(l->reasm_buf);
  	kfree_skb(l->failover_reasm_skb);
  	l->reasm_buf = NULL;
  	l->failover_reasm_skb = NULL;
  	l->rcv_unacked = 0;
  	l->snd_nxt = 1;
  	l->rcv_nxt = 1;
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
823
  	l->acked = 0;
6e498158a   Jon Paul Maloy   tipc: move link s...
824
  	l->silent_intv_cnt = 0;
88e8ac700   Jon Paul Maloy   tipc: reduce tran...
825
  	l->rst_cnt = 0;
6e498158a   Jon Paul Maloy   tipc: move link s...
826
  	l->stale_count = 0;
526669866   Jon Paul Maloy   tipc: let broadca...
827
  	l->bc_peer_is_up = false;
35c55c987   Jon Paul Maloy   tipc: add neighbo...
828
  	memset(&l->mon_state, 0, sizeof(l->mon_state));
38206d593   Jon Paul Maloy   tipc: narrow down...
829
  	tipc_link_reset_stats(l);
b97bf3fd8   Per Liden   [TIPC] Initial merge
830
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
831
  /**
af9b028e2   Jon Paul Maloy   tipc: make media ...
832
833
834
835
836
   * tipc_link_xmit(): enqueue buffer list according to queue situation
   * @link: link to use
   * @list: chain of buffers containing message
   * @xmitq: returned list of packets to be sent by caller
   *
365ad353c   Jon Paul Maloy   tipc: reduce risk...
837
   * Consumes the buffer chain.
af9b028e2   Jon Paul Maloy   tipc: make media ...
838
839
840
841
842
843
844
845
   * Returns 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS
   * Messages at TIPC_SYSTEM_IMPORTANCE are always accepted
   */
  int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
  		   struct sk_buff_head *xmitq)
  {
  	struct tipc_msg *hdr = buf_msg(skb_peek(list));
  	unsigned int maxwin = l->window;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
846
  	int imp = msg_importance(hdr);
af9b028e2   Jon Paul Maloy   tipc: make media ...
847
848
849
  	unsigned int mtu = l->mtu;
  	u16 ack = l->rcv_nxt - 1;
  	u16 seqno = l->snd_nxt;
526669866   Jon Paul Maloy   tipc: let broadca...
850
  	u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
af9b028e2   Jon Paul Maloy   tipc: make media ...
851
852
853
  	struct sk_buff_head *transmq = &l->transmq;
  	struct sk_buff_head *backlogq = &l->backlogq;
  	struct sk_buff *skb, *_skb, *bskb;
959011224   Jon Paul Maloy   tipc: fix link st...
854
  	int pkt_cnt = skb_queue_len(list);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
855
  	int rc = 0;
af9b028e2   Jon Paul Maloy   tipc: make media ...
856

4952cd3e7   Richard Alpe   tipc: refactor no...
857
858
  	if (unlikely(msg_size(hdr) > mtu)) {
  		skb_queue_purge(list);
af9b028e2   Jon Paul Maloy   tipc: make media ...
859
  		return -EMSGSIZE;
4952cd3e7   Richard Alpe   tipc: refactor no...
860
  	}
af9b028e2   Jon Paul Maloy   tipc: make media ...
861

365ad353c   Jon Paul Maloy   tipc: reduce risk...
862
863
864
865
866
867
868
869
  	/* Allow oversubscription of one data msg per source at congestion */
  	if (unlikely(l->backlog[imp].len >= l->backlog[imp].limit)) {
  		if (imp == TIPC_SYSTEM_IMPORTANCE) {
  			pr_warn("%s<%s>, link overflow", link_rst_msg, l->name);
  			return -ENOBUFS;
  		}
  		rc = link_schedule_user(l, hdr);
  	}
959011224   Jon Paul Maloy   tipc: fix link st...
870
871
872
873
  	if (pkt_cnt > 1) {
  		l->stats.sent_fragmented++;
  		l->stats.sent_fragments += pkt_cnt;
  	}
af9b028e2   Jon Paul Maloy   tipc: make media ...
874
875
876
877
878
879
  	/* Prepare each packet for sending, and add to relevant queue: */
  	while (skb_queue_len(list)) {
  		skb = skb_peek(list);
  		hdr = buf_msg(skb);
  		msg_set_seqno(hdr, seqno);
  		msg_set_ack(hdr, ack);
526669866   Jon Paul Maloy   tipc: let broadca...
880
  		msg_set_bcast_ack(hdr, bc_ack);
af9b028e2   Jon Paul Maloy   tipc: make media ...
881
882
883
  
  		if (likely(skb_queue_len(transmq) < maxwin)) {
  			_skb = skb_clone(skb, GFP_ATOMIC);
4952cd3e7   Richard Alpe   tipc: refactor no...
884
885
  			if (!_skb) {
  				skb_queue_purge(list);
af9b028e2   Jon Paul Maloy   tipc: make media ...
886
  				return -ENOBUFS;
4952cd3e7   Richard Alpe   tipc: refactor no...
887
  			}
af9b028e2   Jon Paul Maloy   tipc: make media ...
888
889
890
  			__skb_dequeue(list);
  			__skb_queue_tail(transmq, skb);
  			__skb_queue_tail(xmitq, _skb);
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
891
  			TIPC_SKB_CB(skb)->ackers = l->ackers;
af9b028e2   Jon Paul Maloy   tipc: make media ...
892
  			l->rcv_unacked = 0;
959011224   Jon Paul Maloy   tipc: fix link st...
893
  			l->stats.sent_pkts++;
af9b028e2   Jon Paul Maloy   tipc: make media ...
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
  			seqno++;
  			continue;
  		}
  		if (tipc_msg_bundle(skb_peek_tail(backlogq), hdr, mtu)) {
  			kfree_skb(__skb_dequeue(list));
  			l->stats.sent_bundled++;
  			continue;
  		}
  		if (tipc_msg_make_bundle(&bskb, hdr, mtu, l->addr)) {
  			kfree_skb(__skb_dequeue(list));
  			__skb_queue_tail(backlogq, bskb);
  			l->backlog[msg_importance(buf_msg(bskb))].len++;
  			l->stats.sent_bundled++;
  			l->stats.sent_bundles++;
  			continue;
  		}
  		l->backlog[imp].len += skb_queue_len(list);
  		skb_queue_splice_tail_init(list, backlogq);
  	}
  	l->snd_nxt = seqno;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
914
  	return rc;
af9b028e2   Jon Paul Maloy   tipc: make media ...
915
  }
d999297c3   Jon Paul Maloy   tipc: reduce lock...
916
917
918
919
920
921
  void tipc_link_advance_backlog(struct tipc_link *l, struct sk_buff_head *xmitq)
  {
  	struct sk_buff *skb, *_skb;
  	struct tipc_msg *hdr;
  	u16 seqno = l->snd_nxt;
  	u16 ack = l->rcv_nxt - 1;
526669866   Jon Paul Maloy   tipc: let broadca...
922
  	u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
923
924
925
926
927
928
929
930
931
932
933
934
935
  
  	while (skb_queue_len(&l->transmq) < l->window) {
  		skb = skb_peek(&l->backlogq);
  		if (!skb)
  			break;
  		_skb = skb_clone(skb, GFP_ATOMIC);
  		if (!_skb)
  			break;
  		__skb_dequeue(&l->backlogq);
  		hdr = buf_msg(skb);
  		l->backlog[msg_importance(hdr)].len--;
  		__skb_queue_tail(&l->transmq, skb);
  		__skb_queue_tail(xmitq, _skb);
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
936
  		TIPC_SKB_CB(skb)->ackers = l->ackers;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
937
  		msg_set_seqno(hdr, seqno);
526669866   Jon Paul Maloy   tipc: let broadca...
938
939
  		msg_set_ack(hdr, ack);
  		msg_set_bcast_ack(hdr, bc_ack);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
940
  		l->rcv_unacked = 0;
959011224   Jon Paul Maloy   tipc: fix link st...
941
  		l->stats.sent_pkts++;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
942
943
944
945
  		seqno++;
  	}
  	l->snd_nxt = seqno;
  }
526669866   Jon Paul Maloy   tipc: let broadca...
946
  static void link_retransmit_failure(struct tipc_link *l, struct sk_buff *skb)
d356eeba8   Allan Stephens   [TIPC]: Multicast...
947
  {
526669866   Jon Paul Maloy   tipc: let broadca...
948
949
950
951
  	struct tipc_msg *hdr = buf_msg(skb);
  
  	pr_warn("Retransmission failure on link <%s>
  ", l->name);
40501f90e   Jon Paul Maloy   tipc: don't reset...
952
  	link_print(l, "State of link ");
526669866   Jon Paul Maloy   tipc: let broadca...
953
954
955
956
957
958
  	pr_info("Failed msg: usr %u, typ %u, len %u, err %u
  ",
  		msg_user(hdr), msg_type(hdr), msg_size(hdr), msg_errcode(hdr));
  	pr_info("sqno %u, prev: %x, src: %x
  ",
  		msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr));
d356eeba8   Allan Stephens   [TIPC]: Multicast...
959
  }
40501f90e   Jon Paul Maloy   tipc: don't reset...
960
961
  int tipc_link_retrans(struct tipc_link *l, struct tipc_link *nacker,
  		      u16 from, u16 to, struct sk_buff_head *xmitq)
d999297c3   Jon Paul Maloy   tipc: reduce lock...
962
963
964
  {
  	struct sk_buff *_skb, *skb = skb_peek(&l->transmq);
  	struct tipc_msg *hdr;
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
965
  	u16 ack = l->rcv_nxt - 1;
526669866   Jon Paul Maloy   tipc: let broadca...
966
  	u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
967
968
969
970
971
  
  	if (!skb)
  		return 0;
  
  	/* Detect repeated retransmit failures on same packet */
40501f90e   Jon Paul Maloy   tipc: don't reset...
972
973
974
975
  	if (nacker->last_retransm != buf_seqno(skb)) {
  		nacker->last_retransm = buf_seqno(skb);
  		nacker->stale_count = 1;
  	} else if (++nacker->stale_count > 100) {
d999297c3   Jon Paul Maloy   tipc: reduce lock...
976
  		link_retransmit_failure(l, skb);
40501f90e   Jon Paul Maloy   tipc: don't reset...
977
978
979
  		nacker->stale_count = 0;
  		if (link_is_bc_sndlink(l))
  			return TIPC_LINK_DOWN_EVT;
662921cd0   Jon Paul Maloy   tipc: merge link-...
980
  		return tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
981
  	}
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
982
983
  
  	/* Move forward to where retransmission should start */
d999297c3   Jon Paul Maloy   tipc: reduce lock...
984
  	skb_queue_walk(&l->transmq, skb) {
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
985
986
987
988
989
990
991
  		if (!less(buf_seqno(skb), from))
  			break;
  	}
  
  	skb_queue_walk_from(&l->transmq, skb) {
  		if (more(buf_seqno(skb), to))
  			break;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
992
993
994
995
996
  		hdr = buf_msg(skb);
  		_skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
  		if (!_skb)
  			return 0;
  		hdr = buf_msg(_skb);
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
997
998
  		msg_set_ack(hdr, ack);
  		msg_set_bcast_ack(hdr, bc_ack);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
999
1000
  		_skb->priority = TC_PRIO_CONTROL;
  		__skb_queue_tail(xmitq, _skb);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1001
1002
1003
1004
  		l->stats.retransmitted++;
  	}
  	return 0;
  }
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1005
  /* tipc_data_input - deliver data and name distr msgs to upper layer
7ae934beb   Erik Hugne   tipc: refactor me...
1006
   *
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1007
   * Consumes buffer if message is of right type
7ae934beb   Erik Hugne   tipc: refactor me...
1008
1009
   * Node lock must be held
   */
526669866   Jon Paul Maloy   tipc: let broadca...
1010
  static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
9073fb8be   Jon Paul Maloy   tipc: use tempora...
1011
  			    struct sk_buff_head *inputq)
7ae934beb   Erik Hugne   tipc: refactor me...
1012
  {
a853e4c6d   Jon Paul Maloy   tipc: introduce r...
1013
1014
1015
  	struct tipc_msg *hdr = buf_msg(skb);
  
  	switch (msg_user(hdr)) {
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1016
1017
1018
1019
  	case TIPC_LOW_IMPORTANCE:
  	case TIPC_MEDIUM_IMPORTANCE:
  	case TIPC_HIGH_IMPORTANCE:
  	case TIPC_CRITICAL_IMPORTANCE:
a853e4c6d   Jon Paul Maloy   tipc: introduce r...
1020
1021
1022
1023
  		if (unlikely(msg_type(hdr) == TIPC_MCAST_MSG)) {
  			skb_queue_tail(l->bc_rcvlink->inputq, skb);
  			return true;
  		}
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1024
  	case CONN_MANAGER:
9945e8043   Jon Paul Maloy   tipc: limit usage...
1025
  		skb_queue_tail(inputq, skb);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1026
  		return true;
7ae934beb   Erik Hugne   tipc: refactor me...
1027
  	case NAME_DISTRIBUTOR:
526669866   Jon Paul Maloy   tipc: let broadca...
1028
1029
  		l->bc_rcvlink->state = LINK_ESTABLISHED;
  		skb_queue_tail(l->namedq, skb);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1030
1031
  		return true;
  	case MSG_BUNDLER:
dff29b1a8   Jon Paul Maloy   tipc: eliminate d...
1032
  	case TUNNEL_PROTOCOL:
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1033
  	case MSG_FRAGMENTER:
7ae934beb   Erik Hugne   tipc: refactor me...
1034
  	case BCAST_PROTOCOL:
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1035
  		return false;
7ae934beb   Erik Hugne   tipc: refactor me...
1036
  	default:
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1037
1038
1039
1040
1041
  		pr_warn("Dropping received illegal msg type
  ");
  		kfree_skb(skb);
  		return false;
  	};
7ae934beb   Erik Hugne   tipc: refactor me...
1042
  }
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1043
1044
1045
1046
  
  /* tipc_link_input - process packet that has passed link protocol check
   *
   * Consumes buffer
7ae934beb   Erik Hugne   tipc: refactor me...
1047
   */
9073fb8be   Jon Paul Maloy   tipc: use tempora...
1048
1049
  static int tipc_link_input(struct tipc_link *l, struct sk_buff *skb,
  			   struct sk_buff_head *inputq)
7ae934beb   Erik Hugne   tipc: refactor me...
1050
  {
6e498158a   Jon Paul Maloy   tipc: move link s...
1051
1052
  	struct tipc_msg *hdr = buf_msg(skb);
  	struct sk_buff **reasm_skb = &l->reasm_buf;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1053
  	struct sk_buff *iskb;
9945e8043   Jon Paul Maloy   tipc: limit usage...
1054
  	struct sk_buff_head tmpq;
6e498158a   Jon Paul Maloy   tipc: move link s...
1055
  	int usr = msg_user(hdr);
6144a996a   Jon Paul Maloy   tipc: move all li...
1056
  	int rc = 0;
6e498158a   Jon Paul Maloy   tipc: move link s...
1057
1058
  	int pos = 0;
  	int ipos = 0;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1059

6e498158a   Jon Paul Maloy   tipc: move link s...
1060
1061
1062
1063
  	if (unlikely(usr == TUNNEL_PROTOCOL)) {
  		if (msg_type(hdr) == SYNCH_MSG) {
  			__skb_queue_purge(&l->deferdq);
  			goto drop;
8b4ed8634   Jon Paul Maloy   tipc: eliminate r...
1064
  		}
6e498158a   Jon Paul Maloy   tipc: move link s...
1065
1066
1067
1068
1069
1070
1071
  		if (!tipc_msg_extract(skb, &iskb, &ipos))
  			return rc;
  		kfree_skb(skb);
  		skb = iskb;
  		hdr = buf_msg(skb);
  		if (less(msg_seqno(hdr), l->drop_point))
  			goto drop;
9073fb8be   Jon Paul Maloy   tipc: use tempora...
1072
  		if (tipc_data_input(l, skb, inputq))
6e498158a   Jon Paul Maloy   tipc: move link s...
1073
1074
1075
1076
  			return rc;
  		usr = msg_user(hdr);
  		reasm_skb = &l->failover_reasm_skb;
  	}
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1077

6e498158a   Jon Paul Maloy   tipc: move link s...
1078
  	if (usr == MSG_BUNDLER) {
9945e8043   Jon Paul Maloy   tipc: limit usage...
1079
  		skb_queue_head_init(&tmpq);
6e498158a   Jon Paul Maloy   tipc: move link s...
1080
1081
  		l->stats.recv_bundles++;
  		l->stats.recv_bundled += msg_msgcnt(hdr);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1082
  		while (tipc_msg_extract(skb, &iskb, &pos))
9945e8043   Jon Paul Maloy   tipc: limit usage...
1083
1084
  			tipc_data_input(l, iskb, &tmpq);
  		tipc_skb_queue_splice_tail(&tmpq, inputq);
662921cd0   Jon Paul Maloy   tipc: merge link-...
1085
  		return 0;
6e498158a   Jon Paul Maloy   tipc: move link s...
1086
1087
1088
1089
  	} else if (usr == MSG_FRAGMENTER) {
  		l->stats.recv_fragments++;
  		if (tipc_buf_append(reasm_skb, &skb)) {
  			l->stats.recv_fragmented++;
9073fb8be   Jon Paul Maloy   tipc: use tempora...
1090
  			tipc_data_input(l, skb, inputq);
526669866   Jon Paul Maloy   tipc: let broadca...
1091
1092
1093
  		} else if (!*reasm_skb && !link_is_bc_rcvlink(l)) {
  			pr_warn_ratelimited("Unable to build fragment list
  ");
662921cd0   Jon Paul Maloy   tipc: merge link-...
1094
  			return tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1095
  		}
662921cd0   Jon Paul Maloy   tipc: merge link-...
1096
  		return 0;
6e498158a   Jon Paul Maloy   tipc: move link s...
1097
  	} else if (usr == BCAST_PROTOCOL) {
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
1098
  		tipc_bcast_lock(l->net);
526669866   Jon Paul Maloy   tipc: let broadca...
1099
  		tipc_link_bc_init_rcv(l->bc_rcvlink, hdr);
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
1100
  		tipc_bcast_unlock(l->net);
6e498158a   Jon Paul Maloy   tipc: move link s...
1101
1102
1103
  	}
  drop:
  	kfree_skb(skb);
662921cd0   Jon Paul Maloy   tipc: merge link-...
1104
  	return 0;
7ae934beb   Erik Hugne   tipc: refactor me...
1105
  }
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
  static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked)
  {
  	bool released = false;
  	struct sk_buff *skb, *tmp;
  
  	skb_queue_walk_safe(&l->transmq, skb, tmp) {
  		if (more(buf_seqno(skb), acked))
  			break;
  		__skb_unlink(skb, &l->transmq);
  		kfree_skb(skb);
  		released = true;
  	}
  	return released;
  }
34b9cd64c   Jon Paul Maloy   tipc: let first m...
1120
  /* tipc_link_build_state_msg: prepare link state message for transmission
526669866   Jon Paul Maloy   tipc: let broadca...
1121
1122
1123
   *
   * Note that sending of broadcast ack is coordinated among nodes, to reduce
   * risk of ack storms towards the sender
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1124
   */
34b9cd64c   Jon Paul Maloy   tipc: let first m...
1125
  int tipc_link_build_state_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1126
  {
526669866   Jon Paul Maloy   tipc: let broadca...
1127
1128
1129
1130
1131
  	if (!l)
  		return 0;
  
  	/* Broadcast ACK must be sent via a unicast link => defer to caller */
  	if (link_is_bc_rcvlink(l)) {
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1132
  		if (((l->rcv_nxt ^ tipc_own_addr(l->net)) & 0xf) != 0xf)
526669866   Jon Paul Maloy   tipc: let broadca...
1133
1134
  			return 0;
  		l->rcv_unacked = 0;
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1135
1136
1137
1138
  
  		/* Use snd_nxt to store peer's snd_nxt in broadcast rcv link */
  		l->snd_nxt = l->rcv_nxt;
  		return TIPC_LINK_SND_STATE;
526669866   Jon Paul Maloy   tipc: let broadca...
1139
1140
1141
  	}
  
  	/* Unicast ACK */
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1142
1143
1144
  	l->rcv_unacked = 0;
  	l->stats.sent_acks++;
  	tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, xmitq);
526669866   Jon Paul Maloy   tipc: let broadca...
1145
  	return 0;
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1146
  }
282b3a056   Jon Paul Maloy   tipc: send out RE...
1147
1148
1149
1150
1151
  /* tipc_link_build_reset_msg: prepare link RESET or ACTIVATE message
   */
  void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
  {
  	int mtyp = RESET_MSG;
634696b19   Jon Paul Maloy   tipc: guarantee p...
1152
  	struct sk_buff *skb;
282b3a056   Jon Paul Maloy   tipc: send out RE...
1153
1154
1155
1156
1157
  
  	if (l->state == LINK_ESTABLISHING)
  		mtyp = ACTIVATE_MSG;
  
  	tipc_link_build_proto_msg(l, mtyp, 0, 0, 0, 0, xmitq);
634696b19   Jon Paul Maloy   tipc: guarantee p...
1158
1159
1160
1161
1162
  
  	/* Inform peer that this endpoint is going down if applicable */
  	skb = skb_peek_tail(xmitq);
  	if (skb && (l->state == LINK_RESET))
  		msg_set_peer_stopping(buf_msg(skb), 1);
282b3a056   Jon Paul Maloy   tipc: send out RE...
1163
  }
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1164
  /* tipc_link_build_nack_msg: prepare link nack message for transmission
e0a05ebe2   Jon Paul Maloy   tipc: send broadc...
1165
1166
   * Note that sending of broadcast NACK is coordinated among nodes, to
   * reduce the risk of NACK storms towards the sender
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1167
   */
e0a05ebe2   Jon Paul Maloy   tipc: send broadc...
1168
1169
  static int tipc_link_build_nack_msg(struct tipc_link *l,
  				    struct sk_buff_head *xmitq)
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1170
1171
  {
  	u32 def_cnt = ++l->stats.deferred_recv;
e0a05ebe2   Jon Paul Maloy   tipc: send broadc...
1172
  	int match1, match2;
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1173

e0a05ebe2   Jon Paul Maloy   tipc: send broadc...
1174
1175
1176
1177
1178
1179
1180
  	if (link_is_bc_rcvlink(l)) {
  		match1 = def_cnt & 0xf;
  		match2 = tipc_own_addr(l->net) & 0xf;
  		if (match1 == match2)
  			return TIPC_LINK_SND_STATE;
  		return 0;
  	}
526669866   Jon Paul Maloy   tipc: let broadca...
1181

f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1182
1183
  	if ((skb_queue_len(&l->deferdq) == 1) || !(def_cnt % TIPC_NACK_INTV))
  		tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, xmitq);
e0a05ebe2   Jon Paul Maloy   tipc: send broadc...
1184
  	return 0;
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1185
  }
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1186
  /* tipc_link_rcv - process TIPC packets/messages arriving from off-node
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1187
   * @l: the link that should handle the message
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1188
1189
1190
1191
1192
1193
   * @skb: TIPC packet
   * @xmitq: queue to place packets to be sent after this call
   */
  int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
  		  struct sk_buff_head *xmitq)
  {
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1194
  	struct sk_buff_head *defq = &l->deferdq;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1195
  	struct tipc_msg *hdr;
81204c492   Jon Paul Maloy   tipc: improve seq...
1196
  	u16 seqno, rcv_nxt, win_lim;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1197
  	int rc = 0;
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1198
  	do {
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1199
  		hdr = buf_msg(skb);
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1200
1201
  		seqno = msg_seqno(hdr);
  		rcv_nxt = l->rcv_nxt;
81204c492   Jon Paul Maloy   tipc: improve seq...
1202
  		win_lim = rcv_nxt + TIPC_MAX_LINK_WIN;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1203
1204
  
  		/* Verify and update link state */
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1205
1206
  		if (unlikely(msg_user(hdr) == LINK_PROTOCOL))
  			return tipc_link_proto_rcv(l, skb, xmitq);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1207

662921cd0   Jon Paul Maloy   tipc: merge link-...
1208
  		if (unlikely(!link_is_up(l))) {
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
1209
1210
1211
  			if (l->state == LINK_ESTABLISHING)
  				rc = TIPC_LINK_UP_EVT;
  			goto drop;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1212
  		}
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1213
  		/* Don't send probe at next timeout expiration */
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1214
  		l->silent_intv_cnt = 0;
81204c492   Jon Paul Maloy   tipc: improve seq...
1215
1216
1217
1218
1219
  		/* Drop if outside receive window */
  		if (unlikely(less(seqno, rcv_nxt) || more(seqno, win_lim))) {
  			l->stats.duplicates++;
  			goto drop;
  		}
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1220
1221
1222
1223
1224
1225
  		/* Forward queues and wake up waiting users */
  		if (likely(tipc_link_release_pkts(l, msg_ack(hdr)))) {
  			tipc_link_advance_backlog(l, xmitq);
  			if (unlikely(!skb_queue_empty(&l->wakeupq)))
  				link_prepare_wakeup(l);
  		}
81204c492   Jon Paul Maloy   tipc: improve seq...
1226
1227
  		/* Defer delivery if sequence gap */
  		if (unlikely(seqno != rcv_nxt)) {
8306f99a5   Jon Paul Maloy   tipc: disallow pa...
1228
  			__tipc_skb_queue_sorted(defq, seqno, skb);
e0a05ebe2   Jon Paul Maloy   tipc: send broadc...
1229
  			rc |= tipc_link_build_nack_msg(l, xmitq);
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1230
  			break;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1231
  		}
81204c492   Jon Paul Maloy   tipc: improve seq...
1232
  		/* Deliver packet */
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1233
  		l->rcv_nxt++;
959011224   Jon Paul Maloy   tipc: fix link st...
1234
  		l->stats.recv_pkts++;
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1235
  		if (!tipc_data_input(l, skb, l->inputq))
526669866   Jon Paul Maloy   tipc: let broadca...
1236
  			rc |= tipc_link_input(l, skb, l->inputq);
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1237
  		if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN))
34b9cd64c   Jon Paul Maloy   tipc: let first m...
1238
  			rc |= tipc_link_build_state_msg(l, xmitq);
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1239
  		if (unlikely(rc & ~TIPC_LINK_SND_STATE))
526669866   Jon Paul Maloy   tipc: let broadca...
1240
  			break;
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1241
1242
1243
1244
1245
  	} while ((skb = __skb_dequeue(defq)));
  
  	return rc;
  drop:
  	kfree_skb(skb);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1246
1247
  	return rc;
  }
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1248
1249
1250
1251
  static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
  				      u16 rcvgap, int tolerance, int priority,
  				      struct sk_buff_head *xmitq)
  {
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1252
  	struct tipc_link *bcl = l->bc_rcvlink;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1253
1254
1255
  	struct sk_buff *skb;
  	struct tipc_msg *hdr;
  	struct sk_buff_head *dfq = &l->deferdq;
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1256
  	bool node_up = link_is_up(bcl);
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1257
1258
1259
  	struct tipc_mon_state *mstate = &l->mon_state;
  	int dlen = 0;
  	void *data;
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1260
1261
  
  	/* Don't send protocol message during reset or link failover */
662921cd0   Jon Paul Maloy   tipc: merge link-...
1262
  	if (tipc_link_is_blocked(l))
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1263
  		return;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1264
1265
1266
1267
1268
1269
1270
  	if (!tipc_link_is_up(l) && (mtyp == STATE_MSG))
  		return;
  
  	if (!skb_queue_empty(dfq))
  		rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt;
  
  	skb = tipc_msg_create(LINK_PROTOCOL, mtyp, INT_H_SIZE,
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1271
  			      tipc_max_domain_size, l->addr,
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1272
1273
1274
1275
1276
  			      tipc_own_addr(l->net), 0, 0, 0);
  	if (!skb)
  		return;
  
  	hdr = buf_msg(skb);
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1277
  	data = msg_data(hdr);
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1278
1279
  	msg_set_session(hdr, l->session);
  	msg_set_bearer_id(hdr, l->bearer_id);
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1280
  	msg_set_net_plane(hdr, l->net_plane);
526669866   Jon Paul Maloy   tipc: let broadca...
1281
1282
  	msg_set_next_sent(hdr, l->snd_nxt);
  	msg_set_ack(hdr, l->rcv_nxt - 1);
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1283
  	msg_set_bcast_ack(hdr, bcl->rcv_nxt - 1);
06bd2b1ed   Jon Paul Maloy   tipc: fix broadca...
1284
  	msg_set_bc_ack_invalid(hdr, !node_up);
526669866   Jon Paul Maloy   tipc: let broadca...
1285
  	msg_set_last_bcast(hdr, l->bc_sndlink->snd_nxt - 1);
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1286
1287
1288
1289
  	msg_set_link_tolerance(hdr, tolerance);
  	msg_set_linkprio(hdr, priority);
  	msg_set_redundant_link(hdr, node_up);
  	msg_set_seq_gap(hdr, 0);
526669866   Jon Paul Maloy   tipc: let broadca...
1290
  	msg_set_seqno(hdr, l->snd_nxt + U16_MAX / 2);
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1291
1292
  
  	if (mtyp == STATE_MSG) {
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1293
  		msg_set_seq_gap(hdr, rcvgap);
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1294
  		msg_set_bc_gap(hdr, link_bc_rcv_gap(bcl));
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1295
  		msg_set_probe(hdr, probe);
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1296
1297
1298
  		tipc_mon_prep(l->net, data, &dlen, mstate, l->bearer_id);
  		msg_set_size(hdr, INT_H_SIZE + dlen);
  		skb_trim(skb, INT_H_SIZE + dlen);
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1299
  		l->stats.sent_states++;
526669866   Jon Paul Maloy   tipc: let broadca...
1300
  		l->rcv_unacked = 0;
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1301
1302
1303
  	} else {
  		/* RESET_MSG or ACTIVATE_MSG */
  		msg_set_max_pkt(hdr, l->advertised_mtu);
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1304
1305
1306
  		strcpy(data, l->if_name);
  		msg_set_size(hdr, INT_H_SIZE + TIPC_MAX_IF_NAME);
  		skb_trim(skb, INT_H_SIZE + TIPC_MAX_IF_NAME);
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1307
  	}
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1308
1309
1310
1311
  	if (probe)
  		l->stats.sent_probes++;
  	if (rcvgap)
  		l->stats.sent_nacks++;
426cc2b86   Jon Paul Maloy   tipc: introduce n...
1312
  	skb->priority = TC_PRIO_CONTROL;
6e498158a   Jon Paul Maloy   tipc: move link s...
1313
  	__skb_queue_tail(xmitq, skb);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1314
  }
6e498158a   Jon Paul Maloy   tipc: move link s...
1315
  /* tipc_link_tnl_prepare(): prepare and return a list of tunnel packets
f9aa358a8   Jon Paul Maloy   tipc: simplify ti...
1316
   * with contents of the link's transmit and backlog queues.
b97bf3fd8   Per Liden   [TIPC] Initial merge
1317
   */
6e498158a   Jon Paul Maloy   tipc: move link s...
1318
1319
  void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl,
  			   int mtyp, struct sk_buff_head *xmitq)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1320
  {
6e498158a   Jon Paul Maloy   tipc: move link s...
1321
1322
1323
1324
1325
  	struct sk_buff *skb, *tnlskb;
  	struct tipc_msg *hdr, tnlhdr;
  	struct sk_buff_head *queue = &l->transmq;
  	struct sk_buff_head tmpxq, tnlq;
  	u16 pktlen, pktcnt, seqno = l->snd_nxt;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1326

6e498158a   Jon Paul Maloy   tipc: move link s...
1327
  	if (!tnl)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1328
  		return;
6e498158a   Jon Paul Maloy   tipc: move link s...
1329
1330
  	skb_queue_head_init(&tnlq);
  	skb_queue_head_init(&tmpxq);
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
1331

6e498158a   Jon Paul Maloy   tipc: move link s...
1332
1333
  	/* At least one packet required for safe algorithm => add dummy */
  	skb = tipc_msg_create(TIPC_LOW_IMPORTANCE, TIPC_DIRECT_MSG,
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1334
  			      BASIC_H_SIZE, 0, l->addr, tipc_own_addr(l->net),
6e498158a   Jon Paul Maloy   tipc: move link s...
1335
1336
1337
1338
  			      0, 0, TIPC_ERR_NO_PORT);
  	if (!skb) {
  		pr_warn("%sunable to create tunnel packet
  ", link_co_err);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1339
1340
  		return;
  	}
6e498158a   Jon Paul Maloy   tipc: move link s...
1341
1342
1343
1344
1345
  	skb_queue_tail(&tnlq, skb);
  	tipc_link_xmit(l, &tnlq, &tmpxq);
  	__skb_queue_purge(&tmpxq);
  
  	/* Initialize reusable tunnel packet header */
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1346
  	tipc_msg_init(tipc_own_addr(l->net), &tnlhdr, TUNNEL_PROTOCOL,
6e498158a   Jon Paul Maloy   tipc: move link s...
1347
1348
1349
1350
1351
1352
  		      mtyp, INT_H_SIZE, l->addr);
  	pktcnt = skb_queue_len(&l->transmq) + skb_queue_len(&l->backlogq);
  	msg_set_msgcnt(&tnlhdr, pktcnt);
  	msg_set_bearer_id(&tnlhdr, l->peer_bearer_id);
  tnl:
  	/* Wrap each packet into a tunnel packet */
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
1353
  	skb_queue_walk(queue, skb) {
6e498158a   Jon Paul Maloy   tipc: move link s...
1354
1355
1356
1357
1358
  		hdr = buf_msg(skb);
  		if (queue == &l->backlogq)
  			msg_set_seqno(hdr, seqno++);
  		pktlen = msg_size(hdr);
  		msg_set_size(&tnlhdr, pktlen + INT_H_SIZE);
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
1359
  		tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE, GFP_ATOMIC);
6e498158a   Jon Paul Maloy   tipc: move link s...
1360
1361
1362
  		if (!tnlskb) {
  			pr_warn("%sunable to send packet
  ", link_co_err);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1363
1364
  			return;
  		}
6e498158a   Jon Paul Maloy   tipc: move link s...
1365
1366
1367
  		skb_copy_to_linear_data(tnlskb, &tnlhdr, INT_H_SIZE);
  		skb_copy_to_linear_data_offset(tnlskb, INT_H_SIZE, hdr, pktlen);
  		__skb_queue_tail(&tnlq, tnlskb);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1368
  	}
6e498158a   Jon Paul Maloy   tipc: move link s...
1369
1370
1371
  	if (queue != &l->backlogq) {
  		queue = &l->backlogq;
  		goto tnl;
f006c9c70   Jon Paul Maloy   tipc: change rece...
1372
  	}
1dab3d5ac   Jon Paul Maloy   tipc: change rece...
1373

6e498158a   Jon Paul Maloy   tipc: move link s...
1374
  	tipc_link_xmit(tnl, &tnlq, xmitq);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1375

6e498158a   Jon Paul Maloy   tipc: move link s...
1376
1377
1378
1379
  	if (mtyp == FAILOVER_MSG) {
  		tnl->drop_point = l->rcv_nxt;
  		tnl->failover_reasm_skb = l->reasm_buf;
  		l->reasm_buf = NULL;
2da714251   Jon Paul Maloy   tipc: drop tunnel...
1380
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1381
  }
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
  /* tipc_link_proto_rcv(): receive link level protocol message :
   * Note that network plane id propagates through the network, and may
   * change at any time. The node with lowest numerical id determines
   * network plane
   */
  static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
  			       struct sk_buff_head *xmitq)
  {
  	struct tipc_msg *hdr = buf_msg(skb);
  	u16 rcvgap = 0;
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
1392
1393
  	u16 ack = msg_ack(hdr);
  	u16 gap = msg_seq_gap(hdr);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1394
1395
1396
  	u16 peers_snd_nxt =  msg_next_sent(hdr);
  	u16 peers_tol = msg_link_tolerance(hdr);
  	u16 peers_prio = msg_linkprio(hdr);
2be80c2d8   Jon Paul Maloy   tipc: fix stale l...
1397
  	u16 rcv_nxt = l->rcv_nxt;
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1398
  	u16 dlen = msg_data_sz(hdr);
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
1399
  	int mtyp = msg_type(hdr);
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1400
  	void *data;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1401
1402
  	char *if_name;
  	int rc = 0;
526669866   Jon Paul Maloy   tipc: let broadca...
1403
  	if (tipc_link_is_blocked(l) || !xmitq)
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1404
  		goto exit;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1405
  	if (tipc_own_addr(l->net) > msg_prevnode(hdr))
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1406
  		l->net_plane = msg_net_plane(hdr);
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1407
1408
1409
  	skb_linearize(skb);
  	hdr = buf_msg(skb);
  	data = msg_data(hdr);
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
1410
  	switch (mtyp) {
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1411
1412
1413
1414
  	case RESET_MSG:
  
  		/* Ignore duplicate RESET with old session number */
  		if ((less_eq(msg_session(hdr), l->peer_session)) &&
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1415
  		    (l->peer_session != ANY_SESSION))
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1416
1417
  			break;
  		/* fall thru' */
662921cd0   Jon Paul Maloy   tipc: merge link-...
1418

d999297c3   Jon Paul Maloy   tipc: reduce lock...
1419
1420
1421
1422
1423
1424
1425
1426
  	case ACTIVATE_MSG:
  
  		/* Complete own link name with peer's interface name */
  		if_name =  strrchr(l->name, ':') + 1;
  		if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME)
  			break;
  		if (msg_data_sz(hdr) < TIPC_MAX_IF_NAME)
  			break;
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1427
  		strncpy(if_name, data, TIPC_MAX_IF_NAME);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1428
1429
1430
1431
1432
1433
1434
1435
  
  		/* Update own tolerance if peer indicates a non-zero value */
  		if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL))
  			l->tolerance = peers_tol;
  
  		/* Update own priority if peer's priority is higher */
  		if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI))
  			l->priority = peers_prio;
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
1436
  		/* ACTIVATE_MSG serves as PEER_RESET if link is already down */
634696b19   Jon Paul Maloy   tipc: guarantee p...
1437
1438
1439
  		if (msg_peer_stopping(hdr))
  			rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
  		else if ((mtyp == RESET_MSG) || !link_is_up(l))
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
1440
1441
1442
1443
1444
  			rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT);
  
  		/* ACTIVATE_MSG takes up link if it was already locally reset */
  		if ((mtyp == ACTIVATE_MSG) && (l->state == LINK_ESTABLISHING))
  			rc = TIPC_LINK_UP_EVT;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1445
1446
  		l->peer_session = msg_session(hdr);
  		l->peer_bearer_id = msg_bearer_id(hdr);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1447
1448
1449
  		if (l->mtu > msg_max_pkt(hdr))
  			l->mtu = msg_max_pkt(hdr);
  		break;
662921cd0   Jon Paul Maloy   tipc: merge link-...
1450

d999297c3   Jon Paul Maloy   tipc: reduce lock...
1451
  	case STATE_MSG:
662921cd0   Jon Paul Maloy   tipc: merge link-...
1452

d999297c3   Jon Paul Maloy   tipc: reduce lock...
1453
1454
1455
  		/* Update own tolerance if peer indicates a non-zero value */
  		if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL))
  			l->tolerance = peers_tol;
f79675563   Jon Paul Maloy   tipc: fix compati...
1456
1457
1458
  		/* Update own prio if peer indicates a different value */
  		if ((peers_prio != l->priority) &&
  		    in_range(peers_prio, 1, TIPC_MAX_LINK_PRI)) {
817298102   Richard Alpe   tipc: fix link pr...
1459
1460
1461
  			l->priority = peers_prio;
  			rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
  		}
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1462
1463
1464
1465
  		l->silent_intv_cnt = 0;
  		l->stats.recv_states++;
  		if (msg_probe(hdr))
  			l->stats.recv_probes++;
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
1466
1467
1468
1469
  
  		if (!link_is_up(l)) {
  			if (l->state == LINK_ESTABLISHING)
  				rc = TIPC_LINK_UP_EVT;
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1470
  			break;
73f646cec   Jon Paul Maloy   tipc: delay ESTAB...
1471
  		}
35c55c987   Jon Paul Maloy   tipc: add neighbo...
1472
1473
  		tipc_mon_rcv(l->net, data, dlen, l->addr,
  			     &l->mon_state, l->bearer_id);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1474

662921cd0   Jon Paul Maloy   tipc: merge link-...
1475
  		/* Send NACK if peer has sent pkts we haven't received yet */
2be80c2d8   Jon Paul Maloy   tipc: fix stale l...
1476
  		if (more(peers_snd_nxt, rcv_nxt) && !tipc_link_is_synching(l))
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1477
1478
1479
  			rcvgap = peers_snd_nxt - l->rcv_nxt;
  		if (rcvgap || (msg_probe(hdr)))
  			tipc_link_build_proto_msg(l, STATE_MSG, 0, rcvgap,
16040894b   Jon Paul Maloy   tipc: fix compati...
1480
  						  0, 0, xmitq);
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
1481
  		tipc_link_release_pkts(l, ack);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1482
1483
  
  		/* If NACK, retransmit will now start at right position */
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
1484
  		if (gap) {
40501f90e   Jon Paul Maloy   tipc: don't reset...
1485
  			rc = tipc_link_retrans(l, l, ack + 1, ack + gap, xmitq);
d999297c3   Jon Paul Maloy   tipc: reduce lock...
1486
1487
  			l->stats.recv_nacks++;
  		}
662921cd0   Jon Paul Maloy   tipc: merge link-...
1488

d999297c3   Jon Paul Maloy   tipc: reduce lock...
1489
1490
1491
1492
1493
1494
1495
1496
  		tipc_link_advance_backlog(l, xmitq);
  		if (unlikely(!skb_queue_empty(&l->wakeupq)))
  			link_prepare_wakeup(l);
  	}
  exit:
  	kfree_skb(skb);
  	return rc;
  }
526669866   Jon Paul Maloy   tipc: let broadca...
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
  /* tipc_link_build_bc_proto_msg() - create broadcast protocol message
   */
  static bool tipc_link_build_bc_proto_msg(struct tipc_link *l, bool bcast,
  					 u16 peers_snd_nxt,
  					 struct sk_buff_head *xmitq)
  {
  	struct sk_buff *skb;
  	struct tipc_msg *hdr;
  	struct sk_buff *dfrd_skb = skb_peek(&l->deferdq);
  	u16 ack = l->rcv_nxt - 1;
  	u16 gap_to = peers_snd_nxt - 1;
  
  	skb = tipc_msg_create(BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE,
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1510
  			      0, l->addr, tipc_own_addr(l->net), 0, 0, 0);
526669866   Jon Paul Maloy   tipc: let broadca...
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
  	if (!skb)
  		return false;
  	hdr = buf_msg(skb);
  	msg_set_last_bcast(hdr, l->bc_sndlink->snd_nxt - 1);
  	msg_set_bcast_ack(hdr, ack);
  	msg_set_bcgap_after(hdr, ack);
  	if (dfrd_skb)
  		gap_to = buf_seqno(dfrd_skb) - 1;
  	msg_set_bcgap_to(hdr, gap_to);
  	msg_set_non_seq(hdr, bcast);
  	__skb_queue_tail(xmitq, skb);
  	return true;
  }
  
  /* tipc_link_build_bc_init_msg() - synchronize broadcast link endpoints.
   *
   * Give a newly added peer node the sequence number where it should
   * start receiving and acking broadcast packets.
   */
742e03833   Wu Fengguang   tipc: link_is_bc_...
1530
1531
  static void tipc_link_build_bc_init_msg(struct tipc_link *l,
  					struct sk_buff_head *xmitq)
526669866   Jon Paul Maloy   tipc: let broadca...
1532
1533
1534
1535
1536
1537
  {
  	struct sk_buff_head list;
  
  	__skb_queue_head_init(&list);
  	if (!tipc_link_build_bc_proto_msg(l->bc_rcvlink, false, 0, &list))
  		return;
06bd2b1ed   Jon Paul Maloy   tipc: fix broadca...
1538
  	msg_set_bc_ack_invalid(buf_msg(skb_peek(&list)), true);
526669866   Jon Paul Maloy   tipc: let broadca...
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
  	tipc_link_xmit(l, &list, xmitq);
  }
  
  /* tipc_link_bc_init_rcv - receive initial broadcast synch data from peer
   */
  void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr)
  {
  	int mtyp = msg_type(hdr);
  	u16 peers_snd_nxt = msg_bc_snd_nxt(hdr);
  
  	if (link_is_up(l))
  		return;
  
  	if (msg_user(hdr) == BCAST_PROTOCOL) {
  		l->rcv_nxt = peers_snd_nxt;
  		l->state = LINK_ESTABLISHED;
  		return;
  	}
  
  	if (l->peer_caps & TIPC_BCAST_SYNCH)
  		return;
  
  	if (msg_peer_node_is_up(hdr))
  		return;
  
  	/* Compatibility: accept older, less safe initial synch data */
  	if ((mtyp == RESET_MSG) || (mtyp == ACTIVATE_MSG))
  		l->rcv_nxt = peers_snd_nxt;
  }
7c4a54b96   Jon Paul Maloy   tipc: rate limit ...
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
  /* link_bc_retr eval()- check if the indicated range can be retransmitted now
   * - Adjust permitted range if there is overlap with previous retransmission
   */
  static bool link_bc_retr_eval(struct tipc_link *l, u16 *from, u16 *to)
  {
  	unsigned long elapsed = jiffies_to_msecs(jiffies - l->prev_retr);
  
  	if (less(*to, *from))
  		return false;
  
  	/* New retransmission request */
  	if ((elapsed > TIPC_BC_RETR_LIMIT) ||
  	    less(*to, l->prev_from) || more(*from, l->prev_to)) {
  		l->prev_from = *from;
  		l->prev_to = *to;
  		l->prev_retr = jiffies;
  		return true;
  	}
  
  	/* Inside range of previous retransmit */
  	if (!less(*from, l->prev_from) && !more(*to, l->prev_to))
  		return false;
  
  	/* Fully or partially outside previous range => exclude overlap */
  	if (less(*from, l->prev_from)) {
  		*to = l->prev_from - 1;
  		l->prev_from = *from;
  	}
  	if (more(*to, l->prev_to)) {
  		*from = l->prev_to + 1;
  		l->prev_to = *to;
  	}
  	l->prev_retr = jiffies;
  	return true;
  }
526669866   Jon Paul Maloy   tipc: let broadca...
1603
1604
  /* tipc_link_bc_sync_rcv - update rcv link according to peer's send state
   */
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1605
1606
  int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
  			  struct sk_buff_head *xmitq)
526669866   Jon Paul Maloy   tipc: let broadca...
1607
  {
7c4a54b96   Jon Paul Maloy   tipc: rate limit ...
1608
  	struct tipc_link *snd_l = l->bc_sndlink;
526669866   Jon Paul Maloy   tipc: let broadca...
1609
  	u16 peers_snd_nxt = msg_bc_snd_nxt(hdr);
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1610
1611
1612
  	u16 from = msg_bcast_ack(hdr) + 1;
  	u16 to = from + msg_bc_gap(hdr) - 1;
  	int rc = 0;
526669866   Jon Paul Maloy   tipc: let broadca...
1613
1614
  
  	if (!link_is_up(l))
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1615
  		return rc;
526669866   Jon Paul Maloy   tipc: let broadca...
1616
1617
  
  	if (!msg_peer_node_is_up(hdr))
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1618
  		return rc;
526669866   Jon Paul Maloy   tipc: let broadca...
1619

2d18ac4ba   Jon Paul Maloy   tipc: extend broa...
1620
1621
1622
1623
1624
  	/* Open when peer ackowledges our bcast init msg (pkt #1) */
  	if (msg_ack(hdr))
  		l->bc_peer_is_up = true;
  
  	if (!l->bc_peer_is_up)
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1625
  		return rc;
526669866   Jon Paul Maloy   tipc: let broadca...
1626

7c4a54b96   Jon Paul Maloy   tipc: rate limit ...
1627
  	l->stats.recv_nacks++;
526669866   Jon Paul Maloy   tipc: let broadca...
1628
1629
  	/* Ignore if peers_snd_nxt goes beyond receive window */
  	if (more(peers_snd_nxt, l->rcv_nxt + l->window))
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1630
  		return rc;
7c4a54b96   Jon Paul Maloy   tipc: rate limit ...
1631
  	if (link_bc_retr_eval(snd_l, &from, &to))
40501f90e   Jon Paul Maloy   tipc: don't reset...
1632
  		rc = tipc_link_retrans(snd_l, l, from, to, xmitq);
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
  
  	l->snd_nxt = peers_snd_nxt;
  	if (link_bc_rcv_gap(l))
  		rc |= TIPC_LINK_SND_STATE;
  
  	/* Return now if sender supports nack via STATE messages */
  	if (l->peer_caps & TIPC_BCAST_STATE_NACK)
  		return rc;
  
  	/* Otherwise, be backwards compatible */
526669866   Jon Paul Maloy   tipc: let broadca...
1643
1644
1645
  
  	if (!more(peers_snd_nxt, l->rcv_nxt)) {
  		l->nack_state = BC_NACK_SND_CONDITIONAL;
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1646
  		return 0;
526669866   Jon Paul Maloy   tipc: let broadca...
1647
1648
1649
1650
1651
  	}
  
  	/* Don't NACK if one was recently sent or peeked */
  	if (l->nack_state == BC_NACK_SND_SUPPRESS) {
  		l->nack_state = BC_NACK_SND_UNCONDITIONAL;
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1652
  		return 0;
526669866   Jon Paul Maloy   tipc: let broadca...
1653
1654
1655
1656
1657
1658
  	}
  
  	/* Conditionally delay NACK sending until next synch rcv */
  	if (l->nack_state == BC_NACK_SND_CONDITIONAL) {
  		l->nack_state = BC_NACK_SND_UNCONDITIONAL;
  		if ((peers_snd_nxt - l->rcv_nxt) < TIPC_MIN_LINK_WIN)
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1659
  			return 0;
526669866   Jon Paul Maloy   tipc: let broadca...
1660
1661
1662
1663
1664
  	}
  
  	/* Send NACK now but suppress next one */
  	tipc_link_build_bc_proto_msg(l, true, peers_snd_nxt, xmitq);
  	l->nack_state = BC_NACK_SND_SUPPRESS;
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1665
  	return 0;
526669866   Jon Paul Maloy   tipc: let broadca...
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
  }
  
  void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
  			  struct sk_buff_head *xmitq)
  {
  	struct sk_buff *skb, *tmp;
  	struct tipc_link *snd_l = l->bc_sndlink;
  
  	if (!link_is_up(l) || !l->bc_peer_is_up)
  		return;
  
  	if (!more(acked, l->acked))
  		return;
  
  	/* Skip over packets peer has already acked */
  	skb_queue_walk(&snd_l->transmq, skb) {
  		if (more(buf_seqno(skb), l->acked))
  			break;
  	}
  
  	/* Update/release the packets peer is acking now */
  	skb_queue_walk_from_safe(&snd_l->transmq, skb, tmp) {
  		if (more(buf_seqno(skb), acked))
  			break;
  		if (!--TIPC_SKB_CB(skb)->ackers) {
  			__skb_unlink(skb, &snd_l->transmq);
  			kfree_skb(skb);
  		}
  	}
  	l->acked = acked;
  	tipc_link_advance_backlog(snd_l, xmitq);
  	if (unlikely(!skb_queue_empty(&snd_l->wakeupq)))
  		link_prepare_wakeup(snd_l);
  }
  
  /* tipc_link_bc_nack_rcv(): receive broadcast nack message
02d11ca20   Jon Paul Maloy   tipc: transfer br...
1702
1703
   * This function is here for backwards compatibility, since
   * no BCAST_PROTOCOL/STATE messages occur from TIPC v2.5.
526669866   Jon Paul Maloy   tipc: let broadca...
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
   */
  int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
  			  struct sk_buff_head *xmitq)
  {
  	struct tipc_msg *hdr = buf_msg(skb);
  	u32 dnode = msg_destnode(hdr);
  	int mtyp = msg_type(hdr);
  	u16 acked = msg_bcast_ack(hdr);
  	u16 from = acked + 1;
  	u16 to = msg_bcgap_to(hdr);
  	u16 peers_snd_nxt = to + 1;
  	int rc = 0;
  
  	kfree_skb(skb);
  
  	if (!tipc_link_is_up(l) || !l->bc_peer_is_up)
  		return 0;
  
  	if (mtyp != STATE_MSG)
  		return 0;
e74a386d7   Jon Paul Maloy   tipc: remove pre-...
1724
  	if (dnode == tipc_own_addr(l->net)) {
526669866   Jon Paul Maloy   tipc: let broadca...
1725
  		tipc_link_bc_ack_rcv(l, acked, xmitq);
40501f90e   Jon Paul Maloy   tipc: don't reset...
1726
  		rc = tipc_link_retrans(l->bc_sndlink, l, from, to, xmitq);
526669866   Jon Paul Maloy   tipc: let broadca...
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
  		l->stats.recv_nacks++;
  		return rc;
  	}
  
  	/* Msg for other node => suppress own NACK at next sync if applicable */
  	if (more(peers_snd_nxt, l->rcv_nxt) && !less(l->rcv_nxt, from))
  		l->nack_state = BC_NACK_SND_SUPPRESS;
  
  	return 0;
  }
e3eea1eb4   Jon Paul Maloy   tipc: clean up ha...
1737
  void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1738
  {
ed193ece2   Jon Paul Maloy   tipc: simplify li...
1739
  	int max_bulk = TIPC_MAX_PUBLICATIONS / (l->mtu / ITEM_SIZE);
e3eea1eb4   Jon Paul Maloy   tipc: clean up ha...
1740
1741
  
  	l->window = win;
5a0950c27   Jon Paul Maloy   tipc: ensure that...
1742
1743
1744
1745
  	l->backlog[TIPC_LOW_IMPORTANCE].limit      = max_t(u16, 50, win);
  	l->backlog[TIPC_MEDIUM_IMPORTANCE].limit   = max_t(u16, 100, win * 2);
  	l->backlog[TIPC_HIGH_IMPORTANCE].limit     = max_t(u16, 150, win * 3);
  	l->backlog[TIPC_CRITICAL_IMPORTANCE].limit = max_t(u16, 200, win * 4);
1f66d161a   Jon Paul Maloy   tipc: introduce s...
1746
  	l->backlog[TIPC_SYSTEM_IMPORTANCE].limit   = max_bulk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1747
  }
5c216e1d2   Allan Stephens   tipc: Allow run-t...
1748
  /**
38206d593   Jon Paul Maloy   tipc: narrow down...
1749
   * link_reset_stats - reset link statistics
1a90632da   Jon Paul Maloy   tipc: eliminate r...
1750
   * @l: pointer to link
b97bf3fd8   Per Liden   [TIPC] Initial merge
1751
   */
38206d593   Jon Paul Maloy   tipc: narrow down...
1752
  void tipc_link_reset_stats(struct tipc_link *l)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1753
  {
38206d593   Jon Paul Maloy   tipc: narrow down...
1754
  	memset(&l->stats, 0, sizeof(l->stats));
b97bf3fd8   Per Liden   [TIPC] Initial merge
1755
  }
1a20cc254   Jon Paul Maloy   tipc: introduce n...
1756
  static void link_print(struct tipc_link *l, const char *str)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1757
  {
1a20cc254   Jon Paul Maloy   tipc: introduce n...
1758
  	struct sk_buff *hskb = skb_peek(&l->transmq);
c1ab3f1de   Jon Paul Maloy   tipc: make struct...
1759
  	u16 head = hskb ? msg_seqno(buf_msg(hskb)) : l->snd_nxt - 1;
1a20cc254   Jon Paul Maloy   tipc: introduce n...
1760
  	u16 tail = l->snd_nxt - 1;
7a2f7d18e   Ying Xue   tipc: decouple th...
1761

662921cd0   Jon Paul Maloy   tipc: merge link-...
1762
1763
  	pr_info("%s Link <%s> state %x
  ", str, l->name, l->state);
1a20cc254   Jon Paul Maloy   tipc: introduce n...
1764
1765
1766
1767
  	pr_info("XMTQ: %u [%u-%u], BKLGQ: %u, SNDNX: %u, RCVNX: %u
  ",
  		skb_queue_len(&l->transmq), head, tail,
  		skb_queue_len(&l->backlogq), l->snd_nxt, l->rcv_nxt);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1768
  }
0655f6a86   Richard Alpe   tipc: add bearer ...
1769
1770
1771
1772
1773
1774
1775
1776
  
  /* Parse and validate nested (link) properties valid for media, bearer and link
   */
  int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[])
  {
  	int err;
  
  	err = nla_parse_nested(props, TIPC_NLA_PROP_MAX, prop,
fceb6435e   Johannes Berg   netlink: pass ext...
1777
  			       tipc_nl_prop_policy, NULL);
0655f6a86   Richard Alpe   tipc: add bearer ...
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
  	if (err)
  		return err;
  
  	if (props[TIPC_NLA_PROP_PRIO]) {
  		u32 prio;
  
  		prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
  		if (prio > TIPC_MAX_LINK_PRI)
  			return -EINVAL;
  	}
  
  	if (props[TIPC_NLA_PROP_TOL]) {
  		u32 tol;
  
  		tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
  		if ((tol < TIPC_MIN_LINK_TOL) || (tol > TIPC_MAX_LINK_TOL))
  			return -EINVAL;
  	}
  
  	if (props[TIPC_NLA_PROP_WIN]) {
  		u32 win;
  
  		win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
  		if ((win < TIPC_MIN_LINK_WIN) || (win > TIPC_MAX_LINK_WIN))
  			return -EINVAL;
  	}
  
  	return 0;
  }
7be57fc69   Richard Alpe   tipc: add link ge...
1807

d8182804c   Richard Alpe   tipc: fix sparse ...
1808
  static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s)
7be57fc69   Richard Alpe   tipc: add link ge...
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
  {
  	int i;
  	struct nlattr *stats;
  
  	struct nla_map {
  		u32 key;
  		u32 val;
  	};
  
  	struct nla_map map[] = {
959011224   Jon Paul Maloy   tipc: fix link st...
1819
  		{TIPC_NLA_STATS_RX_INFO, 0},
7be57fc69   Richard Alpe   tipc: add link ge...
1820
1821
1822
1823
  		{TIPC_NLA_STATS_RX_FRAGMENTS, s->recv_fragments},
  		{TIPC_NLA_STATS_RX_FRAGMENTED, s->recv_fragmented},
  		{TIPC_NLA_STATS_RX_BUNDLES, s->recv_bundles},
  		{TIPC_NLA_STATS_RX_BUNDLED, s->recv_bundled},
959011224   Jon Paul Maloy   tipc: fix link st...
1824
  		{TIPC_NLA_STATS_TX_INFO, 0},
7be57fc69   Richard Alpe   tipc: add link ge...
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
  		{TIPC_NLA_STATS_TX_FRAGMENTS, s->sent_fragments},
  		{TIPC_NLA_STATS_TX_FRAGMENTED, s->sent_fragmented},
  		{TIPC_NLA_STATS_TX_BUNDLES, s->sent_bundles},
  		{TIPC_NLA_STATS_TX_BUNDLED, s->sent_bundled},
  		{TIPC_NLA_STATS_MSG_PROF_TOT, (s->msg_length_counts) ?
  			s->msg_length_counts : 1},
  		{TIPC_NLA_STATS_MSG_LEN_CNT, s->msg_length_counts},
  		{TIPC_NLA_STATS_MSG_LEN_TOT, s->msg_lengths_total},
  		{TIPC_NLA_STATS_MSG_LEN_P0, s->msg_length_profile[0]},
  		{TIPC_NLA_STATS_MSG_LEN_P1, s->msg_length_profile[1]},
  		{TIPC_NLA_STATS_MSG_LEN_P2, s->msg_length_profile[2]},
  		{TIPC_NLA_STATS_MSG_LEN_P3, s->msg_length_profile[3]},
  		{TIPC_NLA_STATS_MSG_LEN_P4, s->msg_length_profile[4]},
  		{TIPC_NLA_STATS_MSG_LEN_P5, s->msg_length_profile[5]},
  		{TIPC_NLA_STATS_MSG_LEN_P6, s->msg_length_profile[6]},
  		{TIPC_NLA_STATS_RX_STATES, s->recv_states},
  		{TIPC_NLA_STATS_RX_PROBES, s->recv_probes},
  		{TIPC_NLA_STATS_RX_NACKS, s->recv_nacks},
  		{TIPC_NLA_STATS_RX_DEFERRED, s->deferred_recv},
  		{TIPC_NLA_STATS_TX_STATES, s->sent_states},
  		{TIPC_NLA_STATS_TX_PROBES, s->sent_probes},
  		{TIPC_NLA_STATS_TX_NACKS, s->sent_nacks},
  		{TIPC_NLA_STATS_TX_ACKS, s->sent_acks},
  		{TIPC_NLA_STATS_RETRANSMITTED, s->retransmitted},
  		{TIPC_NLA_STATS_DUPLICATES, s->duplicates},
  		{TIPC_NLA_STATS_LINK_CONGS, s->link_congs},
  		{TIPC_NLA_STATS_MAX_QUEUE, s->max_queue_sz},
  		{TIPC_NLA_STATS_AVG_QUEUE, s->queue_sz_counts ?
  			(s->accu_queue_sz / s->queue_sz_counts) : 0}
  	};
  
  	stats = nla_nest_start(skb, TIPC_NLA_LINK_STATS);
  	if (!stats)
  		return -EMSGSIZE;
  
  	for (i = 0; i <  ARRAY_SIZE(map); i++)
  		if (nla_put_u32(skb, map[i].key, map[i].val))
  			goto msg_full;
  
  	nla_nest_end(skb, stats);
  
  	return 0;
  msg_full:
  	nla_nest_cancel(skb, stats);
  
  	return -EMSGSIZE;
  }
  
  /* Caller should hold appropriate locks to protect the link */
5be9c0867   Jon Paul Maloy   tipc: narrow down...
1874
1875
  int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
  		       struct tipc_link *link, int nlflags)
7be57fc69   Richard Alpe   tipc: add link ge...
1876
1877
1878
1879
1880
  {
  	int err;
  	void *hdr;
  	struct nlattr *attrs;
  	struct nlattr *prop;
347475395   Ying Xue   tipc: make tipc n...
1881
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
7be57fc69   Richard Alpe   tipc: add link ge...
1882

bfb3e5dd8   Richard Alpe   tipc: move and re...
1883
  	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
f2f67390a   Nicolas Dichtel   tipc: remove wron...
1884
  			  nlflags, TIPC_NL_LINK_GET);
7be57fc69   Richard Alpe   tipc: add link ge...
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
  	if (!hdr)
  		return -EMSGSIZE;
  
  	attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
  	if (!attrs)
  		goto msg_full;
  
  	if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, link->name))
  		goto attr_msg_full;
  	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_DEST,
347475395   Ying Xue   tipc: make tipc n...
1895
  			tipc_cluster_mask(tn->own_addr)))
7be57fc69   Richard Alpe   tipc: add link ge...
1896
  		goto attr_msg_full;
ed193ece2   Jon Paul Maloy   tipc: simplify li...
1897
  	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->mtu))
7be57fc69   Richard Alpe   tipc: add link ge...
1898
  		goto attr_msg_full;
959011224   Jon Paul Maloy   tipc: fix link st...
1899
  	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->stats.recv_pkts))
7be57fc69   Richard Alpe   tipc: add link ge...
1900
  		goto attr_msg_full;
959011224   Jon Paul Maloy   tipc: fix link st...
1901
  	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->stats.sent_pkts))
7be57fc69   Richard Alpe   tipc: add link ge...
1902
1903
1904
1905
1906
  		goto attr_msg_full;
  
  	if (tipc_link_is_up(link))
  		if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP))
  			goto attr_msg_full;
c72fa872a   Jon Paul Maloy   tipc: eliminate l...
1907
  	if (link->active)
7be57fc69   Richard Alpe   tipc: add link ge...
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
  		if (nla_put_flag(msg->skb, TIPC_NLA_LINK_ACTIVE))
  			goto attr_msg_full;
  
  	prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
  	if (!prop)
  		goto attr_msg_full;
  	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, link->priority))
  		goto prop_msg_full;
  	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, link->tolerance))
  		goto prop_msg_full;
  	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN,
1f66d161a   Jon Paul Maloy   tipc: introduce s...
1919
  			link->window))
7be57fc69   Richard Alpe   tipc: add link ge...
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
  		goto prop_msg_full;
  	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, link->priority))
  		goto prop_msg_full;
  	nla_nest_end(msg->skb, prop);
  
  	err = __tipc_nl_add_stats(msg->skb, &link->stats);
  	if (err)
  		goto attr_msg_full;
  
  	nla_nest_end(msg->skb, attrs);
  	genlmsg_end(msg->skb, hdr);
  
  	return 0;
  
  prop_msg_full:
  	nla_nest_cancel(msg->skb, prop);
  attr_msg_full:
  	nla_nest_cancel(msg->skb, attrs);
  msg_full:
  	genlmsg_cancel(msg->skb, hdr);
  
  	return -EMSGSIZE;
  }
38206d593   Jon Paul Maloy   tipc: narrow down...
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
  
  static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb,
  				      struct tipc_stats *stats)
  {
  	int i;
  	struct nlattr *nest;
  
  	struct nla_map {
  		__u32 key;
  		__u32 val;
  	};
  
  	struct nla_map map[] = {
959011224   Jon Paul Maloy   tipc: fix link st...
1956
  		{TIPC_NLA_STATS_RX_INFO, stats->recv_pkts},
38206d593   Jon Paul Maloy   tipc: narrow down...
1957
1958
1959
1960
  		{TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments},
  		{TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented},
  		{TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles},
  		{TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled},
959011224   Jon Paul Maloy   tipc: fix link st...
1961
  		{TIPC_NLA_STATS_TX_INFO, stats->sent_pkts},
38206d593   Jon Paul Maloy   tipc: narrow down...
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
  		{TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments},
  		{TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented},
  		{TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles},
  		{TIPC_NLA_STATS_TX_BUNDLED, stats->sent_bundled},
  		{TIPC_NLA_STATS_RX_NACKS, stats->recv_nacks},
  		{TIPC_NLA_STATS_RX_DEFERRED, stats->deferred_recv},
  		{TIPC_NLA_STATS_TX_NACKS, stats->sent_nacks},
  		{TIPC_NLA_STATS_TX_ACKS, stats->sent_acks},
  		{TIPC_NLA_STATS_RETRANSMITTED, stats->retransmitted},
  		{TIPC_NLA_STATS_DUPLICATES, stats->duplicates},
  		{TIPC_NLA_STATS_LINK_CONGS, stats->link_congs},
  		{TIPC_NLA_STATS_MAX_QUEUE, stats->max_queue_sz},
  		{TIPC_NLA_STATS_AVG_QUEUE, stats->queue_sz_counts ?
  			(stats->accu_queue_sz / stats->queue_sz_counts) : 0}
  	};
  
  	nest = nla_nest_start(skb, TIPC_NLA_LINK_STATS);
  	if (!nest)
  		return -EMSGSIZE;
  
  	for (i = 0; i <  ARRAY_SIZE(map); i++)
  		if (nla_put_u32(skb, map[i].key, map[i].val))
  			goto msg_full;
  
  	nla_nest_end(skb, nest);
  
  	return 0;
  msg_full:
  	nla_nest_cancel(skb, nest);
  
  	return -EMSGSIZE;
  }
  
  int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
  {
  	int err;
  	void *hdr;
  	struct nlattr *attrs;
  	struct nlattr *prop;
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
  	struct tipc_link *bcl = tn->bcl;
  
  	if (!bcl)
  		return 0;
  
  	tipc_bcast_lock(net);
  
  	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
  			  NLM_F_MULTI, TIPC_NL_LINK_GET);
b53ce3e7d   Insu Yun   tipc: unlock in e...
2011
2012
  	if (!hdr) {
  		tipc_bcast_unlock(net);
38206d593   Jon Paul Maloy   tipc: narrow down...
2013
  		return -EMSGSIZE;
b53ce3e7d   Insu Yun   tipc: unlock in e...
2014
  	}
38206d593   Jon Paul Maloy   tipc: narrow down...
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
  
  	attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
  	if (!attrs)
  		goto msg_full;
  
  	/* The broadcast link is always up */
  	if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP))
  		goto attr_msg_full;
  
  	if (nla_put_flag(msg->skb, TIPC_NLA_LINK_BROADCAST))
  		goto attr_msg_full;
  	if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name))
  		goto attr_msg_full;
959011224   Jon Paul Maloy   tipc: fix link st...
2028
  	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, 0))
38206d593   Jon Paul Maloy   tipc: narrow down...
2029
  		goto attr_msg_full;
959011224   Jon Paul Maloy   tipc: fix link st...
2030
  	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, 0))
38206d593   Jon Paul Maloy   tipc: narrow down...
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
  		goto attr_msg_full;
  
  	prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
  	if (!prop)
  		goto attr_msg_full;
  	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window))
  		goto prop_msg_full;
  	nla_nest_end(msg->skb, prop);
  
  	err = __tipc_nl_add_bc_link_stat(msg->skb, &bcl->stats);
  	if (err)
  		goto attr_msg_full;
  
  	tipc_bcast_unlock(net);
  	nla_nest_end(msg->skb, attrs);
  	genlmsg_end(msg->skb, hdr);
  
  	return 0;
  
  prop_msg_full:
  	nla_nest_cancel(msg->skb, prop);
  attr_msg_full:
  	nla_nest_cancel(msg->skb, attrs);
  msg_full:
  	tipc_bcast_unlock(net);
  	genlmsg_cancel(msg->skb, hdr);
  
  	return -EMSGSIZE;
  }
d01332f1a   Richard Alpe   tipc: fix link at...
2060
2061
  void tipc_link_set_tolerance(struct tipc_link *l, u32 tol,
  			     struct sk_buff_head *xmitq)
38206d593   Jon Paul Maloy   tipc: narrow down...
2062
2063
  {
  	l->tolerance = tol;
d01332f1a   Richard Alpe   tipc: fix link at...
2064
  	tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, tol, 0, xmitq);
38206d593   Jon Paul Maloy   tipc: narrow down...
2065
  }
d01332f1a   Richard Alpe   tipc: fix link at...
2066
2067
  void tipc_link_set_prio(struct tipc_link *l, u32 prio,
  			struct sk_buff_head *xmitq)
38206d593   Jon Paul Maloy   tipc: narrow down...
2068
2069
  {
  	l->priority = prio;
d01332f1a   Richard Alpe   tipc: fix link at...
2070
  	tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, prio, xmitq);
38206d593   Jon Paul Maloy   tipc: narrow down...
2071
2072
2073
2074
2075
2076
  }
  
  void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit)
  {
  	l->abort_limit = limit;
  }