}
/* Prints information on active (if 'active') and passive (if 'passive')
- * connection methods supported by the vconn. */
+ * connection methods supported by the vconn. If 'bootstrap' is true, also
+ * advertises options to bootstrap the CA certificate. */
void
-vconn_usage(bool active, bool passive)
+vconn_usage(bool active, bool passive, bool bootstrap UNUSED)
{
/* Really this should be implemented via callbacks into the vconn
* providers, but that seems too heavy-weight to bother with at the
" -p, --private-key=FILE file with private key\n"
" -c, --certificate=FILE file with certificate for private key\n"
" -C, --ca-cert=FILE file with peer CA certificate\n");
+ if (bootstrap) {
+ printf(" --bootstrap-ca-cert=FILE file with peer CA certificate "
+ "to read or create\n");
+ }
#endif
}
error->type = htons(OFPET_HELLO_FAILED);
error->code = htons(OFPHFC_INCOMPATIBLE);
ofpbuf_put(b, s, strlen(s));
+ update_openflow_length(b);
retval = do_send(vconn, b);
if (retval) {
ofpbuf_delete(b);
return retval;
}
-/* Sends 'request' to 'vconn' and blocks until it receives a reply with a
- * matching transaction ID. Returns 0 if successful, in which case the reply
- * is stored in '*replyp' for the caller to examine and free. Otherwise
- * returns a positive errno value, or EOF, and sets '*replyp' to null.
+/* Waits until a message with a transaction ID matching 'xid' is recived on
+ * 'vconn'. Returns 0 if successful, in which case the reply is stored in
+ * '*replyp' for the caller to examine and free. Otherwise returns a positive
+ * errno value, or EOF, and sets '*replyp' to null.
*
* 'request' is always destroyed, regardless of the return value. */
int
-vconn_transact(struct vconn *vconn, struct ofpbuf *request,
- struct ofpbuf **replyp)
+vconn_recv_xid(struct vconn *vconn, uint32_t xid, 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) {
- ofpbuf_delete(request);
- return error;
- }
for (;;) {
uint32_t recv_xid;
struct ofpbuf *reply;
+ int error;
error = vconn_recv_block(vconn, &reply);
if (error) {
+ *replyp = NULL;
return error;
}
recv_xid = ((struct ofp_header *) reply->data)->xid;
- if (send_xid == recv_xid) {
+ if (xid == recv_xid) {
*replyp = reply;
return 0;
}
VLOG_DBG_RL(&rl, "%s: received reply with xid %08"PRIx32" != expected "
- "%08"PRIx32, vconn->name, recv_xid, send_xid);
+ "%08"PRIx32, vconn->name, recv_xid, xid);
ofpbuf_delete(reply);
}
}
+/* Sends 'request' to 'vconn' and blocks until it receives a reply with a
+ * matching transaction ID. Returns 0 if successful, in which case the reply
+ * is stored in '*replyp' for the caller to examine and free. Otherwise
+ * returns a positive errno value, or EOF, and sets '*replyp' to null.
+ *
+ * 'request' is always destroyed, regardless of the return value. */
+int
+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);
+ ofpbuf_delete(request);
+ return error ? error : vconn_recv_xid(vconn, send_xid, replyp);
+}
+
void
vconn_wait(struct vconn *vconn, enum vconn_wait_type wait)
{
assert(openflow_len >= sizeof *oh);
assert(openflow_len <= UINT16_MAX);
buffer = *bufferp = ofpbuf_new(openflow_len);
- oh = ofpbuf_put_uninit(buffer, openflow_len);
- memset(oh, 0, openflow_len);
+ oh = ofpbuf_put_zeros(buffer, openflow_len);
oh->version = OFP_VERSION;
oh->type = type;
oh->length = htons(openflow_len);
struct ofpbuf *
make_add_flow(const struct flow *flow, uint32_t buffer_id,
- uint16_t idle_timeout, size_t n_actions)
+ uint16_t idle_timeout, size_t actions_len)
{
struct ofp_flow_mod *ofm;
- size_t size = sizeof *ofm + n_actions * sizeof ofm->actions[0];
+ size_t size = sizeof *ofm + actions_len;
struct ofpbuf *out = ofpbuf_new(size);
- ofm = ofpbuf_put_uninit(out, size);
- memset(ofm, 0, size);
+ ofm = ofpbuf_put_zeros(out, size);
ofm->header.version = OFP_VERSION;
ofm->header.type = OFPT_FLOW_MOD;
ofm->header.length = htons(size);
uint32_t buffer_id, uint16_t out_port,
uint16_t idle_timeout)
{
- struct ofpbuf *buffer = make_add_flow(flow, buffer_id, idle_timeout, 1);
+ struct ofp_action_output *oao;
+ struct ofpbuf *buffer = make_add_flow(flow, buffer_id, idle_timeout,
+ sizeof *oao);
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);
+ oao = (struct ofp_action_output *)&ofm->actions[0];
+ oao->type = htons(OFPAT_OUTPUT);
+ oao->len = htons(sizeof *oao);
+ oao->port = htons(out_port);
return buffer;
}
uint16_t in_port, uint16_t out_port)
{
struct ofp_packet_out *opo;
- size_t size = sizeof *opo + sizeof opo->actions[0];
+ struct ofp_action_output *oao;
+ size_t size = sizeof *opo + sizeof *oao;
struct ofpbuf *out = ofpbuf_new(size + packet->size);
- opo = ofpbuf_put_uninit(out, size);
- memset(opo, 0, size);
+
+ opo = ofpbuf_put_zeros(out, size);
opo->header.version = OFP_VERSION;
opo->header.type = OFPT_PACKET_OUT;
opo->buffer_id = htonl(UINT32_MAX);
opo->in_port = htons(in_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);
+
+ oao = (struct ofp_action_output *)&opo->actions[0];
+ oao->type = htons(OFPAT_OUTPUT);
+ oao->len = htons(sizeof *oao);
+ oao->port = htons(out_port);
+
+ opo->actions_len = htons(sizeof *oao);
+
ofpbuf_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->actions[0];
+ struct ofp_action_output *oao;
+ size_t size = sizeof *opo + sizeof *oao;
struct ofpbuf *out = ofpbuf_new(size);
- opo = ofpbuf_put_uninit(out, size);
- memset(opo, 0, size);
+ opo = ofpbuf_put_zeros(out, size);
opo->header.version = OFP_VERSION;
opo->header.type = OFPT_PACKET_OUT;
opo->header.length = htons(size);
opo->buffer_id = htonl(buffer_id);
opo->in_port = htons(in_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);
+
+ oao = (struct ofp_action_output *)&opo->actions[0];
+ oao->type = htons(OFPAT_OUTPUT);
+ oao->len = htons(sizeof *oao);
+ oao->port = htons(out_port);
+
+ opo->actions_len = htons(sizeof *oao);
return out;
}