Linux集群系统的实现(下)
本篇是《基于linux的集群系统》实现篇的下部分。将向我们讲述各个模块的具体设计和实现。
6 ip伪装模块的分析
6.1 设计思想
ip伪装模块的主要工作是:
1.接收内部网发向外部网的所有请求。
2.内部网中的连接请求通过平衡器转发到外部网。
3.将内部网发向外部网中的所有请求的源地址隐藏,使所有请求看上去都是由平衡器发送的。
4. 建立HASH表来记录已经建立的所有连接。
5. 接收外部网对请求的回应并将其转发到内部网中的发出请求的机器上。
6.2 模块流程
(1) 内部网中的机器向外部网中的机器发送连接请求的流程。
外部网中的机器向内部网中的机器发送连接请求的流程。
6.3 结构设计
程序名 标识符 功能 源程序
建立HASH队列 ip_masq_hash 根据m{addr, port}和s{addr, port}建立两个HASH队列 ip_masq.c
从HASH队列删除表项 ip_masq_unhash 将ip_masq表项从HASH队列中删除 ip_masq.c
处理从外到内的请求 __ip_masq_in_get 处理从外到内的请求,查询HASH表,找到内部机器的ip地址及端口 ip_masq.c
处理从内到外的请求 __ip_masq_out_get 处理从内到外的请求,查询HASH表,找出源地址、端口及目标地址、端口都匹配的表项。 ip_masq.c
减少某个连接的访问计数 __ip_masq_put 将ip_masq表项的访问计数减一。 ip_masq.c
取下一伪装端口 get_next_mport 取得下一个mport。 ip_masq.c
创建新的ip_masq结构 ip_masq_new 创建一个新ip_masq结构,并分配一个新的mport ip_masq.c
从内到外请求处理的最上层函数 ip_fw_masquerade 负责从内向外请求的处理全过程。 ip_masq.c
从外到内请求处理的最上层函数 ip_fw_demasquerade 负责从外向内请求的处理全过程。 ip_masq.c
6.4 主要数据结构
struct
ip_masq{
struct
ip_masq
*m_link,
*s_link;
atomic_t
refcnt;
struct
timer_list
timer;
__u16
protocol;
__u16
sport,
dport,
mport;
__u32
saddr,
daddr,
maddr;
struct
ip_masq_seq
out_seq, in_seq;
void
*app_data;
struct
ip_masq
*control;
atomic_t
n_control;
unsigned
flags;
unsigned
timeout;
unsigned
state;
struct
ip_masq_timeout_table
*timeout_table;
}
6.5 算法及流程
(1) ip_masq_hash
格式:static ip_masq_hash(struct ip_masq *ms)
返回值:1:成功;0:失败。
处理流程:
1. 如果ms-flags 已设IP_MASQ_F_HASHED标志位,则返回0。
2.根据ms-protocol、 ms-maddr和 ms-mport产生hash-key。
3.将ms链接到hash[hash_key] 链的头位置。
4.增加ms的访问计数。
5.根据ms-protocol 、ms-sadd和ms-sport产生hash_key。
6.将ms链接到hash[hash_key] 链的头位置。
7.增加ms的访问计数。
8.ms-flags 设IP_MASQ_F_HASHED位。
9. 返回1。
(2)ip_masq_unhash
格式:static int ip_masq_unhash(struct ip_masq *ms)
返回值: 1:成功;0:失败。
处理流程:
1. 如果ms-flags未设IP_MASQ_F_HASHED位,则返回0。
2. 不然,做以下几步。
3. 根据ms-protocol、 ms-maddr和 ms-mport产生hash-key。
4.在hash[hash_key]链中找匹配的表项,将匹配项的访问计数减一,并从链表中删除此项。
5. 根据ms-protocol 、ms-sadd和 ms-sport产生hash_key。
6.在hash[hash_key]链中找匹配的表项,将匹配项的访问计数减一,并从链表中删除此项。
7. ms-flags设位~IP_MASQ_F_HASHED。
8. 返回1。
(3)__ip_masq_in_get
格式:static struct ip_masq *__ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
返回值:返回一个ip_masq结构ms。
处理流程:
1. 根据 protocol 、 d_addr、 d_port产生hash_key。
2. 在hash[hash_key]链中找匹配的表项,满足: (protocol == ms-protocol && d_addr == ms-maddr && dport == ms-mport && (s_addr == ms-daddr || ms-flags & MASQ_DADDR_PASS) && (s_port == ms-dport || ms_flags & MASQ_DPORT_PASS))。
3. ms的访问计数增1。
4. 返回ms。
(4)__ip_masq_out_get
格式:static struct ip_masq *__ip_masq_out_get(int protocol , __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
返回值:返回一个ms。
处理流程:
1. 如果s_port不为0,做以下几步;不然,跳至第5步。
2. 根据 protocol 、 s_addr和s_port产生hash_key。
3. 在hash[hash_key]链中找匹配的表项,满足:(protocol == ms-protocol && s_addr == ms-saddr && sport == ms-sport && (d_addr == ms-daddr || ms-flags & MASQ_DADDR_PASS) && (d_port == ms-dport || ms_flags & MASQ_DPORT_PASS))。
4. ms的访问计数增1。
5. 返回ms。
6. 根据 protocol 、 s_add、 0产生hash_key。
7. 在hash[hash_key]链中找匹配的表项,满足:(protocol == ms-protocol && s_addr == ms-saddr && sport == ms-sport && (d_addr == ms-daddr || ms-flags & MASQ_DADDR_PASS) && (d_port == ms-dport || ms_flags & MASQ_DPORT_PASS))。
8. ms的访问计数增1。
9. 返回ms。
(5)__ip_masq_getbym
格式:static struct ip_masq *__ip_masq_getbym(int protocol, __u32 m_addr, __u16 m_port)
返回值:返回一个ms。
处理流程:
1. 根据 protocol 、m_add和 m_port产生hash_key。
2. 在hash[hash_key]链中找匹配的表项,满足:(protocol == ms-protocol && m_addr == ms-maddr && mport == ms-mport )。
3. ms的访问计数加1。
4. 返回ms。
(6)ip_masq_out_get
格式:struct ip_masq *ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
返回值:返回ms。
处理流程:
1. 为__ip_masq_lock加读锁。
2. 调__ip_masq_out_get(protocol, s_addr, s_port, d_addr, d_port)返回ms。
3. 解读锁__ip_masq_lock。
4. 为ms设置超时。
5. 返回ms。
(7)ip_masq_in_get
格式:struct ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
返回值:返回ms。
处理流程:
1.为__ip_masq_lock加读锁。
2.调__ip_masq_in_get(protocol, s_addr, s_port, d_addr, d_port)返回ms。
3. 解读锁__ip_masq_lock。
4. 为ms设置超时。
6. 返回ms。
(8)__ip_masq_put
格式:static __inline __void __ip_masq_put(struct ip_masq *ms)
返回值:无
处理流程:
1. 将ms的访问计数减一。
(9)get_next_mport
格式:static __u16 get_next_mport(void)
返回值:返回一个16位的端口号。
处理流程:
1. 为masq_mport_lock加旋转锁。
2. Mport = htons(masq_port ++)。
3. 如果masq_port是最后一个锁,则masq_port = 开始锁。
4. 解旋转锁masq_port_lock。
5. 返回mport。
(10)ip_masq_new
格式:struct ip_masq *ip_masq_new(int proto, __u32 maddr, __u16 mport, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned mflags)
返回值:成功:返回ms;失败:返回null。
处理流程:
1. 如果没有可用端口,返回NULL。
2. 若mflags 设IP_MASQ_F_USER位,则 prio = GFP_KERNEL;不然, prio=GFP_ATOMIC。
3. 为ms分配空间,若失败,返回NULL。
4. MOD_INC_USE_CONUNT。
5. 清空ms。
6. 初始化ms-timer。
7. ms-timer.data = (unsigned long)ms;
ms-tim