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

Reply via email to