.. | .. |
---|
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 | +} |
---|