ofp-actions: Make ofpacts_format() caller add "actions=" if it wants it.
[sliver-openvswitch.git] / lib / ofp-actions.c
index 61e2854..1d0321a 100644 (file)
@@ -860,6 +860,12 @@ ofpact_from_openflow11(const union ofp_action *a, struct ofpbuf *out)
         break;
     }
 
+    case OFPUTIL_OFPAT11_GROUP: {
+        struct ofp11_action_group *oag = (struct ofp11_action_group *)a;
+        ofpact_put_GROUP(out)->group_id = ntohl(oag->group_id);
+        break;
+    }
+
 #define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
 #include "ofp-util.def"
         return ofpact_from_nxast(a, code, out);
@@ -878,14 +884,14 @@ ofpacts_from_openflow11(const union ofp_action *in, size_t n_in,
 /* OpenFlow 1.1 instructions. */
 
 #define DEFINE_INST(ENUM, STRUCT, EXTENSIBLE, NAME)             \
-    static inline const struct STRUCT *                         \
+    static inline const struct STRUCT * OVS_UNUSED              \
     instruction_get_##ENUM(const struct ofp11_instruction *inst)\
     {                                                           \
         ovs_assert(inst->type == htons(ENUM));                  \
         return ALIGNED_CAST(struct STRUCT *, inst);             \
     }                                                           \
                                                                 \
-    static inline void                                          \
+    static inline void OVS_UNUSED                               \
     instruction_init_##ENUM(struct STRUCT *s)                   \
     {                                                           \
         memset(s, 0, sizeof *s);                                \
@@ -893,7 +899,7 @@ ofpacts_from_openflow11(const union ofp_action *in, size_t n_in,
         s->len = htons(sizeof *s);                              \
     }                                                           \
                                                                 \
-    static inline struct STRUCT *                               \
+    static inline struct STRUCT * OVS_UNUSED                    \
     instruction_put_##ENUM(struct ofpbuf *buf)                  \
     {                                                           \
         struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s);   \
@@ -945,6 +951,7 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
     case OFPACT_GOTO_TABLE:
         return OVSINST_OFPIT11_GOTO_TABLE;
     case OFPACT_OUTPUT:
+    case OFPACT_GROUP:
     case OFPACT_CONTROLLER:
     case OFPACT_ENQUEUE:
     case OFPACT_OUTPUT_REG:
@@ -1302,6 +1309,9 @@ ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
         }
         return 0;
 
+    case OFPACT_GROUP:
+        return 0;
+
     default:
         NOT_REACHED();
     }
@@ -1598,6 +1608,7 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
         ofpact_sample_to_nxast(ofpact_get_SAMPLE(a), out);
         break;
 
+    case OFPACT_GROUP:
     case OFPACT_OUTPUT:
     case OFPACT_ENQUEUE:
     case OFPACT_SET_VLAN_VID:
@@ -1710,6 +1721,9 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
         /* XXX */
         break;
 
+    case OFPACT_GROUP:
+        break;
+
     case OFPACT_CONTROLLER:
     case OFPACT_OUTPUT_REG:
     case OFPACT_BUNDLE:
@@ -1882,6 +1896,11 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_METER:
         NOT_REACHED();
 
+    case OFPACT_GROUP:
+        ofputil_put_OFPAT11_GROUP(out)->group_id =
+            htonl(ofpact_get_GROUP(a)->group_id);
+        break;
+
     case OFPACT_CONTROLLER:
     case OFPACT_OUTPUT_REG:
     case OFPACT_BUNDLE:
@@ -2051,6 +2070,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_GOTO_TABLE:
     case OFPACT_METER:
+    case OFPACT_GROUP:
     default:
         return false;
     }
@@ -2073,12 +2093,54 @@ ofpacts_output_to_port(const struct ofpact *ofpacts, size_t ofpacts_len,
     return false;
 }
 
+/* Returns true if any action in the 'ofpacts_len' bytes of 'ofpacts' outputs
+ * to 'group', false otherwise. */
+bool
+ofpacts_output_to_group(const struct ofpact *ofpacts, size_t ofpacts_len,
+                        uint32_t group_id)
+{
+    const struct ofpact *a;
+
+    OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+        if (a->type == OFPACT_GROUP
+            && ofpact_get_GROUP(a)->group_id == group_id) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 bool
 ofpacts_equal(const struct ofpact *a, size_t a_len,
               const struct ofpact *b, size_t b_len)
 {
     return a_len == b_len && !memcmp(a, b, a_len);
 }
+
+/* Finds the OFPACT_METER action, if any, in the 'ofpacts_len' bytes of
+ * 'ofpacts'.  If found, returns its meter ID; if not, returns 0.
+ *
+ * This function relies on the order of 'ofpacts' being correct (as checked by
+ * ofpacts_verify()). */
+uint32_t
+ofpacts_get_meter(const struct ofpact ofpacts[], size_t ofpacts_len)
+{
+    const struct ofpact *a;
+
+    OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+        enum ovs_instruction_type inst;
+
+        inst = ovs_instruction_type_from_ofpact_type(a->type);
+        if (a->type == OFPACT_METER) {
+            return ofpact_get_METER(a)->meter_id;
+        } else if (inst > OVSINST_OFPIT13_METER) {
+            break;
+        }
+    }
+
+    return 0;
+}
 \f
 /* Formatting ofpacts. */
 
@@ -2366,7 +2428,7 @@ ofpact_format(const struct ofpact *a, struct ds *s)
                       ovs_instruction_name_from_type(
                           OVSINST_OFPIT11_WRITE_METADATA),
                       ntohll(metadata->metadata));
-        if (metadata->mask != htonll(UINT64_MAX)) {
+        if (metadata->mask != OVS_BE64_MAX) {
             ds_put_format(s, "/%#"PRIx64, ntohll(metadata->mask));
         }
         break;
@@ -2383,6 +2445,11 @@ ofpact_format(const struct ofpact *a, struct ds *s)
                       ovs_instruction_name_from_type(OVSINST_OFPIT13_METER),
                       ofpact_get_METER(a)->meter_id);
         break;
+
+    case OFPACT_GROUP:
+        ds_put_format(s, "group:%"PRIu32,
+                      ofpact_get_GROUP(a)->group_id);
+        break;
     }
 }
 
@@ -2392,7 +2459,6 @@ void
 ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len,
                struct ds *string)
 {
-    ds_put_cstr(string, "actions=");
     if (!ofpacts_len) {
         ds_put_cstr(string, "drop");
     } else {