#include <stdlib.h>
#include <string.h>
-#include "buffer.h"
#include "command-line.h"
#include "compiler.h"
#include "daemon.h"
#include "fault.h"
#include "learning-switch.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "poll-loop.h"
#include "rconn.h"
signal(SIGPIPE, SIG_IGN);
if (argc - optind < 1) {
- fatal(0, "at least one vconn argument required; use --help for usage");
+ ofp_fatal(0, "at least one vconn argument required; "
+ "use --help for usage");
}
retval = vlog_server_listen(NULL, NULL);
if (retval) {
- fatal(retval, "Could not listen for vlog connections");
+ ofp_fatal(retval, "Could not listen for vlog connections");
}
n_switches = n_listeners = 0;
retval = vconn_open(name, OFP_VERSION, &vconn);
if (!retval) {
if (n_switches >= MAX_SWITCHES) {
- fatal(0, "max %d switch connections", n_switches);
+ ofp_fatal(0, "max %d switch connections", n_switches);
}
new_switch(&switches[n_switches++], vconn, name);
continue;
retval = pvconn_open(name, &pvconn);
if (!retval) {
if (n_listeners >= MAX_LISTENERS) {
- fatal(0, "max %d passive connections", n_listeners);
+ ofp_fatal(0, "max %d passive connections", n_listeners);
}
listeners[n_listeners++] = pvconn;
}
}
}
if (n_switches == 0 && n_listeners == 0) {
- fatal(0, "no active or passive switch connections");
+ ofp_fatal(0, "no active or passive switch connections");
}
die_if_already_running();
do_switching(struct switch_ *sw)
{
unsigned int packets_sent;
- struct buffer *msg;
+ struct ofpbuf *msg;
packets_sent = rconn_packets_sent(sw->rconn);
msg = rconn_recv(sw->rconn);
if (msg) {
lswitch_process_packet(sw->lswitch, sw->rconn, msg);
- buffer_delete(msg);
+ ofpbuf_delete(msg);
}
rconn_run(sw->rconn);
} else {
max_idle = atoi(optarg);
if (max_idle < 1 || max_idle > 65535) {
- fatal(0, "--max-idle argument must be between 1 and "
- "65535 or the word 'permanent'");
+ ofp_fatal(0, "--max-idle argument must be between 1 and "
+ "65535 or the word 'permanent'");
}
}
break;
noinst_HEADERS = \
- buffer.h \
command-line.h \
compiler.h \
csum.h \
netdev.h \
netlink-protocol.h \
netlink.h \
+ ofpbuf.h \
ofp-print.h \
openflow.h \
openflow-netlink.h \
+++ /dev/null
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
- * Junior University
- *
- * We are making the OpenFlow specification and associated documentation
- * (Software) available for public use and benefit with the expectation
- * that others will use, modify and enhance the Software and contribute
- * those enhancements back to the community. However, since we would
- * like to make the Software available for broadest use, with as few
- * restrictions as possible permission is hereby granted, free of
- * charge, to any person obtaining a copy of this Software to deal in
- * the Software under the copyrights without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * The name and trademarks of copyright holder(s) may NOT be used in
- * advertising or publicity pertaining to the Software or any
- * derivatives without specific, written prior permission.
- */
-
-#ifndef BUFFER_H
-#define BUFFER_H 1
-
-#include <stddef.h>
-
-/* Buffer for holding arbitrary data. A buffer is automatically reallocated as
- * necessary if it grows too large for the available memory. */
-struct buffer {
- void *base; /* First byte of area malloc()'d area. */
- size_t allocated; /* Number of bytes allocated. */
-
- void *data; /* First byte actually in use. */
- size_t size; /* Number of bytes in use. */
-
- void *l2; /* Link-level header. */
- void *l3; /* Network-level header. */
- void *l4; /* Transport-level header. */
- void *l7; /* Application data. */
-
- struct buffer *next; /* Next in a list of buffers. */
- void *private; /* Private pointer for use by owner. */
-};
-
-void buffer_use(struct buffer *, void *, size_t);
-
-void buffer_init(struct buffer *, size_t);
-void buffer_uninit(struct buffer *);
-void buffer_reinit(struct buffer *, size_t);
-
-struct buffer *buffer_new(size_t);
-struct buffer *buffer_clone(const struct buffer *);
-void buffer_delete(struct buffer *);
-
-void *buffer_at(const struct buffer *, size_t offset, size_t size);
-void *buffer_at_assert(const struct buffer *, size_t offset, size_t size);
-void *buffer_tail(const struct buffer *);
-void *buffer_end(const struct buffer *);
-
-void *buffer_put_uninit(struct buffer *, size_t);
-void *buffer_put(struct buffer *, const void *, size_t);
-void buffer_reserve(struct buffer *, size_t);
-void *buffer_push_uninit(struct buffer *b, size_t);
-void *buffer_push(struct buffer *b, const void *, size_t);
-
-size_t buffer_headroom(struct buffer *);
-size_t buffer_tailroom(struct buffer *);
-void buffer_prealloc_headroom(struct buffer *, size_t);
-void buffer_prealloc_tailroom(struct buffer *, size_t);
-
-void buffer_clear(struct buffer *);
-void *buffer_pull(struct buffer *, size_t);
-void *buffer_try_pull(struct buffer *, size_t);
-
-#endif /* buffer.h */
#include "util.h"
struct ds;
-struct buffer;
+struct ofpbuf;
/* Values for 'op' field. */
#define DHCP_BOOTREQUEST 1 /* Message sent by DHCP client. */
size_t offset, uint16_t *);
const char *dhcp_msg_to_string(const struct dhcp_msg *, bool multiline,
struct ds *);
-int dhcp_parse(struct dhcp_msg *, const struct buffer *);
-void dhcp_assemble(const struct dhcp_msg *, struct buffer *);
+int dhcp_parse(struct dhcp_msg *, const struct ofpbuf *);
+void dhcp_assemble(const struct dhcp_msg *, struct ofpbuf *);
#endif /* dhcp.h */
#include <stdbool.h>
#include <stdint.h>
-struct buffer;
+struct ofpbuf;
struct ofp_match;
/* A datapath interface. Opaque. */
int dpif_open(int dp_idx, bool subscribe, struct dpif *);
void dpif_close(struct dpif *);
-int dpif_recv_openflow(struct dpif *, struct buffer **, bool wait);
-int dpif_send_openflow(struct dpif *, struct buffer *, bool wait);
+int dpif_recv_openflow(struct dpif *, struct ofpbuf **, bool wait);
+int dpif_send_openflow(struct dpif *, struct ofpbuf *, bool wait);
int dpif_add_dp(struct dpif *);
int dpif_del_dp(struct dpif *);
int dpif_add_port(struct dpif *, const char *netdev);
#include <stdint.h>
#include "util.h"
-struct buffer;
+struct ofpbuf;
/* Identification data for a flow.
All fields are in network byte order.
};
BUILD_ASSERT_DECL(sizeof (struct flow) == 32);
-int flow_extract(struct buffer *, uint16_t in_port, struct flow *);
+int flow_extract(struct ofpbuf *, uint16_t in_port, struct flow *);
void flow_print(FILE *, const struct flow *);
int flow_compare(const struct flow *, const struct flow *);
unsigned long int flow_hash(const struct flow *, uint32_t basis);
#include <stdbool.h>
-struct buffer;
+struct ofpbuf;
struct rconn;
struct lswitch *lswitch_create(struct rconn *, bool learn_macs, int max_idle);
void lswitch_destroy(struct lswitch *);
void lswitch_process_packet(struct lswitch *, struct rconn *,
- const struct buffer *);
+ const struct ofpbuf *);
#endif /* learning-switch.h */
#include <stdbool.h>
#include <stdint.h>
-struct buffer;
+struct ofpbuf;
struct in_addr;
struct in6_addr;
struct netdev;
int netdev_open(const char *name, int ethertype, struct netdev **);
void netdev_close(struct netdev *);
-int netdev_recv(struct netdev *, struct buffer *);
+int netdev_recv(struct netdev *, struct ofpbuf *);
void netdev_recv_wait(struct netdev *);
void netdev_drain(struct netdev *);
-int netdev_send(struct netdev *, const struct buffer *);
+int netdev_send(struct netdev *, const struct ofpbuf *);
const uint8_t *netdev_get_etheraddr(const struct netdev *);
const char *netdev_get_name(const struct netdev *);
int netdev_get_mtu(const struct netdev *);
#include <sys/uio.h>
#include <stdint.h>
-struct buffer;
+struct ofpbuf;
struct nl_sock;
struct nlattr;
struct nl_sock **);
void nl_sock_destroy(struct nl_sock *);
-int nl_sock_send(struct nl_sock *, const struct buffer *, bool wait);
+int nl_sock_send(struct nl_sock *, const struct ofpbuf *, bool wait);
int nl_sock_sendv(struct nl_sock *sock, const struct iovec iov[], size_t n_iov,
bool wait);
-int nl_sock_recv(struct nl_sock *, struct buffer **, bool wait);
-int nl_sock_transact(struct nl_sock *, const struct buffer *request,
- struct buffer **reply);
+int nl_sock_recv(struct nl_sock *, struct ofpbuf **, bool wait);
+int nl_sock_transact(struct nl_sock *, const struct ofpbuf *request,
+ struct ofpbuf **reply);
int nl_sock_fd(const struct nl_sock *);
\f
/* Netlink messages. */
/* Accessing headers and data. */
-struct nlmsghdr *nl_msg_nlmsghdr(const struct buffer *);
-struct genlmsghdr *nl_msg_genlmsghdr(const struct buffer *);
-bool nl_msg_nlmsgerr(const struct buffer *, int *error);
-void nl_msg_reserve(struct buffer *, size_t);
+struct nlmsghdr *nl_msg_nlmsghdr(const struct ofpbuf *);
+struct genlmsghdr *nl_msg_genlmsghdr(const struct ofpbuf *);
+bool nl_msg_nlmsgerr(const struct ofpbuf *, int *error);
+void nl_msg_reserve(struct ofpbuf *, size_t);
/* Appending headers and raw data. */
-void nl_msg_put_nlmsghdr(struct buffer *, struct nl_sock *,
+void nl_msg_put_nlmsghdr(struct ofpbuf *, struct nl_sock *,
size_t expected_payload,
uint32_t type, uint32_t flags);
-void nl_msg_put_genlmsghdr(struct buffer *, struct nl_sock *,
+void nl_msg_put_genlmsghdr(struct ofpbuf *, struct nl_sock *,
size_t expected_payload, int family, uint32_t flags,
uint8_t cmd, uint8_t version);
-void nl_msg_put(struct buffer *, const void *, size_t);
-void *nl_msg_put_uninit(struct buffer *, size_t);
+void nl_msg_put(struct ofpbuf *, const void *, size_t);
+void *nl_msg_put_uninit(struct ofpbuf *, size_t);
/* Appending attributes. */
-void *nl_msg_put_unspec_uninit(struct buffer *, uint16_t type, size_t);
-void nl_msg_put_unspec(struct buffer *, uint16_t type, const void *, size_t);
-void nl_msg_put_flag(struct buffer *, uint16_t type);
-void nl_msg_put_u8(struct buffer *, uint16_t type, uint8_t value);
-void nl_msg_put_u16(struct buffer *, uint16_t type, uint16_t value);
-void nl_msg_put_u32(struct buffer *, uint16_t type, uint32_t value);
-void nl_msg_put_u64(struct buffer *, uint16_t type, uint64_t value);
-void nl_msg_put_string(struct buffer *, uint16_t type, const char *value);
-void nl_msg_put_nested(struct buffer *, uint16_t type, struct buffer *);
+void *nl_msg_put_unspec_uninit(struct ofpbuf *, uint16_t type, size_t);
+void nl_msg_put_unspec(struct ofpbuf *, uint16_t type, const void *, size_t);
+void nl_msg_put_flag(struct ofpbuf *, uint16_t type);
+void nl_msg_put_u8(struct ofpbuf *, uint16_t type, uint8_t value);
+void nl_msg_put_u16(struct ofpbuf *, uint16_t type, uint16_t value);
+void nl_msg_put_u32(struct ofpbuf *, uint16_t type, uint32_t value);
+void nl_msg_put_u64(struct ofpbuf *, uint16_t type, uint64_t value);
+void nl_msg_put_string(struct ofpbuf *, uint16_t type, const char *value);
+void nl_msg_put_nested(struct ofpbuf *, uint16_t type, struct ofpbuf *);
\f
/* Netlink attribute types. */
enum nl_attr_type
bool optional;
};
-bool nl_policy_parse(const struct buffer *, const struct nl_policy[],
+bool nl_policy_parse(const struct ofpbuf *, const struct nl_policy[],
struct nlattr *[], size_t n_attrs);
\f
/* Miscellaneous. */
--- /dev/null
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#ifndef OFPBUF_H
+#define OFPBUF_H 1
+
+#include <stddef.h>
+
+/* Buffer for holding arbitrary data. An ofpbuf is automatically reallocated
+ * as necessary if it grows too large for the available memory. */
+struct ofpbuf {
+ void *base; /* First byte of area malloc()'d area. */
+ size_t allocated; /* Number of bytes allocated. */
+
+ void *data; /* First byte actually in use. */
+ size_t size; /* Number of bytes in use. */
+
+ void *l2; /* Link-level header. */
+ void *l3; /* Network-level header. */
+ void *l4; /* Transport-level header. */
+ void *l7; /* Application data. */
+
+ struct ofpbuf *next; /* Next in a list of ofpbufs. */
+ void *private; /* Private pointer for use by owner. */
+};
+
+void ofpbuf_use(struct ofpbuf *, void *, size_t);
+
+void ofpbuf_init(struct ofpbuf *, size_t);
+void ofpbuf_uninit(struct ofpbuf *);
+void ofpbuf_reinit(struct ofpbuf *, size_t);
+
+struct ofpbuf *ofpbuf_new(size_t);
+struct ofpbuf *ofpbuf_clone(const struct ofpbuf *);
+void ofpbuf_delete(struct ofpbuf *);
+
+void *ofpbuf_at(const struct ofpbuf *, size_t offset, size_t size);
+void *ofpbuf_at_assert(const struct ofpbuf *, size_t offset, size_t size);
+void *ofpbuf_tail(const struct ofpbuf *);
+void *ofpbuf_end(const struct ofpbuf *);
+
+void *ofpbuf_put_uninit(struct ofpbuf *, size_t);
+void *ofpbuf_put(struct ofpbuf *, const void *, size_t);
+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 *);
+void ofpbuf_prealloc_headroom(struct ofpbuf *, size_t);
+void ofpbuf_prealloc_tailroom(struct ofpbuf *, size_t);
+
+void ofpbuf_clear(struct ofpbuf *);
+void *ofpbuf_pull(struct ofpbuf *, size_t);
+void *ofpbuf_try_pull(struct ofpbuf *, size_t);
+
+#endif /* ofpbuf.h */
#define QUEUE_H 1
/* Packet queue. */
-struct queue {
+struct ofp_queue {
int n; /* Number of queued packets. */
- struct buffer *head; /* First queued packet, null if n == 0. */
- struct buffer *tail; /* Last queued packet, null if n == 0. */
+ struct ofpbuf *head; /* First queued packet, null if n == 0. */
+ struct ofpbuf *tail; /* Last queued packet, null if n == 0. */
};
-void queue_init(struct queue *);
-void queue_destroy(struct queue *);
-void queue_clear(struct queue *);
-void queue_advance_head(struct queue *, struct buffer *next);
-void queue_push_tail(struct queue *, struct buffer *);
-struct buffer *queue_pop_head(struct queue *);
+void queue_init(struct ofp_queue *);
+void queue_destroy(struct ofp_queue *);
+void queue_clear(struct ofp_queue *);
+void queue_advance_head(struct ofp_queue *, struct ofpbuf *next);
+void queue_push_tail(struct ofp_queue *, struct ofpbuf *);
+struct ofpbuf *queue_pop_head(struct ofp_queue *);
#endif /* queue.h */
void rconn_run(struct rconn *);
void rconn_run_wait(struct rconn *);
-struct buffer *rconn_recv(struct rconn *);
+struct ofpbuf *rconn_recv(struct rconn *);
void rconn_recv_wait(struct rconn *);
-int rconn_send(struct rconn *, struct buffer *, int *n_queued);
-int rconn_send_with_limit(struct rconn *, struct buffer *,
+int rconn_send(struct rconn *, struct ofpbuf *, int *n_queued);
+int rconn_send_with_limit(struct rconn *, struct ofpbuf *,
int *n_queued, int queue_limit);
unsigned int rconn_packets_sent(const struct rconn *);
unsigned int rconn_packets_received(const struct rconn *);
#ifndef SOCKET_UTIL_H
#define SOCKET_UTIL_H 1
+#include <sys/types.h>
#include <netinet/in.h>
#include <stdbool.h>
-#include <sys/socket.h>
int set_nonblocking(int fd);
int lookup_ip(const char *host_name, struct in_addr *address);
#define ARRAY_SIZE(ARRAY) (sizeof ARRAY / sizeof *ARRAY)
#define ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y) * (Y))
#define ROUND_DOWN(X, Y) ((X) / (Y) * (Y))
+
+#ifndef MIN
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+#endif
+
+#ifndef MAX
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+#endif
#define NOT_REACHED() abort()
#define NOT_IMPLEMENTED() abort()
char *xstrdup(const char *);
char *xasprintf(const char *format, ...) PRINTF_FORMAT(1, 2);
-void fatal(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3) NO_RETURN;
-void error(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3);
-void debug(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3);
-void debug_msg(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3);
-void hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii);
+void ofp_fatal(int err_no, const char *format, ...)
+ PRINTF_FORMAT(2, 3) NO_RETURN;
+void ofp_error(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3);
+void ofp_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii);
#ifdef __cplusplus
}
/* Tries to receive an OpenFlow message from 'vconn'. If successful,
* stores the received message into '*msgp' and returns 0. The caller is
- * responsible for destroying the message with buffer_delete(). On
+ * responsible for destroying the message with ofpbuf_delete(). On
* failure, returns a positive errno value and stores a null pointer into
* '*msgp'.
*
*
* The recv function must not block waiting for a packet to arrive. If no
* packets have been received, it should return EAGAIN. */
- int (*recv)(struct vconn *vconn, struct buffer **msgp);
+ int (*recv)(struct vconn *vconn, struct ofpbuf **msgp);
/* Tries to queue 'msg' for transmission on 'vconn'. If successful,
* returns 0, in which case ownership of 'msg' is transferred to the vconn.
*
* The send function must not block. If 'msg' cannot be immediately
* accepted for transmission, it should return EAGAIN. */
- int (*send)(struct vconn *vconn, struct buffer *msg);
+ int (*send)(struct vconn *vconn, struct ofpbuf *msg);
/* Arranges for the poll loop to wake up when 'vconn' is ready to take an
* action of the given 'type'. */
#include <stddef.h>
#include <stdint.h>
-struct buffer;
+struct ofpbuf;
struct flow;
struct ofp_header;
struct pvconn;
const char *vconn_get_name(const struct vconn *);
uint32_t vconn_get_ip(const struct vconn *);
int vconn_connect(struct vconn *);
-int vconn_recv(struct vconn *, struct buffer **);
-int vconn_send(struct vconn *, struct buffer *);
-int vconn_transact(struct vconn *, struct buffer *, struct buffer **);
+int vconn_recv(struct vconn *, struct ofpbuf **);
+int vconn_send(struct vconn *, struct ofpbuf *);
+int vconn_transact(struct vconn *, struct ofpbuf *, struct ofpbuf **);
int vconn_open_block(const char *name, int min_version, struct vconn **);
-int vconn_send_block(struct vconn *, struct buffer *);
-int vconn_recv_block(struct vconn *, struct buffer **);
+int vconn_send_block(struct vconn *, struct ofpbuf *);
+int vconn_recv_block(struct vconn *, struct ofpbuf **);
enum vconn_wait_type {
WAIT_CONNECT,
void pvconn_wait(struct pvconn *);
/* OpenFlow protocol utility functions. */
-void *make_openflow(size_t openflow_len, uint8_t type, struct buffer **);
+void *make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **);
void *make_openflow_xid(size_t openflow_len, uint8_t type,
- uint32_t xid, struct buffer **);
-void update_openflow_length(struct buffer *);
-struct buffer *make_add_flow(const struct flow *, uint32_t buffer_id,
+ uint32_t xid, struct ofpbuf **);
+void update_openflow_length(struct ofpbuf *);
+struct ofpbuf *make_add_flow(const struct flow *, uint32_t buffer_id,
uint16_t max_idle, size_t n_actions);
-struct buffer *make_add_simple_flow(const struct flow *,
+struct ofpbuf *make_add_simple_flow(const struct flow *,
uint32_t buffer_id, uint16_t out_port,
uint16_t max_idle);
-struct buffer *make_buffered_packet_out(uint32_t buffer_id,
+struct ofpbuf *make_buffered_packet_out(uint32_t buffer_id,
uint16_t in_port, uint16_t out_port);
-struct buffer *make_unbuffered_packet_out(const struct buffer *packet,
+struct ofpbuf *make_unbuffered_packet_out(const struct ofpbuf *packet,
uint16_t in_port, uint16_t out_port);
-struct buffer *make_echo_request(void);
-struct buffer *make_echo_reply(const struct ofp_header *rq);
+struct ofpbuf *make_echo_request(void);
+struct ofpbuf *make_echo_reply(const struct ofp_header *rq);
#endif /* vconn.h */
#include "util.h"
/* Logging importance levels. */
+#define VLOG_LEVELS \
+ VLOG_LEVEL(EMER) \
+ VLOG_LEVEL(ERR) \
+ VLOG_LEVEL(WARN) \
+ VLOG_LEVEL(DBG)
enum vlog_level {
- VLL_EMER,
- VLL_ERR,
- VLL_WARN,
- VLL_DBG,
+#define VLOG_LEVEL(NAME) VLL_##NAME,
+ VLOG_LEVELS
+#undef VLOG_LEVEL
VLL_N_LEVELS
};
enum vlog_level vlog_get_level_val(const char *name);
/* Facilities that we can log to. */
+#define VLOG_FACILITIES \
+ VLOG_FACILITY(SYSLOG) \
+ VLOG_FACILITY(CONSOLE)
enum vlog_facility {
- VLF_SYSLOG,
- VLF_CONSOLE,
+#define VLOG_FACILITY(NAME) VLF_##NAME,
+ VLOG_FACILITIES
+#undef VLOG_FACILITY
VLF_N_FACILITIES,
VLF_ANY_FACILITY = -1
};
noinst_LIBRARIES = libopenflow.a
libopenflow_a_SOURCES = \
- buffer.c \
command-line.c \
csum.c \
daemon.c \
list.c \
mac-learning.c \
netdev.c \
+ ofpbuf.c \
ofp-print.c \
poll-loop.c \
queue.c \
+++ /dev/null
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
- * Junior University
- *
- * We are making the OpenFlow specification and associated documentation
- * (Software) available for public use and benefit with the expectation
- * that others will use, modify and enhance the Software and contribute
- * those enhancements back to the community. However, since we would
- * like to make the Software available for broadest use, with as few
- * restrictions as possible permission is hereby granted, free of
- * charge, to any person obtaining a copy of this Software to deal in
- * the Software under the copyrights without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * The name and trademarks of copyright holder(s) may NOT be used in
- * advertising or publicity pertaining to the Software or any
- * derivatives without specific, written prior permission.
- */
-
-#include <config.h>
-#include "buffer.h"
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "util.h"
-
-/* Initializes 'b' as an empty buffer that contains the 'allocated' bytes of
- * memory starting at 'base'.
- *
- * 'base' should ordinarily be the first byte of a region obtained from
- * malloc(), but in circumstances where it can be guaranteed that 'b' will
- * never need to be expanded or freed, it can be a pointer into arbitrary
- * memory. */
-void
-buffer_use(struct buffer *b, void *base, size_t allocated)
-{
- b->base = b->data = base;
- b->allocated = allocated;
- b->size = 0;
- b->l2 = b->l3 = b->l4 = b->l7 = NULL;
- b->next = NULL;
- b->private = NULL;
-}
-
-/* Initializes 'b' as a buffer with an initial capacity of 'size' bytes. */
-void
-buffer_init(struct buffer *b, size_t size)
-{
- buffer_use(b, size ? xmalloc(size) : NULL, size);
-}
-
-/* Frees memory that 'b' points to. */
-void
-buffer_uninit(struct buffer *b)
-{
- if (b) {
- free(b->base);
- }
-}
-
-/* Frees memory that 'b' points to and allocates a new buffer */
-void
-buffer_reinit(struct buffer *b, size_t size)
-{
- buffer_uninit(b);
- buffer_init(b, size);
-}
-
-/* Creates and returns a new buffer with an initial capacity of 'size'
- * bytes. */
-struct buffer *
-buffer_new(size_t size)
-{
- struct buffer *b = xmalloc(sizeof *b);
- buffer_init(b, size);
- return b;
-}
-
-struct buffer *
-buffer_clone(const struct buffer *buffer)
-{
- /* FIXME: reference counting. */
- struct buffer *b = buffer_new(buffer->size);
- buffer_put(b, buffer->data, buffer->size);
- return b;
-}
-
-/* Frees memory that 'b' points to, as well as 'b' itself. */
-void
-buffer_delete(struct buffer *b)
-{
- if (b) {
- buffer_uninit(b);
- free(b);
- }
-}
-
-/* Returns the number of bytes of headroom in 'b', that is, the number of bytes
- * of unused space in buffer 'b' before the data that is in use. (Most
- * commonly, the data in a buffer is at its beginning, and thus the buffer's
- * headroom is 0.) */
-size_t
-buffer_headroom(struct buffer *b)
-{
- return b->data - b->base;
-}
-
-/* Returns the number of bytes that may be appended to the tail end of buffer
- * 'b' before the buffer must be reallocated. */
-size_t
-buffer_tailroom(struct buffer *b)
-{
- return buffer_end(b) - buffer_tail(b);
-}
-
-/* Ensures that 'b' has room for at least 'size' bytes at its tail end,
- * reallocating and copying its data if necessary. */
-void
-buffer_prealloc_tailroom(struct buffer *b, size_t size)
-{
- if (size > buffer_tailroom(b)) {
- size_t new_allocated = b->allocated + MAX(size, 64);
- void *new_base = xmalloc(new_allocated);
- uintptr_t base_delta = new_base - b->base;
- memcpy(new_base, b->base, b->allocated);
- free(b->base);
- b->base = new_base;
- b->allocated = new_allocated;
- b->data += base_delta;
- if (b->l2) {
- b->l2 += base_delta;
- }
- if (b->l3) {
- b->l3 += base_delta;
- }
- if (b->l4) {
- b->l4 += base_delta;
- }
- if (b->l7) {
- b->l7 += base_delta;
- }
- }
-}
-
-void
-buffer_prealloc_headroom(struct buffer *b, size_t size)
-{
- assert(size <= buffer_headroom(b));
-}
-
-/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
- * copying its data if necessary. Returns a pointer to the first byte of the
- * new data, which is left uninitialized. */
-void *
-buffer_put_uninit(struct buffer *b, size_t size)
-{
- void *p;
- buffer_prealloc_tailroom(b, size);
- p = buffer_tail(b);
- b->size += size;
- return p;
-}
-
-/* Appends the 'size' bytes of data in 'p' to the tail end of 'b'. Data in 'b'
- * is reallocated and copied if necessary. Returns a pointer to the first
- * byte of the data's location in the buffer. */
-void *
-buffer_put(struct buffer *b, const void *p, size_t size)
-{
- void *dst = buffer_put_uninit(b, size);
- memcpy(dst, p, size);
- return dst;
-}
-
-/* Reserves 'size' bytes of headroom so that they can be later allocated with
- * buffer_push_uninit() without reallocating the buffer. */
-void
-buffer_reserve(struct buffer *b, size_t size)
-{
- assert(!b->size);
- buffer_prealloc_tailroom(b, size);
- b->data += size;
-}
-
-void *
-buffer_push_uninit(struct buffer *b, size_t size)
-{
- buffer_prealloc_headroom(b, size);
- b->data -= size;
- b->size += size;
- return b->data;
-}
-
-void *
-buffer_push(struct buffer *b, const void *p, size_t size)
-{
- void *dst = buffer_push_uninit(b, size);
- memcpy(dst, p, size);
- return dst;
-}
-
-/* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
- * byte 'offset'. Otherwise, returns a null pointer. */
-void *
-buffer_at(const struct buffer *b, size_t offset, size_t size)
-{
- return offset + size <= b->size ? (char *) b->data + offset : NULL;
-}
-
-/* Returns a pointer to byte 'offset' in 'b', which must contain at least
- * 'offset + size' bytes of data. */
-void *
-buffer_at_assert(const struct buffer *b, size_t offset, size_t size)
-{
- assert(offset + size <= b->size);
- return ((char *) b->data) + offset;
-}
-
-/* Returns the byte following the last byte of data in use in 'b'. */
-void *
-buffer_tail(const struct buffer *b)
-{
- return (char *) b->data + b->size;
-}
-
-/* Returns the byte following the last byte allocated for use (but not
- * necessarily in use) by 'b'. */
-void *
-buffer_end(const struct buffer *b)
-{
- return (char *) b->base + b->allocated;
-}
-
-/* Clears any data from 'b'. */
-void
-buffer_clear(struct buffer *b)
-{
- b->data = b->base;
- b->size = 0;
-}
-
-/* Removes 'size' bytes from the head end of 'b', which must contain at least
- * 'size' bytes of data. Returns the first byte of data removed. */
-void *
-buffer_pull(struct buffer *b, size_t size)
-{
- void *data = b->data;
- assert(b->size >= size);
- b->data += size;
- b->size -= size;
- return data;
-}
-
-/* If 'b' has at least 'size' bytes of data, removes that many bytes from the
- * head end of 'b' and returns the first byte removed. Otherwise, returns a
- * null pointer without modifying 'b'. */
-void *
-buffer_try_pull(struct buffer *b, size_t size)
-{
- return b->size >= size ? buffer_pull(b, size) : NULL;
-}
pid_t pid = already_running();
if (pid) {
if (!force) {
- fatal(0, "%s: already running as pid %ld",
- get_pidfile(), (long int) pid);
+ ofp_fatal(0, "%s: already running as pid %ld",
+ get_pidfile(), (long int) pid);
} else {
VLOG_WARN("%s: %s already running as pid %ld",
get_pidfile(), program_name, (long int) pid);
char c = 0;
int fds[2];
if (pipe(fds) < 0) {
- fatal(errno, "pipe failed");
+ ofp_fatal(errno, "pipe failed");
}
switch (fork()) {
case -1:
/* Error. */
- fatal(errno, "could not fork");
+ ofp_fatal(errno, "could not fork");
break;
}
} else {
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
-#include "buffer.h"
#include "csum.h"
#include "dhcp.h"
#include "dynamic-string.h"
#include "flow.h"
#include "netdev.h"
-#include "ofp-print.h"
+#include "ofpbuf.h"
#include "poll-loop.h"
#include "sat-math.h"
#include "timeval.h"
static bool
do_receive_msg(struct dhclient *cli, struct dhcp_msg *msg)
{
- struct buffer b;
+ struct ofpbuf b;
- buffer_init(&b, netdev_get_mtu(cli->netdev) + VLAN_ETH_HEADER_LEN);
+ ofpbuf_init(&b, netdev_get_mtu(cli->netdev) + VLAN_ETH_HEADER_LEN);
for (; cli->received < 50; cli->received++) {
const struct ip_header *ip;
const struct dhcp_header *dhcp;
struct flow flow;
int error;
- buffer_clear(&b);
+ ofpbuf_clear(&b);
error = netdev_recv(cli->netdev, &b);
if (error) {
goto drained;
continue;
}
- buffer_pull(&b, b.l7 - b.data);
+ ofpbuf_pull(&b, (char *)b.l7 - (char*)b.data);
error = dhcp_parse(msg, &b);
if (!error) {
VLOG_DBG_RL(&rl, "received %s",
dhcp_msg_to_string(msg, false, &cli->s));
- buffer_uninit(&b);
+ ofpbuf_uninit(&b);
return true;
}
}
netdev_drain(cli->netdev);
drained:
- buffer_uninit(&b);
+ ofpbuf_uninit(&b);
return false;
}
static void
do_send_msg(struct dhclient *cli, const struct dhcp_msg *msg)
{
- struct buffer b;
+ struct ofpbuf b;
struct eth_header eh;
struct ip_header nh;
struct udp_header th;
uint32_t udp_csum;
int error;
- buffer_init(&b, ETH_TOTAL_MAX);
- buffer_reserve(&b, ETH_HEADER_LEN + IP_HEADER_LEN + UDP_HEADER_LEN);
+ ofpbuf_init(&b, ETH_TOTAL_MAX);
+ ofpbuf_reserve(&b, ETH_HEADER_LEN + IP_HEADER_LEN + UDP_HEADER_LEN);
dhcp_assemble(msg, &b);
udp_csum = csum_continue(udp_csum, &th, sizeof th);
th.udp_csum = csum_finish(csum_continue(udp_csum, b.data, b.size));
- buffer_push(&b, &th, sizeof th);
- buffer_push(&b, &nh, sizeof nh);
- buffer_push(&b, &eh, sizeof eh);
+ ofpbuf_push(&b, &th, sizeof th);
+ ofpbuf_push(&b, &nh, sizeof nh);
+ ofpbuf_push(&b, &eh, sizeof eh);
/* Don't try to send the frame if it's too long for an Ethernet frame. We
* disregard the network device's actual MTU because we don't want the
VLOG_ERR("cannot send %zu-byte Ethernet frame", b.size);
}
- buffer_uninit(&b);
+ ofpbuf_uninit(&b);
}
static unsigned int
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
-#include "buffer.h"
#include "dynamic-string.h"
+#include "ofpbuf.h"
#define THIS_MODULE VLM_dhcp
#include "vlog.h"
size_t max_args; /* Maximum number of arguments. */
};
-static struct option_class classes[DHCP_N_OPTIONS] = {
- [0 ... 255] = {NULL, DHCP_ARG_UINT8, 0, SIZE_MAX},
-#define DHCP_OPT(NAME, CODE, TYPE, MIN, MAX) \
- [CODE] = {#NAME, DHCP_ARG_##TYPE, MIN, MAX},
- DHCP_OPTS
+static const struct option_class *
+get_option_class(int code)
+{
+ static struct option_class classes[DHCP_N_OPTIONS];
+ static bool init = false;
+ if (!init) {
+ int i;
+
+ init = true;
+#define DHCP_OPT(NAME, CODE, TYPE, MIN, MAX) \
+ classes[CODE].name = #NAME; \
+ classes[CODE].type = DHCP_ARG_##TYPE; \
+ classes[CODE].min_args = MIN; \
+ classes[CODE].max_args = MAX;
+ DHCP_OPTS
#undef DHCP_OPT
-};
+
+ for (i = 0; i < DHCP_N_OPTIONS; i++) {
+ if (!classes[i].name) {
+ classes[i].name = xasprintf("option-%d", i);
+ classes[i].type = DHCP_ARG_UINT8;
+ classes[i].min_args = 0;
+ classes[i].max_args = SIZE_MAX;
+ }
+ }
+ }
+ assert(code >= 0 && code < DHCP_N_OPTIONS);
+ return &classes[code];
+}
/* A single (bad) DHCP message can in theory dump out many, many log messages,
* especially at high logging levels, so the burst size is set quite high
const char *
dhcp_option_to_string(const struct dhcp_option *opt, int code, struct ds *ds)
{
- struct option_class *class = &classes[code];
+ const struct option_class *class = get_option_class(code);
const struct arg_type *type = &types[class->type];
size_t offset;
+ const char *cp;
- if (class->name) {
- const char *cp;
- for (cp = class->name; *cp; cp++) {
- unsigned char c = *cp;
- ds_put_char(ds, c == '_' ? '-' : tolower(c));
- }
- } else {
- ds_put_format(ds, "option-%d", code);
+ for (cp = class->name; *cp; cp++) {
+ unsigned char c = *cp;
+ ds_put_char(ds, c == '_' ? '-' : tolower(c));
}
ds_put_char(ds, '=');
parse_options(struct dhcp_msg *msg, const char *name, void *data, size_t size,
int option_offset)
{
- struct buffer b;
+ struct ofpbuf b;
b.data = data;
b.size = size;
uint8_t *code, *len;
void *payload;
- code = buffer_try_pull(&b, 1);
+ code = ofpbuf_try_pull(&b, 1);
if (!code || *code == DHCP_CODE_END) {
break;
} else if (*code == DHCP_CODE_PAD) {
continue;
}
- len = buffer_try_pull(&b, 1);
+ len = ofpbuf_try_pull(&b, 1);
if (!len) {
VLOG_DBG_RL(&rl, "reached end of %s expecting length byte", name);
break;
}
- payload = buffer_try_pull(&b, *len);
+ payload = ofpbuf_try_pull(&b, *len);
if (!payload) {
VLOG_DBG_RL(&rl, "expected %"PRIu8" bytes of option-%"PRIu8" "
"payload with only %zu bytes of %s left",
for (code = 0; code < DHCP_N_OPTIONS; code++) {
struct dhcp_option *opt = &msg->options[code];
- struct option_class *class = &classes[code];
+ const struct option_class *class = get_option_class(code);
struct arg_type *type = &types[class->type];
if (opt->data) {
size_t n_elems = opt->n / type->size;
* to the parsed message and returns 0. Otherwise, returns a positive errno
* value and '*msg' is indeterminate. */
int
-dhcp_parse(struct dhcp_msg *msg, const struct buffer *b_)
+dhcp_parse(struct dhcp_msg *msg, const struct ofpbuf *b_)
{
- struct buffer b = *b_;
+ struct ofpbuf b = *b_;
struct dhcp_header *dhcp;
uint32_t *cookie;
uint8_t type;
char *vendor_class;
- dhcp = buffer_try_pull(&b, sizeof *dhcp);
+ dhcp = ofpbuf_try_pull(&b, sizeof *dhcp);
if (!dhcp) {
VLOG_DBG_RL(&rl, "buffer too small for DHCP header (%zu bytes)",
b.size);
msg->giaddr = dhcp->giaddr;
memcpy(msg->chaddr, dhcp->chaddr, ETH_ADDR_LEN);
- cookie = buffer_try_pull(&b, sizeof cookie);
+ cookie = ofpbuf_try_pull(&b, sizeof cookie);
if (cookie) {
if (ntohl(*cookie) == DHCP_OPTS_COOKIE) {
uint8_t overload;
}
static void
-put_option_chunk(struct buffer *b, uint8_t code, void *data, size_t n)
+put_option_chunk(struct ofpbuf *b, uint8_t code, void *data, size_t n)
{
uint8_t header[2];
assert(n < 256);
header[0] = code;
header[1] = n;
- buffer_put(b, header, sizeof header);
- buffer_put(b, data, n);
+ ofpbuf_put(b, header, sizeof header);
+ ofpbuf_put(b, data, n);
}
static void
-put_option(struct buffer *b, uint8_t code, void *data, size_t n)
+put_option(struct ofpbuf *b, uint8_t code, void *data, size_t n)
{
if (data) {
if (n) {
/* Appends to 'b' the DHCP message represented by 'msg'. */
void
-dhcp_assemble(const struct dhcp_msg *msg, struct buffer *b)
+dhcp_assemble(const struct dhcp_msg *msg, struct ofpbuf *b)
{
const uint8_t end = DHCP_CODE_END;
uint32_t cookie = htonl(DHCP_OPTS_COOKIE);
- struct buffer vnd_data;
+ struct ofpbuf vnd_data;
struct dhcp_header dhcp;
int i;
dhcp.siaddr = msg->siaddr;
dhcp.giaddr = msg->giaddr;
memcpy(dhcp.chaddr, msg->chaddr, ETH_ADDR_LEN);
- buffer_put(b, &dhcp, sizeof dhcp);
- buffer_put(b, &cookie, sizeof cookie);
+ ofpbuf_put(b, &dhcp, sizeof dhcp);
+ ofpbuf_put(b, &cookie, sizeof cookie);
/* Put DHCP message type first. (The ordering is not required but it
* seems polite.) */
}
/* Assemble vendor specific option and put it. */
- buffer_init(&vnd_data, 0);
+ ofpbuf_init(&vnd_data, 0);
for (i = DHCP_VENDOR_OFS; i < DHCP_N_OPTIONS; i++) {
const struct dhcp_option *option = &msg->options[i];
put_option(&vnd_data, i - DHCP_VENDOR_OFS, option->data, option->n);
if (vnd_data.size) {
put_option(b, DHCP_CODE_VENDOR_SPECIFIC, vnd_data.data, vnd_data.size);
}
- buffer_uninit(&vnd_data);
+ ofpbuf_uninit(&vnd_data);
/* Put end-of-options option. */
- buffer_put(b, &end, sizeof end);
+ ofpbuf_put(b, &end, sizeof end);
}
#include <stdlib.h>
#include <string.h>
-#include "buffer.h"
#include "netlink.h"
#include "netlink-protocol.h"
-#include "ofp-print.h"
+#include "ofpbuf.h"
#include "openflow-netlink.h"
#include "openflow.h"
#include "packets.h"
/* Tries to receive an openflow message from the kernel on 'sock'. If
* successful, stores the received message into '*msgp' and returns 0. The
- * caller is responsible for destroying the message with buffer_delete(). On
+ * caller is responsible for destroying the message with ofpbuf_delete(). On
* failure, returns a positive errno value and stores a null pointer into
* '*msgp'.
*
* If 'wait' is true, dpif_recv_openflow waits for a message to be ready;
* otherwise, returns EAGAIN if the 'sock' receive buffer is empty. */
int
-dpif_recv_openflow(struct dpif *dp, struct buffer **bufferp,
+dpif_recv_openflow(struct dpif *dp, struct ofpbuf **bufferp,
bool wait)
{
struct nlattr *attrs[ARRAY_SIZE(openflow_policy)];
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_header *oh;
uint16_t ofp_len;
int retval;
buffer = *bufferp = NULL;
do {
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
retval = nl_sock_recv(dp->sock, &buffer, wait);
} while (retval == ENOBUFS
|| (!retval
return 0;
error:
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
return EPROTO;
}
* for details).
*/
int
-dpif_send_openflow(struct dpif *dp, struct buffer *buffer, bool wait)
+dpif_send_openflow(struct dpif *dp, struct ofpbuf *buffer, bool wait)
{
struct ofp_header *oh;
unsigned int dump_flag;
- struct buffer hdr;
+ struct ofpbuf hdr;
struct nlattr *nla;
uint32_t fixed_buffer[64 / 4];
struct iovec iov[3];
/* The reply to OFPT_STATS_REQUEST may be multiple segments long, so we
* need to specify NLM_F_DUMP in the request. */
- oh = buffer_at_assert(buffer, 0, sizeof *oh);
+ oh = ofpbuf_at_assert(buffer, 0, sizeof *oh);
dump_flag = oh->type == OFPT_STATS_REQUEST ? NLM_F_DUMP : 0;
- buffer_use(&hdr, fixed_buffer, sizeof fixed_buffer);
+ ofpbuf_use(&hdr, fixed_buffer, sizeof fixed_buffer);
nl_msg_put_genlmsghdr(&hdr, dp->sock, 32, openflow_family,
NLM_F_REQUEST | dump_flag, DP_GENL_C_OPENFLOW, 1);
nl_msg_put_u32(&hdr, DP_GENL_A_DP_IDX, dp->dp_idx);
- nla = buffer_put_uninit(&hdr, sizeof *nla);
+ nla = ofpbuf_put_uninit(&hdr, sizeof *nla);
nla->nla_len = sizeof *nla + buffer->size;
nla->nla_type = DP_GENL_A_OPENFLOW;
pad_bytes = NLA_ALIGN(nla->nla_len) - nla->nla_len;
lookup_openflow_multicast_group(int dp_idx, int *multicast_group)
{
struct nl_sock *sock;
- struct buffer request, *reply;
+ struct ofpbuf request, *reply;
struct nlattr *attrs[ARRAY_SIZE(openflow_multicast_policy)];
int retval;
if (retval) {
return retval;
}
- buffer_init(&request, 0);
+ ofpbuf_init(&request, 0);
nl_msg_put_genlmsghdr(&request, sock, 0, openflow_family, NLM_F_REQUEST,
DP_GENL_C_QUERY_DP, 1);
nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp_idx);
retval = nl_sock_transact(sock, &request, &reply);
- buffer_uninit(&request);
+ ofpbuf_uninit(&request);
if (retval) {
nl_sock_destroy(sock);
return retval;
if (!nl_policy_parse(reply, openflow_multicast_policy, attrs,
ARRAY_SIZE(openflow_multicast_policy))) {
nl_sock_destroy(sock);
- buffer_delete(reply);
+ ofpbuf_delete(reply);
return EPROTO;
}
*multicast_group = nl_attr_get_u32(attrs[DP_GENL_A_MC_GROUP]);
nl_sock_destroy(sock);
- buffer_delete(reply);
+ ofpbuf_delete(reply);
return 0;
}
static int
send_mgmt_command(struct dpif *dp, int command, const char *netdev)
{
- struct buffer request, *reply;
+ struct ofpbuf request, *reply;
int retval;
- buffer_init(&request, 0);
+ ofpbuf_init(&request, 0);
nl_msg_put_genlmsghdr(&request, dp->sock, 32, openflow_family,
NLM_F_REQUEST | NLM_F_ACK, command, 1);
nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp->dp_idx);
nl_msg_put_string(&request, DP_GENL_A_PORTNAME, netdev);
}
retval = nl_sock_transact(dp->sock, &request, &reply);
- buffer_uninit(&request);
- buffer_delete(reply);
+ ofpbuf_uninit(&request);
+ ofpbuf_delete(reply);
return retval;
}
sigaddset(&fatal_signal_set, sig_nr);
if (sigaction(sig_nr, NULL, &old_sa)) {
- fatal(errno, "sigaction");
+ ofp_fatal(errno, "sigaction");
}
if (old_sa.sa_handler == SIG_DFL
&& signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
- fatal(errno, "signal");
+ ofp_fatal(errno, "signal");
}
}
atexit(atexit_handler);
#include <inttypes.h>
#include <netinet/in.h>
#include <string.h>
-#include "buffer.h"
#include "hash.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "packets.h"
#define THIS_MODULE VLM_flow
static struct ip_header *
-pull_ip(struct buffer *packet)
+pull_ip(struct ofpbuf *packet)
{
if (packet->size >= IP_HEADER_LEN) {
struct ip_header *ip = packet->data;
int ip_len = IP_IHL(ip->ip_ihl_ver) * 4;
if (ip_len >= IP_HEADER_LEN && packet->size >= ip_len) {
- return buffer_pull(packet, ip_len);
+ return ofpbuf_pull(packet, ip_len);
}
}
return NULL;
}
static struct tcp_header *
-pull_tcp(struct buffer *packet)
+pull_tcp(struct ofpbuf *packet)
{
if (packet->size >= TCP_HEADER_LEN) {
struct tcp_header *tcp = packet->data;
int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
if (tcp_len >= TCP_HEADER_LEN && packet->size >= tcp_len) {
- return buffer_pull(packet, tcp_len);
+ return ofpbuf_pull(packet, tcp_len);
}
}
return NULL;
}
static struct udp_header *
-pull_udp(struct buffer *packet)
+pull_udp(struct ofpbuf *packet)
{
- return buffer_try_pull(packet, UDP_HEADER_LEN);
+ return ofpbuf_try_pull(packet, UDP_HEADER_LEN);
}
static struct eth_header *
-pull_eth(struct buffer *packet)
+pull_eth(struct ofpbuf *packet)
{
- return buffer_try_pull(packet, ETH_HEADER_LEN);
+ return ofpbuf_try_pull(packet, ETH_HEADER_LEN);
}
static struct vlan_header *
-pull_vlan(struct buffer *packet)
+pull_vlan(struct ofpbuf *packet)
{
- return buffer_try_pull(packet, VLAN_HEADER_LEN);
+ return ofpbuf_try_pull(packet, VLAN_HEADER_LEN);
}
/* Returns 1 if 'packet' is an IP fragment, 0 otherwise. */
int
-flow_extract(struct buffer *packet, uint16_t in_port, struct flow *flow)
+flow_extract(struct ofpbuf *packet, uint16_t in_port, struct flow *flow)
{
- struct buffer b = *packet;
+ struct ofpbuf b = *packet;
struct eth_header *eth;
int retval = 0;
flow->dl_type = eth->eth_type;
} else {
/* This is an 802.2 frame */
- struct llc_snap_header *h = buffer_at(&b, 0, sizeof *h);
+ struct llc_snap_header *h = ofpbuf_at(&b, 0, sizeof *h);
if (h == NULL) {
return 0;
}
&& !memcmp(h->snap.snap_org, SNAP_ORG_ETHERNET,
sizeof h->snap.snap_org)) {
flow->dl_type = h->snap.snap_type;
- buffer_pull(&b, sizeof *h);
+ ofpbuf_pull(&b, sizeof *h);
} else {
flow->dl_type = htons(OFP_DL_TYPE_NOT_ETH_TYPE);
- buffer_pull(&b, sizeof(struct llc_header));
+ ofpbuf_pull(&b, sizeof(struct llc_header));
}
}
#include <stdlib.h>
#include <time.h>
-#include "buffer.h"
#include "flow.h"
#include "mac-learning.h"
+#include "ofpbuf.h"
#include "ofp-print.h"
#include "openflow.h"
#include "queue.h"
* rate limit relatively high. */
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
-static void queue_tx(struct lswitch *, struct rconn *, struct buffer *);
+static void queue_tx(struct lswitch *, struct rconn *, struct ofpbuf *);
static void send_features_request(struct lswitch *, struct rconn *);
static void process_switch_features(struct lswitch *, struct rconn *,
struct ofp_switch_features *);
}
}
+static size_t
+min_size(uint8_t type)
+{
+ return (type == OFPT_FEATURES_REPLY ? sizeof(struct ofp_switch_features)
+ : type == OFPT_PACKET_IN ? offsetof (struct ofp_packet_in, data)
+ : type == OFPT_PORT_STATUS ? sizeof(struct ofp_port_status)
+ : sizeof(struct ofp_header));
+}
+
/* Processes 'msg', which should be an OpenFlow received on 'rconn', according
* to the learning switch state in 'sw'. The most likely result of processing
* is that flow-setup and packet-out OpenFlow messages will be sent out on
* 'rconn'. */
void
lswitch_process_packet(struct lswitch *sw, struct rconn *rconn,
- const struct buffer *msg)
+ const struct ofpbuf *msg)
{
- static const size_t min_size[UINT8_MAX + 1] = {
- [0 ... UINT8_MAX] = sizeof (struct ofp_header),
- [OFPT_FEATURES_REPLY] = sizeof (struct ofp_switch_features),
- [OFPT_PACKET_IN] = offsetof (struct ofp_packet_in, data),
- [OFPT_PORT_STATUS] = sizeof(struct ofp_port_status),
- };
struct ofp_header *oh;
oh = msg->data;
- if (msg->size < min_size[oh->type]) {
+ if (msg->size < min_size(oh->type)) {
VLOG_WARN_RL(&rl,
"%s: too short (%zu bytes) for type %"PRIu8" (min %zu)",
rconn_get_name(rconn),
- msg->size, oh->type, min_size[oh->type]);
+ msg->size, oh->type, min_size(oh->type));
return;
}
{
time_t now = time_now();
if (now >= sw->last_features_request + 1) {
- struct buffer *b;
+ struct ofpbuf *b;
struct ofp_switch_config *osc;
/* Send OFPT_FEATURES_REQUEST. */
}
static void
-queue_tx(struct lswitch *sw, struct rconn *rconn, struct buffer *b)
+queue_tx(struct lswitch *sw, struct rconn *rconn, struct ofpbuf *b)
{
int retval = rconn_send_with_limit(rconn, b, &sw->n_queued, 10);
if (retval && retval != ENOTCONN) {
uint16_t out_port = OFPP_FLOOD;
size_t pkt_ofs, pkt_len;
- struct buffer pkt;
+ struct ofpbuf pkt;
struct flow flow;
/* Extract flow data from 'opi' into 'flow'. */
} else {
/* We don't know that MAC, or we don't set up flows. Send along the
* packet without setting up a flow. */
- struct buffer *b;
+ struct ofpbuf *b;
if (ntohl(opi->buffer_id) == UINT32_MAX) {
b = make_unbuffered_packet_out(&pkt, in_port, out_port);
} else {
}
if (flags != new_flags) {
struct ofp_port_mod *opm;
- struct buffer *b;
+ struct ofpbuf *b;
int retval;
VLOG_WARN("port %d: flags=%x new_flags=%x",
VLOG_WARN_RL(&rl, "%s: send: %s",
rconn_get_name(rconn), strerror(retval));
}
- buffer_delete(b);
+ ofpbuf_delete(b);
}
}
}
#include <string.h>
#include <unistd.h>
-#include "list.h"
#include "fatal-signal.h"
-#include "buffer.h"
+#include "list.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "packets.h"
#include "poll-loop.h"
/* Pads 'buffer' out with zero-bytes to the minimum valid length of an
* Ethernet packet, if necessary. */
static void
-pad_to_minimum_length(struct buffer *buffer)
+pad_to_minimum_length(struct ofpbuf *buffer)
{
if (buffer->size < ETH_TOTAL_MIN) {
size_t shortage = ETH_TOTAL_MIN - buffer->size;
- memset(buffer_put_uninit(buffer, shortage), 0, shortage);
+ memset(ofpbuf_put_uninit(buffer, shortage), 0, shortage);
}
}
* be returned.
*/
int
-netdev_recv(struct netdev *netdev, struct buffer *buffer)
+netdev_recv(struct netdev *netdev, struct ofpbuf *buffer)
{
ssize_t n_bytes;
assert(buffer->size == 0);
- assert(buffer_tailroom(buffer) >= ETH_TOTAL_MIN);
+ assert(ofpbuf_tailroom(buffer) >= ETH_TOTAL_MIN);
do {
n_bytes = recv(netdev->fd,
- buffer_tail(buffer), buffer_tailroom(buffer),
+ ofpbuf_tail(buffer), ofpbuf_tailroom(buffer),
MSG_DONTWAIT);
} while (n_bytes < 0 && errno == EINTR);
if (n_bytes < 0) {
* The kernel maintains a packet transmission queue, so the caller is not
* expected to do additional queuing of packets. */
int
-netdev_send(struct netdev *netdev, const struct buffer *buffer)
+netdev_send(struct netdev *netdev, const struct ofpbuf *buffer)
{
ssize_t n_bytes;
const struct eth_header *eh;
buffer->size, netdev->name);
return EMSGSIZE;
}
- eh = buffer_at_assert(buffer, 0, sizeof *eh);
+ eh = ofpbuf_at_assert(buffer, 0, sizeof *eh);
do {
n_bytes = sendto(netdev->fd, buffer->data, buffer->size, 0, NULL, 0);
fatal_signal_add_hook(restore_all_flags, NULL, true);
af_inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (af_inet_sock < 0) {
- fatal(errno, "socket(AF_INET)");
+ ofp_fatal(errno, "socket(AF_INET)");
}
}
}
#include <string.h>
#include <time.h>
#include <unistd.h>
-#include "buffer.h"
-#include "netlink-protocol.h"
#include "dynamic-string.h"
+#include "netlink-protocol.h"
+#include "ofpbuf.h"
#include "timeval.h"
#include "util.h"
* 'wait' is true, then the send will wait until buffer space is ready;
* otherwise, returns EAGAIN if the 'sock' send buffer is full. */
int
-nl_sock_send(struct nl_sock *sock, const struct buffer *msg, bool wait)
+nl_sock_send(struct nl_sock *sock, const struct ofpbuf *msg, bool wait)
{
int error;
/* Tries to receive a netlink message from the kernel on 'sock'. If
* successful, stores the received message into '*bufp' and returns 0. The
- * caller is responsible for destroying the message with buffer_delete(). On
+ * caller is responsible for destroying the message with ofpbuf_delete(). On
* failure, returns a positive errno value and stores a null pointer into
* '*bufp'.
*
* If 'wait' is true, nl_sock_recv waits for a message to be ready; otherwise,
* returns EAGAIN if the 'sock' receive buffer is empty. */
int
-nl_sock_recv(struct nl_sock *sock, struct buffer **bufp, bool wait)
+nl_sock_recv(struct nl_sock *sock, struct ofpbuf **bufp, bool wait)
{
uint8_t tmp;
ssize_t bufsize = 2048;
ssize_t nbytes, nbytes2;
- struct buffer *buf;
+ struct ofpbuf *buf;
struct nlmsghdr *nlmsghdr;
struct iovec iov;
struct msghdr msg = {
.msg_flags = 0
};
- buf = buffer_new(bufsize);
+ buf = ofpbuf_new(bufsize);
*bufp = NULL;
try_again:
* yet, so we take a guess at 2048. If we're wrong, we keep trying
* and doubling the buffer size each time.
*/
- nlmsghdr = buffer_put_uninit(buf, bufsize);
+ nlmsghdr = ofpbuf_put_uninit(buf, bufsize);
iov.iov_base = nlmsghdr;
iov.iov_len = bufsize;
do {
nbytes = recvmsg(sock->fd, &msg, (wait ? 0 : MSG_DONTWAIT) | MSG_PEEK);
} while (nbytes < 0 && errno == EINTR);
if (nbytes < 0) {
- buffer_delete(buf);
+ ofpbuf_delete(buf);
return errno;
}
if (msg.msg_flags & MSG_TRUNC) {
bufsize *= 2;
- buffer_reinit(buf, bufsize);
+ ofpbuf_reinit(buf, bufsize);
goto try_again;
}
buf->size = nbytes;
* was dropped. We have to pass this along to the caller in case
* it wants to retry a request. So kill the buffer, which we can
* re-read next time. */
- buffer_delete(buf);
+ ofpbuf_delete(buf);
return ENOBUFS;
} else {
VLOG_ERR_RL(&rl, "failed to remove nlmsg from socket: %s\n",
|| nlmsghdr->nlmsg_len > nbytes) {
VLOG_ERR_RL(&rl, "received invalid nlmsg (%zd bytes < %d)",
bufsize, NLMSG_HDRLEN);
- buffer_delete(buf);
+ ofpbuf_delete(buf);
return EPROTO;
}
*bufp = buf;
/* Sends 'request' to the kernel via 'sock' and waits for a response. If
* successful, stores the reply into '*replyp' and returns 0. The caller is
- * responsible for destroying the reply with buffer_delete(). On failure,
+ * responsible for destroying the reply with ofpbuf_delete(). On failure,
* returns a positive errno value and stores a null pointer into '*replyp'.
*
* Bare Netlink is an unreliable transport protocol. This function layers
*/
int
nl_sock_transact(struct nl_sock *sock,
- const struct buffer *request, struct buffer **replyp)
+ const struct ofpbuf *request, struct ofpbuf **replyp)
{
uint32_t seq = nl_msg_nlmsghdr(request)->nlmsg_seq;
struct nlmsghdr *nlmsghdr;
- struct buffer *reply;
+ struct ofpbuf *reply;
int retval;
*replyp = NULL;
if (seq != nlmsghdr->nlmsg_seq) {
VLOG_DBG_RL(&rl, "ignoring seq %"PRIu32" != expected %"PRIu32,
nl_msg_nlmsghdr(reply)->nlmsg_seq, seq);
- buffer_delete(reply);
+ ofpbuf_delete(reply);
goto recv;
}
if (nl_msg_nlmsgerr(reply, &retval)) {
*
* 'msg' must be at least as large as a nlmsghdr. */
struct nlmsghdr *
-nl_msg_nlmsghdr(const struct buffer *msg)
+nl_msg_nlmsghdr(const struct ofpbuf *msg)
{
- return buffer_at_assert(msg, 0, NLMSG_HDRLEN);
+ return ofpbuf_at_assert(msg, 0, NLMSG_HDRLEN);
}
/* Returns the genlmsghdr just past 'msg''s nlmsghdr.
* Returns a null pointer if 'msg' is not large enough to contain an nlmsghdr
* and a genlmsghdr. */
struct genlmsghdr *
-nl_msg_genlmsghdr(const struct buffer *msg)
+nl_msg_genlmsghdr(const struct ofpbuf *msg)
{
- return buffer_at(msg, NLMSG_HDRLEN, GENL_HDRLEN);
+ return ofpbuf_at(msg, NLMSG_HDRLEN, GENL_HDRLEN);
}
/* If 'buffer' is a NLMSG_ERROR message, stores 0 in '*errorp' if it is an ACK
*
* 'msg' must be at least as large as a nlmsghdr. */
bool
-nl_msg_nlmsgerr(const struct buffer *msg, int *errorp)
+nl_msg_nlmsgerr(const struct ofpbuf *msg, int *errorp)
{
if (nl_msg_nlmsghdr(msg)->nlmsg_type == NLMSG_ERROR) {
- struct nlmsgerr *err = buffer_at(msg, NLMSG_HDRLEN, sizeof *err);
+ struct nlmsgerr *err = ofpbuf_at(msg, NLMSG_HDRLEN, sizeof *err);
int code = EPROTO;
if (!err) {
VLOG_ERR_RL(&rl, "received invalid nlmsgerr (%zd bytes < %zd)",
/* Ensures that 'b' has room for at least 'size' bytes plus netlink padding at
* its tail end, reallocating and copying its data if necessary. */
void
-nl_msg_reserve(struct buffer *msg, size_t size)
+nl_msg_reserve(struct ofpbuf *msg, size_t size)
{
- buffer_prealloc_tailroom(msg, NLMSG_ALIGN(size));
+ ofpbuf_prealloc_tailroom(msg, NLMSG_ALIGN(size));
}
/* Puts a nlmsghdr at the beginning of 'msg', which must be initially empty.
* nl_msg_put_genlmsghdr is more convenient for composing a Generic Netlink
* message. */
void
-nl_msg_put_nlmsghdr(struct buffer *msg, struct nl_sock *sock,
+nl_msg_put_nlmsghdr(struct ofpbuf *msg, struct nl_sock *sock,
size_t expected_payload, uint32_t type, uint32_t flags)
{
struct nlmsghdr *nlmsghdr;
* nl_msg_put_nlmsghdr should be used to compose Netlink messages that are not
* Generic Netlink messages. */
void
-nl_msg_put_genlmsghdr(struct buffer *msg, struct nl_sock *sock,
+nl_msg_put_genlmsghdr(struct ofpbuf *msg, struct nl_sock *sock,
size_t expected_payload, int family, uint32_t flags,
uint8_t cmd, uint8_t version)
{
* the tail end of 'msg'. Data in 'msg' is reallocated and copied if
* necessary. */
void
-nl_msg_put(struct buffer *msg, const void *data, size_t size)
+nl_msg_put(struct ofpbuf *msg, const void *data, size_t size)
{
memcpy(nl_msg_put_uninit(msg, size), data, size);
}
* end of 'msg', reallocating and copying its data if necessary. Returns a
* pointer to the first byte of the new data, which is left uninitialized. */
void *
-nl_msg_put_uninit(struct buffer *msg, size_t size)
+nl_msg_put_uninit(struct ofpbuf *msg, size_t size)
{
size_t pad = NLMSG_ALIGN(size) - size;
- char *p = buffer_put_uninit(msg, size + pad);
+ char *p = ofpbuf_put_uninit(msg, size + pad);
if (pad) {
memset(p + size, 0, pad);
}
* 'msg', reallocating and copying its data if necessary. Returns a pointer to
* the first byte of data in the attribute, which is left uninitialized. */
void *
-nl_msg_put_unspec_uninit(struct buffer *msg, uint16_t type, size_t size)
+nl_msg_put_unspec_uninit(struct ofpbuf *msg, uint16_t type, size_t size)
{
size_t total_size = NLA_HDRLEN + size;
struct nlattr* nla = nl_msg_put_uninit(msg, total_size);
* its data if necessary. Returns a pointer to the first byte of data in the
* attribute, which is left uninitialized. */
void
-nl_msg_put_unspec(struct buffer *msg, uint16_t type,
+nl_msg_put_unspec(struct ofpbuf *msg, uint16_t type,
const void *data, size_t size)
{
memcpy(nl_msg_put_unspec_uninit(msg, type, size), data, size);
* (Some Netlink protocols use the presence or absence of an attribute as a
* Boolean flag.) */
void
-nl_msg_put_flag(struct buffer *msg, uint16_t type)
+nl_msg_put_flag(struct ofpbuf *msg, uint16_t type)
{
nl_msg_put_unspec(msg, type, NULL, 0);
}
/* Appends a Netlink attribute of the given 'type' and the given 8-bit 'value'
* to 'msg'. */
void
-nl_msg_put_u8(struct buffer *msg, uint16_t type, uint8_t value)
+nl_msg_put_u8(struct ofpbuf *msg, uint16_t type, uint8_t value)
{
nl_msg_put_unspec(msg, type, &value, sizeof value);
}
/* Appends a Netlink attribute of the given 'type' and the given 16-bit 'value'
* to 'msg'. */
void
-nl_msg_put_u16(struct buffer *msg, uint16_t type, uint16_t value)
+nl_msg_put_u16(struct ofpbuf *msg, uint16_t type, uint16_t value)
{
nl_msg_put_unspec(msg, type, &value, sizeof value);
}
/* Appends a Netlink attribute of the given 'type' and the given 32-bit 'value'
* to 'msg'. */
void
-nl_msg_put_u32(struct buffer *msg, uint16_t type, uint32_t value)
+nl_msg_put_u32(struct ofpbuf *msg, uint16_t type, uint32_t value)
{
nl_msg_put_unspec(msg, type, &value, sizeof value);
}
/* Appends a Netlink attribute of the given 'type' and the given 64-bit 'value'
* to 'msg'. */
void
-nl_msg_put_u64(struct buffer *msg, uint16_t type, uint64_t value)
+nl_msg_put_u64(struct ofpbuf *msg, uint16_t type, uint64_t value)
{
nl_msg_put_unspec(msg, type, &value, sizeof value);
}
/* Appends a Netlink attribute of the given 'type' and the given
* null-terminated string 'value' to 'msg'. */
void
-nl_msg_put_string(struct buffer *msg, uint16_t type, const char *value)
+nl_msg_put_string(struct ofpbuf *msg, uint16_t type, const char *value)
{
nl_msg_put_unspec(msg, type, value, strlen(value) + 1);
}
* netlink message in 'nested_msg' to 'msg'. The nlmsg_len field in
* 'nested_msg' is finalized to match 'nested_msg->size'. */
void
-nl_msg_put_nested(struct buffer *msg,
- uint16_t type, struct buffer *nested_msg)
+nl_msg_put_nested(struct ofpbuf *msg,
+ uint16_t type, struct ofpbuf *nested_msg)
{
nl_msg_nlmsghdr(nested_msg)->nlmsg_len = nested_msg->size;
nl_msg_put_unspec(msg, type, nested_msg->data, nested_msg->size);
* with nla_type == i is parsed; a pointer to attribute i is stored in
* attrs[i]. Returns true if successful, false on failure. */
bool
-nl_policy_parse(const struct buffer *msg, const struct nl_policy policy[],
+nl_policy_parse(const struct ofpbuf *msg, const struct nl_policy policy[],
struct nlattr *attrs[], size_t n_attrs)
{
void *p, *tail;
}
}
- p = buffer_at(msg, NLMSG_HDRLEN + GENL_HDRLEN, 0);
+ p = ofpbuf_at(msg, NLMSG_HDRLEN + GENL_HDRLEN, 0);
if (p == NULL) {
VLOG_DBG_RL(&rl, "missing headers in nl_policy_parse");
return false;
}
- tail = buffer_tail(msg);
+ tail = ofpbuf_tail(msg);
while (p < tail) {
- size_t offset = p - msg->data;
+ size_t offset = (char*)p - (char*)msg->data;
struct nlattr *nla = p;
size_t len, aligned_len;
uint16_t type;
}
len = nla->nla_len - NLA_HDRLEN;
aligned_len = NLA_ALIGN(len);
- if (aligned_len > tail - p) {
+ if (aligned_len > (char*)tail - (char*)p) {
VLOG_DBG_RL(&rl, "%zu: attr %"PRIu16" aligned data len (%zu) "
"> bytes left (%tu)",
- offset, nla->nla_type, aligned_len, tail - p);
+ offset, nla->nla_type, aligned_len,
+ (char*)tail - (char*)p);
return false;
}
} else {
/* Skip attribute type that we don't care about. */
}
- p += NLA_ALIGN(nla->nla_len);
+ p = (char*)p + NLA_ALIGN(nla->nla_len);
}
if (n_required) {
VLOG_DBG_RL(&rl, "%zu required attrs missing", n_required);
static int do_lookup_genl_family(const char *name)
{
struct nl_sock *sock;
- struct buffer request, *reply;
+ struct ofpbuf request, *reply;
struct nlattr *attrs[ARRAY_SIZE(family_policy)];
int retval;
return -retval;
}
- buffer_init(&request, 0);
+ ofpbuf_init(&request, 0);
nl_msg_put_genlmsghdr(&request, sock, 0, GENL_ID_CTRL, NLM_F_REQUEST,
CTRL_CMD_GETFAMILY, 1);
nl_msg_put_string(&request, CTRL_ATTR_FAMILY_NAME, name);
retval = nl_sock_transact(sock, &request, &reply);
- buffer_uninit(&request);
+ ofpbuf_uninit(&request);
if (retval) {
nl_sock_destroy(sock);
return -retval;
if (!nl_policy_parse(reply, family_policy, attrs,
ARRAY_SIZE(family_policy))) {
nl_sock_destroy(sock);
- buffer_delete(reply);
+ ofpbuf_delete(reply);
return -EPROTO;
}
retval = -EPROTO;
}
nl_sock_destroy(sock);
- buffer_delete(reply);
+ ofpbuf_delete(reply);
return retval;
}
}
static char *
-nlmsg_to_string(const struct buffer *buffer)
+nlmsg_to_string(const struct ofpbuf *buffer)
{
struct ds ds = DS_EMPTY_INITIALIZER;
- const struct nlmsghdr *h = buffer_at(buffer, 0, NLMSG_HDRLEN);
+ const struct nlmsghdr *h = ofpbuf_at(buffer, 0, NLMSG_HDRLEN);
if (h) {
nlmsghdr_to_string(h, &ds);
if (h->nlmsg_type == NLMSG_ERROR) {
const struct nlmsgerr *e;
- e = buffer_at(buffer, NLMSG_HDRLEN,
+ e = ofpbuf_at(buffer, NLMSG_HDRLEN,
NLMSG_ALIGN(sizeof(struct nlmsgerr)));
if (e) {
ds_put_format(&ds, " error(%d", e->error);
ds_put_cstr(&ds, " error(truncated)");
}
} else if (h->nlmsg_type == NLMSG_DONE) {
- int *error = buffer_at(buffer, NLMSG_HDRLEN, sizeof *error);
+ int *error = ofpbuf_at(buffer, NLMSG_HDRLEN, sizeof *error);
if (error) {
ds_put_format(&ds, " done(%d", *error);
if (*error < 0) {
log_nlmsg(const char *function, int error,
const void *message, size_t size)
{
- struct buffer buffer;
+ struct ofpbuf buffer;
char *nlmsg;
if (!VLOG_IS_DBG_ENABLED()) {
#include <stdlib.h>
#include <ctype.h>
-#include "buffer.h"
#include "compiler.h"
#include "dynamic-string.h"
#include "flow.h"
-#include "util.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "packets.h"
+#include "util.h"
static void ofp_print_port_name(struct ds *string, uint16_t port);
static void ofp_print_match(struct ds *, const struct ofp_match *,
pcap = tmpfile();
if (!pcap) {
- error(errno, "tmpfile");
+ ofp_error(errno, "tmpfile");
return xstrdup("<error>");
}
fflush(pcap);
if (ferror(pcap)) {
- error(errno, "error writing temporary file");
+ ofp_error(errno, "error writing temporary file");
}
rewind(pcap);
tcpdump = popen(command, "r");
fclose(pcap);
if (!tcpdump) {
- error(errno, "exec(\"%s\")", command);
+ ofp_error(errno, "exec(\"%s\")", command);
return xstrdup("<error>");
}
status = pclose(tcpdump);
if (WIFEXITED(status)) {
if (WEXITSTATUS(status))
- error(0, "tcpdump exited with status %d", WEXITSTATUS(status));
+ ofp_error(0, "tcpdump exited with status %d", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
- error(0, "tcpdump exited with signal %d", WTERMSIG(status));
+ ofp_error(0, "tcpdump exited with signal %d", WTERMSIG(status));
}
return ds_cstr(&ds);
}
if (verbosity > 0) {
struct flow flow;
- struct buffer packet;
+ struct ofpbuf packet;
struct ofp_match match;
packet.data = (void *) op->data;
packet.size = data_len;
};
struct stats_type {
+ int type;
const char *name;
struct stats_msg request;
struct stats_msg reply;
};
static const struct stats_type stats_types[] = {
- [OFPST_DESC] = {
+ {
+ OFPST_DESC,
"description",
{ 0, 0, NULL },
{ 0, SIZE_MAX, ofp_desc_stats_reply },
},
- [OFPST_FLOW] = {
+ {
+ OFPST_FLOW,
"flow",
{ sizeof(struct ofp_flow_stats_request),
sizeof(struct ofp_flow_stats_request),
ofp_flow_stats_request },
{ 0, SIZE_MAX, ofp_flow_stats_reply },
},
- [OFPST_AGGREGATE] = {
+ {
+ OFPST_AGGREGATE,
"aggregate",
{ sizeof(struct ofp_aggregate_stats_request),
sizeof(struct ofp_aggregate_stats_request),
sizeof(struct ofp_aggregate_stats_reply),
ofp_aggregate_stats_reply },
},
- [OFPST_TABLE] = {
+ {
+ OFPST_TABLE,
"table",
{ 0, 0, NULL },
{ 0, SIZE_MAX, ofp_table_stats_reply },
},
- [OFPST_PORT] = {
+ {
+ OFPST_PORT,
"port",
{ 0, 0, NULL, },
{ 0, SIZE_MAX, ofp_port_stats_reply },
},
- [OFPST_VENDOR] = {
+ {
+ OFPST_VENDOR,
"vendor-specific",
{ sizeof(uint32_t), SIZE_MAX, vendor_stat },
{ sizeof(uint32_t), SIZE_MAX, vendor_stat },
},
+ {
+ -1,
+ "unknown",
+ { 0, 0, NULL, },
+ { 0, 0, NULL, },
+ },
};
const struct stats_type *s;
ds_put_format(string, " ***unknown type %d***", type);
return;
}
- s = &stats_types[type];
+ for (s = stats_types; s->type >= 0; s++) {
+ if (s->type == type) {
+ break;
+ }
+ }
ds_put_format(string, " type=%d(%s)\n", type, s->name);
m = direction == REQUEST ? &s->request : &s->reply;
}
struct openflow_packet {
+ uint8_t type;
const char *name;
size_t min_size;
void (*printer)(struct ds *, const void *, size_t len, int verbosity);
};
static const struct openflow_packet packets[] = {
- [OFPT_HELLO] = {
+ {
+ OFPT_HELLO,
"hello",
sizeof (struct ofp_header),
NULL,
},
- [OFPT_FEATURES_REQUEST] = {
+ {
+ OFPT_FEATURES_REQUEST,
"features_request",
sizeof (struct ofp_header),
NULL,
},
- [OFPT_FEATURES_REPLY] = {
+ {
+ OFPT_FEATURES_REPLY,
"features_reply",
sizeof (struct ofp_switch_features),
ofp_print_switch_features,
},
- [OFPT_GET_CONFIG_REQUEST] = {
+ {
+ OFPT_GET_CONFIG_REQUEST,
"get_config_request",
sizeof (struct ofp_header),
NULL,
},
- [OFPT_GET_CONFIG_REPLY] = {
+ {
+ OFPT_GET_CONFIG_REPLY,
"get_config_reply",
sizeof (struct ofp_switch_config),
ofp_print_switch_config,
},
- [OFPT_SET_CONFIG] = {
+ {
+ OFPT_SET_CONFIG,
"set_config",
sizeof (struct ofp_switch_config),
ofp_print_switch_config,
},
- [OFPT_PACKET_IN] = {
+ {
+ OFPT_PACKET_IN,
"packet_in",
offsetof(struct ofp_packet_in, data),
ofp_packet_in,
},
- [OFPT_PACKET_OUT] = {
+ {
+ OFPT_PACKET_OUT,
"packet_out",
sizeof (struct ofp_packet_out),
ofp_packet_out,
},
- [OFPT_FLOW_MOD] = {
+ {
+ OFPT_FLOW_MOD,
"flow_mod",
sizeof (struct ofp_flow_mod),
ofp_print_flow_mod,
},
- [OFPT_FLOW_EXPIRED] = {
+ {
+ OFPT_FLOW_EXPIRED,
"flow_expired",
sizeof (struct ofp_flow_expired),
ofp_print_flow_expired,
},
- [OFPT_PORT_MOD] = {
+ {
+ OFPT_PORT_MOD,
"port_mod",
sizeof (struct ofp_port_mod),
NULL,
},
- [OFPT_PORT_STATUS] = {
+ {
+ OFPT_PORT_STATUS,
"port_status",
sizeof (struct ofp_port_status),
ofp_print_port_status
},
- [OFPT_ERROR] = {
+ {
+ OFPT_ERROR,
"error_msg",
sizeof (struct ofp_error_msg),
ofp_print_error_msg,
},
- [OFPT_STATS_REQUEST] = {
+ {
+ OFPT_STATS_REQUEST,
"stats_request",
sizeof (struct ofp_stats_request),
ofp_stats_request,
},
- [OFPT_STATS_REPLY] = {
+ {
+ OFPT_STATS_REPLY,
"stats_reply",
sizeof (struct ofp_stats_reply),
ofp_stats_reply,
},
- [OFPT_ECHO_REQUEST] = {
+ {
+ OFPT_ECHO_REQUEST,
"echo_request",
sizeof (struct ofp_header),
ofp_echo,
},
- [OFPT_ECHO_REPLY] = {
+ {
+ OFPT_ECHO_REPLY,
"echo_reply",
sizeof (struct ofp_header),
ofp_echo,
ds_put_format(&string, "Bad OpenFlow version %"PRIu8":\n", oh->version);
ds_put_hex_dump(&string, oh, len, 0, true);
return ds_cstr(&string);
- } else if (oh->type >= ARRAY_SIZE(packets) || !packets[oh->type].name) {
- ds_put_format(&string, "Unknown OpenFlow packet type %"PRIu8":\n",
- oh->type);
- ds_put_hex_dump(&string, oh, len, 0, true);
- return ds_cstr(&string);
}
- pkt = &packets[oh->type];
+ for (pkt = packets; ; pkt++) {
+ if (pkt >= &packets[ARRAY_SIZE(packets)]) {
+ ds_put_format(&string, "Unknown OpenFlow packet type %"PRIu8":\n",
+ oh->type);
+ ds_put_hex_dump(&string, oh, len, 0, true);
+ return ds_cstr(&string);
+ } else if (oh->type == pkt->type) {
+ break;
+ }
+ }
+
ds_put_format(&string, "%s (xid=0x%"PRIx32"):", pkt->name, oh->xid);
if (ntohs(oh->length) > len)
--- /dev/null
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#include <config.h>
+#include "ofpbuf.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "util.h"
+
+/* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
+ * memory starting at 'base'.
+ *
+ * 'base' should ordinarily be the first byte of a region obtained from
+ * malloc(), but in circumstances where it can be guaranteed that 'b' will
+ * never need to be expanded or freed, it can be a pointer into arbitrary
+ * memory. */
+void
+ofpbuf_use(struct ofpbuf *b, void *base, size_t allocated)
+{
+ b->base = b->data = base;
+ b->allocated = allocated;
+ b->size = 0;
+ b->l2 = b->l3 = b->l4 = b->l7 = NULL;
+ b->next = NULL;
+ b->private = NULL;
+}
+
+/* Initializes 'b' as an empty ofpbuf with an initial capacity of 'size'
+ * bytes. */
+void
+ofpbuf_init(struct ofpbuf *b, size_t size)
+{
+ ofpbuf_use(b, size ? xmalloc(size) : NULL, size);
+}
+
+/* Frees memory that 'b' points to. */
+void
+ofpbuf_uninit(struct ofpbuf *b)
+{
+ if (b) {
+ free(b->base);
+ }
+}
+
+/* Frees memory that 'b' points to and allocates a new ofpbuf */
+void
+ofpbuf_reinit(struct ofpbuf *b, size_t size)
+{
+ ofpbuf_uninit(b);
+ ofpbuf_init(b, size);
+}
+
+/* Creates and returns a new ofpbuf with an initial capacity of 'size'
+ * bytes. */
+struct ofpbuf *
+ofpbuf_new(size_t size)
+{
+ struct ofpbuf *b = xmalloc(sizeof *b);
+ ofpbuf_init(b, size);
+ return b;
+}
+
+struct ofpbuf *
+ofpbuf_clone(const struct ofpbuf *buffer)
+{
+ /* FIXME: reference counting. */
+ struct ofpbuf *b = ofpbuf_new(buffer->size);
+ ofpbuf_put(b, buffer->data, buffer->size);
+ return b;
+}
+
+/* Frees memory that 'b' points to, as well as 'b' itself. */
+void
+ofpbuf_delete(struct ofpbuf *b)
+{
+ if (b) {
+ ofpbuf_uninit(b);
+ free(b);
+ }
+}
+
+/* Returns the number of bytes of headroom in 'b', that is, the number of bytes
+ * of unused space in ofpbuf 'b' before the data that is in use. (Most
+ * 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)
+{
+ return (char*)b->data - (char*)b->base;
+}
+
+/* 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)
+{
+ return (char*)ofpbuf_end(b) - (char*)ofpbuf_tail(b);
+}
+
+/* Ensures that 'b' has room for at least 'size' bytes at its tail end,
+ * reallocating and copying its data if necessary. */
+void
+ofpbuf_prealloc_tailroom(struct ofpbuf *b, size_t size)
+{
+ if (size > ofpbuf_tailroom(b)) {
+ size_t new_allocated = b->allocated + MAX(size, 64);
+ void *new_base = xmalloc(new_allocated);
+ uintptr_t base_delta = (char*)new_base - (char*)b->base;
+ memcpy(new_base, b->base, b->allocated);
+ free(b->base);
+ b->base = new_base;
+ b->allocated = new_allocated;
+ b->data = (char*)b->data + base_delta;
+ if (b->l2) {
+ b->l2 = (char*)b->l2 + base_delta;
+ }
+ if (b->l3) {
+ b->l3 = (char*)b->l3 + base_delta;
+ }
+ if (b->l4) {
+ b->l4 = (char*)b->l4 + base_delta;
+ }
+ if (b->l7) {
+ b->l7 = (char*)b->l7 + base_delta;
+ }
+ }
+}
+
+void
+ofpbuf_prealloc_headroom(struct ofpbuf *b, size_t size)
+{
+ assert(size <= ofpbuf_headroom(b));
+}
+
+/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
+ * copying its data if necessary. Returns a pointer to the first byte of the
+ * new data, which is left uninitialized. */
+void *
+ofpbuf_put_uninit(struct ofpbuf *b, size_t size)
+{
+ void *p;
+ ofpbuf_prealloc_tailroom(b, size);
+ p = ofpbuf_tail(b);
+ b->size += size;
+ return p;
+}
+
+/* Appends the 'size' bytes of data in 'p' to the tail end of 'b'. Data in 'b'
+ * is reallocated and copied if necessary. Returns a pointer to the first
+ * byte of the data's location in the ofpbuf. */
+void *
+ofpbuf_put(struct ofpbuf *b, const void *p, size_t size)
+{
+ void *dst = ofpbuf_put_uninit(b, size);
+ memcpy(dst, p, size);
+ return dst;
+}
+
+/* Reserves 'size' bytes of headroom so that they can be later allocated with
+ * ofpbuf_push_uninit() without reallocating the ofpbuf. */
+void
+ofpbuf_reserve(struct ofpbuf *b, size_t size)
+{
+ assert(!b->size);
+ ofpbuf_prealloc_tailroom(b, size);
+ b->data = (char*)b->data + size;
+}
+
+void *
+ofpbuf_push_uninit(struct ofpbuf *b, size_t size)
+{
+ ofpbuf_prealloc_headroom(b, size);
+ b->data = (char*)b->data - size;
+ b->size += size;
+ return b->data;
+}
+
+void *
+ofpbuf_push(struct ofpbuf *b, const void *p, size_t size)
+{
+ void *dst = ofpbuf_push_uninit(b, size);
+ memcpy(dst, p, size);
+ return dst;
+}
+
+/* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
+ * byte 'offset'. Otherwise, returns a null pointer. */
+void *
+ofpbuf_at(const struct ofpbuf *b, size_t offset, size_t size)
+{
+ return offset + size <= b->size ? (char *) b->data + offset : NULL;
+}
+
+/* Returns a pointer to byte 'offset' in 'b', which must contain at least
+ * 'offset + size' bytes of data. */
+void *
+ofpbuf_at_assert(const struct ofpbuf *b, size_t offset, size_t size)
+{
+ assert(offset + size <= b->size);
+ return ((char *) b->data) + offset;
+}
+
+/* Returns the byte following the last byte of data in use in 'b'. */
+void *
+ofpbuf_tail(const struct ofpbuf *b)
+{
+ return (char *) b->data + b->size;
+}
+
+/* Returns the byte following the last byte allocated for use (but not
+ * necessarily in use) by 'b'. */
+void *
+ofpbuf_end(const struct ofpbuf *b)
+{
+ return (char *) b->base + b->allocated;
+}
+
+/* Clears any data from 'b'. */
+void
+ofpbuf_clear(struct ofpbuf *b)
+{
+ b->data = b->base;
+ b->size = 0;
+}
+
+/* Removes 'size' bytes from the head end of 'b', which must contain at least
+ * 'size' bytes of data. Returns the first byte of data removed. */
+void *
+ofpbuf_pull(struct ofpbuf *b, size_t size)
+{
+ void *data = b->data;
+ assert(b->size >= size);
+ b->data = (char*)b->data + size;
+ b->size -= size;
+ return data;
+}
+
+/* If 'b' has at least 'size' bytes of data, removes that many bytes from the
+ * head end of 'b' and returns the first byte removed. Otherwise, returns a
+ * null pointer without modifying 'b'. */
+void *
+ofpbuf_try_pull(struct ofpbuf *b, size_t size)
+{
+ return b->size >= size ? ofpbuf_pull(b, size) : NULL;
+}
#include <config.h>
#include "queue.h"
#include <assert.h>
-#include "buffer.h"
+#include "ofpbuf.h"
-static void check_queue(struct queue *q);
+static void check_queue(struct ofp_queue *q);
/* Initializes 'q' as an empty packet queue. */
void
-queue_init(struct queue *q)
+queue_init(struct ofp_queue *q)
{
q->n = 0;
q->head = NULL;
/* Destroys 'q' and all of the packets that it contains. */
void
-queue_destroy(struct queue *q)
+queue_destroy(struct ofp_queue *q)
{
- struct buffer *cur, *next;
+ struct ofpbuf *cur, *next;
for (cur = q->head; cur != NULL; cur = next) {
next = cur->next;
- buffer_delete(cur);
+ ofpbuf_delete(cur);
}
}
/* Removes and destroys all of the packets in 'q', rendering it empty. */
void
-queue_clear(struct queue *q)
+queue_clear(struct ofp_queue *q)
{
queue_destroy(q);
queue_init(q);
* passed to a function for possible consumption (and destruction) and only
* dropped from the queue if that function actually accepts it. */
void
-queue_advance_head(struct queue *q, struct buffer *next)
+queue_advance_head(struct ofp_queue *q, struct ofpbuf *next)
{
assert(q->n);
assert(q->head);
/* Appends 'b' to the tail of 'q'. */
void
-queue_push_tail(struct queue *q, struct buffer *b)
+queue_push_tail(struct ofp_queue *q, struct ofpbuf *b)
{
check_queue(q);
}
/* Removes the first buffer from 'q', which must not be empty, and returns
- * it. The caller must free the buffer (with buffer_delete()) when it is no
+ * it. The caller must free the buffer (with ofpbuf_delete()) when it is no
* longer needed. */
-struct buffer *
-queue_pop_head(struct queue *q)
+struct ofpbuf *
+queue_pop_head(struct ofp_queue *q)
{
- struct buffer *head = q->head;
+ struct ofpbuf *head = q->head;
queue_advance_head(q, head->next);
return head;
}
/* Checks the internal integrity of 'q'. For use in debugging. */
static void
-check_queue(struct queue *q)
+check_queue(struct ofp_queue *q)
{
#if 0
- struct buffer *iter;
+ struct ofpbuf *iter;
size_t n;
assert(q->n == 0
struct timeval tv;
inited = true;
if (gettimeofday(&tv, NULL) < 0) {
- fatal(errno, "gettimeofday");
+ ofp_fatal(errno, "gettimeofday");
}
srand(tv.tv_sec ^ tv.tv_usec);
}
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include "buffer.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "poll-loop.h"
-#include "ofp-print.h"
#include "sat-math.h"
#include "timeval.h"
#include "util.h"
char *name;
bool reliable;
- struct queue txq;
+ struct ofp_queue txq;
int backoff;
int max_backoff;
static void disconnect(struct rconn *, int error);
static void flush_queue(struct rconn *);
static void question_connectivity(struct rconn *);
-static void copy_to_monitor(struct rconn *, const struct buffer *);
+static void copy_to_monitor(struct rconn *, const struct ofpbuf *);
/* Creates a new rconn, connects it (reliably) to 'name', and returns it. */
struct rconn *
/* Attempts to receive a packet from 'rc'. If successful, returns the packet;
* otherwise, returns a null pointer. The caller is responsible for freeing
- * the packet (with buffer_delete()). */
-struct buffer *
+ * the packet (with ofpbuf_delete()). */
+struct ofpbuf *
rconn_recv(struct rconn *rc)
{
if (rc->state & (S_ACTIVE | S_IDLE)) {
- struct buffer *buffer;
+ struct ofpbuf *buffer;
int error = vconn_recv(rc->vconn, &buffer);
if (!error) {
copy_to_monitor(rc, buffer);
* takes care of sending if you call rconn_run(), which will have the side
* effect of waking up poll_block(). */
int
-rconn_send(struct rconn *rc, struct buffer *b, int *n_queued)
+rconn_send(struct rconn *rc, struct ofpbuf *b, int *n_queued)
{
if (rconn_is_connected(rc)) {
copy_to_monitor(rc, b);
* takes care of sending if you call rconn_run(), which will have the side
* effect of waking up poll_block(). */
int
-rconn_send_with_limit(struct rconn *rc, struct buffer *b,
+rconn_send_with_limit(struct rconn *rc, struct ofpbuf *b,
int *n_queued, int queue_limit)
{
int retval;
retval = *n_queued >= queue_limit ? EAGAIN : rconn_send(rc, b, n_queued);
if (retval) {
- buffer_delete(b);
+ ofpbuf_delete(b);
}
return retval;
}
try_send(struct rconn *rc)
{
int retval = 0;
- struct buffer *next = rc->txq.head->next;
+ struct ofpbuf *next = rc->txq.head->next;
int *n_queued = rc->txq.head->private;
retval = vconn_send(rc->vconn, rc->txq.head);
if (retval) {
return;
}
while (rc->txq.n > 0) {
- struct buffer *b = queue_pop_head(&rc->txq);
+ struct ofpbuf *b = queue_pop_head(&rc->txq);
int *n_queued = b->private;
if (n_queued) {
--*n_queued;
}
- buffer_delete(b);
+ ofpbuf_delete(b);
}
poll_immediate_wake();
}
}
static void
-copy_to_monitor(struct rconn *rc, const struct buffer *b)
+copy_to_monitor(struct rconn *rc, const struct ofpbuf *b)
{
- struct buffer *clone = NULL;
+ struct ofpbuf *clone = NULL;
int retval;
size_t i;
struct vconn *vconn = rc->monitors[i];
if (!clone) {
- clone = buffer_clone(b);
+ clone = ofpbuf_clone(b);
}
retval = vconn_send(vconn, clone);
if (!retval) {
}
i++;
}
- buffer_delete(clone);
+ ofpbuf_delete(clone);
}
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGALRM, &sa, NULL)) {
- fatal(errno, "sigaction(SIGALRM) failed");
+ ofp_fatal(errno, "sigaction(SIGALRM) failed");
}
/* Set up periodic timer. */
itimer.it_interval.tv_usec = TIME_UPDATE_INTERVAL * 1000;
itimer.it_value = itimer.it_interval;
if (setitimer(ITIMER_REAL, &itimer, NULL)) {
- fatal(errno, "setitimer failed");
+ ofp_fatal(errno, "setitimer failed");
}
}
sigemptyset(&sigalrm);
sigaddset(&sigalrm, SIGALRM);
if (sigprocmask(SIG_BLOCK, &sigalrm, oldsigs)) {
- fatal(errno, "sigprocmask");
+ ofp_fatal(errno, "sigprocmask");
}
}
unblock_sigalrm(const sigset_t *oldsigs)
{
if (sigprocmask(SIG_SETMASK, oldsigs, NULL)) {
- fatal(errno, "sigprocmask");
+ ofp_fatal(errno, "sigprocmask");
}
}
static void
out_of_memory(void)
{
- fatal(0, "virtual memory exhausted");
+ ofp_fatal(0, "virtual memory exhausted");
}
void *
return s;
}
-void fatal(int err_no, const char *format, ...)
+void
+ofp_fatal(int err_no, const char *format, ...)
{
va_list args;
exit(EXIT_FAILURE);
}
-void error(int err_no, const char *format, ...)
-{
- va_list args;
-
- fprintf(stderr, "%s: ", program_name);
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- if (err_no != 0)
- fprintf(stderr, " (%s)", strerror(err_no));
- putc('\n', stderr);
-}
-
-void debug(int err_no, const char *format, ...)
+void
+ofp_error(int err_no, const char *format, ...)
{
va_list args;
* byte in 'buf'. If 'ascii' is true then the corresponding ASCII characters
* are also rendered alongside. */
void
-hex_dump(FILE *stream, const void *buf_, size_t size,
- uintptr_t ofs, bool ascii)
+ofp_hex_dump(FILE *stream, const void *buf_, size_t size,
+ uintptr_t ofs, bool ascii)
{
const uint8_t *buf = buf_;
const size_t per_line = 16; /* Maximum bytes per line. */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "openflow-netlink.h"
-#include "buffer.h"
#include "dpif.h"
#include "netlink.h"
+#include "ofpbuf.h"
+#include "openflow-netlink.h"
+#include "openflow.h"
#include "poll-loop.h"
#include "socket-util.h"
#include "util.h"
-#include "openflow.h"
#include "vconn-provider.h"
#include "vlog.h"
subscribe = 1;
if (sscanf(suffix, "%d:%d", &dp_idx, &subscribe) < 1) {
- error(0, "%s: syntax error", name);
+ ofp_error(0, "%s: syntax error", name);
return EAFNOSUPPORT;
}
}
static int
-netlink_recv(struct vconn *vconn, struct buffer **bufferp)
+netlink_recv(struct vconn *vconn, struct ofpbuf **bufferp)
{
struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
return dpif_recv_openflow(&netlink->dp, bufferp, false);
}
static int
-netlink_send(struct vconn *vconn, struct buffer *buffer)
+netlink_send(struct vconn *vconn, struct ofpbuf *buffer)
{
struct netlink_vconn *netlink = netlink_vconn_cast(vconn);
int retval = dpif_send_openflow(&netlink->dp, buffer, false);
if (!retval) {
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
}
return retval;
}
}
struct vconn_class netlink_vconn_class = {
- .name = "nl",
- .open = netlink_open,
- .close = netlink_close,
- .recv = netlink_recv,
- .send = netlink_send,
- .wait = netlink_wait,
+ "nl", /* name */
+ netlink_open, /* open */
+ netlink_close, /* close */
+ NULL, /* connect */
+ netlink_recv, /* recv */
+ netlink_send, /* send */
+ netlink_wait, /* wait */
};
#include <openssl/ssl.h>
#include <poll.h>
#include <unistd.h>
-#include "buffer.h"
+#include "ofpbuf.h"
#include "socket-util.h"
#include "util.h"
#include "openflow.h"
#include "packets.h"
#include "poll-loop.h"
-#include "ofp-print.h"
#include "socket-util.h"
#include "vconn.h"
#include "vconn-provider.h"
enum session_type type;
int fd;
SSL *ssl;
- struct buffer *rxbuf;
- struct buffer *txbuf;
+ struct ofpbuf *rxbuf;
+ struct ofpbuf *txbuf;
struct poll_waiter *tx_waiter;
/* rx_want and tx_want record the result of the last call to SSL_read()
host_name = strtok_r(suffix, "::", &save_ptr);
port_string = strtok_r(NULL, "::", &save_ptr);
if (!host_name) {
- error(0, "%s: bad peer name format", name);
+ ofp_error(0, "%s: bad peer name format", name);
return EAFNOSUPPORT;
}
}
static int
-ssl_recv(struct vconn *vconn, struct buffer **bufferp)
+ssl_recv(struct vconn *vconn, struct ofpbuf **bufferp)
{
struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
- struct buffer *rx;
+ struct ofpbuf *rx;
size_t want_bytes;
int old_state;
ssize_t ret;
if (sslv->rxbuf == NULL) {
- sslv->rxbuf = buffer_new(1564);
+ sslv->rxbuf = ofpbuf_new(1564);
}
rx = sslv->rxbuf;
return 0;
}
}
- buffer_prealloc_tailroom(rx, want_bytes);
+ ofpbuf_prealloc_tailroom(rx, want_bytes);
/* Behavior of zero-byte SSL_read is poorly defined. */
assert(want_bytes > 0);
old_state = SSL_get_state(sslv->ssl);
- ret = SSL_read(sslv->ssl, buffer_tail(rx), want_bytes);
+ ret = SSL_read(sslv->ssl, ofpbuf_tail(rx), want_bytes);
if (old_state != SSL_get_state(sslv->ssl)) {
sslv->tx_want = SSL_NOTHING;
if (sslv->tx_waiter) {
static void
ssl_clear_txbuf(struct ssl_vconn *sslv)
{
- buffer_delete(sslv->txbuf);
+ ofpbuf_delete(sslv->txbuf);
sslv->txbuf = NULL;
sslv->tx_waiter = NULL;
}
}
sslv->tx_want = SSL_NOTHING;
if (ret > 0) {
- buffer_pull(sslv->txbuf, ret);
+ ofpbuf_pull(sslv->txbuf, ret);
if (sslv->txbuf->size == 0) {
return 0;
}
}
static int
-ssl_send(struct vconn *vconn, struct buffer *buffer)
+ssl_send(struct vconn *vconn, struct ofpbuf *buffer)
{
struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
}
struct vconn_class ssl_vconn_class = {
- .name = "ssl",
- .open = ssl_open,
- .close = ssl_close,
- .connect = ssl_connect,
- .recv = ssl_recv,
- .send = ssl_send,
- .wait = ssl_wait,
+ "ssl", /* name */
+ ssl_open, /* open */
+ ssl_close, /* close */
+ ssl_connect, /* connect */
+ ssl_recv, /* recv */
+ ssl_send, /* send */
+ ssl_wait, /* wait */
};
\f
/* Passive SSL. */
if (!dh->dh) {
dh->dh = dh->constructor();
if (!dh->dh) {
- fatal(ENOMEM, "out of memory constructing "
- "Diffie-Hellman parameters");
+ ofp_fatal(ENOMEM, "out of memory constructing "
+ "Diffie-Hellman parameters");
}
}
return dh->dh;
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
-#include "buffer.h"
-#include "util.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "poll-loop.h"
#include "socket-util.h"
-#include "vconn.h"
+#include "util.h"
#include "vconn-provider.h"
+#include "vconn.h"
#include "vlog.h"
#define THIS_MODULE VLM_vconn_stream
{
struct vconn vconn;
int fd;
- struct buffer *rxbuf;
- struct buffer *txbuf;
+ struct ofpbuf *rxbuf;
+ struct ofpbuf *txbuf;
struct poll_waiter *tx_waiter;
};
}
static int
-stream_recv(struct vconn *vconn, struct buffer **bufferp)
+stream_recv(struct vconn *vconn, struct ofpbuf **bufferp)
{
struct stream_vconn *s = stream_vconn_cast(vconn);
- struct buffer *rx;
+ struct ofpbuf *rx;
size_t want_bytes;
ssize_t retval;
if (s->rxbuf == NULL) {
- s->rxbuf = buffer_new(1564);
+ s->rxbuf = ofpbuf_new(1564);
}
rx = s->rxbuf;
return 0;
}
}
- buffer_prealloc_tailroom(rx, want_bytes);
+ ofpbuf_prealloc_tailroom(rx, want_bytes);
- retval = read(s->fd, buffer_tail(rx), want_bytes);
+ retval = read(s->fd, ofpbuf_tail(rx), want_bytes);
if (retval > 0) {
rx->size += retval;
if (retval == want_bytes) {
static void
stream_clear_txbuf(struct stream_vconn *s)
{
- buffer_delete(s->txbuf);
+ ofpbuf_delete(s->txbuf);
s->txbuf = NULL;
s->tx_waiter = NULL;
}
return;
}
} else if (n > 0) {
- buffer_pull(s->txbuf, n);
+ ofpbuf_pull(s->txbuf, n);
if (!s->txbuf->size) {
stream_clear_txbuf(s);
return;
}
static int
-stream_send(struct vconn *vconn, struct buffer *buffer)
+stream_send(struct vconn *vconn, struct ofpbuf *buffer)
{
struct stream_vconn *s = stream_vconn_cast(vconn);
ssize_t retval;
retval = write(s->fd, buffer->data, buffer->size);
if (retval == buffer->size) {
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
return 0;
} else if (retval >= 0 || errno == EAGAIN) {
s->txbuf = buffer;
if (retval > 0) {
- buffer_pull(buffer, retval);
+ ofpbuf_pull(buffer, retval);
}
s->tx_waiter = poll_fd_callback(s->fd, POLLOUT, stream_do_tx, vconn);
return 0;
}
static struct vconn_class stream_vconn_class = {
- .name = "stream",
- .close = stream_close,
- .connect = stream_connect,
- .recv = stream_recv,
- .send = stream_send,
- .wait = stream_wait,
+ "stream", /* name */
+ NULL, /* open */
+ stream_close, /* close */
+ stream_connect, /* connect */
+ stream_recv, /* recv */
+ stream_send, /* send */
+ stream_wait, /* wait */
};
\f
/* Passive stream socket vconn. */
host_name = strtok_r(suffix, "::", &save_ptr);
port_string = strtok_r(NULL, "::", &save_ptr);
if (!host_name) {
- error(0, "%s: bad peer name format", name);
+ ofp_error(0, "%s: bad peer name format", name);
return EAFNOSUPPORT;
}
}
struct vconn_class tcp_vconn_class = {
- .name = "tcp",
- .open = tcp_open,
+ "tcp", /* name */
+ tcp_open, /* open */
+ NULL, /* close */
+ NULL, /* connect */
+ NULL, /* recv */
+ NULL, /* send */
+ NULL, /* wait */
};
\f
/* Passive TCP. */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "buffer.h"
-#include "socket-util.h"
-#include "util.h"
+#include "ofpbuf.h"
#include "openflow.h"
-#include "ofp-print.h"
#include "packets.h"
#include "poll-loop.h"
+#include "socket-util.h"
+#include "util.h"
#include "vconn-provider.h"
#include "vconn-stream.h"
}
struct vconn_class unix_vconn_class = {
- .name = "unix",
- .open = unix_open,
+ "unix", /* name */
+ unix_open, /* open */
+ NULL, /* close */
+ NULL, /* connect */
+ NULL, /* recv */
+ NULL, /* send */
+ NULL, /* wait */
};
\f
/* Passive UNIX socket. */
#include <poll.h>
#include <stdlib.h>
#include <string.h>
-#include "buffer.h"
#include "dynamic-string.h"
#include "flow.h"
#include "ofp-print.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "poll-loop.h"
#include "random.h"
* really need to see them. */
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(600, 600);
-static int do_recv(struct vconn *, struct buffer **);
-static int do_send(struct vconn *, struct buffer *);
+static int do_recv(struct vconn *, struct ofpbuf **);
+static int do_send(struct vconn *, struct ofpbuf *);
/* Check the validity of the vconn class structures. */
static void
static void
vcs_send_hello(struct vconn *vconn)
{
- struct buffer *b;
+ struct ofpbuf *b;
int retval;
make_openflow(sizeof(struct ofp_header), OFPT_HELLO, &b);
if (!retval) {
vconn->state = VCS_RECV_HELLO;
} else {
- buffer_delete(b);
+ ofpbuf_delete(b);
if (retval != EAGAIN) {
vconn->state = VCS_DISCONNECTED;
vconn->error = retval;
static void
vcs_recv_hello(struct vconn *vconn)
{
- struct buffer *b;
+ struct ofpbuf *b;
int retval;
retval = do_recv(vconn, &b);
OFP_VERSION, oh->version);
vconn->state = VCS_CONNECTED;
}
- buffer_delete(b);
+ ofpbuf_delete(b);
return;
} else {
char *s = ofp_to_string(b->data, b->size, 1);
vconn->name, s);
free(s);
retval = EPROTO;
- buffer_delete(b);
+ ofpbuf_delete(b);
}
}
vcs_send_error(struct vconn *vconn)
{
struct ofp_error_msg *error;
- struct buffer *b;
+ struct ofpbuf *b;
char s[128];
int retval;
error = make_openflow(sizeof *error, OFPT_ERROR, &b);
error->type = htons(OFPET_HELLO_FAILED);
error->code = htons(OFPHFC_INCOMPATIBLE);
- buffer_put(b, s, strlen(s));
+ ofpbuf_put(b, s, strlen(s));
retval = do_send(vconn, b);
if (retval) {
- buffer_delete(b);
+ ofpbuf_delete(b);
}
if (retval != EAGAIN) {
vconn->state = VCS_DISCONNECTED;
/* Tries to receive an OpenFlow message from 'vconn', which must be an active
* vconn. If successful, stores the received message into '*msgp' and returns
* 0. The caller is responsible for destroying the message with
- * buffer_delete(). On failure, returns a positive errno value and stores a
+ * ofpbuf_delete(). On failure, returns a positive errno value and stores a
* null pointer into '*msgp'. On normal connection close, returns EOF.
*
* vconn_recv will not block waiting for a packet to arrive. If no packets
* have been received, it returns EAGAIN immediately. */
int
-vconn_recv(struct vconn *vconn, struct buffer **msgp)
+vconn_recv(struct vconn *vconn, struct ofpbuf **msgp)
{
int retval = vconn_connect(vconn);
if (!retval) {
}
static int
-do_recv(struct vconn *vconn, struct buffer **msgp)
+do_recv(struct vconn *vconn, struct ofpbuf **msgp)
{
int retval;
free(s);
}
- oh = buffer_at_assert(*msgp, 0, sizeof *oh);
+ oh = ofpbuf_at_assert(*msgp, 0, sizeof *oh);
if (oh->version != vconn->version
&& oh->type != OFPT_HELLO
&& oh->type != OFPT_ERROR
"!= expected %02x",
vconn->name, oh->version, vconn->version);
}
- buffer_delete(*msgp);
+ ofpbuf_delete(*msgp);
retval = EPROTO;
}
}
* vconn_send will not block. If 'msg' cannot be immediately accepted for
* transmission, it returns EAGAIN immediately. */
int
-vconn_send(struct vconn *vconn, struct buffer *msg)
+vconn_send(struct vconn *vconn, struct ofpbuf *msg)
{
int retval = vconn_connect(vconn);
if (!retval) {
}
static int
-do_send(struct vconn *vconn, struct buffer *msg)
+do_send(struct vconn *vconn, struct ofpbuf *msg)
{
int retval;
/* Same as vconn_send, except that it waits until 'msg' can be transmitted. */
int
-vconn_send_block(struct vconn *vconn, struct buffer *msg)
+vconn_send_block(struct vconn *vconn, struct ofpbuf *msg)
{
int retval;
while ((retval = vconn_send(vconn, msg)) == EAGAIN) {
/* Same as vconn_recv, except that it waits until a message is received. */
int
-vconn_recv_block(struct vconn *vconn, struct buffer **msgp)
+vconn_recv_block(struct vconn *vconn, struct ofpbuf **msgp)
{
int retval;
while ((retval = vconn_recv(vconn, msgp)) == EAGAIN) {
*
* 'request' is always destroyed, regardless of the return value. */
int
-vconn_transact(struct vconn *vconn, struct buffer *request,
- struct buffer **replyp)
+vconn_transact(struct vconn *vconn, struct ofpbuf *request,
+ struct ofpbuf **replyp)
{
uint32_t send_xid = ((struct ofp_header *) request->data)->xid;
int error;
*replyp = NULL;
error = vconn_send_block(vconn, request);
if (error) {
- buffer_delete(request);
+ ofpbuf_delete(request);
return error;
}
for (;;) {
uint32_t recv_xid;
- struct buffer *reply;
+ struct ofpbuf *reply;
error = vconn_recv_block(vconn, &reply);
if (error) {
VLOG_DBG_RL(&rl, "%s: received reply with xid %08"PRIx32" != expected "
"%08"PRIx32, vconn->name, recv_xid, send_xid);
- buffer_delete(reply);
+ ofpbuf_delete(reply);
}
}
* id. Stores the new buffer in '*bufferp'. The caller must free the buffer
* when it is no longer needed. */
void *
-make_openflow(size_t openflow_len, uint8_t type, struct buffer **bufferp)
+make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **bufferp)
{
return make_openflow_xid(openflow_len, type, random_uint32(), bufferp);
}
* buffer when it is no longer needed. */
void *
make_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid,
- struct buffer **bufferp)
+ struct ofpbuf **bufferp)
{
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_header *oh;
assert(openflow_len >= sizeof *oh);
assert(openflow_len <= UINT16_MAX);
- buffer = *bufferp = buffer_new(openflow_len);
- oh = buffer_put_uninit(buffer, openflow_len);
+ buffer = *bufferp = ofpbuf_new(openflow_len);
+ oh = ofpbuf_put_uninit(buffer, openflow_len);
memset(oh, 0, openflow_len);
oh->version = OFP_VERSION;
oh->type = type;
/* Updates the 'length' field of the OpenFlow message in 'buffer' to
* 'buffer->size'. */
void
-update_openflow_length(struct buffer *buffer)
+update_openflow_length(struct ofpbuf *buffer)
{
- struct ofp_header *oh = buffer_at_assert(buffer, 0, sizeof *oh);
+ struct ofp_header *oh = ofpbuf_at_assert(buffer, 0, sizeof *oh);
oh->length = htons(buffer->size);
}
-struct buffer *
+struct ofpbuf *
make_add_flow(const struct flow *flow, uint32_t buffer_id,
uint16_t idle_timeout, size_t n_actions)
{
struct ofp_flow_mod *ofm;
size_t size = sizeof *ofm + n_actions * sizeof ofm->actions[0];
- struct buffer *out = buffer_new(size);
- ofm = buffer_put_uninit(out, size);
+ struct ofpbuf *out = ofpbuf_new(size);
+ ofm = ofpbuf_put_uninit(out, size);
memset(ofm, 0, size);
ofm->header.version = OFP_VERSION;
ofm->header.type = OFPT_FLOW_MOD;
return out;
}
-struct buffer *
+struct ofpbuf *
make_add_simple_flow(const struct flow *flow,
uint32_t buffer_id, uint16_t out_port,
uint16_t idle_timeout)
{
- struct buffer *buffer = make_add_flow(flow, buffer_id, idle_timeout, 1);
+ struct ofpbuf *buffer = make_add_flow(flow, buffer_id, idle_timeout, 1);
struct ofp_flow_mod *ofm = buffer->data;
ofm->actions[0].type = htons(OFPAT_OUTPUT);
ofm->actions[0].arg.output.max_len = htons(0);
return buffer;
}
-struct buffer *
-make_unbuffered_packet_out(const struct buffer *packet,
+struct ofpbuf *
+make_unbuffered_packet_out(const struct ofpbuf *packet,
uint16_t in_port, uint16_t out_port)
{
struct ofp_packet_out *opo;
size_t size = sizeof *opo + sizeof opo->actions[0];
- struct buffer *out = buffer_new(size + packet->size);
- opo = buffer_put_uninit(out, size);
+ struct ofpbuf *out = ofpbuf_new(size + packet->size);
+ opo = ofpbuf_put_uninit(out, size);
memset(opo, 0, size);
opo->header.version = OFP_VERSION;
opo->header.type = OFPT_PACKET_OUT;
opo->actions[0].type = htons(OFPAT_OUTPUT);
opo->actions[0].arg.output.max_len = htons(0);
opo->actions[0].arg.output.port = htons(out_port);
- buffer_put(out, packet->data, packet->size);
+ ofpbuf_put(out, packet->data, packet->size);
update_openflow_length(out);
return out;
}
-struct buffer *
+struct ofpbuf *
make_buffered_packet_out(uint32_t buffer_id,
uint16_t in_port, uint16_t out_port)
{
struct ofp_packet_out *opo;
size_t size = sizeof *opo + sizeof opo->actions[0];
- struct buffer *out = buffer_new(size);
- opo = buffer_put_uninit(out, size);
+ struct ofpbuf *out = ofpbuf_new(size);
+ opo = ofpbuf_put_uninit(out, size);
memset(opo, 0, size);
opo->header.version = OFP_VERSION;
opo->header.type = OFPT_PACKET_OUT;
}
/* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */
-struct buffer *
+struct ofpbuf *
make_echo_request(void)
{
struct ofp_header *rq;
- struct buffer *out = buffer_new(sizeof *rq);
- rq = buffer_put_uninit(out, sizeof *rq);
+ struct ofpbuf *out = ofpbuf_new(sizeof *rq);
+ rq = ofpbuf_put_uninit(out, sizeof *rq);
rq->version = OFP_VERSION;
rq->type = OFPT_ECHO_REQUEST;
rq->length = htons(sizeof *rq);
/* Creates and returns an OFPT_ECHO_REPLY message matching the
* OFPT_ECHO_REQUEST message in 'rq'. */
-struct buffer *
+struct ofpbuf *
make_echo_reply(const struct ofp_header *rq)
{
size_t size = ntohs(rq->length);
- struct buffer *out = buffer_new(size);
- struct ofp_header *reply = buffer_put(out, rq, size);
+ struct ofpbuf *out = ofpbuf_new(size);
+ struct ofp_header *reply = ofpbuf_put(out, rq, size);
reply->type = OFPT_ECHO_REPLY;
return out;
}
/* Name for each logging level. */
static const char *level_names[VLL_N_LEVELS] = {
- [VLL_EMER] = "EMER",
- [VLL_ERR] = "ERR",
- [VLL_WARN] = "WARN",
- [VLL_DBG] = "DBG",
+#define VLOG_LEVEL(NAME) #NAME,
+ VLOG_LEVELS
+#undef VLOG_LEVEL
};
/* Name for each logging facility. */
static const char *facility_names[VLF_N_FACILITIES] = {
- [VLF_CONSOLE] = "console",
- [VLF_SYSLOG] = "syslog",
+#define VLOG_FACILITY(NAME) #NAME,
+ VLOG_FACILITIES
+#undef VLOG_FACILITY
};
/* Name for each logging module */
if (arg) {
char *msg = vlog_set_levels_from_string(arg);
if (msg) {
- fatal(0, "processing \"%s\": %s", arg, msg);
+ ofp_fatal(0, "processing \"%s\": %s", arg, msg);
}
} else {
vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
}
if (log_syslog) {
- static const int syslog_levels[VLL_N_LEVELS] = {
- [VLL_EMER] = LOG_ALERT,
- [VLL_ERR] = LOG_ERR,
- [VLL_WARN] = LOG_WARNING,
- [VLL_DBG] = LOG_DEBUG,
- };
+ int syslog_level = LOG_ALERT;
char *save_ptr = NULL;
char *line;
+ switch (level) {
+ case VLL_EMER: syslog_level = LOG_ALERT; break;
+ case VLL_ERR: syslog_level = LOG_ERR; break;
+ case VLL_WARN: syslog_level = LOG_WARNING; break;
+ case VLL_DBG: syslog_level = LOG_DEBUG; break;
+ case VLL_N_LEVELS: NOT_REACHED();
+ }
for (line = strtok_r(&s.string[time_len], "\n", &save_ptr); line;
line = strtok_r(NULL, "\n", &save_ptr)) {
- syslog(syslog_levels[level], "%s", line);
+ syslog(syslog_level, "%s", line);
}
}
#include <time.h>
#include <unistd.h>
-#include "buffer.h"
#include "command-line.h"
#include "compiler.h"
#include "daemon.h"
-#include "dhcp.h"
#include "dhcp-client.h"
+#include "dhcp.h"
#include "dynamic-string.h"
#include "fault.h"
#include "flow.h"
#include "mac-learning.h"
#include "netdev.h"
#include "nicira-ext.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "packets.h"
#include "poll-loop.h"
struct half {
struct rconn *rconn;
- struct buffer *rxbuf;
+ struct ofpbuf *rxbuf;
int n_txq; /* No. of packets queued for tx on 'rconn'. */
};
static struct ofp_packet_in *get_ofp_packet_in(struct relay *);
static bool get_ofp_packet_eth_header(struct relay *, struct ofp_packet_in **,
struct eth_header **);
-static void get_ofp_packet_payload(struct ofp_packet_in *, struct buffer *);
+static void get_ofp_packet_payload(struct ofp_packet_in *, struct ofpbuf *);
struct switch_status;
struct status_reply;
/* Start listening for vlogconf requests. */
retval = vlog_server_listen(NULL, NULL);
if (retval) {
- fatal(retval, "Could not listen for vlog connections");
+ ofp_fatal(retval, "Could not listen for vlog connections");
}
die_if_already_running();
if (s.controller_name) {
retval = rconn_connect(remote_rconn, s.controller_name);
if (retval == EAFNOSUPPORT) {
- fatal(0, "No support for %s vconn", s.controller_name);
+ ofp_fatal(0, "No support for %s vconn", s.controller_name);
}
}
switch_status_register_category(switch_status, "remote",
retval = pvconn_open(name, &pvconn);
if (retval && retval != EAGAIN) {
- fatal(retval, "opening %s", name);
+ ofp_fatal(retval, "opening %s", name);
}
return pvconn;
}
static struct ofp_packet_in *
get_ofp_packet_in(struct relay *r)
{
- struct buffer *msg = r->halves[HALF_LOCAL].rxbuf;
+ struct ofpbuf *msg = r->halves[HALF_LOCAL].rxbuf;
struct ofp_header *oh = msg->data;
if (oh->type == OFPT_PACKET_IN) {
if (msg->size >= offsetof (struct ofp_packet_in, data)) {
const struct hook *h;
for (h = hooks; h < &hooks[n_hooks]; h++) {
if (h->packet_cb[i] && h->packet_cb[i](r, h->aux)) {
- buffer_delete(this->rxbuf);
+ ofpbuf_delete(this->rxbuf);
this->rxbuf = NULL;
progress = true;
break;
if (!retval) {
progress = true;
} else {
- buffer_delete(this->rxbuf);
+ ofpbuf_delete(this->rxbuf);
}
this->rxbuf = NULL;
}
for (i = 0; i < 2; i++) {
struct half *this = &r->halves[i];
rconn_destroy(this->rconn);
- buffer_delete(this->rxbuf);
+ ofpbuf_delete(this->rxbuf);
}
free(r);
}
port_watcher_local_packet_cb(struct relay *r, void *pw_)
{
struct port_watcher *pw = pw_;
- struct buffer *msg = r->halves[HALF_LOCAL].rxbuf;
+ struct ofpbuf *msg = r->halves[HALF_LOCAL].rxbuf;
struct ofp_header *oh = msg->data;
if (oh->type == OFPT_FEATURES_REPLY
port_watcher_remote_packet_cb(struct relay *r, void *pw_)
{
struct port_watcher *pw = pw_;
- struct buffer *msg = r->halves[HALF_REMOTE].rxbuf;
+ struct ofpbuf *msg = r->halves[HALF_REMOTE].rxbuf;
struct ofp_header *oh = msg->data;
if (oh->type == OFPT_PORT_MOD
struct port_watcher *pw = pw_;
if (!pw->got_feature_reply && time_now() >= pw->last_feature_request + 5) {
- struct buffer *b;
+ struct ofpbuf *b;
make_openflow(sizeof(struct ofp_header), OFPT_FEATURES_REQUEST, &b);
rconn_send_with_limit(pw->local_rconn, b, &pw->n_txq, 1);
pw->last_feature_request = time_now();
struct ofp_phy_port *p;
struct ofp_port_mod *opm;
struct ofp_port_status *ops;
- struct buffer *b;
+ struct ofpbuf *b;
int idx;
idx = port_no_to_pw_idx(port_no);
struct ofp_packet_in *opi;
struct eth_header *eth;
struct llc_header *llc;
- struct buffer payload;
+ struct ofpbuf payload;
uint16_t port_no;
struct flow flow;
VLOG_DBG("non-LLC frame received on STP multicast address");
return false;
}
- llc = buffer_at_assert(&payload, sizeof *eth, sizeof *llc);
+ llc = ofpbuf_at_assert(&payload, sizeof *eth, sizeof *llc);
if (llc->llc_dsap != STP_LLC_DSAP) {
VLOG_DBG("bad DSAP 0x%02"PRIx8" received on STP multicast address",
llc->llc_dsap);
if (payload.size > ntohs(eth->eth_type) + ETH_HEADER_LEN) {
payload.size = ntohs(eth->eth_type) + ETH_HEADER_LEN;
}
- if (buffer_try_pull(&payload, ETH_HEADER_LEN + LLC_HEADER_LEN)) {
+ if (ofpbuf_try_pull(&payload, ETH_HEADER_LEN + LLC_HEADER_LEN)) {
struct stp_port *p = stp_get_port(stp->stp, port_no);
stp_received_bpdu(p, payload.data, payload.size);
}
struct stp_data *stp = stp_;
struct eth_header *eth;
struct llc_header *llc;
- struct buffer pkt, *opo;
+ struct ofpbuf pkt, *opo;
/* Packet skeleton. */
- buffer_init(&pkt, ETH_HEADER_LEN + LLC_HEADER_LEN + bpdu_size);
- eth = buffer_put_uninit(&pkt, sizeof *eth);
- llc = buffer_put_uninit(&pkt, sizeof *llc);
- buffer_put(&pkt, bpdu, bpdu_size);
+ ofpbuf_init(&pkt, ETH_HEADER_LEN + LLC_HEADER_LEN + bpdu_size);
+ eth = ofpbuf_put_uninit(&pkt, sizeof *eth);
+ llc = ofpbuf_put_uninit(&pkt, sizeof *llc);
+ ofpbuf_put(&pkt, bpdu, bpdu_size);
/* 802.2 header. */
memcpy(eth->eth_dst, stp_eth_addr, ETH_ADDR_LEN);
llc->llc_cntl = STP_LLC_CNTL;
opo = make_unbuffered_packet_out(&pkt, OFPP_NONE, port_no);
- buffer_uninit(&pkt);
+ ofpbuf_uninit(&pkt);
rconn_send_with_limit(stp->local_rconn, opo, &stp->n_txq, OFPP_MAX);
}
retval = netdev_open(s->of_name, NETDEV_ETH_TYPE_NONE, &netdev);
if (retval) {
- fatal(retval, "Could not open %s device", s->of_name);
+ ofp_fatal(retval, "Could not open %s device", s->of_name);
}
memcpy(dpid, netdev_get_etheraddr(netdev), ETH_ADDR_LEN);
netdev_close(netdev);
};
static void
-queue_tx(struct rconn *rc, struct in_band_data *in_band, struct buffer *b)
+queue_tx(struct rconn *rc, struct in_band_data *in_band, struct ofpbuf *b)
{
rconn_send_with_limit(rc, b, &in_band->n_queued, 10);
}
struct rconn *rc = r->halves[HALF_LOCAL].rconn;
struct ofp_packet_in *opi;
struct eth_header *eth;
- struct buffer payload;
+ struct ofpbuf payload;
struct flow flow;
uint16_t in_port;
int out_port;
} else {
/* We don't know that MAC. Send along the packet without setting up a
* flow. */
- struct buffer *b;
+ struct ofpbuf *b;
if (ntohl(opi->buffer_id) == UINT32_MAX) {
b = make_unbuffered_packet_out(&payload, in_port, out_port);
} else {
}
static void
-get_ofp_packet_payload(struct ofp_packet_in *opi, struct buffer *payload)
+get_ofp_packet_payload(struct ofp_packet_in *opi, struct ofpbuf *payload)
{
payload->data = opi->data;
payload->size = ntohs(opi->header.length) - offsetof(struct ofp_packet_in,
retval = netdev_open(s->of_name, NETDEV_ETH_TYPE_NONE,
&in_band->of_device);
if (retval) {
- fatal(retval, "Could not open %s device", s->of_name);
+ ofp_fatal(retval, "Could not open %s device", s->of_name);
}
memcpy(in_band->mac, netdev_get_etheraddr(in_band->of_device),
ETH_ADDR_LEN);
struct rconn *remote_rconn;
/* One queue per physical port. */
- struct queue queues[OFPP_MAX];
+ struct ofp_queue queues[OFPP_MAX];
int n_queued; /* Sum over queues[*].n. */
int next_tx_port; /* Next port to check in round-robin. */
static void
drop_packet(struct rate_limiter *rl)
{
- struct queue *longest; /* Queue currently selected as longest. */
+ struct ofp_queue *longest; /* Queue currently selected as longest. */
int n_longest; /* # of queues of same length as 'longest'. */
- struct queue *q;
+ struct ofp_queue *q;
longest = &rl->queues[0];
n_longest = 1;
}
/* FIXME: do we want to pop the tail instead? */
- buffer_delete(queue_pop_head(longest));
+ ofpbuf_delete(queue_pop_head(longest));
rl->n_queued--;
}
/* Remove and return the next packet to transmit (in round-robin order). */
-static struct buffer *
+static struct ofpbuf *
dequeue_packet(struct rate_limiter *rl)
{
unsigned int i;
for (i = 0; i < OFPP_MAX; i++) {
unsigned int port = (rl->next_tx_port + i) % OFPP_MAX;
- struct queue *q = &rl->queues[port];
+ struct ofp_queue *q = &rl->queues[port];
if (q->n) {
rl->next_tx_port = (port + 1) % OFPP_MAX;
rl->n_queued--;
return false;
} else {
/* Otherwise queue it up for the periodic callback to drain out. */
- struct buffer *msg = r->halves[HALF_LOCAL].rxbuf;
+ struct ofpbuf *msg = r->halves[HALF_LOCAL].rxbuf;
int port = ntohs(opi->in_port) % OFPP_MAX;
if (rl->n_queued >= s->burst_limit) {
drop_packet(rl);
}
- queue_push_tail(&rl->queues[port], buffer_clone(msg));
+ queue_push_tail(&rl->queues[port], ofpbuf_clone(msg));
rl->n_queued++;
rl->n_limited++;
return true;
* because the TCP connection is responsible for buffering and there is
* no point in trying to transmit faster than the TCP connection can
* handle. */
- struct buffer *b = dequeue_packet(rl);
+ struct ofpbuf *b = dequeue_packet(rl);
if (rconn_send_with_limit(rl->remote_rconn, b, &rl->n_txq, 10)) {
rl->n_tx_dropped++;
}
{
struct switch_status *ss = ss_;
struct rconn *rc = r->halves[HALF_REMOTE].rconn;
- struct buffer *msg = r->halves[HALF_REMOTE].rxbuf;
+ struct ofpbuf *msg = r->halves[HALF_REMOTE].rxbuf;
struct switch_status_category *c;
struct nicira_header *request;
struct nicira_header *reply;
struct status_reply sr;
- struct buffer *b;
+ struct ofpbuf *b;
int retval;
if (msg->size < sizeof(struct nicira_header)) {
/* Bring ofX network device up. */
retval = netdev_open(s->of_name, NETDEV_ETH_TYPE_NONE, &netdev);
if (retval) {
- fatal(retval, "Could not open %s device", s->of_name);
+ ofp_fatal(retval, "Could not open %s device", s->of_name);
}
retval = netdev_turn_flags_on(netdev, NETDEV_UP, true);
if (retval) {
- fatal(retval, "Could not bring %s device up", s->of_name);
+ ofp_fatal(retval, "Could not bring %s device up", s->of_name);
}
netdev_close(netdev);
retval = dhclient_create(s->of_name, modify_dhcp_request,
validate_dhcp_offer, (void *) s, &dhcp);
if (retval) {
- fatal(retval, "Failed to initialize DHCP client");
+ ofp_fatal(retval, "Failed to initialize DHCP client");
}
dhclient_init(dhcp, 0);
} else if (!strcmp(optarg, "closed")) {
s->fail_mode = FAIL_CLOSED;
} else {
- fatal(0,
- "-f or --fail argument must be \"open\" or \"closed\"");
+ ofp_fatal(0, "-f or --fail argument must be \"open\" "
+ "or \"closed\"");
}
break;
case OPT_INACTIVITY_PROBE:
s->probe_interval = atoi(optarg);
if (s->probe_interval < 5) {
- fatal(0, "--inactivity-probe argument must be at least 5");
+ ofp_fatal(0, "--inactivity-probe argument must be at least 5");
}
break;
} else {
s->max_idle = atoi(optarg);
if (s->max_idle < 1 || s->max_idle > 65535) {
- fatal(0, "--max-idle argument must be between 1 and "
- "65535 or the word 'permanent'");
+ ofp_fatal(0, "--max-idle argument must be between 1 and "
+ "65535 or the word 'permanent'");
}
}
break;
case OPT_MAX_BACKOFF:
s->max_backoff = atoi(optarg);
if (s->max_backoff < 1) {
- fatal(0, "--max-backoff argument must be at least 1");
+ ofp_fatal(0, "--max-backoff argument must be at least 1");
} else if (s->max_backoff > 3600) {
s->max_backoff = 3600;
}
if (optarg) {
s->rate_limit = atoi(optarg);
if (s->rate_limit < 1) {
- fatal(0, "--rate-limit argument must be at least 1");
+ ofp_fatal(0, "--rate-limit argument must be at least 1");
}
} else {
s->rate_limit = 1000;
case OPT_BURST_LIMIT:
s->burst_limit = atoi(optarg);
if (s->burst_limit < 1) {
- fatal(0, "--burst-limit argument must be at least 1");
+ ofp_fatal(0, "--burst-limit argument must be at least 1");
}
break;
case 'l':
if (s->n_listeners >= MAX_MGMT) {
- fatal(0, "-l or --listen may be specified at most %d times",
- MAX_MGMT);
+ ofp_fatal(0,
+ "-l or --listen may be specified at most %d times",
+ MAX_MGMT);
}
s->listener_names[s->n_listeners++] = optarg;
break;
case 'm':
if (s->monitor_name) {
- fatal(0, "-m or --monitor may only be specified once");
+ ofp_fatal(0, "-m or --monitor may only be specified once");
}
s->monitor_name = optarg;
break;
argc -= optind;
argv += optind;
if (argc < 1 || argc > 2) {
- fatal(0, "need one or two non-option arguments; use --help for usage");
+ ofp_fatal(0, "need one or two non-option arguments; "
+ "use --help for usage");
}
/* Local and remote vconns. */
if (strncmp(s->nl_name, "nl:", 3)
|| strlen(s->nl_name) < 4
|| s->nl_name[strspn(s->nl_name + 3, "0123456789") + 3]) {
- fatal(0, "%s: argument is not of the form \"nl:DP_IDX\"", s->nl_name);
+ ofp_fatal(0, "%s: argument is not of the form \"nl:DP_IDX\"",
+ s->nl_name);
}
s->of_name = xasprintf("of%s", s->nl_name + 3);
s->controller_name = argc > 1 ? xstrdup(argv[1]) : NULL;
size_t length = regerror(retval, &s->accept_controller_regex, NULL, 0);
char *buffer = xmalloc(length);
regerror(retval, &s->accept_controller_regex, buffer, length);
- fatal(0, "%s: %s", accept_re, buffer);
+ ofp_fatal(0, "%s: %s", accept_re, buffer);
}
s->accept_controller_re = accept_re;
retval = netdev_open(s->of_name, NETDEV_ETH_TYPE_NONE, &netdev);
if (retval) {
- fatal(retval, "Could not open %s device", s->of_name);
+ ofp_fatal(retval, "Could not open %s device", s->of_name);
}
retval = netdev_get_flags(netdev, &flags);
if (retval) {
- fatal(retval, "Could not get flags for %s device", s->of_name);
+ ofp_fatal(retval, "Could not get flags for %s device", s->of_name);
}
s->in_band = (flags & NETDEV_UP) != 0;
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
-#include "buffer.h"
#include "chain.h"
#include "csum.h"
#include "flow.h"
+#include "list.h"
#include "netdev.h"
+#include "ofpbuf.h"
+#include "openflow.h"
#include "packets.h"
#include "poll-loop.h"
#include "rconn.h"
#include "stp.h"
-#include "vconn.h"
+#include "switch-flow.h"
#include "table.h"
#include "timeval.h"
+#include "vconn.h"
#include "xtoxll.h"
#define THIS_MODULE VLM_datapath
static void remote_wait(struct remote *);
static void remote_destroy(struct remote *);
-void dp_output_port(struct datapath *, struct buffer *,
+void dp_output_port(struct datapath *, struct ofpbuf *,
int in_port, int out_port, bool ignore_no_fwd);
void dp_update_port_flags(struct datapath *dp, const struct ofp_port_mod *opm);
-void dp_output_control(struct datapath *, struct buffer *, int in_port,
+void dp_output_control(struct datapath *, struct ofpbuf *, int in_port,
size_t max_len, int reason);
static void send_flow_expired(struct datapath *, struct sw_flow *,
enum ofp_flow_expired_reason);
static int update_port_status(struct sw_port *p);
static void send_port_status(struct sw_port *p, uint8_t status);
static void del_switch_port(struct sw_port *p);
-static void execute_actions(struct datapath *, struct buffer *,
+static void execute_actions(struct datapath *, struct ofpbuf *,
int in_port, const struct sw_flow_key *,
const struct ofp_action *, int n_actions,
bool ignore_no_fwd);
-static void modify_vlan(struct buffer *buffer, const struct sw_flow_key *key,
+static void modify_vlan(struct ofpbuf *buffer, const struct sw_flow_key *key,
const struct ofp_action *a);
-static void modify_nh(struct buffer *buffer, uint16_t eth_proto,
+static void modify_nh(struct ofpbuf *buffer, uint16_t eth_proto,
uint8_t nw_proto, const struct ofp_action *a);
-static void modify_th(struct buffer *buffer, uint16_t eth_proto,
+static void modify_th(struct ofpbuf *buffer, uint16_t eth_proto,
uint8_t nw_proto, const struct ofp_action *a);
/* Buffers are identified to userspace by a 31-bit opaque ID. We divide the ID
#define PKT_COOKIE_BITS (32 - PKT_BUFFER_BITS)
-int run_flow_through_tables(struct datapath *, struct buffer *,
+int run_flow_through_tables(struct datapath *, struct ofpbuf *,
struct sw_port *);
-void fwd_port_input(struct datapath *, struct buffer *, struct sw_port *);
+void fwd_port_input(struct datapath *, struct ofpbuf *, struct sw_port *);
int fwd_control_input(struct datapath *, const struct sender *,
const void *, size_t);
-uint32_t save_buffer(struct buffer *);
-static struct buffer *retrieve_buffer(uint32_t id);
+uint32_t save_buffer(struct ofpbuf *);
+static struct ofpbuf *retrieve_buffer(uint32_t id);
static void discard_buffer(uint32_t id);
static int port_no(struct datapath *dp, struct sw_port *p)
time_t now = time_now();
struct sw_port *p, *pn;
struct remote *r, *rn;
- struct buffer *buffer = NULL;
+ struct ofpbuf *buffer = NULL;
if (now != dp->last_timeout) {
struct list deleted = LIST_INITIALIZER(&deleted);
const int headroom = 128 + 2;
const int hard_header = VLAN_ETH_HEADER_LEN;
const int mtu = netdev_get_mtu(p->netdev);
- buffer = buffer_new(headroom + hard_header + mtu);
- buffer->data += headroom;
+ buffer = ofpbuf_new(headroom + hard_header + mtu);
+ buffer->data = (char*)buffer->data + headroom;
}
error = netdev_recv(p->netdev, buffer);
if (!error) {
netdev_get_name(p->netdev), strerror(error));
}
}
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
/* Talk to remotes. */
LIST_FOR_EACH_SAFE (r, rn, struct remote, node, &dp->remotes) {
* other processing doesn't starve. */
for (i = 0; i < 50; i++) {
if (!r->cb_dump) {
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_header *oh;
buffer = rconn_recv(r->rconn);
} else {
VLOG_WARN_RL(&rl, "received too-short OpenFlow message");
}
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
} else {
if (r->n_txq < TXQ_LIMIT) {
int error = r->cb_dump(dp, r->cb_aux);
* "flood" argument is set, don't send out ports with flooding disabled.
*/
static int
-output_all(struct datapath *dp, struct buffer *buffer, int in_port, int flood)
+output_all(struct datapath *dp, struct ofpbuf *buffer, int in_port, int flood)
{
struct sw_port *p;
int prev_port;
continue;
}
if (prev_port != -1) {
- dp_output_port(dp, buffer_clone(buffer), in_port, prev_port,
+ dp_output_port(dp, ofpbuf_clone(buffer), in_port, prev_port,
false);
}
prev_port = port_no(dp, p);
if (prev_port != -1)
dp_output_port(dp, buffer, in_port, prev_port, false);
else
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
return 0;
}
void
-output_packet(struct datapath *dp, struct buffer *buffer, int out_port)
+output_packet(struct datapath *dp, struct ofpbuf *buffer, int out_port)
{
if (out_port >= 0 && out_port < OFPP_MAX) {
struct sw_port *p = &dp->ports[out_port];
}
}
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
VLOG_DBG_RL(&rl, "can't forward to bad port %d\n", out_port);
}
/* Takes ownership of 'buffer' and transmits it to 'out_port' on 'dp'.
*/
void
-dp_output_port(struct datapath *dp, struct buffer *buffer,
+dp_output_port(struct datapath *dp, struct ofpbuf *buffer,
int in_port, int out_port, bool ignore_no_fwd)
{
} else if (out_port == OFPP_TABLE) {
struct sw_port *p = in_port < OFPP_MAX ? &dp->ports[in_port] : 0;
if (run_flow_through_tables(dp, buffer, p)) {
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
}
} else {
if (in_port == out_port) {
static void *
make_openflow_reply(size_t openflow_len, uint8_t type,
- const struct sender *sender, struct buffer **bufferp)
+ const struct sender *sender, struct ofpbuf **bufferp)
{
return make_openflow_xid(openflow_len, type, sender ? sender->xid : 0,
bufferp);
}
static int
-send_openflow_buffer(struct datapath *dp, struct buffer *buffer,
+send_openflow_buffer(struct datapath *dp, struct ofpbuf *buffer,
const struct sender *sender)
{
struct remote *remote = sender ? sender->remote : dp->controller;
* the caller wants to be sent; a value of 0 indicates the entire packet should
* be sent. */
void
-dp_output_control(struct datapath *dp, struct buffer *buffer, int in_port,
+dp_output_control(struct datapath *dp, struct ofpbuf *buffer, int in_port,
size_t max_len, int reason)
{
struct ofp_packet_in *opi;
buffer_id = save_buffer(buffer);
total_len = buffer->size;
- if (buffer_id != UINT32_MAX && buffer->size > max_len) {
+ if (buffer_id != UINT32_MAX && max_len && buffer->size > max_len) {
buffer->size = max_len;
}
- opi = buffer_push_uninit(buffer, offsetof(struct ofp_packet_in, data));
+ opi = ofpbuf_push_uninit(buffer, offsetof(struct ofp_packet_in, data));
opi->header.version = OFP_VERSION;
opi->header.type = OFPT_PACKET_IN;
opi->header.length = htons(buffer->size);
static void
dp_send_features_reply(struct datapath *dp, const struct sender *sender)
{
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_switch_features *ofr;
struct sw_port *p;
ofr->capabilities = htonl(OFP_SUPPORTED_CAPABILITIES);
ofr->actions = htonl(OFP_SUPPORTED_ACTIONS);
LIST_FOR_EACH (p, struct sw_port, node, &dp->port_list) {
- struct ofp_phy_port *opp = buffer_put_uninit(buffer, sizeof *opp);
+ struct ofp_phy_port *opp = ofpbuf_put_uninit(buffer, sizeof *opp);
memset(opp, 0, sizeof *opp);
fill_port_desc(dp, p, opp);
}
static void
send_port_status(struct sw_port *p, uint8_t status)
{
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_port_status *ops;
ops = make_openflow_xid(sizeof *ops, OFPT_PORT_STATUS, 0, &buffer);
ops->reason = status;
send_flow_expired(struct datapath *dp, struct sw_flow *flow,
enum ofp_flow_expired_reason reason)
{
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_flow_expired *ofe;
ofe = make_openflow_xid(sizeof *ofe, OFPT_FLOW_EXPIRED, 0, &buffer);
flow_fill_match(&ofe->match, &flow->key);
dp_send_error_msg(struct datapath *dp, const struct sender *sender,
uint16_t type, uint16_t code, const void *data, size_t len)
{
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_error_msg *oem;
oem = make_openflow_reply(sizeof(*oem)+len, OFPT_ERROR, sender, &buffer);
oem->type = htons(type);
}
static void
-fill_flow_stats(struct buffer *buffer, struct sw_flow *flow,
+fill_flow_stats(struct ofpbuf *buffer, struct sw_flow *flow,
int table_idx, time_t now)
{
struct ofp_flow_stats *ofs;
int length = sizeof *ofs + sizeof *ofs->actions * flow->sf_acts->n_actions;
- ofs = buffer_put_uninit(buffer, length);
+ ofs = ofpbuf_put_uninit(buffer, length);
ofs->length = htons(length);
ofs->table_id = table_idx;
ofs->pad = 0;
* null pointer. Process it according to 'dp''s flow table. Returns 0 if
* successful, in which case 'buffer' is destroyed, or -ESRCH if there is no
* matching flow, in which case 'buffer' still belongs to the caller. */
-int run_flow_through_tables(struct datapath *dp, struct buffer *buffer,
+int run_flow_through_tables(struct datapath *dp, struct ofpbuf *buffer,
struct sw_port *p)
{
struct sw_flow_key key;
if (flow_extract(buffer, p ? port_no(dp, p) : OFPP_NONE, &key.flow)
&& (dp->flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP) {
/* Drop fragment. */
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
return 0;
}
if (p && p->flags & (OFPPFL_NO_RECV | OFPPFL_NO_RECV_STP)
&& p->flags & (!eth_addr_equals(key.flow.dl_dst, stp_eth_addr)
? OFPPFL_NO_RECV : OFPPFL_NO_RECV_STP)) {
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
return 0;
}
/* 'buffer' was received on 'p', which may be a a physical switch port or a
* null pointer. Process it according to 'dp''s flow table, sending it up to
* the controller if no flow matches. Takes ownership of 'buffer'. */
-void fwd_port_input(struct datapath *dp, struct buffer *buffer,
+void fwd_port_input(struct datapath *dp, struct ofpbuf *buffer,
struct sw_port *p)
{
if (run_flow_through_tables(dp, buffer, p)) {
}
static void
-do_output(struct datapath *dp, struct buffer *buffer, int in_port,
+do_output(struct datapath *dp, struct ofpbuf *buffer, int in_port,
size_t max_len, int out_port, bool ignore_no_fwd)
{
if (out_port != OFPP_CONTROLLER) {
}
static void
-execute_actions(struct datapath *dp, struct buffer *buffer,
+execute_actions(struct datapath *dp, struct ofpbuf *buffer,
int in_port, const struct sw_flow_key *key,
const struct ofp_action *actions, int n_actions,
bool ignore_no_fwd)
struct eth_header *eh = buffer->l2;
if (prev_port != -1) {
- do_output(dp, buffer_clone(buffer), in_port, max_len, prev_port,
+ do_output(dp, ofpbuf_clone(buffer), in_port, max_len, prev_port,
ignore_no_fwd);
prev_port = -1;
}
if (prev_port != -1)
do_output(dp, buffer, in_port, max_len, prev_port, ignore_no_fwd);
else
- buffer_delete(buffer);
+ ofpbuf_delete(buffer);
}
-static void modify_nh(struct buffer *buffer, uint16_t eth_proto,
+static void modify_nh(struct ofpbuf *buffer, uint16_t eth_proto,
uint8_t nw_proto, const struct ofp_action *a)
{
if (eth_proto == ETH_TYPE_IP) {
}
}
-static void modify_th(struct buffer *buffer, uint16_t eth_proto,
+static void modify_th(struct ofpbuf *buffer, uint16_t eth_proto,
uint8_t nw_proto, const struct ofp_action *a)
{
if (eth_proto == ETH_TYPE_IP) {
}
static void
-modify_vlan(struct buffer *buffer,
+modify_vlan(struct ofpbuf *buffer,
const struct sw_flow_key *key, const struct ofp_action *a)
{
uint16_t new_id = a->arg.vlan_id;
tmp.veth_tci = new_id;
tmp.veth_next_type = eh->eth_type;
- veh = buffer_push_uninit(buffer, VLAN_HEADER_LEN);
+ veh = ofpbuf_push_uninit(buffer, VLAN_HEADER_LEN);
memcpy(veh, &tmp, sizeof tmp);
- buffer->l2 -= VLAN_HEADER_LEN;
+ buffer->l2 = (char*)buffer->l2 - VLAN_HEADER_LEN;
}
} else {
/* Remove an existing vlan header if it exists */
tmp.eth_type = veh->veth_next_type;
buffer->size -= VLAN_HEADER_LEN;
- buffer->data += VLAN_HEADER_LEN;
- buffer->l2 += VLAN_HEADER_LEN;
+ buffer->data = (char*)buffer->data + VLAN_HEADER_LEN;
+ buffer->l2 = (char*)buffer->l2 + VLAN_HEADER_LEN;
memcpy(buffer->data, &tmp, sizeof tmp);
}
}
recv_get_config_request(struct datapath *dp, const struct sender *sender,
const void *msg)
{
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_switch_config *osc;
osc = make_openflow_reply(sizeof *osc, OFPT_GET_CONFIG_REPLY,
{
const struct ofp_packet_out *opo = msg;
struct sw_flow_key key;
- struct buffer *buffer;
+ struct ofpbuf *buffer;
int n_actions = ntohs(opo->n_actions);
int act_len = n_actions * sizeof opo->actions[0];
if (ntohl(opo->buffer_id) == (uint32_t) -1) {
/* FIXME: can we avoid copying data here? */
int data_len = ntohs(opo->header.length) - sizeof *opo - act_len;
- buffer = buffer_new(data_len);
- buffer_put(buffer, &opo->actions[n_actions], data_len);
+ buffer = ofpbuf_new(data_len);
+ ofpbuf_put(buffer, &opo->actions[n_actions], data_len);
} else {
buffer = retrieve_buffer(ntohl(opo->buffer_id));
if (!buffer) {
}
error = 0;
if (ntohl(ofm->buffer_id) != UINT32_MAX) {
- struct buffer *buffer = retrieve_buffer(ntohl(ofm->buffer_id));
+ struct ofpbuf *buffer = retrieve_buffer(ntohl(ofm->buffer_id));
if (buffer) {
struct sw_flow_key key;
uint16_t in_port = ntohs(ofm->match.in_port);
chain_modify(dp->chain, &key, ofm->actions, n_actions);
if (ntohl(ofm->buffer_id) != UINT32_MAX) {
- struct buffer *buffer = retrieve_buffer(ntohl(ofm->buffer_id));
+ struct ofpbuf *buffer = retrieve_buffer(ntohl(ofm->buffer_id));
if (buffer) {
struct sw_flow_key skb_key;
uint16_t in_port = ntohs(ofm->match.in_port);
}
static int desc_stats_dump(struct datapath *dp, void *state,
- struct buffer *buffer)
+ struct ofpbuf *buffer)
{
- struct ofp_desc_stats *ods = buffer_put_uninit(buffer, sizeof *ods);
+ struct ofp_desc_stats *ods = ofpbuf_put_uninit(buffer, sizeof *ods);
strncpy(ods->mfr_desc, &mfr_desc, sizeof ods->mfr_desc);
strncpy(ods->hw_desc, &hw_desc, sizeof ods->hw_desc);
struct ofp_flow_stats_request rq;
time_t now;
- struct buffer *buffer;
+ struct ofpbuf *buffer;
};
#define MAX_FLOW_STATS_BYTES 4096
}
static int flow_stats_dump(struct datapath *dp, void *state,
- struct buffer *buffer)
+ struct ofpbuf *buffer)
{
struct flow_stats_state *s = state;
struct sw_flow_key match_key;
}
static int aggregate_stats_dump(struct datapath *dp, void *state,
- struct buffer *buffer)
+ struct ofpbuf *buffer)
{
struct aggregate_stats_state *s = state;
struct ofp_aggregate_stats_request *rq = &s->rq;
struct sw_flow_key match_key;
int table_idx;
- rpy = buffer_put_uninit(buffer, sizeof *rpy);
+ rpy = ofpbuf_put_uninit(buffer, sizeof *rpy);
memset(rpy, 0, sizeof *rpy);
flow_extract_match(&match_key, &rq->match);
}
static int table_stats_dump(struct datapath *dp, void *state,
- struct buffer *buffer)
+ struct ofpbuf *buffer)
{
int i;
for (i = 0; i < dp->chain->n_tables; i++) {
- struct ofp_table_stats *ots = buffer_put_uninit(buffer, sizeof *ots);
+ struct ofp_table_stats *ots = ofpbuf_put_uninit(buffer, sizeof *ots);
struct sw_table_stats stats;
dp->chain->tables[i]->stats(dp->chain->tables[i], &stats);
strncpy(ots->name, stats.name, sizeof ots->name);
}
static int port_stats_dump(struct datapath *dp, void *state,
- struct buffer *buffer)
+ struct ofpbuf *buffer)
{
struct port_stats_state *s = state;
int i;
if (!p->netdev) {
continue;
}
- ops = buffer_put_uninit(buffer, sizeof *ops);
+ ops = ofpbuf_put_uninit(buffer, sizeof *ops);
ops->port_no = htons(port_no(dp, p));
memset(ops->pad, 0, sizeof ops->pad);
ops->rx_packets = htonll(p->rx_packets);
}
struct stats_type {
+ /* Value for 'type' member of struct ofp_stats_request. */
+ int type;
+
/* Minimum and maximum acceptable number of bytes in body member of
* struct ofp_stats_request. */
size_t min_body, max_body;
* struct ofp_stats_reply. On success, it should return 1 if it should be
* called again later with another buffer, 0 if it is done, or a negative
* errno value on failure. */
- int (*dump)(struct datapath *dp, void *state, struct buffer *buffer);
+ int (*dump)(struct datapath *dp, void *state, struct ofpbuf *buffer);
/* Cleans any state created by the init or dump functions. May be null
* if no cleanup is required. */
};
static const struct stats_type stats[] = {
- [OFPST_DESC] = {
+ {
+ OFPST_DESC,
0,
0,
NULL,
desc_stats_dump,
NULL
},
- [OFPST_FLOW] = {
+ {
+ OFPST_FLOW,
sizeof(struct ofp_flow_stats_request),
sizeof(struct ofp_flow_stats_request),
flow_stats_init,
flow_stats_dump,
flow_stats_done
},
- [OFPST_AGGREGATE] = {
+ {
+ OFPST_AGGREGATE,
sizeof(struct ofp_aggregate_stats_request),
sizeof(struct ofp_aggregate_stats_request),
aggregate_stats_init,
aggregate_stats_dump,
aggregate_stats_done
},
- [OFPST_TABLE] = {
+ {
+ OFPST_TABLE,
0,
0,
NULL,
table_stats_dump,
NULL
},
- [OFPST_PORT] = {
+ {
+ OFPST_PORT,
0,
0,
port_stats_init,
{
struct stats_dump_cb *cb = cb_;
struct ofp_stats_reply *osr;
- struct buffer *buffer;
+ struct ofpbuf *buffer;
int err;
if (cb->done) {
osr = make_openflow_reply(sizeof *osr, OFPT_STATS_REPLY, &cb->sender,
&buffer);
- osr->type = htons(cb->s - stats);
+ osr->type = htons(cb->s->type);
osr->flags = 0;
err = cb->s->dump(dp, cb->state, buffer);
cb->done = true;
} else {
/* Buffer might have been reallocated, so find our data again. */
- osr = buffer_at_assert(buffer, 0, sizeof *osr);
+ osr = ofpbuf_at_assert(buffer, 0, sizeof *osr);
osr->flags = ntohs(OFPSF_REPLY_MORE);
}
err2 = send_openflow_buffer(dp, buffer, &cb->sender);
{
const struct ofp_stats_request *rq = oh;
size_t rq_len = ntohs(rq->header.length);
+ const struct stats_type *st;
struct stats_dump_cb *cb;
int type, body_len;
int err;
type = ntohs(rq->type);
- if (type >= ARRAY_SIZE(stats) || !stats[type].dump) {
- dp_send_error_msg(dp, sender, OFPET_BAD_REQUEST, OFPBRC_BAD_STAT,
- rq, rq_len);
- VLOG_WARN_RL(&rl, "received stats request of unknown type %d", type);
- return -EINVAL;
+ for (st = stats; ; st++) {
+ if (st >= &stats[ARRAY_SIZE(stats)]) {
+ VLOG_WARN_RL(&rl, "received stats request of unknown type %d",
+ type);
+ return -EINVAL;
+ } else if (type == st->type) {
+ break;
+ }
}
cb = xmalloc(sizeof *cb);
cb->done = false;
cb->rq = xmemdup(rq, rq_len);
cb->sender = *sender;
- cb->s = &stats[type];
+ cb->s = st;
cb->state = NULL;
body_len = rq_len - offsetof(struct ofp_stats_request, body);
fwd_control_input(struct datapath *dp, const struct sender *sender,
const void *msg, size_t length)
{
- struct openflow_packet {
- size_t min_size;
- int (*handler)(struct datapath *, const struct sender *, const void *);
- };
-
- static const struct openflow_packet packets[] = {
- [OFPT_FEATURES_REQUEST] = {
- sizeof (struct ofp_header),
- recv_features_request,
- },
- [OFPT_GET_CONFIG_REQUEST] = {
- sizeof (struct ofp_header),
- recv_get_config_request,
- },
- [OFPT_SET_CONFIG] = {
- sizeof (struct ofp_switch_config),
- recv_set_config,
- },
- [OFPT_PACKET_OUT] = {
- sizeof (struct ofp_packet_out),
- recv_packet_out,
- },
- [OFPT_FLOW_MOD] = {
- sizeof (struct ofp_flow_mod),
- recv_flow,
- },
- [OFPT_PORT_MOD] = {
- sizeof (struct ofp_port_mod),
- recv_port_mod,
- },
- [OFPT_STATS_REQUEST] = {
- sizeof (struct ofp_stats_request),
- recv_stats_request,
- },
- [OFPT_ECHO_REQUEST] = {
- sizeof (struct ofp_header),
- recv_echo_request,
- },
- [OFPT_ECHO_REPLY] = {
- sizeof (struct ofp_header),
- recv_echo_reply,
- },
- };
-
+ int (*handler)(struct datapath *, const struct sender *, const void *);
struct ofp_header *oh;
+ size_t min_size;
+ /* Check encapsulated length. */
oh = (struct ofp_header *) msg;
- if (ntohs(oh->length) > length)
+ if (ntohs(oh->length) > length) {
+ return -EINVAL;
+ }
+ assert(oh->version == OFP_VERSION);
+
+ /* Figure out how to handle it. */
+ switch (oh->type) {
+ case OFPT_FEATURES_REQUEST:
+ min_size = sizeof(struct ofp_header);
+ handler = recv_features_request;
+ break;
+ case OFPT_GET_CONFIG_REQUEST:
+ min_size = sizeof(struct ofp_header);
+ handler = recv_get_config_request;
+ break;
+ case OFPT_SET_CONFIG:
+ min_size = sizeof(struct ofp_switch_config);
+ handler = recv_set_config;
+ break;
+ case OFPT_PACKET_OUT:
+ min_size = sizeof(struct ofp_packet_out);
+ handler = recv_packet_out;
+ break;
+ case OFPT_FLOW_MOD:
+ min_size = sizeof(struct ofp_flow_mod);
+ handler = recv_flow;
+ break;
+ case OFPT_PORT_MOD:
+ min_size = sizeof(struct ofp_port_mod);
+ handler = recv_port_mod;
+ break;
+ case OFPT_STATS_REQUEST:
+ min_size = sizeof(struct ofp_stats_request);
+ handler = recv_stats_request;
+ break;
+ case OFPT_ECHO_REQUEST:
+ min_size = sizeof(struct ofp_header);
+ handler = recv_echo_request;
+ break;
+ case OFPT_ECHO_REPLY:
+ min_size = sizeof(struct ofp_header);
+ handler = recv_echo_reply;
+ break;
+ default:
+ dp_send_error_msg(dp, sender, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE,
+ msg, length);
return -EINVAL;
-
- if (oh->type < ARRAY_SIZE(packets)) {
- const struct openflow_packet *pkt = &packets[oh->type];
- if (pkt->handler) {
- if (length < pkt->min_size)
- return -EFAULT;
- return pkt->handler(dp, sender, msg);
- }
}
- dp_send_error_msg(dp, sender, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE,
- msg, length);
- return -EINVAL;
+
+ /* Handle it. */
+ if (length < min_size)
+ return -EFAULT;
+ return handler(dp, sender, msg);
}
\f
/* Packet buffering. */
#define OVERWRITE_SECS 1
struct packet_buffer {
- struct buffer *buffer;
+ struct ofpbuf *buffer;
uint32_t cookie;
time_t timeout;
};
static struct packet_buffer buffers[N_PKT_BUFFERS];
static unsigned int buffer_idx;
-uint32_t save_buffer(struct buffer *buffer)
+uint32_t save_buffer(struct ofpbuf *buffer)
{
struct packet_buffer *p;
uint32_t id;
if (time_now() < p->timeout) { /* FIXME */
return -1;
} else {
- buffer_delete(p->buffer);
+ ofpbuf_delete(p->buffer);
}
}
/* Don't use maximum cookie value since the all-bits-1 id is
* special. */
if (++p->cookie >= (1u << PKT_COOKIE_BITS) - 1)
p->cookie = 0;
- p->buffer = buffer_clone(buffer); /* FIXME */
+ p->buffer = ofpbuf_clone(buffer); /* FIXME */
p->timeout = time_now() + OVERWRITE_SECS; /* FIXME */
id = buffer_idx | (p->cookie << PKT_BUFFER_BITS);
return id;
}
-static struct buffer *retrieve_buffer(uint32_t id)
+static struct ofpbuf *retrieve_buffer(uint32_t id)
{
- struct buffer *buffer = NULL;
+ struct ofpbuf *buffer = NULL;
struct packet_buffer *p;
p = &buffers[id & PKT_BUFFER_MASK];
p = &buffers[id & PKT_BUFFER_MASK];
if (p->cookie == id >> PKT_BUFFER_BITS) {
- buffer_delete(p->buffer);
+ ofpbuf_delete(p->buffer);
p->buffer = NULL;
}
}
#ifndef DATAPATH_H
#define DATAPATH_H 1
-#include <time.h>
-#include "openflow.h"
-#include "switch-flow.h"
-#include "buffer.h"
-#include "list.h"
+#include <stdint.h>
struct datapath;
struct rconn;
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#include "buffer.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "packets.h"
#include "timeval.h"
}
}
-void flow_used(struct sw_flow *flow, struct buffer *buffer)
+void flow_used(struct sw_flow *flow, struct ofpbuf *buffer)
{
flow->used = time_now();
flow->packet_count++;
void print_flow(const struct sw_flow_key *);
bool flow_timeout(struct sw_flow *flow);
-void flow_used(struct sw_flow *flow, struct buffer *buffer);
+void flow_used(struct sw_flow *flow, struct ofpbuf *buffer);
#endif /* switch-flow.h */
signal(SIGPIPE, SIG_IGN);
if (argc - optind != 1) {
- fatal(0, "missing controller argument; use --help for usage");
+ ofp_fatal(0, "missing controller argument; use --help for usage");
}
rconn = rconn_create(60, max_backoff);
error = rconn_connect(rconn, argv[optind]);
if (error == EAFNOSUPPORT) {
- fatal(0, "no support for %s vconn", argv[optind]);
+ ofp_fatal(0, "no support for %s vconn", argv[optind]);
}
error = dp_new(&dp, dpid, rconn);
if (listen_pvconn_name) {
retval = pvconn_open(listen_pvconn_name, &listen_pvconn);
if (retval && retval != EAGAIN) {
- fatal(retval, "opening %s", listen_pvconn_name);
+ ofp_fatal(retval, "opening %s", listen_pvconn_name);
}
dp_add_listen_pvconn(dp, listen_pvconn);
}
if (error) {
- fatal(error, "could not create datapath");
+ ofp_fatal(error, "could not create datapath");
}
if (port_list) {
add_ports(dp, port_list);
error = vlog_server_listen(NULL, NULL);
if (error) {
- fatal(error, "could not listen for vlog connections");
+ ofp_fatal(error, "could not listen for vlog connections");
}
die_if_already_running();
port = strtok_r(NULL, ",,", &save_ptr)) {
int error = dp_add_port(dp, port);
if (error) {
- fatal(error, "failed to add port %s", port);
+ ofp_fatal(error, "failed to add port %s", port);
}
}
}
case 'd':
if (strlen(optarg) != 12
|| strspn(optarg, "0123456789abcdefABCDEF") != 12) {
- fatal(0, "argument to -d or --datapath-id must be "
- "exactly 12 hex digits");
+ ofp_fatal(0, "argument to -d or --datapath-id must be "
+ "exactly 12 hex digits");
}
dpid = strtoll(optarg, NULL, 16);
if (!dpid) {
- fatal(0, "argument to -d or --datapath-id must be nonzero");
+ ofp_fatal(0, "argument to -d or --datapath-id must "
+ "be nonzero");
}
break;
case OPT_MAX_BACKOFF:
max_backoff = atoi(optarg);
if (max_backoff < 1) {
- fatal(0, "--max-backoff argument must be at least 1");
+ ofp_fatal(0, "--max-backoff argument must be at least 1");
} else if (max_backoff > 3600) {
max_backoff = 3600;
}
case 'l':
if (listen_pvconn_name) {
- fatal(0, "-l or --listen may be only specified once");
+ ofp_fatal(0, "-l or --listen may be only specified once");
}
listen_pvconn_name = optarg;
break;
#include <stdlib.h>
#include <string.h>
#include "crc32.h"
-#include "flow.h"
#include "datapath.h"
+#include "flow.h"
+#include "switch-flow.h"
struct sw_table_hash {
struct sw_table swt;
#include <stdlib.h>
#include "flow.h"
#include "list.h"
+#include "openflow.h"
#include "switch-flow.h"
#include "datapath.h"
argc -= optind;
argv += optind;
if (argc != 1) {
- fatal(0, "exactly one non-option argument required; "
- "use --help for help");
+ ofp_fatal(0, "exactly one non-option argument required; "
+ "use --help for help");
}
error = dhclient_create(argv[0], modify_dhcp_request, NULL, NULL, &cli);
if (error) {
- fatal(error, "dhclient_create failed");
+ ofp_fatal(error, "dhclient_create failed");
}
dhclient_init(cli, request_ip.s_addr);
fatal_signal_add_hook(release, cli, true);
switch (c) {
case OPT_REQUEST_IP:
if (!inet_aton(optarg, &request_ip)) {
- fatal(0, "--request-ip argument is not a valid IP address");
+ ofp_fatal(0,
+ "--request-ip argument is not a valid IP address");
}
break;
int i;
if (argc != 2) {
- fatal(0, "usage: test-stp INPUT.STP\n");
+ ofp_fatal(0, "usage: test-stp INPUT.STP\n");
}
file_name = argv[1];
input_file = fopen(file_name, "r");
if (!input_file) {
- fatal(errno, "error opening \"%s\"", file_name);
+ ofp_fatal(errno, "error opening \"%s\"", file_name);
}
tc = new_test_case();
#include "openflow-netlink.h"
#endif
-#include "buffer.h"
#include "command-line.h"
#include "compiler.h"
#include "dpif.h"
#include "nicira-ext.h"
#include "ofp-print.h"
+#include "ofpbuf.h"
#include "openflow.h"
#include "packets.h"
#include "random.h"
argc -= optind;
argv += optind;
if (argc < 1)
- fatal(0, "missing command name; use --help for help");
+ ofp_fatal(0, "missing command name; use --help for help");
for (p = all_commands; p->name != NULL; p++) {
if (!strcmp(p->name, argv[0])) {
int n_arg = argc - 1;
if (n_arg < p->min_args)
- fatal(0, "'%s' command requires at least %d arguments",
- p->name, p->min_args);
+ ofp_fatal(0, "'%s' command requires at least %d arguments",
+ p->name, p->min_args);
else if (n_arg > p->max_args)
- fatal(0, "'%s' command takes at most %d arguments",
- p->name, p->max_args);
+ ofp_fatal(0, "'%s' command takes at most %d arguments",
+ p->name, p->max_args);
else {
p->handler(argc, argv);
exit(0);
}
}
}
- fatal(0, "unknown command '%s'; use --help for help", argv[0]);
+ ofp_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
return 0;
}
case 't':
timeout = strtoul(optarg, NULL, 10);
if (timeout <= 0) {
- fatal(0, "value %s on -t or --timeout is not at least 1",
- optarg);
+ ofp_fatal(0, "value %s on -t or --timeout is not at least 1",
+ optarg);
} else {
time_alarm(timeout);
}
if (strncmp(name, "nl:", 3)
|| strlen(name) < 4
|| name[strspn(name + 3, "0123456789") + 3]) {
- fatal(0, "%s: argument is not of the form \"nl:DP_ID\"", name);
+ ofp_fatal(0, "%s: argument is not of the form \"nl:DP_ID\"", name);
}
run(dpif_open(atoi(name + 3), subscribe, dpif), "opening datapath");
}
for (i = 2; i < argc; i++) {
int retval = function(&dp, argv[i]);
if (retval) {
- error(retval, "failed to %s %s %s %s",
- operation, argv[i], preposition, argv[1]);
+ ofp_error(retval, "failed to %s %s %s %s",
+ operation, argv[i], preposition, argv[1]);
failure = true;
}
}
}
static void *
-alloc_stats_request(size_t body_len, uint16_t type, struct buffer **bufferp)
+alloc_stats_request(size_t body_len, uint16_t type, struct ofpbuf **bufferp)
{
struct ofp_stats_request *rq;
rq = make_openflow((offsetof(struct ofp_stats_request, body)
}
static void
-send_openflow_buffer(struct vconn *vconn, struct buffer *buffer)
+send_openflow_buffer(struct vconn *vconn, struct ofpbuf *buffer)
{
update_openflow_length(buffer);
run(vconn_send_block(vconn, buffer), "failed to send packet to switch");
}
static void
-dump_transaction(const char *vconn_name, struct buffer *request)
+dump_transaction(const char *vconn_name, struct ofpbuf *request)
{
struct vconn *vconn;
- struct buffer *reply;
+ struct ofpbuf *reply;
update_openflow_length(request);
open_vconn(vconn_name, &vconn);
static void
dump_trivial_transaction(const char *vconn_name, uint8_t request_type)
{
- struct buffer *request;
+ struct ofpbuf *request;
make_openflow(sizeof(struct ofp_header), request_type, &request);
dump_transaction(vconn_name, request);
}
static void
-dump_stats_transaction(const char *vconn_name, struct buffer *request)
+dump_stats_transaction(const char *vconn_name, struct ofpbuf *request)
{
uint32_t send_xid = ((struct ofp_header *) request->data)->xid;
struct vconn *vconn;
send_openflow_buffer(vconn, request);
while (!done) {
uint32_t recv_xid;
- struct buffer *reply;
+ struct ofpbuf *reply;
run(vconn_recv_block(vconn, &reply), "OpenFlow packet receive failed");
recv_xid = ((struct ofp_header *) reply->data)->xid;
ofp_print(stdout, reply->data, reply->size, 1);
- osr = buffer_at(reply, 0, sizeof *osr);
+ osr = ofpbuf_at(reply, 0, sizeof *osr);
done = !osr || !(ntohs(osr->flags) & OFPSF_REPLY_MORE);
} else {
VLOG_DBG("received reply with xid %08"PRIx32" "
"!= expected %08"PRIx32, recv_xid, send_xid);
}
- buffer_delete(reply);
+ ofpbuf_delete(reply);
}
vconn_close(vconn);
}
static void
dump_trivial_stats_transaction(const char *vconn_name, uint8_t stats_type)
{
- struct buffer *request;
+ struct ofpbuf *request;
alloc_stats_request(0, stats_type, &request);
dump_stats_transaction(vconn_name, request);
}
{
struct nicira_header *request, *reply;
struct vconn *vconn;
- struct buffer *b;
+ struct ofpbuf *b;
request = make_openflow(sizeof *request, OFPT_VENDOR, &b);
request->vendor_id = htonl(NX_VENDOR_ID);
request->subtype = htonl(NXT_STATUS_REQUEST);
if (argc > 2) {
- buffer_put(b, argv[2], strlen(argv[2]));
+ ofpbuf_put(b, argv[2], strlen(argv[2]));
}
open_vconn(argv[1], &vconn);
run(vconn_transact(vconn, b, &b), "talking to %s", argv[1]);
vconn_close(vconn);
if (b->size < sizeof *reply) {
- fatal(0, "short reply (%zu bytes)", b->size);
+ ofp_fatal(0, "short reply (%zu bytes)", b->size);
}
reply = b->data;
if (reply->header.type != OFPT_VENDOR
|| reply->vendor_id != ntohl(NX_VENDOR_ID)
|| reply->subtype != ntohl(NXT_STATUS_REPLY)) {
ofp_print(stderr, b->data, b->size, 2);
- fatal(0, "bad reply");
+ ofp_fatal(0, "bad reply");
}
fwrite(reply + 1, b->size, 1, stdout);
errno = 0;
value = strtoul(str, &tail, 0);
if (errno == EINVAL || errno == ERANGE || *tail) {
- fatal(0, "invalid numeric format %s", str);
+ ofp_fatal(0, "invalid numeric format %s", str);
}
return value;
}
{
if (sscanf(str, "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8,
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 6) {
- fatal(0, "invalid mac address %s", str);
+ ofp_fatal(0, "invalid mac address %s", str);
}
}
name = strtok_r(str, "//", &save_ptr);
retval = name ? lookup_ip(name, &in_addr) : EINVAL;
if (retval) {
- fatal(0, "%s: could not convert to IP address", str);
+ ofp_fatal(0, "%s: could not convert to IP address", str);
}
*ip = in_addr.s_addr;
/* Verify that the rest of the bits are 1-bits. */
for (; i < 32; i++) {
if (!(nm & (1u << i))) {
- fatal(0, "%s: %s is not a valid netmask", str, netmask);
+ ofp_fatal(0, "%s: %s is not a valid netmask",
+ str, netmask);
}
}
} else {
int prefix = atoi(netmask);
if (prefix <= 0 || prefix > 32) {
- fatal(0, "%s: network prefix bits not between 1 and 32", str);
+ ofp_fatal(0, "%s: network prefix bits not between 1 and 32",
+ str);
}
n_wild = 32 - prefix;
}
} else if (strspn(act, "0123456789") == strlen(act)) {
port = str_to_int(act);
} else {
- fatal(0, "Unknown action: %s", act);
+ ofp_fatal(0, "Unknown action: %s", act);
}
if (port != OFPP_MAX) {
if (action) {
char *act_str = strstr(string, "action");
if (!act_str) {
- fatal(0, "must specify an action");
+ ofp_fatal(0, "must specify an action");
}
*(act_str-1) = '\0';
act_str = strchr(act_str, '=');
if (!act_str) {
- fatal(0, "must specify an action");
+ ofp_fatal(0, "must specify an action");
}
act_str++;
value = strtok(NULL, ", \t\r\n");
if (!value) {
- fatal(0, "field %s missing value", name);
+ ofp_fatal(0, "field %s missing value", name);
}
if (table_idx && !strcmp(name, "table")) {
}
}
} else {
- fatal(0, "unknown keyword %s", name);
+ ofp_fatal(0, "unknown keyword %s", name);
}
}
}
static void do_dump_flows(int argc, char *argv[])
{
struct ofp_flow_stats_request *req;
- struct buffer *request;
+ struct ofpbuf *request;
req = alloc_stats_request(sizeof *req, OFPST_FLOW, &request);
str_to_flow(argc > 2 ? argv[2] : "", &req->match, NULL, 0,
static void do_dump_aggregate(int argc, char *argv[])
{
struct ofp_aggregate_stats_request *req;
- struct buffer *request;
+ struct ofpbuf *request;
req = alloc_stats_request(sizeof *req, OFPST_AGGREGATE, &request);
str_to_flow(argc > 2 ? argv[2] : "", &req->match, NULL, 0,
static void do_add_flow(int argc, char *argv[])
{
struct vconn *vconn;
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
uint16_t priority, idle_timeout, hard_timeout;
size_t size;
ofm->priority = htons(priority);
ofm->reserved = htonl(0);
- /* xxx Should we use the buffer library? */
+ /* xxx Should we use the ofpbuf library? */
buffer->size -= (MAX_ADD_ACTS - n_actions) * sizeof ofm->actions[0];
open_vconn(argv[1], &vconn);
file = fopen(argv[2], "r");
if (file == NULL) {
- fatal(errno, "%s: open", argv[2]);
+ ofp_fatal(errno, "%s: open", argv[2]);
}
open_vconn(argv[1], &vconn);
while (fgets(line, sizeof line, file)) {
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
uint16_t priority, idle_timeout, hard_timeout;
size_t size;
ofm->priority = htons(priority);
ofm->reserved = htonl(0);
- /* xxx Should we use the buffer library? */
+ /* xxx Should we use the ofpbuf library? */
buffer->size -= (MAX_ADD_ACTS - n_actions) * sizeof ofm->actions[0];
send_openflow_buffer(vconn, buffer);
{
uint16_t idle_timeout, hard_timeout;
struct vconn *vconn;
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
size_t size;
int n_actions = MAX_ADD_ACTS;
{
struct vconn *vconn;
uint16_t priority;
- struct buffer *buffer;
+ struct ofpbuf *buffer;
struct ofp_flow_mod *ofm;
size_t size;
}
open_vconn(argv[1], &vconn);
for (;;) {
- struct buffer *b;
+ struct ofpbuf *b;
run(vconn_recv_block(vconn, &b), "vconn_recv");
ofp_print(stderr, b->data, b->size, 2);
- buffer_delete(b);
+ ofpbuf_delete(b);
}
}
static void
do_probe(int argc, char *argv[])
{
- struct buffer *request;
+ struct ofpbuf *request;
struct vconn *vconn;
- struct buffer *reply;
+ struct ofpbuf *reply;
make_openflow(sizeof(struct ofp_header), OFPT_ECHO_REQUEST, &request);
open_vconn(argv[1], &vconn);
run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]);
if (reply->size != request->size) {
- fatal(0, "reply does not match request");
+ ofp_fatal(0, "reply does not match request");
}
- buffer_delete(reply);
+ ofpbuf_delete(reply);
vconn_close(vconn);
}
static void
do_mod_port(int argc, char *argv[])
{
- struct buffer *request, *reply;
+ struct ofpbuf *request, *reply;
struct ofp_switch_features *osf;
struct ofp_port_mod *opm;
struct vconn *vconn;
}
}
if (port_idx == n_ports) {
- fatal(0, "couldn't find monitored port: %s", argv[2]);
+ ofp_fatal(0, "couldn't find monitored port: %s", argv[2]);
}
opm = make_openflow(sizeof(struct ofp_port_mod), OFPT_PORT_MOD, &request);
opm->mask |= htonl(OFPPFL_NO_FLOOD);
opm->desc.flags |= htonl(OFPPFL_NO_FLOOD);
} else {
- fatal(0, "unknown mod-port command '%s'", argv[3]);
+ ofp_fatal(0, "unknown mod-port command '%s'", argv[3]);
}
send_openflow_buffer(vconn, request);
- buffer_delete(reply);
+ ofpbuf_delete(reply);
vconn_close(vconn);
}
payload = argc > 2 ? atoi(argv[2]) : 64;
if (payload > max_payload) {
- fatal(0, "payload must be between 0 and %zu bytes", max_payload);
+ ofp_fatal(0, "payload must be between 0 and %zu bytes", max_payload);
}
open_vconn(argv[1], &vconn);
for (i = 0; i < 10; i++) {
struct timeval start, end;
- struct buffer *request, *reply;
+ struct ofpbuf *request, *reply;
struct ofp_header *rq_hdr, *rpy_hdr;
rq_hdr = make_openflow(sizeof(struct ofp_header) + payload,
random_bytes(rq_hdr + 1, payload);
gettimeofday(&start, NULL);
- run(vconn_transact(vconn, buffer_clone(request), &reply), "transact");
+ run(vconn_transact(vconn, ofpbuf_clone(request), &reply), "transact");
gettimeofday(&end, NULL);
rpy_hdr = reply->data;
reply->size - sizeof *rpy_hdr, argv[1], rpy_hdr->xid,
(1000*(double)(end.tv_sec - start.tv_sec))
+ (.001*(end.tv_usec - start.tv_usec)));
- buffer_delete(request);
- buffer_delete(reply);
+ ofpbuf_delete(request);
+ ofpbuf_delete(reply);
}
vconn_close(vconn);
}
payload_size = atoi(argv[2]);
if (payload_size > max_payload) {
- fatal(0, "payload must be between 0 and %zu bytes", max_payload);
+ ofp_fatal(0, "payload must be between 0 and %zu bytes", max_payload);
}
message_size = sizeof(struct ofp_header) + payload_size;
open_vconn(argv[1], &vconn);
gettimeofday(&start, NULL);
for (i = 0; i < count; i++) {
- struct buffer *request, *reply;
+ struct ofpbuf *request, *reply;
struct ofp_header *rq_hdr;
rq_hdr = make_openflow(message_size, OFPT_ECHO_REQUEST, &request);
memset(rq_hdr + 1, 0, payload_size);
run(vconn_transact(vconn, request, &reply), "transact");
- buffer_delete(reply);
+ ofpbuf_delete(reply);
}
gettimeofday(&end, NULL);
vconn_close(vconn);
argc -= optind;
argv += optind;
if (argc < 1) {
- fatal(0, "need at least one non-option argument; "
- "use --help for usage");
+ ofp_fatal(0, "need at least one non-option argument; "
+ "use --help for usage");
}
ifaces = xmalloc(argc * sizeof *ifaces);
}
}
if (!n_ifaces) {
- fatal(0, "failed to initialize any DHCP clients");
+ ofp_fatal(0, "failed to initialize any DHCP clients");
}
for (i = 0; i < n_ifaces; i++) {
size_t length = regerror(retval, &accept_controller_regex, NULL, 0);
char *buffer = xmalloc(length);
regerror(retval, &accept_controller_regex, buffer, length);
- fatal(0, "%s: %s", accept_controller_re, buffer);
+ ofp_fatal(0, "%s: %s", accept_controller_re, buffer);
}
retval = vlog_server_listen(NULL, NULL);
if (retval) {
- fatal(retval, "Could not listen for vlog connections");
+ ofp_fatal(retval, "Could not listen for vlog connections");
}
die_if_already_running();
retval = netdev_open(iface->name, NETDEV_ETH_TYPE_NONE, &netdev);
if (retval) {
- error(retval, "Could not open %s device", iface->name);
+ ofp_error(retval, "Could not open %s device", iface->name);
return false;
}
retval = netdev_turn_flags_on(netdev, NETDEV_UP, true);
if (retval) {
- error(retval, "Could not bring %s device up", iface->name);
+ ofp_error(retval, "Could not bring %s device up", iface->name);
return false;
}
netdev_close(netdev);
retval = dhclient_create(iface->name, modify_dhcp_request,
validate_dhcp_offer, NULL, &iface->dhcp);
if (retval) {
- error(retval, "%s: failed to initialize DHCP client", iface->name);
+ ofp_error(retval, "%s: failed to initialize DHCP client", iface->name);
return false;
}
case 't':
timeout = strtoul(optarg, NULL, 10);
if (timeout <= 0) {
- fatal(0, "value %s on -t or --timeout is not at least 1",
- optarg);
+ ofp_fatal(0, "value %s on -t or --timeout is not at least 1",
+ optarg);
} else {
time_alarm(timeout);
}
free(short_options);
if ((exit_without_bind + exit_after_bind + !detach_after_bind) > 1) {
- fatal(0, "--exit-without-bind, --exit-after-bind, and --no-detach "
- "are mutually exclusive");
+ ofp_fatal(0, "--exit-without-bind, --exit-after-bind, and --no-detach "
+ "are mutually exclusive");
}
if (detach_after_bind) {
set_detach();
argv += optind;
if (argc < 1) {
if (!force) {
- fatal(0, "need at least one non-option argument; "
- "use --help for usage");
+ ofp_fatal(0, "need at least one non-option argument; "
+ "use --help for usage");
}
}
goto got_name;
}
}
- fatal(0, "unknown signal \"%s\"", optarg);
+ ofp_fatal(0, "unknown signal \"%s\"", optarg);
got_name: ;
}
break;
break;
}
if (!strchr("ath", option) && n_clients == 0) {
- fatal(0, "no targets specified (use --help for help)");
+ ofp_fatal(0, "no targets specified (use --help for help)");
} else {
++n_actions;
}