Hi Everyone

I'm programming a little client-server application to test network performances 
with xenomai 2.3.1 and rtnet 0.9.9.
The 2 programs are based on the rtnet frag-ip example.
The perdiodic scenario is :
- RSG program sends a datagram to the REMOTE program which was waiting.
- REMOTE sends a response to RSG.
- RSG simulates a CPU performing period using rt_timer_spin.
This cycle should take less than 2.5ms.

I observe strange time measurement :

For example when I want to run during 10 secs : 1000 cycles of 10 ms
The program calculates a time between 16 and 17 secs (using rt_timer_tsc)
But the effective elapsed time (i kept time with a chrono :-s ) is around 10secs

When a cycle is supposed to be 5ms it is calculated to be 8.4ms

When I want a rt_timer_spin of 0.750ms, result is a 1.27ms burning period.

So a constant difference between effective and calculated time around +60%.

Maybe there something wrong in my program but I don't know what.
Also, I have read some threads that mentionned time problem and 
/proc/xenomai/latency value.
I didn't understand everything. 
Any suggestion ?


Thanks in advance.

Niry




RSG program

/**
 * \brief Prototype 01
 * Runs a task that :   - sends amount of data via UDP/IP to a remote box
 *                      - waits for data message during a specific time
 *                      - simulates a CPU calcul performing
 * Time is expressed in nanoseconds
 * \file rt_rsg.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <errno.h>
#include <native/task.h>
#include <native/timer.h>
#include <rtnet.h>

typedef unsigned long long uint64;
typedef unsigned long uint32;

/*                        --s--s--s */
/*                       s  m  u  n */
#define ONE_SEC          1000000000ULL
#define ONE_MILLI           1000000ULL
#define ONE_MICRO              1000ULL
#define CYCLE_RSG           2500000ULL      /* 2.5 ms */

#define ONE_KILO          1024


//#define CYCLE ONE_SEC

#define BUFF_SIZE   ONE_KILO + 512
#define PORT        37001

/** remote parameters */
char *dest_ip_s = "192.168.0.10";
struct sockaddr_in dest_addr;

/** communication parameters */
unsigned int data_size = BUFF_SIZE;
unsigned int nb_data = 1;
unsigned int add_rtskbs = 75;
unsigned int cpt, nb_cycles; 

/** time parameters */
uint64 start_time = 0;
uint64 **time_grid;
uint64 period = 5 * ONE_MILLI;
uint64 delay =10 * ONE_SEC;
uint64 recv_timeout = 20 * ONE_MILLI;
uint64 burn_time = 750 * ONE_MICRO;

RT_TASK rt_rsg_task;

FILE * fd;


int sock;

char buffer_out[BUFF_SIZE];
char buffer_in[BUFF_SIZE];


compute_time(int nb_values, char *file_name  )
{
        int i;
        uint64 xr_time, tot_time, burn_time;
        
        fd = fopen(file_name,"w+");
        if (fd == NULL){
                perror("Impossible d'ouvrir le fichier");
                exit(2);
        }
        
        fprintf(fd,"# Duree %llu\n# Repeat %d\n# StartTime %llu\n# \n",
                        delay, nb_values, start_time);
        fprintf(fd,"# Cycle AbsoluteTime XmitRecvTime TaskTime 
CPUBurningTime\n");
        
        /* Calcul des temps xmit - recv */
        for (i = 0; i < nb_values; i++) {
                xr_time = time_grid[i][1] - time_grid[i][0];
                tot_time = time_grid[i][2] - time_grid[i][0];
                burn_time = time_grid[i][2] - time_grid[i][1];
                fprintf(fd,"%d %llu %llu %llu %llu\n",i,
                                time_grid[i][0], xr_time, tot_time, burn_time);
                //fprintf(fd,"%d %llu %llu %llu\n",i, time_grid[i][0], 
time_grid[i][1], time_grid[i][2]);
        }

        fclose(fd);
        
        
}

int burn_cpu(uint64 time)
{
        rt_timer_spin(time);
}

int xmit_data()
{
        int ret, i;
        struct msghdr msg;
        struct iovec iov[3];
        unsigned short msgsize = data_size;
        unsigned short nbmsg = nb_data;
        
        for (i=0;i<nb_data;i++) {
                iov[0].iov_base = &msgsize;
                iov[0].iov_len  = sizeof(msgsize);
                iov[1].iov_base = buffer_out;
                iov[1].iov_len  = data_size;
                iov[2].iov_base = &nbmsg;
                iov[2].iov_len = sizeof(nbmsg);
                
                memset(&msg, 0, sizeof(msg));
                msg.msg_name    = &dest_addr; // ptr addresse socket
                msg.msg_namelen = sizeof(dest_addr); // longueur addresse socket
                msg.msg_iov     = iov; // tampon memoire vectoriel
                msg.msg_iovlen  = 3; // nb elements de msg_iov

                // printf("Sending message of %d+2 bytes\n", size);
                ret = rt_dev_sendmsg(sock, &msg, 0);
                if (ret == -EBADF)
                        return ret;
                else if (ret != (int)(sizeof(nbmsg) + sizeof(msgsize) + 
data_size)) {
                        printf("*** Error *** rt_dev_sendmsg() = %d : %s\n", 
ret, strerror(-ret));
                        return ret;
                } /*else {
                        printf("emit data OK\n");
                }*/
        }
        return 0;
}



int recv_data()
{
        int ret;
        struct msghdr msg;
        struct iovec iov[3];
        unsigned short msgsize = data_size;
        unsigned short nbmsg = nb_data;
        struct sockaddr_in addr;


        iov[0].iov_base = &msgsize;
        iov[0].iov_len  = sizeof(msgsize);
        iov[1].iov_base = buffer_in;
        iov[1].iov_len = data_size;
        iov[2].iov_base = &nbmsg;
        iov[2].iov_len  = sizeof(nbmsg);

        memset(&msg, 0, sizeof(msg));
        msg.msg_name    = &addr;
        msg.msg_namelen = sizeof(addr);
        msg.msg_iov     = iov;
        msg.msg_iovlen  = 2;

        ret = rt_dev_recvmsg(sock, &msg, 0);
        if (ret <= 0) {
                printf("Error rt_dev_recvmsg() = %d : %s\n", ret, 
strerror(-ret));
                return ret;
        } /*else {
                unsigned long ip = ntohl(addr.sin_addr.s_addr);
                printf("received data OK\n");
//              printf("received packet from %lu.%lu.%lu.%lu, length: %zd+2, "
//                              "encoded length: %d,\n flags: %X, content 
%s\n", ip >> 24,
//              (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF,
//              ret-sizeof(msgsize), msgsize, msg.msg_flags,
//              (memcmp(buffer_in, buffer_out, ret-sizeof(msgsize)) == 0) ?
//                              "ok" : "corrupted");
}*/
        return 0;
}



void catch_signal(int sig)
{
}

void perform_rsg(void *arg)
{
        int ret;
        
        if((ret = rt_task_set_periodic (NULL, TM_NOW, period))) {
                printf("ERROR : rt_task_set_periodic : %d\n", ret);
                return;
        }
        start_time = rt_timer_ticks2ns(rt_timer_tsc());
        while(1) {
                if(cpt<nb_cycles) {
                        time_grid[cpt][0] = rt_timer_ticks2ns(rt_timer_tsc());
                        if(!xmit_data()) {
                                if(!recv_data()) {
                                        time_grid[cpt][1] = 
rt_timer_ticks2ns(rt_timer_tsc());
                                        burn_cpu(burn_time);
                                }
                        }
                        time_grid[cpt][2] = rt_timer_ticks2ns(rt_timer_tsc());
                        cpt++;
                }
                if(cpt==nb_cycles) {
                        printf("No cycles remaining. Press ctl-c to quit.\n");
                        cpt++;
                }
                rt_task_wait_period(NULL);
        }
}

int main(int argc, char *argv[])
{
        int ret;
        unsigned int i;
        char *res_file_name = "res_tmp.txt";
        struct sockaddr_in local_addr;
        struct in_addr dest_ip;
        uint64 chrono[2];
        
        while (1) {
                switch (getopt(argc, argv, "d:f:")) {
                case 'd':
                        dest_ip_s = optarg;
                        break;
                
                case 'f':
                        res_file_name = optarg;
                        break;
                        
                case -1:
                        goto end_of_opt;

                default:
                        printf("usage: %s [-d <dest_ip>]\n", argv[0]);
                        return 0;
                }
        }
end_of_opt:

        inet_aton(dest_ip_s, &dest_ip);

        signal(SIGTERM, catch_signal);
        signal(SIGINT, catch_signal);
        signal(SIGHUP, catch_signal);
        mlockall(MCL_CURRENT|MCL_FUTURE);

        printf("*** Infos *** destination ip address %s=%08x\n", dest_ip_s, 
dest_ip.s_addr);
        printf("*** Debug *** size %d\n", data_size);

        /* fill output buffer with test pattern */
        for (i = 0; i < sizeof(buffer_out); i++)
                buffer_out[i] = i & 0xFF;

        printf("*** Debug *** CPU burning time : %llu\n",burn_time);
        
        cpt = 0;
        printf("*** Debug *** Total Duration : %llu\n",delay);
        printf("*** Debug *** Cycle Duration : %llu\n",period);
        nb_cycles = delay / period;
        printf("*** Debug *** Number of cycles : %lu\n",nb_cycles);
        time_grid = (uint64 **) malloc(sizeof(uint64 *) * nb_cycles);
        for(i = 0; i < nb_cycles; i++)
                time_grid[i] = (uint64 *) calloc(3, sizeof(uint64));
        
        /* create rt-socket */
        sock = rt_dev_socket(AF_INET,SOCK_DGRAM,0);
        if (sock < 0) {
                printf("*** Error *** rt_dev_socket() = %d!\n", sock);
                return sock;
        } else {
                printf("*** Debug *** Creating socket OK\n");
        }
        
        /* extend the socket pool */
        ret = rt_dev_ioctl(sock, RTNET_RTIOC_EXTPOOL, &add_rtskbs);
        if (ret != (int)add_rtskbs) {
                printf("*** Error *** rt_dev_ioctl(RT_IOC_SO_EXTPOOL) = %d\n", 
ret);
                rt_dev_close(sock);
                return -1;
        } else {
                printf("*** Debug *** Extending socket pool OK\n");
        }
        
        /* reception acquitement bloquant + timeout */
        ret = rt_dev_ioctl(sock, RTNET_RTIOC_TIMEOUT, &recv_timeout);
        if (ret != 0) {
                printf("*** Error *** rt_dev_ioctl(RT_IOC_TIME_OUT) = %d\n", 
ret);
                rt_dev_close(sock);
                return -1;
        } else {
                printf("*** Debug *** Setting receive timeout OK\n");
        }

        /* bind the rt-socket to a port */
        memset(&local_addr, 0, sizeof(struct sockaddr_in));
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(PORT);
        local_addr.sin_addr.s_addr = INADDR_ANY;
        ret = rt_dev_bind(sock, (struct sockaddr *)&local_addr,
                          sizeof(struct sockaddr_in));
        if (ret < 0) {
                printf("*** Error ***  rt_dev_bind() = %d!\n", ret);
                rt_dev_close(sock);
                return ret;
        } else {
                printf("*** Debug *** Binding socket OK\n");
        }

        /* set destination address */
        memset(&dest_addr, 0, sizeof(struct sockaddr_in));
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(PORT);
        dest_addr.sin_addr = dest_ip;

        ret = rt_task_create(&rt_rsg_task, "RSG", 0, 10, 0);
        if (ret != 0) {
                printf("*** Error ***  rt_task_create(recv) = %d!\n", ret);
                rt_dev_close(sock);
                return ret;
        }

        rt_task_start(&rt_rsg_task, perform_rsg, NULL);

        pause();
                
        /* Note: The following loop and the strict ordering "close before task
         * termination" is no longer required since Xenomai 2.4. */
        while (rt_dev_close(sock) == -EAGAIN) {
                printf("*** Debug *** Socket busy - waiting...\n");
                sleep(1);
        }

        if(ret = rt_task_delete(&rt_rsg_task)) {
                printf("*** Error ***  rt_task_delete() = %d!\n", ret);
        } else {
                printf("*** Debug *** Deleting task OK\n");
        }
        
        compute_time(nb_cycles, res_file_name);
        
        return 0;
}




REMOTE program

/**
 * \brief Prototype 01
 * Runs a task that :   - waits for amount of data via UDP/IP from a remote box
 *                              - sends data message
 * Time is expressed in nanoseconds
 * \file rt_remote.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <errno.h>
#include <native/task.h>
#include <native/timer.h>
#include <rtnet.h>

typedef unsigned long long uint64;
typedef unsigned long uint32;

/*                        --s--s--s */
/*                       s  m  u  n */
#define ONE_SEC          1000000000ull
#define ONE_MILLI           1000000ull
#define ONE_MICRO              1000ull


#define ONE_KILO          1024

//#define CYCLE           2.5 * ONE_MILLI  /* 2.5 ms */
#define CYCLE           ONE_SEC

#define BUFF_SIZE   ONE_KILO + 512
#define PORT        37001

/** remote parameters */
char *dest_ip_s = "192.168.0.1";
struct sockaddr_in dest_addr;

/** communication parameters */
unsigned int data_size = BUFF_SIZE;
unsigned int nb_data = 1;
unsigned int add_rtskbs = 75;

/** time parameters */
uint64 start_time;
uint64 *time_grid;
uint64 recv_timeout = CYCLE;

RT_TASK rt_rsg_task;




int sock;

char buffer_out[BUFF_SIZE];
char buffer_in[BUFF_SIZE];

int xmit_data()
{
        int ret, i;
        struct msghdr msg;
        struct iovec iov[3];
        unsigned short msgsize = data_size;
        unsigned short nbmsg = nb_data;
        

        iov[0].iov_base = &msgsize;
        iov[0].iov_len  = sizeof(msgsize);
        iov[1].iov_base = buffer_out;
        iov[1].iov_len  = data_size;
        iov[2].iov_base = &nbmsg;
        iov[2].iov_len = sizeof(nbmsg);
        
        memset(&msg, 0, sizeof(msg));
        msg.msg_name    = &dest_addr; // ptr addresse socket
        msg.msg_namelen = sizeof(dest_addr); // longueur addresse socket
        msg.msg_iov     = iov; // tampon memoire vectoriel
        msg.msg_iovlen  = 3; // nb elements de msg_iov

        // printf("Sending message of %d+2 bytes\n", size);
        ret = rt_dev_sendmsg(sock, &msg, 0);
        if (ret == -EBADF)
                return ret;
        else if (ret != (int)(sizeof(nbmsg) + sizeof(msgsize) + data_size)) {
                printf("*** Error *** rt_dev_sendmsg() = %d : %s\n", 
                                ret, strerror(-ret));
                return ret;
        }/* else {
                printf("*** Debug ***data emit ok\n");
        }*/
        return 0;
}



int recv_data()
{
        int ret,i;
        struct msghdr msg;
        struct iovec iov[3];
        unsigned short msgsize = data_size;
        unsigned short nbmsg = nb_data;
        struct sockaddr_in addr;

        for (i=0;i<nb_data;i++) {
                iov[0].iov_base = &msgsize;
                iov[0].iov_len  = sizeof(msgsize);
                iov[1].iov_base = buffer_in;
                iov[1].iov_len = data_size;
                iov[2].iov_base = &nbmsg;
                iov[2].iov_len  = sizeof(nbmsg);

                memset(&msg, 0, sizeof(msg));
                msg.msg_name    = &addr;
                msg.msg_namelen = sizeof(addr);
                msg.msg_iov     = iov;
                msg.msg_iovlen  = 3;

                ret = rt_dev_recvmsg(sock, &msg, 0);
                if (ret <= 0) {
                        printf("*** Error *** rt_dev_recvmsg() = %d : %s\n",
                                         ret, strerror(-ret));
                        return ret;
                } /*else {
                        unsigned long ip = ntohl(addr.sin_addr.s_addr);
                        printf("receive data OK\n");
//              printf("received packet from %lu.%lu.%lu.%lu, length: %zd+2, "
//                              "encoded length: %d,\n flags: %X, content 
%s\n", ip >> 24,
//              (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF,
//              ret-sizeof(msgsize), msgsize, msg.msg_flags,
//              (memcmp(buffer_in, buffer_out, ret-sizeof(msgsize)) == 0) ?
//                              "ok" : "corrupted");
                }*/
        }
        return 0;
}



void catch_signal(int sig)
{
        //rt_task_suspend(&rt_rsg_task);
}

void perform_remote(void *arg)
{
        unsigned int i = 0;
        while(1) {
                //printf("\nPass %d",i++);
                if(recv_data()) continue;
                if(xmit_data()) continue;
        }
}

int main(int argc, char *argv[])
{
        int ret;
        unsigned int i;
        struct sockaddr_in local_addr;
        struct in_addr dest_ip;


        while (1) {
                switch (getopt(argc, argv, "d:")) {
                case 'd':
                        dest_ip_s = optarg;
                        break;

                case -1:
                        goto end_of_opt;

                default:
                        printf("usage: %s [-d <dest_ip>]\n", argv[0]);
                        return 0;
                }
        }
end_of_opt:

        inet_aton(dest_ip_s, &dest_ip);

        signal(SIGTERM, catch_signal);
        signal(SIGINT, catch_signal);
        signal(SIGHUP, catch_signal);
        mlockall(MCL_CURRENT|MCL_FUTURE);

        printf("destination ip address %s=%08x\n", dest_ip_s, dest_ip.s_addr);
        printf("size %d\n", data_size);

        /* fill output buffer with test pattern */
        for (i = 0; i < sizeof(buffer_out); i++)
                buffer_out[i] = i & 0xFF;

        /* create rt-socket */
        sock = rt_dev_socket(AF_INET,SOCK_DGRAM,0);
        if (sock < 0) {
                printf("*** Error *** rt_dev_socket() = %d!\n", sock);
                return sock;
        }

        /* extend the socket pool */
        ret = rt_dev_ioctl(sock, RTNET_RTIOC_EXTPOOL, &add_rtskbs);
        if (ret != (int)add_rtskbs) {
                printf("*** Error *** rt_dev_ioctl(RT_IOC_SO_EXTPOOL) = %d\n", 
ret);
                rt_dev_close(sock);
                return -1;
        }
        
//      /* reception acquitement bloquant + timeout */
//      ret = rt_dev_ioctl(sock, RTNET_RTIOC_TIMEOUT, &recv_timeout);
//      if (ret != 0) {
//              printf("Error rt_dev_ioctl(RT_IOC_TIME_OUT) = %d\n", ret);
//              rt_dev_close(sock);
//              return -1;
//      }

        /* bind the rt-socket to a port */
        memset(&local_addr, 0, sizeof(struct sockaddr_in));
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(PORT);
        local_addr.sin_addr.s_addr = INADDR_ANY;
        ret = rt_dev_bind(sock, (struct sockaddr *)&local_addr,
                          sizeof(struct sockaddr_in));
        if (ret < 0) {
                printf("*** Error *** rt_dev_bind() = %d!\n", ret);
                rt_dev_close(sock);
                return ret;
        }

        /* set destination address */
        memset(&dest_addr, 0, sizeof(struct sockaddr_in));
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(PORT);
        dest_addr.sin_addr = dest_ip;

        ret = rt_task_create(&rt_rsg_task, "REMOTE", 0, 10, 0);
        if (ret != 0) {
                printf(" rt_task_create(recv) = %d!\n", ret);
                rt_dev_close(sock);
                return ret;
        }

        rt_task_start(&rt_rsg_task, perform_remote, NULL);

        pause();


        /* Note: The following loop and the strict ordering "close before task
         * termination" is no longer required since Xenomai 2.4. */
        while (rt_dev_close(sock) == -EAGAIN) {
                printf("Socket busy - waiting...\n");
                sleep(1);
        }

        rt_task_delete(&rt_rsg_task);

        return 0;
}









This e-mail is intended only for the above addressee. It may contain privileged 
information.
If you are not the addressee you must not copy, distribute, disclose or use any 
of the information in it. 
If you have received it in error please delete it and immediately notify the 
sender.
Security Notice: all e-mail, sent to or from this address, may be accessed by 
someone other than the recipient, for system management and security reasons. 
This access is controlled under Regulation of security reasons.
This access is controlled under Regulation of Investigatory Powers Act 2000, 
Lawful Business Practises.



-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
RTnet-users mailing list
RTnet-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rtnet-users

Reply via email to