閱讀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麵向對象高級--抽象類與接口的應用