X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Flearning-switch.c;h=8efbce1a5ebecc8c019e5cd9312a4e68408ba3fd;hb=fe29af4c888d48cc1f16b1a247c2ffb6f0864522;hp=f2b331904e6110106141585a394adb9c135587d2;hpb=5d9895170f5b066d4cb2984fc5a890478a5b8206;p=sliver-openvswitch.git diff --git a/lib/learning-switch.c b/lib/learning-switch.c index f2b331904..8efbce1a5 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -89,6 +89,7 @@ struct lswitch { * to set up the flow table. */ const struct ofputil_flow_mod *default_flows; size_t n_default_flows; + enum ofputil_protocol usable_protocols; }; /* The log messages here could actually be useful in debugging, so keep the @@ -161,6 +162,7 @@ lswitch_create(struct rconn *rconn, const struct lswitch_config *cfg) sw->default_flows = cfg->default_flows; sw->n_default_flows = cfg->n_default_flows; + sw->usable_protocols = cfg->usable_protocols; sw->queued = rconn_packet_counter_create(); @@ -176,7 +178,6 @@ lswitch_handshake(struct lswitch *sw) protocol = ofputil_protocol_from_ofp_version(rconn_get_version(sw->rconn)); if (sw->default_flows) { - enum ofputil_protocol usable_protocols; struct ofpbuf *msg = NULL; int error = 0; size_t i; @@ -188,10 +189,8 @@ lswitch_handshake(struct lswitch *sw) * This could be improved by actually negotiating a mutually acceptable * flow format with the switch, but that would require an asynchronous * state machine. This version ought to work fine in practice. */ - usable_protocols = ofputil_flow_mod_usable_protocols( - sw->default_flows, sw->n_default_flows); - if (!(protocol & usable_protocols)) { - enum ofputil_protocol want = rightmost_1bit(usable_protocols); + if (!(protocol & sw->usable_protocols)) { + enum ofputil_protocol want = rightmost_1bit(sw->usable_protocols); while (!error) { msg = ofputil_encode_set_protocol(protocol, want, &protocol); if (!msg) { @@ -200,7 +199,7 @@ lswitch_handshake(struct lswitch *sw) error = rconn_send(sw->rconn, msg, NULL); } } - if (protocol & usable_protocols) { + if (protocol & sw->usable_protocols) { for (i = 0; !error && i < sw->n_default_flows; i++) { msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol); error = rconn_send(sw->rconn, msg, NULL); @@ -208,7 +207,7 @@ lswitch_handshake(struct lswitch *sw) if (error) { VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)", - rconn_get_name(sw->rconn), strerror(error)); + rconn_get_name(sw->rconn), ovs_strerror(error)); } } else { VLOG_INFO_RL(&rl, "%s: failed to set usable protocol", @@ -251,7 +250,9 @@ lswitch_run(struct lswitch *sw) int i; if (sw->ml) { - mac_learning_run(sw->ml, NULL); + ovs_rwlock_wrlock(&sw->ml->rwlock); + mac_learning_run(sw->ml); + ovs_rwlock_unlock(&sw->ml->rwlock); } rconn_run(sw->rconn); @@ -283,7 +284,9 @@ void lswitch_wait(struct lswitch *sw) { if (sw->ml) { + ovs_rwlock_rdlock(&sw->ml->rwlock); mac_learning_wait(sw->ml); + ovs_rwlock_unlock(&sw->ml->rwlock); } rconn_run_wait(sw->rconn); rconn_recv_wait(sw->rconn); @@ -343,7 +346,9 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) case OFPTYPE_PORT_STATUS: case OFPTYPE_PACKET_OUT: case OFPTYPE_FLOW_MOD: + case OFPTYPE_GROUP_MOD: case OFPTYPE_PORT_MOD: + case OFPTYPE_TABLE_MOD: case OFPTYPE_BARRIER_REQUEST: case OFPTYPE_BARRIER_REPLY: case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: @@ -364,6 +369,7 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) case OFPTYPE_PORT_DESC_STATS_REPLY: case OFPTYPE_ROLE_REQUEST: case OFPTYPE_ROLE_REPLY: + case OFPTYPE_ROLE_STATUS: case OFPTYPE_SET_FLOW_FORMAT: case OFPTYPE_FLOW_MOD_TABLE_ID: case OFPTYPE_SET_PACKET_IN_FORMAT: @@ -378,20 +384,20 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) case OFPTYPE_GET_ASYNC_REPLY: case OFPTYPE_SET_ASYNC_CONFIG: case OFPTYPE_METER_MOD: - case OFPTYPE_GROUP_REQUEST: - case OFPTYPE_GROUP_REPLY: - case OFPTYPE_GROUP_DESC_REQUEST: - case OFPTYPE_GROUP_DESC_REPLY: - case OFPTYPE_GROUP_FEATURES_REQUEST: - case OFPTYPE_GROUP_FEATURES_REPLY: - case OFPTYPE_METER_REQUEST: - case OFPTYPE_METER_REPLY: - case OFPTYPE_METER_CONFIG_REQUEST: - case OFPTYPE_METER_CONFIG_REPLY: - case OFPTYPE_METER_FEATURES_REQUEST: - case OFPTYPE_METER_FEATURES_REPLY: - case OFPTYPE_TABLE_FEATURES_REQUEST: - case OFPTYPE_TABLE_FEATURES_REPLY: + case OFPTYPE_GROUP_STATS_REQUEST: + case OFPTYPE_GROUP_STATS_REPLY: + case OFPTYPE_GROUP_DESC_STATS_REQUEST: + case OFPTYPE_GROUP_DESC_STATS_REPLY: + case OFPTYPE_GROUP_FEATURES_STATS_REQUEST: + case OFPTYPE_GROUP_FEATURES_STATS_REPLY: + case OFPTYPE_METER_STATS_REQUEST: + case OFPTYPE_METER_STATS_REPLY: + case OFPTYPE_METER_CONFIG_STATS_REQUEST: + case OFPTYPE_METER_CONFIG_STATS_REPLY: + case OFPTYPE_METER_FEATURES_STATS_REQUEST: + case OFPTYPE_METER_FEATURES_STATS_REPLY: + case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: + case OFPTYPE_TABLE_FEATURES_STATS_REPLY: default: if (VLOG_IS_DBG_ENABLED()) { char *s = ofp_to_string(msg->data, msg->size, 2); @@ -433,7 +439,7 @@ queue_tx(struct lswitch *sw, struct ofpbuf *b) } else { VLOG_WARN_RL(&rl, "%016llx: %s: send: %s", sw->datapath_id, rconn_get_name(sw->rconn), - strerror(retval)); + ovs_strerror(retval)); } } } @@ -472,17 +478,22 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow) ofp_port_t out_port; /* Learn the source MAC. */ - if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) { - struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src, 0); - if (mac_entry_is_new(mac) - || mac->port.ofp_port != flow->in_port.ofp_port) { - VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on " - "port %"PRIu16, sw->datapath_id, - ETH_ADDR_ARGS(flow->dl_src), flow->in_port.ofp_port); - - mac->port.ofp_port = flow->in_port.ofp_port; - mac_learning_changed(sw->ml, mac); + if (sw->ml) { + ovs_rwlock_wrlock(&sw->ml->rwlock); + if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) { + struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src, + 0); + if (mac->port.ofp_port != flow->in_port.ofp_port) { + VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on " + "port %"PRIu16, sw->datapath_id, + ETH_ADDR_ARGS(flow->dl_src), + flow->in_port.ofp_port); + + mac->port.ofp_port = flow->in_port.ofp_port; + mac_learning_changed(sw->ml); + } } + ovs_rwlock_unlock(&sw->ml->rwlock); } /* Drop frames for reserved multicast addresses. */ @@ -494,14 +505,17 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow) if (sw->ml) { struct mac_entry *mac; - mac = mac_learning_lookup(sw->ml, flow->dl_dst, 0, NULL); + ovs_rwlock_rdlock(&sw->ml->rwlock); + mac = mac_learning_lookup(sw->ml, flow->dl_dst, 0); if (mac) { out_port = mac->port.ofp_port; if (out_port == flow->in_port.ofp_port) { /* Don't send a packet back out its input port. */ + ovs_rwlock_unlock(&sw->ml->rwlock); return OFPP_NONE; } } + ovs_rwlock_unlock(&sw->ml->rwlock); } /* Check if we need to use "NORMAL" action. */