Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kcm: Add receive message timeout

This patch adds receive timeout for message assembly on the attached TCP
sockets. The timeout is set when a new messages is started and the whole
message has not been received by TCP (not in the receive queue). If the
completely message is subsequently received the timer is cancelled, if the
timer expires the RX side is aborted.

The timeout value is taken from the socket timeout (SO_RCVTIMEO) that is
set on a TCP socket (i.e. set by get sockopt before attaching a TCP socket
to KCM.

Signed-off-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tom Herbert and committed by
David S. Miller
29152a34 7ced95ef

+39 -2
+3
include/net/kcm.h
··· 29 29 unsigned int rx_mem_fail; 30 30 unsigned int rx_need_more_hdr; 31 31 unsigned int rx_msg_too_big; 32 + unsigned int rx_msg_timeouts; 32 33 unsigned int rx_bad_hdr_len; 33 34 unsigned long long reserved; 34 35 unsigned long long unreserved; ··· 131 130 struct kcm_sock *rx_kcm; 132 131 unsigned long long saved_rx_bytes; 133 132 unsigned long long saved_rx_msgs; 133 + struct timer_list rx_msg_timer; 134 134 unsigned int rx_need_bytes; 135 135 136 136 /* Transmit */ ··· 196 194 SAVE_PSOCK_STATS(rx_mem_fail); 197 195 SAVE_PSOCK_STATS(rx_need_more_hdr); 198 196 SAVE_PSOCK_STATS(rx_msg_too_big); 197 + SAVE_PSOCK_STATS(rx_msg_timeouts); 199 198 SAVE_PSOCK_STATS(rx_bad_hdr_len); 200 199 SAVE_PSOCK_STATS(tx_msgs); 201 200 SAVE_PSOCK_STATS(tx_bytes);
+4 -2
net/kcm/kcmproc.c
··· 331 331 mux_stats.rx_ready_drops); 332 332 333 333 seq_printf(seq, 334 - "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n", 334 + "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n", 335 335 "Psock", 336 336 "RX-Msgs", 337 337 "RX-Bytes", ··· 344 344 "RX-NeedMor", 345 345 "RX-BadLen", 346 346 "RX-TooBig", 347 + "RX-Timeout", 347 348 "TX-Aborts"); 348 349 349 350 seq_printf(seq, 350 - "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u\n", 351 + "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n", 351 352 "", 352 353 psock_stats.rx_msgs, 353 354 psock_stats.rx_bytes, ··· 361 360 psock_stats.rx_need_more_hdr, 362 361 psock_stats.rx_bad_hdr_len, 363 362 psock_stats.rx_msg_too_big, 363 + psock_stats.rx_msg_timeouts, 364 364 psock_stats.tx_aborts); 365 365 366 366 return 0;
+32
net/kcm/kcmsock.c
··· 55 55 56 56 /* Unrecoverable error in receive */ 57 57 58 + del_timer(&psock->rx_msg_timer); 59 + 58 60 if (psock->rx_stopped) 59 61 return; 60 62 ··· 353 351 spin_unlock_bh(&mux->rx_lock); 354 352 } 355 353 354 + static void kcm_start_rx_timer(struct kcm_psock *psock) 355 + { 356 + if (psock->sk->sk_rcvtimeo) 357 + mod_timer(&psock->rx_msg_timer, psock->sk->sk_rcvtimeo); 358 + } 359 + 356 360 /* Macro to invoke filter function. */ 357 361 #define KCM_RUN_FILTER(prog, ctx) \ 358 362 (*prog->bpf_func)(ctx, prog->insnsi) ··· 508 500 509 501 if (!len) { 510 502 /* Need more header to determine length */ 503 + if (!rxm->accum_len) { 504 + /* Start RX timer for new message */ 505 + kcm_start_rx_timer(psock); 506 + } 511 507 rxm->accum_len += cand_len; 512 508 eaten += cand_len; 513 509 KCM_STATS_INCR(psock->stats.rx_need_more_hdr); ··· 552 540 * but don't consume yet per tcp_read_sock. 553 541 */ 554 542 543 + if (!rxm->accum_len) { 544 + /* Start RX timer for new message */ 545 + kcm_start_rx_timer(psock); 546 + } 547 + 555 548 psock->rx_need_bytes = rxm->full_len - 556 549 rxm->accum_len; 557 550 rxm->accum_len += cand_len; ··· 580 563 eaten += (cand_len - extra); 581 564 582 565 /* Hurray, we have a new message! */ 566 + del_timer(&psock->rx_msg_timer); 583 567 psock->rx_skb_head = NULL; 584 568 KCM_STATS_INCR(psock->stats.rx_msgs); 585 569 ··· 1674 1656 spin_unlock_bh(&mux->rx_lock); 1675 1657 } 1676 1658 1659 + static void kcm_rx_msg_timeout(unsigned long arg) 1660 + { 1661 + struct kcm_psock *psock = (struct kcm_psock *)arg; 1662 + 1663 + /* Message assembly timed out */ 1664 + KCM_STATS_INCR(psock->stats.rx_msg_timeouts); 1665 + kcm_abort_rx_psock(psock, ETIMEDOUT, NULL); 1666 + } 1667 + 1677 1668 static int kcm_attach(struct socket *sock, struct socket *csock, 1678 1669 struct bpf_prog *prog) 1679 1670 { ··· 1712 1685 psock->mux = mux; 1713 1686 psock->sk = csk; 1714 1687 psock->bpf_prog = prog; 1688 + 1689 + setup_timer(&psock->rx_msg_timer, kcm_rx_msg_timeout, 1690 + (unsigned long)psock); 1691 + 1715 1692 INIT_WORK(&psock->rx_work, psock_rx_work); 1716 1693 INIT_DELAYED_WORK(&psock->rx_delayed_work, psock_rx_delayed_work); 1717 1694 ··· 1827 1796 1828 1797 write_unlock_bh(&csk->sk_callback_lock); 1829 1798 1799 + del_timer_sync(&psock->rx_msg_timer); 1830 1800 cancel_work_sync(&psock->rx_work); 1831 1801 cancel_delayed_work_sync(&psock->rx_delayed_work); 1832 1802