Replace most uses of assert by ovs_assert.
[sliver-openvswitch.git] / lib / ofp-util.c
index 49cbe2d..c66cd40 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -807,7 +807,7 @@ ofputil_protocols_to_string(enum ofputil_protocol protocols)
 {
     struct ds s;
 
-    assert(!(protocols & ~OFPUTIL_P_ANY));
+    ovs_assert(!(protocols & ~OFPUTIL_P_ANY));
     if (protocols == 0) {
         return xstrdup("none");
     }
@@ -1067,6 +1067,11 @@ ofputil_usable_protocols(const struct match *match)
         return OFPUTIL_P_NONE;
     }
 
+    /* skb_mark and skb_priority can't be sent in a flow_mod */
+    if (wc->masks.skb_mark || wc->masks.skb_priority) {
+        return OFPUTIL_P_NONE;
+    }
+
     /* NXM, OXM, and OF1.1 support bitwise matching on ethernet addresses. */
     if (!eth_mask_is_exact(wc->masks.dl_src)
         && !eth_addr_is_zero(wc->masks.dl_src)) {
@@ -1362,7 +1367,7 @@ ofputil_encode_set_protocol(enum ofputil_protocol current,
         return ofputil_make_flow_mod_table_id(want_tid);
     }
 
-    assert(current == want);
+    ovs_assert(current == want);
 
     *next = current;
     return NULL;
@@ -1376,7 +1381,7 @@ ofputil_encode_nx_set_flow_format(enum nx_flow_format nxff)
     struct nx_set_flow_format *sff;
     struct ofpbuf *msg;
 
-    assert(ofputil_nx_flow_format_is_valid(nxff));
+    ovs_assert(ofputil_nx_flow_format_is_valid(nxff));
 
     msg = ofpraw_alloc(OFPRAW_NXT_SET_FLOW_FORMAT, OFP10_VERSION, 0);
     sff = ofpbuf_put_zeros(msg, sizeof *sff);
@@ -1590,11 +1595,13 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
         if (fm->flags & OFPFF10_EMERG) {
             /* We do not support the OpenFlow 1.0 emergency flow cache, which
              * is not required in OpenFlow 1.0.1 and removed from OpenFlow 1.1.
-             * There is no good error code, so just state that the flow table
-             * is full.
-             * Moreover, OFPFF10_EMERG overlaps with OFPFF12_RESET_COUNTS,
-             * so this check must be here */
-            return OFPERR_OFPFMFC_TABLE_FULL;
+             *
+             * OpenFlow 1.0 specifies the error code to use when idle_timeout
+             * or hard_timeout is nonzero.  Otherwise, there is no good error
+             * code, so just state that the flow table is full. */
+            return (fm->hard_timeout || fm->idle_timeout
+                    ? OFPERR_OFPFMFC_BAD_EMERG_TIMEOUT
+                    : OFPERR_OFPFMFC_TABLE_FULL);
         }
 
         if (protocol & OFPUTIL_P_TID) {
@@ -2288,7 +2295,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
         fr->packet_count = ntohll(ofr->packet_count);
         fr->byte_count = ntohll(ofr->byte_count);
     } else if (raw == OFPRAW_OFPT10_FLOW_REMOVED) {
-        const struct ofp_flow_removed *ofr;
+        const struct ofp10_flow_removed *ofr;
 
         ofr = ofpbuf_pull(&b, sizeof *ofr);
 
@@ -2368,7 +2375,7 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
 
     case OFPUTIL_P_OF10_STD:
     case OFPUTIL_P_OF10_STD_TID: {
-        struct ofp_flow_removed *ofr;
+        struct ofp10_flow_removed *ofr;
 
         msg = ofpraw_alloc_xid(OFPRAW_OFPT10_FLOW_REMOVED, OFP10_VERSION,
                                htonl(0), 0);
@@ -2472,9 +2479,9 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin,
 
         ofputil_decode_packet_in_finish(pin, &match, &b);
     } else if (raw == OFPRAW_OFPT10_PACKET_IN) {
-        const struct ofp_packet_in *opi;
+        const struct ofp10_packet_in *opi;
 
-        opi = ofpbuf_pull(&b, offsetof(struct ofp_packet_in, data));
+        opi = ofpbuf_pull(&b, offsetof(struct ofp10_packet_in, data));
 
         pin->packet = opi->data;
         pin->packet_len = b.size;
@@ -2585,11 +2592,11 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin,
             opi->cookie = pin->cookie;
         }
     } else if (packet_in_format == NXPIF_OPENFLOW10) {
-        struct ofp_packet_in *opi;
+        struct ofp10_packet_in *opi;
 
         packet = ofpraw_alloc_xid(OFPRAW_OFPT10_PACKET_IN, OFP10_VERSION,
                                   htonl(0), send_len);
-        opi = ofpbuf_put_zeros(packet, offsetof(struct ofp_packet_in, data));
+        opi = ofpbuf_put_zeros(packet, offsetof(struct ofp10_packet_in, data));
         opi->total_len = htons(pin->total_len);
         opi->in_port = htons(pin->fmd.in_port);
         opi->reason = pin->reason;
@@ -2698,7 +2705,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
         }
     } else if (raw == OFPRAW_OFPT10_PACKET_OUT) {
         enum ofperr error;
-        const struct ofp_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
+        const struct ofp10_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
 
         po->buffer_id = ntohl(opo->buffer_id);
         po->in_port = ntohs(opo->in_port);
@@ -3190,7 +3197,9 @@ ofputil_put_switch_features_port(const struct ofputil_phy_port *pp,
 {
     const struct ofp_header *oh = b->data;
 
-    ofputil_put_phy_port(oh->version, pp, b);
+    if (oh->version < OFP13_VERSION) {
+        ofputil_put_phy_port(oh->version, pp, b);
+    }
 }
 \f
 /* ofputil_port_status */
@@ -3217,7 +3226,7 @@ ofputil_decode_port_status(const struct ofp_header *oh,
     ps->reason = ops->reason;
 
     retval = ofputil_pull_phy_port(oh->version, &b, &ps->desc);
-    assert(retval != EOF);
+    ovs_assert(retval != EOF);
     return retval;
 }
 
@@ -3346,6 +3355,104 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
     return b;
 }
 \f
+/* ofputil_role_request */
+
+/* Decodes the OpenFlow "role request" or "role reply" message in '*oh' into
+ * an abstract form in '*rr'.  Returns 0 if successful, otherwise an
+ * OFPERR_* value. */
+enum ofperr
+ofputil_decode_role_message(const struct ofp_header *oh,
+                            struct ofputil_role_request *rr)
+{
+    const struct ofp12_role_request *orr = ofpmsg_body(oh);
+    uint32_t role = ntohl(orr->role);
+    struct ofpbuf b;
+    enum ofpraw raw;
+
+    memset(rr, 0, sizeof *rr);
+
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
+    raw = ofpraw_pull_assert(&b);
+
+    if (raw == OFPRAW_OFPT12_ROLE_REQUEST
+        || raw == OFPRAW_OFPT12_ROLE_REPLY) {
+
+        if (raw == OFPRAW_OFPT12_ROLE_REQUEST) {
+            if (role == OFPCR12_ROLE_NOCHANGE) {
+                rr->request_current_role_only = true;
+                return 0;
+            }
+            if (role == OFPCR12_ROLE_MASTER || role == OFPCR12_ROLE_SLAVE) {
+                rr->generation_id = ntohll(orr->generation_id);
+                rr->have_generation_id = true;
+            }
+        }
+
+        /* Map to enum nx_role */
+        role -= 1; /* OFPCR12_ROLE_MASTER -> NX_ROLE_MASTER etc. */
+    } else if (raw != OFPRAW_NXT_ROLE_REQUEST
+               && raw != OFPRAW_NXT_ROLE_REPLY) {
+        return OFPERR_OFPBRC_BAD_TYPE;
+    }
+
+    if (role != NX_ROLE_OTHER && role != NX_ROLE_MASTER
+        && role != NX_ROLE_SLAVE) {
+        return OFPERR_OFPRRFC_BAD_ROLE;
+    }
+
+    rr->role = role;
+    return 0;
+}
+
+/* Returns an encoded form of a role reply suitable for the "request" in a
+ * buffer owned by the caller. */
+struct ofpbuf *
+ofputil_encode_role_reply(const struct ofp_header *request,
+                          enum nx_role role)
+{
+    struct ofp12_role_request *reply;
+    struct ofpbuf *buf;
+    size_t reply_size;
+
+    struct ofpbuf b;
+    enum ofpraw raw;
+
+    ofpbuf_use_const(&b, request, ntohs(request->length));
+    raw = ofpraw_pull_assert(&b);
+    if (raw == OFPRAW_OFPT12_ROLE_REQUEST) {
+        reply_size = sizeof (struct ofp12_role_request);
+        raw = OFPRAW_OFPT12_ROLE_REPLY;
+    }
+    else if (raw == OFPRAW_NXT_ROLE_REQUEST) {
+        reply_size = sizeof (struct nx_role_request);
+        raw = OFPRAW_NXT_ROLE_REPLY;
+    } else {
+        NOT_REACHED();
+    }
+
+    buf = ofpraw_alloc_reply(raw, request, 0);
+    reply = ofpbuf_put_zeros(buf, reply_size);
+
+    if (raw == OFPRAW_OFPT12_ROLE_REPLY) {
+        /* Map to OpenFlow enum ofp12_controller_role */
+        role += 1; /* NX_ROLE_MASTER -> OFPCR12_ROLE_MASTER etc. */
+        /*
+         * OpenFlow specification does not specify use of generation_id field
+         * on reply messages.  Intuitively, it would seem a good idea to return
+         * the current value.  However, the current value is undefined
+         * initially, and there is no way to insert an undefined value in the
+         * message.  Therefore we leave the generation_id zeroed on reply
+         * messages.
+         *
+         * A request for clarification has been filed with the Open Networking
+         * Foundation as EXT-272.
+         */
+    }
+    reply->role = htonl(role);
+
+    return buf;
+}
+\f
 /* Table stats. */
 
 static void
@@ -3353,7 +3460,7 @@ ofputil_put_ofp10_table_stats(const struct ofp12_table_stats *in,
                               struct ofpbuf *buf)
 {
     struct wc_map {
-        enum ofp_flow_wildcards wc10;
+        enum ofp10_flow_wildcards wc10;
         enum oxm12_ofb_match_fields mf12;
     };
 
@@ -3375,9 +3482,9 @@ ofputil_put_ofp10_table_stats(const struct ofp12_table_stats *in,
     struct ofp10_table_stats *out;
     const struct wc_map *p;
 
-    out = ofpbuf_put_uninit(buf, sizeof *out);
+    out = ofpbuf_put_zeros(buf, sizeof *out);
     out->table_id = in->table_id;
-    strcpy(out->name, in->name);
+    ovs_strlcpy(out->name, in->name, sizeof out->name);
     out->wildcards = 0;
     for (p = wc_map; p < &wc_map[ARRAY_SIZE(wc_map)]; p++) {
         if (in->wildcards & htonll(1ULL << p->mf12)) {
@@ -3435,9 +3542,9 @@ ofputil_put_ofp11_table_stats(const struct ofp12_table_stats *in,
 {
     struct ofp11_table_stats *out;
 
-    out = ofpbuf_put_uninit(buf, sizeof *out);
+    out = ofpbuf_put_zeros(buf, sizeof *out);
     out->table_id = in->table_id;
-    strcpy(out->name, in->name);
+    ovs_strlcpy(out->name, in->name, sizeof out->name);
     out->wildcards = oxm12_to_ofp11_flow_match_fields(in->wildcards);
     out->match = oxm12_to_ofp11_flow_match_fields(in->match);
     out->instructions = in->instructions;
@@ -3681,7 +3788,7 @@ ofputil_decode_flow_update(struct ofputil_flow_update *update,
         VLOG_WARN_RL(&bad_ofmsg_rl,
                      "NXST_FLOW_MONITOR reply has bad event %"PRIu16,
                      ntohs(nfuh->event));
-        return OFPERR_OFPET_BAD_REQUEST;
+        return OFPERR_NXBRC_FM_BAD_EVENT;
     }
 
 bad_len:
@@ -3778,7 +3885,7 @@ ofputil_encode_packet_out(const struct ofputil_packet_out *po,
 
     switch (ofp_version) {
     case OFP10_VERSION: {
-        struct ofp_packet_out *opo;
+        struct ofp10_packet_out *opo;
         size_t actions_ofs;
 
         msg = ofpraw_alloc(OFPRAW_OFPT10_PACKET_OUT, OFP10_VERSION, size);
@@ -4021,7 +4128,7 @@ ofputil_port_from_string(const char *s, uint16_t *portp)
             return true;
         } else if (port32 < OFPP11_MAX) {
             VLOG_WARN("port %u is outside the supported range 0 through "
-                      "%"PRIx16"or 0x%x through 0x%"PRIx32, port32,
+                      "%"PRIx16" or 0x%x through 0x%"PRIx32, port32,
                       UINT16_MAX, (unsigned int) OFPP11_MAX, UINT32_MAX);
             return false;
         } else {