網絡子係統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