Linux TCP/IP protocol stack read notes __linux

Source: Internet
Author: User
Tags htons

The following article assumes that you have knowledge of TCP/IP and have seen TCPv1 or comer Vol1

And then make up some of the socket programs under Linux, OK, Come on

Linux kernel startup I will not say, anyway, my compilation is almost forgotten, there is no
have studied gas.

1 from the INIT/MAIN.C start_kernel function. In this function, call Kernel_thread initiates the init process, which corresponds to the INIT function in the same file, and in the INIT function calls a function in the same file called Do_basic_setup, which calls the net/ Socket.c inside the Sock_init function, this function is the TCP/IP protocol stack, but also include the entry of IPX and so on.

First of all, Sock_init function has a lot of ifdef such things, I think for a normal host, these will not be configured, they include: Slab_skb,config_wan_router,config_firewall,config_ Rtnetlink, Config_netlink_dev but tell the truth in addition to Config_wan_router and Config_firewall can see what the meaning of the other, I am because I have not seen, so I think will not be configured.
With these compilation options removed, this code is left:
for (i = 0; i < Nproto; i++)
Net_families = NULL;
Sk_init ();
Proto_init ();

Where net_families is defined in Include/linux/net.h, is this:
struct net_proto_family
{
int family;
Int (*create) (struct socket *sock, int protocol);
/* These are counters for the number of different methods of
Each We support * *
Short authentication;
Short encryption;
Short encrypt_net;
};
One of the useful is only the first two, the create callback function is each protocol, such as af_inet, such as initialization of the upper layer protocol, such as the TCP/ICMP protocol needs, and later will encounter, here first put the Sk_init function in the net/core/ Sock.c inside, nothing to say.
struct sock *sk_alloc (int family, int priority, int zero_it)
{
struct sock *sk = Kmem_cache_alloc (Sk_cachep, priority);
if (SK) {
if (zero_it)
memset (SK, 0, sizeof (struct sock));
sk->family = family;
}
Return SK;
}

The Proto_init function is inside the same file:
void __init proto_init (void)
{
extern struct Net_proto protocols[];
struct Net_proto *pro;
Pro = Protocols;
while (Pro->name!= NULL)
{
(*pro->init_func) (PRO);
pro++;
}
}

struct Net_proto in include/linux/net.h is like this:
struct Net_proto
{
const char *name; /* Protocol Name * *
void (*init_func) (struct Net_proto *); * Bootstrap * *
};
The protocols array is defined in NET/PROTOCOLS.C and contains a bunch of protocol initialization constructs, of which I only notice two: Af_inet and af_packet their initialization functions are inet_proto_ Init and Packet_proto_init

2 First look at the packet protocol, first we assume that the packet protocol is compiled in the core, rather than a module, so that the Packet_proto_init function in net/packet/af_packet.c

The inside is like this:

void __init packet_proto_init (struct Net_proto *pro)

{
Sock_register (& Packet_family_ops);
Register_netdevice_notifier (& Packet_netdev_notifier);
}



Where the Sock_register function is inside the net/socket.c, it is simply to set the corresponding value in the middle of the net_families array mentioned above:
int Sock_register (struct net_proto_family *ops)
{
if (ops->family >= nproto) {

PRINTK (kern_crit "protocol%d >= Nproto (%d) \ n", ops->family, Nproto);
Return-enobufs;
}

net_families[ops->family]=ops;

return 0;
}



The explanation here is that Packet_netdev_notifier is a struct notifier_block type, the struct is in Include/linux/notifier.h:

struct Notifier_block
{
Int (*notifier_call) (struct Notifier_block *self, unsigned long, void *);

struct Notifier_block *next;
int priority;
};


And the Register_netdevice_notifier function is inside the NET/CORE/DEV.C, and it's like this:
int register_netdevice_notifier (struct notifier_block *nb)
{
Return Notifier_chain_register (&netdev_chain, NB);
}

And the Notifier_chain_register function is inside the include/linux/notifier.h, and it's like this:

extern __inline__ int notifier_chain_register (struct notifier_block **list, struct notifier_block)
{

while (*list)
{
if (N->priority > (*list)->priority)
Break

List= & ((*list)->next);
}

N->next = *list;

*list=n;

return 0;
}

It is obvious that the block is arranged in a block list based on the priority of each block, and we can see that the list is netdev_chain in the Notifier_chain_register function. In fact, the function of this list is to open it in each interface, closing
State changes or external calls to the corresponding IOCTL when the linked list of all the relevant devices, and each protocol calls Register_netdevice_notifier registered a netdev_notifier structure, This allows you to be notified when interface changes (by calling each Notifier_call function).


Here's a look at the Inet_proto_init function, which, in the middle of the net/ipv4/af_inet.c, also has a lot of ifdef compiler options, assuming the following are undefined:

Config_net_ipip,config_net_ipgre,config_ip_firewall,
Config_ip_masquerade,config_ip_mroute

Suppose the following are defined:
Config_inet_rarp,config_proc_fs
Here is the sorted code:

(void) Sock_register (&inet_family_ops);
for (p = inet_protocol_base p!= NULL;) {

struct Inet_protocol *tmp= (struct inet_protocol *) p->next;
Inet_add_protocol (P);

PRINTK ("%s%s", p->name,tmp? ",": "\ n");
p = tmp;
}

Arp_init ();
Ip_init ();
Tcp_v4_init (&inet_family_ops);
Tcp_init ();

Icmp_init (&inet_family_ops);
Rarp_ioctl_hook = Rarp_ioctl;

Proc_net_register (&AMP;PROC_NET_RARP);
Proc_net_register (&proc_net_raw);
Proc_net_register (&AMP;PROC_NET_SNMP);

Proc_net_register (&proc_net_netstat);
Proc_net_register (&proc_net_sockstat);
Proc_net_register (&AMP;PROC_NET_TCP);
Proc_net_register (&AMP;PROC_NET_UDP);

The role of the Sock_register function has already been mentioned, and now look at the struct inet_protocol and Inet_add_protocol functions. The front structure is inside the include/net/protocol.h:
struct INET_PROTOCOL
{
Int (*handler) (struct Sk_buff *skb, unsigned short len);
void (*err_handler) (struct Sk_buff *skb, unsigned char *dp, int len);
struct Inet_protocol *next;
unsigned char protocol;
unsigned char copy:1;
void *data;
const char *name;
};
The first function is the callback function to receive the data, and the second is the error-handling function,
Other copy is used for protocol sharing, and later on, data is, of course, the private data for this structure.

The Inet_add_protocol function is inside the NET/IPV4/PROTOCOL.C:
void Inet_add_protocol (struct inet_protocol *prot)
{
unsigned char hash;
struct Inet_protocol *p2;

hash = Prot->protocol & (max_inet_protos-1);
Prot->next = Inet_protos[hash];
Inet_protos[hash] = prot;
prot->copy = 0;

P2 = (struct Inet_protocol *) prot->next;
while (P2!= NULL)
{
if (P2->protocol = = Prot->protocol)
{
Prot->copy = 1;
Break
}
P2 = (struct Inet_protocol *) p2->next;
}
}
Obviously this function is a hash table, and then each hash table item is a linked header, and then through the hash table plus linked list to access each protocol structure. You have also seen the use of copy members here.

The Arp_init function is inside the NET/IPV4/ARP.C (assuming no config_sysctl is defined):

Neigh_table_init (&AMP;ARP_TBL);
Dev_add_pack (&arp_packet_type);
Proc_net_register (&AMP;PROC_NET_ARP);

Do not know if someone's eyes a bright Ah, oh, see the Dev_add_pack function.
or step by step.
Neigh_table_init function in the middle of net/core/neighbour.c:
void Neigh_table_init (struct neigh_table *tbl)
{
unsigned long now = jiffies;

Tbl->parms.reachable_time = Neigh_rand_reach_time (tbl->parms.base_reachable_time);
Init_timer (&tbl->gc_timer);
Tbl->gc_timer.data = (unsigned long) tbl;
Tbl->gc_timer.function = Neigh_periodic_timer;
Tbl->gc_timer.expires = now + Tbl->gc_interval + tbl->parms.reachable_time;
Add_timer (&tbl->gc_timer);
Init_timer (&tbl->proxy_timer);
Tbl->proxy_timer.data = (unsigned long) tbl;
Tbl->proxy_timer.function = neigh_proxy_process;
Skb_queue_head_init (&tbl->proxy_queue);
Tbl->last_flush = Now;
Tbl->last_rand = Now + tbl->parms.reachable_time*20;
Tbl->next = Neigh_tables;
Neigh_tables = TBL;
}
Jiffies is the current system time, on the i386 system like a jiffies on behalf of 50ms, obviously this function is to generate two timer put one in the system timerlist. That gc_timer mean garbage collect timer because every once in a while ARP
The cache should be updated, so have a expires time, this period of time will be updated after the ARP address, the Proxy_timer has not seen what is, but I assume that my machine does not use proxy also do not make proxy, so the proxy is not related to the tube: P that timer's function is obviously the clock-expiration callback function, and data is the private one to use for this callback function.

Here is the Dev_add_pack function, which is inside the NET/CORE/DEV.C:
void Dev_add_pack (struct packet_type *pt)
{
int hash;
#ifdef Config_net_fastroute
/* Hack to detect packet socket * * *
if (pt->data) {
netdev_fastroute_obstacles++;
Dev_clear_fastroute (Pt->dev);
}
#endif
if (Pt->type==htons (Eth_p_all))
{
netdev_nit++;
pt->next=ptype_all;
ptype_all=pt;
}
Else
{
Hash=ntohs (Pt->type) &15;
Pt->next = Ptype_base[hash];
Ptype_base[hash] = pt;
}
}
Obviously the system retains two tables, one is Ptype_all, which receives the list of all types of packages, one is a hash array + linked list structure, used to receive a specific type of package. The fastroute didn't know what it was.

The definition of struct packet_type in include/linux/netdevice.h, I keep the original annotation so that I don't have to say more:
{
unsigned short type;
/* This is really htons (Ether_type). */
struct device *dev;
/* NULL is wildcarded here/*
Int (*func) (struct Sk_buff *,
struct device *, struct packet_type *);
void *data;
/* Private to the packet type * *
struct Packet_type *next;
};
The Func of course is the callback function, for example, Arp_packet_type is like this:
static struct Packet_type Arp_packet_type =
{
__constant_htons (Eth_p_arp),
NULL,/* All devices * *
ARP_RCV,
Null
Null

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.