/*
- * 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.
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 {
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 *);
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
/* 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++) {
static void
update_fail_open(struct connmgr *mgr)
+ OVS_EXCLUDED(ofproto_mutex)
{
if (connmgr_has_controllers(mgr)
&& mgr->fail_mode == OFPROTO_FAIL_STANDALONE) {
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);
}
}
}
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);
{
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;
}
}
}
}
-/* 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
{
struct connmgr *mgr = ofconn->connmgr;
uint16_t controller_max_len;
+ struct list txq;
pin.up.total_len = pin.up.packet_len;
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);
}
\f
/* Fail-open settings. */
default:
case NXFME_ABBREV:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {