free BSD协议栈代码

写在开头

最近在学习freeBSD4.4 协议栈的代码,也就是TCP/IP详解中配套使用的协议栈版本,开这篇博客,也是对自己学习过程的一个输出总结。

domaininit初始化

整个tcp/ip协议栈的初始化是在domaininit函数内,每种协议族都已一个domain结构,如unix域协议,tcp/ip协议等。
tcp/ip协议栈的一些信息是在inetdomain结构中声明:

先看下domain结构体:
struct	domain {
	int	dom_family;		/* AF_xxx */ :域类型,一般是AF开头,如AF_INET
	char	*dom_name;//域名称,如 internet
	void	(*dom_init)		/* 域初始化函数 */
		__P((void));
	int	(*dom_externalize)	/* externalize access rights */
		__P((struct mbuf *));
	int	(*dom_dispose)		/* dispose of internalized rights */
		__P((struct mbuf *));
	struct	protosw *dom_protosw, *dom_protoswNPROTOSW;//具体的域协议信息,域协议结构体的结尾
	struct	domain *dom_next;/*用来连接下一个domain结构*/
	int	(*dom_rtattach)		/* initialize routing table */
		__P((void **, int));
	int	dom_rtoffset;		/* an arg to rtattach, in bits */
	int	dom_maxrtkey;		/* for routing layer */
};

domaininit初始化(部分次要代码已略去):

domaininit()
{
	register struct domain *dp;
	register struct protosw *pr;

	ADDDOMAIN(unix);//将unixdomain挂载到domains上
	ADDDOMAIN(route);//将routedomain挂载到domains上
	ADDDOMAIN(inet);//将inetdomain挂载到domains上,也就是tcp/ip协议的domain结构

    /*这里开始调用相应的domain结构中的初始化接口*/
	for (dp = domains; dp; dp = dp->dom_next) {
		if (dp->dom_init)
			(*dp->dom_init)();
		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)/*这里开始调用inetsw中的协议初始化接口*/
			if (pr->pr_init)
				(*pr->pr_init)();
	}
	
    if (max_linkhdr < 16)		/* 链路层首部长度不能小于16 */
        max_linkhdr = 16;
	max_hdr = max_linkhdr + max_protohdr;
	max_datalen = MHLEN - max_hdr;
	timeout(pffasttimo, (void *)0, 1);//启动定时器,调用protosw中的pffasttimo
	timeout(pfslowtimo, (void *)0, 1);//启动定时器,调用protosw中的pr_slowtimo
}
/*ADDDOMAIN这个宏的作用,就是把每个domain挂载到domains指针上,
  利用dom_next将所有domain结构连接起来形成一个链表结构,最后整个domains指向这个链表的第一个成员*/
#define	ADDDOMAIN(x)	{ \
	extern struct domain __CONCAT(x,domain); \
	__CONCAT(x,domain.dom_next) = domains; \
	domains = &__CONCAT(x,domain); \
}

protosw结构定义

每一种协议族都有相应的protosw结构,
struct protosw {
	short	pr_type;		/* socket的类型*/
	struct	domain *pr_domain;	/* domain protocol a member of */
	short	pr_protocol;		/* protocol number */
	short	pr_flags;		/* see below */
/* protocol-protocol hooks */
	void	(*pr_input)();		/* input to protocol (from below) */
	int	(*pr_output)();		/* output to protocol (from above) */
	void	(*pr_ctlinput)();	/* control input (from below) */
	int	(*pr_ctloutput)();	/* control output (from above) */
/* user-protocol hook */
	int	(*pr_usrreq)();		/* user request: see list below */
/* utility hooks */
	void	(*pr_init)();		/* initialization hook */
	void	(*pr_fasttimo)();	/* fast timeout (200ms) */
	void	(*pr_slowtimo)();	/* slow timeout (500ms) */
	void	(*pr_drain)();		/* flush any excess space possible */
	int	(*pr_sysctl)();		/* sysctl for protocol */
};

inetsw --internet的protosw结构

struct protosw inetsw[] = {
{ 0,		&inetdomain,	0,		0,
  0,		ip_output,	0,		0,
  0,
  ip_init,	0,		ip_slowtimo,	ip_drain,	ip_sysctl
},
{ SOCK_DGRAM,	&inetdomain,	IPPROTO_UDP,	PR_ATOMIC|PR_ADDR,
  udp_input,	0,		udp_ctlinput,	ip_ctloutput,
  udp_usrreq,
  udp_init,	0,		0,		0,		udp_sysctl
},
{ SOCK_STREAM,	&inetdomain,	IPPROTO_TCP,	PR_CONNREQUIRED|PR_WANTRCVD,
  tcp_input,	0,		tcp_ctlinput,	tcp_ctloutput,
  tcp_usrreq,
  tcp_init,	tcp_fasttimo,	tcp_slowtimo,	tcp_drain,
},
{ SOCK_RAW,	&inetdomain,	IPPROTO_RAW,	PR_ATOMIC|PR_ADDR,
  rip_input,	rip_output,	0,		rip_ctloutput,
  rip_usrreq,
  0,		0,		0,		0,
},
{ SOCK_RAW,	&inetdomain,	IPPROTO_ICMP,	PR_ATOMIC|PR_ADDR,
  icmp_input,	rip_output,	0,		rip_ctloutput,
  rip_usrreq,
  0,		0,		0,		0,		icmp_sysctl
},
{ SOCK_RAW,	&inetdomain,	IPPROTO_IGMP,	PR_ATOMIC|PR_ADDR,
  igmp_input,	rip_output,	0,		rip_ctloutput,
  rip_usrreq,
  igmp_init,	igmp_fasttimo,	0,		0,
},
#ifdef TPIP
{ SOCK_SEQPACKET,&inetdomain,	IPPROTO_TP,	PR_CONNREQUIRED|PR_WANTRCVD,
  tpip_input,	0,		tpip_ctlinput,	tp_ctloutput,
  tp_usrreq,
  tp_init,	0,		tp_slowtimo,	tp_drain,
},
#endif
/* EON (ISO CLNL over IP) */
#ifdef EON
{ SOCK_RAW,	&inetdomain,	IPPROTO_EON,	0,
  eoninput,	0,		eonctlinput,		0,
  0,
  eonprotoinit,	0,		0,		0,
},
#endif
#ifdef NSIP
{ SOCK_RAW,	&inetdomain,	IPPROTO_IDP,	PR_ATOMIC|PR_ADDR,
  idpip_input,	rip_output,	nsip_ctlinput,	0,
  rip_usrreq,
  0,		0,		0,		0,
},
#endif
	/* raw wildcard */
{ SOCK_RAW,	&inetdomain,	0,		PR_ATOMIC|PR_ADDR,
  rip_input,	rip_output,	0,		rip_ctloutput,
  rip_usrreq,
  rip_init,	0,		0,		0,
},
};

inetsw数组中共定义了10个成员,分别对应每种协议,如TCP,UDP,IP等,在domaininit初始化中,会分别调用每个协议的pr_init接口初始化协议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值