Signed-off-by: Ben Pfaff <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev