* derivatives without specific, written prior permission.
*/
+#include <config.h>
#include "vconn.h"
#include <assert.h>
#include <errno.h>
&ssl_vconn_class,
&pssl_vconn_class,
#endif
+ &unix_vconn_class,
+ &punix_vconn_class,
};
/* Check the validity of the vconn class structures. */
struct vconn_class *class = vconn_classes[i];
assert(class->name != NULL);
assert(class->open != NULL);
- assert(class->close != NULL);
- assert(class->accept
- ? !class->recv && !class->send
- : class->recv && class->send);
- assert(class->wait != NULL);
+ if (class->close || class->accept || class->recv || class->send
+ || class->wait) {
+ assert(class->close != NULL);
+ assert(class->accept
+ ? !class->recv && !class->send
+ : class->recv && class->send);
+ assert(class->wait != NULL);
+ } else {
+ /* This class delegates to another one. */
+ }
}
#endif
}
printf(" ssl:HOST[:PORT] "
"SSL PORT (default: %d) on remote HOST\n", OFP_SSL_PORT);
#endif
+ printf(" unix:FILE Unix domain socket named FILE\n");
}
if (passive) {
"listen for SSL on PORT (default: %d)\n",
OFP_SSL_PORT);
#endif
+ printf(" punix:FILE "
+ "listen on Unix domain socket FILE\n");
}
#ifdef HAVE_OPENSSL
check_vconn_classes();
+ *vconnp = NULL;
prefix_len = strcspn(name, ":");
if (prefix_len == strlen(name)) {
error(0, "`%s' not correct format for peer name", name);
struct vconn_class *class = vconn_classes[i];
if (strlen(class->name) == prefix_len
&& !memcmp(class->name, name, prefix_len)) {
+ struct vconn *vconn;
char *suffix_copy = xstrdup(name + prefix_len + 1);
- int retval = class->open(name, suffix_copy, vconnp);
+ int retval = class->open(name, suffix_copy, &vconn);
free(suffix_copy);
- if (retval) {
- *vconnp = NULL;
- } else {
- assert((*vconnp)->connect_status != EAGAIN
- || (*vconnp)->class->connect);
+ if (!retval) {
+ assert(vconn->connect_status != EAGAIN
+ || vconn->class->connect);
+ *vconnp = vconn;
}
return retval;
}
int retval = vconn_connect(vconn);
if (!retval) {
retval = (vconn->class->recv)(vconn, msgp);
- if (VLOG_IS_DBG_ENABLED() && !retval) {
- char *s = ofp_to_string((*msgp)->data, (*msgp)->size, 1);
- VLOG_DBG("received: %s", s);
- free(s);
+ if (!retval) {
+ struct ofp_header *oh;
+
+ if (VLOG_IS_DBG_ENABLED()) {
+ char *s = ofp_to_string((*msgp)->data, (*msgp)->size, 1);
+ VLOG_DBG("received: %s", s);
+ free(s);
+ }
+
+ oh = buffer_at_assert(*msgp, 0, sizeof *oh);
+ if (oh->version != OFP_VERSION) {
+ VLOG_ERR("received OpenFlow version %02"PRIx8" "
+ "!= expected %02x",
+ oh->version, OFP_VERSION);
+ buffer_delete(*msgp);
+ *msgp = NULL;
+ return EPROTO;
+ }
}
}
if (retval) {
}
struct buffer *
-make_add_simple_flow(const struct flow *flow,
- uint32_t buffer_id, uint16_t out_port, uint16_t max_idle)
+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 + sizeof ofm->actions[0];
+ size_t size = sizeof *ofm + n_actions * sizeof ofm->actions[0];
struct buffer *out = buffer_new(size);
ofm = buffer_put_uninit(out, size);
memset(ofm, 0, size);
ofm->header.version = OFP_VERSION;
ofm->header.type = OFPT_FLOW_MOD;
ofm->header.length = htons(size);
- ofm->match.wildcards = htons(0);
+ ofm->match.wildcards = htonl(0);
ofm->match.in_port = flow->in_port;
memcpy(ofm->match.dl_src, flow->dl_src, sizeof ofm->match.dl_src);
memcpy(ofm->match.dl_dst, flow->dl_dst, sizeof ofm->match.dl_dst);
ofm->match.tp_src = flow->tp_src;
ofm->match.tp_dst = flow->tp_dst;
ofm->command = htons(OFPFC_ADD);
- ofm->max_idle = htons(max_idle);
+ ofm->idle_timeout = htons(idle_timeout);
+ ofm->hard_timeout = htons(OFP_FLOW_PERMANENT);
ofm->buffer_id = htonl(buffer_id);
+ return out;
+}
+
+struct buffer *
+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 ofp_flow_mod *ofm = buffer->data;
ofm->actions[0].type = htons(OFPAT_OUTPUT);
ofm->actions[0].arg.output.max_len = htons(0);
ofm->actions[0].arg.output.port = htons(out_port);
- return out;
+ return buffer;
}
struct buffer *
uint16_t in_port, uint16_t out_port)
{
struct ofp_packet_out *opo;
- size_t size = sizeof *opo + packet->size;
- struct buffer *out = buffer_new(size);
+ size_t size = sizeof *opo + sizeof opo->actions[0];
+ struct buffer *out = buffer_new(size + packet->size);
opo = buffer_put_uninit(out, size);
memset(opo, 0, sizeof *opo);
opo->header.version = OFP_VERSION;
opo->header.type = OFPT_PACKET_OUT;
- opo->header.length = htons(size);
opo->buffer_id = htonl(UINT32_MAX);
opo->in_port = htons(in_port);
- opo->out_port = htons(out_port);
- memcpy(opo->u.data, packet->data, packet->size);
+ opo->n_actions = htons(1);
+ 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);
+ update_openflow_length(out);
return out;
}
uint16_t in_port, uint16_t out_port)
{
struct ofp_packet_out *opo;
- size_t size = sizeof *opo + sizeof opo->u.actions[0];
+ size_t size = sizeof *opo + sizeof opo->actions[0];
struct buffer *out = buffer_new(size);
opo = buffer_put_uninit(out, size);
memset(opo, 0, size);
opo->header.length = htons(size);
opo->buffer_id = htonl(buffer_id);
opo->in_port = htons(in_port);
- opo->out_port = htons(out_port);
- opo->u.actions[0].type = htons(OFPAT_OUTPUT);
- opo->u.actions[0].arg.output.max_len = htons(0);
- opo->u.actions[0].arg.output.port = htons(out_port);
+ opo->n_actions = htons(1);
+ 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);
return out;
}