X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=lib%2Flearning-switch.c;h=260f5d76abd81055c2a56573a0980b5effd6e8d1;hb=ca069229880ba47ba100b62ed34c0c226355b0c6;hp=73464c688aacd2770fc0d01a1c8087c29bc75b1e;hpb=34e63086edddcae06d7c1a4fa84fec0861e50758;p=openvswitch diff --git a/lib/learning-switch.c b/lib/learning-switch.c index 73464c68..260f5d76 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009 Nicira Networks. + * Copyright (c) 2008, 2009, 2010 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -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; @@ -278,8 +283,8 @@ lswitch_process_packet(struct lswitch *sw, struct rconn *rconn, process_stats_reply }, { - OFPT_FLOW_EXPIRED, - sizeof(struct ofp_flow_expired), + OFPT_FLOW_REMOVED, + sizeof(struct ofp_flow_removed), NULL }, }; @@ -332,7 +337,6 @@ send_features_request(struct lswitch *sw, struct rconn *rconn) /* Send OFPT_SET_CONFIG. */ osc = make_openflow(sizeof *osc, OFPT_SET_CONFIG, &b); - osc->flags = htons(OFPC_SEND_FLOW_EXP); osc->miss_send_len = htons(OFP_DEFAULT_MISS_SEND_LEN); queue_tx(sw, rconn, b); @@ -430,10 +434,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 +469,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 { @@ -482,7 +516,8 @@ process_port_status(struct lswitch *sw, struct rconn *rconn, void *ops_) } static void -process_phy_port(struct lswitch *sw, struct rconn *rconn UNUSED, void *opp_) +process_phy_port(struct lswitch *sw, struct rconn *rconn OVS_UNUSED, + void *opp_) { const struct ofp_phy_port *opp = opp_; uint16_t port_no = ntohs(opp->port_no);