X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Flearning-switch.c;h=78346acbb548bc5e134b6a53f9837891cf7ab221;hb=77909859b05f0d2466069883306e8d75d280bbe7;hp=efc583867dd4f65f79dd978eef950cc30c3f6aff;hpb=064af42167bf4fc9aaea2702d80ce08074b889c0;p=sliver-openvswitch.git diff --git a/lib/learning-switch.c b/lib/learning-switch.c index efc583867..78346acbb 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -1,17 +1,17 @@ /* * Copyright (c) 2008, 2009 Nicira Networks. * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include @@ -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,16 +107,19 @@ 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; - sw = xcalloc(1, sizeof *sw); + sw = xzalloc(sizeof *sw); sw->max_idle = 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 {