]> git.proxmox.com Git - ovs.git/commitdiff
Add OpenFlow extensions for group support in OpenFlow 1.0.
authorBen Pfaff <blp@ovn.org>
Thu, 10 May 2018 00:03:56 +0000 (17:03 -0700)
committerBen Pfaff <blp@ovn.org>
Thu, 17 May 2018 15:16:06 +0000 (08:16 -0700)
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Justin Pettit <jpettit@ovn.org>
NEWS
include/openflow/openflow-1.5.h
include/openvswitch/ofp-errors.h
include/openvswitch/ofp-msgs.h
lib/nx-match.c
lib/ofp-group.c
lib/ofp-print.c
tests/ofp-print.at
tests/ofproto.at
utilities/ovs-ofctl.8.in

diff --git a/NEWS b/NEWS
index cb27aaedf12cd0ea9b154ce91f90cb70030a9a0e..ec548b02a8b0898bb44247fa7f23ffb1842520f6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,7 +15,8 @@ Post-v2.9.0
    - ovs-vsctl: New commands "add-bond-iface" and "del-bond-iface".
    - OpenFlow:
      * OFPT_ROLE_STATUS is now available in OpenFlow 1.3.
-     * OpenFlow 1.5 extensibile statistics (OXS) now implemented.
+     * OpenFlow 1.5 extensible statistics (OXS) now implemented.
+     * New OpenFlow 1.0 extensions for group support.
    - Linux kernel 4.14
      * Add support for compiling OVS with the latest Linux 4.14 kernel
    - ovn:
index d9b867cf2beebdee9db265f494e28c94c9889275..c146052afa6421751d1918209b766ded75909dc1 100644 (file)
@@ -77,12 +77,11 @@ struct ofp15_bucket {
                                        64-bit aligned. */
     ovs_be16 action_array_len;      /* Length of all actions in bytes. */
     ovs_be32 bucket_id;             /* Bucket Id used to identify bucket*/
-    /* Followed by exactly len - 8 bytes of group bucket properties. */
     /* Followed by:
      *   - Exactly 'action_array_len' bytes containing an array of
      *     struct ofp_action_*.
      *   - Zero or more bytes of group bucket properties to fill out the
-     *     overall length in header.length. */
+     *     overall length in 'len'. */
 };
 OFP_ASSERT(sizeof(struct ofp15_bucket) == 8);
 
index 16feacb559b4507f0946f347f6700a99b6cd163b..6e8e55ab4f4fa45acd2ce777ad01d6cdb8e12fc9 100644 (file)
@@ -254,7 +254,7 @@ enum ofperr {
     /* OF1.0+(2,8).  Problem validating output queue. */
     OFPERR_OFPBAC_BAD_QUEUE,
 
-    /* OF1.1+(2,9).  Invalid group id in output action. */
+    /* NX1.0(2,9), OF1.1+(2,9).  Invalid group id in output action. */
     OFPERR_OFPBAC_BAD_OUT_GROUP,
 
     /* NX1.0(1,522), OF1.1+(2,10).  Action can't apply for this match or a
@@ -460,63 +460,65 @@ enum ofperr {
 /* ## OFPET_GROUP_MOD_FAILED ## */
 /* ## ---------------------- ## */
 
-    /* OF1.1+(6,0).  Group not added because a group ADD attempted to replace
-     * an already-present group. */
+    /* NX1.0(6,0), OF1.1+(6,0).  Group not added because a group ADD attempted
+     * to replace an already-present group. */
     OFPERR_OFPGMFC_GROUP_EXISTS,
 
-    /* OF1.1+(6,1).  Group not added because Group specified is invalid. */
+    /* NX1.0(6,1), OF1.1+(6,1).  Group not added because Group specified is
+     * invalid. */
     OFPERR_OFPGMFC_INVALID_GROUP,
 
-    /* OF1.1+(6,2).  Switch does not support unequal load sharing with select
-     * groups. */
+    /* NX1.0(6,2), OF1.1+(6,2).  Switch does not support unequal load sharing
+     * with select groups. */
     OFPERR_OFPGMFC_WEIGHT_UNSUPPORTED,
 
-    /* OF1.1+(6,3).  The group table is full. */
+    /* NX1.0(6,3), OF1.1+(6,3).  The group table is full. */
     OFPERR_OFPGMFC_OUT_OF_GROUPS,
 
-    /* OF1.1+(6,4).  The maximum number of action buckets for a group has been
-     * exceeded. */
+    /* NX1.0(6,4), OF1.1+(6,4).  The maximum number of action buckets for a
+     * group has been exceeded. */
     OFPERR_OFPGMFC_OUT_OF_BUCKETS,
 
-    /* OF1.1+(6,5).  Switch does not support groups that forward to groups. */
+    /* NX1.0(6,5), OF1.1+(6,5).  Switch does not support groups that forward to
+     * groups. */
     OFPERR_OFPGMFC_CHAINING_UNSUPPORTED,
 
-    /* OF1.1+(6,6).  This group cannot watch the watch_port or watch_group
-     * specified. */
+    /* NX1.0(6,6), OF1.1+(6,6).  This group cannot watch the watch_port or
+     * watch_group specified. */
     OFPERR_OFPGMFC_WATCH_UNSUPPORTED,
 
-    /* OF1.1+(6,7).  Group entry would cause a loop. */
+    /* NX1.0(6,7), OF1.1+(6,7).  Group entry would cause a loop. */
     OFPERR_OFPGMFC_LOOP,
 
-    /* OF1.1+(6,8).  Group not modified because a group MODIFY attempted to
-     * modify a non-existent group. */
+    /* NX1.0(6,8), OF1.1+(6,8).  Group not modified because a group MODIFY
+     * attempted to modify a non-existent group. */
     OFPERR_OFPGMFC_UNKNOWN_GROUP,
 
-    /* OF1.2+(6,9).  Group not deleted because another
-                    group is forwarding to it. */
+    /* NX1.0(6,9), OF1.2+(6,9).  Group not deleted because another group is
+     * forwarding to it. */
     OFPERR_OFPGMFC_CHAINED_GROUP,
 
-    /* OF1.2+(6,10).  Unsupported or unknown group type. */
+    /* NX1.0(6,10), OF1.2+(6,10).  Unsupported or unknown group type. */
     OFPERR_OFPGMFC_BAD_TYPE,
 
-    /* OF1.2+(6,11).  Unsupported or unknown command. */
+    /* NX1.0(6,11), OF1.2+(6,11).  Unsupported or unknown command. */
     OFPERR_OFPGMFC_BAD_COMMAND,
 
-    /* OF1.2+(6,12).  Error in bucket. */
+    /* NX1.0(6,12), OF1.2+(6,12).  Error in bucket. */
     OFPERR_OFPGMFC_BAD_BUCKET,
 
-    /* OF1.2+(6,13).  Error in watch port/group. */
+    /* NX1.0(6,13), OF1.2+(6,13).  Error in watch port/group. */
     OFPERR_OFPGMFC_BAD_WATCH,
 
-    /* OF1.2+(6,14).  Permissions error. */
+    /* NX1.0(6,14), OF1.2+(6,14).  Permissions error. */
     OFPERR_OFPGMFC_EPERM,
 
-    /* OF1.5+(6,15).  Invalid bucket identifier used in
-     * INSERT BUCKET or REMOVE BUCKET command. */
+    /* NX1.0(6,15), OF1.5+(6,15).  Invalid bucket identifier used in INSERT
+     * BUCKET or REMOVE BUCKET command. */
     OFPERR_OFPGMFC_UNKNOWN_BUCKET,
 
-    /* OF1.5+(6,16).  Can't insert bucket because a bucket
-     * already exist with that bucket-id. */
+    /* NX1.0(6,16), OF1.5+(6,16).  Can't insert bucket because a bucket already
+     * exist with that bucket-id. */
     OFPERR_OFPGMFC_BUCKET_EXISTS,
 
 /* ## --------------------- ## */
index ea2fa5bb0e52d229d23a9828d30fdee40ae45e16..f180273024eb27719da5f7a15c9b0814780d6275 100644 (file)
@@ -195,6 +195,8 @@ enum ofpraw {
     /* NXT 1.0+ (13): struct nx_flow_mod, uint8_t[8][]. */
     OFPRAW_NXT_FLOW_MOD,
 
+    /* NXT 1.0 (31): struct ofp15_group_mod, uint8_t[8][]. */
+    OFPRAW_NXT_GROUP_MOD,
     /* OFPT 1.1-1.4 (15): struct ofp11_group_mod, uint8_t[8][]. */
     OFPRAW_OFPT11_GROUP_MOD,
     /* OFPT 1.5+ (15): struct ofp15_group_mod, uint8_t[8][]. */
@@ -367,25 +369,37 @@ enum ofpraw {
     /* OFPST 1.4+ (5): uint8_t[8][]. */
     OFPRAW_OFPST14_QUEUE_REPLY,
 
+    /* NXST 1.0 (7): struct ofp11_group_stats_request. */
+    OFPRAW_NXST_GROUP_REQUEST,
     /* OFPST 1.1+ (6): struct ofp11_group_stats_request. */
     OFPRAW_OFPST11_GROUP_REQUEST,
 
+    /* NXST 1.0 (7): uint8_t[8][]. */
+    OFPRAW_NXST_GROUP_REPLY,
     /* OFPST 1.1-1.2 (6): uint8_t[8][]. */
     OFPRAW_OFPST11_GROUP_REPLY,
     /* OFPST 1.3+ (6): uint8_t[8][]. */
     OFPRAW_OFPST13_GROUP_REPLY,
 
+    /* NXST 1.0 (8): struct ofp15_group_desc_request. */
+    OFPRAW_NXST_GROUP_DESC_REQUEST,
     /* OFPST 1.1-1.4 (7): void. */
     OFPRAW_OFPST11_GROUP_DESC_REQUEST,
     /* OFPST 1.5+ (7): struct ofp15_group_desc_request. */
     OFPRAW_OFPST15_GROUP_DESC_REQUEST,
 
+    /* NXST 1.0 (8): uint8_t[8][]. */
+    OFPRAW_NXST_GROUP_DESC_REPLY,
     /* OFPST 1.1+ (7): uint8_t[8][]. */
     OFPRAW_OFPST11_GROUP_DESC_REPLY,
 
+    /* NXST 1.0-1.1 (9): void. */
+    OFPRAW_NXST_GROUP_FEATURES_REQUEST,
     /* OFPST 1.2+ (8): void. */
     OFPRAW_OFPST12_GROUP_FEATURES_REQUEST,
 
+    /* NXST 1.0-1.1 (9): struct ofp12_group_features_stats. */
+    OFPRAW_NXST_GROUP_FEATURES_REPLY,
     /* OFPST 1.2+ (8): struct ofp12_group_features_stats. */
     OFPRAW_OFPST12_GROUP_FEATURES_REPLY,
 
@@ -583,7 +597,8 @@ enum ofptype {
     OFPTYPE_FLOW_MOD,            /* OFPRAW_OFPT10_FLOW_MOD.
                                   * OFPRAW_OFPT11_FLOW_MOD.
                                   * OFPRAW_NXT_FLOW_MOD. */
-    OFPTYPE_GROUP_MOD,           /* OFPRAW_OFPT11_GROUP_MOD.
+    OFPTYPE_GROUP_MOD,           /* OFPRAW_NXT_GROUP_MOD.
+                                  * OFPRAW_OFPT11_GROUP_MOD.
                                   * OFPRAW_OFPT15_GROUP_MOD. */
     OFPTYPE_PORT_MOD,            /* OFPRAW_OFPT10_PORT_MOD.
                                   * OFPRAW_OFPT11_PORT_MOD.
@@ -677,19 +692,25 @@ enum ofptype {
                                       * OFPRAW_OFPST13_QUEUE_REPLY.
                                       * OFPRAW_OFPST14_QUEUE_REPLY. */
 
-    OFPTYPE_GROUP_STATS_REQUEST,     /* OFPRAW_OFPST11_GROUP_REQUEST. */
+    OFPTYPE_GROUP_STATS_REQUEST,     /* OFPRAW_NXST_GROUP_REQUEST.
+                                      * OFPRAW_OFPST11_GROUP_REQUEST. */
 
-    OFPTYPE_GROUP_STATS_REPLY,       /* OFPRAW_OFPST11_GROUP_REPLY.
+    OFPTYPE_GROUP_STATS_REPLY,       /* OFPRAW_NXST_GROUP_REPLY.
+                                      * OFPRAW_OFPST11_GROUP_REPLY.
                                       * OFPRAW_OFPST13_GROUP_REPLY. */
 
-    OFPTYPE_GROUP_DESC_STATS_REQUEST, /* OFPRAW_OFPST11_GROUP_DESC_REQUEST.
+    OFPTYPE_GROUP_DESC_STATS_REQUEST, /* OFPRAW_NXST_GROUP_DESC_REQUEST.
+                                       * OFPRAW_OFPST11_GROUP_DESC_REQUEST.
                                        * OFPRAW_OFPST15_GROUP_DESC_REQUEST. */
 
-    OFPTYPE_GROUP_DESC_STATS_REPLY,  /* OFPRAW_OFPST11_GROUP_DESC_REPLY. */
+    OFPTYPE_GROUP_DESC_STATS_REPLY,  /* OFPRAW_NXST_GROUP_DESC_REPLY.
+                                      * OFPRAW_OFPST11_GROUP_DESC_REPLY. */
 
-    OFPTYPE_GROUP_FEATURES_STATS_REQUEST, /* OFPRAW_OFPST12_GROUP_FEATURES_REQUEST. */
+    OFPTYPE_GROUP_FEATURES_STATS_REQUEST, /* OFPRAW_NXST_GROUP_FEATURES_REQUEST.
+                                           * OFPRAW_OFPST12_GROUP_FEATURES_REQUEST. */
 
-    OFPTYPE_GROUP_FEATURES_STATS_REPLY, /* OFPRAW_OFPST12_GROUP_FEATURES_REPLY. */
+    OFPTYPE_GROUP_FEATURES_STATS_REPLY, /* OFPRAW_NXST_GROUP_FEATURES_REPLY.
+                                         * OFPRAW_OFPST12_GROUP_FEATURES_REPLY. */
 
     OFPTYPE_METER_STATS_REQUEST,     /* OFPRAW_OFPST13_METER_REQUEST. */
 
index a8edb2e9d2455531e69e9d7d0db38f9623ba6af8..a3c22ee8870d4b15d3b684cbea7026adffcfcea0 100644 (file)
@@ -1375,18 +1375,13 @@ oxm_put_field_array(struct ofpbuf *b, const struct field_array *fa,
 {
     size_t start_len = b->size;
 
-    /* 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:
+    /* XXX Some care might 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);
 
     size_t i, offset = 0;
 
index 5b54faee963f6896c28370a09f91c91234b741c1..a2755ee47fea076aa4bf5d0cb62142a4fd397f1e 100644 (file)
@@ -215,29 +215,14 @@ struct ofpbuf *
 ofputil_encode_group_stats_request(enum ofp_version ofp_version,
                                    uint32_t group_id)
 {
-    struct ofpbuf *request;
-
-    switch (ofp_version) {
-    case OFP10_VERSION:
-        ovs_fatal(0, "dump-group-stats needs OpenFlow 1.1 or later "
-                     "(\'-O OpenFlow11\')");
-    case OFP11_VERSION:
-    case OFP12_VERSION:
-    case OFP13_VERSION:
-    case OFP14_VERSION:
-    case OFP15_VERSION:
-    case OFP16_VERSION: {
-        struct ofp11_group_stats_request *req;
-        request = ofpraw_alloc(OFPRAW_OFPST11_GROUP_REQUEST, ofp_version, 0);
-        req = ofpbuf_put_zeros(request, sizeof *req);
-        req->group_id = htonl(group_id);
-        break;
-    }
-    default:
-        OVS_NOT_REACHED();
-    }
-
-    return request;
+    struct ofpbuf *msg = ofpraw_alloc((ofp_version == OFP10_VERSION
+                                       ? OFPRAW_NXST_GROUP_REQUEST
+                                       : OFPRAW_OFPST11_GROUP_REQUEST),
+                                      ofp_version, 0);
+    struct ofp11_group_stats_request *req = ofpbuf_put_zeros(msg, sizeof *req);
+    req->group_id = htonl(group_id);
+
+    return msg;
 }
 
 void
@@ -257,7 +242,8 @@ ofputil_decode_group_desc_request(const struct ofp_header *oh)
     enum ofpraw raw = ofpraw_pull_assert(&request);
     if (raw == OFPRAW_OFPST11_GROUP_DESC_REQUEST) {
         return OFPG_ALL;
-    } else if (raw == OFPRAW_OFPST15_GROUP_DESC_REQUEST) {
+    } else if (raw == OFPRAW_NXST_GROUP_DESC_REQUEST ||
+               raw == OFPRAW_OFPST15_GROUP_DESC_REQUEST) {
         ovs_be32 *group_id = ofpbuf_pull(&request, sizeof *group_id);
         return ntohl(*group_id);
     } else {
@@ -279,9 +265,6 @@ ofputil_encode_group_desc_request(enum ofp_version ofp_version,
     struct ofpbuf *request;
 
     switch (ofp_version) {
-    case OFP10_VERSION:
-        ovs_fatal(0, "dump-groups needs OpenFlow 1.1 or later "
-                     "(\'-O OpenFlow11\')");
     case OFP11_VERSION:
     case OFP12_VERSION:
     case OFP13_VERSION:
@@ -289,10 +272,13 @@ ofputil_encode_group_desc_request(enum ofp_version ofp_version,
         request = ofpraw_alloc(OFPRAW_OFPST11_GROUP_DESC_REQUEST,
                                ofp_version, 0);
         break;
+    case OFP10_VERSION:
     case OFP15_VERSION:
     case OFP16_VERSION: {
         struct ofp15_group_desc_request *req;
-        request = ofpraw_alloc(OFPRAW_OFPST15_GROUP_DESC_REQUEST,
+        request = ofpraw_alloc((ofp_version == OFP10_VERSION
+                                ? OFPRAW_NXST_GROUP_DESC_REQUEST
+                                : OFPRAW_OFPST15_GROUP_DESC_REQUEST),
                                ofp_version, 0);
         req = ofpbuf_put_zeros(request, sizeof *req);
         req->group_id = htonl(group_id);
@@ -367,6 +353,7 @@ ofputil_append_group_stats(struct ovs_list *replies,
             break;
         }
 
+    case OFP10_VERSION:
     case OFP13_VERSION:
     case OFP14_VERSION:
     case OFP15_VERSION:
@@ -380,7 +367,6 @@ ofputil_append_group_stats(struct ovs_list *replies,
             break;
         }
 
-    case OFP10_VERSION:
     default:
         OVS_NOT_REACHED();
     }
@@ -390,26 +376,10 @@ ofputil_append_group_stats(struct ovs_list *replies,
 struct ofpbuf *
 ofputil_encode_group_features_request(enum ofp_version ofp_version)
 {
-    struct ofpbuf *request = NULL;
-
-    switch (ofp_version) {
-    case OFP10_VERSION:
-    case OFP11_VERSION:
-        ovs_fatal(0, "dump-group-features needs OpenFlow 1.2 or later "
-                     "(\'-O OpenFlow12\')");
-    case OFP12_VERSION:
-    case OFP13_VERSION:
-    case OFP14_VERSION:
-    case OFP15_VERSION:
-    case OFP16_VERSION:
-        request = ofpraw_alloc(OFPRAW_OFPST12_GROUP_FEATURES_REQUEST,
-                               ofp_version, 0);
-        break;
-    default:
-        OVS_NOT_REACHED();
-    }
-
-    return request;
+    return ofpraw_alloc((ofp_version < OFP12_VERSION
+                         ? OFPRAW_NXST_GROUP_FEATURES_REQUEST
+                         : OFPRAW_OFPST12_GROUP_FEATURES_REQUEST),
+                        ofp_version, 0);
 }
 
 /* Returns a OpenFlow message that encodes 'features' properly as a reply to
@@ -419,16 +389,12 @@ ofputil_encode_group_features_reply(
     const struct ofputil_group_features *features,
     const struct ofp_header *request)
 {
-    struct ofp12_group_features_stats *ogf;
-    struct ofpbuf *reply;
-    int i;
-
-    reply = ofpraw_alloc_xid(OFPRAW_OFPST12_GROUP_FEATURES_REPLY,
-                             request->version, request->xid, 0);
-    ogf = ofpbuf_put_zeros(reply, sizeof *ogf);
+    struct ofpbuf *reply = ofpraw_alloc_stats_reply(request, 0);
+    struct ofp12_group_features_stats *ogf
+        = ofpbuf_put_zeros(reply, sizeof *ogf);
     ogf->types = htonl(features->types);
     ogf->capabilities = htonl(features->capabilities);
-    for (i = 0; i < OFPGT12_N_TYPES; i++) {
+    for (int i = 0; i < OFPGT12_N_TYPES; i++) {
         ogf->max_groups[i] = htonl(features->max_groups[i]);
         ogf->actions[i] = ofpact_bitmap_to_openflow(features->ofpacts[i],
                                                     request->version);
@@ -504,7 +470,8 @@ ofputil_decode_group_stats_reply(struct ofpbuf *msg,
         base_len = sizeof *ogs11;
         ogs11 = ofpbuf_try_pull(msg, sizeof *ogs11);
         gs->duration_sec = gs->duration_nsec = UINT32_MAX;
-    } else if (raw == OFPRAW_OFPST13_GROUP_REPLY) {
+    } else if (raw == OFPRAW_NXST_GROUP_REPLY ||
+               raw == OFPRAW_OFPST13_GROUP_REPLY) {
         struct ofp13_group_stats *ogs13;
 
         base_len = sizeof *ogs13;
@@ -595,7 +562,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
                 error = xasprintf("invalid bucket_id id %"PRIu32,
                                   bucket->bucket_id);
             }
-            *usable_protocols &= OFPUTIL_P_OF15_UP;
+            *usable_protocols &= OFPUTIL_P_OF10_ANY | OFPUTIL_P_OF15_UP;
         } else if (!strcasecmp(key, "action") || !strcasecmp(key, "actions")) {
             ds_put_format(&actions, "%s,", value);
         } else {
@@ -713,7 +680,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
     struct ofputil_bucket *bucket;
     char *error = NULL;
 
-    *usable_protocols = OFPUTIL_P_OF11_UP;
+    *usable_protocols = OFPUTIL_P_ANY;
 
     if (command == -2) {
         size_t len;
@@ -759,12 +726,12 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
 
     case OFPGC15_INSERT_BUCKET:
         fields = F_BUCKETS | F_COMMAND_BUCKET_ID;
-        *usable_protocols &= OFPUTIL_P_OF15_UP;
+        *usable_protocols &= OFPUTIL_P_OF10_ANY | OFPUTIL_P_OF15_UP;
         break;
 
     case OFPGC15_REMOVE_BUCKET:
         fields = F_COMMAND_BUCKET_ID | F_COMMAND_BUCKET_ID_ALL;
-        *usable_protocols &= OFPUTIL_P_OF15_UP;
+        *usable_protocols &= OFPUTIL_P_OF10_ANY | OFPUTIL_P_OF15_UP;
         break;
 
     default:
@@ -781,8 +748,6 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
         return NULL;
     }
 
-    *usable_protocols = OFPUTIL_P_OF11_UP;
-
     /* Strip the buckets off the end of 'string', if there are any, saving a
      * pointer for later.  We want to parse the buckets last because the bucket
      * type influences bucket defaults. */
@@ -877,7 +842,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
             memset(gm->props.selection_method, '\0',
                    NTR_MAX_SELECTION_METHOD_LEN);
             strcpy(gm->props.selection_method, value);
-            *usable_protocols &= OFPUTIL_P_OF15_UP;
+            *usable_protocols &= OFPUTIL_P_OF10_ANY | OFPUTIL_P_OF15_UP;
         } else if (!strcmp(name, "selection_method_param")) {
             if (!(fields & F_GROUP_TYPE)) {
                 error = xstrdup("selection method param is not needed");
@@ -887,7 +852,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
             if (error) {
                 goto out;
             }
-            *usable_protocols &= OFPUTIL_P_OF15_UP;
+            *usable_protocols &= OFPUTIL_P_OF10_ANY | OFPUTIL_P_OF15_UP;
         } else if (!strcmp(name, "fields")) {
             if (!(fields & F_GROUP_TYPE)) {
                 error = xstrdup("fields are not needed");
@@ -899,7 +864,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command,
             if (error) {
                 goto out;
             }
-            *usable_protocols &= OFPUTIL_P_OF15_UP;
+            *usable_protocols &= OFPUTIL_P_OF10_ANY | OFPUTIL_P_OF15_UP;
         } else {
             error = xasprintf("unknown keyword %s", name);
             goto out;
@@ -1028,7 +993,7 @@ parse_ofp_group_mod_file(const char *file_name,
     allocated_gms = *n_gms;
     ds_init(&s);
     line_number = 0;
-    *usable_protocols = OFPUTIL_P_OF11_UP;
+    *usable_protocols = OFPUTIL_P_ANY;
     while (!ds_get_preprocessed_line(&s, stream, &line_number)) {
         enum ofputil_protocol usable;
         char *error;
@@ -1223,12 +1188,12 @@ ofputil_append_group_desc_reply(const struct ofputil_group_desc *gds,
         ofputil_append_ofp11_group_desc_reply(gds, buckets, replies, version);
         break;
 
+    case OFP10_VERSION:
     case OFP15_VERSION:
     case OFP16_VERSION:
         ofputil_append_ofp15_group_desc_reply(gds, buckets, replies, version);
         break;
 
-    case OFP10_VERSION:
     default:
         OVS_NOT_REACHED();
     }
@@ -1307,8 +1272,6 @@ ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t buckets_length,
                            enum ofp_version version, uint8_t group_type,
                            struct ovs_list *buckets)
 {
-    struct ofp15_bucket *ob;
-
     ovs_list_init(buckets);
     while (buckets_length > 0) {
         struct ofputil_bucket *bucket = NULL;
@@ -1321,7 +1284,7 @@ ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t buckets_length,
 
         ofpbuf_init(&ofpacts, 0);
 
-        ob = ofpbuf_try_pull(msg, sizeof *ob);
+        struct ofp15_bucket *ob = ofpbuf_try_pull(msg, sizeof *ob);
         if (!ob) {
             VLOG_WARN_RL(&rl, "buckets end with %"PRIuSIZE
                          " leftover bytes", buckets_length);
@@ -1694,11 +1657,11 @@ ofputil_decode_group_desc_reply(struct ofputil_group_desc *gd,
     case OFP14_VERSION:
         return ofputil_decode_ofp11_group_desc_reply(gd, msg, version);
 
+    case OFP10_VERSION:
     case OFP15_VERSION:
     case OFP16_VERSION:
         return ofputil_decode_ofp15_group_desc_reply(gd, msg, version);
 
-    case OFP10_VERSION:
     default:
         OVS_NOT_REACHED();
     }
@@ -1745,7 +1708,9 @@ ofputil_encode_ofp15_group_mod(enum ofp_version ofp_version,
     struct ofputil_bucket *bucket;
     struct id_pool *bucket_ids = NULL;
 
-    b = ofpraw_alloc(OFPRAW_OFPT15_GROUP_MOD, ofp_version, 0);
+    b = ofpraw_alloc((ofp_version == OFP10_VERSION
+                      ? OFPRAW_NXT_GROUP_MOD
+                      : OFPRAW_OFPT15_GROUP_MOD), ofp_version, 0);
     start_ogm = b->size;
     ofpbuf_put_zeros(b, sizeof *ogm);
 
@@ -1861,10 +1826,6 @@ ofputil_encode_group_mod(enum ofp_version ofp_version,
 {
 
     switch (ofp_version) {
-    case OFP10_VERSION:
-        bad_group_cmd(gm->command);
-        /* fall through */
-
     case OFP11_VERSION:
     case OFP12_VERSION:
     case OFP13_VERSION:
@@ -1874,6 +1835,7 @@ ofputil_encode_group_mod(enum ofp_version ofp_version,
         }
         return ofputil_encode_ofp11_group_mod(ofp_version, gm);
 
+    case OFP10_VERSION:
     case OFP15_VERSION:
     case OFP16_VERSION:
         return ofputil_encode_ofp15_group_mod(ofp_version, gm);
@@ -2059,12 +2021,12 @@ ofputil_decode_group_mod(const struct ofp_header *oh,
         err = ofputil_pull_ofp11_group_mod(&msg, ofp_version, gm);
         break;
 
+    case OFP10_VERSION:
     case OFP15_VERSION:
     case OFP16_VERSION:
         err = ofputil_pull_ofp15_group_mod(&msg, ofp_version, gm);
         break;
 
-    case OFP10_VERSION:
     default:
         OVS_NOT_REACHED();
     }
index 096c341c9b4dde8018e45b414c0dea228f239965..0d140687321983a348742362565ee797c3c2ebbd 100644 (file)
@@ -1528,7 +1528,7 @@ static void
 ofp_print_bucket_id(struct ds *s, const char *label, uint32_t bucket_id,
                     enum ofp_version ofp_version)
 {
-    if (ofp_version < OFP15_VERSION) {
+    if (ofp_version > OFP10_VERSION && ofp_version < OFP15_VERSION) {
         return;
     }
 
index cfce780028a4ea91e9167ac0c6f6e730fe807ac4..5d1541f9f184c242919774b451a843bb00c6f475 100644 (file)
@@ -2150,7 +2150,16 @@ OFPST_QUEUE reply (OF1.4) (xid=0x1): 6 queues
 ])
 AT_CLEANUP
 
-AT_SETUP([OFPST_GROUP request])
+AT_SETUP([NXST_GROUP request - OF1.0])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+01 10 00 20 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 07 00 00 00 00 \
+ff ff ff ff 00 00 00 00 \
+"], [0], [NXST_GROUP request (xid=0x4): group_id=ANY
+])
+AT_CLEANUP
+
+AT_SETUP([OFPST_GROUP request - OF1.1])
 AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
 AT_CHECK([ovs-ofctl ofp-print "\
 02 12 00 18 00 00 00 02 00 06 00 00 00 00 00 00 \
@@ -2159,6 +2168,28 @@ ff ff ff ff 00 00 00 00 \
 ])
 AT_CLEANUP
 
+AT_SETUP([NXST_GROUP reply - OF1.0])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+01 11 00 b8 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 07 00 00 00 00 \
+00 58 00 00 87 65 43 21 00 00 00 04 00 00 00 00 \
+00 00 00 00 00 00 88 88 00 00 00 00 00 77 77 77 \
+00 00 00 12 1d cd 65 00 \
+00 00 00 00 00 00 11 11 00 00 00 00 00 22 22 22 \
+00 00 00 00 00 00 11 11 00 00 00 00 00 22 22 22 \
+00 00 00 00 00 00 66 66 00 00 00 00 00 33 33 33 \
+00 48 00 00 00 00 00 05 00 00 00 02 00 00 00 00 \
+00 00 00 00 00 00 88 88 00 00 00 00 00 77 77 77 \
+00 00 00 10 1d cd 65 00 \
+00 00 00 00 00 00 11 11 00 00 00 00 00 22 22 22 \
+00 00 00 00 00 00 11 11 00 00 00 00 00 22 22 22 \
+"], [0], [dnl
+NXST_GROUP reply (xid=0x4):
+ group_id=2271560481,duration=18.500s,ref_count=4,packet_count=34952,byte_count=7829367,bucket0:packet_count=4369,byte_count=2236962,bucket1:packet_count=4369,byte_count=2236962,bucket2:packet_count=26214,byte_count=3355443
+ group_id=5,duration=16.500s,ref_count=2,packet_count=34952,byte_count=7829367,bucket0:packet_count=4369,byte_count=2236962,bucket1:packet_count=4369,byte_count=2236962
+])
+AT_CLEANUP
+
 AT_SETUP([OFPST_GROUP reply - OF1.1])
 AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
 AT_CHECK([ovs-ofctl ofp-print "\
@@ -2201,6 +2232,15 @@ OFPST_GROUP reply (OF1.3) (xid=0x2):
 ])
 AT_CLEANUP
 
+AT_SETUP([NXST_GROUP_DESC request - OF1.0])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+01 10 00 20 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 08 00 00 00 00 \
+00 00 00 01 00 00 00 00
+"], [0], [NXST_GROUP_DESC request (xid=0x4): group_id=1
+])
+AT_CLEANUP
+
 AT_SETUP([OFPST_GROUP_DESC request - OF1.1])
 AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
 AT_CHECK([ovs-ofctl ofp-print "\
@@ -2218,6 +2258,31 @@ AT_CHECK([ovs-ofctl ofp-print "\
 ])
 AT_CLEANUP
 
+AT_SETUP([NXST_GROUP_DESC reply - OF1.0])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+01 11 00 c8 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 08 00 00 00 00 \
+00 b0 01 00 00 00 20 00 00 60 00 00 00 00 00 00 \
+00 20 00 08 00 00 00 00 00 00 00 08 00 01 00 00 \
+00 00 00 08 00 64 00 00 \
+00 01 00 08 00 00 00 01 \
+00 20 00 08 00 00 00 01 00 00 00 08 00 02 00 00 \
+00 00 00 08 00 c8 00 00 \
+00 01 00 08 00 00 00 02 \
+00 20 00 08 00 00 00 02 00 00 00 08 00 03 00 00 \
+00 00 00 08 00 c8 00 00 \
+00 01 00 08 00 00 00 03 \
+ff ff 00 3b 00 00 15 40 00 00 00 01 00 00 00 00 \
+68 61 73 68 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 \
+80 00 18 04 ff ff ff 00 80 00 1a 02 ff ff 80 00 \
+14 01 ff 00 00 00 00 00 \
+"], [0], [dnl
+NXST_GROUP_DESC reply (xid=0x4):
+ group_id=8192,type=select,selection_method=hash,fields(ip_dst=255.255.255.0,nw_proto,tcp_src),bucket=bucket_id:0,weight:100,watch_port:1,actions=output:1,bucket=bucket_id:1,weight:200,watch_port:2,actions=output:2,bucket=bucket_id:2,weight:200,watch_port:3,actions=output:3
+])
+AT_CLEANUP
+
 AT_SETUP([OFPST_GROUP_DESC reply - OF1.1])
 AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
 AT_CHECK([ovs-ofctl ofp-print "\
@@ -2260,6 +2325,14 @@ OFPST_GROUP_DESC reply (OF1.5) (xid=0x2):
 ])
 AT_CLEANUP
 
+AT_SETUP([NXST_GROUP_FEATURES request])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+01 10 00 18 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 09 00 00 00 00 \
+"], [0], [NXST_GROUP_FEATURES request (xid=0x4):
+])
+AT_CLEANUP
+
 AT_SETUP([OFPST_GROUP_FEATURES request])
 AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
 AT_CHECK([ovs-ofctl ofp-print "\
@@ -2268,6 +2341,33 @@ AT_CHECK([ovs-ofctl ofp-print "\
 ])
 AT_CLEANUP
 
+AT_SETUP([NXST_GROUP_FEATURES reply])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+01 11 00 40 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 09 00 00 00 00 \
+00 00 00 0f 00 00 00 0f \
+00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 \
+00 00 00 01 00 00 00 07 00 00 00 0f 00 00 00 1f \
+"], [0], [dnl
+NXST_GROUP_FEATURES reply (xid=0x4):
+ Group table:
+    Types:  0xf
+    Capabilities:  0xf
+    all group:
+       max_groups=0x1
+       actions: output
+    select group:
+       max_groups=0x2
+       actions: output set_vlan_vid set_vlan_pcp
+    indirect group:
+       max_groups=0x3
+       actions: output set_vlan_vid set_vlan_pcp strip_vlan
+    fast failover group:
+       max_groups=0x4
+       actions: output set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src
+])
+AT_CLEANUP
+
 AT_SETUP([OFPST_GROUP_FEATURES reply])
 AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
 AT_CHECK([ovs-ofctl ofp-print "\
@@ -3289,6 +3389,30 @@ NXT_FLOW_MOD (xid=0x2): ADD NXM_NX_TUN_ID(00000000000001c8), NXM_NX_REG0(0000007
 ])
 AT_CLEANUP
 
+AT_SETUP([NXT_GROUP_MOD add - OF1.0])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+01 04 00 a8 00 00 00 02 00 00 23 20 00 00 00 1f \
+00 00 01 00 87 65 43 21 \
+00 60 00 00 ff ff ff ff \
+\
+00 20 00 08 00 00 00 00 00 00 00 08 00 01 00 00 \
+00 00 00 08 00 64 00 00 00 01 00 08 00 00 00 01 \
+\
+00 20 00 08 00 00 00 01 00 00 00 08 00 02 00 00 \
+00 00 00 08 00 c8 00 00 00 01 00 08 00 00 00 02
+\
+00 20 00 08 00 00 00 02 00 00 00 08 00 03 00 00 \
+00 00 00 08 00 c8 00 00 00 01 00 08 00 00 00 03 \
+ff ff 00 28 00 00 15 40 00 00 00 01 00 00 00 00 \
+68 61 73 68 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 07 \
+"], [0], [dnl
+NXT_GROUP_MOD (xid=0x2):
+ ADD group_id=2271560481,type=select,selection_method=hash,selection_method_param=7,bucket=bucket_id:0,weight:100,watch_port:1,actions=output:1,bucket=bucket_id:1,weight:200,watch_port:2,actions=output:2,bucket=bucket_id:2,weight:200,watch_port:3,actions=output:3
+])
+AT_CLEANUP
+
 AT_SETUP([OFPT_GROUP_MOD - OF1.1])
 AT_KEYWORDS([ofp-print])
 AT_CHECK([ovs-ofctl ofp-print "\
index d8e9cc093a973d17540d690a1b5616cd44a8e579..fff06eb0d0fd845de90fa7b43bb2476f584aaebb 100644 (file)
@@ -357,19 +357,41 @@ AT_CLEANUP
 dnl This is really bare-bones.
 dnl It at least checks request and reply serialization and deserialization.
 dnl Actions definition listed in both supported formats (w/ actions=)
-AT_SETUP([ofproto - no group support (OpenFlow 1.0)])
+AT_SETUP([ofproto - del group (OpenFlow 1.0 extension)])
 OVS_VSWITCHD_START
 AT_DATA([groups.txt], [dnl
-group_id=1234,type=all,bucket=output:10
-group_id=1235,type=all,bucket=actions=output:10
+group_id=1233,type=select,selection_method=hash,bucket=output:10,bucket=output:11
+group_id=1234,type=select,selection_method=hash,fields(eth_dst,ip_dst,tcp_dst),bucket=output:10,bucket=output:11
+group_id=1235,type=all,bucket=actions=output:12,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+group_id=1236,type=select,selection_method=dp_hash,bucket=output:10,bucket=output:11
 ])
-AT_DATA([stderr], [dnl
-ovs-ofctl: none of the usable flow formats (OXM,OpenFlow11) is among the allowed flow formats (OpenFlow10,NXM)
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn add-groups br0 groups.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-groups br0 1234], [0], [stdout])
+AT_CHECK([strip_xids < stdout], [0], [dnl
+NXST_GROUP_DESC reply:
+ group_id=1234,type=select,selection_method=hash,fields(eth_dst,ip_dst,tcp_dst),bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn del-groups br0 group_id=1234])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-groups br0], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sort], [0], [dnl
+ group_id=1233,type=select,selection_method=hash,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+ group_id=1235,type=all,bucket=bucket_id:2,actions=output:12,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+ group_id=1236,type=select,selection_method=dp_hash,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+NXST_GROUP_DESC reply:
+])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn del-groups br0 group_id=1234])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-groups br0], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sort], [0], [dnl
+ group_id=1233,type=select,selection_method=hash,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+ group_id=1235,type=all,bucket=bucket_id:2,actions=output:12,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+ group_id=1236,type=select,selection_method=dp_hash,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+NXST_GROUP_DESC reply:
+])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn del-groups br0], [0])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-groups br0], [0], [stdout])
+AT_CHECK([strip_xids < stdout], [0], [dnl
+NXST_GROUP_DESC reply:
 ])
-AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn add-groups br0 groups.txt], [1], ,[stderr])
-AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn mod-group br0 'group_id=1234,type=all,bucket=output:10'], [1], ,[stderr])
-AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn del-groups br0], [1], ,[stderr])
-AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-groups br0 ], [1], ,[stderr])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
@@ -711,7 +733,7 @@ OFPT_GROUP_MOD (OF1.5):
 ])
 # Negative test.
 AT_CHECK([ovs-ofctl -O OpenFlow11 -vwarn remove-buckets br0 group_id=1234,command_bucket_id=last], [1], [],
-  [ovs-ofctl: remove-bucket needs OpenFlow 1.5 or later ('-O OpenFlow15')
+  [ovs-ofctl: none of the usable flow formats (OpenFlow10,NXM,OXM-OpenFlow15,OXM-OpenFlow16) is among the allowed flow formats (OpenFlow11)
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -1018,7 +1040,7 @@ Error OFPBFC_MSG_FAILED for: OFPT_BUNDLE_CONTROL (OF1.5):
 ])
 # Negative test.
 AT_CHECK([ovs-ofctl --bundle -O OpenFlow11 -vwarn remove-buckets br0 group_id=1234,command_bucket_id=last], [1], [],
-  [ovs-ofctl: remove-bucket needs OpenFlow 1.5 or later ('-O OpenFlow15')
+  [ovs-ofctl: none of the usable flow formats (OXM-OpenFlow15,OXM-OpenFlow16) is among the allowed flow formats (OXM-OpenFlow14)
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -1075,20 +1097,33 @@ AT_CLEANUP
 
 dnl This is really bare-bones.
 dnl It at least checks request and reply serialization and deserialization.
-AT_SETUP([ofproto - group description])
+AT_SETUP([ofproto - group features (OpenFlow 1.0 extension)])
 OVS_VSWITCHD_START
-AT_CHECK([ovs-ofctl -O OpenFlow11 -vwarn add-group br0 group_id=1234,type=all,bucket=output:10])
-AT_CHECK([ovs-ofctl -O OpenFlow11 -vwarn dump-groups br0], [0], [stdout])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-group-features br0], [0], [stdout])
 AT_CHECK([strip_xids < stdout], [0], [dnl
-OFPST_GROUP_DESC reply (OF1.1):
- group_id=1234,type=all,bucket=actions=output:10
+NXST_GROUP_FEATURES reply:
+ Group table:
+    Types:  0xf
+    Capabilities:  0x7
+    all group:
+       max_groups=0xffffff00
+       actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
+    select group:
+       max_groups=0xffffff00
+       actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
+    indirect group:
+       max_groups=0xffffff00
+       actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
+    fast failover group:
+       max_groups=0xffffff00
+       actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
 dnl This is really bare-bones.
 dnl It at least checks request and reply serialization and deserialization.
-AT_SETUP([ofproto - group features])
+AT_SETUP([ofproto - group features (OpenFlow 1.2)])
 OVS_VSWITCHD_START
 AT_CHECK([ovs-ofctl -O OpenFlow12 -vwarn dump-group-features br0], [0], [stdout])
 AT_CHECK([strip_xids < stdout], [0], [dnl
@@ -1112,6 +1147,30 @@ OFPST_GROUP_FEATURES reply (OF1.2):
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+dnl This is really bare-bones.
+dnl It at least checks request and reply serialization and deserialization.
+AT_SETUP([ofproto - group stats (OpenFlow 1.0 extension)])
+OVS_VSWITCHD_START
+AT_DATA([groups.txt], [dnl
+group_id=1234,type=all,bucket=output:10
+group_id=1235,type=all,bucket=output:10
+])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn add-groups br0 groups.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn add-flow br0 'tcp actions=group:1234'])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-group-stats br0 group_id=1234], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sed 's/duration=[[0-9.]]*s/duration=?s/' | sort], [0], [dnl
+ group_id=1234,duration=?s,ref_count=1,packet_count=0,byte_count=0,bucket0:packet_count=0,byte_count=0
+NXST_GROUP reply:
+])
+AT_CHECK([ovs-ofctl -O OpenFlow10 -vwarn dump-group-stats br0], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sed 's/duration=[[0-9.]]*s/duration=?s/' | sort], [0], [dnl
+ group_id=1234,duration=?s,ref_count=1,packet_count=0,byte_count=0,bucket0:packet_count=0,byte_count=0
+ group_id=1235,duration=?s,ref_count=0,packet_count=0,byte_count=0,bucket0:packet_count=0,byte_count=0
+NXST_GROUP reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 dnl This is really bare-bones.
 dnl It at least checks request and reply serialization and deserialization.
 AT_SETUP([ofproto - group stats (OpenFlow 1.1)])
index abf3d87d1270d61a6d1ccd0ee6a55450677bc8e7..2e2f6966e771f7941254504dcaeeeec35d301875 100644 (file)
@@ -364,7 +364,7 @@ Connects to \fIswitch\fR and instructs it to execute the
 \fIpacket-out\fR OpenFlow message, specified as defined in
 \fBPacket\-Out Syntax\fR section.
 .
-.SS "OpenFlow 1.1+ Switch Group Table Commands"
+.SS "Group Table Commands"
 .
 These commands manage the group table in an OpenFlow switch.  In each
 case, \fIgroup\fR specifies a group entry in the format described in
@@ -373,12 +373,12 @@ zero or more groups in the same syntax, one per line, and the optional
 \fB\-\-bundle\fR option operates the command as a single atomic
 transation, see option \fB\-\-bundle\fR, below.
 .PP
-The group commands work only with switches that support OpenFlow 1.1 or
-later.  It is necessary to explicitly enable these protocol versions in
-\fBovs\-ofctl\fR (using \fB\-O\fR) and in the switch itself (with the
-\fBprotocols\fR column in the \fBBridge\fR table).  For more
-information, see ``Q: What versions of OpenFlow does Open vSwitch
-support?'' in the Open vSwitch FAQ.
+The group commands work only with switches that support OpenFlow 1.1
+or later or the Open vSwitch group extensions to OpenFlow 1.0 (added
+in Open vSwitch 2.9.90).  For OpenFlow 1.1 or later, it is necessary
+to explicitly enable these protocol versions in \fBovs\-ofctl\fR
+(using \fB\-O\fR).  For more information, see ``Q: What versions of
+OpenFlow does Open vSwitch support?'' in the Open vSwitch FAQ.
 .
 .IP "[\fB\-\-bundle\fR] \fBadd\-group \fIswitch group\fR"
 .IQ "[\fB\-\-bundle\fR] \fBadd\-group \fIswitch \fB\- < \fIfile\fR"