Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 13

11.

Introduction to Linux
·
Linux is developed world wide. It is an open development project, meaning everyone
who wants to can become involved. Because it is worldwide, a fast and easy form of
communication is needed so different people and groups can keep updated with what is
going on with Linux.

Kernel Network Interface

For a normal network programmer, the front end to the networking services of the Linux
kernel are available through the following C library routines :

socket()
bind()
listen()
connect()
accept()
sendto()
recvfrom()
send()
recv()

The socket() function is used to create a new socket. All the operations with the
various different protocols occur with a socket. As the routine socket() returns a file
descriptor, the usual file operations can apply to it, i.e. read(), write(), etc.

The bind() function is used to tie a newly created socket to a port. The port along
with the IP address of the network interface is used to uniquely identify a socket. When
a socket is bound to a port, any packet that arrives with the port in its destination field is
passed on to that socket controller.

The listen() function is used for server side programming. After a socket is created
and bound to a port, calling the listen() function sets the socket to the listen state. This
means that the socket is willing to accept connections from foreign hosts.

When the server side calls the accept() function, the program blocks and continually
polls the socket until it receives a connection request from another host. Only when the
connection is established is the server program woken up and allowed to process a request
from the foreign host.

From the client end, the connect() function is used to indicate to a


server that the client wishes to open a connection to a socket and send a request.
This request is read into a string using the recv() function. The server can then use
send() to send the reply to the host that requested the data.

Important Structures in the Linux Kernel

socket: This structure is the basis for the implementation of the BSD socket interface.
The system call socket() sets up and initialises the structure.

sk_buff: This structure manages the individual communications packets arriving and be
ing sent from the host. It buffers the input and output. The structure holds the
packets before either sending them onto the network interface for transmission, or
sending them onto the higher layers for processing and eventually arriving at the
application layer.

INET: This structure administers the networkspecific parts of the sockets. It is required
for TCP, UDP and RAW sockets.
proto: This structure contains a number of operations that are the same for all protocols.
It means that the actions only need to be programmed once and avoids implemen
tation errors.

sockaddr(sockaddr_in): These are necessary to support the different address formats for
different address families.

Linux Protocol Stack


An executing program that needs to use a protocol within the Linux kernel goes through
a number of different layers before reaching its final processing stage. The following
description applies to the TCP/IP stack.

tcp_connect()
inet_connect()
sys_connect()
sys_socketcall()
connect()
User Space
Kernel Space

Flow of Control from User Space to Kernel Space

On the user side, a program executes a system socket command, such as socket(),
bind() or connect(). This is passed into the kernel side through the sys_socketcall() func
tion located in the /usr/src/linux/net/socket.c file.
Design and Implementation

Design Approach

We started of to create simple Server/Client which would support simple User level functionality
of converting characters from lower case to upper case. We wanted to keep it very simple and
make it usable for other user level services too. So we decided to implement it in form of API like
functions.

Major part of designing task was to implement most reliable TCP state machine.
TCP Header
Below is the standard TCP header we are using for our client/server
struct {
unsigned short srcPort;
unsigned short dstPort;
unsigned int seqNo;
unsigned int ackNo;
unsigned short dataOffset;
unsigned short reserved;
char URG;
char ACK;
char PSH;
char RST;
char SYN;
char FIN;
unsigned short windows;
unsigned short chkSum;
unsigned short urgPtr;
unsigned char option[40];
}ztcp;

struct {
char data [SIZE];
}zdata;

struct {
ztcp header;
zdata data;
}zpacket;

TCP Control Block


struct TCB
{
unsigned short ipaddr;
unsigned short portno;
int state;
int not_used;
//unsigned char sequenceno;
//unsigned char ackno;
long SND_UNA; //send unacknowledged
long SND_NXT; //send next
long SND_WND; //send window
long SND_UP ; //send urgent pointer
long SND_WL1; //segment sequence number used for last window update
long SND_WL2; //segment acknowledgment number used for last window
update
//ISS - initial send sequence number

long RCV_NXT; //- receive next


long RCV_WND; //- receive window
long RCV_UP; //- receive urgent pointer
long IRS; //- initial receive sequence number

long SEG_SEQ;
long SEG_ACK;
long SEG_LEN;
long SEG_WND;
FILE *file;
}

TCP State machine


LISTEN - represents waiting for a connection request from any remote
TCP and port.

SYN-SENT - represents waiting for a matching connection request


after having sent a connection request.

SYN-RECEIVED - represents waiting for a confirming connection


request acknowledgment after having both received and sent a
connection request.

ESTABLISHED - represents an open connection, data received can be


delivered to the user. The normal state for the data transfer phase
of the connection.

FIN-WAIT-1 - represents waiting for a connection termination request


from the remote TCP, or an acknowledgment of the connection
termination request previously sent.

FIN-WAIT-2 - represents waiting for a connection termination request


from the remote TCP.

CLOSE-WAIT - represents waiting for a connection termination request


from the local user.

CLOSING - represents waiting for a connection termination request


acknowledgment from the remote TCP.

LAST-ACK - represents waiting for an acknowledgment of the


connection termination request previously sent to the remote TCP
(which includes an acknowledgment of its connection termination
request).

Connection Eshtablishment

Client/Server needs to go through process of connection establishment to start data transfer.


Basic need of connection establishment is to synchronize client/server with sequence number for
data octets. In case of our client/server our client sends out SYN packet to server with its
sequence number which is called active open. Server Send SYN ACK to client to client with
sequence number of its own. And in the end Client send ACK for the last packet sent by Server.
Server Side Connection Establishment
During Connection establishment server is setup. If performs passive open and binds itself to a
localport. After binding itself to the port it goes into listen state where it waits for any incoming
connection. Whenever a new connection request comes in form of SYN packet it creates new
TCB in TCB buffer. It replies back to the client with a SYN/ACK packet. It also changes the
current state of server connection from Listen to SYN_RECV state. After getting ACK from client
it changes its state from SYN_RECV to ESTABLISHED. This is normal scenario of connection
establishement. All this time we also check for any invalid packet If any invalid packet comes in
during this server send RST and goes back to Listen state.

Fig. Connection Establishment Server Side

Fig. Client Side Connection Establishment

Data Transfer

Conceptually, each byte sent is assigned a sequence number and the receiver then sends an
acknowledgement back to the sender that effectively states that they received it. What is done in
practice is only the first data byte is assigned a sequence number which is inserted in the
sequence number field and the receiver sends an acknowledgement value of the next byte they
expect to receive. Data is sent along with each octet and server converts them into upper case
send them back to requesting client.

Sequence numbers and acknowledgments cover discarding duplicate packets, retransmission of


lost packets, and ordered-data transfer. Every incoming packet is checked against fields of TCB
to determine its validity.
Server Data Transfer

·
Fig. Data Transfer Client Side
Connection termination
The connection termination phase uses, at most, a four-way handshake, with each side of the
connection terminating independently. When an endpoint wishes to stop its half of the
connection, it transmits a FIN packet, which the other end acknowledges with an ACK. Therefore,
a typical teardown requires a pair of FIN and ACK segments from each TCP endpoint.
A connection can be "half-open", in which case one side has terminated its end, but the other has
not. The side that has terminated can no longer send any data into the connection, but the other
side can.
It is also possible to terminate the connection by a 3-way handshake, when host A sends a FIN
and host B replies with a FIN & ACK (merely combines 2 steps into one) and host A replies with
an ACK. This is perhaps the most common method.
Finally, it is possible for both hosts to send FINs simultaneously then both just have to ACK. This
could possibly be considered a 2-way handshake since the FIN/ACK sequence is done in parallel
for both direction

Fig. Connection Termination


·Multiclient Scenario

Ours is a Iterative server which creates arrays of TCBs. We have limited our array to 10 at
present. After Connection establishment whenever a packet comes in it checks for its source ip
address and port number and checks TCB array for any present connection with that node. If it
finds that packet is coming from some new node then it create new entry in TCB array structure
and initiates state machine.

When Server is initiated it binds to socket and goes into to Listen State. When connection is
already present for incoming packet the state processing machine handles processing for the
current state as well as decides the next state for the connection,

Fig. Multiclient Scenario

Suppose TCB array is full and there is no place for new connection then server would send RST
to the requesting client.

Architecture
Figure Architecture

Server main: int main (int argc, char *argv[])


Description:
-壱This is the main server function that processes the client packets in a loop.
-弐First it creates a server socket using the zserverSocket() call.
-参Then call zbind() to bind the socket with the INADDR_ANY and specified port number in the
program arguments.
-四Start a loop where it listens for the packets and processes them.
-伍In the loop, call zlisten() to verify if there is any client packet on the socket.
-六If there is any packet, call the zProcessPacket() function to process the packets.
-七If there is no packet for duration of 1 second, its time to do the retransmission processing.
-八Call the zRetransmit() to do the retransmission processing.
-九Go back to the loop to listen for any client packet.

int zlisten (int sockfd, int backlog)


Description:
-壱This function uses select() call to wait for any packet on the UDP socket that is kept in the
structure ‘zionSocket’ identified by ‘sockfd’.
-弐The select() call waits for any packet on the socket for 1 second.

Return:
-壱If the packet is available, it returns ‘0’
-弐If no packet is received from anywhere, it returns -1.

int zProcessPacket(int sockfd)


Description:
-壱This is a major function of the server. This is called in server main() after the listen() returns ‘0’
indicating packet is available on the socket.
-弐It first receives the packet from the socket using recvfrom() call. This packet could be any
packet received from any client.
-参It calls getTCB() function that looks up the TCB corresponding to the source of the packet,
decides the response and returns a value that means what response needs to be sent to client.
-四Based on the return value of the getTCB() function, it sends the response packet to the client.
For example, if client sent a SYN request packet, the return value from the getTCB() means send
the SYN-ACK to client, so it sends the SYN-ACK packet to the client.
-伍Save the packet for retransmission and set the retransmission time.
-六If the packet had the ACK for any un-acknowledged data, then delete that from the
retransmission list.

Return:
-壱Returns ‘0’ if there no error.
-弐Returns ‘-1’ if there is any error.

int zRetransmit()
Description:
-壱This function goes through all the TCBs and looks for un-acknowledged data.
-弐If there is any un-acknowledged data, it looks at the retransmit time for this data.
-参If the current time is < retransmit time, skip, and go to next TCB
-四If the current time is >= retransmit rime, retransmit the packet. And reset the retransmit time
by next interval.
-伍Go to the next TCB.

Return:
-壱Return ‘0’ if there is no error.
-弐Return ‘-1’ if there is any error.
getTCB (zpacket *recvPkt, zpacket *sendPkt, int sockfd)
Description:
-壱First get the sender address and port number from the recvPkt
-弐Lookup the TCB matching these address and port number.
-参If TCB is not found, and the recvPkt is SYN request packet, then create a new TCB for this
connection.
-四Based on the current state of the TCB and control bits in the packet, call the TCP state
machine.
-伍The TCP state machine will decide the next state of the TCB and the next action to take. For
example if the packet is SYN request then the next state would be SYN-RCVD and next action
would be send SYN-ACK.
-六Call the function copyClientData() that copies the data from the recvPkt to the sendPkt and
converts it into the upper case.
-七Prepare the packet to be sent in the sendPkt with the control bits and proper seq-num and
ack-num.

Return:
-壱Returns the value corresponding to the action to be taken.

int zserverSocket()
Description:
-壱create a struct zionSocket
-弐call the socket() function to create a UDP socket and keep this socket fd in the zionSocket
-参Return the address of the zionSocket.
·Project Postmorten
Problems faced:
1. How to wait for packet on the socket.
Solution: Found the select call provides the facility to wait
for incoming data on socket fd.

2. How to handle multiple clients.


Solution: I looked at the Berkeley TCP implementation. It implements
the TCP as single task that handles each connection
as TCB. It keeps receiving the packet from IP and
queues it to the sockets and wakes up the process waiting on it.
I used the similar mechanism in zion TCP implementation where
multiple connections are handled as TCBs. In this implementation,
the server is also running in the context of TCP process so I
did not have to create a seperate process to handle every client.

3. How to handle retransmit timer processing.


Solution: The main issues was to whether create a new timer process
or get the timer alarm in the same process. The new process creation
involves use of shared data and mutex.
The SIGALARM could interrupt the process any time.
So I utilized the select call to handle the timer functionality.
The select call waits for exactly 1 second to check for any data,
if the data is not available, it returns '-1' and that is the time
I did the retransmit processing.

4. Sequence number and FIN issues.


Solution: I studied the ethreal capture for the connection with Yahoo and Google.
This gave goog information about the correct increment of sequence numbers.
Initially I was incrementing the sequence number by 1 but I noticed that
it is incremented by the data length. Same way the FIN processing should
have the ACK set in the FIN request and ACK off in the FIN ack packet.

5. How to create error scenerios.


Solution: When both client and server were doing the right job,
there is no way to create the scenerions like half-open
connection and retransmission. So we wrote the test clients that
would send the packets without first stablishing the connection
so the server would sent RST. So several test clients were written to
simulate the error scenerios.

·
·Conclusion
To Conclude I’ll summarize some of the achievement and some of the shortfalls of our
adventure. We started of to implement TCP, and what I think we ended up is a protocol which is
not totally reliable in the sense it doest not support flow control fully i.e out of sequence packets
are not put back in order. Our server/client is able to connect successfully to others server/client,
although we faced lot of issues with network byte order used by other teams. Basic connection
establishment and connection termination is successfully performed. There are also checks
involving incorrect states of connection and following TCP state diagram.

Other than just the technical difficulties we faced we were having problems managing all our code
files. So we think central repositories managing code are good for handling such large projects.

You might also like