dpvs conn超时处理

  • 连接定时器处理函数设置

    • 超时处理函数为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源码阅读笔记)