aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2010-02-24 13:47:09 -0800
committerBen Pfaff <blp@nicira.com>2010-02-24 13:47:09 -0800
commit02dd3123a0e312f1d33403e744af52dd6096f12d (patch)
tree6e98abcf84cf291f6c9d6ef06959a4e6aa5393f5
parented951f15779df008e43012d99cdb51f3c5a57229 (diff)
parentefa6c663df0bcad748e3a89d7b3f4dec187f6f53 (diff)
Merge "master" into "next".
-rw-r--r--ChangeLog4
-rw-r--r--configure.ac2
-rw-r--r--datapath/actions.c2
-rw-r--r--include/openflow/openflow.h6
-rw-r--r--include/openvswitch/datapath-protocol.h1
-rw-r--r--lib/classifier.c13
-rw-r--r--lib/classifier.h1
-rw-r--r--lib/compiler.h13
-rw-r--r--lib/dpif-netdev.c9
-rw-r--r--lib/dpif.h8
-rw-r--r--lib/flow.h1
-rw-r--r--lib/ofp-print.c3
-rw-r--r--lib/ofpbuf.c20
-rw-r--r--lib/ofpbuf.h6
-rw-r--r--lib/packets.h3
-rw-r--r--lib/pcap.c8
-rw-r--r--lib/poll-loop.h8
-rw-r--r--lib/rconn.c68
-rw-r--r--lib/rconn.h3
-rw-r--r--lib/sflow_poller.c27
-rw-r--r--lib/sflow_sampler.c7
-rw-r--r--lib/stp.c2
-rw-r--r--lib/util.h2
-rw-r--r--lib/vconn.c195
-rw-r--r--lib/vconn.h4
-rw-r--r--ofproto/netflow.h3
-rw-r--r--ofproto/ofproto.c2
-rw-r--r--ofproto/ofproto.h8
-rw-r--r--ofproto/pinsched.c5
-rw-r--r--ofproto/pktbuf.c8
30 files changed, 324 insertions, 118 deletions
diff --git a/ChangeLog b/ChangeLog
index 88653d3c..1acda09a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+v0.99.2 - 18 Feb 2010
+---------------------
+ - Bug fixes
+
v0.99.1 - 25 Jan 2010
---------------------
- Add support for sFlow(R)
diff --git a/configure.ac b/configure.ac
index 6a8a1ea4..ac854508 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@
# limitations under the License.
AC_PREREQ(2.63)
-AC_INIT(openvswitch, 0.99.1, ovs-bugs@openvswitch.org)
+AC_INIT(openvswitch, 0.99.2, ovs-bugs@openvswitch.org)
NX_BUILDNR
AC_CONFIG_SRCDIR([datapath/datapath.c])
AC_CONFIG_MACRO_DIR([m4])
diff --git a/datapath/actions.c b/datapath/actions.c
index ab392222..b39d8307 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -93,7 +93,7 @@ modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
mask = VLAN_VID_MASK;
key->dl_vlan = htons(tci & mask);
} else {
- tci = a->vlan_pcp.vlan_pcp << 13;
+ tci = a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT;
mask = VLAN_PCP_MASK;
}
diff --git a/include/openflow/openflow.h b/include/openflow/openflow.h
index 27dae8fd..b77cd701 100644
--- a/include/openflow/openflow.h
+++ b/include/openflow/openflow.h
@@ -37,12 +37,6 @@
#define OFP_ASSERT BOOST_STATIC_ASSERT
#endif /* __cplusplus */
-#ifndef SWIG
-#define OFP_PACKED __attribute__((packed))
-#else
-#define OFP_PACKED /* SWIG doesn't understand __attribute. */
-#endif
-
/* Version number:
* Non-experimental versions released: 0x01
* Experimental versions released: 0x81 -- 0x99
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h
index 84646c22..6c535454 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -107,6 +107,7 @@ struct odp_stats {
/* Logical ports. */
#define ODPP_LOCAL ((__u16)0)
#define ODPP_NONE ((__u16)-1)
+#define ODPP_NORMAL ((__u16)-2)
/* Listening channels. */
#define _ODPL_MISS_NR 0 /* Packet missed in flow table. */
diff --git a/lib/classifier.c b/lib/classifier.c
index 036c372b..cdad9c9e 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
+#include "dynamic-string.h"
#include "flow.h"
#include "hash.h"
@@ -77,6 +78,18 @@ cls_rule_from_match(struct cls_rule *rule, const struct ofp_match *match,
rule->table_idx = table_idx_from_wildcards(rule->wc.wildcards);
}
+/* Converts 'rule' to a string and returns the string. The caller must free
+ * the string (with free()). */
+char *
+cls_rule_to_string(const struct cls_rule *rule)
+{
+ struct ds s = DS_EMPTY_INITIALIZER;
+ ds_put_format(&s, "wildcards=%x priority=%u ",
+ rule->wc.wildcards, rule->priority);
+ flow_format(&s, &rule->flow);
+ return ds_cstr(&s);
+}
+
/* Prints cls_rule 'rule', for debugging.
*
* (The output could be improved and expanded, but this was good enough to
diff --git a/lib/classifier.h b/lib/classifier.h
index f6cc93b9..126d1498 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -125,6 +125,7 @@ void cls_rule_from_flow(struct cls_rule *, const flow_t *, uint32_t wildcards,
unsigned int priority);
void cls_rule_from_match(struct cls_rule *, const struct ofp_match *,
unsigned int priority);
+char *cls_rule_to_string(const struct cls_rule *);
void cls_rule_print(const struct cls_rule *);
void cls_rule_moved(struct classifier *,
struct cls_rule *old, struct cls_rule *new);
diff --git a/lib/compiler.h b/lib/compiler.h
index 6c0db0fe..6bf51445 100644
--- a/lib/compiler.h
+++ b/lib/compiler.h
@@ -17,15 +17,22 @@
#ifndef COMPILER_H
#define COMPILER_H 1
+#ifdef __GNUC__
#define NO_RETURN __attribute__((__noreturn__))
#define OVS_UNUSED __attribute__((__unused__))
-#define PACKED __attribute__((__packed__))
#define PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
#define STRFTIME_FORMAT(FMT) __attribute__((__format__(__strftime__, FMT, 0)))
#define MALLOC_LIKE __attribute__((__malloc__))
#define ALWAYS_INLINE __attribute__((always_inline))
-#define likely(x) __builtin_expect((x),1)
-#define unlikely(x) __builtin_expect((x),0)
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+#else
+#define NO_RETURN
+#define OVS_UNUSED
+#define PRINTF_FORMAT(FMT, ARG1)
+#define STRFTIME_FORMAT(FMT)
+#define MALLOC_LIKE
+#define ALWAYS_INLINE
+#define WARN_UNUSED_RESULT
+#endif
#endif /* compiler.h */
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index ca5e8eb2..ac0a8caa 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -22,8 +22,8 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <net/if.h>
#include <netinet/in.h>
+#include <net/if.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
@@ -751,7 +751,7 @@ dpif_netdev_validate_actions(const union odp_action *actions, int n_actions,
case ODPAT_SET_VLAN_PCP:
*mutates = true;
- if (a->vlan_pcp.vlan_pcp & ~VLAN_PCP_MASK) {
+ if (a->vlan_pcp.vlan_pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) {
return EINVAL;
}
break;
@@ -1290,8 +1290,9 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
break;
case ODPAT_SET_VLAN_PCP:
- dp_netdev_modify_vlan_tci(packet, key, a->vlan_pcp.vlan_pcp << 13,
- VLAN_PCP_MASK);
+ dp_netdev_modify_vlan_tci(
+ packet, key, a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
+ VLAN_PCP_MASK);
break;
case ODPAT_STRIP_VLAN:
diff --git a/lib/dpif.h b/lib/dpif.h
index b1717937..47892844 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -23,6 +23,10 @@
#include <stddef.h>
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct dpif;
struct ofpbuf;
struct svec;
@@ -97,4 +101,8 @@ void dpif_recv_wait(struct dpif *);
void dpif_get_netflow_ids(const struct dpif *,
uint8_t *engine_type, uint8_t *engine_id);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* dpif.h */
diff --git a/lib/flow.h b/lib/flow.h
index b1292ce3..ca140afa 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -16,6 +16,7 @@
#ifndef FLOW_H
#define FLOW_H 1
+#include <sys/types.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index b392d83e..683fd987 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -16,10 +16,10 @@
#include <config.h>
#include "ofp-print.h"
-#include "xtoxll.h"
#include <errno.h>
#include <inttypes.h>
+#include <sys/types.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <stdarg.h>
@@ -35,6 +35,7 @@
#include "packets.h"
#include "pcap.h"
#include "util.h"
+#include "xtoxll.h"
static void ofp_print_port_name(struct ds *string, uint16_t port);
diff --git a/lib/ofpbuf.c b/lib/ofpbuf.c
index bb216791..9cb2ceb8 100644
--- a/lib/ofpbuf.c
+++ b/lib/ofpbuf.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include "dynamic-string.h"
#include "util.h"
/* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
@@ -103,7 +104,7 @@ ofpbuf_delete(struct ofpbuf *b)
* commonly, the data in a ofpbuf is at its beginning, and thus the ofpbuf's
* headroom is 0.) */
size_t
-ofpbuf_headroom(struct ofpbuf *b)
+ofpbuf_headroom(const struct ofpbuf *b)
{
return (char*)b->data - (char*)b->base;
}
@@ -111,7 +112,7 @@ ofpbuf_headroom(struct ofpbuf *b)
/* Returns the number of bytes that may be appended to the tail end of ofpbuf
* 'b' before the ofpbuf must be reallocated. */
size_t
-ofpbuf_tailroom(struct ofpbuf *b)
+ofpbuf_tailroom(const struct ofpbuf *b)
{
return (char*)ofpbuf_end(b) - (char*)ofpbuf_tail(b);
}
@@ -286,3 +287,18 @@ ofpbuf_try_pull(struct ofpbuf *b, size_t size)
{
return b->size >= size ? ofpbuf_pull(b, size) : NULL;
}
+
+/* Returns a string that describes some of 'b''s metadata plus a hex dump of up
+ * to 'maxbytes' from the start of the buffer. */
+char *
+ofpbuf_to_string(const struct ofpbuf *b, size_t maxbytes)
+{
+ struct ds s;
+
+ ds_init(&s);
+ ds_put_format(&s, "size=%zu, allocated=%zu, head=%zu, tail=%zu\n",
+ b->size, b->allocated,
+ ofpbuf_headroom(b), ofpbuf_tailroom(b));
+ ds_put_hex_dump(&s, b->data, MIN(b->size, maxbytes), 0, false);
+ return ds_cstr(&s);
+}
diff --git a/lib/ofpbuf.h b/lib/ofpbuf.h
index 259e703c..9072cc47 100644
--- a/lib/ofpbuf.h
+++ b/lib/ofpbuf.h
@@ -64,8 +64,8 @@ void ofpbuf_reserve(struct ofpbuf *, size_t);
void *ofpbuf_push_uninit(struct ofpbuf *b, size_t);
void *ofpbuf_push(struct ofpbuf *b, const void *, size_t);
-size_t ofpbuf_headroom(struct ofpbuf *);
-size_t ofpbuf_tailroom(struct ofpbuf *);
+size_t ofpbuf_headroom(const struct ofpbuf *);
+size_t ofpbuf_tailroom(const struct ofpbuf *);
void ofpbuf_prealloc_headroom(struct ofpbuf *, size_t);
void ofpbuf_prealloc_tailroom(struct ofpbuf *, size_t);
void ofpbuf_trim(struct ofpbuf *);
@@ -74,6 +74,8 @@ void ofpbuf_clear(struct ofpbuf *);
void *ofpbuf_pull(struct ofpbuf *, size_t);
void *ofpbuf_try_pull(struct ofpbuf *, size_t);
+char *ofpbuf_to_string(const struct ofpbuf *, size_t maxbytes);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/packets.h b/lib/packets.h
index 7651495e..7ea462bc 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -190,7 +190,10 @@ struct llc_snap_header {
BUILD_ASSERT_DECL(LLC_SNAP_HEADER_LEN == sizeof(struct llc_snap_header));
#define VLAN_VID_MASK 0x0fff
+#define VLAN_VID_SHIFT 0
+
#define VLAN_PCP_MASK 0xe000
+#define VLAN_PCP_SHIFT 13
#define VLAN_HEADER_LEN 4
struct vlan_header {
diff --git a/lib/pcap.c b/lib/pcap.c
index 967bb5c3..028dd0cb 100644
--- a/lib/pcap.c
+++ b/lib/pcap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,14 +34,16 @@ struct pcap_hdr {
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets */
uint32_t network; /* data link type */
-} PACKED;
+};
+BUILD_ASSERT_DECL(sizeof(struct pcap_hdr) == 24);
struct pcaprec_hdr {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
-} PACKED;
+};
+BUILD_ASSERT_DECL(sizeof(struct pcaprec_hdr) == 16);
FILE *
pcap_open(const char *file_name, const char *mode)
diff --git a/lib/poll-loop.h b/lib/poll-loop.h
index 89c8e573..adb88d48 100644
--- a/lib/poll-loop.h
+++ b/lib/poll-loop.h
@@ -34,6 +34,10 @@
#include <poll.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct poll_waiter;
/* Schedule events to wake up the following poll_block(). */
@@ -47,4 +51,8 @@ void poll_block(void);
/* Cancel a file descriptor callback or event. */
void poll_cancel(struct poll_waiter *);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* poll-loop.h */
diff --git a/lib/rconn.c b/lib/rconn.c
index 6bd43940..ea45134f 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -76,6 +76,7 @@ struct rconn {
time_t last_connected;
unsigned int packets_sent;
unsigned int seqno;
+ int last_error;
/* In S_ACTIVE and S_IDLE, probably_admitted reports whether we believe
* that the peer has made a (positive) admission control decision on our
@@ -136,6 +137,7 @@ static void state_transition(struct rconn *, enum state);
static void set_vconn_name(struct rconn *, const char *name);
static int try_send(struct rconn *);
static int reconnect(struct rconn *);
+static void report_error(struct rconn *, int error);
static void disconnect(struct rconn *, int error);
static void flush_queue(struct rconn *);
static void question_connectivity(struct rconn *);
@@ -272,6 +274,7 @@ void
rconn_reconnect(struct rconn *rc)
{
if (rc->state & (S_ACTIVE | S_IDLE)) {
+ VLOG_INFO("%s: disconnecting", rc->name);
disconnect(rc, 0);
}
}
@@ -341,7 +344,7 @@ reconnect(struct rconn *rc)
} else {
VLOG_WARN("%s: connection failed (%s)", rc->name, strerror(retval));
rc->backoff_deadline = TIME_MAX; /* Prevent resetting backoff. */
- disconnect(rc, 0);
+ disconnect(rc, retval);
}
return retval;
}
@@ -381,7 +384,7 @@ run_CONNECTING(struct rconn *rc)
} else if (timed_out(rc)) {
VLOG_INFO("%s: connection timed out", rc->name);
rc->backoff_deadline = TIME_MAX; /* Prevent resetting backoff. */
- disconnect(rc, 0);
+ disconnect(rc, ETIMEDOUT);
}
}
@@ -446,7 +449,7 @@ run_IDLE(struct rconn *rc)
VLOG_ERR("%s: no response to inactivity probe after %u "
"seconds, disconnecting",
rc->name, elapsed_in_this_state(rc));
- disconnect(rc, 0);
+ disconnect(rc, ETIMEDOUT);
} else {
do_tx_work(rc);
}
@@ -530,6 +533,7 @@ rconn_recv(struct rconn *rc)
}
return buffer;
} else if (error != EAGAIN) {
+ report_error(rc, error);
disconnect(rc, error);
}
}
@@ -808,6 +812,22 @@ rconn_get_connection_seqno(const struct rconn *rc)
{
return rc->seqno;
}
+
+/* Returns a value that explains why 'rc' last disconnected:
+ *
+ * - 0 means that the last disconnection was caused by a call to
+ * rconn_disconnect(), or that 'rc' is new and has not yet completed its
+ * initial connection or connection attempt.
+ *
+ * - EOF means that the connection was closed in the normal way by the peer.
+ *
+ * - A positive integer is an errno value that represents the error.
+ */
+int
+rconn_get_last_error(const struct rconn *rc)
+{
+ return rc->last_error;
+}
struct rconn_packet_counter *
rconn_packet_counter_create(void)
@@ -868,6 +888,7 @@ try_send(struct rconn *rc)
retval = vconn_send(rc->vconn, rc->txq.head);
if (retval) {
if (retval != EAGAIN) {
+ report_error(rc, retval);
disconnect(rc, retval);
}
return retval;
@@ -881,26 +902,41 @@ try_send(struct rconn *rc)
return 0;
}
-/* Disconnects 'rc'. 'error' is used only for logging purposes. If it is
- * nonzero, then it should be EOF to indicate the connection was closed by the
- * peer in a normal fashion or a positive errno value. */
+/* Reports that 'error' caused 'rc' to disconnect. 'error' may be a positive
+ * errno value, or it may be EOF to indicate that the connection was closed
+ * normally. */
+static void
+report_error(struct rconn *rc, int error)
+{
+ if (error == EOF) {
+ /* If 'rc' isn't reliable, then we don't really expect this connection
+ * to last forever anyway (probably it's a connection that we received
+ * via accept()), so use DBG level to avoid cluttering the logs. */
+ enum vlog_level level = rc->reliable ? VLL_INFO : VLL_DBG;
+ VLOG(level, "%s: connection closed by peer", rc->name);
+ } else {
+ VLOG_WARN("%s: connection dropped (%s)", rc->name, strerror(error));
+ }
+}
+
+/* Disconnects 'rc' and records 'error' as the error that caused 'rc''s last
+ * disconnection:
+ *
+ * - 0 means that this disconnection is due to a request by 'rc''s client,
+ * not due to any kind of network error.
+ *
+ * - EOF means that the connection was closed in the normal way by the peer.
+ *
+ * - A positive integer is an errno value that represents the error.
+ */
static void
disconnect(struct rconn *rc, int error)
{
+ rc->last_error = error;
if (rc->reliable) {
time_t now = time_now();
if (rc->state & (S_CONNECTING | S_ACTIVE | S_IDLE)) {
- if (error > 0) {
- VLOG_WARN("%s: connection dropped (%s)",
- rc->name, strerror(error));
- } else if (error == EOF) {
- if (rc->reliable) {
- VLOG_INFO("%s: connection closed by peer", rc->name);
- }
- } else {
- VLOG_INFO("%s: connection dropped", rc->name);
- }
vconn_close(rc->vconn);
rc->vconn = NULL;
flush_queue(rc);
diff --git a/lib/rconn.h b/lib/rconn.h
index ef4e16c8..765e88cc 100644
--- a/lib/rconn.h
+++ b/lib/rconn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,6 +88,7 @@ unsigned long int rconn_get_total_time_connected(const struct rconn *);
int rconn_get_backoff(const struct rconn *);
unsigned int rconn_get_state_elapsed(const struct rconn *);
unsigned int rconn_get_connection_seqno(const struct rconn *);
+int rconn_get_last_error(const struct rconn *);
/* Counts the number of packets queued into an rconn by a given source. */
struct rconn_packet_counter {
diff --git a/lib/sflow_poller.c b/lib/sflow_poller.c
index ffd09d3c..e7dc2b12 100644
--- a/lib/sflow_poller.c
+++ b/lib/sflow_poller.c
@@ -68,10 +68,29 @@ u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller) {
void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval) {
poller->sFlowCpInterval = sFlowCpInterval;
- /* Set the countersCountdown to be a randomly selected value between 1 and
- sFlowCpInterval. That way the counter polling would be desynchronised
- (on a 200-port switch, polling all the counters in one second could be harmful). */
- poller->countersCountdown = 1 + (random() % sFlowCpInterval);
+ if(sFlowCpInterval) {
+ /* Set the countersCountdown to be a randomly selected value between 1 and
+ sFlowCpInterval. That way the counter polling will be desynchronised
+ (on a 200-port switch, polling all the counters in one second could be harmful).
+ In a large network, even this might not be ideal if time-synchroniziation
+ between devices is close and counters are always polled on second boundaries. If
+ 1000 different devices all send an sFlow datagram on the same second boundary
+ it could result in an antisocial burst.
+ However when counter-samples are packed into the export datagram they do not
+ always result in that datagram being sent immediately. It is more likely that
+ a subsequent packet-sample will be the one that triggers the datagram to be sent.
+ The packet-sample events are not sychronized to any clock, so that results in
+ excellent desynchronization (http://blog.sflow.com/2009/05/measurement-traffic.html).
+ Another smoothing factor is that the tick() function called here is usually
+ driven from a fairly "soft" polling loop rather than a hard real-time event.
+ */
+ poller->countersCountdown = 1 + (random() % sFlowCpInterval);
+ }
+ else {
+ /* Setting sFlowCpInterval to 0 disables counter polling altogether. Thanks to
+ Andy Kitchingman for spotting this ommission. */
+ poller->countersCountdown = 0;
+ }
}
/*_________________---------------------------------__________________
diff --git a/lib/sflow_sampler.c b/lib/sflow_sampler.c
index 759b5a22..c2b4556c 100644
--- a/lib/sflow_sampler.c
+++ b/lib/sflow_sampler.c
@@ -16,14 +16,17 @@ void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instan
SFLDataSource_instance dsi = *pdsi;
/* preserve the *nxt pointer too, in case we are resetting this poller and it is
- already part of the agent's linked list (thanks to Matt Woodly for pointing this out) */
+ already part of the agent's linked list (thanks to Matt Woodly for pointing this out,
+ and to Andy Kitchingman for pointing out that it applies to the hash_nxt ptr too) */
SFLSampler *nxtPtr = sampler->nxt;
+ SFLSampler *hashPtr = sampler->hash_nxt;
/* clear everything */
memset(sampler, 0, sizeof(*sampler));
- /* restore the linked list ptr */
+ /* restore the linked list and hash-table ptr */
sampler->nxt = nxtPtr;
+ sampler->hash_nxt = hashPtr;
/* now copy in the parameters */
sampler->agent = agent;
diff --git a/lib/stp.c b/lib/stp.c
index 6fad3a08..38885c07 100644
--- a/lib/stp.c
+++ b/lib/stp.c
@@ -18,6 +18,8 @@
* applies to all modifications. */
#include "stp.h"
+#include <sys/types.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <inttypes.h>
diff --git a/lib/util.h b/lib/util.h
index 562f7e0e..a9d5048a 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -76,8 +76,6 @@ extern const char *program_name;
#endif
#define NOT_REACHED() abort()
-#define NOT_IMPLEMENTED() abort()
-#define NOT_TESTED() ((void) 0) /* XXX should print a message. */
/* Given POINTER, the address of the given MEMBER in a STRUCT object, returns
the STRUCT object. */
diff --git a/lib/vconn.c b/lib/vconn.c
index f8d3beb0..d8807fda 100644
--- a/lib/vconn.c
+++ b/lib/vconn.c
@@ -164,6 +164,42 @@ vconn_usage(bool active, bool passive, bool bootstrap OVS_UNUSED)
#endif
}
+/* Given 'name', a connection name in the form "TYPE:ARGS", stores the class
+ * named "TYPE" into '*classp' and returns 0. Returns EAFNOSUPPORT and stores
+ * a null pointer into '*classp' if 'name' is in the wrong form or if no such
+ * class exists. */
+static int
+vconn_lookup_class(const char *name, struct vconn_class **classp)
+{
+ size_t prefix_len;
+
+ prefix_len = strcspn(name, ":");
+ if (name[prefix_len] != '\0') {
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) {
+ struct vconn_class *class = vconn_classes[i];
+ if (strlen(class->name) == prefix_len
+ && !memcmp(class->name, name, prefix_len)) {
+ *classp = class;
+ return 0;
+ }
+ }
+ }
+
+ *classp = NULL;
+ return EAFNOSUPPORT;
+}
+
+/* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is
+ * a supported connection type, otherwise EAFNOSUPPORT. */
+int
+vconn_verify_name(const char *name)
+{
+ struct vconn_class *class;
+ return vconn_lookup_class(name, &class);
+}
+
/* Attempts to connect to an OpenFlow device. 'name' is a connection name in
* the form "TYPE:ARGS", where TYPE is an active vconn class's name and ARGS
* are vconn class-specific.
@@ -178,35 +214,37 @@ vconn_usage(bool active, bool passive, bool bootstrap OVS_UNUSED)
int
vconn_open(const char *name, int min_version, struct vconn **vconnp)
{
- size_t prefix_len;
- size_t i;
+ struct vconn_class *class;
+ struct vconn *vconn;
+ char *suffix_copy;
+ int error;
COVERAGE_INC(vconn_open);
check_vconn_classes();
- *vconnp = NULL;
- prefix_len = strcspn(name, ":");
- if (prefix_len == strlen(name)) {
- return EAFNOSUPPORT;
+ /* Look up the class. */
+ error = vconn_lookup_class(name, &class);
+ if (!class) {
+ goto error;
}
- for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) {
- struct vconn_class *class = vconn_classes[i];
- if (strlen(class->name) == prefix_len
- && !memcmp(class->name, name, prefix_len)) {
- struct vconn *vconn;
- char *suffix_copy = xstrdup(name + prefix_len + 1);
- int retval = class->open(name, suffix_copy, &vconn);
- free(suffix_copy);
- if (!retval) {
- assert(vconn->state != VCS_CONNECTING
- || vconn->class->connect);
- vconn->min_version = min_version;
- *vconnp = vconn;
- }
- return retval;
- }
+
+ /* Call class's "open" function. */
+ suffix_copy = xstrdup(strchr(name, ':') + 1);
+ error = class->open(name, suffix_copy, &vconn);
+ free(suffix_copy);
+ if (error) {
+ goto error;
}
- return EAFNOSUPPORT;
+
+ /* Success. */
+ assert(vconn->state != VCS_CONNECTING || vconn->class->connect);
+ vconn->min_version = min_version;
+ *vconnp = vconn;
+ return 0;
+
+error:
+ *vconnp = NULL;
+ return error;
}
/* Allows 'vconn' to perform maintenance activities, such as flushing output
@@ -691,6 +729,42 @@ vconn_send_wait(struct vconn *vconn)
vconn_wait(vconn, WAIT_SEND);
}
+/* Given 'name', a connection name in the form "TYPE:ARGS", stores the class
+ * named "TYPE" into '*classp' and returns 0. Returns EAFNOSUPPORT and stores
+ * a null pointer into '*classp' if 'name' is in the wrong form or if no such
+ * class exists. */
+static int
+pvconn_lookup_class(const char *name, struct pvconn_class **classp)
+{
+ size_t prefix_len;
+
+ prefix_len = strcspn(name, ":");
+ if (name[prefix_len] != '\0') {
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) {
+ struct pvconn_class *class = pvconn_classes[i];
+ if (strlen(class->name) == prefix_len
+ && !memcmp(class->name, name, prefix_len)) {
+ *classp = class;
+ return 0;
+ }
+ }
+ }
+
+ *classp = NULL;
+ return EAFNOSUPPORT;
+}
+
+/* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is
+ * a supported connection type, otherwise EAFNOSUPPORT. */
+int
+pvconn_verify_name(const char *name)
+{
+ struct pvconn_class *class;
+ return pvconn_lookup_class(name, &class);
+}
+
/* Attempts to start listening for OpenFlow connections. 'name' is a
* connection name in the form "TYPE:ARGS", where TYPE is an passive vconn
* class's name and ARGS are vconn class-specific.
@@ -701,30 +775,34 @@ vconn_send_wait(struct vconn *vconn)
int
pvconn_open(const char *name, struct pvconn **pvconnp)
{
- size_t prefix_len;
- size_t i;
+ struct pvconn_class *class;
+ struct pvconn *pvconn;
+ char *suffix_copy;
+ int error;
check_vconn_classes();
- *pvconnp = NULL;
- prefix_len = strcspn(name, ":");
- if (prefix_len == strlen(name)) {
- return EAFNOSUPPORT;
+ /* Look up the class. */
+ error = pvconn_lookup_class(name, &class);
+ if (!class) {
+ goto error;
}
- for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) {
- struct pvconn_class *class = pvconn_classes[i];
- if (strlen(class->name) == prefix_len
- && !memcmp(class->name, name, prefix_len)) {
- char *suffix_copy = xstrdup(name + prefix_len + 1);
- int retval = class->listen(name, suffix_copy, pvconnp);
- free(suffix_copy);
- if (retval) {
- *pvconnp = NULL;
- }
- return retval;
- }
+
+ /* Call class's "open" function. */
+ suffix_copy = xstrdup(strchr(name, ':') + 1);
+ error = class->listen(name, suffix_copy, &pvconn);
+ free(suffix_copy);
+ if (error) {
+ goto error;
}
- return EAFNOSUPPORT;
+
+ /* Success. */
+ *pvconnp = pvconn;
+ return 0;
+
+error:
+ *pvconnp = NULL;
+ return error;
}
/* Returns the name that was used to open 'pvconn'. The caller must not
@@ -1285,10 +1363,7 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports)
switch (ntohs(a->type)) {
case OFPAT_OUTPUT:
error = check_action_port(ntohs(a->output.port), max_ports);
- if (error) {
- return error;
- }
- return check_action_exact_len(a, len, 8);
+ return error ? error : check_action_exact_len(a, len, 8);
case OFPAT_SET_VLAN_VID:
case OFPAT_SET_VLAN_PCP:
@@ -1305,29 +1380,15 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports)
return check_action_exact_len(a, len, 16);
case OFPAT_VENDOR:
- if (a->vendor.vendor == htonl(NX_VENDOR_ID)) {
- return check_nicira_action(a, len);
- } else {
- return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR);
- }
- break;
+ return (a->vendor.vendor == htonl(NX_VENDOR_ID)
+ ? check_nicira_action(a, len)
+ : ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR));
default:
VLOG_WARN_RL(&bad_ofmsg_rl, "unknown action type %"PRIu16,
ntohs(a->type));
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE);
}
-
- if (!len) {
- VLOG_DBG_RL(&bad_ofmsg_rl, "action has invalid length 0");
- return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
- }
- if (len % ACTION_ALIGNMENT) {
- VLOG_DBG_RL(&bad_ofmsg_rl, "action length %u is not a multiple of %d",
- len, ACTION_ALIGNMENT);
- return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
- }
- return 0;
}
int
@@ -1347,7 +1408,15 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
"action requires %u slots but only %u remain",
n_slots, slots_left);
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
+ } else if (!len) {
+ VLOG_DBG_RL(&bad_ofmsg_rl, "action has invalid length 0");
+ return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
+ } else if (len % ACTION_ALIGNMENT) {
+ VLOG_DBG_RL(&bad_ofmsg_rl, "action length %u is not a multiple "
+ "of %d", len, ACTION_ALIGNMENT);
+ return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
}
+
error = check_action(a, len, max_ports);
if (error) {
return error;
diff --git a/lib/vconn.h b/lib/vconn.h
index 9bd235ae..1426c1d8 100644
--- a/lib/vconn.h
+++ b/lib/vconn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ struct vconn;
void vconn_usage(bool active, bool passive, bool bootstrap);
/* Active vconns: virtual connections to OpenFlow devices. */
+int vconn_verify_name(const char *name);
int vconn_open(const char *name, int min_version, struct vconn **);
void vconn_close(struct vconn *);
const char *vconn_get_name(const struct vconn *);
@@ -66,6 +67,7 @@ void vconn_recv_wait(struct vconn *);
void vconn_send_wait(struct vconn *);
/* Passive vconns: virtual listeners for incoming OpenFlow connections. */
+int pvconn_verify_name(const char *name);
int pvconn_open(const char *name, struct pvconn **);
const char *pvconn_get_name(const struct pvconn *);
void pvconn_close(struct pvconn *);
diff --git a/ofproto/netflow.h b/ofproto/netflow.h
index 7f48ddda..701ffd46 100644
--- a/ofproto/netflow.h
+++ b/ofproto/netflow.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
#ifndef NETFLOW_H
#define NETFLOW_H 1
+#include <stdint.h>
#include "flow.h"
#include "svec.h"
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 0e422146..189aa2c8 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -760,6 +760,8 @@ ofproto_destroy(struct ofproto *p)
free(p->serial_desc);
free(p->dp_desc);
+ port_array_destroy(&p->ports);
+
free(p);
}
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index e735cc60..d9e71d76 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -24,6 +24,10 @@
#include "netflow.h"
#include "tag.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct odp_actions;
struct ofhooks;
struct ofproto;
@@ -127,4 +131,8 @@ struct ofhooks {
void ofproto_revalidate(struct ofproto *, tag_type);
struct tag_set *ofproto_get_revalidate_set(struct ofproto *);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* ofproto.h */
diff --git a/ofproto/pinsched.c b/ofproto/pinsched.c
index a4f5bfad..b9c6371a 100644
--- a/ofproto/pinsched.c
+++ b/ofproto/pinsched.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,10 @@
#include <config.h>
#include "pinsched.h"
+#include <sys/types.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
+#include <stdint.h>
#include <stdlib.h>
#include "ofpbuf.h"
#include "openflow/openflow.h"
diff --git a/ofproto/pktbuf.c b/ofproto/pktbuf.c
index 495a1ee3..c103c7ff 100644
--- a/ofproto/pktbuf.c
+++ b/ofproto/pktbuf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -151,9 +151,9 @@ pktbuf_get_null(void)
* datapath port number on which the packet was received in '*in_port'. The
* caller becomes responsible for freeing the buffer. However, if 'id'
* identifies a "null" packet buffer (created with pktbuf_get_null()), stores
- * NULL in '*bufferp' and -1 in '*in_port'.
+ * NULL in '*bufferp' and UINT16_max in '*in_port'.
*
- * On failure, stores NULL in in '*bufferp' and -1 in '*in_port'. */
+ * On failure, stores NULL in in '*bufferp' and UINT16_MAX in '*in_port'. */
int
pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
uint16_t *in_port)
@@ -194,7 +194,7 @@ pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
error = 0;
}
*bufferp = NULL;
- *in_port = -1;
+ *in_port = UINT16_MAX;
return error;
}