ipvs學習筆記(一)


十分感謝yfydz老大發布ip_vs實現分析系列文章,這使我能盡快理解ipvs的工作原理與源碼組成。

不過yfydz的文章過於長,不便於后續檢索。我計划逐步整理,發到blog上。

 

1ipvs分為三種負載均衡模式

NATtunneldirect routingDR

NAT:所有交互數據必須通過均衡器

tunnel:半連接處理方式,進行了IP封裝

DR:修改MAC地址,需要同一網段。

 

2ipvs支持的均衡調度算法

輪叫調度(Round-Robin Scheduling) 

加權輪叫調度(Weighted Round-Robin Scheduling) 

最小連接調度(Least-Connection Scheduling) 

加權最小連接調度(Weighted Least-Connection Scheduling) 

基於局部性的最少鏈接(Locality-Based Least Connections Scheduling) 

帶復制的基於局部性最少鏈接(Locality-Based Least Connections with Replication Scheduling) 

目標地址散列調度(Destination Hashing Scheduling) 

源地址散列調度(Source Hashing Scheduling)

 

3ipvs代碼記錄

內核為 Linux-kernel 3.3.7

 

3.1、結構體

ipvs各結構體定義在include\net\ip_vs.hinclude\linux\ip_vs.h頭文件中

struct ip_vs_protocol

這個結構用來描述ipvs支持的IP協議。ipvs的IP層協議支持TCP, UDP, AH和ESP這4種IP層協議

struct ip_vs_conn

這個結構用來描述ipvs的鏈接

struct ip_vs_service

這個結構用來描述ipvs對外的虛擬服務器信息

struct ip_vs_dest

這個結構用來描述具體的真實服務器信息

struct ip_vs_scheduler

這個結構用來描述ipvs調度算法,目前調度方法包括rr,wrr,lc, wlc, lblc, lblcr, dh, sh等

struct ip_vs_app

這個結構用來描述ipvs的應用模塊對象

struct ip_vs_service_user

這個結構用來描述ipvs用戶空間的虛擬服務信息

struct ip_vs_dest_user

這個結構用來描述ipvs用戶空間的真實服務器信息

struct ip_vs_stats_user

這個結構用來描述ipvs用戶空間的統計信息

struct ip_vs_getinfo

這個結構用來描述ipvs用戶空間的獲取信息

struct ip_vs_service_entry

這個結構用來描述ipvs用戶空間的服務規則項信息

struct ip_vs_dest_entry

這個結構用來描述ipvs用戶空間的真實服務器規則項信息

struct ip_vs_get_dests

這個結構用來描述ipvs用戶空間的獲取真實服務器項信息

struct ip_vs_get_services

這個結構用來描述ipvs用戶空間的獲取虛擬服務項信息

struct ip_vs_timeout_user

這個結構用來描述ipvs用戶空間的超時信息

struct ip_vs_daemon_user

這個結構用來描述ipvs的內核守護進程信息

 

3.2、模塊初始化

net\netfilter\ipvs\ip_vs_core.c文件

static int __init ip_vs_init(void)

ipvs服務初始化

net\netfilter\ipvs\ip_vs_ctl.c文件

int __init ip_vs_control_init(void)

ioctl初始化

net\netfilter\ipvs\ip_vs_proto.c文件

int __init ip_vs_protocol_init(void)

協議初始化

net\netfilter\ipvs\ip_vs_conn.c文件

int __init ip_vs_conn_init(void)

連接初始化

net\netfilter\ipvs\ip_vs_core.c文件

static struct nf_hook_ops ip_vs_ops[]

ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));

netfilter掛接點數組,具體的數據包處理見數組中對應.hook的函數

 

3.3、調度算法具體實現

各算法與ip_vs_scheduler結構體對應

rr算法在net\netfilter\ipvs\ip_vs_rr.c文件中實現,以此類推。

static struct ip_vs_scheduler ip_vs_rr_scheduler = {

.name =                        "rr",                        /* name */

.refcnt =                ATOMIC_INIT(0),

.module =                THIS_MODULE,

.n_list =                LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),

.init_service =                ip_vs_rr_init_svc,

.update_service =        ip_vs_rr_update_svc,

.schedule =                ip_vs_rr_schedule,

};

init_service

算法初始化,在虛擬服務ip_vs_service和調度器綁定時調用(ip_vs_bind_scheduler()函數)

update_service()

函數在目的服務器變化時調用(如ip_vs_add_dest(), ip_vs_edit_dest()等函數)

而算法核心函數schedule()則是在ip_vs_schedule()函數中在新建IPVS連接前調用,找到真正的服務器提供服務,建立IPVS連接。

具體的算法實現看源代碼+yfydz老大的ipvs實現分析。

 

3.4、連接管理

net\netfilter\ipvs\ip_vs_conn.c文件

struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)

進入方向

struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)

發出方向

struct ip_vs_conn *

ip_vs_conn_new(const struct ip_vs_conn_param *p,

       const union nf_inet_addr *daddr, __be16 dport, unsigned flags,

       struct ip_vs_dest *dest, __u32 fwmark)

建立連接

static inline void

ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)

綁定真實服務器

int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp)

綁定應用協議

static inline void ip_vs_bind_xmit(struct ip_vs_conn *cp)

綁定發送方法

static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)

將連接結構添加到連接hash

static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)

從連接hash表中斷開

static void ip_vs_conn_expire(unsigned long data)

連接超時

static inline void ip_vs_control_del(struct ip_vs_conn *cp)

從主連接中斷開

void ip_vs_unbind_app(struct ip_vs_conn *cp)

解除與應用的綁定

static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)

接觸與真實服務器的綁定

static void ip_vs_conn_flush(struct net *net)

釋放所有連接

void ip_vs_random_dropentry(struct net *net)

定時隨即刪除連接

static inline int todrop_entry(struct ip_vs_conn *cp)

判斷是否要刪除連接

 

3.5、協議管理

net\netfilter\ipvs\ip_vs_proto.c文件

static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)

注冊一個ipvs協議

static int unregister_ip_vs_protocol(struct ip_vs_protocol *pp)

注銷一個ipvs協議

struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto)

查找服務,返回服務結構指針

void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags)

修改協議超時標記

int *ip_vs_create_timeout_table(int *table, int size)

創建狀態超時表

Int ip_vs_set_state_timeout(int *table, int num, const char *const *names,

const char *name, int to)

修改狀態超時表

const char * ip_vs_state_name(__u16 proto, int state)

返回協議狀態名稱

下面以TCP協議的實現來詳細說明,相關代碼文件為net\netfilter\ipvs\ip_vs_proto_tcp.c

struct ip_vs_protocol ip_vs_protocol_tcp = {

.name =                        "TCP",

.protocol =                IPPROTO_TCP,

.num_states =                IP_VS_TCP_S_LAST,

.dont_defrag =                0,

.init =                        NULL,

.exit =                        NULL,

.init_netns =                __ip_vs_tcp_init,

.exit_netns =                __ip_vs_tcp_exit,

.register_app =                tcp_register_app,

.unregister_app =        tcp_unregister_app,

.conn_schedule =        tcp_conn_schedule,

.conn_in_get =                ip_vs_conn_in_get_proto,

.conn_out_get =                ip_vs_conn_out_get_proto,

.snat_handler =                tcp_snat_handler,

.dnat_handler =                tcp_dnat_handler,

.csum_check =                tcp_csum_check,

.state_name =                tcp_state_name,

.state_transition =        tcp_state_transition,

.app_conn_bind =        tcp_app_conn_bind,

.debug_packet =                ip_vs_tcpudp_debug_packet,

.timeout_change =        tcp_timeout_change,

};

static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)

tcp初始化函數

static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd)

tcp退出函數

static int tcp_register_app(struct net *net, struct ip_vs_app *inc)

注冊tcp應用協議

static voidtcp_unregister_app(struct net *net, struct ip_vs_app *inc)

注銷tcp應用協議

static int

tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,

  int *verdict, struct ip_vs_conn **cpp)

tcp連接調度,該函數在ip_vs_in()函數中調用。

struct ip_vs_conn *

ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,

const struct ip_vs_iphdr *iph,

unsigned int proto_off, int inverse)

進入方向連接查找

struct ip_vs_conn *

ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,

 const struct ip_vs_iphdr *iph,

 unsigned int proto_off, int inverse)

發出方向連接查找

static int

tcp_snat_handler(struct sk_buff *skb,

 struct ip_vs_protocol *pp, struct ip_vs_conn *cp)

該函數完成對協議部分數據進行源NAT操作,對TCP來說,NAT部分的數據就是源端口

static inline void

tcp_fast_csum_update(int af, struct tcphdr *tcph,

     const union nf_inet_addr *oldip,

     const union nf_inet_addr *newip,

     __be16 oldport, __be16 newport)

TCP校驗和快速計算法,因為只修改了端口一個參數,可根據RFC1141方法快速計算

static int

tcp_dnat_handler(struct sk_buff *skb,

 struct ip_vs_protocol *pp, struct ip_vs_conn *cp)

該函數完成對協議部分數據進行目的NAT操作,對TCP來說,NAT部分的數據就是目的端口

static int

tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)

計算IP協議中的校驗和,對於TCP,UDP頭中都有校驗和參數,TCP中的校驗和是必須的,而UDP的校驗和可以不用計算。

該函數用的都是linux內核提供標准的校驗和計算函數

static const char * tcp_state_name(int state)

該函數返回協議狀態名稱字符串

static const char *const tcp_state_name_table[IP_VS_TCP_S_LAST+1] = {

[IP_VS_TCP_S_NONE]                =        "NONE",

[IP_VS_TCP_S_ESTABLISHED]        =        "ESTABLISHED",

[IP_VS_TCP_S_SYN_SENT]                =        "SYN_SENT",

[IP_VS_TCP_S_SYN_RECV]                =        "SYN_RECV",

[IP_VS_TCP_S_FIN_WAIT]                =        "FIN_WAIT",

[IP_VS_TCP_S_TIME_WAIT]                =        "TIME_WAIT",

[IP_VS_TCP_S_CLOSE]                =        "CLOSE",

[IP_VS_TCP_S_CLOSE_WAIT]        =        "CLOSE_WAIT",

[IP_VS_TCP_S_LAST_ACK]                =        "LAST_ACK",

[IP_VS_TCP_S_LISTEN]                =        "LISTEN",

[IP_VS_TCP_S_SYNACK]                =        "SYNACK",

[IP_VS_TCP_S_LAST]                =        "BUG!",

};

TCP協議狀態名稱定義

static void

tcp_state_transition(struct ip_vs_conn *cp, int direction,

     const struct sk_buff *skb,

     struct ip_vs_proto_data *pd)

tcp狀態轉換

static inline void

set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,

      int direction, struct tcphdr *th)

設置tcp連接狀態

static struct tcp_states_t tcp_states []

tcp狀態轉換表

static void tcp_timeout_change(struct ip_vs_proto_data *pd, int flags)

超時變化

static int

tcp_app_conn_bind(struct ip_vs_conn *cp)

本函數實現將多連接應用協議處理模塊和IPVS連接進行綁定

 

未完待續

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM