X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=utilities%2Fovs-ofctl.c;h=a96b77a94be9e9634c0ac5b19fe551b7fb16d179;hb=55eccb868b8f1da858a9f724335b5bb059276497;hp=8da6e1a033cec188665140773576f9af8968e637;hpb=640c7c945f3c748240609dc572858fc188db1c06;p=openvswitch diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 8da6e1a0..a96b77a9 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -622,6 +622,43 @@ do_queue_stats(int argc, char *argv[]) dump_stats_transaction(argv[1], request); } +/* Sets up the flow format for a vconn that will be used to modify the flow + * table. Returns the flow format used, after possibly adding an OpenFlow + * request to 'requests'. + * + * If 'preferred_flow_format' is -1, returns NXFF_OPENFLOW10 without modifying + * 'requests', since NXFF_OPENFLOW10 is the default flow format for any + * OpenFlow connection. + * + * If 'preferred_flow_format' is a specific format, adds a request to set that + * format to 'requests' and returns the format. */ +static enum nx_flow_format +set_initial_format_for_flow_mod(struct list *requests) +{ + if (preferred_flow_format < 0) { + return NXFF_OPENFLOW10; + } else { + struct ofpbuf *sff; + + sff = ofputil_make_set_flow_format(preferred_flow_format); + list_push_back(requests, &sff->list_node); + return preferred_flow_format; + } +} + +/* Checks that 'flow_format' is acceptable as a flow format after a flow_mod + * operation, given the global 'preferred_flow_format'. */ +static void +check_final_format_for_flow_mod(enum nx_flow_format flow_format) +{ + if (preferred_flow_format >= 0 && flow_format != preferred_flow_format) { + ovs_fatal(0, "flow cannot be expressed in flow format %s " + "(flow format %s or better is required)", + ofputil_flow_format_to_string(preferred_flow_format), + ofputil_flow_format_to_string(flow_format)); + } +} + static void do_flow_mod__(int argc OVS_UNUSED, char *argv[], uint16_t command) { @@ -630,9 +667,11 @@ do_flow_mod__(int argc OVS_UNUSED, char *argv[], uint16_t command) struct vconn *vconn; list_init(&requests); - flow_format = NXFF_OPENFLOW10; + flow_format = set_initial_format_for_flow_mod(&requests); + parse_ofp_flow_mod_str(&requests, &flow_format, argc > 2 ? argv[2] : "", command); + check_final_format_for_flow_mod(flow_format); open_vconn(argv[1], &vconn); transact_multiple_noreply(vconn, &requests); @@ -659,10 +698,11 @@ do_add_flows(int argc OVS_UNUSED, char *argv[]) } list_init(&requests); - flow_format = NXFF_OPENFLOW10; + flow_format = set_initial_format_for_flow_mod(&requests); open_vconn(argv[1], &vconn); while (parse_ofp_add_flow_file(&requests, &flow_format, file)) { + check_final_format_for_flow_mod(flow_format); transact_multiple_noreply(vconn, &requests); } vconn_close(vconn); @@ -884,6 +924,38 @@ do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) /* Undocumented commands for unit testing. */ +static void +print_packet_list(struct list *packets) +{ + struct ofpbuf *packet, *next; + + LIST_FOR_EACH_SAFE (packet, next, list_node, packets) { + ofp_print(stdout, packet->data, packet->size, verbosity); + list_remove(&packet->list_node); + ofpbuf_delete(packet); + } +} + +/* "parse-flow FLOW": parses the argument as a flow (like add-flow) and prints + * it back to stdout. */ +static void +do_parse_flow(int argc OVS_UNUSED, char *argv[]) +{ + enum nx_flow_format flow_format; + struct list packets; + + flow_format = NXFF_OPENFLOW10; + if (preferred_flow_format > 0) { + flow_format = preferred_flow_format; + } + + list_init(&packets); + parse_ofp_flow_mod_str(&packets, &flow_format, argv[1], OFPFC_ADD); + print_packet_list(&packets); +} + +/* "parse-flows FILENAME": reads the named file as a sequence of flows (like + * add-flows) and prints each of the flows back to stdout. */ static void do_parse_flows(int argc OVS_UNUSED, char *argv[]) { @@ -896,24 +968,21 @@ do_parse_flows(int argc OVS_UNUSED, char *argv[]) ovs_fatal(errno, "%s: open", argv[2]); } - list_init(&packets); flow_format = NXFF_OPENFLOW10; if (preferred_flow_format > 0) { flow_format = preferred_flow_format; } + list_init(&packets); while (parse_ofp_add_flow_file(&packets, &flow_format, file)) { - struct ofpbuf *packet, *next; - - LIST_FOR_EACH_SAFE (packet, next, list_node, &packets) { - ofp_print(stdout, packet->data, packet->size, verbosity); - list_remove(&packet->list_node); - ofpbuf_delete(packet); - } + print_packet_list(&packets); } fclose(file); } +/* "parse-nx-match": reads a series of nx_match specifications as strings from + * stdin, does some internal fussing with them, and then prints them back as + * strings on stdout. */ static void do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) { @@ -968,6 +1037,22 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ds_destroy(&in); } +/* "ofp-print HEXSTRING [VERBOSITY]": Converts the hex digits in HEXSTRING into + * binary data, interpreting them as an OpenFlow message, and prints the + * OpenFlow message on stdout, at VERBOSITY (level 2 by default). */ +static void +do_ofp_print(int argc, char *argv[]) +{ + struct ofpbuf packet; + + ofpbuf_init(&packet, strlen(argv[1]) / 2); + if (ofpbuf_put_hex(&packet, argv[1], NULL)[0] != '\0') { + ovs_fatal(0, "trailing garbage following hex bytes"); + } + ofp_print(stdout, packet.data, packet.size, argc > 2 ? atoi(argv[2]) : 2); + ofpbuf_uninit(&packet); +} + static const struct command all_commands[] = { { "show", 1, 1, do_show }, { "status", 1, 2, do_status }, @@ -990,8 +1075,10 @@ static const struct command all_commands[] = { { "help", 0, INT_MAX, do_help }, /* Undocumented commands for testing. */ + { "parse-flow", 1, 1, do_parse_flow }, { "parse-flows", 1, 1, do_parse_flows }, { "parse-nx-match", 0, 0, do_parse_nx_match }, + { "ofp-print", 1, 2, do_ofp_print }, { NULL, 0, 0, NULL }, };