" dump-desc SWITCH print switch description\n"
" dump-tables SWITCH print table stats\n"
" mod-port SWITCH IFACE ACT modify port behavior\n"
+ " mod-table SWITCH MOD modify flow table behavior\n"
" get-frags SWITCH print fragment handling behavior\n"
" set-frags SWITCH FRAG_MODE set fragment handling behavior\n"
" dump-ports SWITCH [PORT] print port statistics\n"
" monitor SWITCH [MISSLEN] [invalid_ttl] [watch:[...]]\n"
" print packets received from SWITCH\n"
" snoop SWITCH snoop on SWITCH and its controller\n"
+ " add-group SWITCH GROUP add group described by GROUP\n"
+ " add-group SWITCH FILE add group from FILE\n"
+ " mod-group SWITCH GROUP modify specific group\n"
+ " del-groups SWITCH [GROUP] delete matching GROUPs\n"
+ " dump-group-features SWITCH print group features\n"
+ " dump-groups SWITCH print group description\n"
+ " dump-group-stats SWITCH [GROUP] print group statistics\n"
"\nFor OpenFlow switches and controllers:\n"
" probe TARGET probe whether TARGET is up\n"
" ping TARGET [N] latency of N-byte echos\n"
vconn_close(vconn);
}
+static void
+ofctl_mod_table(int argc OVS_UNUSED, char *argv[])
+{
+ enum ofputil_protocol protocol, usable_protocols;
+ struct ofputil_table_mod tm;
+ struct vconn *vconn;
+ char *error;
+ int i;
+
+ error = parse_ofp_table_mod(&tm, argv[2], argv[3], &usable_protocols);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
+
+ protocol = open_vconn(argv[1], &vconn);
+ if (!(protocol & usable_protocols)) {
+ for (i = 0; i < sizeof(enum ofputil_protocol) * CHAR_BIT; i++) {
+ enum ofputil_protocol f = 1 << i;
+ if (f != protocol
+ && f & usable_protocols
+ && try_set_protocol(vconn, f, &protocol)) {
+ protocol = f;
+ break;
+ }
+ }
+ }
+
+ if (!(protocol & usable_protocols)) {
+ char *usable_s = ofputil_protocols_to_string(usable_protocols);
+ ovs_fatal(0, "Switch does not support table mod message(%s)", usable_s);
+ }
+
+ transact_noreply(vconn, ofputil_encode_table_mod(&tm, protocol));
+ vconn_close(vconn);
+}
+
static void
ofctl_get_frags(int argc OVS_UNUSED, char *argv[])
{
count * message_size / (duration / 1000.0));
}
+static void
+ofctl_group_mod__(const char *remote, struct ofputil_group_mod *gms,
+ size_t n_gms)
+{
+ struct ofputil_group_mod *gm;
+ struct ofpbuf *request;
+
+ struct vconn *vconn;
+ size_t i;
+
+ open_vconn(remote, &vconn);
+
+ for (i = 0; i < n_gms; i++) {
+ gm = &gms[i];
+ request = ofputil_encode_group_mod(vconn_get_version(vconn), gm);
+ if (request) {
+ transact_noreply(vconn, request);
+ }
+ }
+
+ vconn_close(vconn);
+
+}
+
+
+static void
+ofctl_group_mod_file(int argc OVS_UNUSED, char *argv[], uint16_t command)
+{
+ struct ofputil_group_mod *gms = NULL;
+ enum ofputil_protocol usable_protocols;
+ size_t n_gms = 0;
+ char *error;
+
+ error = parse_ofp_group_mod_file(argv[2], command, &gms, &n_gms,
+ &usable_protocols);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
+ ofctl_group_mod__(argv[1], gms, n_gms);
+ free(gms);
+}
+
+static void
+ofctl_group_mod(int argc, char *argv[], uint16_t command)
+{
+ if (argc > 2 && !strcmp(argv[2], "-")) {
+ ofctl_group_mod_file(argc, argv, command);
+ } else {
+ enum ofputil_protocol usable_protocols;
+ struct ofputil_group_mod gm;
+ char *error;
+
+ error = parse_ofp_group_mod_str(&gm, command, argc > 2 ? argv[2] : "",
+ &usable_protocols);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
+ ofctl_group_mod__(argv[1], &gm, 1);
+ }
+}
+
+static void
+ofctl_add_group(int argc, char *argv[])
+{
+ ofctl_group_mod(argc, argv, OFPGC11_ADD);
+}
+
+static void
+ofctl_add_groups(int argc, char *argv[])
+{
+ ofctl_group_mod_file(argc, argv, OFPGC11_ADD);
+}
+
+static void
+ofctl_mod_group(int argc, char *argv[])
+{
+ ofctl_group_mod(argc, argv, OFPGC11_MODIFY);
+}
+
+static void
+ofctl_del_groups(int argc, char *argv[])
+{
+ ofctl_group_mod(argc, argv, OFPGC11_DELETE);
+}
+
+static void
+ofctl_dump_group_stats(int argc, char *argv[])
+{
+ enum ofputil_protocol usable_protocols;
+ struct ofputil_group_mod gm;
+ struct ofpbuf *request;
+ struct vconn *vconn;
+ uint32_t group_id;
+ char *error;
+
+ memset(&gm, 0, sizeof gm);
+
+ error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE,
+ argc > 2 ? argv[2] : "",
+ &usable_protocols);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
+
+ group_id = gm.group_id;
+
+ open_vconn(argv[1], &vconn);
+ request = ofputil_encode_group_stats_request(vconn_get_version(vconn),
+ group_id);
+ if (request) {
+ dump_stats_transaction(vconn, request);
+ }
+
+ vconn_close(vconn);
+}
+
+static void
+ofctl_dump_group_desc(int argc OVS_UNUSED, char *argv[])
+{
+ struct ofpbuf *request;
+ struct vconn *vconn;
+
+ open_vconn(argv[1], &vconn);
+
+ request = ofputil_encode_group_desc_request(vconn_get_version(vconn));
+ if (request) {
+ dump_stats_transaction(vconn, request);
+ }
+
+ vconn_close(vconn);
+}
+
+static void
+ofctl_dump_group_features(int argc OVS_UNUSED, char *argv[])
+{
+ struct ofpbuf *request;
+ struct vconn *vconn;
+
+ open_vconn(argv[1], &vconn);
+ request = ofputil_encode_group_features_request(vconn_get_version(vconn));
+ if (request) {
+ dump_stats_transaction(vconn, request);
+ }
+
+ vconn_close(vconn);
+}
+
static void
ofctl_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
{ "dump-ports", 1, 2, ofctl_dump_ports },
{ "dump-ports-desc", 1, 1, ofctl_dump_ports_desc },
{ "mod-port", 3, 3, ofctl_mod_port },
+ { "mod-table", 3, 3, ofctl_mod_table },
{ "get-frags", 1, 1, ofctl_get_frags },
{ "set-frags", 2, 2, ofctl_set_frags },
{ "ofp-parse", 1, 1, ofctl_ofp_parse },
{ "probe", 1, 1, ofctl_probe },
{ "ping", 1, 2, ofctl_ping },
{ "benchmark", 3, 3, ofctl_benchmark },
+
+ { "add-group", 1, 2, ofctl_add_group },
+ { "add-groups", 1, 2, ofctl_add_groups },
+ { "mod-group", 1, 2, ofctl_mod_group },
+ { "del-groups", 1, 2, ofctl_del_groups },
+ { "dump-groups", 1, 1, ofctl_dump_group_desc },
+ { "dump-group-stats", 1, 2, ofctl_dump_group_stats },
+ { "dump-group-features", 1, 1, ofctl_dump_group_features },
{ "help", 0, INT_MAX, ofctl_help },
/* Undocumented commands for testing. */