Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103655351
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: LINUX

2008-04-28 22:37:52

 
文章来源ChinaITLab收集整理

 

 


7.1 设计思想

ip端口转发模块的主要工作:

1. 接受外部网的连接请求。

2. 对外只呈现平衡器,使所有请求看起来都是由平衡器处理的。

3. 建立一个端口转发链表。

4. 接收外部网发向内部网的请求。根据连接请求的源地址、源端口、目标地址和目标端口的信息察看链表中是否有对应表项,如果有,则调用ip伪装模块将请求转发到实际服务器上;如果没有对应表项,则创建一个新的端口转发表项,并且在ip伪装HASH表中增加相应的表项。将实际服务器的处理结果回传给平衡器,再由平衡器发给外部网中的客户。

5. 在ip端口转发模块中通过系统调用的实现函数对用户的系统调用进行处理,首先清空ip端口转发链表,然后建立对应于最轻负载机器ip地址的ip端口转发表项。

7.2 模块流程


7.3 结构设计

程序名 标识符 功能 源程序
删除表项 ip_portfw_del 在双向链表中删除一个ip_portfw结构的表项 ip_masq_portfw.c
清空双向链表 ip_portfw_flush 清空双向链表,释放空间 ip_masq_portfw.c
寻找匹配表项 ip_portfw_lookup 寻找符合要求的表项 ip_masq_portfw.c
设置权重 ip_portfw_edit 为匹配的表项设置权重 ip_masq_portfw.c
添加表项 ip_portfw_add 添加一个表项 ip_masq_portfw.c
控制双向链表 ip_portfw_ctl 对双向链表进行控制,进行添加、删除和清空操作 ip_masq_portfw.c
匹配表项 portfw_in_rule 判断是否存在匹配表项 ip_masq_portfw.c
创建新入口 portfw_in_creat 如果没有匹配表项,则创建一个新的ip_masq结构的表项。 ip_masq_portfw.c
系统调用处理函数 getip 接受来自用户层的系统调用,根据负载最轻的机器的IP值建立新的端口转发链表 ip_masq_portfw.c

7.4 主要数据结构


struct  ip_portfw{
    struct  list_head  list;
    __u32  laddr,  raddr;
    __u16  lport,  rport;
    atomic_t  pref_cnt;
    int  pref;
    }
struct  list_head{
struct  list_head  *next, *prev;
  }
 

7.5 算法及流程

(1) ip_portfw_del

格式: static __inline __ int ip_portfw_del(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr)

返回值:如果模块的访问计数〉0,则返回一个大于0的值,否则返回0;

处理流程:

1. 在双向链表中找到这样的ip_portfw *n 结构,满足:

(n->lport == lport && (!laddr || n->laddr == laddr) && (!raddr || n->raddr == raddr) && (!rport || n->rport == rport )),从链表中删除此入口,释放n结构。

1. 若(&mmod_self -> mmod_nent)为真,则返回ESRCH,否则返回0。

(2) ip_portfw_flush

格式: static __inline__ void ip_portfw_flush(void)

返回值:无。

处理流程:

1. 对于TCP 和UDP链,循环做2. 3步

2. 从链表上删除一个入口,释放结构n。

3. 取下一入口。

(3) ip_portfw_lookup

格式: static __inline__ struct ip_portfw *ip_portfw_lookup(__u16 protocol, __u16 lport, __u32 laddr, __u32 *daddr_p, __u16 *dport_p)

返回值:返回一个ip_portfw结构的变量n。

处理流程:

1.在双向链表中找到这样的ip_portfw *n 结构,满足:

(lport == n->lport && laddr == n->laddr) ,若没有找到,则n = NULL。

2.赋值:*daddr_p = n->raddr;*dport_p = n->rport。

3.返回n。

(4) ip_portfw_edit

格式: static __inline__ int ip_portfw_edit(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr, int pref)

返回值:返回满足匹配条件的表项的数目。

处理流程:

1. 设count为0。

2. 在双向链表中找这样的n,满足:( lport == n->lport && (!laddr || laddr == n->laddr) && (!raddr || raddr == n->raddr) && (!rport || rport == n->rport )) 。

3. 为n设置权重。

4. 设n->pref_cnt = pref。

5. 每找到一个匹配项, count都加1。

6. 解读锁portfw_lock。

7. 返回count。

(5) ip_portfw_add

格式: static __inline__ int ip_portfw_add(__u16 protocol, __u16 lport,__u32 laddr, __u16 rport,__u32 raddr, int pref)

返回值:成功:返回0;失败:返回EINVAL。

处理流程:

1. 调用ip_portfw_edit, 若有匹配项,则返回0。

2. 为npf分配一个 struct ip_portfw的空间,若分配失败,则返回"无可用空间" 。

3. MOD_INC_USE_COUNT。

4. npf清0。

5. npf->laddr = laddr;

npf->lport = lport;

npf->rport = rport;

npf->raddr = raddr;

npf->pref = pref;

设npf的访问计数为npf的权重;

6. 调用INIT_LIST_HEAD初始化npf->list。

7. 加写锁&portfw_lock。

8. 调用list_add增加一项到链头。

9. 解写锁。

10. 增加mmod_self计数。

11. 返回0。

(6) portfw_ctl

格式: static __inline__ int portfw_ctl(int optname,struct ip_masq_ctl *mctl, int optlen) 返回值:成功:返回0;失败:返回EINVAL。

处理流程:

1. 如果cmd为IP_MASQ_CMD_NONE,返回0。

2. 如果cmd为IP_MASQ_CMD_ADD,调用 ip_portfw_add。

3. 如果cmd为IP_MASQ_CMD_DEL,调用 ip_portfw_del。

4. 如果cmd为IP_MASQ_CMD_FLUSH,调用ip_portfw_flush。

5. 返回EINVAL。

(7)portfw_in_creat

格式: static struct ip_masq *portfw_in_creat(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)

返回值: 成功:返回ms。

处理流程:

1. 加写锁&portfw_lock。

2. 调用ip_portfw_lookup,若找到匹配项,则调ip_masq_new创建一个新入口表项ms。

阅读(251) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~