- 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:
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);
/* 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
/* ## 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,
/* ## --------------------- ## */
/* 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][]. */
/* 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,
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.
* 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. */
{
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;
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
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 {
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:
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);
break;
}
+ case OFP10_VERSION:
case OFP13_VERSION:
case OFP14_VERSION:
case OFP15_VERSION:
break;
}
- case OFP10_VERSION:
default:
OVS_NOT_REACHED();
}
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
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);
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;
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 {
struct ofputil_bucket *bucket;
char *error = NULL;
- *usable_protocols = OFPUTIL_P_OF11_UP;
+ *usable_protocols = OFPUTIL_P_ANY;
if (command == -2) {
size_t len;
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:
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. */
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");
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");
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;
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;
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();
}
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;
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);
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();
}
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);
{
switch (ofp_version) {
- case OFP10_VERSION:
- bad_group_cmd(gm->command);
- /* fall through */
-
case OFP11_VERSION:
case OFP12_VERSION:
case OFP13_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);
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();
}
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;
}
])
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 \
])
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 "\
])
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 "\
])
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 "\
])
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 "\
])
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 "\
])
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 "\
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
])
# 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
])
# 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
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
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)])
\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
\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"