Friday, 4 September 2015

Useful String Operations used in real time C language


The Following list of String operations are being used in real time C applications.

String Operations:
==================

Header File Required : #include<string.h>

------------------------
strcat(), strncat()
------------------------

Concatenate two strings into a single string.


Prototypes
------------
#include <string.h>
int strcat(const char *dest, const char *src);
int strncat(const char *dest, const char *src, size_t n);

Concatenate", for those not in the know, means to "stick together".
These functions take two strings, and stick them together, storing the result in the first string.


Return Value
-------------
Both functions return a pointer to the destination string, like most of the string-oriented functions.


Example
========

char dest[20] = "Hello";
char *src = ", World!";
char numbers[] = "12345678";

printf("dest before strcat: \"%s\"\n", dest); // "Hello"

strcat(dest, src);
printf("dest after strcat:  \"%s\"\n", dest); // "Hello, world!"

strncat(dest, numbers, 3); // strcat first 3 chars of numbers
printf("dest after strncat: \"%s\"\n", dest); // "Hello, world!123"


--------------------------------------------------------------

strchr(), strrchr()  : Find a character in a string.
---------------------------------------------------------------



strchr() : Find the first occurance of a letter in a string
----------

strrchr(): Find the last occurance of a letter in a string
---------          
(The extra "r" in strrchr() stands for "reverse"-- it looks starting at the end of the string and working backward.)

-----------
Example 1:
----------

The above function returns a pointer to the char or NULL if the letter isn't found in the string.

// "Hello, world!"
//       ^  ^  
//       A  B

char *str = "Hello, world!";
char *p;

p = strchr(str, ','); // p now points at position A
p = strrchr(str, 'o'); // p now points at position B

-----------
Example 2:
----------

// repeatedly find all occurances of the letter 'B'
char *str = "A BIG BROWN BAT BIT BEEJ";
char *p;

for(p = strchr(str, 'B'); p != NULL; p = strchr(p + 1, 'B')) {
    printf("Found a 'B' here: %s\n", p);
}

// output is:
//
// Found a 'B' here: BIG BROWN BAT BIT BEEJ
// Found a 'B' here: BROWN BAT BIT BEEJ
// Found a 'B' here: BAT BIT BEEJ
// Found a 'B' here: BIT BEEJ
// Found a 'B' here: BEEJ


-------------------------------------------------------
strstr()  : Find a string in another string.
-------------------------------------------------------

#include <string.h>
char *strstr(const char *str, const char *substr);


Return Value:
------------
You get back a pointer to the occurance of the substr inside the str, or NULL if the substring can't be found.

----------------------------------------------------------------
Example :
----------------------------------------------------------------

char *str = "The quick brown fox jumped over the lazy dogs.";
char *p;

p = strstr(str, "lazy");
printf("%s\n", p); // "lazy dogs."

// p is NULL after this, since the string "wombat" isn't in str:
p = strstr(str, "wombat");


---------------------------------------------
strtok()
---------------------------------------------

Tokenize a string.

#include <string.h>
char *strtok(char *str, const char *delim);

If you have a string that has a bunch of separators in it, and you want to break that string up into individual pieces,
this function can do it for you.

Note that it does this by actually putting a NUL terminator after the token, and then returning a pointer to the start of the token.
So the original string you pass in is destroyed, as it were.
If you need to preserve the string, be sure to pass a copy of it to strtok() so the original isn't destroyed.

Return Value:
------------
A pointer to the next token. If you're out of tokens, NULL is returned.

-------
Example
-------

// break up the string into a series of space or
// punctuation-separated words
char *str = "Where is my bacon, dude?";
char *token;

// Note that the following if-do-while construct is very very
// very very very common to see when using strtok().

// grab the first token (making sure there is a first token!)
if ((token = strtok(str, ".,?! ")) != NULL) {
    do {
        printf("Word: \"%s\"\n", token);

        // now, the while continuation condition grabs the
        // next token (by passing NULL as the first param)
        // and continues if the token's not NULL:
    } while ((token = strtok(NULL, ".,?! ")) != NULL);
}

// output is:
//
// Word: "Where"
// Word: "is"
// Word: "my"
// Word: "bacon"
// Word: "dude"
//



---------------------------------------------
strspn(), strcspn()
---------------------------------------------



#include <string.h>
size_t strspn(char *str, const char *accept);
size_t strcspn(char *str, const char *reject);

strspn() will tell you the length of a string consisting entirely of the set of characters in accept.
That is, it starts walking down str until it finds a character that is not in the set
(that is, a character that is not to be accepted), and returns the length of the string so far.

strcspn() works much the same way, except that it walks down str until it finds a character
in the reject set (that is, a character that is to be rejected.) It then returns the length of the string so far.


Return Value

The lenght of the string consisting of all characters in accept (for strspn()),
or the length of the string consisting of all characters except reject (for strcspn()


Example
========

char str1[] = "a banana";
char str2[] = "the bolivian navy on manuvers in the south pacific";

// how many letters in str1 until we reach something that's not a vowel?
n = strspn(str1, "aeiou");  // n == 1, just "a"

// how many letters in str1 until we reach something that's not a, b,
// or space?
n = strspn(str1, "ab "); // n == 4, "a ba"

// how many letters in str2 before we get a "y"?
n = strcspn(str2, "y"); // n = 16, "the bolivian nav"


-------------------

strcpy(), strncpy()   : Copy a string

---------------------


Prototypes

#include <string.h>
char *strcpy(char *dest, char *src);
char *strncpy(char *dest, char *src, size_t n);

Description

These functions copy a string from one address to another, stopping at the NUL terminator on the srcstring.

strncpy() is just like strcpy(), except only the first n characters are actually copied.
Beware that if you hit the limit, n before you get a NUL terminator on the src string,
your dest string won't be NUL-terminated. Beware! BEWARE!

(If the src string has fewer than n characters, it works just like strcpy().)

You can terminate the string yourself by sticking the '\0' in there yourself:


Example
=======

char s[10];
char foo = "My hovercraft is full of eels."; // more than 10 chars

strncpy(s, foo, 9); // only copy 9 chars into positions 0-8
s[9] = '\0';        // position 9 gets the terminator


Thursday, 29 January 2015

What is Unix or Domain Socket? How to implement unix Socket in C?

In this post, i will explain about Unix/Domain Sockets.

Why Unix Sockets are Required?


You might have heard different types of sockets like TCP, UDP, SCTP, RAW etc.
These sockets are useful best for inter communications where IP address and port number (TCP /UDP Header) is most important.

When there are two process let's say X and Y reside in the same system(machine) needs to communicate each other, then which sockets would be the better option?

For the above case, i would prefer to use UNIX sockets rather than TCP/UDP sockets, since there is no over head of TCP/UDP header.  Unix Sockets doesn't carry any TCP/UDP header for communication.

What is Unix Socket?

A Unix domain socket  is a data communications endpoint for exchanging data between processes executing within the same host operating system. 

While similar in functionality to named pipes.Unix domain sockets may be created as connection‑mode (SOCK_STREAM or SOCK_SEQPACKET) or as connectionless (SOCK_DGRAM), while pipes are streams only. 

Processes using Unix domain sockets do not need to share a common ancestry. The API for Unix domain sockets is similar to that of an Internet socket, but it does not use an underlying network protocol for communication. 

Unix domain sockets use the file system as their address name space. They are referenced by processes as inodes in the file system. This allows two processes to open the same socket in order to communicate. However, communication occurs entirely within the operating system kernel.

In addition to sending data, processes may send file descriptors across a Unix domain socket connection using the sendmsg() and recvmsg() system calls. 

How to Implement Unix Sockets?

In Unix sockets,  the socket API are similar to internet socket.

Unix Socket create using API:

 if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        perror("server: socket");
        return -1;
    }


    /*
     * Create the address we will be connecting to.
     */
    address.sun_family = AF_UNIX;
    snprintf(address.sun_path, UNIX_PATH_MAX, "demo_socket");


UNIX CLIENT PROGRAM
-----------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define UNIX_PATH_MAX 108

/*
 * Strings we send to the server.
 */
char str[100] ;

int main()
{
    int sock_fd= -1, i, len;
 
    /* Unix Sock Address structure */
    struct sockaddr_un address;

    /*
     * Create domain socket.
     * This socket will be in the UNIX domain,
     * and will be a stream socket.
     */
    if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        perror("server: socket");
        return -1;
    }
     /* start with a clean address structure */
    memset(&address, 0, sizeof(struct sockaddr_un));

    /*
     * Create the address we will be connecting to.
     */
    address.sun_family = AF_UNIX;
    snprintf(address.sun_path, UNIX_PATH_MAX, "demo_socket");



    /*
     * Connect to the address.  For this to
     * succeed, the server must already have bound
     * this address, and must have issued a listen()
     * request.
     *
     * The third argument indicates the "length" of
     * the structure.
     *
     */
    if(connect(sock_fd,
            (struct sockaddr *) &address,
            sizeof(struct sockaddr_un)) != 0)
     {
       printf("connect() failed\n");
       return 1;
     }

    /* Send and recieve Data
     *   in while Loop
     */
    while(printf("> "), fgets(str, 100, stdin), !feof(stdin))
    {
        /* Send the Data to server */
        if (send(sock_fd, str, strlen(str), 0) == -1)
         {
            perror("send");
            return 1;
         }

        /* Recieve the Date from Server */
        if ((len=recv(sock_fd, str, 100, 0)) > 0)
         {
            str[len] = '\0';
            printf("echo> %s", str);

         }
        else
         {
            if (len < 0)
              perror("recv");
            else // Length = 0
              printf("Server closed connection\n");
              return 1;
        }
     }
    /*
     * We can simply use close() to terminate the
     * connection, since we're done with both sides.
     */
    close(sock_fd);

    return 0;
}

UNIX SERVER PROGRAM
-----------------------------------

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define UNIX_PATH_MAX  108

char str[100];

int main()
{

    /* Sock Fd and Connection Fd = -1 */
    int  sock_fd= -1, connection_fd = -1, listen_fd =-1, i;

   /* unix Socket address Structure */
    struct sockaddr_un address;
   
    /* Socket Address Len */
    socklen_t address_len;

    /*
     * Get a socket to work with.  This socket will
     * be in the UNIX domain, and will be a
     * stream socket.
     */
    if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        perror("server: socket");
        return -1;
    }

     /* start with a clean address structure */
     memset(&address, 0, sizeof(struct sockaddr_un));

    /*
     * Create the address we will be binding to.
     */
     address.sun_family = AF_UNIX;
     snprintf(address.sun_path, UNIX_PATH_MAX, "demo_socket");


    /*
     * Bind the address to the socket.  We
     * unlink the name first so that the bind won't
     * fail.
     *
     * The third argument indicates the "length" of
     * the structure, not just the length of the
     * socket name.
     */

     unlink("demo_socket");
    
     if(bind(sock_fd,
                 (struct sockaddr *) &address,
                 sizeof(struct sockaddr_un)) != 0)
      {
          printf("bind() failed\n");
          return 1;
      }

    /*
     * Listen on the socket.
     */
      if( listen_fd = listen(sock_fd, 5) != 0)
       {
          printf("listen() failed\n");
          return 1;
       }
    
    /*
     * Accept connections.  When we accept one, ns
     * will be connected to the client.  fsaun will
     * contain the address of the client.
     */
    while (1)
    {
       int done, len;

       connection_fd = accept(sock_fd,
             (struct sockaddr *)&address,
             &address_len);
       if(connection_fd < 0)
       {
         perror("server: accept");
         return -1;
       }
      
       close(listen_fd);
      
       /* Recv and Send in Infinite Loop */
       done = 0;
       do
       {
          /* Recieve Data from Client */
          len = recv(connection_fd, str, 100, 0);

          if (len <= 0)
          {
             if (len < 0)
                perror("recv");
             done = 1;
          }

          if (!done)
             /* Send Data to Client */
             if (send(connection_fd, str, len, 0) < 0)
              {
                  perror("send");
                  done = 1;
              }
        } while (!done);

      /*
       * We can simply use close() to terminate the
       * connection, since we're done with both sides.
       */
   
      close(connection_fd);
    }
    return 0;
}


--------------------------------------------------------------
 HOW UNIX SOCKETS ARE USED IN REAL TIME APPLICATIONS
------------------------------------------------------------- 
Explain With simple example:

Let's take two process x_process (as a client) and y_process(as a server.
x_process have different call back functions and it shall be triggered based on the message type send from the server(y_process).


x_process registers the call back functions for different Message types during initialization time.

Message Types : HELLO_MESSAGE, DOWN_MESSAGE, UPDATE_MESSAGE.

Based on the respective message, the corresponding call back function is called.

x_process   (CLIENT)
------------
#include<stdio.h>
#include<stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include "message.h"

#define SOCK_PATH "echo_socket"


/* Hello Message Handle Function */
int handle_hello_message_func(int message_type)
{
   printf(" I am in Hello function \n");
   return 0;
}

/* Down Message Handle Function */
int handle_down_message_func(int message_type)
{
   printf(" I am in down function \n");
   return 0;
}

/* Update Message Handle Function */
int handle_update_message_func(int message_type)
{
   printf(" I am in update function \n");
   return 0;
}

/*
 * Trigger Callback function
 */

void trigger_callback_function(char *str, struct handle_msg *msg)
{

  printf("%s", str);

  if(strcmp(str, "HELLO_MESSAGE\n") == 0)
      msg->callback_function[HELLO_MESSAGE](HELLO_MESSAGE);
  else if (strcmp(str, "UPDATE_MESSAGE\n") == 0)
      msg->callback_function[UPDATE_MESSAGE](UPDATE_MESSAGE);
  else if (strcmp(str, "DOWN_MESSAGE\n") == 0)
      msg->callback_function[DOWN_MESSAGE](DOWN_MESSAGE);
  else
      printf(" Message is not Known, Ignored ");
}

/*
 * Unix Socket Creation
 *
 */ 

int unix_socket_init(struct handle_msg **msg)
{
   int len, recv_len, t,s;
 
   /* Declare the remote (Server) structure */
   struct sockaddr_un remote;

   char str[100];

   /* Create Unix Socket */
   (*msg)->sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);

   if((*msg)->sock_fd < 0)
    {
      perror("socket");
      return 1;
    }
  
   printf("Trying to connect...\n");

   /* Set the server Attributes */
   remote.sun_family = AF_UNIX;
   strcpy(remote.sun_path, SOCK_PATH);
   
   /* Calculate the length */
   len = strlen(remote.sun_path) + sizeof(remote.sun_family);
  
   /* Connect to the server */
   if (connect((*msg)->sock_fd, (struct sockaddr *)&remote, len) == -1) {
        perror("connect");
        return 1;
    }

   printf("Connected.\n");

   s= (*msg)->sock_fd;

   /* Send and recieve in while Loop */
   while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
        if (send(s, str, strlen(str), 0) == -1) {
            perror("send");
            exit(1);
        }

        if ((t=recv(s, str, 100, 0)) > 0) {
            str[t] = '\0';
            printf("echo> %s", str);

        /* Trigger the Respective Call back Function */
        trigger_callback_function(str, *msg); 

         
        } else {
            if (t < 0) perror("recv");
            else printf("Server closed connection\n");
            exit(1);
        }
     }
   close(s);
}

/* Intialise the X process
 * Step 1 : Create Unix Socket
 * Step 2 : Register the CallBack functions with the Lib Code
 *
 *
 */
void x_client_process_init()
{

   struct handle_msg *msg= NULL;

   /* Allocate Message Structure */
   msg= (struct handle_msg *)malloc(sizeof(struct handle_msg));


   /* Register the server HELLO call back function */
   client_register_callback_function(msg, HELLO_MESSAGE,
                                     handle_hello_message_func );

   /* Register the server DOWN call back function */
   client_register_callback_function(msg, DOWN_MESSAGE,
                     handle_down_message_func);

   /* Register the server DOWN call back function */
   client_register_callback_function(msg, UPDATE_MESSAGE,
                     handle_update_message_func);

 
   /* Create Unix Socket and  connect to the server*/
   unix_socket_init(&msg);
}

int main()
{
   /* Intialise the X Client Process */
   x_client_process_init();
  
 
   return 0;
}

message.h  (Common File)
========================

/* DECLARE THE DIFFERENT Message TYPES between Server and Client */
#define HELLO_MESSAGE                   0
#define UPDATE_MESSAGE                  1
#define DOWN_MESSAGE                    2
#define MAX_MESSAGE                     3

/* There are many ways to declare array of Call back functions */
/* One way is :
 *  -> int (*fun[10])(int, int) or
 *  -> typedef int (*func)(int, int); func arrayfunc[10]
 */
/* Declare the Message Call back handler function */
typedef int (*CALLBACK_MESSAGE)(int message_type);




/* Common Message Structure for Client and Server */
struct handle_msg
{

  /* Socket to accept or connect.  */
  int sock_fd;

  /* functions registers in to this call back function */
  CALLBACK_MESSAGE callback_function[MAX_MESSAGE];
};

/* Register the call back functions
 * once the functions are registered and will be
 * triggered dynamically
 *
 */

void client_register_callback_function(struct handle_msg *msg,
                              int message_type,
                              CALLBACK_MESSAGE cb)
{
  if (message_type >= MAX_MESSAGE)
    return;

  msg->callback_function[message_type] = cb;
}


Y_PROCESS (Server)
================
#include<stdio.h>
#include<stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include "message.h"

#define SOCK_PATH "echo_socket"

/*
 * Server Unix Socket Creation
 *
 */
int server_unix_socket_init(struct handle_msg **msg)
{

   int s, connect_fd, t, len;
   struct sockaddr_un local, remote;
   char str[100];


   /* Create Unix Socket */
   (*msg)->sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);

   if((*msg)->sock_fd < 0)
    {
       perror("socket");
       return 1;
    }

   /* Populate the local structure */
   local.sun_family = AF_UNIX;
   strcpy(local.sun_path, SOCK_PATH);
  
   /* Unlink the path */
   unlink(local.sun_path);
  
   len = strlen(local.sun_path) + sizeof(local.sun_family);
  
   /*
    * Bind to the Local path -> For Unix Sockets there will not
    * be any port Num or IP address
    *
    * It will bind to the local path.
    */   

   if (bind((*msg)->sock_fd, (struct sockaddr *)&local, len) == -1)
    {
        perror("bind");
        return 1;
    }

    if (listen((*msg)->sock_fd, 5) == -1) {
        perror("listen");
        return 1;
    }

    for(;;)
      {
        int done, n;
        printf("Waiting for a connection...\n");
        len = sizeof(remote);
       
  
        connect_fd = accept((*msg)->sock_fd, (struct sockaddr *)&remote, &len);
       
        if((*msg)->sock_fd < 0)
         {
            perror("accept");
            return 1;
         }

        printf("Connected.\n");

 
        done = 0;
        do {
            n = recv(connect_fd, str, 100, 0);
            if (n <= 0) {
                if (n < 0) perror("recv");
                done = 1;
            }

            if (!done)
                if (send(connect_fd, str, n, 0) < 0) {
                    perror("send");
                    done = 1;
                }
        } while (!done);
         
        /* Send and recieve in while Loop */
        close(connect_fd);
     }
}
/*
 * Y server process init()
 */
void y_server_process_init()
{
   struct handle_msg *msg= NULL;

   /* Allocate Message Structure */
   msg= (struct handle_msg *)malloc(sizeof(struct handle_msg));


   /* Create Server Unix Socket, listen and accept the connection*/
   server_unix_socket_init(&msg);

}
/*
 * Main()
 */
int main()
{
   /* Intialise the Y Process */
   y_server_process_init();

}



NOTE: Give Input as " HELLO_MESSAGE\n"  or DOWN_MESSAGE\n, UPDATE_MESSAGE\n to get proper output.   "\n" is getting added to the string while reading.









Friday, 22 August 2014

What is SKB in Linux kernel? What are SKB operations? Memory Representation of SKB? How to send packet out using skb operations?

As many of them are aware, OSI reference and TCP/IP Model.

For any Networking application TCP/IP model is required to process/route the packets from one end to other. Then, How to support the networking in Linux kernel?  How to process the packets in Linux kernel?   

This article will answer the above questions.
  •   A network interface represents a thing which sends and receives packets. This is normally interface code for a physical device like an ethernet card. However some devices are software only such as the loopback device which is used for sending data to yourself.
  • The network subsystem of the Linux kernel is designed to be completely protocol-independent. This applies to both networking protocols (Internet protocol [IP] versus IPX or other protocols) and hardware protocols (Ethernet versus token ring, etc.).
  •    A header is a set of bytes (err, octets) prepended to a packet as it is passed through the various layers of the networking subsystem. When an application sends a block of data through a TCP socket, the networking subsystem breaks that data up into packets and puts a TCP header, describing where each packet fits within the stream, at the beginning. The lower levels then put an IP header, used to route the packet to its destination, in front of the TCP header. If the packet moves over an Ethernet-like medium, an Ethernet header, interpreted by the hardware, goes in front of the rest.

The two important data structures of Linux kernel network layer are:
-         sk_buff     (defined  in  /include/linux/sk_buff.h)


-         net_device  (defined  in  /include/linux/net_device.h)
Each interface is described by a struct net_device item. ( Please refer in another post)

What is sk_buff:
  • sk_buff means socket buffers. This is core structure in Linux networking.
  •  skbuffs are the buffers in which the Linux kernel handles network packets. The packet is received by the network card, put into a skbuff and then passed to the network stack, which uses the skbuff all the time.
  • In the same words as above:
As we need to manipulate packets through the Linux kernel stack, this manipulation involves efficiently:  
  • Adding protocol headers/trailers down the stack.
  •  Removing protocol headers/trailers up the stack. 
  •  Concatenating/separating data. 
  • Each protocol should have convenient access to header fields.
To order to perform all of above, kernel provides the sk_buff structure.

Structure of sk_buff

sk_buff structure is created when an application passes data to a socket or when a packet arrives at the network adaptor (dev_alloc_skb() is invoked).


MEMORY Representation of SKB structure:
SKB has four parts. Memory representation of skb structure is depicted below.


sk_buff has five pointers as mentioned below.
head      
the start of the packet
data
the start of the packet payload
tail 
the end of the packet payload
end  
the end of the packet
len
the amount of data of the packet

As shown in above figure, Skb memory usually has four parts:
1.       head room : located skb-> between the head and skb-> data, which is stored in the local network protocol header, such as TCP, IP header, Ethernet header are located here;
2.       User data  : usually filled by the application layer calls through the system between skb-> data and skb-> tail between;
3.       tail room : between skb-> tail and skb-> end, which is the core part of the user data to fill in the back part;
4.       skb-> after the end is stored in a special structure struct skb_shared_info.

STEPS for sending the packet out using SKB OPERATIONS:

Step 1:   Allocate Memory for the skb
 
skb = alloc_skb(len, GFP_KERNEL);
Once the skb is allocated with memory using alloc_skb() then it will look like as shown in below.

As you can see, the head, data, and tail pointers all point to the beginning of the data buffer. And the end pointer points to the end of it. Note that all of the data area is considered tail room.
The length of this SKB is zero, it isn't very interesting since it doesn't contain any packet data at all. 

Step 2:  Space for Headroom to add protocol headers (Ethernet + IP+ TCP headers etc..)

Reserve some space for protocol headers using skb_reserve().It usually initialize the head room, by calling skb_reserve () function as shown in figure below.


skb_reserve(skb, header_len);


skb->data and skb->tail pointer increments (advances or moves) by the specified Header length.


For example, the TCP layer to send a data packet, head room, at least if tcphdr + iphdr + ethhdr. 

Step 3 :  Add the User Data (payload) after the skb->put()
skb_put() advances (moves the) 'skb->tail' pointer by the specified number of bytes (user_data_len), it also increments 'skb->len' by that number of bytes as well. This routine must not be called on a SKB that has any paged data. 

unsigned char *data = skb_put(skb, user_data_len);                    
memcpy(data, 0x11,  user_data_len);

 
Step 3:  Add the Headers Using the skb->push()  in the Headroom

skb_push() will decrement the 'skb->data' pointer by the specified number of bytes. It will also increment'skb->len' by that number of bytes as well.  Make sure that there is enough head room for the push being performed.
For example , push the TCP header to the front of the SKB.
unsigned char *tcp_header = skb->push(skb, sizeof(struct udphdr));
struct tcphdr *tcp;
tcp = tcp_header;
 
tcp->source = htons(1025);
tcp->dest = htons(2095);
tcp->len = htons(user_data_len);
tcp->check = 0;
 
skb->pull()   :
Remove the respective headers From the Headroom and returning the bytes to headroom using skb_pull() operation.
It Increments (pulled down) the skb-> data by a specified number of bytes and decrements the skb_len.



Step 5: Similarly Push the Ipv4 header in to sk_buffer using
skb_push operation and send the packet out using dev_queue_xmit() function.
Please refer the example code below.

Pictorial representation of skb operations.


Some more skb operations 
skb_clone(),skb_copy(),skb_trim()

skb_clone() : This function will not copy the entire skb structure. It is just make the skb to point to the same region of memory on the line.
In this case data_ref pointer present in the skb_shared_info structure will be incremented to 2
For example:
Packets can be captured using "tcpdump" in linux kernel. At this point, the packet will be given to linux stack and the same packet is given to tcpdump as well (First protocol stack and after tcpdump). 
In this case not to completely copy skb it? Not necessary, because the two parts are read, the network data itself is unchanged, becomes just strcut sk_buff pointer inside, that is to say, we just copy skb to point to the same region of memory on the line! This is skb_clone () did:




It can also access using by skb + 1

skb_copy()
In some cases we need have to write a complete copy of their data skb call skb_copy().It copies entire data of skb and creates another skb. 

skb_trim()  : remove end from a buffer

Prototype
void skb_trim(struct sk_buff *skb, unsigned int len);

skb support functions

There are a bunch of skb support functions provided by the sk_buff layer. 

allocation / free / copy / clone and expansion functions

struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)
This function allocates a new skb. This is provided by the skb layer to initialize some privat data and do memory statistics. The returned buffer has no headroom and a tailroom of /size/ bytes.

void kfree_skb(struct sk_buff *skb)
Decrement the skb's usage count by one and free the skb if no references left.

struct sk_buff *skb_get(struct sk_buff *skb)
Increments the skb's usage count by one and returns a pointer to it.

struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
This function clones a skb. Both copies share the packet data but have their own struct sk_buff. The new copy is not owned by any socket, reference count is 1.

struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask)
Makes a real copy of the skb, including packet data. This is needed, if You wish to modify the packet data. Reference count of the new skb is 1.

struct skb_copy_expand(const struct sk_buff *skb, int new_headroom, int new_tailroom, int gfp_mask)
Make a copy of the skb, including packet data. Additionally the new skb has a haedroom of /new_headroom/ bytes size and a tailroom of /new_tailroom/ bytes.

anciliary functions

int skb_cloned(struct sk_buff *skb)
Is the skb a clone?

int skb_shared(struct sk_Buff *skb)
Is this skb shared? (is the reference count > 1)?

operations on lists of skb's

struct sk_buff *skb_peek(struct sk_buff_head *list_)
peek a skb from front of the list; does not remove skb from the list

struct sk_buff *skb_peek_tail(struct sk_buff_head *list_)
peek a skb from tail of the list; does not remove sk from the list

__u32 skb_queue_len(sk_buff_head *list_)
return the length of the given skb list

void skb_queue_head(struct sk_buff_head *list_, struct sk_buff *newsk)
enqueue a skb at the head of a given list

void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
enqueue a skb at the end of a given list. 

int skb_headroom(struct sk_buff *skb)
return the amount of bytes of free space at the head of skb

int skb_tailroom(struct sk_buff *skb)
return the amount of bytes of free space at the end of skb

struct sk_buff *skb_cow(struct sk_buff *skb, int headroom)
if the buffer passed lacks sufficient headroom or is a clone it is copied and additional headroom made available. 

void struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
            skb_dequeue() takes the first buffer from a list (dequeue a skb from the head of the given list) If the list is empty a NULL pointer is returned. This is used to pull buffers off queues. The buffers are added with the routines skb_queue_head() andskb_queue_tail().

struct sk_buff *sbk_dequeue_tail(struct sk_buff_head *list_)
              dequeue a skb from the tail of the given list 

Network device packet flow:

How to Identify skb is linear or not.
Data is placed between skb-> head and skb-> end, it is called as linear (linear).
skb->data_len == 0  is Linear.

else
If skb is not linear  means  skb->data_len != 0
the length of  skb->data is (skb->len) - (skb-> data_len) for the head ONLY.


Pseudocode
----------
/* SKB Is Linear */
  if (skb->data_len == 0)
    {
      printk(" Skb is Linear : the skb_len is :%d", skb->len);
    }
  /* SKB Is Not Linear */
  else
    {
      if(skb->data_len != 0)
        {
          skb->len = (skb->len) - (skb->data_len);
        }
       Printk(“Skb is Not Linear : the skb_len is :%d", skb->len);

    }

skb->data_len =   struct skb_shared_info->frags[0...struct skb_shared_info->nr_frags].size
                                          + size of data in struct skb_shared_info->frag_list

When SKB is Non Linear?

First Model :
One is the common NIC driver model, data is stored in different locations of physical pages, skb_shared_info there are an array to store a set of (page, offset, size) of the information used to record these data


Second Model:
frag_list assembled IP packet fragmentation (fragment) when used in: 
Fragmentation of data has its own skb structure, which through skb-> next link into a single linked list, the first table is the first one in the skb shared_info frag_list.


Third  Model:
GSO segment (segmentation) used a model, when a large TCP data packets are cut into several MTU size, they are also through skb-> next link together:


References:
http://wangcong.org/blog/archives/2337
http://www.skbuff.net/skbbasic.html
http://vger.kernel.org/~davem/skb_data.html
http://blog.csdn.net/npy_lp/article/details/7263902