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