Include NMX selection method experimenter group property in
in group mod request and group desc reply.

NMX selection method
Signed-off-by: Simon Horman <simon.hor...@netronome.com>

---
v2 Use list of struct field_array of TLVs rather than OF1.1 match
   for fields field of NMX selection method property
---
 lib/nx-match.c    | 37 +++++++++++++++++++++++++++++++++++++
 lib/nx-match.h    |  2 ++
 lib/ofp-util.c    | 38 +++++++++++++++++++++++++++++++++++++-
 lib/ofp-util.h    |  1 +
 ofproto/ofproto.c |  7 ++++++-
 5 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/lib/nx-match.c b/lib/nx-match.c
index 4f84619..82fcfc2 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -1068,6 +1068,43 @@ oxm_put_match(struct ofpbuf *b, const struct match 
*match,
     return match_len;
 }
 
+/* Appends to 'b' a series of OXM TLVs corresponding to the series
+ * of enum mf_field_id and value tuples in 'fa_'.
+ *
+ * OXM differs slightly among versions of OpenFlow.  Specify the OpenFlow
+ * version in use as 'version'.
+ *
+ * This function can cause 'b''s data to be reallocated.
+ *
+ * Returns the number of bytes appended to 'b'.  May return zero. */
+int
+oxm_put_field_array(struct ofpbuf *b, const struct ovs_list *field_array,
+                    enum ofp_version version)
+{
+    size_t start_len = ofpbuf_size(b);
+    const struct field_array *fa;
+
+    /* Field arrays are only used with the group selection method
+     * property and group properties are only available in OpenFlow * 1.5+.
+     * So the following assertion should never fail.
+     *
+     * If support for older OpenFlow versions is desired then some care
+     * will need to be taken of different TLVs that handle the same
+     * flow fields. In particular:
+     * - VLAN_TCI, VLAN_VID and MFF_VLAN_PCP
+     * - IP_DSCP_MASK and DSCP_SHIFTED
+     * - REGS and XREGS
+     */
+    ovs_assert(version >= OFP15_VERSION);
+
+    LIST_FOR_EACH (fa, list_node, field_array) {
+        nxm_put_unmasked(b, fa->id, version, &fa->value,
+                         mf_from_id(fa->id)->n_bytes);
+    }
+
+    return ofpbuf_size(b) - start_len;
+}
+
 static void
 nx_put_header__(struct ofpbuf *b, uint64_t header, bool masked)
 {
diff --git a/lib/nx-match.h b/lib/nx-match.h
index 1c9821c..14cd67a 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -61,6 +61,8 @@ enum ofperr oxm_pull_field_array(const void *, size_t 
fields_len,
 int nx_put_match(struct ofpbuf *, const struct match *,
                  ovs_be64 cookie, ovs_be64 cookie_mask);
 int oxm_put_match(struct ofpbuf *, const struct match *, enum ofp_version);
+int oxm_put_field_array(struct ofpbuf *, const struct ovs_list *,
+                        enum ofp_version version);
 
 /* Decoding and encoding OXM/NXM headers (just a field ID) or entries (a field
  * ID followed by a value and possibly a mask). */
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 9019a258..aa4af73 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -7423,6 +7423,27 @@ ofputil_put_ofp15_bucket(const struct ofputil_bucket 
*bucket,
 }
 
 static void
+ofputil_put_group_prop_nmx_selection_method(enum ofp_version ofp_version,
+                                            const struct ofputil_group_props 
*gp,
+                                            const struct ovs_list *fields,
+                                            struct ofpbuf *openflow)
+{
+    struct nmx_group_prop_selection_method *prop;
+    size_t start;
+
+    start = ofpbuf_size(openflow);
+    ofpbuf_put_zeros(openflow, sizeof *prop);
+    oxm_put_field_array(openflow, fields, ofp_version);
+    prop = ofpbuf_at_assert(openflow, start, sizeof *prop);
+    prop->type = htons(OFPGPT15_EXPERIMENTER);
+    prop->experimenter = htonl(NMX_VENDOR_ID);
+    prop->exp_type = htonl(NMXT_SELECTION_METHOD);
+    strcpy(prop->selection_method, gp->selection_method);
+    prop->selection_method_param = htonll(gp->selection_method_param);
+    end_property(openflow, start);
+}
+
+static void
 ofputil_append_ofp11_group_desc_reply(const struct ofputil_group_desc *gds,
                                       const struct ovs_list *buckets,
                                       struct ovs_list *replies,
@@ -7449,6 +7470,7 @@ ofputil_append_ofp11_group_desc_reply(const struct 
ofputil_group_desc *gds,
 static void
 ofputil_append_ofp15_group_desc_reply(const struct ofputil_group_desc *gds,
                                       const struct ovs_list *buckets,
+                                      const struct ovs_list *fields,
                                       struct ovs_list *replies,
                                       enum ofp_version version)
 {
@@ -7470,6 +7492,12 @@ ofputil_append_ofp15_group_desc_reply(const struct 
ofputil_group_desc *gds,
     ogds->group_id = htonl(gds->group_id);
     ogds->bucket_list_len =  htons(ofpbuf_size(reply) - start_buckets);
 
+    /* Add group properties */
+    if (gds->props.selection_method[0]) {
+        ofputil_put_group_prop_nmx_selection_method(version, &gds->props,
+                                                    fields, reply);
+    }
+
     ofpmp_postappend(replies, start_ogds);
 }
 
@@ -7479,6 +7507,7 @@ ofputil_append_ofp15_group_desc_reply(const struct 
ofputil_group_desc *gds,
 void
 ofputil_append_group_desc_reply(const struct ofputil_group_desc *gds,
                                 const struct ovs_list *buckets,
+                                const struct ovs_list *fields,
                                 struct ovs_list *replies)
 {
     enum ofp_version version = ofpmp_version(replies);
@@ -7493,7 +7522,8 @@ ofputil_append_group_desc_reply(const struct 
ofputil_group_desc *gds,
         break;
 
     case OFP15_VERSION:
-        ofputil_append_ofp15_group_desc_reply(gds, buckets, replies, version);
+        ofputil_append_ofp15_group_desc_reply(gds, buckets, fields, replies,
+                                              version);
         break;
 
     case OFP10_VERSION:
@@ -8126,6 +8156,12 @@ ofputil_encode_ofp15_group_mod(enum ofp_version 
ofp_version,
     ogm->command_bucket_id = htonl(gm->command_bucket_id);
     ogm->bucket_array_len = htons(ofpbuf_size(b) - start_ogm - sizeof *ogm);
 
+    /* Add group properties */
+    if (gm->props.selection_method[0]) {
+        ofputil_put_group_prop_nmx_selection_method(ofp_version, &gm->props,
+                                                    &gm->props.fields, b);
+    }
+
     id_pool_destroy(bucket_ids);
     return b;
 }
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 31b250b..f75c363 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -1095,6 +1095,7 @@ int ofputil_decode_group_desc_reply(struct 
ofputil_group_desc *,
 
 void ofputil_append_group_desc_reply(const struct ofputil_group_desc *,
                                      const struct ovs_list *buckets,
+                                     const struct ovs_list *fields,
                                      struct ovs_list *replies);
 
 struct ofputil_bundle_ctrl_msg {
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 2f4d62f..b0043b0 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -5749,7 +5749,12 @@ append_group_desc(struct ofgroup *group, struct ovs_list 
*replies)
 
     gds.group_id = group->group_id;
     gds.type = group->type;
-    ofputil_append_group_desc_reply(&gds, &group->buckets, replies);
+
+    memcpy(gds.props.selection_method, group->selection_method,
+           NMX_MAX_SELECTION_METHOD_LEN);
+    gds.props.selection_method_param = group->selection_method_param;
+    ofputil_append_group_desc_reply(&gds, &group->buckets,
+                                    &group->fields, replies);
 }
 
 static enum ofperr
-- 
2.1.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to