The iproute patch is to big to send on the mailing list,
since the distribution data have changed the directory.
For ease of discussion I add the important changes in this mail.

signed-of-by: Ariane Keller <[EMAIL PROTECTED]

---

diff -uprN iproute2-2.6.23/netem/trace/flowseed.c iproute2-2.6.23_buf/netem/trace/flowseed.c --- iproute2-2.6.23/netem/trace/flowseed.c 1970-01-01 01:00:00.000000000 +0100 +++ iproute2-2.6.23_buf/netem/trace/flowseed.c 2007-12-12 08:43:01.000000000 +0100
@@ -0,0 +1,209 @@
+/* flowseed.c    flowseedprocess to deliver values for packet delay,
+ *               duplication, loss and curruption form userspace to netem
+ *
+ * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version
+ *               2 of the License, or (at your option) any later version.
+ *
+ *  Authors:     Ariane Keller <[EMAIL PROTECTED]> ETH Zurich
+ *               Rainer Baumann <[EMAIL PROTECTED]> ETH Zurich
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <signal.h>
+
+#include "utils.h"
+#include "linux/pkt_sched.h"
+
+#define DATA_PACKAGE 4000
+#define DATA_PACKAGE_ID DATA_PACKAGE + sizeof(unsigned int) + sizeof(int)
+#define TCA_BUF_MAX  (64*1024)
+/* maximal amount of parallel flows */
+struct rtnl_handle rth;
+unsigned int loop;
+int infinity = 0;
+int fdflowseed;
+char *sendpkg;
+int fid;
+int initialized = 0;
+int semid;
+int moreData = 1, r = 0, rold = 0;
+FILE * file;
+
+
+int printfct(const struct sockaddr_nl *who,
+                      struct nlmsghdr *n,
+                      void *arg)
+{
+       struct {
+               struct nlmsghdr         n;
+               struct tcmsg            t;
+               char                    buf[TCA_BUF_MAX];
+       } req;
+       struct tcmsg *t = NLMSG_DATA(n);
+       struct rtattr *tail = NULL;
+       struct tc_netem_qopt opt;
+       memset(&opt, 0, sizeof(opt));
+
+       if(n->nlmsg_type == RTM_DELQDISC) {
+               goto outerr;
+       }
+       else if(n->nlmsg_type == RTM_NEWQDISC){
+               initialized = 1;
+       
+               memset(&req, 0, sizeof(req));
+               req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
+               req.n.nlmsg_flags = NLM_F_REQUEST;
+               req.n.nlmsg_type = RTM_NEWQDISC;
+               req.t.tcm_family = AF_UNSPEC;
+               req.t.tcm_handle = t->tcm_handle;
+               req.t.tcm_parent = t->tcm_parent;
+               req.t.tcm_ifindex = t->tcm_ifindex;
+
+               tail = NLMSG_TAIL(&req.n);
+again:
+               if (loop <= 0 && !infinity){
+                       goto out;
+               }
+               if ((r = read(fdflowseed, sendpkg + rold, DATA_PACKAGE - rold)) 
>= 0) {
+                       if (r + rold < DATA_PACKAGE) {
+                       /* Tail of input file reached,
+                          set rest at start from next iteration */
+                               rold = r;
+                               fprintf(file, "flowseed: at end of file.\n");
+
+                               if (lseek(fdflowseed, 0L, SEEK_SET) < 0){
+                                       perror("lseek reset");
+                                       goto out;
+                               }
+                               goto again;
+                       }
+                       r = 0;
+                       rold = 0;
+                       memcpy(sendpkg + DATA_PACKAGE, &fid, sizeof(int));
+                       memcpy(sendpkg + DATA_PACKAGE + sizeof(int), &moreData, 
sizeof(int));
+               
+                       /* opt has to be added for each netem request */
+                       if (addattr_l(&req.n, TCA_BUF_MAX, TCA_OPTIONS, &opt, 
sizeof(opt)) < 0){
+                               perror("add options");
+                               return -1;
+                       }
+
+ if(addattr_l(&req.n, TCA_BUF_MAX, TCA_NETEM_TRACE_DATA, sendpkg, DATA_PACKAGE_ID) < 0){
+                               perror("add data\n");
+                               return -1;
+                       }
+
+                       tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void 
*)tail;
+
+                       if(rtnl_send(&rth, (char*)&req, req.n.nlmsg_len) < 0){
+                               perror("send data");
+                               return -1;
+                       }
+                       return 0;
+               }
+       }
+/* no more data, what to do? we send a notification to the kernel module */
+out:
+       fprintf(stderr, "flowseed: Tail of input file reached. Exit.\n");
+       fprintf(file, "flowseed: Tail of input file reached. Exit.\n");
+       moreData = 0;
+       memcpy(sendpkg + DATA_PACKAGE, &fid, sizeof(int));
+       memcpy(sendpkg + DATA_PACKAGE + sizeof(int), &moreData, sizeof(int));
+       if (addattr_l(&req.n, TCA_BUF_MAX, TCA_OPTIONS, &opt, sizeof(opt)) < 0){
+               perror("add options");
+               goto outerr;
+       }
+ if(addattr_l(&req.n, TCA_BUF_MAX, TCA_NETEM_TRACE_DATA, sendpkg, DATA_PACKAGE_ID) < 0){
+               perror("add data\n");
+               goto outerr;
+       }
+       
+       tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail;
+
+       if(rtnl_send(&rth, (char*)&req, req.n.nlmsg_len) < 0){
+               perror("rtnl_send");
+       }
+outerr:
+       fprintf(file, "flowseed: outerr Exit.\n");
+       fclose(file);
+       close(fdflowseed);
+       free(sendpkg);
+       rtnl_close(&rth);
+       exit(0);
+}
+
+void sigact(int signal){
+       if(initialized){
+               return;
+       }
+       else{
+               fprintf(stderr, "flowseed: not yet initialized. Exit\n");
+               exit(0);
+       }
+}
+int main(int argc, char *argv[])
+{
+       struct sembuf buf;
+        file = fopen("flowseedout.txt", "a+");
+       fprintf(file, "flowseed: initial msg.\n");
+
+       if (argc < 3) {
+               printf("usage: <tracefilename> <loop>");
+               return -1;
+       }
+       loop = strtoul(argv[2], NULL, 10);
+       if (loop == 0)
+               infinity = 1;
+
+       if ((fdflowseed = open(argv[1], O_RDONLY, 0)) < 0) {
+               perror("cannot open tracefile");
+               return -1;
+       }
+
+       fid = getpid();
+       sendpkg = malloc(DATA_PACKAGE_ID);
+
+       if (rtnl_open(&rth, 0) < 0) {
+               perror("Cannot open rtnetlink");
+               return -1;
+       }
+       ll_init_map(&rth);
+       /* we are ready to receive notifications */
+       if((semid = semget(0x12345678, 1, IPC_CREAT | 0666))<0){
+               perror("semget");
+               return -1;
+       }
+       buf.sem_num = 0;
+       buf.sem_op = +1;
+       buf.sem_flg = SEM_UNDO;
+       if(semop(semid, &buf, 1) < 0){
+               perror("semop");
+               return -1;
+       }
+       /* if the user typed an invalid command we cannot detect this
+        * therefore we set a timer, if the timer expires before we receive
+        * any message from the kernel module, we assume there was an
+        * error and quit.
+        */
+       signal(SIGALRM, sigact);
+       alarm(3);
+
+       /* listen to notifications from kernel */
+       if (rtnl_listen(&rth, printfct, NULL) < 0) {
+               perror("listen");
+               rtnl_close(&rth);
+               exit(2);
+       }
+       return 0;
+}


diff -uprN iproute2-2.6.23/tc/q_netem.c iproute2-2.6.23_buf/tc/q_netem.c
--- iproute2-2.6.23/tc/q_netem.c        2007-10-16 23:27:42.000000000 +0200
+++ iproute2-2.6.23_buf/tc/q_netem.c    2007-12-21 19:08:19.000000000 +0100
@@ -6,7 +6,12 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  *
+ *             README files:   iproute2/netem/distribution
+ *                             iproute2/netem/trace
+ *
  * Authors:    Stephen Hemminger <[EMAIL PROTECTED]>
+ *              netem trace: Ariane Keller <[EMAIL PROTECTED]> ETH Zurich
+ *                           Rainer Baumann <[EMAIL PROTECTED]> ETH Zurich
  *
  */

@@ -20,6 +25,9 @@
 #include <arpa/inet.h>
 #include <string.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>

 #include "utils.h"
 #include "tc_util.h"
@@ -34,7 +42,8 @@ static void explain(void)
 "                 [ drop PERCENT [CORRELATION]] \n" \
 "                 [ corrupt PERCENT [CORRELATION]] \n" \
 "                 [ duplicate PERCENT [CORRELATION]]\n" \
-"                 [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n");
+"                 [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n" \
+"                 [ trace PATH buf NR_BUFS loops NR_LOOPS [DEFAULT]\n");
 }

 static void explain1(const char *arg)
@@ -42,6 +51,7 @@ static void explain1(const char *arg)
        fprintf(stderr, "Illegal \"%s\"\n", arg);
 }

+#define FLOWPATH "/usr/local/bin/flowseed"
 #define usage() return(-1)

 /*
@@ -129,6 +139,7 @@ static int netem_parse_opt(struct qdisc_
        struct tc_netem_corr cor;
        struct tc_netem_reorder reorder;
        struct tc_netem_corrupt corrupt;
+       struct tc_netem_trace traceopt;
        __s16 *dist_data = NULL;
        int present[__TCA_NETEM_MAX];

@@ -137,8 +148,12 @@ static int netem_parse_opt(struct qdisc_
        memset(&cor, 0, sizeof(cor));
        memset(&reorder, 0, sizeof(reorder));
        memset(&corrupt, 0, sizeof(corrupt));
+       memset(&traceopt, 0, sizeof(traceopt));
        memset(present, 0, sizeof(present));
-
+       if (argc == 0) {
+               explain();
+               return -1;
+       }
        while (argc > 0) {
                if (matches(*argv, "limit") == 0) {
                        NEXT_ARG();
@@ -164,7 +179,7 @@ static int netem_parse_opt(struct qdisc_
                                if (NEXT_IS_NUMBER()) {
                                        NEXT_ARG();
                                        ++present[TCA_NETEM_CORR];
-                                       if (get_percent(&cor.delay_corr,        
                                            *argv)) {
+                                       if (get_percent(&cor.delay_corr, 
*argv)) {
                                                explain1("latency");
                                                return -1;
                                        }
@@ -243,6 +258,75 @@ static int netem_parse_opt(struct qdisc_
                } else if (strcmp(*argv, "help") == 0) {
                        explain();
                        return -1;
+               } else if (strcmp(*argv, "trace") == 0) {
+                       int fd;
+                       int execvl;
+                       char *filename;
+                       int pid;
+               
+                       /*get ticks correct since tracefile is in us,
+                        *and ticks may not be equal to us
+                        */
+                       get_ticks(&traceopt.ticks, "1000us");
+                       NEXT_ARG();
+                       filename = *argv;
+                       if ((fd = open(filename, O_RDONLY, 0)) < 0) {
+                               fprintf(stderr, "Cannot open trace file %s! 
\n", filename);
+                               return -1;
+                       }
+                       close(fd);
+                       NEXT_ARG();
+                       if(strcmp(*argv, "buf") == 0) {
+                               NEXT_ARG();
+                               traceopt.nr_bufs = atoi(*argv);
+                       }
+                       else{
+                               explain();
+                               return -1;
+                       }
+                       NEXT_ARG();
+                       if (strcmp(*argv, "loops") == 0 && NEXT_IS_NUMBER()) {
+                               NEXT_ARG();
+                               /*child will load tracefile to kernel */
+                               switch (pid = fork()) {
+                               case -1:{
+                                       fprintf(stderr,
+                                               "Cannot fork\n");
+                                       return -1;
+                                       }
+                               case 0:{
+                                       execvl = execl(FLOWPATH, "flowseed", 
filename, *argv, NULL);
+                                       if (execvl < 0) {
+                                               fprintf(stderr,
+                                               "starting child failed\n");
+                                               return -1;
+                                       }
+                                       }
+                               default:{
+                                       /* parent has to wait until child has 
done rtnl_open.
+                                        * otherwise the kernel module cannot 
send a notification
+                                        * to the child
+                                        */
+                                       int semid = semget(0x12345678, 1, 
IPC_CREAT | 0666);
+                                       struct sembuf buf;
+                                       buf.sem_num = 0;
+                                       buf.sem_op = -1;
+                                       buf.sem_flg = SEM_UNDO;
+                                       semop(semid, &buf, 1);
+                                       semctl(semid, 0, IPC_RMID);
+                                       }
+                               }
+                       }
+                       else {
+                               explain();
+                               return -1;
+                       }
+                       traceopt.def = 0;
+                       if (NEXT_IS_NUMBER()) {
+                               NEXT_ARG();
+                               traceopt.def = atoi(*argv);
+                       }
+                       traceopt.fid = pid;
                } else {
                        fprintf(stderr, "What is \"%s\"?\n", *argv);
                        explain();
@@ -291,7 +375,13 @@ static int netem_parse_opt(struct qdisc_
                              dist_data, dist_size*sizeof(dist_data[0])) < 0)
                        return -1;
        }
-       tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+       if (traceopt.fid) {
+               if (addattr_l(n, TCA_BUF_MAX, TCA_NETEM_TRACE, &traceopt,
+                    sizeof(traceopt)) < 0)
+                       return -1;
+       }
+
+       tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
        return 0;
 }

@@ -300,6 +390,8 @@ static int netem_print_opt(struct qdisc_
        const struct tc_netem_corr *cor = NULL;
        const struct tc_netem_reorder *reorder = NULL;
        const struct tc_netem_corrupt *corrupt = NULL;
+       const struct tc_netem_trace *traceopt = NULL;
+       const struct tc_netem_stats *tracestats = NULL;
        struct tc_netem_qopt qopt;
        int len = RTA_PAYLOAD(opt) - sizeof(qopt);
        SPRINT_BUF(b1);
@@ -333,9 +425,31 @@ static int netem_print_opt(struct qdisc_
                                return -1;
                        corrupt = RTA_DATA(tb[TCA_NETEM_CORRUPT]);
                }
+               if (tb[TCA_NETEM_TRACE]) {
+                       if (RTA_PAYLOAD(tb[TCA_NETEM_TRACE]) < 
sizeof(*traceopt))
+                               return -1;
+                       traceopt = RTA_DATA(tb[TCA_NETEM_TRACE]);
+               }
+               if (tb[TCA_NETEM_STATS]) {
+                       if (RTA_PAYLOAD(tb[TCA_NETEM_STATS]) < 
sizeof(*tracestats))
+                               return -1;
+                       tracestats = RTA_DATA(tb[TCA_NETEM_STATS]);
+               }
        }

        fprintf(f, "limit %d", qopt.limit);
+       if (traceopt && traceopt->fid) {
+               fprintf(f, " trace\n");
+
+               fprintf(f, "packetcount= %d\n", tracestats->packetcount);
+               fprintf(f, "packetok= %d\n", tracestats->packetok);
+               fprintf(f, "normaldelay= %d\n", tracestats->normaldelay);
+               fprintf(f, "drops= %d\n", tracestats->drops);
+               fprintf(f, "dupl= %d\n", tracestats->dupl);
+               fprintf(f, "corrupt= %d\n", tracestats->corrupt);
+               fprintf(f, "novaliddata= %d\n", tracestats->novaliddata);
+               fprintf(f, "bufferreload= %d\n", tracestats->reloadbuffer);
+               }

        if (qopt.latency) {
                fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1));

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to