Wednesday, October 28, 2009

Section 25.6.  Protocol Initialization










25.6. Protocol Initialization













The ICMPv4 protocol is initialized with icmp_init in net/ipv4/icmp.c. The ICMP protocol cannot be compiled as a module, so there is no module_init or module_cleanup function. The meaning of the _ _init macro tagging icmp_init can be found in Chapter 7.


Initialization consists of the creation of an array of sockets, one per CPU, which will be used when transmitting ICMP messages generated by the kernel (as opposed to user-generated messages). Those sockets, of type SOCK_RAW and protocol IPPROTO_ICMP, are not to be inserted into the kernel socket's table because they are not supposed to be used as targets for ingress ICMP messages. For this reason, a call to the unhash function takes the sockets out of the hash tables where they have been added by the generic routine sock_create_kern.



void _ _init icmp_init(struct net_proto_family *ops)
{
struct inet_sock *inet;
int i;
for (i = 0; I < NR_CPUS; i++) {
...
err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
&per_cpu(_ _icmp_socket, i));
if (err < 0)
panic("Failed to create the ICMP control socket.\n");
...
inet = inet_sk(per_cpu(_ _icmp_socket, i)->sk);
inet->uc_ttl = -1;
inet->pmtudisc = IP_PMTUDISC_DONT;
per_cpu(_ _icmp_socket, i)->sk->sk_prot->unhash(per_cpu(_ _icmp_socket, i)->sk);
}



uc_ttl, the TTL value to use for IP packets sent to unicast addresses, is initialized to -1 to tell the kernel to use the default unicast TTL (sysctl_ip_default_ttl). The setting of IP_PMTUDISC_DONT disables PMTU discovery on the sockets.


The per-CPU sockets can be accessed with the icmp_socket macro defined in net/ipv4/icmp.c, which transparently selects the right socket based on the local CPU ID.



static DEFINE_PER_CPU(struct socket *, _ _icmp_socket) = NULL;
#define icmp_socket _ _get_cpu_var(_ _icmp_socket)













No comments: