aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/port.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/port.c')
-rw-r--r--net/tipc/port.c284
1 files changed, 129 insertions, 155 deletions
diff --git a/net/tipc/port.c b/net/tipc/port.c
index c68dc956a423..54d812a5a4d9 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -222,7 +222,7 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,
222 p_ptr->max_pkt = MAX_PKT_DEFAULT; 222 p_ptr->max_pkt = MAX_PKT_DEFAULT;
223 p_ptr->ref = ref; 223 p_ptr->ref = ref;
224 msg = &p_ptr->phdr; 224 msg = &p_ptr->phdr;
225 tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); 225 tipc_msg_init(msg, importance, TIPC_NAMED_MSG, NAMED_H_SIZE, 0);
226 msg_set_origport(msg, ref); 226 msg_set_origport(msg, ref);
227 INIT_LIST_HEAD(&p_ptr->wait_list); 227 INIT_LIST_HEAD(&p_ptr->wait_list);
228 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); 228 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
@@ -327,26 +327,23 @@ int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
327} 327}
328 328
329/* 329/*
330 * port_build_proto_msg(): build a port level protocol 330 * port_build_proto_msg(): create connection protocol message for port
331 * or a connection abortion message. Called with 331 *
332 * tipc_port lock on. 332 * On entry the port must be locked and connected.
333 */ 333 */
334static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, 334static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr,
335 u32 origport, u32 orignode, 335 u32 type, u32 ack)
336 u32 usr, u32 type, u32 err,
337 u32 ack)
338{ 336{
339 struct sk_buff *buf; 337 struct sk_buff *buf;
340 struct tipc_msg *msg; 338 struct tipc_msg *msg;
341 339
342 buf = tipc_buf_acquire(LONG_H_SIZE); 340 buf = tipc_buf_acquire(INT_H_SIZE);
343 if (buf) { 341 if (buf) {
344 msg = buf_msg(buf); 342 msg = buf_msg(buf);
345 tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode); 343 tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE,
346 msg_set_errcode(msg, err); 344 port_peernode(p_ptr));
347 msg_set_destport(msg, destport); 345 msg_set_destport(msg, port_peerport(p_ptr));
348 msg_set_origport(msg, origport); 346 msg_set_origport(msg, p_ptr->ref);
349 msg_set_orignode(msg, orignode);
350 msg_set_msgcnt(msg, ack); 347 msg_set_msgcnt(msg, ack);
351 } 348 }
352 return buf; 349 return buf;
@@ -358,45 +355,48 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
358 struct sk_buff *rbuf; 355 struct sk_buff *rbuf;
359 struct tipc_msg *rmsg; 356 struct tipc_msg *rmsg;
360 int hdr_sz; 357 int hdr_sz;
361 u32 imp = msg_importance(msg); 358 u32 imp;
362 u32 data_sz = msg_data_sz(msg); 359 u32 data_sz = msg_data_sz(msg);
363 360 u32 src_node;
364 if (data_sz > MAX_REJECT_SIZE) 361 u32 rmsg_sz;
365 data_sz = MAX_REJECT_SIZE;
366 if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE))
367 imp++;
368 362
369 /* discard rejected message if it shouldn't be returned to sender */ 363 /* discard rejected message if it shouldn't be returned to sender */
370 if (msg_errcode(msg) || msg_dest_droppable(msg)) {
371 buf_discard(buf);
372 return data_sz;
373 }
374 364
375 /* construct rejected message */ 365 if (WARN(!msg_isdata(msg),
376 if (msg_mcast(msg)) 366 "attempt to reject message with user=%u", msg_user(msg))) {
377 hdr_sz = MCAST_H_SIZE; 367 dump_stack();
378 else 368 goto exit;
379 hdr_sz = LONG_H_SIZE;
380 rbuf = tipc_buf_acquire(data_sz + hdr_sz);
381 if (rbuf == NULL) {
382 buf_discard(buf);
383 return data_sz;
384 } 369 }
370 if (msg_errcode(msg) || msg_dest_droppable(msg))
371 goto exit;
372
373 /*
374 * construct returned message by copying rejected message header and
375 * data (or subset), then updating header fields that need adjusting
376 */
377
378 hdr_sz = msg_hdr_sz(msg);
379 rmsg_sz = hdr_sz + min_t(u32, data_sz, MAX_REJECT_SIZE);
380
381 rbuf = tipc_buf_acquire(rmsg_sz);
382 if (rbuf == NULL)
383 goto exit;
384
385 rmsg = buf_msg(rbuf); 385 rmsg = buf_msg(rbuf);
386 tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); 386 skb_copy_to_linear_data(rbuf, msg, rmsg_sz);
387 msg_set_errcode(rmsg, err); 387
388 msg_set_destport(rmsg, msg_origport(msg)); 388 if (msg_connected(rmsg)) {
389 msg_set_origport(rmsg, msg_destport(msg)); 389 imp = msg_importance(rmsg);
390 if (msg_short(msg)) { 390 if (imp < TIPC_CRITICAL_IMPORTANCE)
391 msg_set_orignode(rmsg, tipc_own_addr); 391 msg_set_importance(rmsg, ++imp);
392 /* leave name type & instance as zeroes */
393 } else {
394 msg_set_orignode(rmsg, msg_destnode(msg));
395 msg_set_nametype(rmsg, msg_nametype(msg));
396 msg_set_nameinst(rmsg, msg_nameinst(msg));
397 } 392 }
398 msg_set_size(rmsg, data_sz + hdr_sz); 393 msg_set_non_seq(rmsg, 0);
399 skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz); 394 msg_set_size(rmsg, rmsg_sz);
395 msg_set_errcode(rmsg, err);
396 msg_set_prevnode(rmsg, tipc_own_addr);
397 msg_swap_words(rmsg, 4, 5);
398 if (!msg_short(rmsg))
399 msg_swap_words(rmsg, 6, 7);
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)) {
@@ -411,9 +411,15 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
411 tipc_net_route_msg(abuf); 411 tipc_net_route_msg(abuf);
412 } 412 }
413 413
414 /* send rejected message */ 414 /* send returned message & dispose of rejected message */
415
416 src_node = msg_prevnode(msg);
417 if (src_node == tipc_own_addr)
418 tipc_port_recv_msg(rbuf);
419 else
420 tipc_link_send(rbuf, src_node, msg_link_selector(rmsg));
421exit:
415 buf_discard(buf); 422 buf_discard(buf);
416 tipc_net_route_msg(rbuf);
417 return data_sz; 423 return data_sz;
418} 424}
419 425
@@ -449,14 +455,7 @@ static void port_timeout(unsigned long ref)
449 if (p_ptr->probing_state == PROBING) { 455 if (p_ptr->probing_state == PROBING) {
450 buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); 456 buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
451 } else { 457 } else {
452 buf = port_build_proto_msg(port_peerport(p_ptr), 458 buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0);
453 port_peernode(p_ptr),
454 p_ptr->ref,
455 tipc_own_addr,
456 CONN_MANAGER,
457 CONN_PROBE,
458 TIPC_OK,
459 0);
460 p_ptr->probing_state = PROBING; 459 p_ptr->probing_state = PROBING;
461 k_start_timer(&p_ptr->timer, p_ptr->probing_interval); 460 k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
462 } 461 }
@@ -480,100 +479,94 @@ static void port_handle_node_down(unsigned long ref)
480 479
481static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err) 480static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err)
482{ 481{
483 u32 imp = msg_importance(&p_ptr->phdr); 482 struct sk_buff *buf = port_build_peer_abort_msg(p_ptr, err);
484 483
485 if (!p_ptr->connected) 484 if (buf) {
486 return NULL; 485 struct tipc_msg *msg = buf_msg(buf);
487 if (imp < TIPC_CRITICAL_IMPORTANCE) 486 msg_swap_words(msg, 4, 5);
488 imp++; 487 msg_swap_words(msg, 6, 7);
489 return port_build_proto_msg(p_ptr->ref, 488 }
490 tipc_own_addr, 489 return buf;
491 port_peerport(p_ptr),
492 port_peernode(p_ptr),
493 imp,
494 TIPC_CONN_MSG,
495 err,
496 0);
497} 490}
498 491
499 492
500static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err) 493static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err)
501{ 494{
502 u32 imp = msg_importance(&p_ptr->phdr); 495 struct sk_buff *buf;
496 struct tipc_msg *msg;
497 u32 imp;
503 498
504 if (!p_ptr->connected) 499 if (!p_ptr->connected)
505 return NULL; 500 return NULL;
506 if (imp < TIPC_CRITICAL_IMPORTANCE) 501
507 imp++; 502 buf = tipc_buf_acquire(BASIC_H_SIZE);
508 return port_build_proto_msg(port_peerport(p_ptr), 503 if (buf) {
509 port_peernode(p_ptr), 504 msg = buf_msg(buf);
510 p_ptr->ref, 505 memcpy(msg, &p_ptr->phdr, BASIC_H_SIZE);
511 tipc_own_addr, 506 msg_set_hdr_sz(msg, BASIC_H_SIZE);
512 imp, 507 msg_set_size(msg, BASIC_H_SIZE);
513 TIPC_CONN_MSG, 508 imp = msg_importance(msg);
514 err, 509 if (imp < TIPC_CRITICAL_IMPORTANCE)
515 0); 510 msg_set_importance(msg, ++imp);
511 msg_set_errcode(msg, err);
512 }
513 return buf;
516} 514}
517 515
518void tipc_port_recv_proto_msg(struct sk_buff *buf) 516void tipc_port_recv_proto_msg(struct sk_buff *buf)
519{ 517{
520 struct tipc_msg *msg = buf_msg(buf); 518 struct tipc_msg *msg = buf_msg(buf);
521 struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); 519 struct tipc_port *p_ptr;
522 u32 err = TIPC_OK;
523 struct sk_buff *r_buf = NULL; 520 struct sk_buff *r_buf = NULL;
524 struct sk_buff *abort_buf = NULL; 521 u32 orignode = msg_orignode(msg);
525 522 u32 origport = msg_origport(msg);
526 if (!p_ptr) { 523 u32 destport = msg_destport(msg);
527 err = TIPC_ERR_NO_PORT; 524 int wakeable;
528 } else if (p_ptr->connected) { 525
529 if ((port_peernode(p_ptr) != msg_orignode(msg)) || 526 /* Validate connection */
530 (port_peerport(p_ptr) != msg_origport(msg))) { 527
531 err = TIPC_ERR_NO_PORT; 528 p_ptr = tipc_port_lock(destport);
532 } else if (msg_type(msg) == CONN_ACK) { 529 if (!p_ptr || !p_ptr->connected ||
533 int wakeup = tipc_port_congested(p_ptr) && 530 (port_peernode(p_ptr) != orignode) ||
534 p_ptr->congested && 531 (port_peerport(p_ptr) != origport)) {
535 p_ptr->wakeup; 532 r_buf = tipc_buf_acquire(BASIC_H_SIZE);
536 p_ptr->acked += msg_msgcnt(msg); 533 if (r_buf) {
537 if (tipc_port_congested(p_ptr)) 534 msg = buf_msg(r_buf);
538 goto exit; 535 tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG,
539 p_ptr->congested = 0; 536 BASIC_H_SIZE, orignode);
540 if (!wakeup) 537 msg_set_errcode(msg, TIPC_ERR_NO_PORT);
541 goto exit; 538 msg_set_origport(msg, destport);
542 p_ptr->wakeup(p_ptr); 539 msg_set_destport(msg, origport);
543 goto exit;
544 } 540 }
545 } else if (p_ptr->published) { 541 if (p_ptr)
546 err = TIPC_ERR_NO_PORT; 542 tipc_port_unlock(p_ptr);
547 }
548 if (err) {
549 r_buf = port_build_proto_msg(msg_origport(msg),
550 msg_orignode(msg),
551 msg_destport(msg),
552 tipc_own_addr,
553 TIPC_HIGH_IMPORTANCE,
554 TIPC_CONN_MSG,
555 err,
556 0);
557 goto exit; 543 goto exit;
558 } 544 }
559 545
560 /* All is fine */ 546 /* Process protocol message sent by peer */
561 if (msg_type(msg) == CONN_PROBE) { 547
562 r_buf = port_build_proto_msg(msg_origport(msg), 548 switch (msg_type(msg)) {
563 msg_orignode(msg), 549 case CONN_ACK:
564 msg_destport(msg), 550 wakeable = tipc_port_congested(p_ptr) && p_ptr->congested &&
565 tipc_own_addr, 551 p_ptr->wakeup;
566 CONN_MANAGER, 552 p_ptr->acked += msg_msgcnt(msg);
567 CONN_PROBE_REPLY, 553 if (!tipc_port_congested(p_ptr)) {
568 TIPC_OK, 554 p_ptr->congested = 0;
569 0); 555 if (wakeable)
556 p_ptr->wakeup(p_ptr);
557 }
558 break;
559 case CONN_PROBE:
560 r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0);
561 break;
562 default:
563 /* CONN_PROBE_REPLY or unrecognized - no action required */
564 break;
570 } 565 }
571 p_ptr->probing_state = CONFIRMED; 566 p_ptr->probing_state = CONFIRMED;
567 tipc_port_unlock(p_ptr);
572exit: 568exit:
573 if (p_ptr)
574 tipc_port_unlock(p_ptr);
575 tipc_net_route_msg(r_buf); 569 tipc_net_route_msg(r_buf);
576 tipc_net_route_msg(abort_buf);
577 buf_discard(buf); 570 buf_discard(buf);
578} 571}
579 572
@@ -889,14 +882,7 @@ void tipc_acknowledge(u32 ref, u32 ack)
889 return; 882 return;
890 if (p_ptr->connected) { 883 if (p_ptr->connected) {
891 p_ptr->conn_unacked -= ack; 884 p_ptr->conn_unacked -= ack;
892 buf = port_build_proto_msg(port_peerport(p_ptr), 885 buf = port_build_proto_msg(p_ptr, CONN_ACK, ack);
893 port_peernode(p_ptr),
894 ref,
895 tipc_own_addr,
896 CONN_MANAGER,
897 CONN_ACK,
898 TIPC_OK,
899 ack);
900 } 886 }
901 tipc_port_unlock(p_ptr); 887 tipc_port_unlock(p_ptr);
902 tipc_net_route_msg(buf); 888 tipc_net_route_msg(buf);
@@ -1140,19 +1126,7 @@ int tipc_shutdown(u32 ref)
1140 if (!p_ptr) 1126 if (!p_ptr)
1141 return -EINVAL; 1127 return -EINVAL;
1142 1128
1143 if (p_ptr->connected) { 1129 buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN);
1144 u32 imp = msg_importance(&p_ptr->phdr);
1145 if (imp < TIPC_CRITICAL_IMPORTANCE)
1146 imp++;
1147 buf = port_build_proto_msg(port_peerport(p_ptr),
1148 port_peernode(p_ptr),
1149 ref,
1150 tipc_own_addr,
1151 imp,
1152 TIPC_CONN_MSG,
1153 TIPC_CONN_SHUTDOWN,
1154 0);
1155 }
1156 tipc_port_unlock(p_ptr); 1130 tipc_port_unlock(p_ptr);
1157 tipc_net_route_msg(buf); 1131 tipc_net_route_msg(buf);
1158 return tipc_disconnect(ref); 1132 return tipc_disconnect(ref);
@@ -1238,7 +1212,7 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
1238 msg_set_type(msg, TIPC_NAMED_MSG); 1212 msg_set_type(msg, TIPC_NAMED_MSG);
1239 msg_set_orignode(msg, tipc_own_addr); 1213 msg_set_orignode(msg, tipc_own_addr);
1240 msg_set_origport(msg, ref); 1214 msg_set_origport(msg, ref);
1241 msg_set_hdr_sz(msg, LONG_H_SIZE); 1215 msg_set_hdr_sz(msg, NAMED_H_SIZE);
1242 msg_set_nametype(msg, name->type); 1216 msg_set_nametype(msg, name->type);
1243 msg_set_nameinst(msg, name->instance); 1217 msg_set_nameinst(msg, name->instance);
1244 msg_set_lookup_scope(msg, tipc_addr_scope(domain)); 1218 msg_set_lookup_scope(msg, tipc_addr_scope(domain));
@@ -1291,7 +1265,7 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest,
1291 msg_set_origport(msg, ref); 1265 msg_set_origport(msg, ref);
1292 msg_set_destnode(msg, dest->node); 1266 msg_set_destnode(msg, dest->node);
1293 msg_set_destport(msg, dest->ref); 1267 msg_set_destport(msg, dest->ref);
1294 msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); 1268 msg_set_hdr_sz(msg, BASIC_H_SIZE);
1295 1269
1296 if (dest->node == tipc_own_addr) 1270 if (dest->node == tipc_own_addr)
1297 res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, 1271 res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect,
@@ -1331,13 +1305,13 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
1331 msg_set_origport(msg, ref); 1305 msg_set_origport(msg, ref);
1332 msg_set_destnode(msg, dest->node); 1306 msg_set_destnode(msg, dest->node);
1333 msg_set_destport(msg, dest->ref); 1307 msg_set_destport(msg, dest->ref);
1334 msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); 1308 msg_set_hdr_sz(msg, BASIC_H_SIZE);
1335 msg_set_size(msg, DIR_MSG_H_SIZE + dsz); 1309 msg_set_size(msg, BASIC_H_SIZE + dsz);
1336 if (skb_cow(buf, DIR_MSG_H_SIZE)) 1310 if (skb_cow(buf, BASIC_H_SIZE))
1337 return -ENOMEM; 1311 return -ENOMEM;
1338 1312
1339 skb_push(buf, DIR_MSG_H_SIZE); 1313 skb_push(buf, BASIC_H_SIZE);
1340 skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE); 1314 skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE);
1341 1315
1342 if (dest->node == tipc_own_addr) 1316 if (dest->node == tipc_own_addr)
1343 res = tipc_port_recv_msg(buf); 1317 res = tipc_port_recv_msg(buf);