X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=utilities%2Fdpctl.c;h=bd89065d698ea0708b5ac6386b43a0605a873e25;hb=57d52057650716ee354ebbe588d2a884ccabc81f;hp=33a51f856c2413e2efba907baf9007547270b5fe;hpb=d0fb7347b9029284128b0ceb433c586dfd43dc62;p=sliver-openvswitch.git diff --git a/utilities/dpctl.c b/utilities/dpctl.c index 33a51f856..bd89065d6 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -204,7 +204,8 @@ usage(void) " dump-aggregate SWITCH FLOW print aggregate stats for FLOWs\n" " add-flow SWITCH FLOW add flow described by FLOW\n" " add-flows SWITCH FILE add flows from FILE\n" - " del-flows SWITCH FLOW delete matching FLOWs\n" + " mod-flows SWITCH FLOW modify actions of matching FLOWs\n" + " del-flows SWITCH [FLOW] delete matching FLOWs\n" " monitor SWITCH print packets received from SWITCH\n" "\nFor local datapaths, remote switches, and controllers:\n" " probe VCONN probe whether VCONN is up\n" @@ -328,6 +329,12 @@ static void do_del_port(int argc UNUSED, char *argv[]) /* Generic commands. */ +static void +open_vconn(const char *name, struct vconn **vconnp) +{ + run(vconn_open_block(name, OFP_VERSION, vconnp), "connecting to %s", name); +} + static void * alloc_stats_request(size_t body_len, uint16_t type, struct buffer **bufferp) { @@ -353,7 +360,7 @@ dump_transaction(const char *vconn_name, struct buffer *request) struct buffer *reply; update_openflow_length(request); - run(vconn_open_block(vconn_name, &vconn), "connecting to %s", vconn_name); + open_vconn(vconn_name, &vconn); run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name); ofp_print(stdout, reply->data, reply->size, 1); vconn_close(vconn); @@ -374,7 +381,7 @@ dump_stats_transaction(const char *vconn_name, struct buffer *request) struct vconn *vconn; bool done = false; - run(vconn_open_block(vconn_name, &vconn), "connecting to %s", vconn_name); + open_vconn(vconn_name, &vconn); send_openflow_buffer(vconn, request); while (!done) { uint32_t recv_xid; @@ -426,7 +433,7 @@ do_status(int argc, char *argv[]) if (argc > 2) { buffer_put(b, argv[2], strlen(argv[2])); } - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); + open_vconn(argv[1], &vconn); run(vconn_transact(vconn, b, &b), "talking to %s", argv[1]); vconn_close(vconn); @@ -793,8 +800,6 @@ static void do_add_flow(int argc, char *argv[]) size_t size; int n_actions = MAX_ADD_ACTS; - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); - /* Parse and send. */ size = sizeof *ofm + (sizeof ofm->actions[0] * MAX_ADD_ACTS); ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer); @@ -810,6 +815,7 @@ static void do_add_flow(int argc, char *argv[]) /* xxx Should we use the buffer library? */ buffer->size -= (MAX_ADD_ACTS - n_actions) * sizeof ofm->actions[0]; + open_vconn(argv[1], &vconn); send_openflow_buffer(vconn, buffer); vconn_close(vconn); } @@ -817,7 +823,6 @@ static void do_add_flow(int argc, char *argv[]) static void do_add_flows(int argc, char *argv[]) { struct vconn *vconn; - FILE *file; char line[1024]; @@ -826,7 +831,7 @@ static void do_add_flows(int argc, char *argv[]) fatal(errno, "%s: open", argv[2]); } - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); + open_vconn(argv[1], &vconn); while (fgets(line, sizeof line, file)) { struct buffer *buffer; struct ofp_flow_mod *ofm; @@ -868,17 +873,43 @@ static void do_add_flows(int argc, char *argv[]) fclose(file); } +static void do_mod_flows(int argc, char *argv[]) +{ + uint16_t idle_timeout, hard_timeout; + struct vconn *vconn; + struct buffer *buffer; + struct ofp_flow_mod *ofm; + size_t size; + int n_actions = MAX_ADD_ACTS; + + /* Parse and send. */ + size = sizeof *ofm + (sizeof ofm->actions[0] * MAX_ADD_ACTS); + ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer); + str_to_flow(argv[2], &ofm->match, &ofm->actions[0], &n_actions, + NULL, NULL, &idle_timeout, &hard_timeout); + ofm->command = htons(OFPFC_MODIFY); + ofm->idle_timeout = htons(idle_timeout); + ofm->hard_timeout = htons(hard_timeout); + ofm->buffer_id = htonl(UINT32_MAX); + ofm->priority = htons(0); + ofm->reserved = htonl(0); + + /* xxx Should we use the buffer library? */ + buffer->size -= (MAX_ADD_ACTS - n_actions) * sizeof ofm->actions[0]; + + open_vconn(argv[1], &vconn); + send_openflow_buffer(vconn, buffer); + vconn_close(vconn); +} + static void do_del_flows(int argc, char *argv[]) { struct vconn *vconn; uint16_t priority; - - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); struct buffer *buffer; struct ofp_flow_mod *ofm; size_t size; - /* Parse and send. */ size = sizeof *ofm; ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer); @@ -891,8 +922,8 @@ static void do_del_flows(int argc, char *argv[]) ofm->priority = htons(priority); ofm->reserved = htonl(0); + open_vconn(argv[1], &vconn); send_openflow_buffer(vconn, buffer); - vconn_close(vconn); } @@ -910,7 +941,7 @@ do_monitor(int argc UNUSED, char *argv[]) } else { name = argv[1]; } - run(vconn_open_block(argv[1], &vconn), "connecting to %s", name); + open_vconn(argv[1], &vconn); for (;;) { struct buffer *b; run(vconn_recv_block(vconn, &b), "vconn_recv"); @@ -933,7 +964,7 @@ do_probe(int argc, char *argv[]) struct buffer *reply; make_openflow(sizeof(struct ofp_header), OFPT_ECHO_REQUEST, &request); - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); + open_vconn(argv[1], &vconn); run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]); if (reply->size != request->size) { fatal(0, "reply does not match request"); @@ -965,7 +996,7 @@ do_mod_port(int argc, char *argv[]) /* Send a "Features Request" to get the information we need in order * to modify the port. */ make_openflow(sizeof(struct ofp_header), OFPT_FEATURES_REQUEST, &request); - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); + open_vconn(argv[1], &vconn); run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]); osf = reply->data; @@ -1033,7 +1064,7 @@ do_ping(int argc, char *argv[]) fatal(0, "payload must be between 0 and %zu bytes", max_payload); } - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); + open_vconn(argv[1], &vconn); for (i = 0; i < 10; i++) { struct timeval start, end; struct buffer *request, *reply; @@ -1089,7 +1120,7 @@ do_benchmark(int argc, char *argv[]) printf("Sending %d packets * %u bytes (with header) = %u bytes total\n", count, message_size, count * message_size); - run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]); + open_vconn(argv[1], &vconn); gettimeofday(&start, NULL); for (i = 0; i < count; i++) { struct buffer *request, *reply; @@ -1134,6 +1165,7 @@ static struct command all_commands[] = { { "dump-aggregate", 1, 2, do_dump_aggregate }, { "add-flow", 2, 2, do_add_flow }, { "add-flows", 2, 2, do_add_flows }, + { "mod-flows", 2, 2, do_mod_flows }, { "del-flows", 1, 2, do_del_flows }, { "dump-ports", 1, 1, do_dump_ports }, { "mod-port", 3, 3, do_mod_port },