This paper analyzes Linux Kernel 1.2.13 based on
Original works, reproduced please mark http://blog.csdn.net/yming0221/article/details/7549340
See column, Address http://blog.csdn.net/column/details/linux-kernel-net.html
Shuming
Note: In the title, "(UP)", "(bottom)" means that the analysis process is based on the delivery direction of the packet: "(top)" means that the analysis is parsed from the bottom up, and "(bottom)" indicates that the analysis is parsed from the top down.
In this paper, the application layer through the BSD socket layer to the INET socket layer function call relationship and data processing flow, the inet layer will invoke the specific transport layer protocol, or the UDP protocol as an example
Udp_write () function
[CPP]View Plaincopy
- static int udp_write (struct sock *sk, unsigned char *buff, int len, int noblock,
- Unsigned flags)
- {
- Return (Udp_sendto (SK, Buff, Len, Noblock, Flags, NULL, 0));
- }
Before analyzing the Udp_sendto () function, let's look at the sockaddr_in structure, which is the definition of the standard network interface address structure.
[CPP]View Plaincopy
- struct SOCKADDR_IN {
- short int sin_family; /* Address Family family */
- unsigned short int sin_port; /* Port number Port numbers */
- struct IN_ADDR sin_addr; /* Internet Address network addresses */
- /* Pad to size of ' struct sockaddr '. */
- unsigned char __pad[__sock_size__-sizeof (short int)-
- sizeof (unsigned short int)-sizeof (struct in_addr)];
- };
- #define Sin_zero __pad/* for BSD UNIX comp.-FVK */
Udp_sentdto () function
[CPP]View Plaincopy
- static int udp_sendto (struct sock *sk, unsigned char *from, int len, int noblock,
- Unsigned flags, struct sockaddr_in *usin, int addr_len)
- {
- struct sockaddr_in sin;
- int tmp;
- /*
- * Check the flags. WE Support No flags for UDP sending
- */
- if (Flags&~msg_dontroute)
- return (-einval);
- /*
- * Get and verify the address.
- */
- if (usin)//If usin is not empty
- {
- if (Addr_len < sizeof (sin))
- return (-einval);
- memcpy (&sin,usin,sizeof (sin));
- if (sin.sin_family && sin.sin_family! = af_inet)
- return (-einval);
- if (Sin.sin_port = = 0)
- return (-einval);
- }
- else//usin is empty
- {
- if (sk->state! = tcp_established)
- return (-einval);
- sin.sin_family = af_inet;//protocol Family
- Sin.sin_port = sk->dummy_th.dest;//Destination port
- SIN.SIN_ADDR.S_ADDR = sk->daddr;//Destination Address
- }
- /*
- * BSD socket semantics. You must set So_broadcast to permit
- * Broadcasting of data.
- */
- if (sin.sin_addr.s_addr==inaddr_any)//Destination address is a full 0 address, corresponding to the current host
- SIN.SIN_ADDR.S_ADDR=IP_MY_ADDR ();//Set the destination to the network address of the current host
- if (!sk->broadcast && ip_chk_addr (sin.sin_addr.s_addr) ==is_broadcast)
- Return-eacces; /* must turn broadcast on first */
- Sk->inuse = 1;
- /* Send the packet. */
- TMP = Udp_send (SK, &sin, from, Len, flags);//Call Udp_send () to actually send the data
- /* The datagram has been sent off. Release the socket. */
- Release_sock (SK);
- return (TMP);
- }
Udp_send () function
[CPP]View Plaincopy
- static int udp_send (struct sock *sk,//sock structure used for packets to be sent using the protocol pair
- The standard network interface address of the struct sockaddr_in *sin,//destination
- unsigned char *from,//the address of the data to be sent
- int len,//The length of the sent data
- int RT)
- {
- struct Sk_buff *skb;
- struct device *dev;
- struct UDPHDR *uh;
- unsigned char *buff;
- unsigned long saddr;
- int size, TMP;
- int ttl;
- /*
- * Allocate an sk_buff copy of the packet.
- */
- Size = Sk->prot->max_header + len;//Compute the longest header + data length for UDP
- SKB = SOCK_ALLOC_SEND_SKB (sk, size, 0, &tmp);//Allocate sk_buff structure space based on data to be sent and check for current socket status
- if (SKB = = NULL)
- return TMP;
- Skb->sk = NULL; /* To avoid changing sk->saddr */
- Skb->free = 1;
- Skb->localroute = sk->localroute| (Rt&msg_dontroute);
- /*
- * Now build the IP and MAC header.
- */
- Buff = skb->data;//Assigns a data pointer in SKB to the buff pointer
- SADDR = sk->saddr;//Local Address
- dev = NULL;
- TTL = sk->ip_ttl;//time to Live
- #ifdef Config_ip_multicast
- if (multicast (SIN->SIN_ADDR.S_ADDR))
- TTL = sk->ip_mc_ttl;
- #endif
- TMP = Sk->prot->build_header (SKB, saddr, SIN->SIN_ADDR.S_ADDR,
- &dev, IPPROTO_UDP, sk->opt, Skb->mem_len,sk->ip_tos,ttl);//Call Ip_build_header () to create an IP header and invoke Ip_send () Create a Mac Header
- skb->sk=sk; /* So memory is freed correctly */
- /*
- * Unable to put a header on the packet.
- */
- if (TMP < 0)
- {
- Sk->prot->wfree (SK, SKB->MEM_ADDR, Skb->mem_len);
- return (TMP);
- }
- Buff + = tmp;
- SADDR = skb->saddr; /*dev->pa_addr;*/
- Skb->len = tmp + sizeof (struct UDPHDR) + len; /* len + UDP + IP + MAC */
- Skb->dev = Dev;
- /*
- * Fill in the UDP header. Fill in the header of the UDP
- */
- Uh = (struct UDPHDR *) buff;
- Uh->len = htons (len + sizeof (struct UDPHDR));//Packet length
- Uh->source = sk->dummy_th.source;//Local Port
- Uh->dest = sin->sin_port;//Remote port
- Buff = (unsigned char *) (uh + 1);
- /*
- * Copy the user data.
- */
- Memcpy_fromfs (Buff, from, Len);//Copy User data
- /*
- * Set up the UDP checksum.
- */
- Udp_send_check (uh, saddr, SIN->SIN_ADDR.S_ADDR, Skb->len-tmp, SK);//Calculate the checksum of the UDP header
- /*
- * Send the datagram to the interface.
- */
- Udp_statistics. udpoutdatagrams++;
- Sk->prot->queue_xmit (SK, Dev, SKB, 1);//Call the IP layer function to send the data
- return (LEN);
- }
This sends the data to the Sk_buff structure that is populated after the IP data header and the Mac frame header are added to the UDP packet. Finally, the Send function of the IP layer is called to send the packet.
Linux kernel--Network stack Implementation Analysis (ix)--UDP protocol for Transport layer (bottom)