diff options
author | Ben Pfaff <blp@nicira.com> | 2010-02-24 13:47:09 -0800 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2010-02-24 13:47:09 -0800 |
commit | 02dd3123a0e312f1d33403e744af52dd6096f12d (patch) | |
tree | 6e98abcf84cf291f6c9d6ef06959a4e6aa5393f5 | |
parent | ed951f15779df008e43012d99cdb51f3c5a57229 (diff) | |
parent | efa6c663df0bcad748e3a89d7b3f4dec187f6f53 (diff) | |
download | openvswitch-02dd3123a0e312f1d33403e744af52dd6096f12d.tar.gz |
Merge "master" into "next".
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | datapath/actions.c | 2 | ||||
-rw-r--r-- | include/openflow/openflow.h | 6 | ||||
-rw-r--r-- | include/openvswitch/datapath-protocol.h | 1 | ||||
-rw-r--r-- | lib/classifier.c | 13 | ||||
-rw-r--r-- | lib/classifier.h | 1 | ||||
-rw-r--r-- | lib/compiler.h | 13 | ||||
-rw-r--r-- | lib/dpif-netdev.c | 9 | ||||
-rw-r--r-- | lib/dpif.h | 8 | ||||
-rw-r--r-- | lib/flow.h | 1 | ||||
-rw-r--r-- | lib/ofp-print.c | 3 | ||||
-rw-r--r-- | lib/ofpbuf.c | 20 | ||||
-rw-r--r-- | lib/ofpbuf.h | 6 | ||||
-rw-r--r-- | lib/packets.h | 3 | ||||
-rw-r--r-- | lib/pcap.c | 8 | ||||
-rw-r--r-- | lib/poll-loop.h | 8 | ||||
-rw-r--r-- | lib/rconn.c | 68 | ||||
-rw-r--r-- | lib/rconn.h | 3 | ||||
-rw-r--r-- | lib/sflow_poller.c | 27 | ||||
-rw-r--r-- | lib/sflow_sampler.c | 7 | ||||
-rw-r--r-- | lib/stp.c | 2 | ||||
-rw-r--r-- | lib/util.h | 2 | ||||
-rw-r--r-- | lib/vconn.c | 195 | ||||
-rw-r--r-- | lib/vconn.h | 4 | ||||
-rw-r--r-- | ofproto/netflow.h | 3 | ||||
-rw-r--r-- | ofproto/ofproto.c | 2 | ||||
-rw-r--r-- | ofproto/ofproto.h | 8 | ||||
-rw-r--r-- | ofproto/pinsched.c | 5 | ||||
-rw-r--r-- | ofproto/pktbuf.c | 8 |
30 files changed, 324 insertions, 118 deletions
@@ -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 6a8a1ea47..ac8545084 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 ab3922224..b39d83070 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 27dae8fd4..b77cd7011 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 84646c229..6c5354548 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 036c372bd..cdad9c9e1 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 f6cc93b9c..126d1498a 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 6c0db0fea..6bf514456 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 ca5e8eb25..ac0a8caac 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 b1717937e..478928446 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 b1292ce35..ca140afaa 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 b392d83ea..683fd9872 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 bb216791b..9cb2ceb80 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 259e703cf..9072cc474 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 7651495ee..7ea462bcf 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 967bb5c34..028dd0cb7 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 89c8e573e..adb88d482 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 6bd43940e..ea45134fe 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 ef4e16c8b..765e88cc5 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 ffd09d3c2..e7dc2b12f 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 759b5a22c..c2b4556cf 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; @@ -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 562f7e0e0..a9d5048a0 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 f8d3beb0c..d8807fda3 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 9bd235ae6..1426c1d84 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 7f48ddda9..701ffd462 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 0e4221460..189aa2c82 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 e735cc60a..d9e71d762 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 a4f5bfad5..b9c6371ad 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 495a1ee37..c103c7ffb 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; } |