* [uml-devel] [PATCH] uml_switch: configurable network delay
@ 2010-11-25 17:36 Morten Hustveit
2010-11-26 17:49 ` Renzo Davoli
2010-12-02 8:55 ` [uml-devel] [PATCH v2] " Morten Hustveit
0 siblings, 2 replies; 4+ messages in thread
From: Morten Hustveit @ 2010-11-25 17:36 UTC (permalink / raw)
To: user-mode-linux-devel
Add the "-delay" option to configure network delay in milliseconds
When using UML to test networking code, it would be helpful if the
switch daemon could provide configurable delay, in order to simulate
ordinary network delay. This patch provides that feature by storing
scheduled packets in a linked list, and using the poll() timeout
parameter to pop items from the list at the appropriate time.
Presently, the size of the backlog is unbounded, but I think this is
acceptable for a testing/debugging feature.
PS: I could not find a public SCM with the most recent development
version of the utilities.
---
diff -ur tools-20070815/uml_switch/port.c tools-20070815.my/uml_switch/port.c
--- tools-20070815/uml_switch/port.c 2006-02-27 22:02:45.000000000 +0100
+++ tools-20070815.my/uml_switch/port.c 2010-11-25 18:32:20.597950521 +0100
@@ -8,6 +8,8 @@
#include "hash.h"
#include "port.h"
+typedef void (*sender_t)(int fd, void *packet, int len, void *data);
+
struct packet {
struct {
unsigned char dest[ETH_ALEN];
@@ -24,15 +26,57 @@
void *data;
int data_len;
unsigned char src[ETH_ALEN];
- void (*sender)(int fd, void *packet, int len, void *data);
+ sender_t sender;
};
static struct port *head = NULL;
+struct queued_packet {
+ struct queued_packet *next;
+
+ struct timeval delivery_time;
+
+ sender_t sender;
+ void *data;
+
+ int fd;
+ int len;
+ struct sockaddr_un sock;
+
+ char packet[1];
+};
+
+static struct queued_packet *first_packet = NULL;
+static struct queued_packet *last_packet = NULL;
+
+extern int simulated_delay;
+
#define IS_BROADCAST(addr) ((addr[0] & 1) == 1)
static void free_port(struct port *port)
{
+ struct queued_packet *qp, *prev = 0, *next;
+
+ /* Remove queued packets belonging to `port' */
+ qp = first_packet;
+
+ while (qp) {
+ if (qp->fd == port->control) {
+ next = qp->next;
+ if (prev)
+ prev->next = next;
+ else
+ first_packet = next;
+ free (qp);
+ qp = next;
+ } else {
+ prev = qp;
+ qp = qp->next;
+ }
+ }
+
+ last_packet = prev;
+
if(port->prev) port->prev->next = port->next;
else head = port->next;
if(port->next) port->next->prev = port->prev;
@@ -83,6 +127,76 @@
update_entry_time(p->header.src);
}
+static void send_dst_packet(sender_t sender, int fd, void *packet, int len, void *data)
+{
+ struct queued_packet *qp;
+ if (!simulated_delay) {
+ sender(fd, data, len, data);
+ } else {
+ qp = malloc(sizeof(*qp) - sizeof(qp->packet) + len);
+
+ if(qp == NULL) {
+ perror("malloc");
+ return;
+ }
+
+ qp->next = 0;
+
+ gettimeofday(&qp->delivery_time, 0);
+
+ qp->delivery_time.tv_usec += simulated_delay * 1000;
+
+ if (qp->delivery_time.tv_usec > 1000000) {
+ qp->delivery_time.tv_sec += qp->delivery_time.tv_usec / 1000000;
+ qp->delivery_time.tv_usec %= 1000000;
+ }
+
+ qp->sender = sender;
+ qp->data = data;
+
+ qp->fd = fd;
+ qp->len = len;
+ memcpy(qp->packet, packet, len);
+
+ if (!first_packet)
+ first_packet = qp;
+ else
+ last_packet->next = qp;
+
+ last_packet = qp;
+ }
+}
+
+void process_queued_packets()
+{
+ struct queued_packet *qp;
+ struct timeval now;
+ int err;
+
+ if (!first_packet)
+ return;
+
+ gettimeofday(&now, 0);
+
+ while (first_packet)
+ {
+ if (first_packet->delivery_time.tv_sec > now.tv_sec
+ || (first_packet->delivery_time.tv_sec == now.tv_sec
+ && first_packet->delivery_time.tv_usec > now.tv_usec))
+ break;
+
+ qp = first_packet;
+
+ if (qp == last_packet)
+ last_packet = 0;
+ first_packet = qp->next;
+
+ (*qp->sender)(qp->fd, qp->packet, qp->len, qp->data);
+
+ free(qp);
+ }
+}
+
static void send_dst(struct port *port, struct packet *packet, int len,
int hub)
{
@@ -104,10 +218,11 @@
/* don't send it back the port it came in */
if(p == port) continue;
- (*p->sender)(p->control, packet, len, p->data);
+ send_dst_packet(p->sender, p->control, packet, len, p->data);
}
}
- else (*target->sender)(target->control, packet, len, target->data);
+ else
+ send_dst_packet(target->sender, target->control, packet, len, target->data);
}
static void handle_data(int fd, int hub, struct packet *packet, int len,
@@ -148,8 +263,7 @@
handle_data(fd, hub, &packet, len, NULL, match_tap);
}
-int setup_port(int fd, void (*sender)(int fd, void *packet, int len,
- void *data), void *data, int data_len)
+int setup_port(int fd, sender_t sender)
{
struct port *port;
@@ -188,6 +302,25 @@
}
}
+int next_queued_packet()
+{
+ struct timeval now;
+ int result = -1;
+
+ if (first_packet)
+ {
+ gettimeofday(&now, 0);
+
+ result = (first_packet->delivery_time.tv_sec - now.tv_sec) * 1000
+ + (first_packet->delivery_time.tv_usec - now.tv_usec) / 1000;
+
+ if (result < 0)
+ result = 0;
+ }
+
+ return result;
+}
+
static int match_sock(int port_fd, int data_fd, void *port_data,
int port_data_len, void *data)
{
diff -ur tools-20070815/uml_switch/port.h tools-20070815.my/uml_switch/port.h
--- tools-20070815/uml_switch/port.h 2002-04-10 15:07:02.000000000 +0200
+++ tools-20070815.my/uml_switch/port.h 2010-11-25 18:15:51.557625929 +0100
@@ -16,5 +16,7 @@
int data_len);
extern void handle_tap_data(int fd, int hub);
extern void handle_sock_data(int fd, int hub);
+extern int next_queued_packet();
+extern void process_queued_packets();
#endif
diff -ur tools-20070815/uml_switch/uml_switch.c tools-20070815.my/uml_switch/uml_switch.c
--- tools-20070815/uml_switch/uml_switch.c 2006-02-27 22:02:36.000000000 +0100
+++ tools-20070815.my/uml_switch/uml_switch.c 2010-11-25 18:15:51.545961139 +0100
@@ -26,6 +26,7 @@
static int hub = 0;
static int compat_v0 = 0;
+int simulated_delay = 0;
enum request_type { REQ_NEW_CONTROL };
@@ -392,9 +393,10 @@
tap_str = "[ -tap tap-device ]";
#endif
- fprintf(stderr, "Usage : %s [ -unix control-socket ] [ -hub ] %s\n"
+ fprintf(stderr, "Usage : %s [ -unix control-socket ] [ -hub ] "
+ "[ -delay ms ] %s\n"
"or : %s -compat-v0 [ -unix control-socket data-socket ] "
- "[ -hub ] %s\n", prog, tap_str, prog, tap_str);
+ "[ -hub ] [ -delay ms ] %s\n", prog, tap_str, prog, tap_str);
exit(1);
}
@@ -455,6 +457,13 @@
argc--;
argv++;
}
+ else if(!strcmp(argv[0], "-delay")){
+ if(argc < 2)
+ Usage();
+ simulated_delay = atoi(argv[1]);
+ argv += 2;
+ argc -= 2;
+ }
else Usage();
}
@@ -521,7 +530,7 @@
while(1){
char buf[128];
- n = poll(fds, nfds, -1);
+ n = poll(fds, nfds, next_queued_packet());
if(n < 0){
if(errno == EINTR) continue;
perror("poll");
@@ -562,6 +571,8 @@
else close_descriptor(fds[i].fd);
}
}
+
+ process_queued_packets();
}
out:
cleanup();
------------------------------------------------------------------------------
Increase Visibility of Your 3D Game App & Earn a Chance To Win $500!
Tap into the largest installed PC base & get more eyes on your game by
optimizing for Intel(R) Graphics Technology. Get started today with the
Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs.
http://p.sf.net/sfu/intelisp-dev2dev
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [uml-devel] [PATCH] uml_switch: configurable network delay 2010-11-25 17:36 [uml-devel] [PATCH] uml_switch: configurable network delay Morten Hustveit @ 2010-11-26 17:49 ` Renzo Davoli 2010-11-27 12:04 ` Morten Hustveit 2010-12-02 8:55 ` [uml-devel] [PATCH v2] " Morten Hustveit 1 sibling, 1 reply; 4+ messages in thread From: Renzo Davoli @ 2010-11-26 17:49 UTC (permalink / raw) To: Morten Hustveit; +Cc: user-mode-linux-devel On Thu, Nov 25, 2010 at 06:36:49PM +0100, Morten Hustveit wrote: > Add the "-delay" option to configure network delay in milliseconds If you use vde instead of uml_switch, vde provides wirefilter which implements packet delay as well as several other networking testing features: packet loss packet dup bandwidth limit interface speed channel capacity channel noise fifoness errors renzo ------------------------------------------------------------------------------ Increase Visibility of Your 3D Game App & Earn a Chance To Win $500! Tap into the largest installed PC base & get more eyes on your game by optimizing for Intel(R) Graphics Technology. Get started today with the Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs. http://p.sf.net/sfu/intelisp-dev2dev _______________________________________________ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [uml-devel] [PATCH] uml_switch: configurable network delay 2010-11-26 17:49 ` Renzo Davoli @ 2010-11-27 12:04 ` Morten Hustveit 0 siblings, 0 replies; 4+ messages in thread From: Morten Hustveit @ 2010-11-27 12:04 UTC (permalink / raw) To: user-mode-linux-devel On Thu, Nov 25, 2010 at 06:36:49PM +0100, Morten Hustveit wrote: > > Add the "-delay" option to configure network delay in milliseconds On Fri, Nov 26, 2010 at 06:49:26PM +0100, Renzo Davoli wrote: > If you use vde instead of uml_switch, vde provides wirefilter > which implements packet delay as well as several other networking testing features: That looks nice, but I couldn't understand how to use it. It seemed to me that to do something like uml_switch -delay 100 with vde, you would need to write several long command lines and perhaps a configuration file. I understand this is not a problem for most people, but I would like to have a simple way of doing things as well. I'm hoping to contribute other similarly simple testing features to uml_switch, but first I need to know whether such changes are welcome. ------------------------------------------------------------------------------ Increase Visibility of Your 3D Game App & Earn a Chance To Win $500! Tap into the largest installed PC base & get more eyes on your game by optimizing for Intel(R) Graphics Technology. Get started today with the Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs. http://p.sf.net/sfu/intelisp-dev2dev _______________________________________________ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel ^ permalink raw reply [flat|nested] 4+ messages in thread
* [uml-devel] [PATCH v2] uml_switch: configurable network delay 2010-11-25 17:36 [uml-devel] [PATCH] uml_switch: configurable network delay Morten Hustveit 2010-11-26 17:49 ` Renzo Davoli @ 2010-12-02 8:55 ` Morten Hustveit 1 sibling, 0 replies; 4+ messages in thread From: Morten Hustveit @ 2010-12-02 8:55 UTC (permalink / raw) To: user-mode-linux-devel Add the "-delay" option to configure network delay in milliseconds When using UML to test networking code, it would be helpful if the switch daemon could provide configurable delay, in order to simulate ordinary network delay. This patch provides that feature by storing scheduled packets in a linked list, and using the poll() timeout parameter to pop items from the list at the appropriate time. The size of the backlog is unbounded, but I think this is acceptable for a testing/debugging feature. --- Changes for v2: - The previous version was incorrectly submitted, and didn't even compile. Apologies to anyone who tried to use it. diff -ur tools-20070815/uml_switch/port.c tools-20070815.mortehu/uml_switch/port.c --- tools-20070815/uml_switch/port.c 2006-02-27 22:02:45.000000000 +0100 +++ tools-20070815.mortehu/uml_switch/port.c 2010-12-01 18:14:03.033429453 +0100 @@ -24,15 +24,57 @@ void *data; int data_len; unsigned char src[ETH_ALEN]; - void (*sender)(int fd, void *packet, int len, void *data); + sender_t sender; }; static struct port *head = NULL; +struct queued_packet { + struct queued_packet *next; + + struct timeval delivery_time; + + sender_t sender; + void *data; + + int fd; + int len; + struct sockaddr_un sock; + + char packet[1]; +}; + +static struct queued_packet *first_packet = NULL; +static struct queued_packet *last_packet = NULL; + +extern int simulated_delay; + #define IS_BROADCAST(addr) ((addr[0] & 1) == 1) static void free_port(struct port *port) { + struct queued_packet *qp, *prev = 0, *next; + + /* Remove queued packets belonging to `port' */ + qp = first_packet; + + while (qp) { + if (qp->fd == port->control) { + next = qp->next; + if (prev) + prev->next = next; + else + first_packet = next; + free (qp); + qp = next; + } else { + prev = qp; + qp = qp->next; + } + } + + last_packet = prev; + if(port->prev) port->prev->next = port->next; else head = port->next; if(port->next) port->next->prev = port->prev; @@ -83,6 +125,76 @@ update_entry_time(p->header.src); } +static void send_dst_packet(sender_t sender, int fd, void *packet, int len, void *data) +{ + struct queued_packet *qp; + if (!simulated_delay) { + sender(fd, packet, len, data); + } else { + qp = malloc(sizeof(*qp) - sizeof(qp->packet) + len); + + if(qp == NULL) { + perror("malloc"); + return; + } + + qp->next = 0; + + gettimeofday(&qp->delivery_time, 0); + + qp->delivery_time.tv_usec += simulated_delay * 1000; + + if (qp->delivery_time.tv_usec > 1000000) { + qp->delivery_time.tv_sec += qp->delivery_time.tv_usec / 1000000; + qp->delivery_time.tv_usec %= 1000000; + } + + qp->sender = sender; + qp->data = data; + + qp->fd = fd; + qp->len = len; + memcpy(qp->packet, packet, len); + + if (!first_packet) + first_packet = qp; + else + last_packet->next = qp; + + last_packet = qp; + } +} + +void process_queued_packets() +{ + struct queued_packet *qp; + struct timeval now; + int err; + + if (!first_packet) + return; + + gettimeofday(&now, 0); + + while (first_packet) + { + if (first_packet->delivery_time.tv_sec > now.tv_sec + || (first_packet->delivery_time.tv_sec == now.tv_sec + && first_packet->delivery_time.tv_usec > now.tv_usec)) + break; + + qp = first_packet; + + if (qp == last_packet) + last_packet = 0; + first_packet = qp->next; + + (*qp->sender)(qp->fd, qp->packet, qp->len, qp->data); + + free(qp); + } +} + static void send_dst(struct port *port, struct packet *packet, int len, int hub) { @@ -104,10 +216,11 @@ /* don't send it back the port it came in */ if(p == port) continue; - (*p->sender)(p->control, packet, len, p->data); + send_dst_packet(p->sender, p->control, packet, len, p->data); } } - else (*target->sender)(target->control, packet, len, target->data); + else + send_dst_packet(target->sender, target->control, packet, len, target->data); } static void handle_data(int fd, int hub, struct packet *packet, int len, @@ -148,8 +261,7 @@ handle_data(fd, hub, &packet, len, NULL, match_tap); } -int setup_port(int fd, void (*sender)(int fd, void *packet, int len, - void *data), void *data, int data_len) +int setup_port(int fd, sender_t sender, void *data, int data_len) { struct port *port; @@ -188,6 +300,25 @@ } } +int next_queued_packet() +{ + struct timeval now; + int result = -1; + + if (first_packet) + { + gettimeofday(&now, 0); + + result = (first_packet->delivery_time.tv_sec - now.tv_sec) * 1000 + + (first_packet->delivery_time.tv_usec - now.tv_usec) / 1000; + + if (result < 0) + result = 0; + } + + return result; +} + static int match_sock(int port_fd, int data_fd, void *port_data, int port_data_len, void *data) { diff -ur tools-20070815/uml_switch/port.h tools-20070815.mortehu/uml_switch/port.h --- tools-20070815/uml_switch/port.h 2002-04-10 15:07:02.000000000 +0200 +++ tools-20070815.mortehu/uml_switch/port.h 2010-12-01 17:59:04.817923444 +0100 @@ -8,13 +8,15 @@ #include <sys/socket.h> #include <sys/un.h> +typedef void (*sender_t)(int fd, void *packet, int len, void *data); + extern int handle_port(int fd); extern void close_port(int fd); extern int setup_sock_port(int fd, struct sockaddr_un *name, int data_fd); -extern int setup_port(int fd, void (*sender)(int fd, void *packet, int len, - void *data), void *data, - int data_len); +extern int setup_port(int fd, sender_t sender, void *data, int data_len); extern void handle_tap_data(int fd, int hub); extern void handle_sock_data(int fd, int hub); +extern int next_queued_packet(); +extern void process_queued_packets(); #endif diff -ur tools-20070815/uml_switch/uml_switch.c tools-20070815.mortehu/uml_switch/uml_switch.c --- tools-20070815/uml_switch/uml_switch.c 2006-02-27 22:02:36.000000000 +0100 +++ tools-20070815.mortehu/uml_switch/uml_switch.c 2010-11-25 18:15:51.545961139 +0100 @@ -26,6 +26,7 @@ static int hub = 0; static int compat_v0 = 0; +int simulated_delay = 0; enum request_type { REQ_NEW_CONTROL }; @@ -392,9 +393,10 @@ tap_str = "[ -tap tap-device ]"; #endif - fprintf(stderr, "Usage : %s [ -unix control-socket ] [ -hub ] %s\n" + fprintf(stderr, "Usage : %s [ -unix control-socket ] [ -hub ] " + "[ -delay ms ] %s\n" "or : %s -compat-v0 [ -unix control-socket data-socket ] " - "[ -hub ] %s\n", prog, tap_str, prog, tap_str); + "[ -hub ] [ -delay ms ] %s\n", prog, tap_str, prog, tap_str); exit(1); } @@ -455,6 +457,13 @@ argc--; argv++; } + else if(!strcmp(argv[0], "-delay")){ + if(argc < 2) + Usage(); + simulated_delay = atoi(argv[1]); + argv += 2; + argc -= 2; + } else Usage(); } @@ -521,7 +530,7 @@ while(1){ char buf[128]; - n = poll(fds, nfds, -1); + n = poll(fds, nfds, next_queued_packet()); if(n < 0){ if(errno == EINTR) continue; perror("poll"); @@ -562,6 +571,8 @@ else close_descriptor(fds[i].fd); } } + + process_queued_packets(); } out: cleanup(); ------------------------------------------------------------------------------ Increase Visibility of Your 3D Game App & Earn a Chance To Win $500! Tap into the largest installed PC base & get more eyes on your game by optimizing for Intel(R) Graphics Technology. Get started today with the Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs. http://p.sf.net/sfu/intelisp-dev2dev _______________________________________________ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-12-02 8:55 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-11-25 17:36 [uml-devel] [PATCH] uml_switch: configurable network delay Morten Hustveit 2010-11-26 17:49 ` Renzo Davoli 2010-11-27 12:04 ` Morten Hustveit 2010-12-02 8:55 ` [uml-devel] [PATCH v2] " Morten Hustveit
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.