diff options
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; |
