Signed-off-by: Ben Pfaff <b...@nicira.com> --- lib/netdev-dummy.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- lib/pcap.c | 31 +++++++++++++++++++++++++------ 2 files changed, 70 insertions(+), 7 deletions(-)
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index a466358..4790492 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -31,9 +31,11 @@ #include "ofp-print.h" #include "ofpbuf.h" #include "packets.h" +#include "pcap.h" #include "poll-loop.h" #include "shash.h" #include "sset.h" +#include "timeval.h" #include "unixctl.h" #include "vlog.h" @@ -51,6 +53,8 @@ struct netdev_dev_dummy { struct pktgen **pktgens; size_t n_pktgens; + FILE *tx_pcap, *rx_pcap; + struct list devs; /* List of child "netdev_dummy"s. */ }; @@ -70,8 +74,10 @@ static bool pktgen_is_done(struct pktgen *); struct netdev_dummy { struct netdev netdev; struct list node; /* In netdev_dev_dummy's "devs" list. */ + struct list recv_queue; int recv_queue_len; /* list_size(&recv_queue). */ + bool listening; }; @@ -204,9 +210,13 @@ netdev_dummy_set_config(struct netdev_dev *netdev_dev_, const char *name = netdev_dev_get_name(netdev_dev_); const struct smap_node *node; const char *peer; + const char *pcap; SMAP_FOR_EACH (node, args) { - if (strcmp(node->key, "peer")) { + if (strcmp(node->key, "peer") + && strcmp(node->key, "pcap") + && strcmp(node->key, "rx_pcap") + && strcmp(node->key, "tx_pcap")) { VLOG_WARN("%s: unknown option '%s'", name, node->key); return EINVAL; } @@ -215,6 +225,29 @@ netdev_dummy_set_config(struct netdev_dev *netdev_dev_, free(netdev_dev->peer); peer = smap_get(args, "peer"); netdev_dev->peer = peer ? xstrdup(peer) : NULL; + + if (netdev_dev->rx_pcap) { + fclose(netdev_dev->rx_pcap); + } + if (netdev_dev->tx_pcap && netdev_dev->tx_pcap != netdev_dev->rx_pcap) { + fclose(netdev_dev->tx_pcap); + } + netdev_dev->rx_pcap = netdev_dev->tx_pcap = NULL; + pcap = smap_get(args, "pcap"); + if (pcap) { + netdev_dev->rx_pcap = netdev_dev->tx_pcap = pcap_open(pcap, "ab"); + } else { + const char *rx_pcap = smap_get(args, "rx_pcap"); + const char *tx_pcap = smap_get(args, "tx_pcap"); + + if (rx_pcap) { + netdev_dev->rx_pcap = pcap_open(rx_pcap, "ab"); + } + if (tx_pcap) { + netdev_dev->tx_pcap = pcap_open(tx_pcap, "ab"); + } + } + return 0; } @@ -328,6 +361,13 @@ netdev_dummy_send(struct netdev *netdev, const void *buffer, size_t size) dev->stats.tx_packets++; dev->stats.tx_bytes += size; + if (dev->tx_pcap) { + struct ofpbuf packet; + + ofpbuf_use_const(&packet, buffer, size); + pcap_write(dev->tx_pcap, &packet); + fflush(dev->tx_pcap); + } if (dev->peer) { struct netdev_dev_dummy *peer; @@ -575,6 +615,10 @@ netdev_dummy_queue_packet(struct netdev_dev_dummy *dummy_dev, dummy_dev->stats.rx_packets++; dummy_dev->stats.rx_bytes += packet->size; + if (dummy_dev->rx_pcap) { + pcap_write(dummy_dev->rx_pcap, packet); + fflush(dummy_dev->rx_pcap); + } prev = NULL; LIST_FOR_EACH (dev, node, &dummy_dev->devs) { if (dev->listening && dev->recv_queue_len < NETDEV_DUMMY_MAX_QUEUE) { diff --git a/lib/pcap.c b/lib/pcap.c index aa63be3..bb05212 100644 --- a/lib/pcap.c +++ b/lib/pcap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira, Inc. + * Copyright (c) 2009, 2010, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,9 @@ #include <assert.h> #include <errno.h> #include <inttypes.h> +#include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include "compiler.h" #include "ofpbuf.h" #include "vlog.h" @@ -48,24 +50,41 @@ BUILD_ASSERT_DECL(sizeof(struct pcaprec_hdr) == 16); FILE * pcap_open(const char *file_name, const char *mode) { + struct stat s; FILE *file; - assert(!strcmp(mode, "rb") || !strcmp(mode, "wb")); + assert(!strcmp(mode, "rb") || !strcmp(mode, "wb") || !strcmp(mode, "ab")); file = fopen(file_name, mode); if (file == NULL) { - VLOG_WARN("%s: failed to open pcap file for %s", - file_name, mode[0] == 'r' ? "reading" : "writing"); + VLOG_WARN("%s: failed to open pcap file for %s (%s)", file_name, + (mode[0] == 'r' ? "reading" + : mode[0] == 'w' ? "writing" + : "appending"), + strerror(errno)); return NULL; } - if (mode[0] == 'r') { + switch (mode[0]) { + case 'r': if (!pcap_read_header(file)) { fclose(file); return NULL; } - } else { + break; + + case 'w': pcap_write_header(file); + break; + + case 'a': + if (!fstat(fileno(file), &s) && !s.st_size) { + pcap_write_header(file); + } + break; + + default: + NOT_REACHED(); } return file; } -- 1.7.2.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev