unification of netdev&netdev_dev in pltap&tunnel
[sliver-openvswitch.git] / lib / ofp-util.c
index 6d88512..2ca0077 100644 (file)
@@ -23,7 +23,6 @@
 #include <netinet/in.h>
 #include <netinet/icmp6.h>
 #include <stdlib.h>
-#include "autopath.h"
 #include "bundle.h"
 #include "byte-order.h"
 #include "classifier.h"
@@ -85,7 +84,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
 void
 ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
 {
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
 
     /* Initialize most of wc. */
     flow_wildcards_init_catchall(wc);
@@ -923,7 +922,7 @@ ofputil_version_from_string(const char *s)
 }
 
 static bool
-is_delimiter(char c)
+is_delimiter(unsigned char c)
 {
     return isspace(c) || c == ',';
 }
@@ -1040,16 +1039,6 @@ regs_fully_wildcarded(const struct flow_wildcards *wc)
     return true;
 }
 
-static bool
-tun_parms_fully_wildcarded(const struct flow_wildcards *wc)
-{
-    return (!wc->masks.tunnel.ip_src &&
-            !wc->masks.tunnel.ip_dst &&
-            !wc->masks.tunnel.ip_ttl &&
-            !wc->masks.tunnel.ip_tos &&
-            !wc->masks.tunnel.flags);
-}
-
 /* Returns a bit-mask of ofputil_protocols that can be used for sending 'match'
  * to a switch (e.g. to add or remove a flow).  Only NXM can handle tunnel IDs,
  * registers, or fixing the Ethernet multicast bit.  Otherwise, it's better to
@@ -1059,10 +1048,11 @@ ofputil_usable_protocols(const struct match *match)
 {
     const struct flow_wildcards *wc = &match->wc;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
 
-    /* tunnel params other than tun_id can't be sent in a flow_mod */
-    if (!tun_parms_fully_wildcarded(wc)) {
+    /* These tunnel params can't be sent in a flow_mod */
+    if (wc->masks.tunnel.ip_ttl
+        || wc->masks.tunnel.ip_tos || wc->masks.tunnel.flags) {
         return OFPUTIL_P_NONE;
     }
 
@@ -1108,8 +1098,10 @@ ofputil_usable_protocols(const struct match *match)
             | OFPUTIL_P_OF13_OXM;
     }
 
-    /* NXM and OXM support matching tun_id. */
-    if (wc->masks.tunnel.tun_id != htonll(0)) {
+    /* NXM and OXM support matching tun_id, tun_src, and tun_dst. */
+    if (wc->masks.tunnel.tun_id != htonll(0)
+        || wc->masks.tunnel.ip_src != htonl(0)
+        || wc->masks.tunnel.ip_dst != htonl(0)) {
         return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
             | OFPUTIL_P_OF13_OXM;
     }
@@ -2346,7 +2338,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
         fr->priority = ntohs(nfr->priority);
         fr->cookie = nfr->cookie;
         fr->reason = nfr->reason;
-        fr->table_id = 255;
+        fr->table_id = nfr->table_id ? nfr->table_id - 1 : 255;
         fr->duration_sec = ntohl(nfr->duration_sec);
         fr->duration_nsec = ntohl(nfr->duration_nsec);
         fr->idle_timeout = ntohs(nfr->idle_timeout);
@@ -2425,6 +2417,7 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
         nfr->cookie = fr->cookie;
         nfr->priority = htons(fr->priority);
         nfr->reason = fr->reason;
+        nfr->table_id = fr->table_id + 1;
         nfr->duration_sec = htonl(fr->duration_sec);
         nfr->duration_nsec = htonl(fr->duration_nsec);
         nfr->idle_timeout = htons(fr->idle_timeout);
@@ -2450,6 +2443,8 @@ ofputil_decode_packet_in_finish(struct ofputil_packet_in *pin,
 
     pin->fmd.in_port = match->flow.in_port;
     pin->fmd.tun_id = match->flow.tunnel.tun_id;
+    pin->fmd.tun_src = match->flow.tunnel.ip_src;
+    pin->fmd.tun_dst = match->flow.tunnel.ip_dst;
     pin->fmd.metadata = match->flow.metadata;
     memcpy(pin->fmd.regs, match->flow.regs, sizeof pin->fmd.regs);
 }
@@ -2550,6 +2545,12 @@ ofputil_packet_in_to_match(const struct ofputil_packet_in *pin,
     if (pin->fmd.tun_id != htonll(0)) {
         match_set_tun_id(match, pin->fmd.tun_id);
     }
+    if (pin->fmd.tun_src != htonl(0)) {
+        match_set_tun_src(match, pin->fmd.tun_src);
+    }
+    if (pin->fmd.tun_dst != htonl(0)) {
+        match_set_tun_dst(match, pin->fmd.tun_dst);
+    }
     if (pin->fmd.metadata != htonll(0)) {
         match_set_metadata(match, pin->fmd.metadata);
     }
@@ -3383,43 +3384,54 @@ 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 ||
+        raw == OFPRAW_OFPT12_ROLE_REPLY) {
+        const struct ofp12_role_request *orr = b.l3;
 
-        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;
-            }
+        if (orr->role != htonl(OFPCR12_ROLE_NOCHANGE) &&
+            orr->role != htonl(OFPCR12_ROLE_EQUAL) &&
+            orr->role != htonl(OFPCR12_ROLE_MASTER) &&
+            orr->role != htonl(OFPCR12_ROLE_SLAVE)) {
+            return OFPERR_OFPRRFC_BAD_ROLE;
         }
 
-        /* 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;
-    }
+        rr->role = ntohl(orr->role);
+        if (raw == OFPRAW_OFPT12_ROLE_REQUEST
+            ? orr->role == htonl(OFPCR12_ROLE_NOCHANGE)
+            : orr->generation_id == htonll(UINT64_MAX)) {
+            rr->have_generation_id = false;
+            rr->generation_id = 0;
+        } else {
+            rr->have_generation_id = true;
+            rr->generation_id = ntohll(orr->generation_id);
+        }
+    } else if (raw == OFPRAW_NXT_ROLE_REQUEST ||
+               raw == OFPRAW_NXT_ROLE_REPLY) {
+        const struct nx_role_request *nrr = b.l3;
+
+        BUILD_ASSERT(NX_ROLE_OTHER + 1 == OFPCR12_ROLE_EQUAL);
+        BUILD_ASSERT(NX_ROLE_MASTER + 1 == OFPCR12_ROLE_MASTER);
+        BUILD_ASSERT(NX_ROLE_SLAVE + 1 == OFPCR12_ROLE_SLAVE);
+
+        if (nrr->role != htonl(NX_ROLE_OTHER) &&
+            nrr->role != htonl(NX_ROLE_MASTER) &&
+            nrr->role != htonl(NX_ROLE_SLAVE)) {
+            return OFPERR_OFPRRFC_BAD_ROLE;
+        }
 
-    if (role != NX_ROLE_OTHER && role != NX_ROLE_MASTER
-        && role != NX_ROLE_SLAVE) {
-        return OFPERR_OFPRRFC_BAD_ROLE;
+        rr->role = ntohl(nrr->role) + 1;
+        rr->have_generation_id = false;
+        rr->generation_id = 0;
+    } else {
+        NOT_REACHED();
     }
 
-    rr->role = role;
     return 0;
 }
 
@@ -3427,47 +3439,35 @@ ofputil_decode_role_message(const struct ofp_header *oh,
  * buffer owned by the caller. */
 struct ofpbuf *
 ofputil_encode_role_reply(const struct ofp_header *request,
-                          enum nx_role role)
+                          const struct ofputil_role_request *rr)
 {
-    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);
+    raw = ofpraw_decode_assert(request);
     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();
-    }
+        struct ofp12_role_request *orr;
 
-    buf = ofpraw_alloc_reply(raw, request, 0);
-    reply = ofpbuf_put_zeros(buf, reply_size);
+        buf = ofpraw_alloc_reply(OFPRAW_OFPT12_ROLE_REPLY, request, 0);
+        orr = ofpbuf_put_zeros(buf, sizeof *orr);
 
-    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.
-         */
+        orr->role = htonl(rr->role);
+        orr->generation_id = htonll(rr->have_generation_id
+                                    ? rr->generation_id
+                                    : UINT64_MAX);
+    } else if (raw == OFPRAW_NXT_ROLE_REQUEST) {
+        struct nx_role_request *nrr;
+
+        BUILD_ASSERT(NX_ROLE_OTHER == OFPCR12_ROLE_EQUAL - 1);
+        BUILD_ASSERT(NX_ROLE_MASTER == OFPCR12_ROLE_MASTER - 1);
+        BUILD_ASSERT(NX_ROLE_SLAVE == OFPCR12_ROLE_SLAVE - 1);
+
+        buf = ofpraw_alloc_reply(OFPRAW_NXT_ROLE_REPLY, request, 0);
+        nrr = ofpbuf_put_zeros(buf, sizeof *nrr);
+        nrr->role = htonl(rr->role - 1);
+    } else {
+        NOT_REACHED();
     }
-    reply->role = htonl(role);
 
     return buf;
 }
@@ -4236,7 +4236,7 @@ size_t ofputil_count_phy_ports(uint8_t ofp_version, struct ofpbuf *b)
 int
 ofputil_action_code_from_name(const char *name)
 {
-    static const char *names[OFPUTIL_N_ACTIONS] = {
+    static const char *const names[OFPUTIL_N_ACTIONS] = {
         NULL,
 #define OFPAT10_ACTION(ENUM, STRUCT, NAME)             NAME,
 #define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME,
@@ -4244,7 +4244,7 @@ ofputil_action_code_from_name(const char *name)
 #include "ofp-util.def"
     };
 
-    const char **p;
+    const char *const *p;
 
     for (p = names; p < &names[ARRAY_SIZE(names)]; p++) {
         if (*p && !strcasecmp(name, *p)) {
@@ -4521,7 +4521,7 @@ ofputil_parse_key_value(char **stringp, char **keyp, char **valuep)
  * will be for Open Flow version 'ofp_version'. Returns message
  * as a struct ofpbuf. Returns encoded message on success, NULL on error */
 struct ofpbuf *
-ofputil_encode_dump_ports_request(enum ofp_version ofp_version, int16_t port)
+ofputil_encode_dump_ports_request(enum ofp_version ofp_version, uint16_t port)
 {
     struct ofpbuf *request;