阅读553 返回首页    go 阿里云 go 技术社区[云栖]


网络子系统10_inet模块初始化

//inet模块初始化
//inet功能以模块的形式提供
//1.sock_register(inet_family_ops)向socket注册地址族,保存在net_families数组中,socket通过地址族查找对应的inet_family_ops
//2.struct inet_protosw 由l4使用,表示地址族(协议族)中某一具体协议的操作,保存在inetsw链表数组中,通过协议类型查找对应的协议操作
//3.struct net_protocol 由l3使用,表示l4协议的回调函数,l3通过l3报头中的协议字段,在inet_protos数组中查找对应l4回调函数。
static int __init inet_init(void)
{
	struct sk_buff *dummy_skb;
	struct inet_protosw *q;
	struct list_head *r;
	int rc = -EINVAL;
	//如果inet控制块的大小 > skb提供的控制块的大小
	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
		printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
		goto out;
	}
	//tcp sock SLAB 缓存
	rc = sk_alloc_slab(&tcp_prot, "tcp_sock");
	if (rc) {
		sk_alloc_slab_error(&tcp_prot);
		goto out;
	}
	//udp sock SLAB 缓存
	rc = sk_alloc_slab(&udp_prot, "udp_sock");
	if (rc) {
		sk_alloc_slab_error(&udp_prot);
		goto out_tcp_free_slab;
	}
	//raw sock SLBA缓存
	rc = sk_alloc_slab(&raw_prot, "raw_sock");
	if (rc) {
		sk_alloc_slab_error(&raw_prot);
		goto out_udp_free_slab;
	}

	//向sock注册af_inet服务
  	(void)sock_register(&inet_family_ops);

  	//注册l4协议,l3接收到数据包时,通过协议字段,找到对应的上层协议的回调函数
  	//xxx_protocol用于向下提供服务
	if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)//icmp
		printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n");
	if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)//udp
		printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n");
	if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)//tcp
		printk(KERN_CRIT "inet_init: Cannot add TCP protocol\n");
#ifdef CONFIG_IP_MULTICAST
	if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)//igmp
		printk(KERN_CRIT "inet_init: Cannot add IGMP protocol\n");
#endif

	//初始化inetsw数组,其中每一个元素为一个链表头
	//inetsw用链表的形式组织af_inet地址族中的所有协议
	//inetsw中的每一个链表头,代表一种套接字类型(type)
	//链表中的一个元素,对应一个具体的协议(protocal)
	for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)//SOCK_MAX = 11
		INIT_LIST_HEAD(r);
	//inet默认提供的协议,静态编码在inetsw_array数组中,
	//先通过inet_register_protosw,将其从inetsw_array添加到inetsw中
	//注册af_inet下不同套接字类型,提供的各种协议,用于向上提供服务
	for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
		inet_register_protosw(q);


	//arp子系统初始化
	arp_init();

	//ip子系统初始化
	ip_init();

	//tcp子系统初始化
	tcp_v4_init(&inet_family_ops);
	tcp_init();

	//icmp子系统初始化
	icmp_init(&inet_family_ops);

	//ip多播初始化
#if defined(CONFIG_IP_MROUTE)
	ip_mr_init();
#endif

	//snmp的mibs初始化
	if(init_ipv4_mibs())
		printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;
	
	//ip在proc中的初始化
	ipv4_proc_init();

	//ip分片/合并子系统初始化
	ipfrag_init();

	rc = 0;
out:
	return rc;
out_tcp_free_slab:
	sk_free_slab(&tcp_prot);
out_udp_free_slab:
	sk_free_slab(&udp_prot);
	goto out;
}
//已模块形式提供ip功能
module_init(inet_init);

//注册协议族or地址族 
//inet为af_inet
2.1 int sock_register(struct net_proto_family *ops)
{
	int err;
	//族编号大于最大的族号(32目前)
	if (ops->family >= NPROTO) {
		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
		return -ENOBUFS;
	}
	net_family_write_lock();
	err = -EEXIST;
	//将协议族注册到net_families数组中
	if (net_families[ops->family] == NULL) {
		net_families[ops->family]=ops;
		err = 0;
	}
	net_family_write_unlock();
	printk(KERN_INFO "NET: Registered protocol family %d\n",
	       ops->family);
	return err;
}

2.2 
//linux中,协议族等于地址族
#define PF_UNSPEC	AF_UNSPEC
#define PF_UNIX		AF_UNIX
#define PF_LOCAL	AF_LOCAL
#define PF_INET		AF_INET
#define PF_AX25		AF_AX25
#define PF_IPX		AF_IPX
#define PF_APPLETALK	AF_APPLETALK
#define	PF_NETROM	AF_NETROM
#define PF_BRIDGE	AF_BRIDGE
#define PF_ATMPVC	AF_ATMPVC
#define PF_X25		AF_X25
#define PF_INET6	AF_INET6
#define PF_ROSE		AF_ROSE
#define PF_DECnet	AF_DECnet
#define PF_NETBEUI	AF_NETBEUI
#define PF_SECURITY	AF_SECURITY
#define PF_KEY		AF_KEY
#define PF_NETLINK	AF_NETLINK
#define PF_ROUTE	AF_ROUTE
#define PF_PACKET	AF_PACKET
#define PF_ASH		AF_ASH
#define PF_ECONET	AF_ECONET
#define PF_ATMSVC	AF_ATMSVC
#define PF_SNA		AF_SNA
#define PF_IRDA		AF_IRDA
#define PF_PPPOX	AF_PPPOX
#define PF_WANPIPE	AF_WANPIPE
#define PF_LLC		AF_LLC
#define PF_BLUETOOTH	AF_BLUETOOTH
#define PF_MAX		AF_MAX


//注册inet协议族特定协议的数据处理handler
//在下层接收到数据时,根据协议号,查找指定的处理handler
//protocol可取值为;
enum {
  IPPROTO_IP = 0,		/* Dummy protocol for TCP		*/
  IPPROTO_ICMP = 1,		/* Internet Control Message Protocol	*/
  IPPROTO_IGMP = 2,		/* Internet Group Management Protocol	*/
  IPPROTO_IPIP = 4,		/* IPIP tunnels (older KA9Q tunnels use 94) */
  IPPROTO_TCP = 6,		/* Transmission Control Protocol	*/
  IPPROTO_EGP = 8,		/* Exterior Gateway Protocol		*/
  IPPROTO_PUP = 12,		/* PUP protocol				*/
  IPPROTO_UDP = 17,		/* User Datagram Protocol		*/
  IPPROTO_IDP = 22,		/* XNS IDP protocol			*/
  IPPROTO_RSVP = 46,		/* RSVP protocol			*/
  IPPROTO_GRE = 47,		/* Cisco GRE tunnels (rfc 1701,1702)	*/

  IPPROTO_IPV6	 = 41,		/* IPv6-in-IPv4 tunnelling		*/

  IPPROTO_ESP = 50,            /* Encapsulation Security Payload protocol */
  IPPROTO_AH = 51,             /* Authentication Header protocol       */
  IPPROTO_PIM    = 103,		/* Protocol Independent Multicast	*/

  IPPROTO_COMP   = 108,                /* Compression Header protocol */
  IPPROTO_SCTP   = 132,		/* Stream Control Transport Protocol	*/

  IPPROTO_RAW	 = 255,		/* Raw IP packets			*/
  IPPROTO_MAX
};
3.1 int inet_add_protocol(struct net_protocol *prot, unsigned char protocol)
{
	int hash, ret;

	//哈希协议号
	hash = protocol & (MAX_INET_PROTOS - 1);

	spin_lock_bh(&inet_proto_lock);
	//协议号唯一
	if (inet_protos[hash]) {
		ret = -1;
	} else {
		//将协议处理handler保存到inet_protos数组中
		inet_protos[hash] = prot;
		ret = 0;
	}
	spin_unlock_bh(&inet_proto_lock);

	return ret;
}


//注册特定inet协议与socket interface交互的控制块
4.1 void inet_register_protosw(struct inet_protosw *p)
{
	struct list_head *lh;
	struct inet_protosw *answer;
	int protocol = p->protocol;
	struct list_head *last_perm;

	spin_lock_bh(&inetsw_lock);

	//套接字类型 不应该超过 系统支持的最大类型号(socket type)
	if (p->type >= SOCK_MAX)
		goto out_illegal;
	answer = NULL;
	
	//对应套接字类型在inetsw中的列表头
	last_perm = &inetsw[p->type];
	//遍历该套接字类型的所有协议控制块
	list_for_each(lh, &inetsw[p->type]) {
		answer = list_entry(lh, struct inet_protosw, list);

		//判断协议是否可移动
		if (INET_PROTOSW_PERMANENT & answer->flags) {
			//该类型的套接字下,已存在一个这样协议号的控制块
			if (protocol == answer->protocol)
				break;
			last_perm = lh;
		}

		answer = NULL;
	}
	//存在此套接字类型的协议号
	if (answer)
		goto out_permanent;

	//添加这种类型套接字下的一个特定协议控制块
	list_add_rcu(&p->list, last_perm);
out:
	spin_unlock_bh(&inetsw_lock);
	//同步
	synchronize_net();

	return;

out_permanent:
	printk(KERN_ERR "Attempt to override permanent protocol %d.\n",
	       protocol);
	goto out;

out_illegal:
	printk(KERN_ERR
	       "Ignoring attempt to register invalid socket type %d.\n",
	       p->type);
	goto out;
}

最后更新:2017-04-03 15:21:56

  上一篇:go 如何将报表中的参数传递给VB
  下一篇:go Java面向对象高级--抽象类与接口的应用