| .. | .. |
|---|
| 46 | 46 | #include "bcast.h" |
|---|
| 47 | 47 | #include "netlink.h" |
|---|
| 48 | 48 | #include "group.h" |
|---|
| 49 | +#include "trace.h" |
|---|
| 49 | 50 | |
|---|
| 50 | | -#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ |
|---|
| 51 | +#define NAGLE_START_INIT 4 |
|---|
| 52 | +#define NAGLE_START_MAX 1024 |
|---|
| 53 | +#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ |
|---|
| 51 | 54 | #define CONN_PROBING_INTV msecs_to_jiffies(3600000) /* [ms] => 1 h */ |
|---|
| 52 | | -#define TIPC_FWD_MSG 1 |
|---|
| 53 | 55 | #define TIPC_MAX_PORT 0xffffffff |
|---|
| 54 | 56 | #define TIPC_MIN_PORT 1 |
|---|
| 55 | | -#define TIPC_ACK_RATE 4 /* ACK at 1/4 of of rcv window size */ |
|---|
| 57 | +#define TIPC_ACK_RATE 4 /* ACK at 1/4 of rcv window size */ |
|---|
| 56 | 58 | |
|---|
| 57 | 59 | enum { |
|---|
| 58 | 60 | TIPC_LISTEN = TCP_LISTEN, |
|---|
| .. | .. |
|---|
| 74 | 76 | * @conn_instance: TIPC instance used when connection was established |
|---|
| 75 | 77 | * @published: non-zero if port has one or more associated names |
|---|
| 76 | 78 | * @max_pkt: maximum packet size "hint" used when building messages sent by port |
|---|
| 79 | + * @maxnagle: maximum size of msg which can be subject to nagle |
|---|
| 77 | 80 | * @portid: unique port identity in TIPC socket hash table |
|---|
| 78 | 81 | * @phdr: preformatted message header used when sending messages |
|---|
| 79 | 82 | * #cong_links: list of congested links |
|---|
| 80 | 83 | * @publications: list of publications for port |
|---|
| 81 | 84 | * @blocking_link: address of the congested link we are currently sleeping on |
|---|
| 82 | 85 | * @pub_count: total # of publications port has made during its lifetime |
|---|
| 83 | | - * @probing_state: |
|---|
| 84 | 86 | * @conn_timeout: the time we can wait for an unresponded setup request |
|---|
| 85 | 87 | * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue |
|---|
| 86 | 88 | * @cong_link_cnt: number of congested links |
|---|
| .. | .. |
|---|
| 97 | 99 | u32 conn_instance; |
|---|
| 98 | 100 | int published; |
|---|
| 99 | 101 | u32 max_pkt; |
|---|
| 102 | + u32 maxnagle; |
|---|
| 100 | 103 | u32 portid; |
|---|
| 101 | 104 | struct tipc_msg phdr; |
|---|
| 102 | 105 | struct list_head cong_links; |
|---|
| 103 | 106 | struct list_head publications; |
|---|
| 104 | 107 | u32 pub_count; |
|---|
| 105 | | - uint conn_timeout; |
|---|
| 106 | 108 | atomic_t dupl_rcvcnt; |
|---|
| 109 | + u16 conn_timeout; |
|---|
| 107 | 110 | bool probe_unacked; |
|---|
| 108 | 111 | u16 cong_link_cnt; |
|---|
| 109 | 112 | u16 snt_unacked; |
|---|
| .. | .. |
|---|
| 116 | 119 | struct tipc_mc_method mc_method; |
|---|
| 117 | 120 | struct rcu_head rcu; |
|---|
| 118 | 121 | struct tipc_group *group; |
|---|
| 122 | + u32 oneway; |
|---|
| 123 | + u32 nagle_start; |
|---|
| 124 | + u16 snd_backlog; |
|---|
| 125 | + u16 msg_acc; |
|---|
| 126 | + u16 pkt_cnt; |
|---|
| 127 | + bool expect_ack; |
|---|
| 128 | + bool nodelay; |
|---|
| 119 | 129 | bool group_is_open; |
|---|
| 120 | 130 | }; |
|---|
| 121 | 131 | |
|---|
| .. | .. |
|---|
| 137 | 147 | static void tipc_sk_remove(struct tipc_sock *tsk); |
|---|
| 138 | 148 | static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dsz); |
|---|
| 139 | 149 | static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz); |
|---|
| 150 | +static void tipc_sk_push_backlog(struct tipc_sock *tsk, bool nagle_ack); |
|---|
| 151 | +static int tipc_wait_for_connect(struct socket *sock, long *timeo_p); |
|---|
| 140 | 152 | |
|---|
| 141 | 153 | static const struct proto_ops packet_ops; |
|---|
| 142 | 154 | static const struct proto_ops stream_ops; |
|---|
| .. | .. |
|---|
| 184 | 196 | return msg_importance(&tsk->phdr); |
|---|
| 185 | 197 | } |
|---|
| 186 | 198 | |
|---|
| 187 | | -static int tsk_set_importance(struct tipc_sock *tsk, int imp) |
|---|
| 188 | | -{ |
|---|
| 189 | | - if (imp > TIPC_CRITICAL_IMPORTANCE) |
|---|
| 190 | | - return -EINVAL; |
|---|
| 191 | | - msg_set_importance(&tsk->phdr, (u32)imp); |
|---|
| 192 | | - return 0; |
|---|
| 193 | | -} |
|---|
| 194 | | - |
|---|
| 195 | 199 | static struct tipc_sock *tipc_sk(const struct sock *sk) |
|---|
| 196 | 200 | { |
|---|
| 197 | 201 | return container_of(sk, struct tipc_sock, sk); |
|---|
| 202 | +} |
|---|
| 203 | + |
|---|
| 204 | +int tsk_set_importance(struct sock *sk, int imp) |
|---|
| 205 | +{ |
|---|
| 206 | + if (imp > TIPC_CRITICAL_IMPORTANCE) |
|---|
| 207 | + return -EINVAL; |
|---|
| 208 | + msg_set_importance(&tipc_sk(sk)->phdr, (u32)imp); |
|---|
| 209 | + return 0; |
|---|
| 198 | 210 | } |
|---|
| 199 | 211 | |
|---|
| 200 | 212 | static bool tsk_conn_cong(struct tipc_sock *tsk) |
|---|
| .. | .. |
|---|
| 227 | 239 | return 1; |
|---|
| 228 | 240 | } |
|---|
| 229 | 241 | |
|---|
| 242 | +/* tsk_set_nagle - enable/disable nagle property by manipulating maxnagle |
|---|
| 243 | + */ |
|---|
| 244 | +static void tsk_set_nagle(struct tipc_sock *tsk) |
|---|
| 245 | +{ |
|---|
| 246 | + struct sock *sk = &tsk->sk; |
|---|
| 247 | + |
|---|
| 248 | + tsk->maxnagle = 0; |
|---|
| 249 | + if (sk->sk_type != SOCK_STREAM) |
|---|
| 250 | + return; |
|---|
| 251 | + if (tsk->nodelay) |
|---|
| 252 | + return; |
|---|
| 253 | + if (!(tsk->peer_caps & TIPC_NAGLE)) |
|---|
| 254 | + return; |
|---|
| 255 | + /* Limit node local buffer size to avoid receive queue overflow */ |
|---|
| 256 | + if (tsk->max_pkt == MAX_MSG_SIZE) |
|---|
| 257 | + tsk->maxnagle = 1500; |
|---|
| 258 | + else |
|---|
| 259 | + tsk->maxnagle = tsk->max_pkt; |
|---|
| 260 | +} |
|---|
| 261 | + |
|---|
| 230 | 262 | /** |
|---|
| 231 | 263 | * tsk_advance_rx_queue - discard first buffer in socket receive queue |
|---|
| 232 | 264 | * |
|---|
| .. | .. |
|---|
| 234 | 266 | */ |
|---|
| 235 | 267 | static void tsk_advance_rx_queue(struct sock *sk) |
|---|
| 236 | 268 | { |
|---|
| 269 | + trace_tipc_sk_advance_rx(sk, NULL, TIPC_DUMP_SK_RCVQ, " "); |
|---|
| 237 | 270 | kfree_skb(__skb_dequeue(&sk->sk_receive_queue)); |
|---|
| 238 | 271 | } |
|---|
| 239 | 272 | |
|---|
| .. | .. |
|---|
| 248 | 281 | if (!tipc_msg_reverse(onode, &skb, err)) |
|---|
| 249 | 282 | return; |
|---|
| 250 | 283 | |
|---|
| 284 | + trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_NONE, "@sk_respond!"); |
|---|
| 251 | 285 | dnode = msg_destnode(buf_msg(skb)); |
|---|
| 252 | 286 | selector = msg_origport(buf_msg(skb)); |
|---|
| 253 | 287 | tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector); |
|---|
| .. | .. |
|---|
| 258 | 292 | * |
|---|
| 259 | 293 | * Caller must hold socket lock |
|---|
| 260 | 294 | */ |
|---|
| 261 | | -static void tsk_rej_rx_queue(struct sock *sk) |
|---|
| 295 | +static void tsk_rej_rx_queue(struct sock *sk, int error) |
|---|
| 262 | 296 | { |
|---|
| 263 | 297 | struct sk_buff *skb; |
|---|
| 264 | 298 | |
|---|
| 265 | 299 | while ((skb = __skb_dequeue(&sk->sk_receive_queue))) |
|---|
| 266 | | - tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT); |
|---|
| 300 | + tipc_sk_respond(sk, skb, error); |
|---|
| 267 | 301 | } |
|---|
| 268 | 302 | |
|---|
| 269 | | -static bool tipc_sk_connected(struct sock *sk) |
|---|
| 303 | +static bool tipc_sk_connected(const struct sock *sk) |
|---|
| 270 | 304 | { |
|---|
| 271 | | - return sk->sk_state == TIPC_ESTABLISHED; |
|---|
| 305 | + return READ_ONCE(sk->sk_state) == TIPC_ESTABLISHED; |
|---|
| 272 | 306 | } |
|---|
| 273 | 307 | |
|---|
| 274 | 308 | /* tipc_sk_type_connectionless - check if the socket is datagram socket |
|---|
| .. | .. |
|---|
| 388 | 422 | rc_ = tipc_sk_sock_err((sock_), timeo_); \ |
|---|
| 389 | 423 | if (rc_) \ |
|---|
| 390 | 424 | break; \ |
|---|
| 391 | | - prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE); \ |
|---|
| 425 | + add_wait_queue(sk_sleep(sk_), &wait_); \ |
|---|
| 392 | 426 | release_sock(sk_); \ |
|---|
| 393 | 427 | *(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \ |
|---|
| 394 | 428 | sched_annotate_sleep(); \ |
|---|
| .. | .. |
|---|
| 444 | 478 | |
|---|
| 445 | 479 | tsk = tipc_sk(sk); |
|---|
| 446 | 480 | tsk->max_pkt = MAX_PKT_DEFAULT; |
|---|
| 481 | + tsk->maxnagle = 0; |
|---|
| 482 | + tsk->nagle_start = NAGLE_START_INIT; |
|---|
| 447 | 483 | INIT_LIST_HEAD(&tsk->publications); |
|---|
| 448 | 484 | INIT_LIST_HEAD(&tsk->cong_links); |
|---|
| 449 | 485 | msg = &tsk->phdr; |
|---|
| .. | .. |
|---|
| 453 | 489 | sock_init_data(sock, sk); |
|---|
| 454 | 490 | tipc_set_sk_state(sk, TIPC_OPEN); |
|---|
| 455 | 491 | if (tipc_sk_insert(tsk)) { |
|---|
| 492 | + sk_free(sk); |
|---|
| 456 | 493 | pr_warn("Socket create failed; port number exhausted\n"); |
|---|
| 457 | 494 | return -EINVAL; |
|---|
| 458 | 495 | } |
|---|
| .. | .. |
|---|
| 467 | 504 | timer_setup(&sk->sk_timer, tipc_sk_timeout, 0); |
|---|
| 468 | 505 | sk->sk_shutdown = 0; |
|---|
| 469 | 506 | sk->sk_backlog_rcv = tipc_sk_backlog_rcv; |
|---|
| 470 | | - sk->sk_rcvbuf = sysctl_tipc_rmem[1]; |
|---|
| 507 | + sk->sk_rcvbuf = READ_ONCE(sysctl_tipc_rmem[1]); |
|---|
| 471 | 508 | sk->sk_data_ready = tipc_data_ready; |
|---|
| 472 | 509 | sk->sk_write_space = tipc_write_space; |
|---|
| 473 | 510 | sk->sk_destruct = tipc_sock_destruct; |
|---|
| .. | .. |
|---|
| 484 | 521 | if (sock->type == SOCK_DGRAM) |
|---|
| 485 | 522 | tsk_set_unreliable(tsk, true); |
|---|
| 486 | 523 | } |
|---|
| 487 | | - |
|---|
| 524 | + __skb_queue_head_init(&tsk->mc_method.deferredq); |
|---|
| 525 | + trace_tipc_sk_create(sk, NULL, TIPC_DUMP_NONE, " "); |
|---|
| 488 | 526 | return 0; |
|---|
| 489 | 527 | } |
|---|
| 490 | 528 | |
|---|
| .. | .. |
|---|
| 509 | 547 | tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt && |
|---|
| 510 | 548 | !tsk_conn_cong(tsk))); |
|---|
| 511 | 549 | |
|---|
| 512 | | - /* Reject all unreceived messages, except on an active connection |
|---|
| 513 | | - * (which disconnects locally & sends a 'FIN+' to peer). |
|---|
| 514 | | - */ |
|---|
| 515 | | - while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) { |
|---|
| 516 | | - if (TIPC_SKB_CB(skb)->bytes_read) { |
|---|
| 517 | | - kfree_skb(skb); |
|---|
| 518 | | - continue; |
|---|
| 519 | | - } |
|---|
| 520 | | - if (!tipc_sk_type_connectionless(sk) && |
|---|
| 521 | | - sk->sk_state != TIPC_DISCONNECTING) { |
|---|
| 522 | | - tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 523 | | - tipc_node_remove_conn(net, dnode, tsk->portid); |
|---|
| 524 | | - } |
|---|
| 525 | | - tipc_sk_respond(sk, skb, error); |
|---|
| 550 | + /* Push out delayed messages if in Nagle mode */ |
|---|
| 551 | + tipc_sk_push_backlog(tsk, false); |
|---|
| 552 | + /* Remove pending SYN */ |
|---|
| 553 | + __skb_queue_purge(&sk->sk_write_queue); |
|---|
| 554 | + |
|---|
| 555 | + /* Remove partially received buffer if any */ |
|---|
| 556 | + skb = skb_peek(&sk->sk_receive_queue); |
|---|
| 557 | + if (skb && TIPC_SKB_CB(skb)->bytes_read) { |
|---|
| 558 | + __skb_unlink(skb, &sk->sk_receive_queue); |
|---|
| 559 | + kfree_skb(skb); |
|---|
| 526 | 560 | } |
|---|
| 527 | 561 | |
|---|
| 528 | | - if (tipc_sk_type_connectionless(sk)) |
|---|
| 562 | + /* Reject all unreceived messages if connectionless */ |
|---|
| 563 | + if (tipc_sk_type_connectionless(sk)) { |
|---|
| 564 | + tsk_rej_rx_queue(sk, error); |
|---|
| 529 | 565 | return; |
|---|
| 566 | + } |
|---|
| 530 | 567 | |
|---|
| 531 | | - if (sk->sk_state != TIPC_DISCONNECTING) { |
|---|
| 568 | + switch (sk->sk_state) { |
|---|
| 569 | + case TIPC_CONNECTING: |
|---|
| 570 | + case TIPC_ESTABLISHED: |
|---|
| 571 | + tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 572 | + tipc_node_remove_conn(net, dnode, tsk->portid); |
|---|
| 573 | + /* Send a FIN+/- to its peer */ |
|---|
| 574 | + skb = __skb_dequeue(&sk->sk_receive_queue); |
|---|
| 575 | + if (skb) { |
|---|
| 576 | + __skb_queue_purge(&sk->sk_receive_queue); |
|---|
| 577 | + tipc_sk_respond(sk, skb, error); |
|---|
| 578 | + break; |
|---|
| 579 | + } |
|---|
| 532 | 580 | skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, |
|---|
| 533 | 581 | TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode, |
|---|
| 534 | 582 | tsk_own_node(tsk), tsk_peer_port(tsk), |
|---|
| 535 | 583 | tsk->portid, error); |
|---|
| 536 | 584 | if (skb) |
|---|
| 537 | 585 | tipc_node_xmit_skb(net, skb, dnode, tsk->portid); |
|---|
| 538 | | - tipc_node_remove_conn(net, dnode, tsk->portid); |
|---|
| 539 | | - tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 586 | + break; |
|---|
| 587 | + case TIPC_LISTEN: |
|---|
| 588 | + /* Reject all SYN messages */ |
|---|
| 589 | + tsk_rej_rx_queue(sk, error); |
|---|
| 590 | + break; |
|---|
| 591 | + default: |
|---|
| 592 | + __skb_queue_purge(&sk->sk_receive_queue); |
|---|
| 593 | + break; |
|---|
| 540 | 594 | } |
|---|
| 541 | 595 | } |
|---|
| 542 | 596 | |
|---|
| .. | .. |
|---|
| 571 | 625 | tsk = tipc_sk(sk); |
|---|
| 572 | 626 | lock_sock(sk); |
|---|
| 573 | 627 | |
|---|
| 628 | + trace_tipc_sk_release(sk, NULL, TIPC_DUMP_ALL, " "); |
|---|
| 574 | 629 | __tipc_shutdown(sock, TIPC_ERR_NO_PORT); |
|---|
| 575 | 630 | sk->sk_shutdown = SHUTDOWN_MASK; |
|---|
| 576 | 631 | tipc_sk_leave(tsk); |
|---|
| 577 | 632 | tipc_sk_withdraw(tsk, 0, NULL); |
|---|
| 633 | + __skb_queue_purge(&tsk->mc_method.deferredq); |
|---|
| 578 | 634 | sk_stop_timer(sk, &sk->sk_timer); |
|---|
| 579 | 635 | tipc_sk_remove(tsk); |
|---|
| 580 | 636 | |
|---|
| .. | .. |
|---|
| 656 | 712 | * tipc_getname - get port ID of socket or peer socket |
|---|
| 657 | 713 | * @sock: socket structure |
|---|
| 658 | 714 | * @uaddr: area for returned socket address |
|---|
| 659 | | - * @uaddr_len: area for returned length of socket address |
|---|
| 660 | 715 | * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID |
|---|
| 661 | 716 | * |
|---|
| 662 | 717 | * Returns 0 on success, errno otherwise |
|---|
| .. | .. |
|---|
| 718 | 773 | __poll_t revents = 0; |
|---|
| 719 | 774 | |
|---|
| 720 | 775 | sock_poll_wait(file, sock, wait); |
|---|
| 776 | + trace_tipc_sk_poll(sk, NULL, TIPC_DUMP_ALL, " "); |
|---|
| 721 | 777 | |
|---|
| 722 | 778 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
|---|
| 723 | 779 | revents |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM; |
|---|
| .. | .. |
|---|
| 728 | 784 | case TIPC_ESTABLISHED: |
|---|
| 729 | 785 | if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk)) |
|---|
| 730 | 786 | revents |= EPOLLOUT; |
|---|
| 731 | | - /* fall thru' */ |
|---|
| 787 | + fallthrough; |
|---|
| 732 | 788 | case TIPC_LISTEN: |
|---|
| 733 | 789 | case TIPC_CONNECTING: |
|---|
| 734 | 790 | if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) |
|---|
| .. | .. |
|---|
| 804 | 860 | rc = tipc_msg_build(hdr, msg, 0, dlen, mtu, &pkts); |
|---|
| 805 | 861 | |
|---|
| 806 | 862 | /* Send message if build was successful */ |
|---|
| 807 | | - if (unlikely(rc == dlen)) |
|---|
| 863 | + if (unlikely(rc == dlen)) { |
|---|
| 864 | + trace_tipc_sk_sendmcast(sk, skb_peek(&pkts), |
|---|
| 865 | + TIPC_DUMP_SK_SNDQ, " "); |
|---|
| 808 | 866 | rc = tipc_mcast_xmit(net, &pkts, method, &dsts, |
|---|
| 809 | 867 | &tsk->cong_link_cnt); |
|---|
| 868 | + } |
|---|
| 810 | 869 | |
|---|
| 811 | 870 | tipc_nlist_purge(&dsts); |
|---|
| 812 | 871 | |
|---|
| .. | .. |
|---|
| 842 | 901 | |
|---|
| 843 | 902 | /* Build message as chain of buffers */ |
|---|
| 844 | 903 | __skb_queue_head_init(&pkts); |
|---|
| 845 | | - mtu = tipc_node_get_mtu(net, dnode, tsk->portid); |
|---|
| 904 | + mtu = tipc_node_get_mtu(net, dnode, tsk->portid, false); |
|---|
| 846 | 905 | rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts); |
|---|
| 847 | 906 | if (unlikely(rc != dlen)) |
|---|
| 848 | 907 | return rc; |
|---|
| .. | .. |
|---|
| 994 | 1053 | |
|---|
| 995 | 1054 | /** |
|---|
| 996 | 1055 | * tipc_send_group_bcast - send message to all members in communication group |
|---|
| 997 | | - * @sk: socket structure |
|---|
| 1056 | + * @sock: socket structure |
|---|
| 998 | 1057 | * @m: message to send |
|---|
| 999 | 1058 | * @dlen: total length of message data |
|---|
| 1000 | 1059 | * @timeout: timeout to wait for wakeup |
|---|
| .. | .. |
|---|
| 1199 | 1258 | tipc_sk_rcv(net, inputq); |
|---|
| 1200 | 1259 | } |
|---|
| 1201 | 1260 | |
|---|
| 1261 | +/* tipc_sk_push_backlog(): send accumulated buffers in socket write queue |
|---|
| 1262 | + * when socket is in Nagle mode |
|---|
| 1263 | + */ |
|---|
| 1264 | +static void tipc_sk_push_backlog(struct tipc_sock *tsk, bool nagle_ack) |
|---|
| 1265 | +{ |
|---|
| 1266 | + struct sk_buff_head *txq = &tsk->sk.sk_write_queue; |
|---|
| 1267 | + struct sk_buff *skb = skb_peek_tail(txq); |
|---|
| 1268 | + struct net *net = sock_net(&tsk->sk); |
|---|
| 1269 | + u32 dnode = tsk_peer_node(tsk); |
|---|
| 1270 | + int rc; |
|---|
| 1271 | + |
|---|
| 1272 | + if (nagle_ack) { |
|---|
| 1273 | + tsk->pkt_cnt += skb_queue_len(txq); |
|---|
| 1274 | + if (!tsk->pkt_cnt || tsk->msg_acc / tsk->pkt_cnt < 2) { |
|---|
| 1275 | + tsk->oneway = 0; |
|---|
| 1276 | + if (tsk->nagle_start < NAGLE_START_MAX) |
|---|
| 1277 | + tsk->nagle_start *= 2; |
|---|
| 1278 | + tsk->expect_ack = false; |
|---|
| 1279 | + pr_debug("tsk %10u: bad nagle %u -> %u, next start %u!\n", |
|---|
| 1280 | + tsk->portid, tsk->msg_acc, tsk->pkt_cnt, |
|---|
| 1281 | + tsk->nagle_start); |
|---|
| 1282 | + } else { |
|---|
| 1283 | + tsk->nagle_start = NAGLE_START_INIT; |
|---|
| 1284 | + if (skb) { |
|---|
| 1285 | + msg_set_ack_required(buf_msg(skb)); |
|---|
| 1286 | + tsk->expect_ack = true; |
|---|
| 1287 | + } else { |
|---|
| 1288 | + tsk->expect_ack = false; |
|---|
| 1289 | + } |
|---|
| 1290 | + } |
|---|
| 1291 | + tsk->msg_acc = 0; |
|---|
| 1292 | + tsk->pkt_cnt = 0; |
|---|
| 1293 | + } |
|---|
| 1294 | + |
|---|
| 1295 | + if (!skb || tsk->cong_link_cnt) |
|---|
| 1296 | + return; |
|---|
| 1297 | + |
|---|
| 1298 | + /* Do not send SYN again after congestion */ |
|---|
| 1299 | + if (msg_is_syn(buf_msg(skb))) |
|---|
| 1300 | + return; |
|---|
| 1301 | + |
|---|
| 1302 | + if (tsk->msg_acc) |
|---|
| 1303 | + tsk->pkt_cnt += skb_queue_len(txq); |
|---|
| 1304 | + tsk->snt_unacked += tsk->snd_backlog; |
|---|
| 1305 | + tsk->snd_backlog = 0; |
|---|
| 1306 | + rc = tipc_node_xmit(net, txq, dnode, tsk->portid); |
|---|
| 1307 | + if (rc == -ELINKCONG) |
|---|
| 1308 | + tsk->cong_link_cnt = 1; |
|---|
| 1309 | +} |
|---|
| 1310 | + |
|---|
| 1202 | 1311 | /** |
|---|
| 1203 | 1312 | * tipc_sk_conn_proto_rcv - receive a connection mng protocol message |
|---|
| 1204 | 1313 | * @tsk: receiving socket |
|---|
| .. | .. |
|---|
| 1212 | 1321 | u32 onode = tsk_own_node(tsk); |
|---|
| 1213 | 1322 | struct sock *sk = &tsk->sk; |
|---|
| 1214 | 1323 | int mtyp = msg_type(hdr); |
|---|
| 1215 | | - bool conn_cong; |
|---|
| 1324 | + bool was_cong; |
|---|
| 1216 | 1325 | |
|---|
| 1217 | 1326 | /* Ignore if connection cannot be validated: */ |
|---|
| 1218 | | - if (!tsk_peer_msg(tsk, hdr)) |
|---|
| 1327 | + if (!tsk_peer_msg(tsk, hdr)) { |
|---|
| 1328 | + trace_tipc_sk_drop_msg(sk, skb, TIPC_DUMP_NONE, "@proto_rcv!"); |
|---|
| 1219 | 1329 | goto exit; |
|---|
| 1330 | + } |
|---|
| 1220 | 1331 | |
|---|
| 1221 | 1332 | if (unlikely(msg_errcode(hdr))) { |
|---|
| 1222 | 1333 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| .. | .. |
|---|
| 1243 | 1354 | __skb_queue_tail(xmitq, skb); |
|---|
| 1244 | 1355 | return; |
|---|
| 1245 | 1356 | } else if (mtyp == CONN_ACK) { |
|---|
| 1246 | | - conn_cong = tsk_conn_cong(tsk); |
|---|
| 1357 | + was_cong = tsk_conn_cong(tsk); |
|---|
| 1358 | + tipc_sk_push_backlog(tsk, msg_nagle_ack(hdr)); |
|---|
| 1247 | 1359 | tsk->snt_unacked -= msg_conn_ack(hdr); |
|---|
| 1248 | 1360 | if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL) |
|---|
| 1249 | 1361 | tsk->snd_win = msg_adv_win(hdr); |
|---|
| 1250 | | - if (conn_cong) |
|---|
| 1362 | + if (was_cong && !tsk_conn_cong(tsk)) |
|---|
| 1251 | 1363 | sk->sk_write_space(sk); |
|---|
| 1252 | 1364 | } else if (mtyp != CONN_PROBE_REPLY) { |
|---|
| 1253 | 1365 | pr_warn("Received unknown CONN_PROTO msg\n"); |
|---|
| .. | .. |
|---|
| 1295 | 1407 | struct tipc_msg *hdr = &tsk->phdr; |
|---|
| 1296 | 1408 | struct tipc_name_seq *seq; |
|---|
| 1297 | 1409 | struct sk_buff_head pkts; |
|---|
| 1298 | | - u32 dport, dnode = 0; |
|---|
| 1299 | | - u32 type, inst; |
|---|
| 1410 | + u32 dport = 0, dnode = 0; |
|---|
| 1411 | + u32 type = 0, inst = 0; |
|---|
| 1300 | 1412 | int mtu, rc; |
|---|
| 1301 | 1413 | |
|---|
| 1302 | 1414 | if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE)) |
|---|
| .. | .. |
|---|
| 1338 | 1450 | tsk->conn_type = dest->addr.name.name.type; |
|---|
| 1339 | 1451 | tsk->conn_instance = dest->addr.name.name.instance; |
|---|
| 1340 | 1452 | } |
|---|
| 1453 | + msg_set_syn(hdr, 1); |
|---|
| 1341 | 1454 | } |
|---|
| 1342 | 1455 | |
|---|
| 1343 | 1456 | seq = &dest->addr.nameseq; |
|---|
| .. | .. |
|---|
| 1348 | 1461 | type = dest->addr.name.name.type; |
|---|
| 1349 | 1462 | inst = dest->addr.name.name.instance; |
|---|
| 1350 | 1463 | dnode = dest->addr.name.domain; |
|---|
| 1351 | | - msg_set_type(hdr, TIPC_NAMED_MSG); |
|---|
| 1352 | | - msg_set_hdr_sz(hdr, NAMED_H_SIZE); |
|---|
| 1353 | | - msg_set_nametype(hdr, type); |
|---|
| 1354 | | - msg_set_nameinst(hdr, inst); |
|---|
| 1355 | | - msg_set_lookup_scope(hdr, tipc_node2scope(dnode)); |
|---|
| 1356 | 1464 | dport = tipc_nametbl_translate(net, type, inst, &dnode); |
|---|
| 1357 | | - msg_set_destnode(hdr, dnode); |
|---|
| 1358 | | - msg_set_destport(hdr, dport); |
|---|
| 1359 | 1465 | if (unlikely(!dport && !dnode)) |
|---|
| 1360 | 1466 | return -EHOSTUNREACH; |
|---|
| 1361 | 1467 | } else if (dest->addrtype == TIPC_ADDR_ID) { |
|---|
| 1362 | 1468 | dnode = dest->addr.id.node; |
|---|
| 1363 | | - msg_set_type(hdr, TIPC_DIRECT_MSG); |
|---|
| 1364 | | - msg_set_lookup_scope(hdr, 0); |
|---|
| 1365 | | - msg_set_destnode(hdr, dnode); |
|---|
| 1366 | | - msg_set_destport(hdr, dest->addr.id.ref); |
|---|
| 1367 | | - msg_set_hdr_sz(hdr, BASIC_H_SIZE); |
|---|
| 1368 | 1469 | } else { |
|---|
| 1369 | 1470 | return -EINVAL; |
|---|
| 1370 | 1471 | } |
|---|
| .. | .. |
|---|
| 1375 | 1476 | if (unlikely(rc)) |
|---|
| 1376 | 1477 | return rc; |
|---|
| 1377 | 1478 | |
|---|
| 1479 | + if (dest->addrtype == TIPC_ADDR_NAME) { |
|---|
| 1480 | + msg_set_type(hdr, TIPC_NAMED_MSG); |
|---|
| 1481 | + msg_set_hdr_sz(hdr, NAMED_H_SIZE); |
|---|
| 1482 | + msg_set_nametype(hdr, type); |
|---|
| 1483 | + msg_set_nameinst(hdr, inst); |
|---|
| 1484 | + msg_set_lookup_scope(hdr, tipc_node2scope(dnode)); |
|---|
| 1485 | + msg_set_destnode(hdr, dnode); |
|---|
| 1486 | + msg_set_destport(hdr, dport); |
|---|
| 1487 | + } else { /* TIPC_ADDR_ID */ |
|---|
| 1488 | + msg_set_type(hdr, TIPC_DIRECT_MSG); |
|---|
| 1489 | + msg_set_lookup_scope(hdr, 0); |
|---|
| 1490 | + msg_set_destnode(hdr, dnode); |
|---|
| 1491 | + msg_set_destport(hdr, dest->addr.id.ref); |
|---|
| 1492 | + msg_set_hdr_sz(hdr, BASIC_H_SIZE); |
|---|
| 1493 | + } |
|---|
| 1494 | + |
|---|
| 1378 | 1495 | __skb_queue_head_init(&pkts); |
|---|
| 1379 | | - mtu = tipc_node_get_mtu(net, dnode, tsk->portid); |
|---|
| 1496 | + mtu = tipc_node_get_mtu(net, dnode, tsk->portid, true); |
|---|
| 1380 | 1497 | rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts); |
|---|
| 1381 | 1498 | if (unlikely(rc != dlen)) |
|---|
| 1382 | 1499 | return rc; |
|---|
| 1500 | + if (unlikely(syn && !tipc_msg_skb_clone(&pkts, &sk->sk_write_queue))) { |
|---|
| 1501 | + __skb_queue_purge(&pkts); |
|---|
| 1502 | + return -ENOMEM; |
|---|
| 1503 | + } |
|---|
| 1383 | 1504 | |
|---|
| 1505 | + trace_tipc_sk_sendmsg(sk, skb_peek(&pkts), TIPC_DUMP_SK_SNDQ, " "); |
|---|
| 1384 | 1506 | rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid); |
|---|
| 1385 | 1507 | if (unlikely(rc == -ELINKCONG)) { |
|---|
| 1386 | 1508 | tipc_dest_push(clinks, dnode, 0); |
|---|
| .. | .. |
|---|
| 1388 | 1510 | rc = 0; |
|---|
| 1389 | 1511 | } |
|---|
| 1390 | 1512 | |
|---|
| 1391 | | - if (unlikely(syn && !rc)) |
|---|
| 1513 | + if (unlikely(syn && !rc)) { |
|---|
| 1392 | 1514 | tipc_set_sk_state(sk, TIPC_CONNECTING); |
|---|
| 1515 | + if (dlen && timeout) { |
|---|
| 1516 | + timeout = msecs_to_jiffies(timeout); |
|---|
| 1517 | + tipc_wait_for_connect(sock, &timeout); |
|---|
| 1518 | + } |
|---|
| 1519 | + } |
|---|
| 1393 | 1520 | |
|---|
| 1394 | 1521 | return rc ? rc : dlen; |
|---|
| 1395 | 1522 | } |
|---|
| .. | .. |
|---|
| 1422 | 1549 | struct sock *sk = sock->sk; |
|---|
| 1423 | 1550 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
|---|
| 1424 | 1551 | long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
|---|
| 1552 | + struct sk_buff_head *txq = &sk->sk_write_queue; |
|---|
| 1425 | 1553 | struct tipc_sock *tsk = tipc_sk(sk); |
|---|
| 1426 | 1554 | struct tipc_msg *hdr = &tsk->phdr; |
|---|
| 1427 | 1555 | struct net *net = sock_net(sk); |
|---|
| 1428 | | - struct sk_buff_head pkts; |
|---|
| 1556 | + struct sk_buff *skb; |
|---|
| 1429 | 1557 | u32 dnode = tsk_peer_node(tsk); |
|---|
| 1558 | + int maxnagle = tsk->maxnagle; |
|---|
| 1559 | + int maxpkt = tsk->max_pkt; |
|---|
| 1430 | 1560 | int send, sent = 0; |
|---|
| 1431 | | - int rc = 0; |
|---|
| 1432 | | - |
|---|
| 1433 | | - __skb_queue_head_init(&pkts); |
|---|
| 1561 | + int blocks, rc = 0; |
|---|
| 1434 | 1562 | |
|---|
| 1435 | 1563 | if (unlikely(dlen > INT_MAX)) |
|---|
| 1436 | 1564 | return -EMSGSIZE; |
|---|
| 1437 | 1565 | |
|---|
| 1438 | 1566 | /* Handle implicit connection setup */ |
|---|
| 1439 | | - if (unlikely(dest)) { |
|---|
| 1567 | + if (unlikely(dest && sk->sk_state == TIPC_OPEN)) { |
|---|
| 1440 | 1568 | rc = __tipc_sendmsg(sock, m, dlen); |
|---|
| 1441 | 1569 | if (dlen && dlen == rc) { |
|---|
| 1442 | 1570 | tsk->peer_caps = tipc_node_get_capabilities(net, dnode); |
|---|
| .. | .. |
|---|
| 1452 | 1580 | tipc_sk_connected(sk))); |
|---|
| 1453 | 1581 | if (unlikely(rc)) |
|---|
| 1454 | 1582 | break; |
|---|
| 1455 | | - |
|---|
| 1456 | 1583 | send = min_t(size_t, dlen - sent, TIPC_MAX_USER_MSG_SIZE); |
|---|
| 1457 | | - rc = tipc_msg_build(hdr, m, sent, send, tsk->max_pkt, &pkts); |
|---|
| 1458 | | - if (unlikely(rc != send)) |
|---|
| 1459 | | - break; |
|---|
| 1460 | | - |
|---|
| 1461 | | - rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid); |
|---|
| 1584 | + blocks = tsk->snd_backlog; |
|---|
| 1585 | + if (tsk->oneway++ >= tsk->nagle_start && maxnagle && |
|---|
| 1586 | + send <= maxnagle) { |
|---|
| 1587 | + rc = tipc_msg_append(hdr, m, send, maxnagle, txq); |
|---|
| 1588 | + if (unlikely(rc < 0)) |
|---|
| 1589 | + break; |
|---|
| 1590 | + blocks += rc; |
|---|
| 1591 | + tsk->msg_acc++; |
|---|
| 1592 | + if (blocks <= 64 && tsk->expect_ack) { |
|---|
| 1593 | + tsk->snd_backlog = blocks; |
|---|
| 1594 | + sent += send; |
|---|
| 1595 | + break; |
|---|
| 1596 | + } else if (blocks > 64) { |
|---|
| 1597 | + tsk->pkt_cnt += skb_queue_len(txq); |
|---|
| 1598 | + } else { |
|---|
| 1599 | + skb = skb_peek_tail(txq); |
|---|
| 1600 | + if (skb) { |
|---|
| 1601 | + msg_set_ack_required(buf_msg(skb)); |
|---|
| 1602 | + tsk->expect_ack = true; |
|---|
| 1603 | + } else { |
|---|
| 1604 | + tsk->expect_ack = false; |
|---|
| 1605 | + } |
|---|
| 1606 | + tsk->msg_acc = 0; |
|---|
| 1607 | + tsk->pkt_cnt = 0; |
|---|
| 1608 | + } |
|---|
| 1609 | + } else { |
|---|
| 1610 | + rc = tipc_msg_build(hdr, m, sent, send, maxpkt, txq); |
|---|
| 1611 | + if (unlikely(rc != send)) |
|---|
| 1612 | + break; |
|---|
| 1613 | + blocks += tsk_inc(tsk, send + MIN_H_SIZE); |
|---|
| 1614 | + } |
|---|
| 1615 | + trace_tipc_sk_sendstream(sk, skb_peek(txq), |
|---|
| 1616 | + TIPC_DUMP_SK_SNDQ, " "); |
|---|
| 1617 | + rc = tipc_node_xmit(net, txq, dnode, tsk->portid); |
|---|
| 1462 | 1618 | if (unlikely(rc == -ELINKCONG)) { |
|---|
| 1463 | 1619 | tsk->cong_link_cnt = 1; |
|---|
| 1464 | 1620 | rc = 0; |
|---|
| 1465 | 1621 | } |
|---|
| 1466 | 1622 | if (likely(!rc)) { |
|---|
| 1467 | | - tsk->snt_unacked += tsk_inc(tsk, send + MIN_H_SIZE); |
|---|
| 1623 | + tsk->snt_unacked += blocks; |
|---|
| 1624 | + tsk->snd_backlog = 0; |
|---|
| 1468 | 1625 | sent += send; |
|---|
| 1469 | 1626 | } |
|---|
| 1470 | 1627 | } while (sent < dlen && !rc); |
|---|
| .. | .. |
|---|
| 1499 | 1656 | struct net *net = sock_net(sk); |
|---|
| 1500 | 1657 | struct tipc_msg *msg = &tsk->phdr; |
|---|
| 1501 | 1658 | |
|---|
| 1659 | + msg_set_syn(msg, 0); |
|---|
| 1502 | 1660 | msg_set_destnode(msg, peer_node); |
|---|
| 1503 | 1661 | msg_set_destport(msg, peer_port); |
|---|
| 1504 | 1662 | msg_set_type(msg, TIPC_CONN_MSG); |
|---|
| .. | .. |
|---|
| 1508 | 1666 | sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTV); |
|---|
| 1509 | 1667 | tipc_set_sk_state(sk, TIPC_ESTABLISHED); |
|---|
| 1510 | 1668 | tipc_node_add_conn(net, peer_node, tsk->portid, peer_port); |
|---|
| 1511 | | - tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid); |
|---|
| 1669 | + tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid, true); |
|---|
| 1512 | 1670 | tsk->peer_caps = tipc_node_get_capabilities(net, peer_node); |
|---|
| 1671 | + tsk_set_nagle(tsk); |
|---|
| 1672 | + __skb_queue_purge(&sk->sk_write_queue); |
|---|
| 1513 | 1673 | if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL) |
|---|
| 1514 | 1674 | return; |
|---|
| 1515 | 1675 | |
|---|
| .. | .. |
|---|
| 1521 | 1681 | /** |
|---|
| 1522 | 1682 | * tipc_sk_set_orig_addr - capture sender's address for received message |
|---|
| 1523 | 1683 | * @m: descriptor for message info |
|---|
| 1524 | | - * @hdr: received message header |
|---|
| 1684 | + * @skb: received message |
|---|
| 1525 | 1685 | * |
|---|
| 1526 | 1686 | * Note: Address is not captured if not requested by receiver. |
|---|
| 1527 | 1687 | */ |
|---|
| .. | .. |
|---|
| 1630 | 1790 | return 0; |
|---|
| 1631 | 1791 | } |
|---|
| 1632 | 1792 | |
|---|
| 1633 | | -static void tipc_sk_send_ack(struct tipc_sock *tsk) |
|---|
| 1793 | +static struct sk_buff *tipc_sk_build_ack(struct tipc_sock *tsk) |
|---|
| 1634 | 1794 | { |
|---|
| 1635 | 1795 | struct sock *sk = &tsk->sk; |
|---|
| 1636 | | - struct net *net = sock_net(sk); |
|---|
| 1637 | 1796 | struct sk_buff *skb = NULL; |
|---|
| 1638 | 1797 | struct tipc_msg *msg; |
|---|
| 1639 | 1798 | u32 peer_port = tsk_peer_port(tsk); |
|---|
| 1640 | 1799 | u32 dnode = tsk_peer_node(tsk); |
|---|
| 1641 | 1800 | |
|---|
| 1642 | 1801 | if (!tipc_sk_connected(sk)) |
|---|
| 1643 | | - return; |
|---|
| 1802 | + return NULL; |
|---|
| 1644 | 1803 | skb = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0, |
|---|
| 1645 | 1804 | dnode, tsk_own_node(tsk), peer_port, |
|---|
| 1646 | 1805 | tsk->portid, TIPC_OK); |
|---|
| 1647 | 1806 | if (!skb) |
|---|
| 1648 | | - return; |
|---|
| 1807 | + return NULL; |
|---|
| 1649 | 1808 | msg = buf_msg(skb); |
|---|
| 1650 | 1809 | msg_set_conn_ack(msg, tsk->rcv_unacked); |
|---|
| 1651 | 1810 | tsk->rcv_unacked = 0; |
|---|
| .. | .. |
|---|
| 1655 | 1814 | tsk->rcv_win = tsk_adv_blocks(tsk->sk.sk_rcvbuf); |
|---|
| 1656 | 1815 | msg_set_adv_win(msg, tsk->rcv_win); |
|---|
| 1657 | 1816 | } |
|---|
| 1658 | | - tipc_node_xmit_skb(net, skb, dnode, msg_link_selector(msg)); |
|---|
| 1817 | + return skb; |
|---|
| 1818 | +} |
|---|
| 1819 | + |
|---|
| 1820 | +static void tipc_sk_send_ack(struct tipc_sock *tsk) |
|---|
| 1821 | +{ |
|---|
| 1822 | + struct sk_buff *skb; |
|---|
| 1823 | + |
|---|
| 1824 | + skb = tipc_sk_build_ack(tsk); |
|---|
| 1825 | + if (!skb) |
|---|
| 1826 | + return; |
|---|
| 1827 | + |
|---|
| 1828 | + tipc_node_xmit_skb(sock_net(&tsk->sk), skb, tsk_peer_node(tsk), |
|---|
| 1829 | + msg_link_selector(buf_msg(skb))); |
|---|
| 1659 | 1830 | } |
|---|
| 1660 | 1831 | |
|---|
| 1661 | 1832 | static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) |
|---|
| 1662 | 1833 | { |
|---|
| 1663 | 1834 | struct sock *sk = sock->sk; |
|---|
| 1664 | | - DEFINE_WAIT(wait); |
|---|
| 1835 | + DEFINE_WAIT_FUNC(wait, woken_wake_function); |
|---|
| 1665 | 1836 | long timeo = *timeop; |
|---|
| 1666 | 1837 | int err = sock_error(sk); |
|---|
| 1667 | 1838 | |
|---|
| .. | .. |
|---|
| 1669 | 1840 | return err; |
|---|
| 1670 | 1841 | |
|---|
| 1671 | 1842 | for (;;) { |
|---|
| 1672 | | - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
|---|
| 1673 | 1843 | if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
|---|
| 1674 | 1844 | if (sk->sk_shutdown & RCV_SHUTDOWN) { |
|---|
| 1675 | 1845 | err = -ENOTCONN; |
|---|
| 1676 | 1846 | break; |
|---|
| 1677 | 1847 | } |
|---|
| 1848 | + add_wait_queue(sk_sleep(sk), &wait); |
|---|
| 1678 | 1849 | release_sock(sk); |
|---|
| 1679 | | - timeo = schedule_timeout(timeo); |
|---|
| 1850 | + timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); |
|---|
| 1851 | + sched_annotate_sleep(); |
|---|
| 1680 | 1852 | lock_sock(sk); |
|---|
| 1853 | + remove_wait_queue(sk_sleep(sk), &wait); |
|---|
| 1681 | 1854 | } |
|---|
| 1682 | 1855 | err = 0; |
|---|
| 1683 | 1856 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
|---|
| .. | .. |
|---|
| 1693 | 1866 | if (err) |
|---|
| 1694 | 1867 | break; |
|---|
| 1695 | 1868 | } |
|---|
| 1696 | | - finish_wait(sk_sleep(sk), &wait); |
|---|
| 1697 | 1869 | *timeop = timeo; |
|---|
| 1698 | 1870 | return err; |
|---|
| 1699 | 1871 | } |
|---|
| .. | .. |
|---|
| 1919 | 2091 | |
|---|
| 1920 | 2092 | /* Send connection flow control advertisement when applicable */ |
|---|
| 1921 | 2093 | tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen); |
|---|
| 1922 | | - if (unlikely(tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE)) |
|---|
| 2094 | + if (tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE) |
|---|
| 1923 | 2095 | tipc_sk_send_ack(tsk); |
|---|
| 1924 | 2096 | |
|---|
| 1925 | 2097 | /* Exit if all requested data or FIN/error received */ |
|---|
| .. | .. |
|---|
| 1951 | 2123 | /** |
|---|
| 1952 | 2124 | * tipc_data_ready - wake up threads to indicate messages have been received |
|---|
| 1953 | 2125 | * @sk: socket |
|---|
| 1954 | | - * @len: the length of messages |
|---|
| 1955 | 2126 | */ |
|---|
| 1956 | 2127 | static void tipc_data_ready(struct sock *sk) |
|---|
| 1957 | 2128 | { |
|---|
| .. | .. |
|---|
| 1990 | 2161 | smp_wmb(); |
|---|
| 1991 | 2162 | tsk->cong_link_cnt--; |
|---|
| 1992 | 2163 | wakeup = true; |
|---|
| 2164 | + tipc_sk_push_backlog(tsk, false); |
|---|
| 1993 | 2165 | break; |
|---|
| 1994 | 2166 | case GROUP_PROTOCOL: |
|---|
| 1995 | 2167 | tipc_group_proto_rcv(grp, &wakeup, hdr, inputq, xmitq); |
|---|
| .. | .. |
|---|
| 2009 | 2181 | } |
|---|
| 2010 | 2182 | |
|---|
| 2011 | 2183 | /** |
|---|
| 2012 | | - * tipc_filter_connect - Handle incoming message for a connection-based socket |
|---|
| 2184 | + * tipc_sk_filter_connect - check incoming message for a connection-based socket |
|---|
| 2013 | 2185 | * @tsk: TIPC socket |
|---|
| 2014 | | - * @skb: pointer to message buffer. Set to NULL if buffer is consumed |
|---|
| 2015 | | - * |
|---|
| 2016 | | - * Returns true if everything ok, false otherwise |
|---|
| 2186 | + * @skb: pointer to message buffer. |
|---|
| 2187 | + * @xmitq: for Nagle ACK if any |
|---|
| 2188 | + * Returns true if message should be added to receive queue, false otherwise |
|---|
| 2017 | 2189 | */ |
|---|
| 2018 | | -static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb) |
|---|
| 2190 | +static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb, |
|---|
| 2191 | + struct sk_buff_head *xmitq) |
|---|
| 2019 | 2192 | { |
|---|
| 2020 | 2193 | struct sock *sk = &tsk->sk; |
|---|
| 2021 | 2194 | struct net *net = sock_net(sk); |
|---|
| 2022 | 2195 | struct tipc_msg *hdr = buf_msg(skb); |
|---|
| 2023 | | - u32 pport = msg_origport(hdr); |
|---|
| 2024 | | - u32 pnode = msg_orignode(hdr); |
|---|
| 2196 | + bool con_msg = msg_connected(hdr); |
|---|
| 2197 | + u32 pport = tsk_peer_port(tsk); |
|---|
| 2198 | + u32 pnode = tsk_peer_node(tsk); |
|---|
| 2199 | + u32 oport = msg_origport(hdr); |
|---|
| 2200 | + u32 onode = msg_orignode(hdr); |
|---|
| 2201 | + int err = msg_errcode(hdr); |
|---|
| 2202 | + unsigned long delay; |
|---|
| 2025 | 2203 | |
|---|
| 2026 | 2204 | if (unlikely(msg_mcast(hdr))) |
|---|
| 2027 | 2205 | return false; |
|---|
| 2206 | + tsk->oneway = 0; |
|---|
| 2028 | 2207 | |
|---|
| 2029 | 2208 | switch (sk->sk_state) { |
|---|
| 2030 | 2209 | case TIPC_CONNECTING: |
|---|
| 2031 | | - /* Accept only ACK or NACK message */ |
|---|
| 2032 | | - if (unlikely(!msg_connected(hdr))) { |
|---|
| 2033 | | - if (pport != tsk_peer_port(tsk) || |
|---|
| 2034 | | - pnode != tsk_peer_node(tsk)) |
|---|
| 2035 | | - return false; |
|---|
| 2036 | | - |
|---|
| 2037 | | - tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2038 | | - sk->sk_err = ECONNREFUSED; |
|---|
| 2210 | + /* Setup ACK */ |
|---|
| 2211 | + if (likely(con_msg)) { |
|---|
| 2212 | + if (err) |
|---|
| 2213 | + break; |
|---|
| 2214 | + tipc_sk_finish_conn(tsk, oport, onode); |
|---|
| 2215 | + msg_set_importance(&tsk->phdr, msg_importance(hdr)); |
|---|
| 2216 | + /* ACK+ message with data is added to receive queue */ |
|---|
| 2217 | + if (msg_data_sz(hdr)) |
|---|
| 2218 | + return true; |
|---|
| 2219 | + /* Empty ACK-, - wake up sleeping connect() and drop */ |
|---|
| 2039 | 2220 | sk->sk_state_change(sk); |
|---|
| 2040 | | - return true; |
|---|
| 2221 | + msg_set_dest_droppable(hdr, 1); |
|---|
| 2222 | + return false; |
|---|
| 2041 | 2223 | } |
|---|
| 2042 | | - |
|---|
| 2043 | | - if (unlikely(msg_errcode(hdr))) { |
|---|
| 2044 | | - tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2045 | | - sk->sk_err = ECONNREFUSED; |
|---|
| 2046 | | - sk->sk_state_change(sk); |
|---|
| 2047 | | - return true; |
|---|
| 2048 | | - } |
|---|
| 2049 | | - |
|---|
| 2050 | | - if (unlikely(!msg_isdata(hdr))) { |
|---|
| 2051 | | - tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2052 | | - sk->sk_err = EINVAL; |
|---|
| 2053 | | - sk->sk_state_change(sk); |
|---|
| 2054 | | - return true; |
|---|
| 2055 | | - } |
|---|
| 2056 | | - |
|---|
| 2057 | | - tipc_sk_finish_conn(tsk, msg_origport(hdr), msg_orignode(hdr)); |
|---|
| 2058 | | - msg_set_importance(&tsk->phdr, msg_importance(hdr)); |
|---|
| 2059 | | - |
|---|
| 2060 | | - /* If 'ACK+' message, add to socket receive queue */ |
|---|
| 2061 | | - if (msg_data_sz(hdr)) |
|---|
| 2062 | | - return true; |
|---|
| 2063 | | - |
|---|
| 2064 | | - /* If empty 'ACK-' message, wake up sleeping connect() */ |
|---|
| 2065 | | - sk->sk_state_change(sk); |
|---|
| 2066 | | - |
|---|
| 2067 | | - /* 'ACK-' message is neither accepted nor rejected: */ |
|---|
| 2068 | | - msg_set_dest_droppable(hdr, 1); |
|---|
| 2069 | | - return false; |
|---|
| 2070 | | - |
|---|
| 2071 | | - case TIPC_OPEN: |
|---|
| 2072 | | - case TIPC_DISCONNECTING: |
|---|
| 2073 | | - break; |
|---|
| 2074 | | - case TIPC_LISTEN: |
|---|
| 2075 | | - /* Accept only SYN message */ |
|---|
| 2076 | | - if (!msg_connected(hdr) && !(msg_errcode(hdr))) |
|---|
| 2077 | | - return true; |
|---|
| 2078 | | - break; |
|---|
| 2079 | | - case TIPC_ESTABLISHED: |
|---|
| 2080 | | - /* Accept only connection-based messages sent by peer */ |
|---|
| 2081 | | - if (unlikely(!tsk_peer_msg(tsk, hdr))) |
|---|
| 2224 | + /* Ignore connectionless message if not from listening socket */ |
|---|
| 2225 | + if (oport != pport || onode != pnode) |
|---|
| 2082 | 2226 | return false; |
|---|
| 2083 | 2227 | |
|---|
| 2084 | | - if (unlikely(msg_errcode(hdr))) { |
|---|
| 2085 | | - tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2086 | | - /* Let timer expire on it's own */ |
|---|
| 2087 | | - tipc_node_remove_conn(net, tsk_peer_node(tsk), |
|---|
| 2088 | | - tsk->portid); |
|---|
| 2089 | | - sk->sk_state_change(sk); |
|---|
| 2228 | + /* Rejected SYN */ |
|---|
| 2229 | + if (err != TIPC_ERR_OVERLOAD) |
|---|
| 2230 | + break; |
|---|
| 2231 | + |
|---|
| 2232 | + /* Prepare for new setup attempt if we have a SYN clone */ |
|---|
| 2233 | + if (skb_queue_empty(&sk->sk_write_queue)) |
|---|
| 2234 | + break; |
|---|
| 2235 | + get_random_bytes(&delay, 2); |
|---|
| 2236 | + delay %= (tsk->conn_timeout / 4); |
|---|
| 2237 | + delay = msecs_to_jiffies(delay + 100); |
|---|
| 2238 | + sk_reset_timer(sk, &sk->sk_timer, jiffies + delay); |
|---|
| 2239 | + return false; |
|---|
| 2240 | + case TIPC_OPEN: |
|---|
| 2241 | + case TIPC_DISCONNECTING: |
|---|
| 2242 | + return false; |
|---|
| 2243 | + case TIPC_LISTEN: |
|---|
| 2244 | + /* Accept only SYN message */ |
|---|
| 2245 | + if (!msg_is_syn(hdr) && |
|---|
| 2246 | + tipc_node_get_capabilities(net, onode) & TIPC_SYN_BIT) |
|---|
| 2247 | + return false; |
|---|
| 2248 | + if (!con_msg && !err) |
|---|
| 2249 | + return true; |
|---|
| 2250 | + return false; |
|---|
| 2251 | + case TIPC_ESTABLISHED: |
|---|
| 2252 | + if (!skb_queue_empty(&sk->sk_write_queue)) |
|---|
| 2253 | + tipc_sk_push_backlog(tsk, false); |
|---|
| 2254 | + /* Accept only connection-based messages sent by peer */ |
|---|
| 2255 | + if (likely(con_msg && !err && pport == oport && |
|---|
| 2256 | + pnode == onode)) { |
|---|
| 2257 | + if (msg_ack_required(hdr)) { |
|---|
| 2258 | + struct sk_buff *skb; |
|---|
| 2259 | + |
|---|
| 2260 | + skb = tipc_sk_build_ack(tsk); |
|---|
| 2261 | + if (skb) { |
|---|
| 2262 | + msg_set_nagle_ack(buf_msg(skb)); |
|---|
| 2263 | + __skb_queue_tail(xmitq, skb); |
|---|
| 2264 | + } |
|---|
| 2265 | + } |
|---|
| 2266 | + return true; |
|---|
| 2090 | 2267 | } |
|---|
| 2268 | + if (!tsk_peer_msg(tsk, hdr)) |
|---|
| 2269 | + return false; |
|---|
| 2270 | + if (!err) |
|---|
| 2271 | + return true; |
|---|
| 2272 | + tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2273 | + tipc_node_remove_conn(net, pnode, tsk->portid); |
|---|
| 2274 | + sk->sk_state_change(sk); |
|---|
| 2091 | 2275 | return true; |
|---|
| 2092 | 2276 | default: |
|---|
| 2093 | 2277 | pr_err("Unknown sk_state %u\n", sk->sk_state); |
|---|
| 2094 | 2278 | } |
|---|
| 2095 | | - |
|---|
| 2096 | | - return false; |
|---|
| 2279 | + /* Abort connection setup attempt */ |
|---|
| 2280 | + tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2281 | + sk->sk_err = ECONNREFUSED; |
|---|
| 2282 | + sk->sk_state_change(sk); |
|---|
| 2283 | + return true; |
|---|
| 2097 | 2284 | } |
|---|
| 2098 | 2285 | |
|---|
| 2099 | 2286 | /** |
|---|
| .. | .. |
|---|
| 2120 | 2307 | struct tipc_msg *hdr = buf_msg(skb); |
|---|
| 2121 | 2308 | |
|---|
| 2122 | 2309 | if (unlikely(msg_in_group(hdr))) |
|---|
| 2123 | | - return sk->sk_rcvbuf; |
|---|
| 2310 | + return READ_ONCE(sk->sk_rcvbuf); |
|---|
| 2124 | 2311 | |
|---|
| 2125 | 2312 | if (unlikely(!msg_connected(hdr))) |
|---|
| 2126 | | - return sk->sk_rcvbuf << msg_importance(hdr); |
|---|
| 2313 | + return READ_ONCE(sk->sk_rcvbuf) << msg_importance(hdr); |
|---|
| 2127 | 2314 | |
|---|
| 2128 | 2315 | if (likely(tsk->peer_caps & TIPC_BLOCK_FLOWCTL)) |
|---|
| 2129 | | - return sk->sk_rcvbuf; |
|---|
| 2316 | + return READ_ONCE(sk->sk_rcvbuf); |
|---|
| 2130 | 2317 | |
|---|
| 2131 | 2318 | return FLOWCTL_MSG_LIM; |
|---|
| 2132 | 2319 | } |
|---|
| .. | .. |
|---|
| 2151 | 2338 | struct tipc_msg *hdr = buf_msg(skb); |
|---|
| 2152 | 2339 | struct net *net = sock_net(sk); |
|---|
| 2153 | 2340 | struct sk_buff_head inputq; |
|---|
| 2341 | + int mtyp = msg_type(hdr); |
|---|
| 2154 | 2342 | int limit, err = TIPC_OK; |
|---|
| 2155 | 2343 | |
|---|
| 2344 | + trace_tipc_sk_filter_rcv(sk, skb, TIPC_DUMP_ALL, " "); |
|---|
| 2156 | 2345 | TIPC_SKB_CB(skb)->bytes_read = 0; |
|---|
| 2157 | 2346 | __skb_queue_head_init(&inputq); |
|---|
| 2158 | 2347 | __skb_queue_tail(&inputq, skb); |
|---|
| .. | .. |
|---|
| 2163 | 2352 | if (unlikely(grp)) |
|---|
| 2164 | 2353 | tipc_group_filter_msg(grp, &inputq, xmitq); |
|---|
| 2165 | 2354 | |
|---|
| 2355 | + if (unlikely(!grp) && mtyp == TIPC_MCAST_MSG) |
|---|
| 2356 | + tipc_mcast_filter_msg(net, &tsk->mc_method.deferredq, &inputq); |
|---|
| 2357 | + |
|---|
| 2166 | 2358 | /* Validate and add to receive buffer if there is space */ |
|---|
| 2167 | 2359 | while ((skb = __skb_dequeue(&inputq))) { |
|---|
| 2168 | 2360 | hdr = buf_msg(skb); |
|---|
| 2169 | 2361 | limit = rcvbuf_limit(sk, skb); |
|---|
| 2170 | | - if ((sk_conn && !tipc_sk_filter_connect(tsk, skb)) || |
|---|
| 2362 | + if ((sk_conn && !tipc_sk_filter_connect(tsk, skb, xmitq)) || |
|---|
| 2171 | 2363 | (!sk_conn && msg_connected(hdr)) || |
|---|
| 2172 | 2364 | (!grp && msg_in_group(hdr))) |
|---|
| 2173 | 2365 | err = TIPC_ERR_NO_PORT; |
|---|
| 2174 | 2366 | else if (sk_rmem_alloc_get(sk) + skb->truesize >= limit) { |
|---|
| 2367 | + trace_tipc_sk_dump(sk, skb, TIPC_DUMP_ALL, |
|---|
| 2368 | + "err_overload2!"); |
|---|
| 2175 | 2369 | atomic_inc(&sk->sk_drops); |
|---|
| 2176 | 2370 | err = TIPC_ERR_OVERLOAD; |
|---|
| 2177 | 2371 | } |
|---|
| 2178 | 2372 | |
|---|
| 2179 | 2373 | if (unlikely(err)) { |
|---|
| 2180 | | - tipc_skb_reject(net, err, skb, xmitq); |
|---|
| 2374 | + if (tipc_msg_reverse(tipc_own_addr(net), &skb, err)) { |
|---|
| 2375 | + trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_NONE, |
|---|
| 2376 | + "@filter_rcv!"); |
|---|
| 2377 | + __skb_queue_tail(xmitq, skb); |
|---|
| 2378 | + } |
|---|
| 2181 | 2379 | err = TIPC_OK; |
|---|
| 2182 | 2380 | continue; |
|---|
| 2183 | 2381 | } |
|---|
| 2184 | 2382 | __skb_queue_tail(&sk->sk_receive_queue, skb); |
|---|
| 2185 | 2383 | skb_set_owner_r(skb, sk); |
|---|
| 2384 | + trace_tipc_sk_overlimit2(sk, skb, TIPC_DUMP_ALL, |
|---|
| 2385 | + "rcvq >90% allocated!"); |
|---|
| 2186 | 2386 | sk->sk_data_ready(sk); |
|---|
| 2187 | 2387 | } |
|---|
| 2188 | 2388 | } |
|---|
| .. | .. |
|---|
| 2248 | 2448 | if (!sk->sk_backlog.len) |
|---|
| 2249 | 2449 | atomic_set(dcnt, 0); |
|---|
| 2250 | 2450 | lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt); |
|---|
| 2251 | | - if (likely(!sk_add_backlog(sk, skb, lim))) |
|---|
| 2451 | + if (likely(!sk_add_backlog(sk, skb, lim))) { |
|---|
| 2452 | + trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_ALL, |
|---|
| 2453 | + "bklg & rcvq >90% allocated!"); |
|---|
| 2252 | 2454 | continue; |
|---|
| 2455 | + } |
|---|
| 2253 | 2456 | |
|---|
| 2457 | + trace_tipc_sk_dump(sk, skb, TIPC_DUMP_ALL, "err_overload!"); |
|---|
| 2254 | 2458 | /* Overload => reject message back to sender */ |
|---|
| 2255 | 2459 | onode = tipc_own_addr(sock_net(sk)); |
|---|
| 2256 | 2460 | atomic_inc(&sk->sk_drops); |
|---|
| 2257 | | - if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) |
|---|
| 2461 | + if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) { |
|---|
| 2462 | + trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_ALL, |
|---|
| 2463 | + "@sk_enqueue!"); |
|---|
| 2258 | 2464 | __skb_queue_tail(xmitq, skb); |
|---|
| 2465 | + } |
|---|
| 2259 | 2466 | break; |
|---|
| 2260 | 2467 | } |
|---|
| 2261 | 2468 | } |
|---|
| .. | .. |
|---|
| 2304 | 2511 | /* Prepare for message rejection */ |
|---|
| 2305 | 2512 | if (!tipc_msg_reverse(tipc_own_addr(net), &skb, err)) |
|---|
| 2306 | 2513 | continue; |
|---|
| 2514 | + |
|---|
| 2515 | + trace_tipc_sk_rej_msg(NULL, skb, TIPC_DUMP_NONE, "@sk_rcv!"); |
|---|
| 2307 | 2516 | xmit: |
|---|
| 2308 | 2517 | dnode = msg_destnode(buf_msg(skb)); |
|---|
| 2309 | 2518 | tipc_node_xmit_skb(net, skb, dnode, dport); |
|---|
| .. | .. |
|---|
| 2324 | 2533 | return -ETIMEDOUT; |
|---|
| 2325 | 2534 | if (signal_pending(current)) |
|---|
| 2326 | 2535 | return sock_intr_errno(*timeo_p); |
|---|
| 2536 | + if (sk->sk_state == TIPC_DISCONNECTING) |
|---|
| 2537 | + break; |
|---|
| 2327 | 2538 | |
|---|
| 2328 | 2539 | add_wait_queue(sk_sleep(sk), &wait); |
|---|
| 2329 | | - done = sk_wait_event(sk, timeo_p, |
|---|
| 2330 | | - sk->sk_state != TIPC_CONNECTING, &wait); |
|---|
| 2540 | + done = sk_wait_event(sk, timeo_p, tipc_sk_connected(sk), |
|---|
| 2541 | + &wait); |
|---|
| 2331 | 2542 | remove_wait_queue(sk_sleep(sk), &wait); |
|---|
| 2332 | 2543 | } while (!done); |
|---|
| 2333 | 2544 | return 0; |
|---|
| .. | .. |
|---|
| 2415 | 2626 | * case is EINPROGRESS, rather than EALREADY. |
|---|
| 2416 | 2627 | */ |
|---|
| 2417 | 2628 | res = -EINPROGRESS; |
|---|
| 2418 | | - /* fall thru' */ |
|---|
| 2629 | + fallthrough; |
|---|
| 2419 | 2630 | case TIPC_CONNECTING: |
|---|
| 2420 | 2631 | if (!timeout) { |
|---|
| 2421 | 2632 | if (previous == TIPC_CONNECTING) |
|---|
| .. | .. |
|---|
| 2492 | 2703 | /** |
|---|
| 2493 | 2704 | * tipc_accept - wait for connection request |
|---|
| 2494 | 2705 | * @sock: listening socket |
|---|
| 2495 | | - * @newsock: new socket that is to be connected |
|---|
| 2706 | + * @new_sock: new socket that is to be connected |
|---|
| 2496 | 2707 | * @flags: file-related flags associated with socket |
|---|
| 2497 | 2708 | * |
|---|
| 2498 | 2709 | * Returns 0 on success, errno otherwise |
|---|
| .. | .. |
|---|
| 2501 | 2712 | bool kern) |
|---|
| 2502 | 2713 | { |
|---|
| 2503 | 2714 | struct sock *new_sk, *sk = sock->sk; |
|---|
| 2504 | | - struct sk_buff *buf; |
|---|
| 2505 | 2715 | struct tipc_sock *new_tsock; |
|---|
| 2716 | + struct msghdr m = {NULL,}; |
|---|
| 2506 | 2717 | struct tipc_msg *msg; |
|---|
| 2718 | + struct sk_buff *buf; |
|---|
| 2507 | 2719 | long timeo; |
|---|
| 2508 | 2720 | int res; |
|---|
| 2509 | 2721 | |
|---|
| .. | .. |
|---|
| 2536 | 2748 | * Reject any stray messages received by new socket |
|---|
| 2537 | 2749 | * before the socket lock was taken (very, very unlikely) |
|---|
| 2538 | 2750 | */ |
|---|
| 2539 | | - tsk_rej_rx_queue(new_sk); |
|---|
| 2751 | + tsk_rej_rx_queue(new_sk, TIPC_ERR_NO_PORT); |
|---|
| 2540 | 2752 | |
|---|
| 2541 | 2753 | /* Connect new socket to it's peer */ |
|---|
| 2542 | 2754 | tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg)); |
|---|
| 2543 | 2755 | |
|---|
| 2544 | | - tsk_set_importance(new_tsock, msg_importance(msg)); |
|---|
| 2756 | + tsk_set_importance(new_sk, msg_importance(msg)); |
|---|
| 2545 | 2757 | if (msg_named(msg)) { |
|---|
| 2546 | 2758 | new_tsock->conn_type = msg_nametype(msg); |
|---|
| 2547 | 2759 | new_tsock->conn_instance = msg_nameinst(msg); |
|---|
| 2548 | 2760 | } |
|---|
| 2549 | 2761 | |
|---|
| 2550 | 2762 | /* |
|---|
| 2551 | | - * Respond to 'SYN-' by discarding it & returning 'ACK'-. |
|---|
| 2552 | | - * Respond to 'SYN+' by queuing it on new socket. |
|---|
| 2763 | + * Respond to 'SYN-' by discarding it & returning 'ACK'. |
|---|
| 2764 | + * Respond to 'SYN+' by queuing it on new socket & returning 'ACK'. |
|---|
| 2553 | 2765 | */ |
|---|
| 2554 | 2766 | if (!msg_data_sz(msg)) { |
|---|
| 2555 | | - struct msghdr m = {NULL,}; |
|---|
| 2556 | | - |
|---|
| 2557 | 2767 | tsk_advance_rx_queue(sk); |
|---|
| 2558 | | - __tipc_sendstream(new_sock, &m, 0); |
|---|
| 2559 | 2768 | } else { |
|---|
| 2560 | 2769 | __skb_dequeue(&sk->sk_receive_queue); |
|---|
| 2561 | 2770 | __skb_queue_head(&new_sk->sk_receive_queue, buf); |
|---|
| 2562 | 2771 | skb_set_owner_r(buf, new_sk); |
|---|
| 2563 | 2772 | } |
|---|
| 2773 | + __tipc_sendstream(new_sock, &m, 0); |
|---|
| 2564 | 2774 | release_sock(new_sk); |
|---|
| 2565 | 2775 | exit: |
|---|
| 2566 | 2776 | release_sock(sk); |
|---|
| .. | .. |
|---|
| 2586 | 2796 | |
|---|
| 2587 | 2797 | lock_sock(sk); |
|---|
| 2588 | 2798 | |
|---|
| 2799 | + trace_tipc_sk_shutdown(sk, NULL, TIPC_DUMP_ALL, " "); |
|---|
| 2589 | 2800 | __tipc_shutdown(sock, TIPC_CONN_SHUTDOWN); |
|---|
| 2590 | 2801 | sk->sk_shutdown = SHUTDOWN_MASK; |
|---|
| 2591 | 2802 | |
|---|
| .. | .. |
|---|
| 2604 | 2815 | return res; |
|---|
| 2605 | 2816 | } |
|---|
| 2606 | 2817 | |
|---|
| 2818 | +static void tipc_sk_check_probing_state(struct sock *sk, |
|---|
| 2819 | + struct sk_buff_head *list) |
|---|
| 2820 | +{ |
|---|
| 2821 | + struct tipc_sock *tsk = tipc_sk(sk); |
|---|
| 2822 | + u32 pnode = tsk_peer_node(tsk); |
|---|
| 2823 | + u32 pport = tsk_peer_port(tsk); |
|---|
| 2824 | + u32 self = tsk_own_node(tsk); |
|---|
| 2825 | + u32 oport = tsk->portid; |
|---|
| 2826 | + struct sk_buff *skb; |
|---|
| 2827 | + |
|---|
| 2828 | + if (tsk->probe_unacked) { |
|---|
| 2829 | + tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2830 | + sk->sk_err = ECONNABORTED; |
|---|
| 2831 | + tipc_node_remove_conn(sock_net(sk), pnode, pport); |
|---|
| 2832 | + sk->sk_state_change(sk); |
|---|
| 2833 | + return; |
|---|
| 2834 | + } |
|---|
| 2835 | + /* Prepare new probe */ |
|---|
| 2836 | + skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, 0, |
|---|
| 2837 | + pnode, self, pport, oport, TIPC_OK); |
|---|
| 2838 | + if (skb) |
|---|
| 2839 | + __skb_queue_tail(list, skb); |
|---|
| 2840 | + tsk->probe_unacked = true; |
|---|
| 2841 | + sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTV); |
|---|
| 2842 | +} |
|---|
| 2843 | + |
|---|
| 2844 | +static void tipc_sk_retry_connect(struct sock *sk, struct sk_buff_head *list) |
|---|
| 2845 | +{ |
|---|
| 2846 | + struct tipc_sock *tsk = tipc_sk(sk); |
|---|
| 2847 | + |
|---|
| 2848 | + /* Try again later if dest link is congested */ |
|---|
| 2849 | + if (tsk->cong_link_cnt) { |
|---|
| 2850 | + sk_reset_timer(sk, &sk->sk_timer, |
|---|
| 2851 | + jiffies + msecs_to_jiffies(100)); |
|---|
| 2852 | + return; |
|---|
| 2853 | + } |
|---|
| 2854 | + /* Prepare SYN for retransmit */ |
|---|
| 2855 | + tipc_msg_skb_clone(&sk->sk_write_queue, list); |
|---|
| 2856 | +} |
|---|
| 2857 | + |
|---|
| 2607 | 2858 | static void tipc_sk_timeout(struct timer_list *t) |
|---|
| 2608 | 2859 | { |
|---|
| 2609 | 2860 | struct sock *sk = from_timer(sk, t, sk_timer); |
|---|
| 2610 | 2861 | struct tipc_sock *tsk = tipc_sk(sk); |
|---|
| 2611 | | - u32 peer_port = tsk_peer_port(tsk); |
|---|
| 2612 | | - u32 peer_node = tsk_peer_node(tsk); |
|---|
| 2613 | | - u32 own_node = tsk_own_node(tsk); |
|---|
| 2614 | | - u32 own_port = tsk->portid; |
|---|
| 2615 | | - struct net *net = sock_net(sk); |
|---|
| 2616 | | - struct sk_buff *skb = NULL; |
|---|
| 2862 | + u32 pnode = tsk_peer_node(tsk); |
|---|
| 2863 | + struct sk_buff_head list; |
|---|
| 2864 | + int rc = 0; |
|---|
| 2617 | 2865 | |
|---|
| 2866 | + __skb_queue_head_init(&list); |
|---|
| 2618 | 2867 | bh_lock_sock(sk); |
|---|
| 2619 | | - if (!tipc_sk_connected(sk)) |
|---|
| 2620 | | - goto exit; |
|---|
| 2621 | 2868 | |
|---|
| 2622 | 2869 | /* Try again later if socket is busy */ |
|---|
| 2623 | 2870 | if (sock_owned_by_user(sk)) { |
|---|
| 2624 | 2871 | sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 20); |
|---|
| 2625 | | - goto exit; |
|---|
| 2872 | + bh_unlock_sock(sk); |
|---|
| 2873 | + sock_put(sk); |
|---|
| 2874 | + return; |
|---|
| 2626 | 2875 | } |
|---|
| 2627 | 2876 | |
|---|
| 2628 | | - if (tsk->probe_unacked) { |
|---|
| 2629 | | - tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
|---|
| 2630 | | - tipc_node_remove_conn(net, peer_node, peer_port); |
|---|
| 2631 | | - sk->sk_state_change(sk); |
|---|
| 2632 | | - goto exit; |
|---|
| 2633 | | - } |
|---|
| 2634 | | - /* Send new probe */ |
|---|
| 2635 | | - skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, 0, |
|---|
| 2636 | | - peer_node, own_node, peer_port, own_port, |
|---|
| 2637 | | - TIPC_OK); |
|---|
| 2638 | | - tsk->probe_unacked = true; |
|---|
| 2639 | | - sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTV); |
|---|
| 2640 | | -exit: |
|---|
| 2877 | + if (sk->sk_state == TIPC_ESTABLISHED) |
|---|
| 2878 | + tipc_sk_check_probing_state(sk, &list); |
|---|
| 2879 | + else if (sk->sk_state == TIPC_CONNECTING) |
|---|
| 2880 | + tipc_sk_retry_connect(sk, &list); |
|---|
| 2881 | + |
|---|
| 2641 | 2882 | bh_unlock_sock(sk); |
|---|
| 2642 | | - if (skb) |
|---|
| 2643 | | - tipc_node_xmit_skb(net, skb, peer_node, own_port); |
|---|
| 2883 | + |
|---|
| 2884 | + if (!skb_queue_empty(&list)) |
|---|
| 2885 | + rc = tipc_node_xmit(sock_net(sk), &list, pnode, tsk->portid); |
|---|
| 2886 | + |
|---|
| 2887 | + /* SYN messages may cause link congestion */ |
|---|
| 2888 | + if (rc == -ELINKCONG) { |
|---|
| 2889 | + tipc_dest_push(&tsk->cong_links, pnode, 0); |
|---|
| 2890 | + tsk->cong_link_cnt = 1; |
|---|
| 2891 | + } |
|---|
| 2644 | 2892 | sock_put(sk); |
|---|
| 2645 | 2893 | } |
|---|
| 2646 | 2894 | |
|---|
| .. | .. |
|---|
| 2746 | 2994 | struct tipc_sock *tsk; |
|---|
| 2747 | 2995 | |
|---|
| 2748 | 2996 | rcu_read_lock(); |
|---|
| 2749 | | - tsk = rhashtable_lookup_fast(&tn->sk_rht, &portid, tsk_rht_params); |
|---|
| 2997 | + tsk = rhashtable_lookup(&tn->sk_rht, &portid, tsk_rht_params); |
|---|
| 2750 | 2998 | if (tsk) |
|---|
| 2751 | 2999 | sock_hold(&tsk->sk); |
|---|
| 2752 | 3000 | rcu_read_unlock(); |
|---|
| .. | .. |
|---|
| 2883 | 3131 | * Returns 0 on success, errno otherwise |
|---|
| 2884 | 3132 | */ |
|---|
| 2885 | 3133 | static int tipc_setsockopt(struct socket *sock, int lvl, int opt, |
|---|
| 2886 | | - char __user *ov, unsigned int ol) |
|---|
| 3134 | + sockptr_t ov, unsigned int ol) |
|---|
| 2887 | 3135 | { |
|---|
| 2888 | 3136 | struct sock *sk = sock->sk; |
|---|
| 2889 | 3137 | struct tipc_sock *tsk = tipc_sk(sk); |
|---|
| .. | .. |
|---|
| 2901 | 3149 | case TIPC_SRC_DROPPABLE: |
|---|
| 2902 | 3150 | case TIPC_DEST_DROPPABLE: |
|---|
| 2903 | 3151 | case TIPC_CONN_TIMEOUT: |
|---|
| 3152 | + case TIPC_NODELAY: |
|---|
| 2904 | 3153 | if (ol < sizeof(value)) |
|---|
| 2905 | 3154 | return -EINVAL; |
|---|
| 2906 | | - if (get_user(value, (u32 __user *)ov)) |
|---|
| 3155 | + if (copy_from_sockptr(&value, ov, sizeof(u32))) |
|---|
| 2907 | 3156 | return -EFAULT; |
|---|
| 2908 | 3157 | break; |
|---|
| 2909 | 3158 | case TIPC_GROUP_JOIN: |
|---|
| 2910 | 3159 | if (ol < sizeof(mreq)) |
|---|
| 2911 | 3160 | return -EINVAL; |
|---|
| 2912 | | - if (copy_from_user(&mreq, ov, sizeof(mreq))) |
|---|
| 3161 | + if (copy_from_sockptr(&mreq, ov, sizeof(mreq))) |
|---|
| 2913 | 3162 | return -EFAULT; |
|---|
| 2914 | 3163 | break; |
|---|
| 2915 | 3164 | default: |
|---|
| 2916 | | - if (ov || ol) |
|---|
| 3165 | + if (!sockptr_is_null(ov) || ol) |
|---|
| 2917 | 3166 | return -EINVAL; |
|---|
| 2918 | 3167 | } |
|---|
| 2919 | 3168 | |
|---|
| .. | .. |
|---|
| 2921 | 3170 | |
|---|
| 2922 | 3171 | switch (opt) { |
|---|
| 2923 | 3172 | case TIPC_IMPORTANCE: |
|---|
| 2924 | | - res = tsk_set_importance(tsk, value); |
|---|
| 3173 | + res = tsk_set_importance(sk, value); |
|---|
| 2925 | 3174 | break; |
|---|
| 2926 | 3175 | case TIPC_SRC_DROPPABLE: |
|---|
| 2927 | 3176 | if (sock->type != SOCK_STREAM) |
|---|
| .. | .. |
|---|
| 2948 | 3197 | break; |
|---|
| 2949 | 3198 | case TIPC_GROUP_LEAVE: |
|---|
| 2950 | 3199 | res = tipc_sk_leave(tsk); |
|---|
| 3200 | + break; |
|---|
| 3201 | + case TIPC_NODELAY: |
|---|
| 3202 | + tsk->nodelay = !!value; |
|---|
| 3203 | + tsk_set_nagle(tsk); |
|---|
| 2951 | 3204 | break; |
|---|
| 2952 | 3205 | default: |
|---|
| 2953 | 3206 | res = -EINVAL; |
|---|
| .. | .. |
|---|
| 3010 | 3263 | break; |
|---|
| 3011 | 3264 | case TIPC_SOCK_RECVQ_DEPTH: |
|---|
| 3012 | 3265 | value = skb_queue_len(&sk->sk_receive_queue); |
|---|
| 3266 | + break; |
|---|
| 3267 | + case TIPC_SOCK_RECVQ_USED: |
|---|
| 3268 | + value = sk_rmem_alloc_get(sk); |
|---|
| 3013 | 3269 | break; |
|---|
| 3014 | 3270 | case TIPC_GROUP_JOIN: |
|---|
| 3015 | 3271 | seq.type = 0; |
|---|
| .. | .. |
|---|
| 3211 | 3467 | peer_node = tsk_peer_node(tsk); |
|---|
| 3212 | 3468 | peer_port = tsk_peer_port(tsk); |
|---|
| 3213 | 3469 | |
|---|
| 3214 | | - nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON); |
|---|
| 3470 | + nest = nla_nest_start_noflag(skb, TIPC_NLA_SOCK_CON); |
|---|
| 3471 | + if (!nest) |
|---|
| 3472 | + return -EMSGSIZE; |
|---|
| 3215 | 3473 | |
|---|
| 3216 | 3474 | if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node)) |
|---|
| 3217 | 3475 | goto msg_full; |
|---|
| .. | .. |
|---|
| 3268 | 3526 | if (!hdr) |
|---|
| 3269 | 3527 | goto msg_cancel; |
|---|
| 3270 | 3528 | |
|---|
| 3271 | | - attrs = nla_nest_start(skb, TIPC_NLA_SOCK); |
|---|
| 3529 | + attrs = nla_nest_start_noflag(skb, TIPC_NLA_SOCK); |
|---|
| 3272 | 3530 | if (!attrs) |
|---|
| 3273 | 3531 | goto genlmsg_cancel; |
|---|
| 3274 | 3532 | |
|---|
| .. | .. |
|---|
| 3373 | 3631 | if (!(sk_filter_state & (1 << sk->sk_state))) |
|---|
| 3374 | 3632 | return 0; |
|---|
| 3375 | 3633 | |
|---|
| 3376 | | - attrs = nla_nest_start(skb, TIPC_NLA_SOCK); |
|---|
| 3634 | + attrs = nla_nest_start_noflag(skb, TIPC_NLA_SOCK); |
|---|
| 3377 | 3635 | if (!attrs) |
|---|
| 3378 | 3636 | goto msg_cancel; |
|---|
| 3379 | 3637 | |
|---|
| .. | .. |
|---|
| 3391 | 3649 | TIPC_NLA_SOCK_PAD)) |
|---|
| 3392 | 3650 | goto attr_msg_cancel; |
|---|
| 3393 | 3651 | |
|---|
| 3394 | | - stat = nla_nest_start(skb, TIPC_NLA_SOCK_STAT); |
|---|
| 3652 | + stat = nla_nest_start_noflag(skb, TIPC_NLA_SOCK_STAT); |
|---|
| 3395 | 3653 | if (!stat) |
|---|
| 3396 | 3654 | goto attr_msg_cancel; |
|---|
| 3397 | 3655 | |
|---|
| .. | .. |
|---|
| 3448 | 3706 | if (!hdr) |
|---|
| 3449 | 3707 | goto msg_cancel; |
|---|
| 3450 | 3708 | |
|---|
| 3451 | | - attrs = nla_nest_start(skb, TIPC_NLA_PUBL); |
|---|
| 3709 | + attrs = nla_nest_start_noflag(skb, TIPC_NLA_PUBL); |
|---|
| 3452 | 3710 | if (!attrs) |
|---|
| 3453 | 3711 | goto genlmsg_cancel; |
|---|
| 3454 | 3712 | |
|---|
| .. | .. |
|---|
| 3525 | 3783 | struct tipc_sock *tsk; |
|---|
| 3526 | 3784 | |
|---|
| 3527 | 3785 | if (!tsk_portid) { |
|---|
| 3528 | | - struct nlattr **attrs; |
|---|
| 3786 | + struct nlattr **attrs = genl_dumpit_info(cb)->attrs; |
|---|
| 3529 | 3787 | struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1]; |
|---|
| 3530 | | - |
|---|
| 3531 | | - err = tipc_nlmsg_parse(cb->nlh, &attrs); |
|---|
| 3532 | | - if (err) |
|---|
| 3533 | | - return err; |
|---|
| 3534 | 3788 | |
|---|
| 3535 | 3789 | if (!attrs[TIPC_NLA_SOCK]) |
|---|
| 3536 | 3790 | return -EINVAL; |
|---|
| 3537 | 3791 | |
|---|
| 3538 | | - err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, |
|---|
| 3539 | | - attrs[TIPC_NLA_SOCK], |
|---|
| 3540 | | - tipc_nl_sock_policy, NULL); |
|---|
| 3792 | + err = nla_parse_nested_deprecated(sock, TIPC_NLA_SOCK_MAX, |
|---|
| 3793 | + attrs[TIPC_NLA_SOCK], |
|---|
| 3794 | + tipc_nl_sock_policy, NULL); |
|---|
| 3541 | 3795 | if (err) |
|---|
| 3542 | 3796 | return err; |
|---|
| 3543 | 3797 | |
|---|
| .. | .. |
|---|
| 3567 | 3821 | |
|---|
| 3568 | 3822 | return skb->len; |
|---|
| 3569 | 3823 | } |
|---|
| 3824 | + |
|---|
| 3825 | +/** |
|---|
| 3826 | + * tipc_sk_filtering - check if a socket should be traced |
|---|
| 3827 | + * @sk: the socket to be examined |
|---|
| 3828 | + * @sysctl_tipc_sk_filter[]: the socket tuple for filtering, |
|---|
| 3829 | + * (portid, sock type, name type, name lower, name upper) |
|---|
| 3830 | + * |
|---|
| 3831 | + * Returns true if the socket meets the socket tuple data |
|---|
| 3832 | + * (value 0 = 'any') or when there is no tuple set (all = 0), |
|---|
| 3833 | + * otherwise false |
|---|
| 3834 | + */ |
|---|
| 3835 | +bool tipc_sk_filtering(struct sock *sk) |
|---|
| 3836 | +{ |
|---|
| 3837 | + struct tipc_sock *tsk; |
|---|
| 3838 | + struct publication *p; |
|---|
| 3839 | + u32 _port, _sktype, _type, _lower, _upper; |
|---|
| 3840 | + u32 type = 0, lower = 0, upper = 0; |
|---|
| 3841 | + |
|---|
| 3842 | + if (!sk) |
|---|
| 3843 | + return true; |
|---|
| 3844 | + |
|---|
| 3845 | + tsk = tipc_sk(sk); |
|---|
| 3846 | + |
|---|
| 3847 | + _port = sysctl_tipc_sk_filter[0]; |
|---|
| 3848 | + _sktype = sysctl_tipc_sk_filter[1]; |
|---|
| 3849 | + _type = sysctl_tipc_sk_filter[2]; |
|---|
| 3850 | + _lower = sysctl_tipc_sk_filter[3]; |
|---|
| 3851 | + _upper = sysctl_tipc_sk_filter[4]; |
|---|
| 3852 | + |
|---|
| 3853 | + if (!_port && !_sktype && !_type && !_lower && !_upper) |
|---|
| 3854 | + return true; |
|---|
| 3855 | + |
|---|
| 3856 | + if (_port) |
|---|
| 3857 | + return (_port == tsk->portid); |
|---|
| 3858 | + |
|---|
| 3859 | + if (_sktype && _sktype != sk->sk_type) |
|---|
| 3860 | + return false; |
|---|
| 3861 | + |
|---|
| 3862 | + if (tsk->published) { |
|---|
| 3863 | + p = list_first_entry_or_null(&tsk->publications, |
|---|
| 3864 | + struct publication, binding_sock); |
|---|
| 3865 | + if (p) { |
|---|
| 3866 | + type = p->type; |
|---|
| 3867 | + lower = p->lower; |
|---|
| 3868 | + upper = p->upper; |
|---|
| 3869 | + } |
|---|
| 3870 | + } |
|---|
| 3871 | + |
|---|
| 3872 | + if (!tipc_sk_type_connectionless(sk)) { |
|---|
| 3873 | + type = tsk->conn_type; |
|---|
| 3874 | + lower = tsk->conn_instance; |
|---|
| 3875 | + upper = tsk->conn_instance; |
|---|
| 3876 | + } |
|---|
| 3877 | + |
|---|
| 3878 | + if ((_type && _type != type) || (_lower && _lower != lower) || |
|---|
| 3879 | + (_upper && _upper != upper)) |
|---|
| 3880 | + return false; |
|---|
| 3881 | + |
|---|
| 3882 | + return true; |
|---|
| 3883 | +} |
|---|
| 3884 | + |
|---|
| 3885 | +u32 tipc_sock_get_portid(struct sock *sk) |
|---|
| 3886 | +{ |
|---|
| 3887 | + return (sk) ? (tipc_sk(sk))->portid : 0; |
|---|
| 3888 | +} |
|---|
| 3889 | + |
|---|
| 3890 | +/** |
|---|
| 3891 | + * tipc_sk_overlimit1 - check if socket rx queue is about to be overloaded, |
|---|
| 3892 | + * both the rcv and backlog queues are considered |
|---|
| 3893 | + * @sk: tipc sk to be checked |
|---|
| 3894 | + * @skb: tipc msg to be checked |
|---|
| 3895 | + * |
|---|
| 3896 | + * Returns true if the socket rx queue allocation is > 90%, otherwise false |
|---|
| 3897 | + */ |
|---|
| 3898 | + |
|---|
| 3899 | +bool tipc_sk_overlimit1(struct sock *sk, struct sk_buff *skb) |
|---|
| 3900 | +{ |
|---|
| 3901 | + atomic_t *dcnt = &tipc_sk(sk)->dupl_rcvcnt; |
|---|
| 3902 | + unsigned int lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt); |
|---|
| 3903 | + unsigned int qsize = sk->sk_backlog.len + sk_rmem_alloc_get(sk); |
|---|
| 3904 | + |
|---|
| 3905 | + return (qsize > lim * 90 / 100); |
|---|
| 3906 | +} |
|---|
| 3907 | + |
|---|
| 3908 | +/** |
|---|
| 3909 | + * tipc_sk_overlimit2 - check if socket rx queue is about to be overloaded, |
|---|
| 3910 | + * only the rcv queue is considered |
|---|
| 3911 | + * @sk: tipc sk to be checked |
|---|
| 3912 | + * @skb: tipc msg to be checked |
|---|
| 3913 | + * |
|---|
| 3914 | + * Returns true if the socket rx queue allocation is > 90%, otherwise false |
|---|
| 3915 | + */ |
|---|
| 3916 | + |
|---|
| 3917 | +bool tipc_sk_overlimit2(struct sock *sk, struct sk_buff *skb) |
|---|
| 3918 | +{ |
|---|
| 3919 | + unsigned int lim = rcvbuf_limit(sk, skb); |
|---|
| 3920 | + unsigned int qsize = sk_rmem_alloc_get(sk); |
|---|
| 3921 | + |
|---|
| 3922 | + return (qsize > lim * 90 / 100); |
|---|
| 3923 | +} |
|---|
| 3924 | + |
|---|
| 3925 | +/** |
|---|
| 3926 | + * tipc_sk_dump - dump TIPC socket |
|---|
| 3927 | + * @sk: tipc sk to be dumped |
|---|
| 3928 | + * @dqueues: bitmask to decide if any socket queue to be dumped? |
|---|
| 3929 | + * - TIPC_DUMP_NONE: don't dump socket queues |
|---|
| 3930 | + * - TIPC_DUMP_SK_SNDQ: dump socket send queue |
|---|
| 3931 | + * - TIPC_DUMP_SK_RCVQ: dump socket rcv queue |
|---|
| 3932 | + * - TIPC_DUMP_SK_BKLGQ: dump socket backlog queue |
|---|
| 3933 | + * - TIPC_DUMP_ALL: dump all the socket queues above |
|---|
| 3934 | + * @buf: returned buffer of dump data in format |
|---|
| 3935 | + */ |
|---|
| 3936 | +int tipc_sk_dump(struct sock *sk, u16 dqueues, char *buf) |
|---|
| 3937 | +{ |
|---|
| 3938 | + int i = 0; |
|---|
| 3939 | + size_t sz = (dqueues) ? SK_LMAX : SK_LMIN; |
|---|
| 3940 | + struct tipc_sock *tsk; |
|---|
| 3941 | + struct publication *p; |
|---|
| 3942 | + bool tsk_connected; |
|---|
| 3943 | + |
|---|
| 3944 | + if (!sk) { |
|---|
| 3945 | + i += scnprintf(buf, sz, "sk data: (null)\n"); |
|---|
| 3946 | + return i; |
|---|
| 3947 | + } |
|---|
| 3948 | + |
|---|
| 3949 | + tsk = tipc_sk(sk); |
|---|
| 3950 | + tsk_connected = !tipc_sk_type_connectionless(sk); |
|---|
| 3951 | + |
|---|
| 3952 | + i += scnprintf(buf, sz, "sk data: %u", sk->sk_type); |
|---|
| 3953 | + i += scnprintf(buf + i, sz - i, " %d", sk->sk_state); |
|---|
| 3954 | + i += scnprintf(buf + i, sz - i, " %x", tsk_own_node(tsk)); |
|---|
| 3955 | + i += scnprintf(buf + i, sz - i, " %u", tsk->portid); |
|---|
| 3956 | + i += scnprintf(buf + i, sz - i, " | %u", tsk_connected); |
|---|
| 3957 | + if (tsk_connected) { |
|---|
| 3958 | + i += scnprintf(buf + i, sz - i, " %x", tsk_peer_node(tsk)); |
|---|
| 3959 | + i += scnprintf(buf + i, sz - i, " %u", tsk_peer_port(tsk)); |
|---|
| 3960 | + i += scnprintf(buf + i, sz - i, " %u", tsk->conn_type); |
|---|
| 3961 | + i += scnprintf(buf + i, sz - i, " %u", tsk->conn_instance); |
|---|
| 3962 | + } |
|---|
| 3963 | + i += scnprintf(buf + i, sz - i, " | %u", tsk->published); |
|---|
| 3964 | + if (tsk->published) { |
|---|
| 3965 | + p = list_first_entry_or_null(&tsk->publications, |
|---|
| 3966 | + struct publication, binding_sock); |
|---|
| 3967 | + i += scnprintf(buf + i, sz - i, " %u", (p) ? p->type : 0); |
|---|
| 3968 | + i += scnprintf(buf + i, sz - i, " %u", (p) ? p->lower : 0); |
|---|
| 3969 | + i += scnprintf(buf + i, sz - i, " %u", (p) ? p->upper : 0); |
|---|
| 3970 | + } |
|---|
| 3971 | + i += scnprintf(buf + i, sz - i, " | %u", tsk->snd_win); |
|---|
| 3972 | + i += scnprintf(buf + i, sz - i, " %u", tsk->rcv_win); |
|---|
| 3973 | + i += scnprintf(buf + i, sz - i, " %u", tsk->max_pkt); |
|---|
| 3974 | + i += scnprintf(buf + i, sz - i, " %x", tsk->peer_caps); |
|---|
| 3975 | + i += scnprintf(buf + i, sz - i, " %u", tsk->cong_link_cnt); |
|---|
| 3976 | + i += scnprintf(buf + i, sz - i, " %u", tsk->snt_unacked); |
|---|
| 3977 | + i += scnprintf(buf + i, sz - i, " %u", tsk->rcv_unacked); |
|---|
| 3978 | + i += scnprintf(buf + i, sz - i, " %u", atomic_read(&tsk->dupl_rcvcnt)); |
|---|
| 3979 | + i += scnprintf(buf + i, sz - i, " %u", sk->sk_shutdown); |
|---|
| 3980 | + i += scnprintf(buf + i, sz - i, " | %d", sk_wmem_alloc_get(sk)); |
|---|
| 3981 | + i += scnprintf(buf + i, sz - i, " %d", sk->sk_sndbuf); |
|---|
| 3982 | + i += scnprintf(buf + i, sz - i, " | %d", sk_rmem_alloc_get(sk)); |
|---|
| 3983 | + i += scnprintf(buf + i, sz - i, " %d", sk->sk_rcvbuf); |
|---|
| 3984 | + i += scnprintf(buf + i, sz - i, " | %d\n", READ_ONCE(sk->sk_backlog.len)); |
|---|
| 3985 | + |
|---|
| 3986 | + if (dqueues & TIPC_DUMP_SK_SNDQ) { |
|---|
| 3987 | + i += scnprintf(buf + i, sz - i, "sk_write_queue: "); |
|---|
| 3988 | + i += tipc_list_dump(&sk->sk_write_queue, false, buf + i); |
|---|
| 3989 | + } |
|---|
| 3990 | + |
|---|
| 3991 | + if (dqueues & TIPC_DUMP_SK_RCVQ) { |
|---|
| 3992 | + i += scnprintf(buf + i, sz - i, "sk_receive_queue: "); |
|---|
| 3993 | + i += tipc_list_dump(&sk->sk_receive_queue, false, buf + i); |
|---|
| 3994 | + } |
|---|
| 3995 | + |
|---|
| 3996 | + if (dqueues & TIPC_DUMP_SK_BKLGQ) { |
|---|
| 3997 | + i += scnprintf(buf + i, sz - i, "sk_backlog:\n head "); |
|---|
| 3998 | + i += tipc_skb_dump(sk->sk_backlog.head, false, buf + i); |
|---|
| 3999 | + if (sk->sk_backlog.tail != sk->sk_backlog.head) { |
|---|
| 4000 | + i += scnprintf(buf + i, sz - i, " tail "); |
|---|
| 4001 | + i += tipc_skb_dump(sk->sk_backlog.tail, false, |
|---|
| 4002 | + buf + i); |
|---|
| 4003 | + } |
|---|
| 4004 | + } |
|---|
| 4005 | + |
|---|
| 4006 | + return i; |
|---|
| 4007 | +} |
|---|