{ OFPUTIL_NXT_FLOW_AGE, OFP10_VERSION,
NXT_FLOW_AGE, "NXT_FLOW_AGE",
sizeof(struct nicira_header), 0 },
+
+ { OFPUTIL_NXT_SET_ASYNC_CONFIG, OFP10_VERSION,
+ NXT_SET_ASYNC_CONFIG, "NXT_SET_ASYNC_CONFIG",
+ sizeof(struct nx_async_config), 0 },
+
+ { OFPUTIL_NXT_SET_CONTROLLER_ID, OFP10_VERSION,
+ NXT_SET_CONTROLLER_ID, "NXT_SET_CONTROLLER_ID",
+ sizeof(struct nx_controller_id), 0 },
};
static const struct ofputil_msg_category nxt_category = {
return packet;
}
+const char *
+ofputil_packet_in_reason_to_string(enum ofp_packet_in_reason reason)
+{
+ static char s[INT_STRLEN(int) + 1];
+
+ switch (reason) {
+ case OFPR_NO_MATCH:
+ return "no_match";
+ case OFPR_ACTION:
+ return "action";
+ case OFPR_INVALID_TTL:
+ return "invalid_ttl";
+
+ case OFPR_N_REASONS:
+ default:
+ sprintf(s, "%d", (int) reason);
+ return s;
+ }
+}
+
+bool
+ofputil_packet_in_reason_from_string(const char *s,
+ enum ofp_packet_in_reason *reason)
+{
+ int i;
+
+ for (i = 0; i < OFPR_N_REASONS; i++) {
+ if (!strcasecmp(s, ofputil_packet_in_reason_to_string(i))) {
+ *reason = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+enum ofperr
+ofputil_decode_packet_out(struct ofputil_packet_out *po,
+ const struct ofp_packet_out *opo)
+{
+ enum ofperr error;
+ struct ofpbuf b;
+
+ po->buffer_id = ntohl(opo->buffer_id);
+ po->in_port = ntohs(opo->in_port);
+ if (po->in_port >= OFPP_MAX && po->in_port != OFPP_LOCAL
+ && po->in_port != OFPP_NONE) {
+ VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx16,
+ po->in_port);
+ return OFPERR_NXBRC_BAD_IN_PORT;
+ }
+
+ ofpbuf_use_const(&b, opo, ntohs(opo->header.length));
+ ofpbuf_pull(&b, sizeof *opo);
+
+ error = ofputil_pull_actions(&b, ntohs(opo->actions_len),
+ &po->actions, &po->n_actions);
+ if (error) {
+ return error;
+ }
+
+ if (po->buffer_id == UINT32_MAX) {
+ po->packet = b.data;
+ po->packet_len = b.size;
+ } else {
+ po->packet = NULL;
+ po->packet_len = 0;
+ }
+
+ return 0;
+}
+
+struct ofpbuf *
+ofputil_encode_packet_out(const struct ofputil_packet_out *po)
+{
+ struct ofp_packet_out *opo;
+ size_t actions_len;
+ struct ofpbuf *msg;
+ size_t size;
+
+ actions_len = po->n_actions * sizeof *po->actions;
+ size = sizeof *opo + actions_len;
+ if (po->buffer_id == UINT32_MAX) {
+ size += po->packet_len;
+ }
+
+ msg = ofpbuf_new(size);
+ opo = put_openflow(sizeof *opo, OFPT_PACKET_OUT, msg);
+ opo->buffer_id = htonl(po->buffer_id);
+ opo->in_port = htons(po->in_port);
+ opo->actions_len = htons(actions_len);
+ ofpbuf_put(msg, po->actions, actions_len);
+ if (po->buffer_id == UINT32_MAX) {
+ ofpbuf_put(msg, po->packet, po->packet_len);
+ }
+ update_openflow_length(msg);
+
+ return msg;
+}
+
/* Returns a string representing the message type of 'type'. The string is the
* enumeration constant for the type, e.g. "OFPT_HELLO". For statistics
* messages, the constant is followed by "request" or "reply",
return buf;
}
-struct ofpbuf *
-make_packet_out(const struct ofpbuf *packet, uint32_t buffer_id,
- uint16_t in_port,
- const struct ofp_action_header *actions, size_t n_actions)
-{
- size_t actions_len = n_actions * sizeof *actions;
- struct ofp_packet_out *opo;
- size_t size = sizeof *opo + actions_len + (packet ? packet->size : 0);
- struct ofpbuf *out = ofpbuf_new(size);
-
- opo = ofpbuf_put_uninit(out, sizeof *opo);
- opo->header.version = OFP_VERSION;
- opo->header.type = OFPT_PACKET_OUT;
- opo->header.length = htons(size);
- opo->header.xid = htonl(0);
- opo->buffer_id = htonl(buffer_id);
- opo->in_port = htons(in_port);
- opo->actions_len = htons(actions_len);
- ofpbuf_put(out, actions, actions_len);
- if (packet) {
- ofpbuf_put(out, packet->data, packet->size);
- }
- return out;
-}
-
-struct ofpbuf *
-make_unbuffered_packet_out(const struct ofpbuf *packet,
- uint16_t in_port, uint16_t out_port)
-{
- struct ofp_action_output action;
- action.type = htons(OFPAT_OUTPUT);
- action.len = htons(sizeof action);
- action.port = htons(out_port);
- return make_packet_out(packet, UINT32_MAX, in_port,
- (struct ofp_action_header *) &action, 1);
-}
-
-struct ofpbuf *
-make_buffered_packet_out(uint32_t buffer_id,
- uint16_t in_port, uint16_t out_port)
-{
- if (out_port != OFPP_NONE) {
- struct ofp_action_output action;
- action.type = htons(OFPAT_OUTPUT);
- action.len = htons(sizeof action);
- action.port = htons(out_port);
- return make_packet_out(NULL, buffer_id, in_port,
- (struct ofp_action_header *) &action, 1);
- } else {
- return make_packet_out(NULL, buffer_id, in_port, NULL, 0);
- }
-}
-
/* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */
struct ofpbuf *
make_echo_request(void)
return out;
}
+struct ofpbuf *
+ofputil_encode_barrier_request(void)
+{
+ struct ofpbuf *msg;
+
+ make_openflow(sizeof(struct ofp_header), OFPT_BARRIER_REQUEST, &msg);
+ return msg;
+}
+
const char *
ofputil_frag_handling_to_string(enum ofp_config_flags flags)
{
error = learn_check((const struct nx_action_learn *) a, flow);
break;
+ case OFPUTIL_NXAST_CONTROLLER:
+ if (((const struct nx_action_controller *) a)->zero) {
+ error = OFPERR_NXBAC_MUST_BE_ZERO;
+ }
+ break;
+
case OFPUTIL_OFPAT_STRIP_VLAN:
case OFPUTIL_OFPAT_SET_NW_SRC:
case OFPUTIL_OFPAT_SET_NW_DST:
case OFPUTIL_NXAST_SET_TUNNEL64:
case OFPUTIL_NXAST_EXIT:
case OFPUTIL_NXAST_DEC_TTL:
+ case OFPUTIL_NXAST_FIN_TIMEOUT:
break;
}