-
连接定时器处理函数设置
- 超时处理函数为dp_vs_conn_expire
- 设置priv为当前conn
static void dp_vs_conn_attach_timer(struct dp_vs_conn *conn, bool lock) { int rc; //如果conn->timer正在运行中,则直接返回 if (dp_vs_conn_is_in_timer(conn)) { return; } //如果为长连接,则将定时器加入到global_timer中,否则加入至per-lcore timer中 if (dp_vs_conn_is_template(conn)) { if (lock) { rc = dpvs_timer_sched(&conn->timer, &conn->timeout, dp_vs_conn_expire, conn, true); } else { rc = dpvs_timer_sched_nolock(&conn->timer, &conn->timeout, dp_vs_conn_expire, conn, true); } } else { if (lock) { rc = dpvs_timer_sched(&conn->timer, &conn->timeout, dp_vs_conn_expire, conn, false); } else { rc = dpvs_timer_sched_nolock(&conn->timer, &conn->timeout, dp_vs_conn_expire, conn, false); } } if (rc == EDPVS_OK) { //设置conn->timer正在运行中 dp_vs_conn_set_in_timer(conn); } }
-
dp_vs_conn_expire
/* timeout hanlder */ static int dp_vs_conn_expire(void *priv) { //拿到设置的priv,即超时的conn struct dp_vs_conn * conn = priv; struct dp_vs_proto *pp; assert(conn); assert(conn->af == AF_INET || conn->af == AF_INET6); assert(rte_atomic32_read(&conn->refcnt) > 0); //获取对应的传输层接口实例,例如tcp层为dp_vs_proto_tcp pp = dp_vs_proto_lookup(conn->proto); //重新获取conn超时时间 dp_vs_conn_set_timeout(conn, pp); //增加conn的引用 rte_atomic32_inc(&conn->refcnt); //此处主要在syn_retry开启时,重新发送syn包至RS if (dp_vs_conn_resend_packets(conn, pp) == EDPVS_OK) { /* expire later */ dp_vs_conn_put_nolock(conn); return(DTIMER_OK); } /* somebody is controlled by me, expire later */ //TODO:此处暂时还未看明白,好像跟什么dp_vs_sched_persist 长连接有关 if (rte_atomic32_read(&conn->n_control)) { dp_vs_conn_put_nolock(conn); return(DTIMER_OK); } /* unhash it then no further user can get it, * even we cannot del it now. */ //开始清理流表,这样后续就查找不到了 dp_vs_conn_unhash(conn); /* refcnt == 1 means we are the only referer. * no one is using the conn and it's timed out. */ //引用计数为1时, if (rte_atomic32_read(&conn->refcnt) == 1) { //首先删除定时器 dp_vs_conn_detach_timer(conn, false); /* I was controlled by someone */ if (conn->control) { dp_vs_control_del(conn); } //如果传输层协议有conn_expire接口,调用连接超时接口,tcp中为tcp_conn_expire,主要用于在fnat模式下向两端发送rst包 //强制断开连接 if (pp && pp->conn_expire) { pp->conn_expire(pp, conn); } //snat模式中清除sa_pool dp_vs_conn_sa_release(conn); //解绑RS之间的关系,主要减少活动连接之类的统计信息 dp_vs_conn_unbind_dest(conn); //释放本地地址 dp_vs_laddr_unbind(conn); //清理ack_mbuf,syn_mbuf等等 dp_vs_conn_free_packets(conn); //减少连接的引用技术 rte_atomic32_dec(&conn->refcnt); #ifdef CONFIG_DPVS_IPVS_STATS_DEBUG conn_stats_dump("del conn", conn); #endif #ifdef CONFIG_DPVS_IPVS_DEBUG conn_dump("del conn: ", conn); #endif //释放回缓存池 dp_vs_conn_free(conn); return(DTIMER_STOP); } //走到这里,说明连接还有人在用,那么加回流表 dp_vs_conn_hash(conn); /* some one is using it when expire, * try del it again later */ //如果走到这里,说明连接还有人在用,那么更新超时时间加回定时器 dp_vs_conn_refresh_timer(conn, false); rte_atomic32_dec(&conn->refcnt); return(DTIMER_OK); }
-
tcp_conn_expire
- 在nat和fnat这种双臂模式下,向两端发送rst包断链
static int tcp_conn_expire(struct dp_vs_proto *proto, struct dp_vs_conn *conn) { int err; assert(proto && conn && conn->dest); if (conn->dest->fwdmode == DPVS_FWD_MODE_NAT || conn->dest->fwdmode == DPVS_FWD_MODE_FNAT) { /* send RST to RS and client */ err = tcp_send_rst(proto, conn, DPVS_CONN_DIR_INBOUND); if (err != EDPVS_OK) { RTE_LOG(WARNING, IPVS, "%s: fail RST RS.\\n", __func__); } err = tcp_send_rst(proto, conn, DPVS_CONN_DIR_OUTBOUND); if (err != EDPVS_OK) { RTE_LOG(WARNING, IPVS, "%s: fail RST Client.\\n", __func__); } } return(EDPVS_OK); }
dpvs conn超时处理
最新推荐文章于 2024-04-02 17:39:08 发布