IPVS中的PE引擎结构

负载均衡 专栏收录该内容
42 篇文章 4 订阅

如下配置命令指定使用Persistence功能,并且PE引擎(Persistence Engine)指定为sip。

$ sudo ipvsadm -A -t 207.175.44.110:80 -s rr -p --pe sip
$ 
$ sudo ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  207.175.44.110:80 rr persistent 360 pe sip

由于FTP连接包含控制和数据两个部分,如果使用Direct Routing 或者 Tunnelling作为虚拟服务的转发模式,那么必须开启Persistence功能,以便保证FTP的控制和数据连接在同一个真实服务器上处理。如果使用的是Masquerading/NAT转发模式,Persistence功能就不是必须的了,但是需要加载ip_vs_ftp模块,此模块负责保证FTP的控制和数据连接分配到同一个真实服务器上。

PE模块的注册

函数register_ip_vs_pe负责PE引擎的注册,内核注册的PE链接在全局链表ip_vs_pe上。PE引擎以名称作为关键字,所以不同的PE引擎不能够重名。

static LIST_HEAD(ip_vs_pe);

int register_ip_vs_pe(struct ip_vs_pe *pe)
{
    struct ip_vs_pe *tmp;

    mutex_lock(&ip_vs_pe_mutex);
    /* Make sure that the pe with this name doesn't exist in the pe list. */
    list_for_each_entry(tmp, &ip_vs_pe, n_list) {
            if (strcmp(tmp->name, pe->name) == 0) {
                    mutex_unlock(&ip_vs_pe_mutex);
                    ip_vs_use_count_dec();
                    pr_err("%s(): [%s] pe already existed in the system\n", __func__, pe->name);
                    return -EINVAL;
            }
    }
    /* Add it into the d-linked pe list */
    list_add_rcu(&pe->n_list, &ip_vs_pe);
}

PE引擎的查找

参见以下函数ip_vs_pe_getbyname,由于PE引擎以名称作为标识,此处使用名称进行查找。首先使用核心查找函数__ip_vs_pe_getbyname进行查找;如果没有找到,有可能是因为请求的PE模块没有加载,执行模块加载之后,进行再次查找。

struct ip_vs_pe *ip_vs_pe_getbyname(const char *name)
{
        struct ip_vs_pe *pe;

        pe = __ip_vs_pe_getbyname(name);

        /* If pe not found, load the module and search again */
        if (!pe) {
                request_module("ip_vs_pe_%s", name);
                pe = __ip_vs_pe_getbyname(name);
        }

        return pe;
}

核心查找函数__ip_vs_pe_getbyname遍历全局PE链表:ip_vs_pe,对比其中的PE名称与请求的名称,如果相等,返回找到的PE结构。

struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
{
        struct ip_vs_pe *pe;

        rcu_read_lock();
        list_for_each_entry_rcu(pe, &ip_vs_pe, n_list) {
                /* Test and get the modules atomically */
                if (pe->module && !try_module_get(pe->module)) 
                        continue;         /* This pe is just deleted */
                
                if (strcmp(pe_name, pe->name)==0) {
                        rcu_read_unlock();
                        return pe;        /* HIT */
                }
                module_put(pe->module);
        }
}

虚拟服务中的PE绑定

在添加虚拟服务函数ip_vs_add_service中,如果用户层配置中指定了PE名称,内核调用上节介绍的ip_vs_pe_getbyname根据此名称查找对应的PE引擎结构,如果找到,将此结构绑定到新创建的ip_vs_service结构的pe成员上。

static int ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, struct ip_vs_service **svc_p)
{
    struct ip_vs_pe *pe = NULL;
    struct ip_vs_service *svc = NULL;

    if (u->pe_name && *u->pe_name) {
        pe = ip_vs_pe_getbyname(u->pe_name);
        if (pe == NULL) {
            pr_info("persistence engine module ip_vs_pe_%s not found\n", u->pe_name);
            ret = -ENOENT;
            goto out_err;
        }
    }

    /* Bind the ct retriever */
    RCU_INIT_POINTER(svc->pe, pe);
}

内核版本 4.15

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值