From 04aba58506d4477ba598e8351e3a9075f19f8e29 Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Sat, 11 Jun 2022 13:29:31 +0200 Subject: [PATCH] add keepalive --- net/cor/conn.c | 11 +++ net/cor/conn_src_sock.c | 218 +++++++++++++++++++++++++++++++++++++++++++-- net/cor/conn_trgt_sock.c | 21 ++++- net/cor/conn_trgt_unconn.c | 1 + net/cor/cor.h | 56 +++++++++--- net/cor/settings.h | 2 + net/cor/sock_managed.c | 174 ++++++++++++++++++++++++------------ net/cor/sock_raw.c | 7 ++ 8 files changed, 406 insertions(+), 84 deletions(-) diff --git a/net/cor/conn.c b/net/cor/conn.c index 4a317d4d8287..008727b58460 100644 --- a/net/cor/conn.c +++ b/net/cor/conn.c @@ -450,6 +450,8 @@ void cor_conn_init_sock_source(struct cor_conn *cn) cn->source.sock.priority = cor_priority_max(); cn->source.sock.snd_speed.jiffies_last_refresh = jiffies; cn->source.sock.snd_speed.flushed = 1; + timer_setup(&(cn->source.sock.keepalive_timer), + cor_keepalive_req_timerfunc, 0); } void cor_conn_init_sock_target(struct cor_conn *cn) @@ -799,6 +801,12 @@ static void _cor_reset_conn(struct cor_conn *cn_ll, int trgt_out_resetneeded) cn_ll->source.sock.in_cl_list = 0; cor_conn_kref_put_bug(cn_ll, "conn_queue"); } + + if (cn_ll->source.sock.socktype == SOCKTYPE_MANAGED) { + if (del_timer(&(cn_ll->source.sock.keepalive_timer)) != + 0) + cor_conn_kref_put(cn_ll, "keepalive_snd_timer"); + } } if (cn_ll->targettype == TARGET_UNCONNECTED) { @@ -893,9 +901,12 @@ static int __init cor_init(void) printk(KERN_ERR "sizeof conn: %u\n", (__u32) sizeof(c)); printk(KERN_ERR " conn.source: %u\n", (__u32) sizeof(c.source)); printk(KERN_ERR " conn.source.in: %u\n", (__u32) sizeof(c.source.in)); + printk(KERN_ERR " conn.source.sock: %u\n", (__u32) sizeof(c.source.sock)); printk(KERN_ERR " conn.target: %u\n", (__u32) sizeof(c.target)); printk(KERN_ERR " conn.target.out: %u\n", (__u32) sizeof(c.target.out)); + printk(KERN_ERR " conn.target.sock: %u\n", + (__u32) sizeof(c.target.sock)); printk(KERN_ERR " conn.data_buf: %u\n", (__u32) sizeof(c.data_buf)); printk(KERN_ERR " conn.bufsize: %u\n", (__u32) sizeof(c.bufsize)); diff --git a/net/cor/conn_src_sock.c b/net/cor/conn_src_sock.c index 8b467c7d0828..268e5b9f3b94 100644 --- a/net/cor/conn_src_sock.c +++ b/net/cor/conn_src_sock.c @@ -25,6 +25,13 @@ static LIST_HEAD(cor_flushtoconn_oom_list); static struct delayed_work cor_flushtoconn_oom_work; +static void cor_keepalive_req_workfunc(struct work_struct *work); + +static DEFINE_SPINLOCK(cor_keepalive_req_lock); +DECLARE_WORK(cor_keepalive_req_work, cor_keepalive_req_workfunc); +static LIST_HEAD(cor_keepalive_req_list); + + static void _cor_update_src_sock_sndspeed(struct cor_snd_speed *snd_speed, __u32 timediff_jiffies) { @@ -279,22 +286,55 @@ static void _cor_mngdsocket_flushtoconn_fill_ctrl(struct cor_conn *src_sock_l) src_sock_l->source.sock.send_rcvend_needed = 0; } + if (unlikely(src_sock_l->source.sock.send_keepalive_req_needed != 0)) { + hdr |= CONN_MNGD_KEEPALIVE_REQ; + src_sock_l->source.sock.send_keepalive_req_needed = 0; + } + + if (unlikely(src_sock_l->source.sock.send_keepalive_resp_needed != 0)) { + hdr |= CONN_MNGD_KEEPALIVE_RESP; + src_sock_l->source.sock.send_keepalive_resp_needed = 0; + } + if (likely(hdr == 0)) return; BUILD_BUG_ON(CONN_MNGD_HEADERLEN != 2); BUILD_BUG_ON(sizeof(src_sock_l->source.sock.buf_ctrl.snd_hdr) != CONN_MNGD_HEADERLEN); + BUILD_BUG_ON(CONN_MNGD_MAX_CTRL_DATALEN != 8); + BUILD_BUG_ON(sizeof(src_sock_l->source.sock.buf_ctrl.snd_data) != + CONN_MNGD_MAX_CTRL_DATALEN); BUILD_BUG_ON(sizeof(src_sock_l->source.sock.buf_ctrl.snd_chksum) != CONN_MNGD_CHECKSUMLEN); cor_put_u16(&(src_sock_l->source.sock.buf_ctrl.snd_hdr[0]), hdr); + src_sock_l->source.sock.buf_ctrl.snd_data_len = 0; + + if ((hdr & CONN_MNGD_KEEPALIVE_REQ) != 0) { + BUG_ON(src_sock_l->source.sock.buf_ctrl.snd_data_len + 4 > + CONN_MNGD_MAX_CTRL_DATALEN); + cor_put_be32(&(src_sock_l->source.sock.buf_ctrl.snd_data[0]) + + src_sock_l->source.sock.buf_ctrl.snd_data_len, + src_sock_l->source.sock.keepalive_req_cookie); + src_sock_l->source.sock.buf_ctrl.snd_data_len += 4; + } + + if ((hdr & CONN_MNGD_KEEPALIVE_RESP) != 0) { + BUG_ON(src_sock_l->source.sock.buf_ctrl.snd_data_len + 4 > + CONN_MNGD_MAX_CTRL_DATALEN); + cor_put_be32(&(src_sock_l->source.sock.buf_ctrl.snd_data[0]) + + src_sock_l->source.sock.buf_ctrl.snd_data_len, + src_sock_l->source.sock.keepalive_resp_cookie); + src_sock_l->source.sock.buf_ctrl.snd_data_len += 4; + } + cor_mngdsocket_chksum( &(src_sock_l->source.sock.buf_ctrl.snd_hdr[0]), CONN_MNGD_HEADERLEN, &(src_sock_l->source.sock.buf_ctrl.snd_data[0]), - 0, + src_sock_l->source.sock.buf_ctrl.snd_data_len, &(src_sock_l->source.sock.buf_ctrl.snd_chksum[0]), CONN_MNGD_CHECKSUMLEN); @@ -329,7 +369,7 @@ static int _cor_mngdsocket_flushtoconn_ctrl(struct cor_conn *src_sock_l) &(src_sock_l->source.sock.buf_ctrl.snd_hdr[0]), CONN_MNGD_HEADERLEN, &(src_sock_l->source.sock.buf_ctrl.snd_data[0]), - 0, + src_sock_l->source.sock.buf_ctrl.snd_data_len, &(src_sock_l->source.sock.buf_ctrl.snd_chksum[0]), CONN_MNGD_CHECKSUMLEN, flush); @@ -400,7 +440,9 @@ static int _cor_mngdsocket_flushtoconn_data(struct cor_conn *src_sock_l) int _cor_mngdsocket_flushtoconn(struct cor_conn *src_sock_l) { BUG_ON(src_sock_l->sourcetype != SOURCE_SOCK); - BUG_ON(src_sock_l->isreset != 0); + + if (unlikely(src_sock_l->isreset != 0)) + return RC_FTC_OK; if (unlikely(src_sock_l->source.sock.buf_ctrl_filled != 0)) { int rc = _cor_mngdsocket_flushtoconn_ctrl(src_sock_l); @@ -469,12 +511,36 @@ static void cor_mngdsocket_flushtoconn_oomresume(struct work_struct *work) } } +void cor_mngdsocket_flushtoconn_ctrl_send_keepalive_req( + struct cor_conn *src_sock_l) +{ + int rc; + + BUG_ON(src_sock_l->source.sock.keepalive_intransit != 0); + BUG_ON(src_sock_l->source.sock.send_keepalive_req_needed != 0); + + get_random_bytes((char *) + &(src_sock_l->source.sock.keepalive_req_cookie), + sizeof(src_sock_l->source.sock.keepalive_req_cookie)); + src_sock_l->source.sock.send_keepalive_req_needed = 1; + + src_sock_l->source.sock.keepalive_intransit = 1; + src_sock_l->source.sock.jiffies_keepalive_lastact = jiffies; + + rc = _cor_mngdsocket_flushtoconn(src_sock_l); + cor_update_flushtoconn_oom_list(src_sock_l, rc == RC_FTC_OOM); +} + int cor_mngdsocket_flushtoconn_ctrl(struct cor_sock *cs_m_l, __u8 send_eof, - __u8 send_rcvend) + __u8 send_rcvend, __u8 send_keepalive_resp, + __be32 keepalive_resp_cookie) { int rc = RC_FTC_OK; - struct cor_conn *src_sock = cs_m_l->data.conn_managed.src_sock; + struct cor_conn *src_sock; + + BUG_ON(cs_m_l->type != CS_TYPE_CONN_MANAGED); + src_sock = cs_m_l->data.conn_managed.src_sock; if (unlikely(src_sock == 0)) return RC_FTC_ERR; @@ -497,6 +563,13 @@ int cor_mngdsocket_flushtoconn_ctrl(struct cor_sock *cs_m_l, __u8 send_eof, if (send_rcvend != 0) src_sock->source.sock.send_rcvend_needed = 1; + if (send_keepalive_resp != 0 && + src_sock->source.sock.send_keepalive_resp_needed == 0) { + src_sock->source.sock.keepalive_resp_cookie = + keepalive_resp_cookie; + src_sock->source.sock.send_keepalive_resp_needed = 1; + } + rc = _cor_mngdsocket_flushtoconn(src_sock); out_err: @@ -507,8 +580,7 @@ out_err: return rc; } -#warning todo keepalive -int cor_mngdsocket_flushtoconn(struct cor_sock *cs_m_l) +int cor_mngdsocket_flushtoconn_data(struct cor_sock *cs_m_l) { int rc = RC_FTC_OK; @@ -586,6 +658,138 @@ out: return rc; } +static void cor_keepalive_req_workfunc(struct work_struct *work) +{ + while (1) { + unsigned long iflags; + struct cor_conn *src_sock_o; + + spin_lock_irqsave(&cor_keepalive_req_lock, iflags); + + if (list_empty(&cor_keepalive_req_list)) { + spin_unlock_irqrestore(&cor_keepalive_req_lock, iflags); + break; + } + + src_sock_o = container_of(cor_keepalive_req_list.next, + struct cor_conn, source.sock.keepalive_lh); + + list_del(&(src_sock_o->source.sock.keepalive_lh)); + src_sock_o->source.sock.in_keepalive_list = 0; + + spin_unlock_irqrestore(&cor_keepalive_req_lock, iflags); + + + spin_lock_bh(&(src_sock_o->rcv_lock)); + + BUG_ON(src_sock_o->sourcetype != SOURCE_SOCK); + + if (likely(src_sock_o->isreset != 0)) { + spin_unlock_bh(&(src_sock_o->rcv_lock)); + } else if (src_sock_o->source.sock.keepalive_intransit == 0) { + cor_mngdsocket_flushtoconn_ctrl_send_keepalive_req( + src_sock_o); + cor_keepalive_req_sched_timer(src_sock_o); + spin_unlock_bh(&(src_sock_o->rcv_lock)); + } else { + spin_unlock_bh(&(src_sock_o->rcv_lock)); + cor_reset_conn(src_sock_o); + } + + cor_conn_kref_put(src_sock_o, "keepalive_snd_list"); + } +} + +void cor_keepalive_req_timerfunc(struct timer_list *retrans_conn_timer) +{ + struct cor_conn *src_sock_o = container_of(retrans_conn_timer, + struct cor_conn, source.sock.keepalive_timer); + spin_lock_bh(&(src_sock_o->rcv_lock)); + + BUG_ON(src_sock_o->sourcetype != SOURCE_SOCK); + + if (likely(src_sock_o->isreset == 0) && + src_sock_o->source.sock.in_keepalive_list == 0) { + unsigned long iflags; + int schedule_work_needed; + + spin_lock_irqsave(&cor_keepalive_req_lock, iflags); + + schedule_work_needed = list_empty(&cor_keepalive_req_list); + + list_add_tail(&(src_sock_o->source.sock.keepalive_lh), + &cor_keepalive_req_list); + src_sock_o->source.sock.in_keepalive_list = 1; + cor_conn_kref_get(src_sock_o, "keepalive_snd_list"); + + if (schedule_work_needed) + schedule_work(&cor_keepalive_req_work); + + spin_unlock_irqrestore(&cor_keepalive_req_lock, iflags); + } + + spin_unlock_bh(&(src_sock_o->rcv_lock)); + + cor_conn_kref_put(src_sock_o, "keepalive_snd_timer"); +} + +void cor_keepalive_req_sched_timer(struct cor_conn *src_sock_lx) +{ + unsigned long timeout; + + BUG_ON(src_sock_lx->sourcetype != SOURCE_SOCK); + + BUG_ON(src_sock_lx->source.sock.socktype != SOCKTYPE_MANAGED); + + if (src_sock_lx->source.sock.keepalive_intransit == 0) { + timeout = src_sock_lx->source.sock.jiffies_keepalive_lastact + + KEEPALIVE_INTERVAL_SECS * HZ; + } else { + timeout = src_sock_lx->source.sock.jiffies_keepalive_lastact + + KEEPALIVE_TIMEOUT_SECS * HZ; + } + + if (mod_timer(&(src_sock_lx->source.sock.keepalive_timer), timeout) == + 0) + cor_conn_kref_get(src_sock_lx, "keepalive_snd_timer"); +} + +void cor_keepalive_resp_rcvd(struct cor_sock *cs_m_l, __be32 cookie) +{ + int reset_needed = 0; + struct cor_conn *src_sock; + + BUG_ON(cs_m_l->type != CS_TYPE_CONN_MANAGED); + src_sock = cs_m_l->data.conn_managed.src_sock; + + if (unlikely(src_sock == 0)) + return; + + spin_lock_bh(&(src_sock->rcv_lock)); + + if (unlikely(cor_is_src_sock(src_sock, cs_m_l) == 0 || + src_sock->isreset != 0)) { + cs_m_l->data.conn_managed.is_reset = 1; + cor_sk_data_ready(cs_m_l); + cor_flush_buf(src_sock); + goto out_err; + } + + if (cookie != src_sock->source.sock.keepalive_req_cookie) { + reset_needed = 1; + } else { + src_sock->source.sock.keepalive_intransit = 0; + src_sock->source.sock.jiffies_keepalive_lastact = jiffies; + cor_keepalive_req_sched_timer(src_sock); + } + + spin_unlock_bh(&(src_sock->rcv_lock)); + +out_err: + if (reset_needed) + cor_reset_conn(src_sock); +} + int __init cor_conn_src_sock_init1(void) { INIT_DELAYED_WORK(&cor_flushtoconn_oom_work, diff --git a/net/cor/conn_trgt_sock.c b/net/cor/conn_trgt_sock.c index 6c70d59271dd..eb9566e43c06 100644 --- a/net/cor/conn_trgt_sock.c +++ b/net/cor/conn_trgt_sock.c @@ -48,12 +48,18 @@ static __u8 cor_flush_sock_managed_hdr(struct cor_conn *trgt_sock_lx, hdr = cor_parse_u16(&(trgt_sock_lx->target.sock.rcv_hdr[0])); - if (unlikely((hdr & CONN_MNGD_HASDATA) == 0)) { - trgt_sock_lx->target.sock.rcv_data_len = 0; - trgt_sock_lx->target.sock.rcv_hdr_flags = hdr; - } else { + trgt_sock_lx->target.sock.rcv_hdr_flags = hdr; + trgt_sock_lx->target.sock.rcv_data_len = 0; + + if (likely((hdr & CONN_MNGD_HASDATA) != 0)) { trgt_sock_lx->target.sock.rcv_data_len = (hdr & CONN_MNGD_DATALEN) + 1; + } else { + if (unlikely((hdr & CONN_MNGD_KEEPALIVE_REQ) != 0)) + trgt_sock_lx->target.sock.rcv_data_len += 4; + + if (unlikely((hdr & CONN_MNGD_KEEPALIVE_RESP) != 0)) + trgt_sock_lx->target.sock.rcv_data_len += 4; } } @@ -161,6 +167,11 @@ void cor_flush_sock_managed(struct cor_conn *trgt_sock_lx, int from_recvmsg, rc = cor_flush_sock_managed_chksum(trgt_sock_lx, do_wake_sender); out: + BUG_ON(trgt_sock_lx->target.sock.rcvd > + CONN_MNGD_HEADERLEN + + trgt_sock_lx->target.sock.rcv_data_len + + CONN_MNGD_CHECKSUMLEN); + cor_databuf_ackread(trgt_sock_lx); cor_bufsize_read_to_sock(trgt_sock_lx); @@ -189,6 +200,8 @@ out: return;*/ if (likely(rc == RCV_BUF_STATE_OK && + (trgt_sock_lx->target.sock.rcv_hdr_flags & + CONN_MNGD_HASDATA) != 0 && trgt_sock_lx->target.sock.rcv_data_len > 0)) { cor_sk_data_ready(cs); } else { diff --git a/net/cor/conn_trgt_unconn.c b/net/cor/conn_trgt_unconn.c index 4ecc95e57a9e..4881afd7c16b 100644 --- a/net/cor/conn_trgt_unconn.c +++ b/net/cor/conn_trgt_unconn.c @@ -116,6 +116,7 @@ static void cor_send_resp_bin(struct cor_conn *trgt_unconn_ll, char *buf, char hdr[5]; int len_len; + #warning todo skip execok hdr[0] = CDR_BINDATA; len_len = cor_encode_len(hdr + 1, 4, len); diff --git a/net/cor/cor.h b/net/cor/cor.h index b59327150631..567ce176a7aa 100644 --- a/net/cor/cor.h +++ b/net/cor/cor.h @@ -441,11 +441,14 @@ static inline __u8 kp_min(__u8 code) #define CRD_UTK_CONNECTERROR_REFUSED 4 #define CONN_MNGD_HEADERLEN 2 +#define CONN_MNGD_MAX_CTRL_DATALEN 8 #define CONN_MNGD_CHECKSUMLEN 4 #define CONN_MNGD_HASDATA (1 << 15) #define CONN_MNGD_EOF (1 << 0) #define CONN_MNGD_RCVEND (1 << 1) +#define CONN_MNGD_KEEPALIVE_REQ (1 << 2) +#define CONN_MNGD_KEEPALIVE_RESP (1 << 3) #define CONN_MNGD_DATALEN 4095 #define CONN_MNGD_MAX_SEGMENT_SIZE (CONN_MNGD_DATALEN + 1) @@ -897,26 +900,45 @@ struct cor_conn{ struct cor_snd_speed snd_speed; - /* protected by conn->lock */ - __u8 in_flushtoconn_oom_list; + /** + * keepalive_lh and in_keepalive_list is protected by + * cor_keepalive_req_lock + */ + struct timer_list keepalive_timer; + struct list_head keepalive_lh; + + __u8 in_keepalive_list; + __be32 keepalive_req_cookie; + __be32 keepalive_resp_cookie; + /** + * keepalive_intransit == 0... last resp received + * keepalive_intransit == 0... req sent + */ + unsigned long jiffies_keepalive_lastact; + /* protected by flushtoconn_oom_lock */ struct list_head flushtoconn_oom_lh; + /* protected by conn->rcv_lock */ + __u8 in_flushtoconn_oom_list; - __u8 buf_ctrl_filled; - __u8 buf_data_filled; - __u8 send_eof_needed:1, + __u8 keepalive_intransit:1, + buf_ctrl_filled:1, + buf_data_filled:1, + send_keepalive_req_needed:1, + send_keepalive_resp_needed:1, + send_eof_needed:1, send_rcvend_needed:1; __u8 last_windowused; - __u8 flush; - - __u16 sent; + __u8 flush:1, + socktype:1; struct{ char snd_hdr[CONN_MNGD_HEADERLEN]; - char snd_data[0]; + char snd_data[CONN_MNGD_MAX_CTRL_DATALEN]; char snd_chksum[CONN_MNGD_CHECKSUMLEN]; + __u8 snd_data_len; }buf_ctrl; struct{ @@ -925,6 +947,8 @@ struct cor_conn{ char *snd_data; __u16 snd_data_len; }buf_data; + + __u16 sent; }sock; }source; @@ -1229,10 +1253,7 @@ struct cor_sock { __u8 send_in_progress; /* receiving */ - char rcv_hdr[CONN_MNGD_HEADERLEN]; - char rcv_chksum[CONN_MNGD_CHECKSUMLEN]; char *rcv_buf; - __u16 rcv_hdr_flags; __u16 rcv_data_len; __u16 rcvbuf_consumed; __u8 rcv_buf_state; @@ -1648,9 +1669,16 @@ extern int cor_sock_sndbufavailable(struct cor_conn *src_sock_lx, extern int _cor_mngdsocket_flushtoconn(struct cor_conn *src_sock_l); extern int cor_mngdsocket_flushtoconn_ctrl(struct cor_sock *cs_m_l, - __u8 send_eof, __u8 send_rcvend); + __u8 send_eof, __u8 send_rcvend, + __u8 send_keepalive_resp, __be32 keepalive_resp_cookie); + +extern int cor_mngdsocket_flushtoconn_data(struct cor_sock *cs_m_l); + +extern void cor_keepalive_req_timerfunc(struct timer_list *retrans_conn_timer); + +extern void cor_keepalive_req_sched_timer(struct cor_conn *src_sock_lx); -extern int cor_mngdsocket_flushtoconn(struct cor_sock *cs_m_l); +extern void cor_keepalive_resp_rcvd(struct cor_sock *cs_m_l, __be32 cookie); extern int __init cor_conn_src_sock_init1(void); diff --git a/net/cor/settings.h b/net/cor/settings.h index 0fe814439f92..9baca2da6e94 100644 --- a/net/cor/settings.h +++ b/net/cor/settings.h @@ -87,6 +87,8 @@ #define SOCK_SNDSPEED_MAX (2 * 1024 * 1024) +#define KEEPALIVE_INTERVAL_SECS 300 +#define KEEPALIVE_TIMEOUT_SECS 120 /* #define DEBUG_QOS_SLOWSEND */ /* #define COR_DEBUG */ diff --git a/net/cor/sock_managed.c b/net/cor/sock_managed.c index ffc96b89f649..72eecfb94af9 100644 --- a/net/cor/sock_managed.c +++ b/net/cor/sock_managed.c @@ -578,12 +578,18 @@ int cor_mngdsocket_accept(struct socket *sock, struct socket *newsock, kref_get(&(newcs->ref)); BUG_ON(newcs->data.conn_managed.rcv_buf == 0); + src_sock_o->source.sock.socktype = SOCKTYPE_MANAGED; trgt_sock_o->target.sock.socktype = SOCKTYPE_MANAGED; trgt_sock_o->target.sock.rcv_buf_state = RCV_BUF_STATE_INCOMPLETE; trgt_sock_o->target.sock.rcv_buf = newcs->data.conn_managed.rcv_buf; trgt_sock_o->target.sock.rcvd = 0; + + BUG_ON(src_sock_o->source.sock.keepalive_intransit != 0); + src_sock_o->source.sock.jiffies_keepalive_lastact = jiffies - + KEEPALIVE_INTERVAL_SECS * HZ + HZ; + cor_keepalive_req_sched_timer(src_sock_o); } newcs->data.conn_managed.connect_state = CS_CONNECTSTATE_CONNECTED; @@ -655,7 +661,8 @@ static void _cor_mngdsocket_shutdown(struct cor_sock *cs_m_l, int flags) } if (send_eof != 0 || send_rcvend != 0) - cor_mngdsocket_flushtoconn_ctrl(cs_m_l, send_eof, send_rcvend); + cor_mngdsocket_flushtoconn_ctrl(cs_m_l, send_eof, send_rcvend, + 0, 0); } int cor_mngdsocket_shutdown(struct socket *sock, int flags) @@ -892,7 +899,7 @@ static int _cor_mngdsocket_sendmsg(struct msghdr *msg, __u32 totallen, cs->data.conn_managed.snd_data_len == cs->data.conn_managed.snd_segment_size)) { cs->data.conn_managed.flush = 0; - cor_mngdsocket_flushtoconn(cs); + cor_mngdsocket_flushtoconn_data(cs); if (cs->data.conn_managed.send_in_progress != 0 || cs->data.conn_managed.snd_data_len == cs->data.conn_managed.snd_segment_size) { @@ -933,7 +940,7 @@ static int _cor_mngdsocket_sendmsg(struct msghdr *msg, __u32 totallen, if (flush != 0 || cs->data.conn_managed.snd_data_len == cs->data.conn_managed.snd_segment_size) { - cor_mngdsocket_flushtoconn(cs); + cor_mngdsocket_flushtoconn_data(cs); } out: @@ -998,12 +1005,92 @@ int cor_mngdsocket_sendmsg(struct socket *sock, struct msghdr *msg, return copied; } +static void __cor_mngdsocket_readfromconn(struct cor_sock *cs_m_l, + struct cor_conn *trgt_sock_l, + __u8 *send_eof, __u8 *send_rcvend, + __u8 *keepalive_req_rcvd, + __be32 *keepalive_req_cookie, + __u8 *keepalive_resp_rcvd, + __be32 *keepalive_resp_cookie) +{ + __u16 rcvbuf_consumed = 0; + + BUG_ON(trgt_sock_l->target.sock.rcv_buf_state != RCV_BUF_STATE_OK); + + if (likely((trgt_sock_l->target.sock.rcv_hdr_flags & + CONN_MNGD_HASDATA) != 0)) { + if (unlikely(trgt_sock_l->target.sock.rcv_data_len == 0 || + cs_m_l->data.conn_managed.shutdown_rd != 0)) + cs_m_l->data.conn_managed.rcv_data_len = 0; + else + cs_m_l->data.conn_managed.rcv_data_len = + trgt_sock_l->target.sock.rcv_data_len; + cs_m_l->data.conn_managed.rcv_buf_state = RCV_BUF_STATE_OK; + return; + } + + if (unlikely((trgt_sock_l->target.sock.rcv_hdr_flags & + CONN_MNGD_EOF) != 0)) { + if (cs_m_l->data.conn_managed.sent_rcvend == 0) { + *send_rcvend = 1; + cs_m_l->data.conn_managed.sent_rcvend = 1; + } + + cs_m_l->data.conn_managed.rcvd_eof = 1; + } + + if (unlikely((trgt_sock_l->target.sock.rcv_hdr_flags & + CONN_MNGD_RCVEND) != 0)) { + if (cs_m_l->data.conn_managed.sent_eof == 0) { + *send_eof = 1; + cs_m_l->data.conn_managed.sent_eof = 1; + } + + cs_m_l->data.conn_managed.rcvd_rcvend = 1; + } + + if (unlikely((trgt_sock_l->target.sock.rcv_hdr_flags & + CONN_MNGD_KEEPALIVE_REQ) != 0)) { + BUG_ON(rcvbuf_consumed + 4 > + trgt_sock_l->target.sock.rcv_data_len); + + *keepalive_req_cookie = cor_parse_be32( + trgt_sock_l->target.sock.rcv_buf + + rcvbuf_consumed); + rcvbuf_consumed += 4; + + *keepalive_req_rcvd = 1; + } + + if (unlikely((trgt_sock_l->target.sock.rcv_hdr_flags & + CONN_MNGD_KEEPALIVE_RESP) != 0)) { + BUG_ON(rcvbuf_consumed + 4 > + trgt_sock_l->target.sock.rcv_data_len); + + *keepalive_resp_cookie = cor_parse_be32( + trgt_sock_l->target.sock.rcv_buf + + rcvbuf_consumed); + rcvbuf_consumed += 4; + + *keepalive_resp_rcvd = 1; + } + + BUG_ON(rcvbuf_consumed != trgt_sock_l->target.sock.rcv_data_len); + + trgt_sock_l->target.sock.rcv_buf_state = RCV_BUF_STATE_INCOMPLETE; + trgt_sock_l->target.sock.rcvd = 0; +} + static void _cor_mngdsocket_readfromconn(struct cor_sock *cs_m_l) { __u8 do_wake_sender = 0; int reset_needed = 0; __u8 send_eof = 0; __u8 send_rcvend = 0; + __u8 keepalive_req_rcvd = 0; + __be32 keepalive_req_cookie = 0; + __u8 keepalive_resp_rcvd = 0; + __be32 keepalive_resp_cookie = 0; struct cor_conn *trgt_sock = cs_m_l->data.conn_managed.trgt_sock; @@ -1020,11 +1107,7 @@ static void _cor_mngdsocket_readfromconn(struct cor_sock *cs_m_l) BUG_ON(trgt_sock->target.sock.rcv_buf != cs_m_l->data.conn_managed.rcv_buf); - while (1) { - if (cs_m_l->data.conn_managed.rcv_buf_state == - RCV_BUF_STATE_INCOMPLETE) - goto skip_reset_bufstate; - + if (cs_m_l->data.conn_managed.rcv_buf_state == RCV_BUF_STATE_OK) { cs_m_l->data.conn_managed.rcv_data_len = 0; cs_m_l->data.conn_managed.rcvbuf_consumed = 0; cs_m_l->data.conn_managed.rcv_buf_state = @@ -1033,62 +1116,29 @@ static void _cor_mngdsocket_readfromconn(struct cor_sock *cs_m_l) trgt_sock->target.sock.rcv_buf_state = RCV_BUF_STATE_INCOMPLETE; trgt_sock->target.sock.rcvd = 0; + } -skip_reset_bufstate: + while (cs_m_l->data.conn_managed.rcv_buf_state == + RCV_BUF_STATE_INCOMPLETE) { cor_flush_sock_managed(trgt_sock, 1, &do_wake_sender); - BUG_ON(trgt_sock->target.sock.rcvd > - CONN_MNGD_HEADERLEN + - trgt_sock->target.sock.rcv_data_len + - CONN_MNGD_CHECKSUMLEN); if (trgt_sock->target.sock.rcv_buf_state == - RCV_BUF_STATE_INCOMPLETE) + RCV_BUF_STATE_INCOMPLETE) { break; - - cs_m_l->data.conn_managed.rcv_hdr_flags = - trgt_sock->target.sock.rcv_hdr_flags; - cs_m_l->data.conn_managed.rcv_data_len = - trgt_sock->target.sock.rcv_data_len; - cs_m_l->data.conn_managed.rcv_buf_state = - trgt_sock->target.sock.rcv_buf_state; - - if (unlikely(cs_m_l->data.conn_managed.rcv_buf_state == - RCV_BUF_STATE_RESET)) + } else if (unlikely(trgt_sock->target.sock.rcv_buf_state == + RCV_BUF_STATE_RESET)) { goto reset; - - BUG_ON(cs_m_l->data.conn_managed.rcv_buf_state != - RCV_BUF_STATE_OK); - - if (likely((cs_m_l->data.conn_managed.rcv_hdr_flags & - CONN_MNGD_HASDATA) != 0)) - goto skip_low_hdrflags; - - if (unlikely((cs_m_l->data.conn_managed.rcv_hdr_flags & - CONN_MNGD_EOF) != 0)) { - if (cs_m_l->data.conn_managed.sent_rcvend == 0) { - send_rcvend = 1; - cs_m_l->data.conn_managed.sent_rcvend = 1; - } - - cs_m_l->data.conn_managed.rcvd_eof = 1; - } - - if (unlikely((cs_m_l->data.conn_managed.rcv_hdr_flags & - CONN_MNGD_RCVEND) != 0)) { - if (cs_m_l->data.conn_managed.sent_eof == 0) { - send_eof = 1; - cs_m_l->data.conn_managed.sent_eof = 1; - } - - cs_m_l->data.conn_managed.rcvd_rcvend = 1; + } else { + BUG_ON(trgt_sock->target.sock.rcv_buf_state != + RCV_BUF_STATE_OK); + + __cor_mngdsocket_readfromconn(cs_m_l, trgt_sock, + &send_eof, &send_rcvend, + &keepalive_req_rcvd, + &keepalive_req_cookie, + &keepalive_resp_rcvd, + &keepalive_resp_cookie); } - -skip_low_hdrflags: - cs_m_l->data.conn_managed.rcv_hdr_flags = 0; - - if (likely(cs_m_l->data.conn_managed.rcv_data_len > 0 && - cs_m_l->data.conn_managed.shutdown_rd == 0)) - break; } if (unlikely(cs_m_l->data.conn_managed.rcvd_eof != 0 && @@ -1114,14 +1164,20 @@ reset: cs_m_l->data.conn_managed.is_reset = 1; cor_sk_data_ready(cs_m_l); cor_sk_write_space(cs_m_l); + + return; } else if (do_wake_sender != 0) { cor_wake_sender(trgt_sock); } - if (unlikely(send_eof != 0 || send_rcvend != 0)) { + if (unlikely(send_eof != 0 || send_rcvend != 0 || + keepalive_req_rcvd != 0)) { cor_mngdsocket_flushtoconn_ctrl(cs_m_l, send_eof, - send_rcvend); + send_rcvend, keepalive_req_rcvd, + keepalive_req_cookie); } + if (unlikely(keepalive_resp_rcvd != 0)) + cor_keepalive_resp_rcvd(cs_m_l, keepalive_resp_cookie); } #define RC_RFC_OK 0 diff --git a/net/cor/sock_raw.c b/net/cor/sock_raw.c index 884f0d60c280..68d97b3cc0c1 100644 --- a/net/cor/sock_raw.c +++ b/net/cor/sock_raw.c @@ -80,11 +80,17 @@ static int cor_rawsocket_release_trypasssocket(struct cor_sock *cs) src_sock->source.sock.priority = cs->priority; BUG_ON(passto->data.conn_managed.rcv_buf == 0); + src_sock->source.sock.socktype = SOCKTYPE_MANAGED; trgt_sock->target.sock.socktype = SOCKTYPE_MANAGED; trgt_sock->target.sock.rcv_buf_state = RCV_BUF_STATE_INCOMPLETE; trgt_sock->target.sock.rcv_buf = passto->data.conn_managed.rcv_buf; trgt_sock->target.sock.rcvd = 0; + BUG_ON(src_sock->source.sock.keepalive_intransit != 0); + src_sock->source.sock.jiffies_keepalive_lastact = jiffies - + KEEPALIVE_INTERVAL_SECS * HZ + HZ; + cor_keepalive_req_sched_timer(src_sock); + cor_conn_refresh_priority(src_sock, 1); rc = 1; @@ -226,6 +232,7 @@ int cor_rawsocket_connect(struct socket *sock, struct sockaddr *saddr, kref_get(&(cs->ref)); kref_get(&(cs->ref)); + src_sock->source.sock.socktype = SOCKTYPE_RAW; trgt_sock->target.sock.socktype = SOCKTYPE_RAW; src_sock->source.sock.priority = cs->priority; -- 2.11.4.GIT