X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fconnmgr.c;h=a58e785a2d6fef7b44e59a0cae1fe6cfda420437;hb=2784a40b81278fc0bd4381ed2fe6e881f0ee51ad;hp=d42ab4f93eccc99a14469f51ad18022a4e6e2b58;hpb=cfa955b083c5617212a29a03423e063ff6cb350a;p=sliver-openvswitch.git diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index d42ab4f93..a58e785a2 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -153,7 +153,7 @@ static void ofconn_set_rate_limit(struct ofconn *, int rate, int burst); static void ofconn_send(const struct ofconn *, struct ofpbuf *, struct rconn_packet_counter *); -static void do_send_packet_in(struct ofpbuf *, void *ofconn_); +static void do_send_packet_ins(struct ofconn *, struct list *txq); /* A listener for incoming OpenFlow "service" connections. */ struct ofservice { @@ -454,7 +454,7 @@ static void add_controller(struct connmgr *, const char *target, uint8_t dscp, OVS_REQUIRES(ofproto_mutex); static struct ofconn *find_controller_by_target(struct connmgr *, const char *target); -static void update_fail_open(struct connmgr *); +static void update_fail_open(struct connmgr *) OVS_EXCLUDED(ofproto_mutex); static int set_pvconns(struct pvconn ***pvconnsp, size_t *n_pvconnsp, const struct sset *); @@ -637,12 +637,13 @@ connmgr_set_controllers(struct connmgr *mgr, shash_destroy(&new_controllers); + ovs_mutex_unlock(&ofproto_mutex); + update_in_band_remotes(mgr); update_fail_open(mgr); if (had_controllers != connmgr_has_controllers(mgr)) { ofproto_flush_flows(mgr->ofproto); } - ovs_mutex_unlock(&ofproto_mutex); } /* Drops the connections between 'mgr' and all of its primary and secondary @@ -733,17 +734,13 @@ update_in_band_remotes(struct connmgr *mgr) /* Add all the remotes. */ HMAP_FOR_EACH (ofconn, hmap_node, &mgr->controllers) { - struct sockaddr_in *sin = &addrs[n_addrs]; const char *target = rconn_get_target(ofconn->rconn); + struct sockaddr_storage ss; - if (ofconn->band == OFPROTO_OUT_OF_BAND) { - continue; - } - - if (stream_parse_target_with_default_port(target, - OFP_OLD_PORT, - sin)) { - n_addrs++; + if (ofconn->band == OFPROTO_IN_BAND + && stream_parse_target_with_default_port(target, OFP_OLD_PORT, &ss) + && ss.ss_family == AF_INET) { + addrs[n_addrs++] = *(struct sockaddr_in *) &ss; } } for (i = 0; i < mgr->n_extra_remotes; i++) { @@ -770,6 +767,7 @@ update_in_band_remotes(struct connmgr *mgr) static void update_fail_open(struct connmgr *mgr) + OVS_EXCLUDED(ofproto_mutex) { if (connmgr_has_controllers(mgr) && mgr->fail_mode == OFPROTO_FAIL_STANDALONE) { @@ -912,17 +910,33 @@ ofconn_get_role(const struct ofconn *ofconn) return ofconn->role; } +void +ofconn_send_role_status(struct ofconn *ofconn, uint32_t role, uint8_t reason) +{ + struct ofputil_role_status status; + struct ofpbuf *buf; + + status.reason = reason; + status.role = role; + ofconn_get_master_election_id(ofconn, &status.generation_id); + + buf = ofputil_encode_role_status(&status, ofconn_get_protocol(ofconn)); + + ofconn_send(ofconn, buf, NULL); +} + /* Changes 'ofconn''s role to 'role'. If 'role' is OFPCR12_ROLE_MASTER then * any existing master is demoted to a slave. */ void ofconn_set_role(struct ofconn *ofconn, enum ofp12_controller_role role) { - if (role == OFPCR12_ROLE_MASTER) { + if (role != ofconn->role && role == OFPCR12_ROLE_MASTER) { struct ofconn *other; HMAP_FOR_EACH (other, hmap_node, &ofconn->connmgr->controllers) { if (other->role == OFPCR12_ROLE_MASTER) { other->role = OFPCR12_ROLE_SLAVE; + ofconn_send_role_status(other, OFPCR12_ROLE_SLAVE, OFPCRR_MASTER_REQUEST); } } } @@ -1301,7 +1315,10 @@ ofconn_run(struct ofconn *ofconn, size_t i; for (i = 0; i < N_SCHEDULERS; i++) { - pinsched_run(ofconn->schedulers[i], do_send_packet_in, ofconn); + struct list txq; + + pinsched_run(ofconn->schedulers[i], &txq); + do_send_packet_ins(ofconn, &txq); } rconn_run(ofconn->rconn); @@ -1493,9 +1510,9 @@ wire_reason(struct ofconn *ofconn, const struct ofproto_packet_in *pin) { if (pin->generated_by_table_miss && pin->up.reason == OFPR_ACTION) { enum ofputil_protocol protocol = ofconn_get_protocol(ofconn); - enum ofp_version version = ofputil_protocol_to_ofp_version(protocol); - if (version >= OFP13_VERSION) { + if (protocol != OFPUTIL_P_NONE + && ofputil_protocol_to_ofp_version(protocol) >= OFP13_VERSION) { return OFPR_NO_MATCH; } } @@ -1522,14 +1539,22 @@ connmgr_send_packet_in(struct connmgr *mgr, } } -/* pinsched callback for sending 'ofp_packet_in' on 'ofconn'. */ static void -do_send_packet_in(struct ofpbuf *ofp_packet_in, void *ofconn_) +do_send_packet_ins(struct ofconn *ofconn, struct list *txq) { - struct ofconn *ofconn = ofconn_; + struct ofpbuf *pin, *next_pin; - rconn_send_with_limit(ofconn->rconn, ofp_packet_in, - ofconn->packet_in_counter, 100); + LIST_FOR_EACH_SAFE (pin, next_pin, list_node, txq) { + list_remove(&pin->list_node); + + if (rconn_send_with_limit(ofconn->rconn, pin, + ofconn->packet_in_counter, 100) == EAGAIN) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); + + VLOG_INFO_RL(&rl, "%s: dropping packet-in due to queue overflow", + rconn_get_name(ofconn->rconn)); + } + } } /* Takes 'pin', composes an OpenFlow packet-in message from it, and passes it @@ -1540,6 +1565,7 @@ schedule_packet_in(struct ofconn *ofconn, struct ofproto_packet_in pin, { struct connmgr *mgr = ofconn->connmgr; uint16_t controller_max_len; + struct list txq; pin.up.total_len = pin.up.packet_len; @@ -1573,15 +1599,14 @@ schedule_packet_in(struct ofconn *ofconn, struct ofproto_packet_in pin, pin.up.packet_len = controller_max_len; } - /* Make OFPT_PACKET_IN and hand over to packet scheduler. It might - * immediately call into do_send_packet_in() or it might buffer it for a - * while (until a later call to pinsched_run()). */ + /* Make OFPT_PACKET_IN and hand over to packet scheduler. */ pinsched_send(ofconn->schedulers[pin.up.reason == OFPR_NO_MATCH ? 0 : 1], pin.up.fmd.in_port, ofputil_encode_packet_in(&pin.up, ofconn_get_protocol(ofconn), ofconn->packet_in_format), - do_send_packet_in, ofconn); + &txq); + do_send_packet_ins(ofconn, &txq); } /* Fail-open settings. */ @@ -1943,7 +1968,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule, default: case NXFME_ABBREV: - NOT_REACHED(); + OVS_NOT_REACHED(); } LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {