ofp-util: Remove extra blank line.
[sliver-openvswitch.git] / lib / ofp-util.c
index 8d0f993..8a2f3fd 100644 (file)
@@ -111,7 +111,7 @@ ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
     flow_wildcards_init_catchall(wc);
     wc->wildcards = (OVS_FORCE flow_wildcards_t) ofpfw & WC_INVARIANTS;
 
-    /* Wildcard fields that aren't defined by ofp10_match or tun_id. */
+    /* Wildcard fields that aren't defined by ofp10_match. */
     wc->wildcards |= FWW_NW_ECN | FWW_NW_TTL;
 
     if (ofpfw & OFPFW10_NW_TOS) {
@@ -469,7 +469,6 @@ ofputil_cls_rule_to_ofp11_match(const struct cls_rule *rule,
         match->in_port = ofputil_port_to_ofp11(rule->flow.in_port);
     }
 
-
     memcpy(match->dl_src, rule->flow.dl_src, ETH_ADDR_LEN);
     for (i = 0; i < ETH_ADDR_LEN; i++) {
         match->dl_src_mask[i] = ~rule->wc.dl_src_mask[i];
@@ -595,18 +594,22 @@ size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols);
  * 1.0, 0x02 for OpenFlow 1.1).  Returns 0 if 'version' is not supported or
  * outside the valid range.  */
 enum ofputil_protocol
-ofputil_protocol_from_ofp_version(int version)
+ofputil_protocol_from_ofp_version(enum ofp_version version)
 {
     switch (version) {
-    case OFP10_VERSION: return OFPUTIL_P_OF10;
-    case OFP12_VERSION: return OFPUTIL_P_OF12;
-    default: return 0;
+    case OFP10_VERSION:
+        return OFPUTIL_P_OF10;
+    case OFP12_VERSION:
+        return OFPUTIL_P_OF12;
+    case OFP11_VERSION:
+    default:
+        return 0;
     }
 }
 
 /* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION,
  * OFP11_VERSION or OFP12_VERSION) that corresponds to 'protocol'. */
-uint8_t
+enum ofp_version
 ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
 {
     switch (protocol) {
@@ -1262,11 +1265,8 @@ struct ofpbuf *
 ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
                         enum ofputil_protocol protocol)
 {
-    struct ofp10_flow_mod *ofm;
-    struct nx_flow_mod *nfm;
     struct ofpbuf *msg;
     uint16_t command;
-    int match_len;
 
     command = (protocol & OFPUTIL_P_TID
                ? (fm->command & 0xff) | (fm->table_id << 8)
@@ -1274,7 +1274,9 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
 
     switch (protocol) {
     case OFPUTIL_P_OF10:
-    case OFPUTIL_P_OF10_TID:
+    case OFPUTIL_P_OF10_TID: {
+        struct ofp10_flow_mod *ofm;
+
         msg = ofpraw_alloc(OFPRAW_OFPT10_FLOW_MOD, OFP10_VERSION,
                            fm->ofpacts_len);
         ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
@@ -1288,9 +1290,13 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         ofm->out_port = htons(fm->out_port);
         ofm->flags = htons(fm->flags);
         break;
+    }
 
     case OFPUTIL_P_NXM:
-    case OFPUTIL_P_NXM_TID:
+    case OFPUTIL_P_NXM_TID: {
+        struct nx_flow_mod *nfm;
+        int match_len;
+
         msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD, OFP10_VERSION,
                            NXM_TYPICAL_LEN + fm->ofpacts_len);
         nfm = ofpbuf_put_zeros(msg, sizeof *nfm);
@@ -1307,6 +1313,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         nfm->flags = htons(fm->flags);
         nfm->match_len = htons(match_len);
         break;
+    }
 
     case OFPUTIL_P_OF12:
     default:
@@ -2191,10 +2198,17 @@ ofputil_decode_ofp11_port(struct ofputil_phy_port *pp,
 }
 
 static size_t
-ofputil_get_phy_port_size(uint8_t ofp_version)
-{
-    return ofp_version == OFP10_VERSION ? sizeof(struct ofp10_phy_port)
-                                        : sizeof(struct ofp11_port);
+ofputil_get_phy_port_size(enum ofp_version ofp_version)
+{
+    switch (ofp_version) {
+    case OFP10_VERSION:
+        return sizeof(struct ofp10_phy_port);
+    case OFP11_VERSION:
+    case OFP12_VERSION:
+        return sizeof(struct ofp11_port);
+    default:
+        NOT_REACHED();
+    }
 }
 
 static void
@@ -2239,46 +2253,66 @@ ofputil_encode_ofp11_port(const struct ofputil_phy_port *pp,
 }
 
 static void
-ofputil_put_phy_port(uint8_t ofp_version, const struct ofputil_phy_port *pp,
-                     struct ofpbuf *b)
+ofputil_put_phy_port(enum ofp_version ofp_version,
+                     const struct ofputil_phy_port *pp, struct ofpbuf *b)
 {
-    if (ofp_version == OFP10_VERSION) {
+    switch (ofp_version) {
+    case OFP10_VERSION: {
         struct ofp10_phy_port *opp;
         if (b->size + sizeof *opp <= UINT16_MAX) {
             opp = ofpbuf_put_uninit(b, sizeof *opp);
             ofputil_encode_ofp10_phy_port(pp, opp);
         }
-    } else {
+        break;
+    }
+
+    case OFP11_VERSION:
+    case OFP12_VERSION: {
         struct ofp11_port *op;
         if (b->size + sizeof *op <= UINT16_MAX) {
             op = ofpbuf_put_uninit(b, sizeof *op);
             ofputil_encode_ofp11_port(pp, op);
         }
+        break;
+    }
+
+    default:
+        NOT_REACHED();
     }
 }
 
 void
-ofputil_append_port_desc_stats_reply(uint8_t ofp_version,
+ofputil_append_port_desc_stats_reply(enum ofp_version ofp_version,
                                      const struct ofputil_phy_port *pp,
                                      struct list *replies)
 {
-    if (ofp_version == OFP10_VERSION) {
+    switch (ofp_version) {
+    case OFP10_VERSION: {
         struct ofp10_phy_port *opp;
 
         opp = ofpmp_append(replies, sizeof *opp);
         ofputil_encode_ofp10_phy_port(pp, opp);
-    } else {
+        break;
+    }
+
+    case OFP11_VERSION:
+    case OFP12_VERSION: {
         struct ofp11_port *op;
 
         op = ofpmp_append(replies, sizeof *op);
         ofputil_encode_ofp11_port(pp, op);
+        break;
+    }
+
+    default:
+      NOT_REACHED();
     }
 }
 \f
 /* ofputil_switch_features */
 
 #define OFPC_COMMON (OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
-                     OFPC_IP_REASM | OFPC_QUEUE_STATS | OFPC_ARP_MATCH_IP)
+                     OFPC_IP_REASM | OFPC_QUEUE_STATS)
 BUILD_ASSERT_DECL((int) OFPUTIL_C_FLOW_STATS == OFPC_FLOW_STATS);
 BUILD_ASSERT_DECL((int) OFPUTIL_C_TABLE_STATS == OFPC_TABLE_STATS);
 BUILD_ASSERT_DECL((int) OFPUTIL_C_PORT_STATS == OFPC_PORT_STATS);
@@ -2336,6 +2370,23 @@ static const struct ofputil_action_bit_translation of11_action_bits[] = {
     { 0, 0 },
 };
 
+static const struct ofputil_action_bit_translation of12_action_bits[] = {
+    { OFPUTIL_A_OUTPUT,         OFPAT12_OUTPUT },
+    { OFPUTIL_A_COPY_TTL_OUT,   OFPAT12_COPY_TTL_OUT },
+    { OFPUTIL_A_COPY_TTL_IN,    OFPAT12_COPY_TTL_IN },
+    { OFPUTIL_A_SET_MPLS_TTL,   OFPAT12_SET_MPLS_TTL },
+    { OFPUTIL_A_DEC_MPLS_TTL,   OFPAT12_DEC_MPLS_TTL },
+    { OFPUTIL_A_PUSH_VLAN,      OFPAT12_PUSH_VLAN },
+    { OFPUTIL_A_POP_VLAN,       OFPAT12_POP_VLAN },
+    { OFPUTIL_A_PUSH_MPLS,      OFPAT12_PUSH_MPLS },
+    { OFPUTIL_A_POP_MPLS,       OFPAT12_POP_MPLS },
+    { OFPUTIL_A_SET_QUEUE,      OFPAT12_SET_QUEUE },
+    { OFPUTIL_A_GROUP,          OFPAT12_GROUP },
+    { OFPUTIL_A_SET_NW_TTL,     OFPAT12_SET_NW_TTL },
+    { OFPUTIL_A_DEC_NW_TTL,     OFPAT12_DEC_NW_TTL },
+    { 0, 0 },
+};
+
 static enum ofputil_action_bitmap
 decode_action_bits(ovs_be32 of_actions,
                    const struct ofputil_action_bit_translation *x)
@@ -2351,6 +2402,22 @@ decode_action_bits(ovs_be32 of_actions,
     return ofputil_actions;
 }
 
+static uint32_t
+ofputil_capabilities_mask(enum ofp_version ofp_version)
+{
+    /* Handle capabilities whose bit is unique for all Open Flow versions */
+    switch (ofp_version) {
+    case OFP10_VERSION:
+    case OFP11_VERSION:
+        return OFPC_COMMON | OFPC_ARP_MATCH_IP;
+    case OFP12_VERSION:
+        return OFPC_COMMON | OFPC12_PORT_BLOCKED;
+    default:
+        /* Caller needs to check osf->header.version itself */
+        return 0;
+    }
+}
+
 /* Decodes an OpenFlow 1.0 or 1.1 "switch_features" structure 'osf' into an
  * abstract representation in '*features'.  Initializes '*b' to iterate over
  * the OpenFlow port structures following 'osf' with later calls to
@@ -2372,7 +2439,8 @@ ofputil_decode_switch_features(const struct ofp_header *oh,
     features->n_buffers = ntohl(osf->n_buffers);
     features->n_tables = osf->n_tables;
 
-    features->capabilities = ntohl(osf->capabilities) & OFPC_COMMON;
+    features->capabilities = ntohl(osf->capabilities) &
+        ofputil_capabilities_mask(oh->version);
 
     if (b->size % ofputil_get_phy_port_size(oh->version)) {
         return OFPERR_OFPBRC_BAD_LEN;
@@ -2387,7 +2455,19 @@ ofputil_decode_switch_features(const struct ofp_header *oh,
         if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) {
             features->capabilities |= OFPUTIL_C_GROUP_STATS;
         }
-        features->actions = decode_action_bits(osf->actions, of11_action_bits);
+        switch ((enum ofp_version)oh->version) {
+        case OFP11_VERSION:
+            features->actions = decode_action_bits(htonl(UINT32_MAX),
+                                                   of11_action_bits);
+            break;
+        case OFP12_VERSION:
+            features->actions = decode_action_bits(htonl(UINT32_MAX),
+                                                   of12_action_bits);
+            break;
+        case OFP10_VERSION:
+        default:
+            NOT_REACHED();
+        }
     } else {
         return OFPERR_OFPBRC_BAD_VERSION;
     }
@@ -2452,29 +2532,45 @@ ofputil_encode_switch_features(const struct ofputil_switch_features *features,
 {
     struct ofp_switch_features *osf;
     struct ofpbuf *b;
-    uint8_t version;
+    enum ofp_version version;
+    enum ofpraw raw;
 
     version = ofputil_protocol_to_ofp_version(protocol);
-    b = ofpraw_alloc_xid(version == OFP10_VERSION
-                         ? OFPRAW_OFPT10_FEATURES_REPLY
-                         : OFPRAW_OFPT11_FEATURES_REPLY,
-                         version, xid, 0);
+    switch (version) {
+    case OFP10_VERSION:
+        raw = OFPRAW_OFPT10_FEATURES_REPLY;
+        break;
+    case OFP11_VERSION:
+    case OFP12_VERSION:
+        raw = OFPRAW_OFPT11_FEATURES_REPLY;
+        break;
+    default:
+        NOT_REACHED();
+    }
+    b = ofpraw_alloc_xid(raw, version, xid, 0);
     osf = ofpbuf_put_zeros(b, sizeof *osf);
     osf->datapath_id = htonll(features->datapath_id);
     osf->n_buffers = htonl(features->n_buffers);
     osf->n_tables = features->n_tables;
 
     osf->capabilities = htonl(features->capabilities & OFPC_COMMON);
-    if (version == OFP10_VERSION) {
+    osf->capabilities = htonl(features->capabilities &
+                              ofputil_capabilities_mask(version));
+    switch (version) {
+    case OFP10_VERSION:
         if (features->capabilities & OFPUTIL_C_STP) {
             osf->capabilities |= htonl(OFPC10_STP);
         }
         osf->actions = encode_action_bits(features->actions, of10_action_bits);
-    } else {
+        break;
+    case OFP11_VERSION:
+    case OFP12_VERSION:
         if (features->capabilities & OFPUTIL_C_GROUP_STATS) {
             osf->capabilities |= htonl(OFPC11_GROUP_STATS);
         }
-        osf->actions = encode_action_bits(features->actions, of11_action_bits);
+        break;
+    default:
+        NOT_REACHED();
     }
 
     return b;
@@ -2529,13 +2625,25 @@ ofputil_encode_port_status(const struct ofputil_port_status *ps,
 {
     struct ofp_port_status *ops;
     struct ofpbuf *b;
-    uint8_t version;
+    enum ofp_version version;
+    enum ofpraw raw;
 
     version = ofputil_protocol_to_ofp_version(protocol);
-    b = ofpraw_alloc_xid(version == OFP10_VERSION
-                         ? OFPRAW_OFPT10_PORT_STATUS
-                         : OFPRAW_OFPT11_PORT_STATUS,
-                         version, htonl(0), 0);
+    switch (version) {
+    case OFP10_VERSION:
+        raw = OFPRAW_OFPT10_PORT_STATUS;
+        break;
+
+    case OFP11_VERSION:
+    case OFP12_VERSION:
+        raw = OFPRAW_OFPT11_PORT_STATUS;
+        break;
+
+    default:
+        NOT_REACHED();
+    }
+
+    b = ofpraw_alloc_xid(raw, version, htonl(0), 0);
     ops = ofpbuf_put_zeros(b, sizeof *ops);
     ops->reason = ps->reason;
     ofputil_put_phy_port(version, &ps->desc, b);
@@ -2593,10 +2701,11 @@ struct ofpbuf *
 ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
                         enum ofputil_protocol protocol)
 {
-    uint8_t ofp_version = ofputil_protocol_to_ofp_version(protocol);
+    enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
     struct ofpbuf *b;
 
-    if (ofp_version == OFP10_VERSION) {
+    switch (ofp_version) {
+    case OFP10_VERSION: {
         struct ofp10_port_mod *opm;
 
         b = ofpraw_alloc(OFPRAW_OFPT10_PORT_MOD, ofp_version, 0);
@@ -2606,7 +2715,10 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
         opm->config = htonl(pm->config & OFPPC10_ALL);
         opm->mask = htonl(pm->mask & OFPPC10_ALL);
         opm->advertise = netdev_port_features_to_ofp10(pm->advertise);
-    } else if (ofp_version == OFP11_VERSION) {
+        break;
+    }
+
+    case OFP11_VERSION: {
         struct ofp11_port_mod *opm;
 
         b = ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD, ofp_version, 0);
@@ -2616,7 +2728,11 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
         opm->config = htonl(pm->config & OFPPC11_ALL);
         opm->mask = htonl(pm->mask & OFPPC11_ALL);
         opm->advertise = netdev_port_features_to_ofp11(pm->advertise);
-    } else {
+        break;
+    }
+
+    case OFP12_VERSION:
+    default:
         NOT_REACHED();
     }
 
@@ -3106,16 +3222,22 @@ ofputil_format_port(uint16_t port, struct ds *s)
  * port and returns 0.  If no ports remain to be decoded, returns EOF.
  * On an error, returns a positive OFPERR_* value. */
 int
-ofputil_pull_phy_port(uint8_t ofp_version, struct ofpbuf *b,
+ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b,
                       struct ofputil_phy_port *pp)
 {
-    if (ofp_version == OFP10_VERSION) {
+    switch (ofp_version) {
+    case OFP10_VERSION: {
         const struct ofp10_phy_port *opp = ofpbuf_try_pull(b, sizeof *opp);
         return opp ? ofputil_decode_ofp10_phy_port(pp, opp) : EOF;
-    } else {
+    }
+    case OFP11_VERSION:
+    case OFP12_VERSION: {
         const struct ofp11_port *op = ofpbuf_try_pull(b, sizeof *op);
         return op ? ofputil_decode_ofp11_port(pp, op) : EOF;
     }
+    default:
+        NOT_REACHED();
+    }
 }
 
 /* Given a buffer 'b' that contains an array of OpenFlow ports of type