linux-kernel 3.5.3Tcp系统调用,源码分析4-inet_init

来源:互联网 发布:php开源文档管理 编辑:程序博客网 时间:2024/06/06 00:00

inet_init是ipv4的初始化函数,在系统初始化的时候会调用(在哪里?)

/*

#define __init      __attribute__ ((__section__ (".init.text"))) __cold

简单来说是指示gcc把标记的数据或者函数放到指定sector。
linux中把一些启动及初始化时候用的数据用__init标识,然后在适当的时候把它们释放,回收内存。

*/

static int __init inet_init(void)
{
struct sk_buff *dummy_skb;
struct inet_protosw *q;
struct list_head *r;
int rc = -EINVAL;
BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));
sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);
if (!sysctl_local_reserved_ports)
goto out;

/*

注册tcp协议,包括各种函数

struct proto tcp_prot = {
.name = "TCP",
.owner = THIS_MODULE,
.close = tcp_close,
.connect = tcp_v4_connect,
.disconnect = tcp_disconnect,
.accept = inet_csk_accept,
.ioctl = tcp_ioctl,
.init = tcp_v4_init_sock,
.destroy = tcp_v4_destroy_sock,
.shutdown = tcp_shutdown,
.setsockopt = tcp_setsockopt,
.getsockopt = tcp_getsockopt,
.recvmsg = tcp_recvmsg,
.sendmsg = tcp_sendmsg,
.sendpage = tcp_sendpage,
.backlog_rcv = tcp_v4_do_rcv,
.hash = inet_hash,
.unhash = inet_unhash,
.get_port = inet_csk_get_port,
.enter_memory_pressure= tcp_enter_memory_pressure,
.sockets_allocated= &tcp_sockets_allocated,
.orphan_count = &tcp_orphan_count,
.memory_allocated= &tcp_memory_allocated,
.memory_pressure= &tcp_memory_pressure,
.sysctl_wmem = sysctl_tcp_wmem,
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
.obj_size = sizeof(struct tcp_sock),
.slab_flags = SLAB_DESTROY_BY_RCU,
.twsk_prot = &tcp_timewait_sock_ops,
.rsk_prot = &tcp_request_sock_ops,
.h.hashinfo = &tcp_hashinfo,
.no_autobind = true,
#ifdef CONFIG_COMPAT
.compat_setsockopt= compat_tcp_setsockopt,
.compat_getsockopt= compat_tcp_getsockopt,
#endif
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
.init_cgroup = tcp_init_cgroup,
.destroy_cgroup= tcp_destroy_cgroup,
.proto_cgroup = tcp_proto_cgroup,
#endif
};

*/
rc = proto_register(&tcp_prot, 1);
if (rc)
goto out_free_reserved_ports;

/*

注册udp协议

*/

rc = proto_register(&udp_prot, 1);
if (rc)
goto out_unregister_tcp_proto;
rc = proto_register(&raw_prot, 1);
if (rc)
goto out_unregister_udp_proto;
rc = proto_register(&ping_prot, 1);
if (rc)
goto out_unregister_raw_proto;
/*
* Tell SOCKET that we are alive...
*/
/*

注册协议族操作

*/
(void)sock_register(&inet_family_ops);
#ifdef CONFIG_SYSCTL
ip_static_sysctl_init();
#endif
tcp_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem;
/*
* Add all the base protocols.
*/

/*

看一下tcp_protocol

static const struct net_protocol tcp_protocol = {
.handler = tcp_v4_rcv,
.err_handler =tcp_v4_err,
.gso_send_check = tcp_v4_gso_send_check,
.gso_segment =tcp_tso_segment,
.gro_receive =tcp4_gro_receive,
.gro_complete =tcp4_gro_complete,
.no_policy = 1,
.netns_ok = 1,
};

struct net_protocol {
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
int (*gso_send_check)(struct sk_buff *skb);
struct sk_buff      *(*gso_segment)(struct sk_buff *skb,
      netdev_features_t features);
struct sk_buff     **(*gro_receive)(struct sk_buff **head,
      struct sk_buff *skb);
int (*gro_complete)(struct sk_buff *skb);
unsigned int no_policy:1,
netns_ok:1;
};

inet_add_protocol注册的是协议接受处理的函数

*/
if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)
pr_crit("%s: Cannot add ICMP protocol\n", __func__);
if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)
pr_crit("%s: Cannot add UDP protocol\n", __func__);
if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)
pr_crit("%s: Cannot add TCP protocol\n", __func__);
#ifdef CONFIG_IP_MULTICAST
if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)
pr_crit("%s: Cannot add IGMP protocol\n", __func__);
#endif

/* Register the socket-side information for inet_create. */
for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
INIT_LIST_HEAD(r);
/*

将inetsw_array中的元素按套接字类型注册到inetsw链表数组中, 就是前一篇文章中init_create在初始化sock的时候需要用的的inetsw

*/
for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
inet_register_protosw(q);
/*
* Set the ARP module up

*/

/*

初始化arp模块,包括arp表等

*/
arp_init();
/*
* Set the IP module up
*/
ip_init();
tcp_v4_init();
/* Setup TCP slab cache for open requests. */
tcp_init();
/* Setup UDP memory threshold */
udp_init();
/* Add UDP-Lite (RFC 3828) */
udplite4_register();
ping_init();
/*
* Set the ICMP layer up
*/
if (icmp_init() < 0)
panic("Failed to create the ICMP control socket.\n");
/*
* Initialise the multicast router
*/
#if defined(CONFIG_IP_MROUTE)
if (ip_mr_init())
pr_crit("%s: Cannot init ipv4 mroute\n", __func__);
#endif
/*
* Initialise per-cpu ipv4 mibs
*/
if (init_ipv4_mibs())
pr_crit("%s: Cannot init ipv4 mibs\n", __func__);
ipv4_proc_init();
ipfrag_init();
dev_add_pack(&ip_packet_type);
rc = 0;
out:
return rc;
out_unregister_raw_proto:
proto_unregister(&raw_prot);
out_unregister_udp_proto:
proto_unregister(&udp_prot);
out_unregister_tcp_proto:
proto_unregister(&tcp_prot);
out_free_reserved_ports:
kfree(sysctl_local_reserved_ports);
goto out;
}


小结

inet_init对ipv4相关的协议进行了初始化,包括tcp,udp,icmp等

原创粉丝点击