hvn-network

My Blog List

Showing posts with label Created by Hung Son (Clark). Show all posts
Showing posts with label Created by Hung Son (Clark). Show all posts

Monday, September 19, 2016

Debug and Log system

1. What is debugging technique
- Debug is a work that eliminate all mistakes in a program to the program works in whatever situation. Usually, fixing a bug requires us to know the reasons it appears

- In common, there are three techniques for finding bugs:
+ Using printf or cout statements
+ Including command lines debug switch (using MACROs)
+ Using a debugger (ex: gdb, ..)

2. Logger in HG700
a. User space API
User space defines 4 levels of log severity (debug, information, error, critical). The macros are:
- LOGF_LOG_CRITICAL(...)
- LOGF_LOG_ERROR(...)
- LOGF_LOG_INFO(...)
- LOG_LOG_DEBUG(...)
One additional macro, LOGF_LOG, is available for developer debugging. Should a developer require a record to be logged beyond any of the proposed levels, this could be used.

Note: To use logging API, modules must include “ulogging.h” in C files and add the following code to global section (in any one of the C files)
//#define BENCHMARK 
#ifndef LOG_LEVEL
uint16_t LOGLEVEL = SYS_LOG_DEBUG + 1;
#else
uint16_t LOGLEVEL = LOG_LEVEL + 1;
#endif
#else

#ifndef LOG_TYPE
uint16_t LOGTYPE = SYS_LOG_TYPE_FILE;
#endif
uint16_t LOGTYPE = LOG_TYPE;
b. Kernel space API
The kernel log API provide a way for the kernel modules to record their logging messages (to a file, show log in a terminal, ...). Refer the API’s provided through the header file “klogging.h” added by kernel patch

c. Usage examples:
Putting log messages
LOGF_LOG_DEBUG(“Logginf messages\n”);
Putting log messages with integer and string
LOGF_LOG_DEBUG(“Logging messages, int_var: %d, string_var: %s\n”, int_var, string_var);
(Changing SL Log Level and Type at Run-time)
Modify and print specific Log level(7) and Log type(2)
      slloglevel sl_network 7 2

Modify and print all SL log level and Log type
      slloglevel all 7 2
      slloglevel print all

Note: Log level values [0 .. 7]
          Log type values [0 .. 3]
          Log type 0 -> None, 1 -> File, 2 -> Console, 3 -> File & Console)
d. Guidelines for Log Level Usage
  • DEBUG level includes ALL messages from the module. This is not enabled in normal image. If a problem occurs on the image and you want to debug, this mode can be enabled. Dumping the complete contents of posts, objects list, parameters list are good candidates.
  • INFO level indicates informational messages to the user to know state of the box. Like csd has started, servd started. Service library is initialized successfully. DSL is up. WAN PPPoE is up
  • CRITICAL within a module, shows either module can not start (SL initialization can not be done, a dependent component is missing, a configuration file missing, module is exiting) or can not proceed in abnormal conditions (no memory available)
  • ERROR level is nay other message which does not fit the above three and throws up error conditions in the box
e. Library: ulogging.h , syslog.h
The C library of Intel framework
Define Log level and log type
//#define SYS_LOG_EMERG     LOG_EMERG 
//#define SYS_LOG_ALERT     LOG_ALERT
#define SYS_LOG_CRIT      LOG_CRIT     /*!< critical level   */ 
#define SYS_LOG_ERR       LOG_ERR    /*!< error level   */ 
//#define SYS_LOG_WARNING   LOG_WARNING 
//#define SYS_LOG_NOTICE    LOG_NOTICE 
#define SYS_LOG_INFO      LOG_INFO     /*!< info level   */ 
#define SYS_LOG_DEBUG     LOG_DEBUG    /*!< debug level   */ 

#define SYS_LOG_TYPE_NONE               0    /*!< log type  */ 
#define SYS_LOG_TYPE_FILE             (1 << 0)   /*!< log type file  */ 
#define SYS_LOG_TYPE_CONSOLE          (1 << 1)   /*!< log type console    */ 
#define SYS_LOG_TYPE_FILE_AND_CONSOLE (SYS_LOG_TYPE_FILE | SYS_LOG_TYPE_CONSOLE)    /*!< log type both console and file    */
LOG Macro function
/* PACKAGE_ID will be provided by relevant package make file.  */
#define LOGF_LOG_ERROR(args...)       PRINTF(ERR, ##args);   /*!< macro to define error level  */ 
#define LOGF_LOG_EMERG(args...)       PRINTF(EMERG, ##args)   /*!< macro to define emergency level  */ 
#define LOGF_LOG_ALERT(args...)       PRINTF(ALERT, ##args)    /*!< macro to define alert level  */ 
#define LOGF_LOG_CRITICAL(args...)    PRINTF(CRIT, ##args)  /*!< macro to define critical level  */ 
#define LOGF_LOG_WARNING(args...)     PRINTF(WARNING, ##args)  /*!< macro to define warnning  level  */ 
#define LOGF_LOG_NOTICE(args...)     PRINTF(NOTICE, ##args)  /*!< macro to define notice level  */ 
#define LOGF_LOG_INFO(args...)      PRINTF(INFO, ##args)  /*!< macro to define info level  */ 
#define LOGF_LOG_DEBUG(args...)       PRINTF(DEBUG, ##args)   /*!< macro to define debug level  */ 
#define LOGF_LOG(LEVEL, fmt, args...) SYSLOG_##LEVEL(PACKAGE_ID"{%s, %d}:"fmt, __func__, __LINE__, ##args) /*!< PRINTF Macro */ 
#define PRINTF(LEVEL, fmt, args...)   SYSLOG_##LEVEL(PACKAGE_ID"{%s, %d}:"fmt, __func__, __LINE__, ##args) /*!< PRINTF Macro */ 
The C library of Linux
Define priorities

#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR  3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */

And one C file that use debug and logging technique
cgi.c
Example using debug and logging
if (nRet == UGW_SUCCESS) {
   nRet = cgi_fileDownload(RESTORE);
   if (nRet == UGW_SUCCESS) {
    LOGF_LOG_INFO("Config file download completed !!\n");
   } else {
    LOGF_LOG_ERROR("Config file download failed !! nRet = %d\n", nRet);
    nDBRestore = 0;
    goto returnHandler;
   }
  } else {
   LOGF_LOG_ERROR("Config update Request Failed !! cal_set nRet = %d\n", nRet);
   nFirmwareUpgrade = 0;
   goto returnHandler;
  }

Tuesday, August 23, 2016

Socket

1. Socket and fundamental concepts
1.1 Definition
  • A socket is communication mechanism that allow client/server system to be developed either locally, on a single machine, or across networks. Linux function such as printing, connecting to database, and serving web pages as well as network utilities such as rlogin for remote login and ftp for file transfer usually use sockets to communicate
  • Another definition: A socket is just a logical endpoint for communication. They exist on the transport layer. You can send and receive things on a socket, you can bind and listen to a socket. A socket is specific to a protocol, machine, and port, and is addressed as such in the header of a packet.
  • A simple definition: A network socket is one endpoint in a communication flow between two programs running over a network
A simple socket model

1.2. Types of Socket
There are two types of socket used widely: stream sockets and datagram sockets
  • Stream Sockets (based on TCP protocol): is a stream oriented protocol. Delivery in a networked environment is guaranteed. If you send through the stream socket three items "A, B, C", they will arrive in the same order - "A, B, C". These sockets use TCP (Transmission Control Protocol) for data transmission. If delivery is impossible, the sender receives an error indicator. Data records do not have any boundaries. 
  • Datagram Sockets (based on UDP protocol): is a message oriented protocol. Delivery in a networked environment is not guaranteed. They're connectionless because you don't need to have an open connection as in Stream Sockets - you build a packet with the destination information and send it out. They use UDP (User Datagram Protocol)
1.3 Client-server model
Most of the Net application use the Client-Server architecture, which refers to two processes or two applications that communicate with each other to exchange some information. One of the two processes acts as a client process and another process acts as a server. 
  • Client process: This is the process, which typically makes a request for information. After getting the response, this process may terminate or may do some other processing. Example: Internet Browser (Chrome, Firefox, ..) works as a client application, which sends a request to the Web Server to get one HTML web page.
  • Server process: This is the process which takes a request from the clients. After getting a request from the client, this process will perform the required processing, gather the requested information, and send it to the request client. Once done, it becomes ready to server another client. Server processes are always alert and ready to serve incoming requests. Example: A web page server waiting for requests from Internet Browsers. 
There are two types of server: Iterative server, concurrent server
  • Iterative Server: This is the simplest form of server where a server process serves one client and after completing the first request, it takes request from another client. Meanwhile, another client keeps waiting.
  • Concurrent Servers: This type of server runs multiple concurrent processes to serve many requests at a time because one process may tke longer and another client cannot wait for so long. The simplest way to write a concurrent server under Unix is to fork  child process to handle each client separately
1.4 Ports and Services
When a client process wants to a connect a server, the client must have a way of identifying the server that it wants to connect. If the client knows the 32-bit Internet address (with IPv4, or 128-bit Internet address of Ipv6) of the host on which the server resides, it can contact that host. But how does the client identify the particular server process running on that host?


How to request a specific service

To resolve the problem of identifying a particular server process running on a host, both TP and UDP have defined a group of well-know ports that are in the range of 0 – 1023
For our different purposes, ports will be defined as an integer number between 1024-65535
The port assignments to network services can be found in the file /etc/services. If you are writing your own server then care must be taken to assign a port to your server. You should make sure that this port should not be assigned to any other server.

2. Socket connection
First, a server process gives the socket a name. Local sockets are given a filename in the Linux file system, often to be found in /tmp or /usr/tmp. For network sockets, the filename will be a service identifier allows Linux to route incoming connections specifying a particular port number to the correct server process.
2.1 Socket parameter
ü  The protocol (TCP, UDP, …)
ü  The local address
ü  The remote address
ü  The local port number
ü  The remote port number
Socket Parameter

2.2 Steps to establish a socket pair
Establish a socket connection

2.3 Core functions
Creating a socket
Socket Addresses: Each socket domain requires its own address format.
int socket(int domain, int type, int protocol);
}
struct socketaddr_un {
 sa_family_t sun_family;
 char sun_path[];
}
struct sockaddr_in {
 short int sin_family;  // AF_INET
 unsighed short int sin_port; // port number
 struct in_addr  sin_addr; // Internet address
}
The IP address structure, in_addr, is defined as follows
struct in_addr {
 unsigned long int s_addr;
};
Naming a Socket
To make a socket available for use by other processes, a server program needs to give the socket a name
      #include <sys/socket.h>
      int bind(int socket, const struct sockaddr *address, size_t address_len)
Creating a Socket Queue
      #include <sys/socket.h>
      int listen(int socket, int backog)
Accepting Connections
Once a server program has created and named a socket, it can wait for connections to be made to the socket by using the accept call
      #include <sys/socket.h>
      int accept(int socket, struct sockaddr *address size_t *address_len)
Requesting connections
Client program connect to servers by establishing a connection between an unnamed socket and the server listen socket
      #include <sys/socket.h>
      int connect(int socket, const struct socketaddr *address, size_t address_len);
Close a socket
You should always close the socket at both ends. 

3. Unix internal Socket and Unix network Socket

3.1 Unix internal Socket - Creating local Socket
You can download source here
3.2 Unix network Socket - Creating network Socket
You can download source here

4. Multiple client using fork()
4.1 Concurrent server
Server can serve more than one client in a time. We can see the way server do that by fork() to create child processes
Client connects to child server

Two clients connect to two child servers

4.2 Status of client/server before call to accept return

Status of client/server when client request connection

Status of client/server after return from accept

Status of client/server after fork return

Status of client/server after parent and child close appropriate sockets

4.3 Outline for typical concurrent server
pid_t pid;
int listenfd, connfd;
listenfd = Socket( ... );
/* fill in sockaddr_in{} with server's well-known port */
bind(listenfd, ... );
listen(listenfd, LISTENQ);
for ( ; ; ) 
{
 connfd = accept (listenfd, ... ); /* probably blocks */
 if( (pid = fork()) == 0) 
 {
  close(listenfd); /* child closes listening socket */
  doit(connfd); /* process the request */
  close(connfd); /* done with this client */
  exit(0); /* child terminates */
 }
 close(connfd); /* parent closes connected socket */
}

Code full:

4.4 Prevent zombie process
Using fork() to create child process to handle connections from clients causes “zombie process”. Obviously we do not want to leave ombies around. They take up space in the kernel and evenrually can run out of processes. We need to prevent that by handling SIGCHLD Signals. Whenever we fork children, we must wait for them to prevent them from becoming zombies. To di this, we establish a signal-handle to catch SIGCHLD, and within the handler, we call wait. We establish the signal handler by adding the function call
Signal(SIGCHLD, sig_chld);

References
Beginning Linux Programming
Unix network programming





Sunday, August 21, 2016

Queue

1. Definition:
Queue is a type of data structure that contain elements working basing on FIFO (stand for: First In First Out). In a queue, elements can be added in at any time, but only the first element can be archived. Pushing an element to a queue (enqueue) always takes place at the end (back) of a queue, and popping an element from a queue (dequeue) always takes place at the head (front) of the queue.
FIFO structure

2. Queue installed on an array
Queue installed on an array

#define MAX 100
typedef struct {
 int head, tail, count;
 int node[MAX];
} queue;

2.1 Initial an empty queue
void QueueInitialize(queue *q)
{
 q -> head = 0;
 q -> tail = MAX - 1;
 q -> count = 0;
 return;
}
2.2 Check if a queue is empty or full
int QueueEmpty(queue q)
{
 return (q.count <= 0);
}
2.3 Push function
Push function
void Push(queue *q, int x)
{
 if (q -> count == MAX)
  printf("Queue is full!\n");
 else 
 {
  if (q -> tail == MAX - 1)
   q -> tail = 0;
  else
   (q -> tail)++;
  q -> node[q -> tail] = x;
  q -> count++;
 }
 return;
}
2.4 Pop function
Pop function

int Pop(queue *q)
{
 int x;
 if (QueueEmpty(*q))
  printf("Queue is empty!\n");
 else
 {
  x = q-> node[q -> head];
  if (q -> head == MAX - 1)
   q -> head = 0;
  else
   (q -> head)++;
  q -> count--;
 }
 return x;
}
2.5 Full code
You can download code here
3. Queue installed on a linked list
struct node 
{
 int item;
 struct node *next;
};
typedef struct node *queuenode;
typedef struct {
 queuenode head;
 queuenode tail;
} queue;
3.1 Initial an empty queue
void QueueInitialize(queue *q)
{
 q -> head = q -> tail = NULL;
 return;
}
3.2 Check if a queue is empty
int QueueEmpty(queue q)
{
 return (q.head == NULL);
}
3.3 Push function
Push function
void Push(queue *q, int x)
{
 queuenode p;
 p = (queuenode) malloc (sizeof(struct node));
 p -> item = x;
 p -> next = NULL;

 if ( q -> head == NULL)
 {
  q -> head = q -> tail = p;
 }
 else
 {
  q -> tail -> next = p;
  q -> tail = q -> tail -> next;
 }
 return;

}
3.4 Pop function



Pop function
int Pop(queue *q)
{
 queuenode p;
 if (QueueEmpty(*q))
 {
  printf("Queue is empty!\n");
  return 0;
 }
 else
 {
  p = q -> head;
  q -> head = q -> head -> next;
  return p -> item;
 }
}
3.5 Full code
You can download code here


Reference
http://www.nguyenvanquan7826.com/2014/12/30/lập-trình-c-bài-16-xây-dựng-hạng-đợi-queue/

Stack

1. Definition
A stack is a special type of list that removing or adding 1 element takes place at the top of bottom of list. In other way, stack is a data structure having two basic functions: push (adding one more element) and pop (getting and removing last element). Because of that features, stacks are called rule data structure LIFO (Last In First Out)

LIFO structure


2. Some examples of stack
A stack of books in a tale, a stack of CD in a box, ... When you add one book into the stack, the book will be in the top of the stack. When you get the book out of the stack, it will be put out first.

A stack of books

There are two general types of stack: a stack installed on an array (array stack), a stack installed on a linked list (linked list stack)

3. Stack installed on an array
An array stack is simple to install, but size is fixed so it is not flexible with a large amount of data
The structure of an array stack could be defined somethings like this:
#define MAX 100
typedef struct {
 int top;
 int data[MAX];
} stack;
3.1 Initial empty array, check if the array is empty or full
void StackInitial(stack *s) 
{
 s->top = -1;
 return;
}
int isStackEmpty(stack s)
{
 return (s.top == -1);
}
int isStackFull(stack s){
 return (s.top == MAX - 1);
}
3.2 Push function

Push funtion of a stack



void Push(stack *s, int x)
{
 if(isStackFull(*s))
 {
  printf("Stack is full!\n");
  return;
 }
 else
 {
  s->top++;
  s->data[s->top] = x;
  return;
 }
}
3.3 Pop function

Pop function of a stack


int Pop(stack *s)
{
 if(isStackEmpty(*s))
 {
  printf("Stack is empty\n");
  return;
 }
 else
 {
  return s->data[s->top--];
 }
}

3.4 Create a main function to test the stack type installed
int main()
{
 int a;

 // Creating stack and initialing
 stack *s = (stack *) malloc(sizeof(stack));
 StackInitial(s);
 printf("%d\n", isStackEmpty(*s));

 // Push and Pop
 Push(s, 10);
 Push(s, 20);
 Push(s, 50);

 a = Pop(s);
 printf("%d\n", a);
 a = Pop(s);
 printf("%d\n", a);
 
 return 0;
}
3.5 Full code You can download the full code here
Full code

4. Stack installed on a Linked List
Because an array stack has fixed size, so we need a type of stack that can be change, for some purposes, to avoid wasting memories or lacking of memories. We use linked list stack


A linked list stack Structure

struct node
{
 int data;
 struct node *next;
};
typedef struct node *stacknode;
typedef struct {
 stacknode top;
} stack;
4.1 Initial empty array, check if the array is empty
void StackInitial(stack *s)
{
 s->top = NULL;
 return;
}
int StackEmpty(stack s)
{
 return (s.top == NULL);
}
4.2 Push function


Push function of a linked list stack


void Push(stack *s, int x)
{
 stacknode p;
 p = (stacknode) malloc(sizeof(struct node));
 p->data = x;
 p->next = s->top;
 s->top = p;
 return;
}
4.3 Pop function


Pop function of a linked list stack


struct node
int Pop(stack *s)
{
 stacknode p;
 if (StackEmpty(*s))
 {
  printf("Stack is empty\n");
 }
 else
 {
  p = s->top;
  s->top = s->top->next;
  return p->data;
 }
}
4.4 Create a main function to test the stack type installed
int main()
{
 int a = 0;
 stack *s = (stack *) malloc(sizeof(stack));
 StackInitial(s);
 printf("%d\n", StackEmpty(*s));
 Push(s, 10);
 Push(s, 20);
 Push(s, 30);
 a = Pop(s);
 printf("%d\n", a);
 a = Pop(s);
 printf("%d\n", a);

 return 0;
}
4.5 Full code You can download the full code here
Full code

Reference:
http://www.nguyenvanquan7826.com/2014/12/29/lap-trinh-c-bai-15-cai-dat-ngan-xep-stack/
http://www.tutorialspoint.com/data_structures_algorithms/stack_program_in_c.htm
http://www.sanfoundry.com/c-programming-examples-stacks/