diff options
author | Len Brown <len.brown@intel.com> | 2012-04-06 21:48:59 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-04-06 21:48:59 -0400 |
commit | eeaab2d8af2cf1d36d7086f22e9de42d6dd2995c (patch) | |
tree | 369b9c91a6d808944f07d2290fec6f9fe2731904 /net/tipc | |
parent | ee01e663373343c63e0e3d364d09f6155378dbcc (diff) | |
parent | aaef292acf3a78d9c0bb6fb72226077d286b45d7 (diff) |
Merge branches 'idle-fix' and 'misc' into release
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.c | 336 | ||||
-rw-r--r-- | net/tipc/bcast.h | 2 | ||||
-rw-r--r-- | net/tipc/bearer.c | 5 | ||||
-rw-r--r-- | net/tipc/config.c | 21 | ||||
-rw-r--r-- | net/tipc/core.c | 10 | ||||
-rw-r--r-- | net/tipc/core.h | 42 | ||||
-rw-r--r-- | net/tipc/discover.c | 79 | ||||
-rw-r--r-- | net/tipc/link.c | 299 | ||||
-rw-r--r-- | net/tipc/log.c | 2 | ||||
-rw-r--r-- | net/tipc/msg.c | 2 | ||||
-rw-r--r-- | net/tipc/msg.h | 15 | ||||
-rw-r--r-- | net/tipc/name_distr.c | 8 | ||||
-rw-r--r-- | net/tipc/name_table.c | 48 | ||||
-rw-r--r-- | net/tipc/name_table.h | 2 | ||||
-rw-r--r-- | net/tipc/net.c | 11 | ||||
-rw-r--r-- | net/tipc/node.c | 84 | ||||
-rw-r--r-- | net/tipc/node.h | 37 | ||||
-rw-r--r-- | net/tipc/port.c | 72 | ||||
-rw-r--r-- | net/tipc/port.h | 42 | ||||
-rw-r--r-- | net/tipc/socket.c | 11 | ||||
-rw-r--r-- | net/tipc/subscr.c | 2 |
21 files changed, 532 insertions, 598 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 8eb87b11d100..e00441a2092f 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -157,39 +157,14 @@ u32 tipc_bclink_get_last_sent(void) | |||
157 | return bcl->fsm_msg_cnt; | 157 | return bcl->fsm_msg_cnt; |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | 160 | static void bclink_update_last_sent(struct tipc_node *node, u32 seqno) |
161 | * bclink_set_gap - set gap according to contents of current deferred pkt queue | ||
162 | * | ||
163 | * Called with 'node' locked, bc_lock unlocked | ||
164 | */ | ||
165 | |||
166 | static void bclink_set_gap(struct tipc_node *n_ptr) | ||
167 | { | ||
168 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | ||
169 | |||
170 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = | ||
171 | mod(n_ptr->bclink.last_in); | ||
172 | if (unlikely(buf != NULL)) | ||
173 | n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * bclink_ack_allowed - test if ACK or NACK message can be sent at this moment | ||
178 | * | ||
179 | * This mechanism endeavours to prevent all nodes in network from trying | ||
180 | * to ACK or NACK at the same time. | ||
181 | * | ||
182 | * Note: TIPC uses a different trigger to distribute ACKs than it does to | ||
183 | * distribute NACKs, but tries to use the same spacing (divide by 16). | ||
184 | */ | ||
185 | |||
186 | static int bclink_ack_allowed(u32 n) | ||
187 | { | 161 | { |
188 | return (n % TIPC_MIN_LINK_WIN) == tipc_own_tag; | 162 | node->bclink.last_sent = less_eq(node->bclink.last_sent, seqno) ? |
163 | seqno : node->bclink.last_sent; | ||
189 | } | 164 | } |
190 | 165 | ||
191 | 166 | ||
192 | /** | 167 | /* |
193 | * tipc_bclink_retransmit_to - get most recent node to request retransmission | 168 | * tipc_bclink_retransmit_to - get most recent node to request retransmission |
194 | * | 169 | * |
195 | * Called with bc_lock locked | 170 | * Called with bc_lock locked |
@@ -281,7 +256,7 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) | |||
281 | if (bcbuf_acks(crs) == 0) { | 256 | if (bcbuf_acks(crs) == 0) { |
282 | bcl->first_out = next; | 257 | bcl->first_out = next; |
283 | bcl->out_queue_size--; | 258 | bcl->out_queue_size--; |
284 | buf_discard(crs); | 259 | kfree_skb(crs); |
285 | released = 1; | 260 | released = 1; |
286 | } | 261 | } |
287 | crs = next; | 262 | crs = next; |
@@ -300,140 +275,94 @@ exit: | |||
300 | spin_unlock_bh(&bc_lock); | 275 | spin_unlock_bh(&bc_lock); |
301 | } | 276 | } |
302 | 277 | ||
303 | /** | 278 | /* |
304 | * bclink_send_ack - unicast an ACK msg | 279 | * tipc_bclink_update_link_state - update broadcast link state |
305 | * | 280 | * |
306 | * tipc_net_lock and node lock set | 281 | * tipc_net_lock and node lock set |
307 | */ | 282 | */ |
308 | 283 | ||
309 | static void bclink_send_ack(struct tipc_node *n_ptr) | 284 | void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent) |
310 | { | 285 | { |
311 | struct tipc_link *l_ptr = n_ptr->active_links[n_ptr->addr & 1]; | 286 | struct sk_buff *buf; |
312 | 287 | ||
313 | if (l_ptr != NULL) | 288 | /* Ignore "stale" link state info */ |
314 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
315 | } | ||
316 | 289 | ||
317 | /** | 290 | if (less_eq(last_sent, n_ptr->bclink.last_in)) |
318 | * bclink_send_nack- broadcast a NACK msg | 291 | return; |
319 | * | ||
320 | * tipc_net_lock and node lock set | ||
321 | */ | ||
322 | 292 | ||
323 | static void bclink_send_nack(struct tipc_node *n_ptr) | 293 | /* Update link synchronization state; quit if in sync */ |
324 | { | 294 | |
325 | struct sk_buff *buf; | 295 | bclink_update_last_sent(n_ptr, last_sent); |
326 | struct tipc_msg *msg; | 296 | |
297 | if (n_ptr->bclink.last_sent == n_ptr->bclink.last_in) | ||
298 | return; | ||
299 | |||
300 | /* Update out-of-sync state; quit if loss is still unconfirmed */ | ||
301 | |||
302 | if ((++n_ptr->bclink.oos_state) == 1) { | ||
303 | if (n_ptr->bclink.deferred_size < (TIPC_MIN_LINK_WIN / 2)) | ||
304 | return; | ||
305 | n_ptr->bclink.oos_state++; | ||
306 | } | ||
327 | 307 | ||
328 | if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to)) | 308 | /* Don't NACK if one has been recently sent (or seen) */ |
309 | |||
310 | if (n_ptr->bclink.oos_state & 0x1) | ||
329 | return; | 311 | return; |
330 | 312 | ||
313 | /* Send NACK */ | ||
314 | |||
331 | buf = tipc_buf_acquire(INT_H_SIZE); | 315 | buf = tipc_buf_acquire(INT_H_SIZE); |
332 | if (buf) { | 316 | if (buf) { |
333 | msg = buf_msg(buf); | 317 | struct tipc_msg *msg = buf_msg(buf); |
318 | |||
334 | tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, | 319 | tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, |
335 | INT_H_SIZE, n_ptr->addr); | 320 | INT_H_SIZE, n_ptr->addr); |
336 | msg_set_non_seq(msg, 1); | 321 | msg_set_non_seq(msg, 1); |
337 | msg_set_mc_netid(msg, tipc_net_id); | 322 | msg_set_mc_netid(msg, tipc_net_id); |
338 | msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); | 323 | msg_set_bcast_ack(msg, n_ptr->bclink.last_in); |
339 | msg_set_bcgap_after(msg, n_ptr->bclink.gap_after); | 324 | msg_set_bcgap_after(msg, n_ptr->bclink.last_in); |
340 | msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); | 325 | msg_set_bcgap_to(msg, n_ptr->bclink.deferred_head |
341 | msg_set_bcast_tag(msg, tipc_own_tag); | 326 | ? buf_seqno(n_ptr->bclink.deferred_head) - 1 |
327 | : n_ptr->bclink.last_sent); | ||
342 | 328 | ||
329 | spin_lock_bh(&bc_lock); | ||
343 | tipc_bearer_send(&bcbearer->bearer, buf, NULL); | 330 | tipc_bearer_send(&bcbearer->bearer, buf, NULL); |
344 | bcl->stats.sent_nacks++; | 331 | bcl->stats.sent_nacks++; |
345 | buf_discard(buf); | 332 | spin_unlock_bh(&bc_lock); |
346 | 333 | kfree_skb(buf); | |
347 | /* | ||
348 | * Ensure we doesn't send another NACK msg to the node | ||
349 | * until 16 more deferred messages arrive from it | ||
350 | * (i.e. helps prevent all nodes from NACK'ing at same time) | ||
351 | */ | ||
352 | 334 | ||
353 | n_ptr->bclink.nack_sync = tipc_own_tag; | 335 | n_ptr->bclink.oos_state++; |
354 | } | 336 | } |
355 | } | 337 | } |
356 | 338 | ||
357 | /** | 339 | /* |
358 | * tipc_bclink_check_gap - send a NACK if a sequence gap exists | 340 | * bclink_peek_nack - monitor retransmission requests sent by other nodes |
359 | * | 341 | * |
360 | * tipc_net_lock and node lock set | 342 | * Delay any upcoming NACK by this node if another node has already |
361 | */ | 343 | * requested the first message this node is going to ask for. |
362 | |||
363 | void tipc_bclink_check_gap(struct tipc_node *n_ptr, u32 last_sent) | ||
364 | { | ||
365 | if (!n_ptr->bclink.supported || | ||
366 | less_eq(last_sent, mod(n_ptr->bclink.last_in))) | ||
367 | return; | ||
368 | |||
369 | bclink_set_gap(n_ptr); | ||
370 | if (n_ptr->bclink.gap_after == n_ptr->bclink.gap_to) | ||
371 | n_ptr->bclink.gap_to = last_sent; | ||
372 | bclink_send_nack(n_ptr); | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * tipc_bclink_peek_nack - process a NACK msg meant for another node | ||
377 | * | 344 | * |
378 | * Only tipc_net_lock set. | 345 | * Only tipc_net_lock set. |
379 | */ | 346 | */ |
380 | 347 | ||
381 | static void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) | 348 | static void bclink_peek_nack(struct tipc_msg *msg) |
382 | { | 349 | { |
383 | struct tipc_node *n_ptr = tipc_node_find(dest); | 350 | struct tipc_node *n_ptr = tipc_node_find(msg_destnode(msg)); |
384 | u32 my_after, my_to; | ||
385 | 351 | ||
386 | if (unlikely(!n_ptr || !tipc_node_is_up(n_ptr))) | 352 | if (unlikely(!n_ptr)) |
387 | return; | 353 | return; |
354 | |||
388 | tipc_node_lock(n_ptr); | 355 | tipc_node_lock(n_ptr); |
389 | /* | ||
390 | * Modify gap to suppress unnecessary NACKs from this node | ||
391 | */ | ||
392 | my_after = n_ptr->bclink.gap_after; | ||
393 | my_to = n_ptr->bclink.gap_to; | ||
394 | |||
395 | if (less_eq(gap_after, my_after)) { | ||
396 | if (less(my_after, gap_to) && less(gap_to, my_to)) | ||
397 | n_ptr->bclink.gap_after = gap_to; | ||
398 | else if (less_eq(my_to, gap_to)) | ||
399 | n_ptr->bclink.gap_to = n_ptr->bclink.gap_after; | ||
400 | } else if (less_eq(gap_after, my_to)) { | ||
401 | if (less_eq(my_to, gap_to)) | ||
402 | n_ptr->bclink.gap_to = gap_after; | ||
403 | } else { | ||
404 | /* | ||
405 | * Expand gap if missing bufs not in deferred queue: | ||
406 | */ | ||
407 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | ||
408 | u32 prev = n_ptr->bclink.gap_to; | ||
409 | 356 | ||
410 | for (; buf; buf = buf->next) { | 357 | if (n_ptr->bclink.supported && |
411 | u32 seqno = buf_seqno(buf); | 358 | (n_ptr->bclink.last_in != n_ptr->bclink.last_sent) && |
359 | (n_ptr->bclink.last_in == msg_bcgap_after(msg))) | ||
360 | n_ptr->bclink.oos_state = 2; | ||
412 | 361 | ||
413 | if (mod(seqno - prev) != 1) { | ||
414 | buf = NULL; | ||
415 | break; | ||
416 | } | ||
417 | if (seqno == gap_after) | ||
418 | break; | ||
419 | prev = seqno; | ||
420 | } | ||
421 | if (buf == NULL) | ||
422 | n_ptr->bclink.gap_to = gap_after; | ||
423 | } | ||
424 | /* | ||
425 | * Some nodes may send a complementary NACK now: | ||
426 | */ | ||
427 | if (bclink_ack_allowed(sender_tag + 1)) { | ||
428 | if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) { | ||
429 | bclink_send_nack(n_ptr); | ||
430 | bclink_set_gap(n_ptr); | ||
431 | } | ||
432 | } | ||
433 | tipc_node_unlock(n_ptr); | 362 | tipc_node_unlock(n_ptr); |
434 | } | 363 | } |
435 | 364 | ||
436 | /** | 365 | /* |
437 | * tipc_bclink_send_msg - broadcast a packet to all nodes in cluster | 366 | * tipc_bclink_send_msg - broadcast a packet to all nodes in cluster |
438 | */ | 367 | */ |
439 | 368 | ||
@@ -445,7 +374,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf) | |||
445 | 374 | ||
446 | if (!bclink->bcast_nodes.count) { | 375 | if (!bclink->bcast_nodes.count) { |
447 | res = msg_data_sz(buf_msg(buf)); | 376 | res = msg_data_sz(buf_msg(buf)); |
448 | buf_discard(buf); | 377 | kfree_skb(buf); |
449 | goto exit; | 378 | goto exit; |
450 | } | 379 | } |
451 | 380 | ||
@@ -460,7 +389,33 @@ exit: | |||
460 | return res; | 389 | return res; |
461 | } | 390 | } |
462 | 391 | ||
463 | /** | 392 | /* |
393 | * bclink_accept_pkt - accept an incoming, in-sequence broadcast packet | ||
394 | * | ||
395 | * Called with both sending node's lock and bc_lock taken. | ||
396 | */ | ||
397 | |||
398 | static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) | ||
399 | { | ||
400 | bclink_update_last_sent(node, seqno); | ||
401 | node->bclink.last_in = seqno; | ||
402 | node->bclink.oos_state = 0; | ||
403 | bcl->stats.recv_info++; | ||
404 | |||
405 | /* | ||
406 | * Unicast an ACK periodically, ensuring that | ||
407 | * all nodes in the cluster don't ACK at the same time | ||
408 | */ | ||
409 | |||
410 | if (((seqno - tipc_own_addr) % TIPC_MIN_LINK_WIN) == 0) { | ||
411 | tipc_link_send_proto_msg( | ||
412 | node->active_links[node->addr & 1], | ||
413 | STATE_MSG, 0, 0, 0, 0, 0); | ||
414 | bcl->stats.sent_acks++; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | /* | ||
464 | * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards | 419 | * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards |
465 | * | 420 | * |
466 | * tipc_net_lock is read_locked, no other locks set | 421 | * tipc_net_lock is read_locked, no other locks set |
@@ -472,7 +427,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) | |||
472 | struct tipc_node *node; | 427 | struct tipc_node *node; |
473 | u32 next_in; | 428 | u32 next_in; |
474 | u32 seqno; | 429 | u32 seqno; |
475 | struct sk_buff *deferred; | 430 | int deferred; |
476 | 431 | ||
477 | /* Screen out unwanted broadcast messages */ | 432 | /* Screen out unwanted broadcast messages */ |
478 | 433 | ||
@@ -487,6 +442,8 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) | |||
487 | if (unlikely(!node->bclink.supported)) | 442 | if (unlikely(!node->bclink.supported)) |
488 | goto unlock; | 443 | goto unlock; |
489 | 444 | ||
445 | /* Handle broadcast protocol message */ | ||
446 | |||
490 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { | 447 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { |
491 | if (msg_type(msg) != STATE_MSG) | 448 | if (msg_type(msg) != STATE_MSG) |
492 | goto unlock; | 449 | goto unlock; |
@@ -501,89 +458,118 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) | |||
501 | spin_unlock_bh(&bc_lock); | 458 | spin_unlock_bh(&bc_lock); |
502 | } else { | 459 | } else { |
503 | tipc_node_unlock(node); | 460 | tipc_node_unlock(node); |
504 | tipc_bclink_peek_nack(msg_destnode(msg), | 461 | bclink_peek_nack(msg); |
505 | msg_bcast_tag(msg), | ||
506 | msg_bcgap_after(msg), | ||
507 | msg_bcgap_to(msg)); | ||
508 | } | 462 | } |
509 | goto exit; | 463 | goto exit; |
510 | } | 464 | } |
511 | 465 | ||
512 | /* Handle in-sequence broadcast message */ | 466 | /* Handle in-sequence broadcast message */ |
513 | 467 | ||
514 | receive: | ||
515 | next_in = mod(node->bclink.last_in + 1); | ||
516 | seqno = msg_seqno(msg); | 468 | seqno = msg_seqno(msg); |
469 | next_in = mod(node->bclink.last_in + 1); | ||
517 | 470 | ||
518 | if (likely(seqno == next_in)) { | 471 | if (likely(seqno == next_in)) { |
519 | bcl->stats.recv_info++; | 472 | receive: |
520 | node->bclink.last_in++; | 473 | /* Deliver message to destination */ |
521 | bclink_set_gap(node); | 474 | |
522 | if (unlikely(bclink_ack_allowed(seqno))) { | ||
523 | bclink_send_ack(node); | ||
524 | bcl->stats.sent_acks++; | ||
525 | } | ||
526 | if (likely(msg_isdata(msg))) { | 475 | if (likely(msg_isdata(msg))) { |
476 | spin_lock_bh(&bc_lock); | ||
477 | bclink_accept_pkt(node, seqno); | ||
478 | spin_unlock_bh(&bc_lock); | ||
527 | tipc_node_unlock(node); | 479 | tipc_node_unlock(node); |
528 | if (likely(msg_mcast(msg))) | 480 | if (likely(msg_mcast(msg))) |
529 | tipc_port_recv_mcast(buf, NULL); | 481 | tipc_port_recv_mcast(buf, NULL); |
530 | else | 482 | else |
531 | buf_discard(buf); | 483 | kfree_skb(buf); |
532 | } else if (msg_user(msg) == MSG_BUNDLER) { | 484 | } else if (msg_user(msg) == MSG_BUNDLER) { |
485 | spin_lock_bh(&bc_lock); | ||
486 | bclink_accept_pkt(node, seqno); | ||
533 | bcl->stats.recv_bundles++; | 487 | bcl->stats.recv_bundles++; |
534 | bcl->stats.recv_bundled += msg_msgcnt(msg); | 488 | bcl->stats.recv_bundled += msg_msgcnt(msg); |
489 | spin_unlock_bh(&bc_lock); | ||
535 | tipc_node_unlock(node); | 490 | tipc_node_unlock(node); |
536 | tipc_link_recv_bundle(buf); | 491 | tipc_link_recv_bundle(buf); |
537 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | 492 | } else if (msg_user(msg) == MSG_FRAGMENTER) { |
493 | int ret = tipc_link_recv_fragment(&node->bclink.defragm, | ||
494 | &buf, &msg); | ||
495 | if (ret < 0) | ||
496 | goto unlock; | ||
497 | spin_lock_bh(&bc_lock); | ||
498 | bclink_accept_pkt(node, seqno); | ||
538 | bcl->stats.recv_fragments++; | 499 | bcl->stats.recv_fragments++; |
539 | if (tipc_link_recv_fragment(&node->bclink.defragm, | 500 | if (ret > 0) |
540 | &buf, &msg)) | ||
541 | bcl->stats.recv_fragmented++; | 501 | bcl->stats.recv_fragmented++; |
502 | spin_unlock_bh(&bc_lock); | ||
542 | tipc_node_unlock(node); | 503 | tipc_node_unlock(node); |
543 | tipc_net_route_msg(buf); | 504 | tipc_net_route_msg(buf); |
544 | } else if (msg_user(msg) == NAME_DISTRIBUTOR) { | 505 | } else if (msg_user(msg) == NAME_DISTRIBUTOR) { |
506 | spin_lock_bh(&bc_lock); | ||
507 | bclink_accept_pkt(node, seqno); | ||
508 | spin_unlock_bh(&bc_lock); | ||
545 | tipc_node_unlock(node); | 509 | tipc_node_unlock(node); |
546 | tipc_named_recv(buf); | 510 | tipc_named_recv(buf); |
547 | } else { | 511 | } else { |
512 | spin_lock_bh(&bc_lock); | ||
513 | bclink_accept_pkt(node, seqno); | ||
514 | spin_unlock_bh(&bc_lock); | ||
548 | tipc_node_unlock(node); | 515 | tipc_node_unlock(node); |
549 | buf_discard(buf); | 516 | kfree_skb(buf); |
550 | } | 517 | } |
551 | buf = NULL; | 518 | buf = NULL; |
519 | |||
520 | /* Determine new synchronization state */ | ||
521 | |||
552 | tipc_node_lock(node); | 522 | tipc_node_lock(node); |
553 | deferred = node->bclink.deferred_head; | 523 | if (unlikely(!tipc_node_is_up(node))) |
554 | if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { | 524 | goto unlock; |
555 | buf = deferred; | 525 | |
556 | msg = buf_msg(buf); | 526 | if (node->bclink.last_in == node->bclink.last_sent) |
557 | node->bclink.deferred_head = deferred->next; | 527 | goto unlock; |
558 | goto receive; | 528 | |
559 | } | 529 | if (!node->bclink.deferred_head) { |
560 | } else if (less(next_in, seqno)) { | 530 | node->bclink.oos_state = 1; |
561 | u32 gap_after = node->bclink.gap_after; | 531 | goto unlock; |
562 | u32 gap_to = node->bclink.gap_to; | ||
563 | |||
564 | if (tipc_link_defer_pkt(&node->bclink.deferred_head, | ||
565 | &node->bclink.deferred_tail, | ||
566 | buf)) { | ||
567 | node->bclink.nack_sync++; | ||
568 | bcl->stats.deferred_recv++; | ||
569 | if (seqno == mod(gap_after + 1)) | ||
570 | node->bclink.gap_after = seqno; | ||
571 | else if (less(gap_after, seqno) && less(seqno, gap_to)) | ||
572 | node->bclink.gap_to = seqno; | ||
573 | } | 532 | } |
533 | |||
534 | msg = buf_msg(node->bclink.deferred_head); | ||
535 | seqno = msg_seqno(msg); | ||
536 | next_in = mod(next_in + 1); | ||
537 | if (seqno != next_in) | ||
538 | goto unlock; | ||
539 | |||
540 | /* Take in-sequence message from deferred queue & deliver it */ | ||
541 | |||
542 | buf = node->bclink.deferred_head; | ||
543 | node->bclink.deferred_head = buf->next; | ||
544 | node->bclink.deferred_size--; | ||
545 | goto receive; | ||
546 | } | ||
547 | |||
548 | /* Handle out-of-sequence broadcast message */ | ||
549 | |||
550 | if (less(next_in, seqno)) { | ||
551 | deferred = tipc_link_defer_pkt(&node->bclink.deferred_head, | ||
552 | &node->bclink.deferred_tail, | ||
553 | buf); | ||
554 | node->bclink.deferred_size += deferred; | ||
555 | bclink_update_last_sent(node, seqno); | ||
574 | buf = NULL; | 556 | buf = NULL; |
575 | if (bclink_ack_allowed(node->bclink.nack_sync)) { | 557 | } else |
576 | if (gap_to != gap_after) | 558 | deferred = 0; |
577 | bclink_send_nack(node); | 559 | |
578 | bclink_set_gap(node); | 560 | spin_lock_bh(&bc_lock); |
579 | } | 561 | |
580 | } else { | 562 | if (deferred) |
563 | bcl->stats.deferred_recv++; | ||
564 | else | ||
581 | bcl->stats.duplicates++; | 565 | bcl->stats.duplicates++; |
582 | } | 566 | |
567 | spin_unlock_bh(&bc_lock); | ||
568 | |||
583 | unlock: | 569 | unlock: |
584 | tipc_node_unlock(node); | 570 | tipc_node_unlock(node); |
585 | exit: | 571 | exit: |
586 | buf_discard(buf); | 572 | kfree_skb(buf); |
587 | } | 573 | } |
588 | 574 | ||
589 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) | 575 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index b009666c60b0..5571394098f9 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -96,7 +96,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf); | |||
96 | void tipc_bclink_recv_pkt(struct sk_buff *buf); | 96 | void tipc_bclink_recv_pkt(struct sk_buff *buf); |
97 | u32 tipc_bclink_get_last_sent(void); | 97 | u32 tipc_bclink_get_last_sent(void); |
98 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); | 98 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); |
99 | void tipc_bclink_check_gap(struct tipc_node *n_ptr, u32 seqno); | 99 | void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent); |
100 | int tipc_bclink_stats(char *stats_buf, const u32 buf_size); | 100 | int tipc_bclink_stats(char *stats_buf, const u32 buf_size); |
101 | int tipc_bclink_reset_stats(void); | 101 | int tipc_bclink_reset_stats(void); |
102 | int tipc_bclink_set_queue_limits(u32 limit); | 102 | int tipc_bclink_set_queue_limits(u32 limit); |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 329fb659fae4..5dfd89c40429 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -435,7 +435,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | |||
435 | u32 i; | 435 | u32 i; |
436 | int res = -EINVAL; | 436 | int res = -EINVAL; |
437 | 437 | ||
438 | if (tipc_mode != TIPC_NET_MODE) { | 438 | if (!tipc_own_addr) { |
439 | warn("Bearer <%s> rejected, not supported in standalone mode\n", | 439 | warn("Bearer <%s> rejected, not supported in standalone mode\n", |
440 | name); | 440 | name); |
441 | return -ENOPROTOOPT; | 441 | return -ENOPROTOOPT; |
@@ -456,8 +456,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | |||
456 | warn("Bearer <%s> rejected, illegal discovery domain\n", name); | 456 | warn("Bearer <%s> rejected, illegal discovery domain\n", name); |
457 | return -EINVAL; | 457 | return -EINVAL; |
458 | } | 458 | } |
459 | if ((priority < TIPC_MIN_LINK_PRI || | 459 | if ((priority > TIPC_MAX_LINK_PRI) && |
460 | priority > TIPC_MAX_LINK_PRI) && | ||
461 | (priority != TIPC_MEDIA_LINK_PRI)) { | 460 | (priority != TIPC_MEDIA_LINK_PRI)) { |
462 | warn("Bearer <%s> rejected, illegal priority\n", name); | 461 | warn("Bearer <%s> rejected, illegal priority\n", name); |
463 | return -EINVAL; | 462 | return -EINVAL; |
diff --git a/net/tipc/config.c b/net/tipc/config.c index 4785bf26cdf4..f76d3b15e4e2 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -179,7 +179,7 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
179 | if (!tipc_addr_node_valid(addr)) | 179 | if (!tipc_addr_node_valid(addr)) |
180 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 180 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
181 | " (node address)"); | 181 | " (node address)"); |
182 | if (tipc_mode == TIPC_NET_MODE) | 182 | if (tipc_own_addr) |
183 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 183 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
184 | " (cannot change node address once assigned)"); | 184 | " (cannot change node address once assigned)"); |
185 | 185 | ||
@@ -218,7 +218,7 @@ static struct sk_buff *cfg_set_max_publications(void) | |||
218 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 218 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
219 | 219 | ||
220 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 220 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
221 | if (value != delimit(value, 1, 65535)) | 221 | if (value < 1 || value > 65535) |
222 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 222 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
223 | " (max publications must be 1-65535)"); | 223 | " (max publications must be 1-65535)"); |
224 | tipc_max_publications = value; | 224 | tipc_max_publications = value; |
@@ -233,7 +233,7 @@ static struct sk_buff *cfg_set_max_subscriptions(void) | |||
233 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 233 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
234 | 234 | ||
235 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 235 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
236 | if (value != delimit(value, 1, 65535)) | 236 | if (value < 1 || value > 65535) |
237 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 237 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
238 | " (max subscriptions must be 1-65535"); | 238 | " (max subscriptions must be 1-65535"); |
239 | tipc_max_subscriptions = value; | 239 | tipc_max_subscriptions = value; |
@@ -249,14 +249,11 @@ static struct sk_buff *cfg_set_max_ports(void) | |||
249 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 249 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
250 | if (value == tipc_max_ports) | 250 | if (value == tipc_max_ports) |
251 | return tipc_cfg_reply_none(); | 251 | return tipc_cfg_reply_none(); |
252 | if (value != delimit(value, 127, 65535)) | 252 | if (value < 127 || value > 65535) |
253 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 253 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
254 | " (max ports must be 127-65535)"); | 254 | " (max ports must be 127-65535)"); |
255 | if (tipc_mode != TIPC_NOT_RUNNING) | 255 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
256 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 256 | " (cannot change max ports while TIPC is active)"); |
257 | " (cannot change max ports while TIPC is active)"); | ||
258 | tipc_max_ports = value; | ||
259 | return tipc_cfg_reply_none(); | ||
260 | } | 257 | } |
261 | 258 | ||
262 | static struct sk_buff *cfg_set_netid(void) | 259 | static struct sk_buff *cfg_set_netid(void) |
@@ -268,10 +265,10 @@ static struct sk_buff *cfg_set_netid(void) | |||
268 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 265 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
269 | if (value == tipc_net_id) | 266 | if (value == tipc_net_id) |
270 | return tipc_cfg_reply_none(); | 267 | return tipc_cfg_reply_none(); |
271 | if (value != delimit(value, 1, 9999)) | 268 | if (value < 1 || value > 9999) |
272 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 269 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
273 | " (network id must be 1-9999)"); | 270 | " (network id must be 1-9999)"); |
274 | if (tipc_mode == TIPC_NET_MODE) | 271 | if (tipc_own_addr) |
275 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 272 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
276 | " (cannot change network id once TIPC has joined a network)"); | 273 | " (cannot change network id once TIPC has joined a network)"); |
277 | tipc_net_id = value; | 274 | tipc_net_id = value; |
@@ -481,7 +478,7 @@ int tipc_cfg_init(void) | |||
481 | 478 | ||
482 | seq.type = TIPC_CFG_SRV; | 479 | seq.type = TIPC_CFG_SRV; |
483 | seq.lower = seq.upper = tipc_own_addr; | 480 | seq.lower = seq.upper = tipc_own_addr; |
484 | res = tipc_nametbl_publish_rsv(config_port_ref, TIPC_ZONE_SCOPE, &seq); | 481 | res = tipc_publish(config_port_ref, TIPC_ZONE_SCOPE, &seq); |
485 | if (res) | 482 | if (res) |
486 | goto failed; | 483 | goto failed; |
487 | 484 | ||
diff --git a/net/tipc/core.c b/net/tipc/core.c index 2691cd57b8a8..68eba03e7955 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -53,7 +53,6 @@ | |||
53 | 53 | ||
54 | /* global variables used by multiple sub-systems within TIPC */ | 54 | /* global variables used by multiple sub-systems within TIPC */ |
55 | 55 | ||
56 | int tipc_mode = TIPC_NOT_RUNNING; | ||
57 | int tipc_random; | 56 | int tipc_random; |
58 | 57 | ||
59 | const char tipc_alphabet[] = | 58 | const char tipc_alphabet[] = |
@@ -125,11 +124,6 @@ int tipc_core_start_net(unsigned long addr) | |||
125 | 124 | ||
126 | static void tipc_core_stop(void) | 125 | static void tipc_core_stop(void) |
127 | { | 126 | { |
128 | if (tipc_mode != TIPC_NODE_MODE) | ||
129 | return; | ||
130 | |||
131 | tipc_mode = TIPC_NOT_RUNNING; | ||
132 | |||
133 | tipc_netlink_stop(); | 127 | tipc_netlink_stop(); |
134 | tipc_handler_stop(); | 128 | tipc_handler_stop(); |
135 | tipc_cfg_stop(); | 129 | tipc_cfg_stop(); |
@@ -148,11 +142,7 @@ static int tipc_core_start(void) | |||
148 | { | 142 | { |
149 | int res; | 143 | int res; |
150 | 144 | ||
151 | if (tipc_mode != TIPC_NOT_RUNNING) | ||
152 | return -ENOPROTOOPT; | ||
153 | |||
154 | get_random_bytes(&tipc_random, sizeof(tipc_random)); | 145 | get_random_bytes(&tipc_random, sizeof(tipc_random)); |
155 | tipc_mode = TIPC_NODE_MODE; | ||
156 | 146 | ||
157 | res = tipc_handler_start(); | 147 | res = tipc_handler_start(); |
158 | if (!res) | 148 | if (!res) |
diff --git a/net/tipc/core.h b/net/tipc/core.h index 2761af36d141..13837e0e56b1 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -130,13 +130,6 @@ void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *); | |||
130 | #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ | 130 | #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * TIPC operating mode routines | ||
134 | */ | ||
135 | #define TIPC_NOT_RUNNING 0 | ||
136 | #define TIPC_NODE_MODE 1 | ||
137 | #define TIPC_NET_MODE 2 | ||
138 | |||
139 | /* | ||
140 | * Global configuration variables | 133 | * Global configuration variables |
141 | */ | 134 | */ |
142 | 135 | ||
@@ -151,7 +144,6 @@ extern int tipc_remote_management; | |||
151 | * Other global variables | 144 | * Other global variables |
152 | */ | 145 | */ |
153 | 146 | ||
154 | extern int tipc_mode; | ||
155 | extern int tipc_random; | 147 | extern int tipc_random; |
156 | extern const char tipc_alphabet[]; | 148 | extern const char tipc_alphabet[]; |
157 | 149 | ||
@@ -168,16 +160,6 @@ extern void tipc_netlink_stop(void); | |||
168 | extern int tipc_socket_init(void); | 160 | extern int tipc_socket_init(void); |
169 | extern void tipc_socket_stop(void); | 161 | extern void tipc_socket_stop(void); |
170 | 162 | ||
171 | static inline int delimit(int val, int min, int max) | ||
172 | { | ||
173 | if (val > max) | ||
174 | return max; | ||
175 | if (val < min) | ||
176 | return min; | ||
177 | return val; | ||
178 | } | ||
179 | |||
180 | |||
181 | /* | 163 | /* |
182 | * TIPC timer and signal code | 164 | * TIPC timer and signal code |
183 | */ | 165 | */ |
@@ -279,28 +261,4 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb) | |||
279 | 261 | ||
280 | extern struct sk_buff *tipc_buf_acquire(u32 size); | 262 | extern struct sk_buff *tipc_buf_acquire(u32 size); |
281 | 263 | ||
282 | /** | ||
283 | * buf_discard - frees a TIPC message buffer | ||
284 | * @skb: message buffer | ||
285 | * | ||
286 | * Frees a message buffer. If passed NULL, just returns. | ||
287 | */ | ||
288 | |||
289 | static inline void buf_discard(struct sk_buff *skb) | ||
290 | { | ||
291 | kfree_skb(skb); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * buf_linearize - convert a TIPC message buffer into a single contiguous piece | ||
296 | * @skb: message buffer | ||
297 | * | ||
298 | * Returns 0 on success. | ||
299 | */ | ||
300 | |||
301 | static inline int buf_linearize(struct sk_buff *skb) | ||
302 | { | ||
303 | return skb_linearize(skb); | ||
304 | } | ||
305 | |||
306 | #endif | 264 | #endif |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index a00e5f811569..c630a21b2bed 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -82,6 +82,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, | |||
82 | msg = buf_msg(buf); | 82 | msg = buf_msg(buf); |
83 | tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); | 83 | tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); |
84 | msg_set_non_seq(msg, 1); | 84 | msg_set_non_seq(msg, 1); |
85 | msg_set_node_sig(msg, tipc_random); | ||
85 | msg_set_dest_domain(msg, dest_domain); | 86 | msg_set_dest_domain(msg, dest_domain); |
86 | msg_set_bc_netid(msg, tipc_net_id); | 87 | msg_set_bc_netid(msg, tipc_net_id); |
87 | b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg)); | 88 | b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg)); |
@@ -121,20 +122,22 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
121 | { | 122 | { |
122 | struct tipc_node *n_ptr; | 123 | struct tipc_node *n_ptr; |
123 | struct tipc_link *link; | 124 | struct tipc_link *link; |
124 | struct tipc_media_addr media_addr, *addr; | 125 | struct tipc_media_addr media_addr; |
125 | struct sk_buff *rbuf; | 126 | struct sk_buff *rbuf; |
126 | struct tipc_msg *msg = buf_msg(buf); | 127 | struct tipc_msg *msg = buf_msg(buf); |
127 | u32 dest = msg_dest_domain(msg); | 128 | u32 dest = msg_dest_domain(msg); |
128 | u32 orig = msg_prevnode(msg); | 129 | u32 orig = msg_prevnode(msg); |
129 | u32 net_id = msg_bc_netid(msg); | 130 | u32 net_id = msg_bc_netid(msg); |
130 | u32 type = msg_type(msg); | 131 | u32 type = msg_type(msg); |
132 | u32 signature = msg_node_sig(msg); | ||
133 | int addr_mismatch; | ||
131 | int link_fully_up; | 134 | int link_fully_up; |
132 | 135 | ||
133 | media_addr.broadcast = 1; | 136 | media_addr.broadcast = 1; |
134 | b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg)); | 137 | b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg)); |
135 | buf_discard(buf); | 138 | kfree_skb(buf); |
136 | 139 | ||
137 | /* Validate discovery message from requesting node */ | 140 | /* Ensure message from node is valid and communication is permitted */ |
138 | if (net_id != tipc_net_id) | 141 | if (net_id != tipc_net_id) |
139 | return; | 142 | return; |
140 | if (media_addr.broadcast) | 143 | if (media_addr.broadcast) |
@@ -162,15 +165,50 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
162 | } | 165 | } |
163 | tipc_node_lock(n_ptr); | 166 | tipc_node_lock(n_ptr); |
164 | 167 | ||
168 | /* Prepare to validate requesting node's signature and media address */ | ||
165 | link = n_ptr->links[b_ptr->identity]; | 169 | link = n_ptr->links[b_ptr->identity]; |
170 | addr_mismatch = (link != NULL) && | ||
171 | memcmp(&link->media_addr, &media_addr, sizeof(media_addr)); | ||
166 | 172 | ||
167 | /* Create a link endpoint for this bearer, if necessary */ | 173 | /* |
168 | if (!link) { | 174 | * Ensure discovery message's signature is correct |
169 | link = tipc_link_create(n_ptr, b_ptr, &media_addr); | 175 | * |
170 | if (!link) { | 176 | * If signature is incorrect and there is no working link to the node, |
177 | * accept the new signature but invalidate all existing links to the | ||
178 | * node so they won't re-activate without a new discovery message. | ||
179 | * | ||
180 | * If signature is incorrect and the requested link to the node is | ||
181 | * working, accept the new signature. (This is an instance of delayed | ||
182 | * rediscovery, where a link endpoint was able to re-establish contact | ||
183 | * with its peer endpoint on a node that rebooted before receiving a | ||
184 | * discovery message from that node.) | ||
185 | * | ||
186 | * If signature is incorrect and there is a working link to the node | ||
187 | * that is not the requested link, reject the request (must be from | ||
188 | * a duplicate node). | ||
189 | */ | ||
190 | if (signature != n_ptr->signature) { | ||
191 | if (n_ptr->working_links == 0) { | ||
192 | struct tipc_link *curr_link; | ||
193 | int i; | ||
194 | |||
195 | for (i = 0; i < MAX_BEARERS; i++) { | ||
196 | curr_link = n_ptr->links[i]; | ||
197 | if (curr_link) { | ||
198 | memset(&curr_link->media_addr, 0, | ||
199 | sizeof(media_addr)); | ||
200 | tipc_link_reset(curr_link); | ||
201 | } | ||
202 | } | ||
203 | addr_mismatch = (link != NULL); | ||
204 | } else if (tipc_link_is_up(link) && !addr_mismatch) { | ||
205 | /* delayed rediscovery */ | ||
206 | } else { | ||
207 | disc_dupl_alert(b_ptr, orig, &media_addr); | ||
171 | tipc_node_unlock(n_ptr); | 208 | tipc_node_unlock(n_ptr); |
172 | return; | 209 | return; |
173 | } | 210 | } |
211 | n_ptr->signature = signature; | ||
174 | } | 212 | } |
175 | 213 | ||
176 | /* | 214 | /* |
@@ -183,17 +221,26 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
183 | * the new media address and reset the link to ensure it starts up | 221 | * the new media address and reset the link to ensure it starts up |
184 | * cleanly. | 222 | * cleanly. |
185 | */ | 223 | */ |
186 | addr = &link->media_addr; | 224 | |
187 | if (memcmp(addr, &media_addr, sizeof(*addr))) { | 225 | if (addr_mismatch) { |
188 | if (tipc_link_is_up(link) || (!link->started)) { | 226 | if (tipc_link_is_up(link)) { |
189 | disc_dupl_alert(b_ptr, orig, &media_addr); | 227 | disc_dupl_alert(b_ptr, orig, &media_addr); |
190 | tipc_node_unlock(n_ptr); | 228 | tipc_node_unlock(n_ptr); |
191 | return; | 229 | return; |
230 | } else { | ||
231 | memcpy(&link->media_addr, &media_addr, | ||
232 | sizeof(media_addr)); | ||
233 | tipc_link_reset(link); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | /* Create a link endpoint for this bearer, if necessary */ | ||
238 | if (!link) { | ||
239 | link = tipc_link_create(n_ptr, b_ptr, &media_addr); | ||
240 | if (!link) { | ||
241 | tipc_node_unlock(n_ptr); | ||
242 | return; | ||
192 | } | 243 | } |
193 | warn("Resetting link <%s>, peer interface address changed\n", | ||
194 | link->name); | ||
195 | memcpy(addr, &media_addr, sizeof(*addr)); | ||
196 | tipc_link_reset(link); | ||
197 | } | 244 | } |
198 | 245 | ||
199 | /* Accept discovery message & send response, if necessary */ | 246 | /* Accept discovery message & send response, if necessary */ |
@@ -203,7 +250,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
203 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); | 250 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); |
204 | if (rbuf) { | 251 | if (rbuf) { |
205 | b_ptr->media->send_msg(rbuf, b_ptr, &media_addr); | 252 | b_ptr->media->send_msg(rbuf, b_ptr, &media_addr); |
206 | buf_discard(rbuf); | 253 | kfree_skb(rbuf); |
207 | } | 254 | } |
208 | } | 255 | } |
209 | 256 | ||
@@ -349,7 +396,7 @@ void tipc_disc_delete(struct tipc_link_req *req) | |||
349 | { | 396 | { |
350 | k_cancel_timer(&req->timer); | 397 | k_cancel_timer(&req->timer); |
351 | k_term_timer(&req->timer); | 398 | k_term_timer(&req->timer); |
352 | buf_discard(req->buf); | 399 | kfree_skb(req->buf); |
353 | kfree(req); | 400 | kfree(req); |
354 | } | 401 | } |
355 | 402 | ||
diff --git a/net/tipc/link.c b/net/tipc/link.c index ac1832a66f8a..b4b9b30167a3 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -484,7 +484,7 @@ static void link_release_outqueue(struct tipc_link *l_ptr) | |||
484 | 484 | ||
485 | while (buf) { | 485 | while (buf) { |
486 | next = buf->next; | 486 | next = buf->next; |
487 | buf_discard(buf); | 487 | kfree_skb(buf); |
488 | buf = next; | 488 | buf = next; |
489 | } | 489 | } |
490 | l_ptr->first_out = NULL; | 490 | l_ptr->first_out = NULL; |
@@ -503,7 +503,7 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr) | |||
503 | 503 | ||
504 | while (buf) { | 504 | while (buf) { |
505 | next = buf->next; | 505 | next = buf->next; |
506 | buf_discard(buf); | 506 | kfree_skb(buf); |
507 | buf = next; | 507 | buf = next; |
508 | } | 508 | } |
509 | l_ptr->defragm_buf = NULL; | 509 | l_ptr->defragm_buf = NULL; |
@@ -522,20 +522,20 @@ void tipc_link_stop(struct tipc_link *l_ptr) | |||
522 | buf = l_ptr->oldest_deferred_in; | 522 | buf = l_ptr->oldest_deferred_in; |
523 | while (buf) { | 523 | while (buf) { |
524 | next = buf->next; | 524 | next = buf->next; |
525 | buf_discard(buf); | 525 | kfree_skb(buf); |
526 | buf = next; | 526 | buf = next; |
527 | } | 527 | } |
528 | 528 | ||
529 | buf = l_ptr->first_out; | 529 | buf = l_ptr->first_out; |
530 | while (buf) { | 530 | while (buf) { |
531 | next = buf->next; | 531 | next = buf->next; |
532 | buf_discard(buf); | 532 | kfree_skb(buf); |
533 | buf = next; | 533 | buf = next; |
534 | } | 534 | } |
535 | 535 | ||
536 | tipc_link_reset_fragments(l_ptr); | 536 | tipc_link_reset_fragments(l_ptr); |
537 | 537 | ||
538 | buf_discard(l_ptr->proto_msg_queue); | 538 | kfree_skb(l_ptr->proto_msg_queue); |
539 | l_ptr->proto_msg_queue = NULL; | 539 | l_ptr->proto_msg_queue = NULL; |
540 | } | 540 | } |
541 | 541 | ||
@@ -571,12 +571,12 @@ void tipc_link_reset(struct tipc_link *l_ptr) | |||
571 | /* Clean up all queues: */ | 571 | /* Clean up all queues: */ |
572 | 572 | ||
573 | link_release_outqueue(l_ptr); | 573 | link_release_outqueue(l_ptr); |
574 | buf_discard(l_ptr->proto_msg_queue); | 574 | kfree_skb(l_ptr->proto_msg_queue); |
575 | l_ptr->proto_msg_queue = NULL; | 575 | l_ptr->proto_msg_queue = NULL; |
576 | buf = l_ptr->oldest_deferred_in; | 576 | buf = l_ptr->oldest_deferred_in; |
577 | while (buf) { | 577 | while (buf) { |
578 | struct sk_buff *next = buf->next; | 578 | struct sk_buff *next = buf->next; |
579 | buf_discard(buf); | 579 | kfree_skb(buf); |
580 | buf = next; | 580 | buf = next; |
581 | } | 581 | } |
582 | if (!list_empty(&l_ptr->waiting_ports)) | 582 | if (!list_empty(&l_ptr->waiting_ports)) |
@@ -810,7 +810,7 @@ static int link_bundle_buf(struct tipc_link *l_ptr, | |||
810 | skb_copy_to_linear_data_offset(bundler, to_pos, buf->data, size); | 810 | skb_copy_to_linear_data_offset(bundler, to_pos, buf->data, size); |
811 | msg_set_size(bundler_msg, to_pos + size); | 811 | msg_set_size(bundler_msg, to_pos + size); |
812 | msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); | 812 | msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); |
813 | buf_discard(buf); | 813 | kfree_skb(buf); |
814 | l_ptr->stats.sent_bundled++; | 814 | l_ptr->stats.sent_bundled++; |
815 | return 1; | 815 | return 1; |
816 | } | 816 | } |
@@ -871,17 +871,15 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
871 | u32 queue_limit = l_ptr->queue_limit[imp]; | 871 | u32 queue_limit = l_ptr->queue_limit[imp]; |
872 | u32 max_packet = l_ptr->max_pkt; | 872 | u32 max_packet = l_ptr->max_pkt; |
873 | 873 | ||
874 | msg_set_prevnode(msg, tipc_own_addr); /* If routed message */ | ||
875 | |||
876 | /* Match msg importance against queue limits: */ | 874 | /* Match msg importance against queue limits: */ |
877 | 875 | ||
878 | if (unlikely(queue_size >= queue_limit)) { | 876 | if (unlikely(queue_size >= queue_limit)) { |
879 | if (imp <= TIPC_CRITICAL_IMPORTANCE) { | 877 | if (imp <= TIPC_CRITICAL_IMPORTANCE) { |
880 | link_schedule_port(l_ptr, msg_origport(msg), size); | 878 | link_schedule_port(l_ptr, msg_origport(msg), size); |
881 | buf_discard(buf); | 879 | kfree_skb(buf); |
882 | return -ELINKCONG; | 880 | return -ELINKCONG; |
883 | } | 881 | } |
884 | buf_discard(buf); | 882 | kfree_skb(buf); |
885 | if (imp > CONN_MANAGER) { | 883 | if (imp > CONN_MANAGER) { |
886 | warn("Resetting link <%s>, send queue full", l_ptr->name); | 884 | warn("Resetting link <%s>, send queue full", l_ptr->name); |
887 | tipc_link_reset(l_ptr); | 885 | tipc_link_reset(l_ptr); |
@@ -968,10 +966,10 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) | |||
968 | if (l_ptr) | 966 | if (l_ptr) |
969 | res = tipc_link_send_buf(l_ptr, buf); | 967 | res = tipc_link_send_buf(l_ptr, buf); |
970 | else | 968 | else |
971 | buf_discard(buf); | 969 | kfree_skb(buf); |
972 | tipc_node_unlock(n_ptr); | 970 | tipc_node_unlock(n_ptr); |
973 | } else { | 971 | } else { |
974 | buf_discard(buf); | 972 | kfree_skb(buf); |
975 | } | 973 | } |
976 | read_unlock_bh(&tipc_net_lock); | 974 | read_unlock_bh(&tipc_net_lock); |
977 | return res; | 975 | return res; |
@@ -1018,7 +1016,7 @@ void tipc_link_send_names(struct list_head *message_list, u32 dest) | |||
1018 | 1016 | ||
1019 | list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { | 1017 | list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { |
1020 | list_del((struct list_head *)buf); | 1018 | list_del((struct list_head *)buf); |
1021 | buf_discard(buf); | 1019 | kfree_skb(buf); |
1022 | } | 1020 | } |
1023 | } | 1021 | } |
1024 | 1022 | ||
@@ -1262,7 +1260,7 @@ again: | |||
1262 | error: | 1260 | error: |
1263 | for (; buf_chain; buf_chain = buf) { | 1261 | for (; buf_chain; buf_chain = buf) { |
1264 | buf = buf_chain->next; | 1262 | buf = buf_chain->next; |
1265 | buf_discard(buf_chain); | 1263 | kfree_skb(buf_chain); |
1266 | } | 1264 | } |
1267 | return -EFAULT; | 1265 | return -EFAULT; |
1268 | } | 1266 | } |
@@ -1316,7 +1314,7 @@ error: | |||
1316 | tipc_node_unlock(node); | 1314 | tipc_node_unlock(node); |
1317 | for (; buf_chain; buf_chain = buf) { | 1315 | for (; buf_chain; buf_chain = buf) { |
1318 | buf = buf_chain->next; | 1316 | buf = buf_chain->next; |
1319 | buf_discard(buf_chain); | 1317 | kfree_skb(buf_chain); |
1320 | } | 1318 | } |
1321 | goto again; | 1319 | goto again; |
1322 | } | 1320 | } |
@@ -1324,7 +1322,7 @@ error: | |||
1324 | reject: | 1322 | reject: |
1325 | for (; buf_chain; buf_chain = buf) { | 1323 | for (; buf_chain; buf_chain = buf) { |
1326 | buf = buf_chain->next; | 1324 | buf = buf_chain->next; |
1327 | buf_discard(buf_chain); | 1325 | kfree_skb(buf_chain); |
1328 | } | 1326 | } |
1329 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, | 1327 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, |
1330 | total_len, TIPC_ERR_NO_NODE); | 1328 | total_len, TIPC_ERR_NO_NODE); |
@@ -1390,7 +1388,7 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr) | |||
1390 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); | 1388 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); |
1391 | if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | 1389 | if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { |
1392 | l_ptr->unacked_window = 0; | 1390 | l_ptr->unacked_window = 0; |
1393 | buf_discard(buf); | 1391 | kfree_skb(buf); |
1394 | l_ptr->proto_msg_queue = NULL; | 1392 | l_ptr->proto_msg_queue = NULL; |
1395 | return 0; | 1393 | return 0; |
1396 | } else { | 1394 | } else { |
@@ -1501,13 +1499,13 @@ static void link_retransmit_failure(struct tipc_link *l_ptr, | |||
1501 | tipc_node_lock(n_ptr); | 1499 | tipc_node_lock(n_ptr); |
1502 | 1500 | ||
1503 | tipc_addr_string_fill(addr_string, n_ptr->addr); | 1501 | tipc_addr_string_fill(addr_string, n_ptr->addr); |
1504 | info("Multicast link info for %s\n", addr_string); | 1502 | info("Broadcast link info for %s\n", addr_string); |
1503 | info("Supportable: %d, ", n_ptr->bclink.supportable); | ||
1505 | info("Supported: %d, ", n_ptr->bclink.supported); | 1504 | info("Supported: %d, ", n_ptr->bclink.supported); |
1506 | info("Acked: %u\n", n_ptr->bclink.acked); | 1505 | info("Acked: %u\n", n_ptr->bclink.acked); |
1507 | info("Last in: %u, ", n_ptr->bclink.last_in); | 1506 | info("Last in: %u, ", n_ptr->bclink.last_in); |
1508 | info("Gap after: %u, ", n_ptr->bclink.gap_after); | 1507 | info("Oos state: %u, ", n_ptr->bclink.oos_state); |
1509 | info("Gap to: %u\n", n_ptr->bclink.gap_to); | 1508 | info("Last sent: %u\n", n_ptr->bclink.last_sent); |
1510 | info("Nack sync: %u\n\n", n_ptr->bclink.nack_sync); | ||
1511 | 1509 | ||
1512 | tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); | 1510 | tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); |
1513 | 1511 | ||
@@ -1679,7 +1677,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1679 | 1677 | ||
1680 | /* Ensure message data is a single contiguous unit */ | 1678 | /* Ensure message data is a single contiguous unit */ |
1681 | 1679 | ||
1682 | if (unlikely(buf_linearize(buf))) | 1680 | if (unlikely(skb_linearize(buf))) |
1683 | goto cont; | 1681 | goto cont; |
1684 | 1682 | ||
1685 | /* Handle arrival of a non-unicast link message */ | 1683 | /* Handle arrival of a non-unicast link message */ |
@@ -1736,7 +1734,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1736 | 1734 | ||
1737 | /* Release acked messages */ | 1735 | /* Release acked messages */ |
1738 | 1736 | ||
1739 | if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported) | 1737 | if (n_ptr->bclink.supported) |
1740 | tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); | 1738 | tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); |
1741 | 1739 | ||
1742 | crs = l_ptr->first_out; | 1740 | crs = l_ptr->first_out; |
@@ -1744,7 +1742,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1744 | less_eq(buf_seqno(crs), ackd)) { | 1742 | less_eq(buf_seqno(crs), ackd)) { |
1745 | struct sk_buff *next = crs->next; | 1743 | struct sk_buff *next = crs->next; |
1746 | 1744 | ||
1747 | buf_discard(crs); | 1745 | kfree_skb(crs); |
1748 | crs = next; | 1746 | crs = next; |
1749 | released++; | 1747 | released++; |
1750 | } | 1748 | } |
@@ -1773,52 +1771,56 @@ protocol_check: | |||
1773 | if (unlikely(l_ptr->oldest_deferred_in)) | 1771 | if (unlikely(l_ptr->oldest_deferred_in)) |
1774 | head = link_insert_deferred_queue(l_ptr, | 1772 | head = link_insert_deferred_queue(l_ptr, |
1775 | head); | 1773 | head); |
1776 | if (likely(msg_is_dest(msg, tipc_own_addr))) { | ||
1777 | deliver: | 1774 | deliver: |
1778 | if (likely(msg_isdata(msg))) { | 1775 | if (likely(msg_isdata(msg))) { |
1779 | tipc_node_unlock(n_ptr); | 1776 | tipc_node_unlock(n_ptr); |
1780 | tipc_port_recv_msg(buf); | 1777 | tipc_port_recv_msg(buf); |
1781 | continue; | 1778 | continue; |
1779 | } | ||
1780 | switch (msg_user(msg)) { | ||
1781 | int ret; | ||
1782 | case MSG_BUNDLER: | ||
1783 | l_ptr->stats.recv_bundles++; | ||
1784 | l_ptr->stats.recv_bundled += | ||
1785 | msg_msgcnt(msg); | ||
1786 | tipc_node_unlock(n_ptr); | ||
1787 | tipc_link_recv_bundle(buf); | ||
1788 | continue; | ||
1789 | case NAME_DISTRIBUTOR: | ||
1790 | tipc_node_unlock(n_ptr); | ||
1791 | tipc_named_recv(buf); | ||
1792 | continue; | ||
1793 | case CONN_MANAGER: | ||
1794 | tipc_node_unlock(n_ptr); | ||
1795 | tipc_port_recv_proto_msg(buf); | ||
1796 | continue; | ||
1797 | case MSG_FRAGMENTER: | ||
1798 | l_ptr->stats.recv_fragments++; | ||
1799 | ret = tipc_link_recv_fragment( | ||
1800 | &l_ptr->defragm_buf, | ||
1801 | &buf, &msg); | ||
1802 | if (ret == 1) { | ||
1803 | l_ptr->stats.recv_fragmented++; | ||
1804 | goto deliver; | ||
1782 | } | 1805 | } |
1783 | switch (msg_user(msg)) { | 1806 | if (ret == -1) |
1784 | case MSG_BUNDLER: | 1807 | l_ptr->next_in_no--; |
1785 | l_ptr->stats.recv_bundles++; | 1808 | break; |
1786 | l_ptr->stats.recv_bundled += | 1809 | case CHANGEOVER_PROTOCOL: |
1787 | msg_msgcnt(msg); | 1810 | type = msg_type(msg); |
1788 | tipc_node_unlock(n_ptr); | 1811 | if (link_recv_changeover_msg(&l_ptr, |
1789 | tipc_link_recv_bundle(buf); | 1812 | &buf)) { |
1790 | continue; | 1813 | msg = buf_msg(buf); |
1791 | case NAME_DISTRIBUTOR: | 1814 | seq_no = msg_seqno(msg); |
1792 | tipc_node_unlock(n_ptr); | 1815 | if (type == ORIGINAL_MSG) |
1793 | tipc_named_recv(buf); | ||
1794 | continue; | ||
1795 | case CONN_MANAGER: | ||
1796 | tipc_node_unlock(n_ptr); | ||
1797 | tipc_port_recv_proto_msg(buf); | ||
1798 | continue; | ||
1799 | case MSG_FRAGMENTER: | ||
1800 | l_ptr->stats.recv_fragments++; | ||
1801 | if (tipc_link_recv_fragment(&l_ptr->defragm_buf, | ||
1802 | &buf, &msg)) { | ||
1803 | l_ptr->stats.recv_fragmented++; | ||
1804 | goto deliver; | 1816 | goto deliver; |
1805 | } | 1817 | goto protocol_check; |
1806 | break; | ||
1807 | case CHANGEOVER_PROTOCOL: | ||
1808 | type = msg_type(msg); | ||
1809 | if (link_recv_changeover_msg(&l_ptr, &buf)) { | ||
1810 | msg = buf_msg(buf); | ||
1811 | seq_no = msg_seqno(msg); | ||
1812 | if (type == ORIGINAL_MSG) | ||
1813 | goto deliver; | ||
1814 | goto protocol_check; | ||
1815 | } | ||
1816 | break; | ||
1817 | default: | ||
1818 | buf_discard(buf); | ||
1819 | buf = NULL; | ||
1820 | break; | ||
1821 | } | 1818 | } |
1819 | break; | ||
1820 | default: | ||
1821 | kfree_skb(buf); | ||
1822 | buf = NULL; | ||
1823 | break; | ||
1822 | } | 1824 | } |
1823 | tipc_node_unlock(n_ptr); | 1825 | tipc_node_unlock(n_ptr); |
1824 | tipc_net_route_msg(buf); | 1826 | tipc_net_route_msg(buf); |
@@ -1847,23 +1849,22 @@ deliver: | |||
1847 | } | 1849 | } |
1848 | tipc_node_unlock(n_ptr); | 1850 | tipc_node_unlock(n_ptr); |
1849 | cont: | 1851 | cont: |
1850 | buf_discard(buf); | 1852 | kfree_skb(buf); |
1851 | } | 1853 | } |
1852 | read_unlock_bh(&tipc_net_lock); | 1854 | read_unlock_bh(&tipc_net_lock); |
1853 | } | 1855 | } |
1854 | 1856 | ||
1855 | /* | 1857 | /* |
1856 | * link_defer_buf(): Sort a received out-of-sequence packet | 1858 | * tipc_link_defer_pkt - Add out-of-sequence message to deferred reception queue |
1857 | * into the deferred reception queue. | 1859 | * |
1858 | * Returns the increase of the queue length,i.e. 0 or 1 | 1860 | * Returns increase in queue length (i.e. 0 or 1) |
1859 | */ | 1861 | */ |
1860 | 1862 | ||
1861 | u32 tipc_link_defer_pkt(struct sk_buff **head, | 1863 | u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, |
1862 | struct sk_buff **tail, | ||
1863 | struct sk_buff *buf) | 1864 | struct sk_buff *buf) |
1864 | { | 1865 | { |
1865 | struct sk_buff *prev = NULL; | 1866 | struct sk_buff *queue_buf; |
1866 | struct sk_buff *crs = *head; | 1867 | struct sk_buff **prev; |
1867 | u32 seq_no = buf_seqno(buf); | 1868 | u32 seq_no = buf_seqno(buf); |
1868 | 1869 | ||
1869 | buf->next = NULL; | 1870 | buf->next = NULL; |
@@ -1881,31 +1882,30 @@ u32 tipc_link_defer_pkt(struct sk_buff **head, | |||
1881 | return 1; | 1882 | return 1; |
1882 | } | 1883 | } |
1883 | 1884 | ||
1884 | /* Scan through queue and sort it in */ | 1885 | /* Locate insertion point in queue, then insert; discard if duplicate */ |
1885 | do { | 1886 | prev = head; |
1886 | struct tipc_msg *msg = buf_msg(crs); | 1887 | queue_buf = *head; |
1888 | for (;;) { | ||
1889 | u32 curr_seqno = buf_seqno(queue_buf); | ||
1887 | 1890 | ||
1888 | if (less(seq_no, msg_seqno(msg))) { | 1891 | if (seq_no == curr_seqno) { |
1889 | buf->next = crs; | 1892 | kfree_skb(buf); |
1890 | if (prev) | 1893 | return 0; |
1891 | prev->next = buf; | ||
1892 | else | ||
1893 | *head = buf; | ||
1894 | return 1; | ||
1895 | } | 1894 | } |
1896 | if (seq_no == msg_seqno(msg)) | 1895 | |
1896 | if (less(seq_no, curr_seqno)) | ||
1897 | break; | 1897 | break; |
1898 | prev = crs; | ||
1899 | crs = crs->next; | ||
1900 | } while (crs); | ||
1901 | 1898 | ||
1902 | /* Message is a duplicate of an existing message */ | 1899 | prev = &queue_buf->next; |
1900 | queue_buf = queue_buf->next; | ||
1901 | } | ||
1903 | 1902 | ||
1904 | buf_discard(buf); | 1903 | buf->next = queue_buf; |
1905 | return 0; | 1904 | *prev = buf; |
1905 | return 1; | ||
1906 | } | 1906 | } |
1907 | 1907 | ||
1908 | /** | 1908 | /* |
1909 | * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet | 1909 | * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet |
1910 | */ | 1910 | */ |
1911 | 1911 | ||
@@ -1930,7 +1930,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | |||
1930 | 1930 | ||
1931 | if (less(seq_no, mod(l_ptr->next_in_no))) { | 1931 | if (less(seq_no, mod(l_ptr->next_in_no))) { |
1932 | l_ptr->stats.duplicates++; | 1932 | l_ptr->stats.duplicates++; |
1933 | buf_discard(buf); | 1933 | kfree_skb(buf); |
1934 | return; | 1934 | return; |
1935 | } | 1935 | } |
1936 | 1936 | ||
@@ -1956,6 +1956,13 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, | |||
1956 | u32 msg_size = sizeof(l_ptr->proto_msg); | 1956 | u32 msg_size = sizeof(l_ptr->proto_msg); |
1957 | int r_flag; | 1957 | int r_flag; |
1958 | 1958 | ||
1959 | /* Discard any previous message that was deferred due to congestion */ | ||
1960 | |||
1961 | if (l_ptr->proto_msg_queue) { | ||
1962 | kfree_skb(l_ptr->proto_msg_queue); | ||
1963 | l_ptr->proto_msg_queue = NULL; | ||
1964 | } | ||
1965 | |||
1959 | if (link_blocked(l_ptr)) | 1966 | if (link_blocked(l_ptr)) |
1960 | return; | 1967 | return; |
1961 | 1968 | ||
@@ -1964,9 +1971,11 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, | |||
1964 | if ((l_ptr->owner->block_setup) && (msg_typ != RESET_MSG)) | 1971 | if ((l_ptr->owner->block_setup) && (msg_typ != RESET_MSG)) |
1965 | return; | 1972 | return; |
1966 | 1973 | ||
1974 | /* Create protocol message with "out-of-sequence" sequence number */ | ||
1975 | |||
1967 | msg_set_type(msg, msg_typ); | 1976 | msg_set_type(msg, msg_typ); |
1968 | msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); | 1977 | msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); |
1969 | msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); | 1978 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); |
1970 | msg_set_last_bcast(msg, tipc_bclink_get_last_sent()); | 1979 | msg_set_last_bcast(msg, tipc_bclink_get_last_sent()); |
1971 | 1980 | ||
1972 | if (msg_typ == STATE_MSG) { | 1981 | if (msg_typ == STATE_MSG) { |
@@ -2020,44 +2029,36 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, | |||
2020 | r_flag = (l_ptr->owner->working_links > tipc_link_is_up(l_ptr)); | 2029 | r_flag = (l_ptr->owner->working_links > tipc_link_is_up(l_ptr)); |
2021 | msg_set_redundant_link(msg, r_flag); | 2030 | msg_set_redundant_link(msg, r_flag); |
2022 | msg_set_linkprio(msg, l_ptr->priority); | 2031 | msg_set_linkprio(msg, l_ptr->priority); |
2023 | 2032 | msg_set_size(msg, msg_size); | |
2024 | /* Ensure sequence number will not fit : */ | ||
2025 | 2033 | ||
2026 | msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2))); | 2034 | msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2))); |
2027 | 2035 | ||
2028 | /* Congestion? */ | ||
2029 | |||
2030 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { | ||
2031 | if (!l_ptr->proto_msg_queue) { | ||
2032 | l_ptr->proto_msg_queue = | ||
2033 | tipc_buf_acquire(sizeof(l_ptr->proto_msg)); | ||
2034 | } | ||
2035 | buf = l_ptr->proto_msg_queue; | ||
2036 | if (!buf) | ||
2037 | return; | ||
2038 | skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); | ||
2039 | return; | ||
2040 | } | ||
2041 | |||
2042 | /* Message can be sent */ | ||
2043 | |||
2044 | buf = tipc_buf_acquire(msg_size); | 2036 | buf = tipc_buf_acquire(msg_size); |
2045 | if (!buf) | 2037 | if (!buf) |
2046 | return; | 2038 | return; |
2047 | 2039 | ||
2048 | skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); | 2040 | skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); |
2049 | msg_set_size(buf_msg(buf), msg_size); | ||
2050 | 2041 | ||
2051 | if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | 2042 | /* Defer message if bearer is already congested */ |
2052 | l_ptr->unacked_window = 0; | 2043 | |
2053 | buf_discard(buf); | 2044 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { |
2045 | l_ptr->proto_msg_queue = buf; | ||
2054 | return; | 2046 | return; |
2055 | } | 2047 | } |
2056 | 2048 | ||
2057 | /* New congestion */ | 2049 | /* Defer message if attempting to send results in bearer congestion */ |
2058 | tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); | 2050 | |
2059 | l_ptr->proto_msg_queue = buf; | 2051 | if (!tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { |
2060 | l_ptr->stats.bearer_congs++; | 2052 | tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); |
2053 | l_ptr->proto_msg_queue = buf; | ||
2054 | l_ptr->stats.bearer_congs++; | ||
2055 | return; | ||
2056 | } | ||
2057 | |||
2058 | /* Discard message if it was sent successfully */ | ||
2059 | |||
2060 | l_ptr->unacked_window = 0; | ||
2061 | kfree_skb(buf); | ||
2061 | } | 2062 | } |
2062 | 2063 | ||
2063 | /* | 2064 | /* |
@@ -2105,6 +2106,8 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
2105 | l_ptr->owner->block_setup = WAIT_NODE_DOWN; | 2106 | l_ptr->owner->block_setup = WAIT_NODE_DOWN; |
2106 | } | 2107 | } |
2107 | 2108 | ||
2109 | link_state_event(l_ptr, RESET_MSG); | ||
2110 | |||
2108 | /* fall thru' */ | 2111 | /* fall thru' */ |
2109 | case ACTIVATE_MSG: | 2112 | case ACTIVATE_MSG: |
2110 | /* Update link settings according other endpoint's values */ | 2113 | /* Update link settings according other endpoint's values */ |
@@ -2127,16 +2130,22 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
2127 | } else { | 2130 | } else { |
2128 | l_ptr->max_pkt = l_ptr->max_pkt_target; | 2131 | l_ptr->max_pkt = l_ptr->max_pkt_target; |
2129 | } | 2132 | } |
2130 | l_ptr->owner->bclink.supported = (max_pkt_info != 0); | 2133 | l_ptr->owner->bclink.supportable = (max_pkt_info != 0); |
2131 | 2134 | ||
2132 | link_state_event(l_ptr, msg_type(msg)); | 2135 | /* Synchronize broadcast link info, if not done previously */ |
2136 | |||
2137 | if (!tipc_node_is_up(l_ptr->owner)) { | ||
2138 | l_ptr->owner->bclink.last_sent = | ||
2139 | l_ptr->owner->bclink.last_in = | ||
2140 | msg_last_bcast(msg); | ||
2141 | l_ptr->owner->bclink.oos_state = 0; | ||
2142 | } | ||
2133 | 2143 | ||
2134 | l_ptr->peer_session = msg_session(msg); | 2144 | l_ptr->peer_session = msg_session(msg); |
2135 | l_ptr->peer_bearer_id = msg_bearer_id(msg); | 2145 | l_ptr->peer_bearer_id = msg_bearer_id(msg); |
2136 | 2146 | ||
2137 | /* Synchronize broadcast sequence numbers */ | 2147 | if (msg_type(msg) == ACTIVATE_MSG) |
2138 | if (!tipc_node_redundant_links(l_ptr->owner)) | 2148 | link_state_event(l_ptr, ACTIVATE_MSG); |
2139 | l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); | ||
2140 | break; | 2149 | break; |
2141 | case STATE_MSG: | 2150 | case STATE_MSG: |
2142 | 2151 | ||
@@ -2177,7 +2186,9 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
2177 | 2186 | ||
2178 | /* Protocol message before retransmits, reduce loss risk */ | 2187 | /* Protocol message before retransmits, reduce loss risk */ |
2179 | 2188 | ||
2180 | tipc_bclink_check_gap(l_ptr->owner, msg_last_bcast(msg)); | 2189 | if (l_ptr->owner->bclink.supported) |
2190 | tipc_bclink_update_link_state(l_ptr->owner, | ||
2191 | msg_last_bcast(msg)); | ||
2181 | 2192 | ||
2182 | if (rec_gap || (msg_probe(msg))) { | 2193 | if (rec_gap || (msg_probe(msg))) { |
2183 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, | 2194 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, |
@@ -2191,7 +2202,7 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
2191 | break; | 2202 | break; |
2192 | } | 2203 | } |
2193 | exit: | 2204 | exit: |
2194 | buf_discard(buf); | 2205 | kfree_skb(buf); |
2195 | } | 2206 | } |
2196 | 2207 | ||
2197 | 2208 | ||
@@ -2389,7 +2400,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, | |||
2389 | warn("Link changeover error, duplicate msg dropped\n"); | 2400 | warn("Link changeover error, duplicate msg dropped\n"); |
2390 | goto exit; | 2401 | goto exit; |
2391 | } | 2402 | } |
2392 | buf_discard(tunnel_buf); | 2403 | kfree_skb(tunnel_buf); |
2393 | return 1; | 2404 | return 1; |
2394 | } | 2405 | } |
2395 | 2406 | ||
@@ -2421,7 +2432,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, | |||
2421 | } else { | 2432 | } else { |
2422 | *buf = buf_extract(tunnel_buf, INT_H_SIZE); | 2433 | *buf = buf_extract(tunnel_buf, INT_H_SIZE); |
2423 | if (*buf != NULL) { | 2434 | if (*buf != NULL) { |
2424 | buf_discard(tunnel_buf); | 2435 | kfree_skb(tunnel_buf); |
2425 | return 1; | 2436 | return 1; |
2426 | } else { | 2437 | } else { |
2427 | warn("Link changeover error, original msg dropped\n"); | 2438 | warn("Link changeover error, original msg dropped\n"); |
@@ -2429,7 +2440,7 @@ static int link_recv_changeover_msg(struct tipc_link **l_ptr, | |||
2429 | } | 2440 | } |
2430 | exit: | 2441 | exit: |
2431 | *buf = NULL; | 2442 | *buf = NULL; |
2432 | buf_discard(tunnel_buf); | 2443 | kfree_skb(tunnel_buf); |
2433 | return 0; | 2444 | return 0; |
2434 | } | 2445 | } |
2435 | 2446 | ||
@@ -2451,7 +2462,7 @@ void tipc_link_recv_bundle(struct sk_buff *buf) | |||
2451 | pos += align(msg_size(buf_msg(obuf))); | 2462 | pos += align(msg_size(buf_msg(obuf))); |
2452 | tipc_net_route_msg(obuf); | 2463 | tipc_net_route_msg(obuf); |
2453 | } | 2464 | } |
2454 | buf_discard(buf); | 2465 | kfree_skb(buf); |
2455 | } | 2466 | } |
2456 | 2467 | ||
2457 | /* | 2468 | /* |
@@ -2500,11 +2511,11 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
2500 | } | 2511 | } |
2501 | fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); | 2512 | fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); |
2502 | if (fragm == NULL) { | 2513 | if (fragm == NULL) { |
2503 | buf_discard(buf); | 2514 | kfree_skb(buf); |
2504 | while (buf_chain) { | 2515 | while (buf_chain) { |
2505 | buf = buf_chain; | 2516 | buf = buf_chain; |
2506 | buf_chain = buf_chain->next; | 2517 | buf_chain = buf_chain->next; |
2507 | buf_discard(buf); | 2518 | kfree_skb(buf); |
2508 | } | 2519 | } |
2509 | return -ENOMEM; | 2520 | return -ENOMEM; |
2510 | } | 2521 | } |
@@ -2521,7 +2532,7 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
2521 | crs += fragm_sz; | 2532 | crs += fragm_sz; |
2522 | msg_set_type(&fragm_hdr, FRAGMENT); | 2533 | msg_set_type(&fragm_hdr, FRAGMENT); |
2523 | } | 2534 | } |
2524 | buf_discard(buf); | 2535 | kfree_skb(buf); |
2525 | 2536 | ||
2526 | /* Append chain of fragments to send queue & send them */ | 2537 | /* Append chain of fragments to send queue & send them */ |
2527 | 2538 | ||
@@ -2608,7 +2619,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | |||
2608 | if (msg_type(imsg) == TIPC_MCAST_MSG) | 2619 | if (msg_type(imsg) == TIPC_MCAST_MSG) |
2609 | max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; | 2620 | max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; |
2610 | if (msg_size(imsg) > max) { | 2621 | if (msg_size(imsg) > max) { |
2611 | buf_discard(fbuf); | 2622 | kfree_skb(fbuf); |
2612 | return 0; | 2623 | return 0; |
2613 | } | 2624 | } |
2614 | pbuf = tipc_buf_acquire(msg_size(imsg)); | 2625 | pbuf = tipc_buf_acquire(msg_size(imsg)); |
@@ -2623,9 +2634,11 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | |||
2623 | set_fragm_size(pbuf, fragm_sz); | 2634 | set_fragm_size(pbuf, fragm_sz); |
2624 | set_expected_frags(pbuf, exp_fragm_cnt - 1); | 2635 | set_expected_frags(pbuf, exp_fragm_cnt - 1); |
2625 | } else { | 2636 | } else { |
2626 | warn("Link unable to reassemble fragmented message\n"); | 2637 | dbg("Link unable to reassemble fragmented message\n"); |
2638 | kfree_skb(fbuf); | ||
2639 | return -1; | ||
2627 | } | 2640 | } |
2628 | buf_discard(fbuf); | 2641 | kfree_skb(fbuf); |
2629 | return 0; | 2642 | return 0; |
2630 | } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) { | 2643 | } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) { |
2631 | u32 dsz = msg_data_sz(fragm); | 2644 | u32 dsz = msg_data_sz(fragm); |
@@ -2634,7 +2647,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | |||
2634 | u32 exp_frags = get_expected_frags(pbuf) - 1; | 2647 | u32 exp_frags = get_expected_frags(pbuf) - 1; |
2635 | skb_copy_to_linear_data_offset(pbuf, crs, | 2648 | skb_copy_to_linear_data_offset(pbuf, crs, |
2636 | msg_data(fragm), dsz); | 2649 | msg_data(fragm), dsz); |
2637 | buf_discard(fbuf); | 2650 | kfree_skb(fbuf); |
2638 | 2651 | ||
2639 | /* Is message complete? */ | 2652 | /* Is message complete? */ |
2640 | 2653 | ||
@@ -2651,7 +2664,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | |||
2651 | set_expected_frags(pbuf, exp_frags); | 2664 | set_expected_frags(pbuf, exp_frags); |
2652 | return 0; | 2665 | return 0; |
2653 | } | 2666 | } |
2654 | buf_discard(fbuf); | 2667 | kfree_skb(fbuf); |
2655 | return 0; | 2668 | return 0; |
2656 | } | 2669 | } |
2657 | 2670 | ||
@@ -2682,7 +2695,7 @@ static void link_check_defragm_bufs(struct tipc_link *l_ptr) | |||
2682 | prev->next = buf->next; | 2695 | prev->next = buf->next; |
2683 | else | 2696 | else |
2684 | l_ptr->defragm_buf = buf->next; | 2697 | l_ptr->defragm_buf = buf->next; |
2685 | buf_discard(buf); | 2698 | kfree_skb(buf); |
2686 | } | 2699 | } |
2687 | buf = next; | 2700 | buf = next; |
2688 | } | 2701 | } |
@@ -3057,7 +3070,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_s | |||
3057 | str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), | 3070 | str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), |
3058 | (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); | 3071 | (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); |
3059 | if (!str_len) { | 3072 | if (!str_len) { |
3060 | buf_discard(buf); | 3073 | kfree_skb(buf); |
3061 | return tipc_cfg_reply_error_string("link not found"); | 3074 | return tipc_cfg_reply_error_string("link not found"); |
3062 | } | 3075 | } |
3063 | 3076 | ||
diff --git a/net/tipc/log.c b/net/tipc/log.c index 952c39f643e6..895c6e530b0b 100644 --- a/net/tipc/log.c +++ b/net/tipc/log.c | |||
@@ -304,7 +304,7 @@ struct sk_buff *tipc_log_resize_cmd(const void *req_tlv_area, int req_tlv_space) | |||
304 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 304 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
305 | 305 | ||
306 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 306 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
307 | if (value != delimit(value, 0, 32768)) | 307 | if (value > 32768) |
308 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 308 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
309 | " (log size must be 0-32768)"); | 309 | " (log size must be 0-32768)"); |
310 | if (tipc_log_resize(value)) | 310 | if (tipc_log_resize(value)) |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 3e4d3e29be61..e3afe162c0ac 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -106,7 +106,7 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, | |||
106 | if (likely(res)) | 106 | if (likely(res)) |
107 | return dsz; | 107 | return dsz; |
108 | 108 | ||
109 | buf_discard(*buf); | 109 | kfree_skb(*buf); |
110 | *buf = NULL; | 110 | *buf = NULL; |
111 | return -EFAULT; | 111 | return -EFAULT; |
112 | } | 112 | } |
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 7b0cda167107..eba524e34a6b 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -384,11 +384,6 @@ static inline void msg_set_destnode(struct tipc_msg *m, u32 a) | |||
384 | msg_set_word(m, 7, a); | 384 | msg_set_word(m, 7, a); |
385 | } | 385 | } |
386 | 386 | ||
387 | static inline int msg_is_dest(struct tipc_msg *m, u32 d) | ||
388 | { | ||
389 | return msg_short(m) || (msg_destnode(m) == d); | ||
390 | } | ||
391 | |||
392 | static inline u32 msg_nametype(struct tipc_msg *m) | 387 | static inline u32 msg_nametype(struct tipc_msg *m) |
393 | { | 388 | { |
394 | return msg_word(m, 8); | 389 | return msg_word(m, 8); |
@@ -517,6 +512,16 @@ static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) | |||
517 | msg_set_bits(m, 1, 16, 0x1fff, n); | 512 | msg_set_bits(m, 1, 16, 0x1fff, n); |
518 | } | 513 | } |
519 | 514 | ||
515 | static inline u32 msg_node_sig(struct tipc_msg *m) | ||
516 | { | ||
517 | return msg_bits(m, 1, 0, 0xffff); | ||
518 | } | ||
519 | |||
520 | static inline void msg_set_node_sig(struct tipc_msg *m, u32 n) | ||
521 | { | ||
522 | msg_set_bits(m, 1, 0, 0xffff, n); | ||
523 | } | ||
524 | |||
520 | 525 | ||
521 | /* | 526 | /* |
522 | * Word 2 | 527 | * Word 2 |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 98ebb37f1808..d57da6159616 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -120,7 +120,7 @@ static void named_cluster_distribute(struct sk_buff *buf) | |||
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | buf_discard(buf); | 123 | kfree_skb(buf); |
124 | } | 124 | } |
125 | 125 | ||
126 | /** | 126 | /** |
@@ -239,9 +239,6 @@ exit: | |||
239 | * | 239 | * |
240 | * Invoked for each publication issued by a newly failed node. | 240 | * Invoked for each publication issued by a newly failed node. |
241 | * Removes publication structure from name table & deletes it. | 241 | * Removes publication structure from name table & deletes it. |
242 | * In rare cases the link may have come back up again when this | ||
243 | * function is called, and we have two items representing the same | ||
244 | * publication. Nudge this item's key to distinguish it from the other. | ||
245 | */ | 242 | */ |
246 | 243 | ||
247 | static void named_purge_publ(struct publication *publ) | 244 | static void named_purge_publ(struct publication *publ) |
@@ -249,7 +246,6 @@ static void named_purge_publ(struct publication *publ) | |||
249 | struct publication *p; | 246 | struct publication *p; |
250 | 247 | ||
251 | write_lock_bh(&tipc_nametbl_lock); | 248 | write_lock_bh(&tipc_nametbl_lock); |
252 | publ->key += 1222345; | ||
253 | p = tipc_nametbl_remove_publ(publ->type, publ->lower, | 249 | p = tipc_nametbl_remove_publ(publ->type, publ->lower, |
254 | publ->node, publ->ref, publ->key); | 250 | publ->node, publ->ref, publ->key); |
255 | if (p) | 251 | if (p) |
@@ -316,7 +312,7 @@ void tipc_named_recv(struct sk_buff *buf) | |||
316 | item++; | 312 | item++; |
317 | } | 313 | } |
318 | write_unlock_bh(&tipc_nametbl_lock); | 314 | write_unlock_bh(&tipc_nametbl_lock); |
319 | buf_discard(buf); | 315 | kfree_skb(buf); |
320 | } | 316 | } |
321 | 317 | ||
322 | /** | 318 | /** |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 89eb5621ebba..c6a1ae36952e 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -114,10 +114,8 @@ struct name_table { | |||
114 | }; | 114 | }; |
115 | 115 | ||
116 | static struct name_table table; | 116 | static struct name_table table; |
117 | static atomic_t rsv_publ_ok = ATOMIC_INIT(0); | ||
118 | DEFINE_RWLOCK(tipc_nametbl_lock); | 117 | DEFINE_RWLOCK(tipc_nametbl_lock); |
119 | 118 | ||
120 | |||
121 | static int hash(int x) | 119 | static int hash(int x) |
122 | { | 120 | { |
123 | return x & (tipc_nametbl_size - 1); | 121 | return x & (tipc_nametbl_size - 1); |
@@ -270,6 +268,13 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, | |||
270 | } | 268 | } |
271 | 269 | ||
272 | info = sseq->info; | 270 | info = sseq->info; |
271 | |||
272 | /* Check if an identical publication already exists */ | ||
273 | list_for_each_entry(publ, &info->zone_list, zone_list) { | ||
274 | if ((publ->ref == port) && (publ->key == key) && | ||
275 | (!publ->node || (publ->node == node))) | ||
276 | return NULL; | ||
277 | } | ||
273 | } else { | 278 | } else { |
274 | u32 inspos; | 279 | u32 inspos; |
275 | struct sub_seq *freesseq; | 280 | struct sub_seq *freesseq; |
@@ -534,10 +539,17 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, | |||
534 | } | 539 | } |
535 | 540 | ||
536 | /* | 541 | /* |
537 | * tipc_nametbl_translate - translate name to port id | 542 | * tipc_nametbl_translate - perform name translation |
543 | * | ||
544 | * On entry, 'destnode' is the search domain used during translation. | ||
538 | * | 545 | * |
539 | * Note: on entry 'destnode' is the search domain used during translation; | 546 | * On exit: |
540 | * on exit it passes back the node address of the matching port (if any) | 547 | * - if name translation is deferred to another node/cluster/zone, |
548 | * leaves 'destnode' unchanged (will be non-zero) and returns 0 | ||
549 | * - if name translation is attempted and succeeds, sets 'destnode' | ||
550 | * to publishing node and returns port reference (will be non-zero) | ||
551 | * - if name translation is attempted and fails, sets 'destnode' to 0 | ||
552 | * and returns 0 | ||
541 | */ | 553 | */ |
542 | 554 | ||
543 | u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) | 555 | u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) |
@@ -547,6 +559,7 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) | |||
547 | struct publication *publ; | 559 | struct publication *publ; |
548 | struct name_seq *seq; | 560 | struct name_seq *seq; |
549 | u32 ref = 0; | 561 | u32 ref = 0; |
562 | u32 node = 0; | ||
550 | 563 | ||
551 | if (!tipc_in_scope(*destnode, tipc_own_addr)) | 564 | if (!tipc_in_scope(*destnode, tipc_own_addr)) |
552 | return 0; | 565 | return 0; |
@@ -604,11 +617,12 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) | |||
604 | } | 617 | } |
605 | 618 | ||
606 | ref = publ->ref; | 619 | ref = publ->ref; |
607 | *destnode = publ->node; | 620 | node = publ->node; |
608 | no_match: | 621 | no_match: |
609 | spin_unlock_bh(&seq->lock); | 622 | spin_unlock_bh(&seq->lock); |
610 | not_found: | 623 | not_found: |
611 | read_unlock_bh(&tipc_nametbl_lock); | 624 | read_unlock_bh(&tipc_nametbl_lock); |
625 | *destnode = node; | ||
612 | return ref; | 626 | return ref; |
613 | } | 627 | } |
614 | 628 | ||
@@ -665,22 +679,7 @@ exit: | |||
665 | return res; | 679 | return res; |
666 | } | 680 | } |
667 | 681 | ||
668 | /** | 682 | /* |
669 | * tipc_nametbl_publish_rsv - publish port name using a reserved name type | ||
670 | */ | ||
671 | |||
672 | int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, | ||
673 | struct tipc_name_seq const *seq) | ||
674 | { | ||
675 | int res; | ||
676 | |||
677 | atomic_inc(&rsv_publ_ok); | ||
678 | res = tipc_publish(ref, scope, seq); | ||
679 | atomic_dec(&rsv_publ_ok); | ||
680 | return res; | ||
681 | } | ||
682 | |||
683 | /** | ||
684 | * tipc_nametbl_publish - add name publication to network name tables | 683 | * tipc_nametbl_publish - add name publication to network name tables |
685 | */ | 684 | */ |
686 | 685 | ||
@@ -694,11 +693,6 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, | |||
694 | tipc_max_publications); | 693 | tipc_max_publications); |
695 | return NULL; | 694 | return NULL; |
696 | } | 695 | } |
697 | if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { | ||
698 | warn("Publication failed, reserved name {%u,%u,%u}\n", | ||
699 | type, lower, upper); | ||
700 | return NULL; | ||
701 | } | ||
702 | 696 | ||
703 | write_lock_bh(&tipc_nametbl_lock); | 697 | write_lock_bh(&tipc_nametbl_lock); |
704 | table.local_publ_count++; | 698 | table.local_publ_count++; |
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 8086b42f92ad..207d59ebf849 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h | |||
@@ -91,8 +91,6 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); | |||
91 | u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); | 91 | u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); |
92 | int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, | 92 | int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, |
93 | struct tipc_port_list *dports); | 93 | struct tipc_port_list *dports); |
94 | int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope, | ||
95 | struct tipc_name_seq const *seq); | ||
96 | struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, | 94 | struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, |
97 | u32 scope, u32 port_ref, u32 key); | 95 | u32 scope, u32 port_ref, u32 key); |
98 | int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); | 96 | int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 61afee7e8291..d4531b07076c 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -117,7 +117,7 @@ static void net_route_named_msg(struct sk_buff *buf) | |||
117 | u32 dport; | 117 | u32 dport; |
118 | 118 | ||
119 | if (!msg_named(msg)) { | 119 | if (!msg_named(msg)) { |
120 | buf_discard(buf); | 120 | kfree_skb(buf); |
121 | return; | 121 | return; |
122 | } | 122 | } |
123 | 123 | ||
@@ -161,7 +161,7 @@ void tipc_net_route_msg(struct sk_buff *buf) | |||
161 | tipc_port_recv_proto_msg(buf); | 161 | tipc_port_recv_proto_msg(buf); |
162 | break; | 162 | break; |
163 | default: | 163 | default: |
164 | buf_discard(buf); | 164 | kfree_skb(buf); |
165 | } | 165 | } |
166 | return; | 166 | return; |
167 | } | 167 | } |
@@ -175,14 +175,10 @@ int tipc_net_start(u32 addr) | |||
175 | { | 175 | { |
176 | char addr_string[16]; | 176 | char addr_string[16]; |
177 | 177 | ||
178 | if (tipc_mode != TIPC_NODE_MODE) | ||
179 | return -ENOPROTOOPT; | ||
180 | |||
181 | tipc_subscr_stop(); | 178 | tipc_subscr_stop(); |
182 | tipc_cfg_stop(); | 179 | tipc_cfg_stop(); |
183 | 180 | ||
184 | tipc_own_addr = addr; | 181 | tipc_own_addr = addr; |
185 | tipc_mode = TIPC_NET_MODE; | ||
186 | tipc_named_reinit(); | 182 | tipc_named_reinit(); |
187 | tipc_port_reinit(); | 183 | tipc_port_reinit(); |
188 | 184 | ||
@@ -201,10 +197,9 @@ void tipc_net_stop(void) | |||
201 | { | 197 | { |
202 | struct tipc_node *node, *t_node; | 198 | struct tipc_node *node, *t_node; |
203 | 199 | ||
204 | if (tipc_mode != TIPC_NET_MODE) | 200 | if (!tipc_own_addr) |
205 | return; | 201 | return; |
206 | write_lock_bh(&tipc_net_lock); | 202 | write_lock_bh(&tipc_net_lock); |
207 | tipc_mode = TIPC_NODE_MODE; | ||
208 | tipc_bearer_stop(); | 203 | tipc_bearer_stop(); |
209 | tipc_bclink_stop(); | 204 | tipc_bclink_stop(); |
210 | list_for_each_entry_safe(node, t_node, &tipc_node_list, list) | 205 | list_for_each_entry_safe(node, t_node, &tipc_node_list, list) |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 6b226faad89f..a34cabc2c43a 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #include "node.h" | 39 | #include "node.h" |
40 | #include "name_distr.h" | 40 | #include "name_distr.h" |
41 | 41 | ||
42 | #define NODE_HTABLE_SIZE 512 | ||
43 | |||
42 | static void node_lost_contact(struct tipc_node *n_ptr); | 44 | static void node_lost_contact(struct tipc_node *n_ptr); |
43 | static void node_established_contact(struct tipc_node *n_ptr); | 45 | static void node_established_contact(struct tipc_node *n_ptr); |
44 | 46 | ||
@@ -49,9 +51,19 @@ LIST_HEAD(tipc_node_list); | |||
49 | static u32 tipc_num_nodes; | 51 | static u32 tipc_num_nodes; |
50 | 52 | ||
51 | static atomic_t tipc_num_links = ATOMIC_INIT(0); | 53 | static atomic_t tipc_num_links = ATOMIC_INIT(0); |
52 | u32 tipc_own_tag; | ||
53 | 54 | ||
54 | /** | 55 | /* |
56 | * A trivial power-of-two bitmask technique is used for speed, since this | ||
57 | * operation is done for every incoming TIPC packet. The number of hash table | ||
58 | * entries has been chosen so that no hash chain exceeds 8 nodes and will | ||
59 | * usually be much smaller (typically only a single node). | ||
60 | */ | ||
61 | static inline unsigned int tipc_hashfn(u32 addr) | ||
62 | { | ||
63 | return addr & (NODE_HTABLE_SIZE - 1); | ||
64 | } | ||
65 | |||
66 | /* | ||
55 | * tipc_node_find - locate specified node object, if it exists | 67 | * tipc_node_find - locate specified node object, if it exists |
56 | */ | 68 | */ |
57 | 69 | ||
@@ -113,6 +125,7 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
113 | } | 125 | } |
114 | list_add_tail(&n_ptr->list, &temp_node->list); | 126 | list_add_tail(&n_ptr->list, &temp_node->list); |
115 | n_ptr->block_setup = WAIT_PEER_DOWN; | 127 | n_ptr->block_setup = WAIT_PEER_DOWN; |
128 | n_ptr->signature = INVALID_NODE_SIG; | ||
116 | 129 | ||
117 | tipc_num_nodes++; | 130 | tipc_num_nodes++; |
118 | 131 | ||
@@ -253,63 +266,14 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | |||
253 | n_ptr->link_cnt--; | 266 | n_ptr->link_cnt--; |
254 | } | 267 | } |
255 | 268 | ||
256 | /* | ||
257 | * Routing table management - five cases to handle: | ||
258 | * | ||
259 | * 1: A link towards a zone/cluster external node comes up. | ||
260 | * => Send a multicast message updating routing tables of all | ||
261 | * system nodes within own cluster that the new destination | ||
262 | * can be reached via this node. | ||
263 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
264 | * | ||
265 | * 2: A link towards a slave node comes up. | ||
266 | * => Send a multicast message updating routing tables of all | ||
267 | * system nodes within own cluster that the new destination | ||
268 | * can be reached via this node. | ||
269 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
270 | * => Send a message to the slave node about existence | ||
271 | * of all system nodes within cluster: | ||
272 | * (node.establishedContact()=>cluster.sendLocalRoutes()) | ||
273 | * | ||
274 | * 3: A new cluster local system node becomes available. | ||
275 | * => Send message(s) to this particular node containing | ||
276 | * information about all cluster external and slave | ||
277 | * nodes which can be reached via this node. | ||
278 | * (node.establishedContact()==>network.sendExternalRoutes()) | ||
279 | * (node.establishedContact()==>network.sendSlaveRoutes()) | ||
280 | * => Send messages to all directly connected slave nodes | ||
281 | * containing information about the existence of the new node | ||
282 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
283 | * | ||
284 | * 4: The link towards a zone/cluster external node or slave | ||
285 | * node goes down. | ||
286 | * => Send a multcast message updating routing tables of all | ||
287 | * nodes within cluster that the new destination can not any | ||
288 | * longer be reached via this node. | ||
289 | * (node.lostAllLinks()=>cluster.bcastLostRoute()) | ||
290 | * | ||
291 | * 5: A cluster local system node becomes unavailable. | ||
292 | * => Remove all references to this node from the local | ||
293 | * routing tables. Note: This is a completely node | ||
294 | * local operation. | ||
295 | * (node.lostAllLinks()=>network.removeAsRouter()) | ||
296 | * => Send messages to all directly connected slave nodes | ||
297 | * containing information about loss of the node | ||
298 | * (node.establishedContact()=>cluster.multicastLostRoute()) | ||
299 | * | ||
300 | */ | ||
301 | |||
302 | static void node_established_contact(struct tipc_node *n_ptr) | 269 | static void node_established_contact(struct tipc_node *n_ptr) |
303 | { | 270 | { |
304 | tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); | 271 | tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); |
305 | 272 | ||
306 | /* Syncronize broadcast acks */ | 273 | if (n_ptr->bclink.supportable) { |
307 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); | 274 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); |
308 | |||
309 | if (n_ptr->bclink.supported) { | ||
310 | tipc_bclink_add_node(n_ptr->addr); | 275 | tipc_bclink_add_node(n_ptr->addr); |
311 | if (n_ptr->addr < tipc_own_addr) | 276 | n_ptr->bclink.supported = 1; |
312 | tipc_own_tag++; | ||
313 | } | 277 | } |
314 | } | 278 | } |
315 | 279 | ||
@@ -338,22 +302,20 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
338 | /* Flush broadcast link info associated with lost node */ | 302 | /* Flush broadcast link info associated with lost node */ |
339 | 303 | ||
340 | if (n_ptr->bclink.supported) { | 304 | if (n_ptr->bclink.supported) { |
341 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; | ||
342 | while (n_ptr->bclink.deferred_head) { | 305 | while (n_ptr->bclink.deferred_head) { |
343 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | 306 | struct sk_buff *buf = n_ptr->bclink.deferred_head; |
344 | n_ptr->bclink.deferred_head = buf->next; | 307 | n_ptr->bclink.deferred_head = buf->next; |
345 | buf_discard(buf); | 308 | kfree_skb(buf); |
346 | } | 309 | } |
310 | n_ptr->bclink.deferred_size = 0; | ||
347 | 311 | ||
348 | if (n_ptr->bclink.defragm) { | 312 | if (n_ptr->bclink.defragm) { |
349 | buf_discard(n_ptr->bclink.defragm); | 313 | kfree_skb(n_ptr->bclink.defragm); |
350 | n_ptr->bclink.defragm = NULL; | 314 | n_ptr->bclink.defragm = NULL; |
351 | } | 315 | } |
352 | 316 | ||
353 | tipc_bclink_remove_node(n_ptr->addr); | 317 | tipc_bclink_remove_node(n_ptr->addr); |
354 | tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ); | 318 | tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ); |
355 | if (n_ptr->addr < tipc_own_addr) | ||
356 | tipc_own_tag--; | ||
357 | 319 | ||
358 | n_ptr->bclink.supported = 0; | 320 | n_ptr->bclink.supported = 0; |
359 | } | 321 | } |
@@ -444,12 +406,12 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
444 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 406 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
445 | " (network address)"); | 407 | " (network address)"); |
446 | 408 | ||
447 | if (tipc_mode != TIPC_NET_MODE) | 409 | if (!tipc_own_addr) |
448 | return tipc_cfg_reply_none(); | 410 | return tipc_cfg_reply_none(); |
449 | 411 | ||
450 | read_lock_bh(&tipc_net_lock); | 412 | read_lock_bh(&tipc_net_lock); |
451 | 413 | ||
452 | /* Get space for all unicast links + multicast link */ | 414 | /* Get space for all unicast links + broadcast link */ |
453 | 415 | ||
454 | payload_size = TLV_SPACE(sizeof(link_info)) * | 416 | payload_size = TLV_SPACE(sizeof(link_info)) * |
455 | (atomic_read(&tipc_num_links) + 1); | 417 | (atomic_read(&tipc_num_links) + 1); |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 0b1c5f8b6996..72561c971d67 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -42,6 +42,11 @@ | |||
42 | #include "net.h" | 42 | #include "net.h" |
43 | #include "bearer.h" | 43 | #include "bearer.h" |
44 | 44 | ||
45 | /* | ||
46 | * Out-of-range value for node signature | ||
47 | */ | ||
48 | #define INVALID_NODE_SIG 0x10000 | ||
49 | |||
45 | /* Flags used to block (re)establishment of contact with a neighboring node */ | 50 | /* Flags used to block (re)establishment of contact with a neighboring node */ |
46 | 51 | ||
47 | #define WAIT_PEER_DOWN 0x0001 /* wait to see that peer's links are down */ | 52 | #define WAIT_PEER_DOWN 0x0001 /* wait to see that peer's links are down */ |
@@ -61,13 +66,15 @@ | |||
61 | * @block_setup: bit mask of conditions preventing link establishment to node | 66 | * @block_setup: bit mask of conditions preventing link establishment to node |
62 | * @link_cnt: number of links to node | 67 | * @link_cnt: number of links to node |
63 | * @permit_changeover: non-zero if node has redundant links to this system | 68 | * @permit_changeover: non-zero if node has redundant links to this system |
69 | * @signature: node instance identifier | ||
64 | * @bclink: broadcast-related info | 70 | * @bclink: broadcast-related info |
71 | * @supportable: non-zero if node supports TIPC b'cast link capability | ||
65 | * @supported: non-zero if node supports TIPC b'cast capability | 72 | * @supported: non-zero if node supports TIPC b'cast capability |
66 | * @acked: sequence # of last outbound b'cast message acknowledged by node | 73 | * @acked: sequence # of last outbound b'cast message acknowledged by node |
67 | * @last_in: sequence # of last in-sequence b'cast message received from node | 74 | * @last_in: sequence # of last in-sequence b'cast message received from node |
68 | * @gap_after: sequence # of last message not requiring a NAK request | 75 | * @last_sent: sequence # of last b'cast message sent by node |
69 | * @gap_to: sequence # of last message requiring a NAK request | 76 | * @oos_state: state tracker for handling OOS b'cast messages |
70 | * @nack_sync: counter that determines when NAK requests should be sent | 77 | * @deferred_size: number of OOS b'cast messages in deferred queue |
71 | * @deferred_head: oldest OOS b'cast message received from node | 78 | * @deferred_head: oldest OOS b'cast message received from node |
72 | * @deferred_tail: newest OOS b'cast message received from node | 79 | * @deferred_tail: newest OOS b'cast message received from node |
73 | * @defragm: list of partially reassembled b'cast message fragments from node | 80 | * @defragm: list of partially reassembled b'cast message fragments from node |
@@ -85,35 +92,23 @@ struct tipc_node { | |||
85 | int working_links; | 92 | int working_links; |
86 | int block_setup; | 93 | int block_setup; |
87 | int permit_changeover; | 94 | int permit_changeover; |
95 | u32 signature; | ||
88 | struct { | 96 | struct { |
89 | int supported; | 97 | u8 supportable; |
98 | u8 supported; | ||
90 | u32 acked; | 99 | u32 acked; |
91 | u32 last_in; | 100 | u32 last_in; |
92 | u32 gap_after; | 101 | u32 last_sent; |
93 | u32 gap_to; | 102 | u32 oos_state; |
94 | u32 nack_sync; | 103 | u32 deferred_size; |
95 | struct sk_buff *deferred_head; | 104 | struct sk_buff *deferred_head; |
96 | struct sk_buff *deferred_tail; | 105 | struct sk_buff *deferred_tail; |
97 | struct sk_buff *defragm; | 106 | struct sk_buff *defragm; |
98 | } bclink; | 107 | } bclink; |
99 | }; | 108 | }; |
100 | 109 | ||
101 | #define NODE_HTABLE_SIZE 512 | ||
102 | extern struct list_head tipc_node_list; | 110 | extern struct list_head tipc_node_list; |
103 | 111 | ||
104 | /* | ||
105 | * A trivial power-of-two bitmask technique is used for speed, since this | ||
106 | * operation is done for every incoming TIPC packet. The number of hash table | ||
107 | * entries has been chosen so that no hash chain exceeds 8 nodes and will | ||
108 | * usually be much smaller (typically only a single node). | ||
109 | */ | ||
110 | static inline unsigned int tipc_hashfn(u32 addr) | ||
111 | { | ||
112 | return addr & (NODE_HTABLE_SIZE - 1); | ||
113 | } | ||
114 | |||
115 | extern u32 tipc_own_tag; | ||
116 | |||
117 | struct tipc_node *tipc_node_find(u32 addr); | 112 | struct tipc_node *tipc_node_find(u32 addr); |
118 | struct tipc_node *tipc_node_create(u32 addr); | 113 | struct tipc_node *tipc_node_create(u32 addr); |
119 | void tipc_node_delete(struct tipc_node *n_ptr); | 114 | void tipc_node_delete(struct tipc_node *n_ptr); |
diff --git a/net/tipc/port.c b/net/tipc/port.c index d91efc69e6f9..94d2904cce66 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -116,13 +116,13 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | |||
116 | ibuf = skb_copy(buf, GFP_ATOMIC); | 116 | ibuf = skb_copy(buf, GFP_ATOMIC); |
117 | if (ibuf == NULL) { | 117 | if (ibuf == NULL) { |
118 | tipc_port_list_free(&dports); | 118 | tipc_port_list_free(&dports); |
119 | buf_discard(buf); | 119 | kfree_skb(buf); |
120 | return -ENOMEM; | 120 | return -ENOMEM; |
121 | } | 121 | } |
122 | } | 122 | } |
123 | res = tipc_bclink_send_msg(buf); | 123 | res = tipc_bclink_send_msg(buf); |
124 | if ((res < 0) && (dports.count != 0)) | 124 | if ((res < 0) && (dports.count != 0)) |
125 | buf_discard(ibuf); | 125 | kfree_skb(ibuf); |
126 | } else { | 126 | } else { |
127 | ibuf = buf; | 127 | ibuf = buf; |
128 | } | 128 | } |
@@ -187,7 +187,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) | |||
187 | } | 187 | } |
188 | } | 188 | } |
189 | exit: | 189 | exit: |
190 | buf_discard(buf); | 190 | kfree_skb(buf); |
191 | tipc_port_list_free(dp); | 191 | tipc_port_list_free(dp); |
192 | } | 192 | } |
193 | 193 | ||
@@ -400,15 +400,16 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) | |||
400 | 400 | ||
401 | /* send self-abort message when rejecting on a connected port */ | 401 | /* send self-abort message when rejecting on a connected port */ |
402 | if (msg_connected(msg)) { | 402 | if (msg_connected(msg)) { |
403 | struct sk_buff *abuf = NULL; | ||
404 | struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); | 403 | struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); |
405 | 404 | ||
406 | if (p_ptr) { | 405 | if (p_ptr) { |
406 | struct sk_buff *abuf = NULL; | ||
407 | |||
407 | if (p_ptr->connected) | 408 | if (p_ptr->connected) |
408 | abuf = port_build_self_abort_msg(p_ptr, err); | 409 | abuf = port_build_self_abort_msg(p_ptr, err); |
409 | tipc_port_unlock(p_ptr); | 410 | tipc_port_unlock(p_ptr); |
411 | tipc_net_route_msg(abuf); | ||
410 | } | 412 | } |
411 | tipc_net_route_msg(abuf); | ||
412 | } | 413 | } |
413 | 414 | ||
414 | /* send returned message & dispose of rejected message */ | 415 | /* send returned message & dispose of rejected message */ |
@@ -419,7 +420,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) | |||
419 | else | 420 | else |
420 | tipc_link_send(rbuf, src_node, msg_link_selector(rmsg)); | 421 | tipc_link_send(rbuf, src_node, msg_link_selector(rmsg)); |
421 | exit: | 422 | exit: |
422 | buf_discard(buf); | 423 | kfree_skb(buf); |
423 | return data_sz; | 424 | return data_sz; |
424 | } | 425 | } |
425 | 426 | ||
@@ -567,7 +568,7 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) | |||
567 | tipc_port_unlock(p_ptr); | 568 | tipc_port_unlock(p_ptr); |
568 | exit: | 569 | exit: |
569 | tipc_net_route_msg(r_buf); | 570 | tipc_net_route_msg(r_buf); |
570 | buf_discard(buf); | 571 | kfree_skb(buf); |
571 | } | 572 | } |
572 | 573 | ||
573 | static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id) | 574 | static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id) |
@@ -758,7 +759,7 @@ static void port_dispatcher_sigh(void *dummy) | |||
758 | } | 759 | } |
759 | } | 760 | } |
760 | if (buf) | 761 | if (buf) |
761 | buf_discard(buf); | 762 | kfree_skb(buf); |
762 | buf = next; | 763 | buf = next; |
763 | continue; | 764 | continue; |
764 | err: | 765 | err: |
@@ -812,7 +813,7 @@ err: | |||
812 | } | 813 | } |
813 | } | 814 | } |
814 | if (buf) | 815 | if (buf) |
815 | buf_discard(buf); | 816 | kfree_skb(buf); |
816 | buf = next; | 817 | buf = next; |
817 | continue; | 818 | continue; |
818 | reject: | 819 | reject: |
@@ -1053,8 +1054,6 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) | |||
1053 | msg = &p_ptr->phdr; | 1054 | msg = &p_ptr->phdr; |
1054 | msg_set_destnode(msg, peer->node); | 1055 | msg_set_destnode(msg, peer->node); |
1055 | msg_set_destport(msg, peer->ref); | 1056 | msg_set_destport(msg, peer->ref); |
1056 | msg_set_orignode(msg, tipc_own_addr); | ||
1057 | msg_set_origport(msg, p_ptr->ref); | ||
1058 | msg_set_type(msg, TIPC_CONN_MSG); | 1057 | msg_set_type(msg, TIPC_CONN_MSG); |
1059 | msg_set_lookup_scope(msg, 0); | 1058 | msg_set_lookup_scope(msg, 0); |
1060 | msg_set_hdr_sz(msg, SHORT_H_SIZE); | 1059 | msg_set_hdr_sz(msg, SHORT_H_SIZE); |
@@ -1132,6 +1131,49 @@ int tipc_shutdown(u32 ref) | |||
1132 | return tipc_disconnect(ref); | 1131 | return tipc_disconnect(ref); |
1133 | } | 1132 | } |
1134 | 1133 | ||
1134 | /** | ||
1135 | * tipc_port_recv_msg - receive message from lower layer and deliver to port user | ||
1136 | */ | ||
1137 | |||
1138 | int tipc_port_recv_msg(struct sk_buff *buf) | ||
1139 | { | ||
1140 | struct tipc_port *p_ptr; | ||
1141 | struct tipc_msg *msg = buf_msg(buf); | ||
1142 | u32 destport = msg_destport(msg); | ||
1143 | u32 dsz = msg_data_sz(msg); | ||
1144 | u32 err; | ||
1145 | |||
1146 | /* forward unresolved named message */ | ||
1147 | if (unlikely(!destport)) { | ||
1148 | tipc_net_route_msg(buf); | ||
1149 | return dsz; | ||
1150 | } | ||
1151 | |||
1152 | /* validate destination & pass to port, otherwise reject message */ | ||
1153 | p_ptr = tipc_port_lock(destport); | ||
1154 | if (likely(p_ptr)) { | ||
1155 | if (likely(p_ptr->connected)) { | ||
1156 | if ((unlikely(msg_origport(msg) != | ||
1157 | tipc_peer_port(p_ptr))) || | ||
1158 | (unlikely(msg_orignode(msg) != | ||
1159 | tipc_peer_node(p_ptr))) || | ||
1160 | (unlikely(!msg_connected(msg)))) { | ||
1161 | err = TIPC_ERR_NO_PORT; | ||
1162 | tipc_port_unlock(p_ptr); | ||
1163 | goto reject; | ||
1164 | } | ||
1165 | } | ||
1166 | err = p_ptr->dispatcher(p_ptr, buf); | ||
1167 | tipc_port_unlock(p_ptr); | ||
1168 | if (likely(!err)) | ||
1169 | return dsz; | ||
1170 | } else { | ||
1171 | err = TIPC_ERR_NO_PORT; | ||
1172 | } | ||
1173 | reject: | ||
1174 | return tipc_reject_msg(buf, err); | ||
1175 | } | ||
1176 | |||
1135 | /* | 1177 | /* |
1136 | * tipc_port_recv_sections(): Concatenate and deliver sectioned | 1178 | * tipc_port_recv_sections(): Concatenate and deliver sectioned |
1137 | * message for this node. | 1179 | * message for this node. |
@@ -1210,8 +1252,6 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | |||
1210 | 1252 | ||
1211 | msg = &p_ptr->phdr; | 1253 | msg = &p_ptr->phdr; |
1212 | msg_set_type(msg, TIPC_NAMED_MSG); | 1254 | msg_set_type(msg, TIPC_NAMED_MSG); |
1213 | msg_set_orignode(msg, tipc_own_addr); | ||
1214 | msg_set_origport(msg, ref); | ||
1215 | msg_set_hdr_sz(msg, NAMED_H_SIZE); | 1255 | msg_set_hdr_sz(msg, NAMED_H_SIZE); |
1216 | msg_set_nametype(msg, name->type); | 1256 | msg_set_nametype(msg, name->type); |
1217 | msg_set_nameinst(msg, name->instance); | 1257 | msg_set_nameinst(msg, name->instance); |
@@ -1220,7 +1260,7 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | |||
1220 | msg_set_destnode(msg, destnode); | 1260 | msg_set_destnode(msg, destnode); |
1221 | msg_set_destport(msg, destport); | 1261 | msg_set_destport(msg, destport); |
1222 | 1262 | ||
1223 | if (likely(destport)) { | 1263 | if (likely(destport || destnode)) { |
1224 | if (likely(destnode == tipc_own_addr)) | 1264 | if (likely(destnode == tipc_own_addr)) |
1225 | res = tipc_port_recv_sections(p_ptr, num_sect, | 1265 | res = tipc_port_recv_sections(p_ptr, num_sect, |
1226 | msg_sect, total_len); | 1266 | msg_sect, total_len); |
@@ -1261,8 +1301,6 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, | |||
1261 | msg = &p_ptr->phdr; | 1301 | msg = &p_ptr->phdr; |
1262 | msg_set_type(msg, TIPC_DIRECT_MSG); | 1302 | msg_set_type(msg, TIPC_DIRECT_MSG); |
1263 | msg_set_lookup_scope(msg, 0); | 1303 | msg_set_lookup_scope(msg, 0); |
1264 | msg_set_orignode(msg, tipc_own_addr); | ||
1265 | msg_set_origport(msg, ref); | ||
1266 | msg_set_destnode(msg, dest->node); | 1304 | msg_set_destnode(msg, dest->node); |
1267 | msg_set_destport(msg, dest->ref); | 1305 | msg_set_destport(msg, dest->ref); |
1268 | msg_set_hdr_sz(msg, BASIC_H_SIZE); | 1306 | msg_set_hdr_sz(msg, BASIC_H_SIZE); |
@@ -1301,8 +1339,6 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, | |||
1301 | 1339 | ||
1302 | msg = &p_ptr->phdr; | 1340 | msg = &p_ptr->phdr; |
1303 | msg_set_type(msg, TIPC_DIRECT_MSG); | 1341 | msg_set_type(msg, TIPC_DIRECT_MSG); |
1304 | msg_set_orignode(msg, tipc_own_addr); | ||
1305 | msg_set_origport(msg, ref); | ||
1306 | msg_set_destnode(msg, dest->node); | 1342 | msg_set_destnode(msg, dest->node); |
1307 | msg_set_destport(msg, dest->ref); | 1343 | msg_set_destport(msg, dest->ref); |
1308 | msg_set_hdr_sz(msg, BASIC_H_SIZE); | 1344 | msg_set_hdr_sz(msg, BASIC_H_SIZE); |
diff --git a/net/tipc/port.h b/net/tipc/port.h index f751807e2a91..9b88531e5a61 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h | |||
@@ -205,6 +205,7 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr); | |||
205 | /* | 205 | /* |
206 | * TIPC messaging routines | 206 | * TIPC messaging routines |
207 | */ | 207 | */ |
208 | int tipc_port_recv_msg(struct sk_buff *buf); | ||
208 | int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect, | 209 | int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect, |
209 | unsigned int total_len); | 210 | unsigned int total_len); |
210 | 211 | ||
@@ -271,45 +272,4 @@ static inline int tipc_port_congested(struct tipc_port *p_ptr) | |||
271 | return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); | 272 | return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); |
272 | } | 273 | } |
273 | 274 | ||
274 | /** | ||
275 | * tipc_port_recv_msg - receive message from lower layer and deliver to port user | ||
276 | */ | ||
277 | |||
278 | static inline int tipc_port_recv_msg(struct sk_buff *buf) | ||
279 | { | ||
280 | struct tipc_port *p_ptr; | ||
281 | struct tipc_msg *msg = buf_msg(buf); | ||
282 | u32 destport = msg_destport(msg); | ||
283 | u32 dsz = msg_data_sz(msg); | ||
284 | u32 err; | ||
285 | |||
286 | /* forward unresolved named message */ | ||
287 | if (unlikely(!destport)) { | ||
288 | tipc_net_route_msg(buf); | ||
289 | return dsz; | ||
290 | } | ||
291 | |||
292 | /* validate destination & pass to port, otherwise reject message */ | ||
293 | p_ptr = tipc_port_lock(destport); | ||
294 | if (likely(p_ptr)) { | ||
295 | if (likely(p_ptr->connected)) { | ||
296 | if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) || | ||
297 | (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) || | ||
298 | (unlikely(!msg_connected(msg)))) { | ||
299 | err = TIPC_ERR_NO_PORT; | ||
300 | tipc_port_unlock(p_ptr); | ||
301 | goto reject; | ||
302 | } | ||
303 | } | ||
304 | err = p_ptr->dispatcher(p_ptr, buf); | ||
305 | tipc_port_unlock(p_ptr); | ||
306 | if (likely(!err)) | ||
307 | return dsz; | ||
308 | } else { | ||
309 | err = TIPC_ERR_NO_PORT; | ||
310 | } | ||
311 | reject: | ||
312 | return tipc_reject_msg(buf, err); | ||
313 | } | ||
314 | |||
315 | #endif | 275 | #endif |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index e2f7c5d370ba..29e957f64458 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -126,7 +126,7 @@ static atomic_t tipc_queue_size = ATOMIC_INIT(0); | |||
126 | 126 | ||
127 | static void advance_rx_queue(struct sock *sk) | 127 | static void advance_rx_queue(struct sock *sk) |
128 | { | 128 | { |
129 | buf_discard(__skb_dequeue(&sk->sk_receive_queue)); | 129 | kfree_skb(__skb_dequeue(&sk->sk_receive_queue)); |
130 | atomic_dec(&tipc_queue_size); | 130 | atomic_dec(&tipc_queue_size); |
131 | } | 131 | } |
132 | 132 | ||
@@ -142,7 +142,7 @@ static void discard_rx_queue(struct sock *sk) | |||
142 | 142 | ||
143 | while ((buf = __skb_dequeue(&sk->sk_receive_queue))) { | 143 | while ((buf = __skb_dequeue(&sk->sk_receive_queue))) { |
144 | atomic_dec(&tipc_queue_size); | 144 | atomic_dec(&tipc_queue_size); |
145 | buf_discard(buf); | 145 | kfree_skb(buf); |
146 | } | 146 | } |
147 | } | 147 | } |
148 | 148 | ||
@@ -288,7 +288,7 @@ static int release(struct socket *sock) | |||
288 | break; | 288 | break; |
289 | atomic_dec(&tipc_queue_size); | 289 | atomic_dec(&tipc_queue_size); |
290 | if (TIPC_SKB_CB(buf)->handle != 0) | 290 | if (TIPC_SKB_CB(buf)->handle != 0) |
291 | buf_discard(buf); | 291 | kfree_skb(buf); |
292 | else { | 292 | else { |
293 | if ((sock->state == SS_CONNECTING) || | 293 | if ((sock->state == SS_CONNECTING) || |
294 | (sock->state == SS_CONNECTED)) { | 294 | (sock->state == SS_CONNECTED)) { |
@@ -355,6 +355,9 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | |||
355 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) | 355 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) |
356 | return -EAFNOSUPPORT; | 356 | return -EAFNOSUPPORT; |
357 | 357 | ||
358 | if (addr->addr.nameseq.type < TIPC_RESERVED_TYPES) | ||
359 | return -EACCES; | ||
360 | |||
358 | return (addr->scope > 0) ? | 361 | return (addr->scope > 0) ? |
359 | tipc_publish(portref, addr->scope, &addr->addr.nameseq) : | 362 | tipc_publish(portref, addr->scope, &addr->addr.nameseq) : |
360 | tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq); | 363 | tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq); |
@@ -1612,7 +1615,7 @@ restart: | |||
1612 | if (buf) { | 1615 | if (buf) { |
1613 | atomic_dec(&tipc_queue_size); | 1616 | atomic_dec(&tipc_queue_size); |
1614 | if (TIPC_SKB_CB(buf)->handle != 0) { | 1617 | if (TIPC_SKB_CB(buf)->handle != 0) { |
1615 | buf_discard(buf); | 1618 | kfree_skb(buf); |
1616 | goto restart; | 1619 | goto restart; |
1617 | } | 1620 | } |
1618 | tipc_disconnect(tport->ref); | 1621 | tipc_disconnect(tport->ref); |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 8c49566da8f3..b2964e9895d3 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -552,7 +552,7 @@ int tipc_subscr_start(void) | |||
552 | if (res) | 552 | if (res) |
553 | goto failed; | 553 | goto failed; |
554 | 554 | ||
555 | res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); | 555 | res = tipc_publish(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); |
556 | if (res) { | 556 | if (res) { |
557 | tipc_deleteport(topsrv.setup_port); | 557 | tipc_deleteport(topsrv.setup_port); |
558 | topsrv.setup_port = 0; | 558 | topsrv.setup_port = 0; |