From 7286b1e13dbf358ea6071d04b311474208308ad6 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 1 Jun 2011 09:09:20 -0700 Subject: [PATCH] ovs-controller: Allow --wildcards to specify a wildcard set. Based on a patch by Jean Tourrilhes . According to Jean, besides increasing flexibility, this reduces normalization warnings. Tested-by: Jean Tourrilhes --- lib/learning-switch.c | 23 +++++++++++++++-------- lib/learning-switch.h | 11 ++++++++--- lib/ofp-util.c | 2 +- lib/ofp-util.h | 1 + utilities/ovs-controller.8.in | 13 ++++++++++--- utilities/ovs-controller.c | 13 +++++++------ 6 files changed, 42 insertions(+), 21 deletions(-) diff --git a/lib/learning-switch.c b/lib/learning-switch.c index 6bd22862..fc45b043 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -100,14 +100,21 @@ lswitch_create(struct rconn *rconn, const struct lswitch_config *cfg) sw->action_normal = cfg->mode == LSW_NORMAL; flow_wildcards_init_exact(&sw->wc); - if (!cfg->exact_flows) { - /* We cannot wildcard all fields. - * We need in_port to detect moves. - * We need both SA and DA to do learning. */ - sw->wc.wildcards = (FWW_DL_TYPE | FWW_NW_PROTO - | FWW_TP_SRC | FWW_TP_DST); - sw->wc.nw_src_mask = htonl(0); - sw->wc.nw_dst_mask = htonl(0); + if (cfg->wildcards) { + uint32_t ofpfw; + + if (cfg->wildcards == UINT32_MAX) { + /* Try to wildcard as many fields as possible, but we cannot + * wildcard all fields. We need in_port to detect moves. We need + * Ethernet source and dest and VLAN to do L2 learning. */ + ofpfw = (OFPFW_DL_TYPE | OFPFW_NW_SRC_ALL | OFPFW_NW_DST_ALL + | OFPFW_NW_TOS | OFPFW_NW_PROTO + | OFPFW_TP_SRC | OFPFW_TP_DST); + } else { + ofpfw = cfg->wildcards; + } + + ofputil_wildcard_from_openflow(ofpfw, &sw->wc); } sw->default_queue = cfg->default_queue; diff --git a/lib/learning-switch.h b/lib/learning-switch.h index e5036906..c6f347e1 100644 --- a/lib/learning-switch.h +++ b/lib/learning-switch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010 Nicira Networks. + * Copyright (c) 2008, 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. @@ -33,8 +33,13 @@ enum lswitch_mode { struct lswitch_config { enum lswitch_mode mode; - /* Set up only exact-match flows? */ - bool exact_flows; + /* 0 to use exact-match flow entries, + * a OFPFW_* bitmask to enable specific wildcards, + * or UINT32_MAX to use the default wildcards (wildcarding as many fields + * as possible. + * + * Ignored when max_idle < 0 (in which case no flows are set up). */ + uint32_t wildcards; /* <0: Process every packet at the controller. * >=0: Expire flows after they are unused for 'max_idle' seconds. diff --git a/lib/ofp-util.c b/lib/ofp-util.c index df2f21df..e21831fd 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -104,7 +104,7 @@ static const flow_wildcards_t WC_INVARIANTS = 0 /* Converts the wildcard in 'ofpfw' into a flow_wildcards in 'wc' for use in * struct cls_rule. It is the caller's responsibility to handle the special * case where the flow match's dl_vlan is set to OFP_VLAN_NONE. */ -static void +void ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc) { /* Initialize most of rule->wc. */ diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 152f4dd8..bba36630 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -99,6 +99,7 @@ ovs_be32 ofputil_wcbits_to_netmask(int wcbits); int ofputil_netmask_to_wcbits(ovs_be32 netmask); /* Work with OpenFlow 1.0 ofp_match. */ +void ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *); void ofputil_cls_rule_from_match(const struct ofp_match *, unsigned int priority, struct cls_rule *); void ofputil_normalize_rule(struct cls_rule *, enum nx_flow_format); diff --git a/utilities/ovs-controller.8.in b/utilities/ovs-controller.8.in index 18d77de2..016c7e39 100644 --- a/utilities/ovs-controller.8.in +++ b/utilities/ovs-controller.8.in @@ -65,13 +65,20 @@ 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" -.IQ "\fB\-\-wildcard\fR" +.IP "\fB\-w\fR[\fIwildcard_mask\fR]" +.IQ "\fB\-\-wildcards\fR[\fB=\fIwildcard_mask\fR]\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 +flow setup latency by causing less traffic to be sent up to the controller. .IP +The optional \fIwildcard_mask\fR is an OpenFlow wildcard bitmask in +hexadecimal that specifies the fields to wildcard. If no +\fIwildcard_mask\fR is specified, the default value 0x2820F0 is used +which specifies L2-only switching and wildcards L3 and L4 fields. +Another interesting value is 0x2000EC, which specifies L3-only +switching and wildcards L2 and L4 fields. +.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). . diff --git a/utilities/ovs-controller.c b/utilities/ovs-controller.c index f9779747..022b1a4d 100644 --- a/utilities/ovs-controller.c +++ b/utilities/ovs-controller.c @@ -61,8 +61,9 @@ 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; +/* -w, --wildcard: 0 to disable wildcard flow entries, a OFPFW_* bitmask to + * enable specific wildcards, or UINT32_MAX to use the default wildcards. */ +static uint32_t wildcards = 0; /* --max-idle: Maximum idle time, in seconds, before flows expire. */ static int max_idle = 60; @@ -227,7 +228,7 @@ new_switch(struct switch_ *sw, struct vconn *vconn) cfg.mode = (action_normal ? LSW_NORMAL : learn_macs ? LSW_LEARN : LSW_FLOOD); - cfg.exact_flows = exact_flows; + cfg.wildcards = wildcards; cfg.max_idle = set_up_flows ? max_idle : -1; cfg.default_flows = &default_flows; cfg.default_queue = default_queue; @@ -317,7 +318,7 @@ parse_options(int argc, char *argv[]) {"hub", no_argument, NULL, 'H'}, {"noflow", no_argument, NULL, 'n'}, {"normal", no_argument, NULL, 'N'}, - {"wildcard", no_argument, NULL, 'w'}, + {"wildcards", optional_argument, NULL, 'w'}, {"max-idle", required_argument, NULL, OPT_MAX_IDLE}, {"mute", no_argument, NULL, OPT_MUTE}, {"queue", required_argument, NULL, 'q'}, @@ -361,7 +362,7 @@ parse_options(int argc, char *argv[]) break; case 'w': - exact_flows = false; + wildcards = optarg ? strtol(optarg, NULL, 16) : UINT32_MAX; break; case OPT_MAX_IDLE: @@ -447,7 +448,7 @@ usage(void) " -n, --noflow pass traffic, but don't add flows\n" " --max-idle=SECS max idle time for new flows\n" " -N, --normal use OFPP_NORMAL action\n" - " -w, --wildcard use wildcards, not exact-match rules\n" + " -w, --wildcards[=MASK] wildcard (specified) bits in flows\n" " -q, --queue=QUEUE-ID OpenFlow queue ID to use for output\n" " -Q PORT-NAME:QUEUE-ID use QUEUE-ID for frames from PORT-NAME\n" " --with-flows FILE use the flows from FILE\n" -- 2.30.2