From 9af9e2e8cff919c6053d862703ac228ce1a15bdd Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Thu, 19 Nov 2009 12:48:32 -0800 Subject: [PATCH] ovs-controller: Add --wildcard and --normal features. This adds two command line switches to ovs-controller to: 1) Use wildcards instead of exact matches. 2) Use "normal" action instead of explicit port. --- lib/learning-switch.c | 43 +++++++++++++++++++++++++++++++---- lib/learning-switch.h | 4 +++- utilities/ovs-controller.8.in | 19 +++++++++++++++- utilities/ovs-controller.c | 23 +++++++++++++++++-- 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/lib/learning-switch.c b/lib/learning-switch.c index 73464c68..ecfa87f6 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -57,6 +57,8 @@ struct lswitch { uint32_t capabilities; time_t last_features_request; struct mac_learning *ml; /* NULL to act as hub instead of switch. */ + bool exact_flows; /* Use exact-match flows? */ + bool action_normal; /* Use OFPP_NORMAL? */ /* Number of outgoing queued packets on the rconn. */ struct rconn_packet_counter *queued; @@ -105,7 +107,8 @@ static packet_handler_func process_stats_reply; * * 'rconn' is used to send out an OpenFlow features request. */ struct lswitch * -lswitch_create(struct rconn *rconn, bool learn_macs, int max_idle) +lswitch_create(struct rconn *rconn, bool learn_macs, + bool exact_flows, int max_idle, bool action_normal) { struct lswitch *sw; size_t i; @@ -115,6 +118,8 @@ lswitch_create(struct rconn *rconn, bool learn_macs, int max_idle) sw->datapath_id = 0; sw->last_features_request = time_now() - 1; sw->ml = learn_macs ? mac_learning_create() : NULL; + sw->action_normal = action_normal; + sw->exact_flows = exact_flows; sw->queued = rconn_packet_counter_create(); sw->next_query = LLONG_MIN; sw->last_query = LLONG_MIN; @@ -430,10 +435,34 @@ process_packet_in(struct lswitch *sw, struct rconn *rconn, void *opi_) /* Don't send out packets on their input ports. */ goto drop_it; } else if (sw->max_idle >= 0 && (!sw->ml || out_port != OFPP_FLOOD)) { + struct ofpbuf *buffer; + struct ofp_flow_mod *ofm; + uint32_t wildcards; + + /* Check if we need to wildcard the flows. */ + if (!sw->exact_flows) { + /* We can not wildcard all fields. + * We need in_port to detect moves. + * We need both SA and DA to do learning. */ + wildcards = (OFPFW_DL_TYPE | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK + | OFPFW_NW_PROTO | OFPFW_TP_SRC | OFPFW_TP_DST); + } else { + /* Exact match */ + wildcards = 0; + } + + /* Check if we need to use "NORMAL" action. */ + if (sw->action_normal && out_port != OFPP_FLOOD) { + out_port = OFPP_NORMAL; + } + /* The output port is known, or we always flood everything, so add a * new flow. */ - queue_tx(sw, rconn, make_add_simple_flow(&flow, ntohl(opi->buffer_id), - out_port, sw->max_idle)); + buffer = make_add_simple_flow(&flow, ntohl(opi->buffer_id), + out_port, sw->max_idle); + ofm = buffer->data; + ofm->match.wildcards = htonl(wildcards); + queue_tx(sw, rconn, buffer); /* If the switch didn't buffer the packet, we need to send a copy. */ if (ntohl(opi->buffer_id) == UINT32_MAX) { @@ -441,9 +470,15 @@ process_packet_in(struct lswitch *sw, struct rconn *rconn, void *opi_) make_unbuffered_packet_out(&pkt, in_port, out_port)); } } else { + struct ofpbuf *b; + + /* Check if we need to use "NORMAL" action. */ + if (sw->action_normal && out_port != OFPP_FLOOD) { + out_port = OFPP_NORMAL; + } + /* We don't know that MAC, or we don't set up flows. Send along the * packet without setting up a flow. */ - struct ofpbuf *b; if (ntohl(opi->buffer_id) == UINT32_MAX) { b = make_unbuffered_packet_out(&pkt, in_port, out_port); } else { diff --git a/lib/learning-switch.h b/lib/learning-switch.h index 8837d647..2de862e6 100644 --- a/lib/learning-switch.h +++ b/lib/learning-switch.h @@ -22,7 +22,9 @@ struct ofpbuf; struct rconn; -struct lswitch *lswitch_create(struct rconn *, bool learn_macs, int max_idle); +struct lswitch *lswitch_create(struct rconn *, bool learn_macs, + bool exact_flows, int max_idle, + bool action_normal); void lswitch_run(struct lswitch *, struct rconn *); void lswitch_wait(struct lswitch *); void lswitch_destroy(struct lswitch *); diff --git a/utilities/ovs-controller.8.in b/utilities/ovs-controller.8.in index 07ea6840..040f6330 100644 --- a/utilities/ovs-controller.8.in +++ b/utilities/ovs-controller.8.in @@ -118,7 +118,24 @@ through the controller and every packet is flooded. This option is most useful for debugging. It reduces switching performance, so it should not be used in production. - +. +.IP "\fB-w\fR, \fB--wildcard\fR" +By default, \fBovs\-controller\fR sets up exact-match flows. This +option allows it to set up wildcarded flows, which may reduce +flow-setup latency by causing less traffic to be sent up to the +controller. +.IP +This option has no effect when \fB-n\fR (or \fB--noflow\fR) is in use +(because the controller does not set up flows in that case). +. +.IP "\fB-N\fR, \fB--normal\fR" +By default, \fBovs\-controller\fR directs packets to a particular port +or floods them. This option causes it to direct non-flooded packets +to the OpenFlow \fBOFPP_NORMAL\fR port. This allows the switch itself +to make decisions about packet destinations. Support for +\fBOFPP_NORMAL\fR is optional in OpenFlow, so this option may not well +with some non-Open vSwitch switches. +. .IP "\fB--mute\fR" Prevents ovs\-controller from replying to any OpenFlow messages sent to it by switches. diff --git a/utilities/ovs-controller.c b/utilities/ovs-controller.c index 30ab52db..bb55c7fe 100644 --- a/utilities/ovs-controller.c +++ b/utilities/ovs-controller.c @@ -55,6 +55,12 @@ static bool learn_macs = true; /* Set up flows? (If not, every packet is processed at the controller.) */ static bool set_up_flows = true; +/* -N, --normal: Use "NORMAL" action instead of explicit port? */ +static bool action_normal = false; + +/* -w, --wildcard: Set up exact match or wildcard flow entries? */ +static bool exact_flows = true; + /* --max-idle: Maximum idle time, in seconds, before flows expire. */ static int max_idle = 60; @@ -201,8 +207,9 @@ static void new_switch(struct switch_ *sw, struct vconn *vconn, const char *name) { sw->rconn = rconn_new_from_vconn(name, vconn); - sw->lswitch = lswitch_create(sw->rconn, learn_macs, - set_up_flows ? max_idle : -1); + sw->lswitch = lswitch_create(sw->rconn, learn_macs, exact_flows, + set_up_flows ? max_idle : -1, + action_normal); } static int @@ -239,6 +246,8 @@ parse_options(int argc, char *argv[]) static struct option long_options[] = { {"hub", no_argument, 0, 'H'}, {"noflow", no_argument, 0, 'n'}, + {"normal", no_argument, 0, 'N'}, + {"wildcard", no_argument, 0, 'w'}, {"max-idle", required_argument, 0, OPT_MAX_IDLE}, {"mute", no_argument, 0, OPT_MUTE}, {"help", no_argument, 0, 'h'}, @@ -275,6 +284,14 @@ parse_options(int argc, char *argv[]) mute = true; break; + case 'N': + action_normal = true; + break; + + case 'w': + exact_flows = false; + break; + case OPT_MAX_IDLE: if (!strcmp(optarg, "permanent")) { max_idle = OFP_FLOW_PERMANENT; @@ -329,6 +346,8 @@ usage(void) " -H, --hub act as hub instead of learning switch\n" " -n, --noflow pass traffic, but don't add flows\n" " --max-idle=SECS max idle time for new flows\n" + " -N, --normal use OFPAT_NORMAL action\n" + " -w, --wildcard use wildcards, not exact-match rules\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); -- 2.30.2