#include "pinsched.h"
#include "poll-loop.h"
#include "pktbuf.h"
+#include "private.h"
#include "rconn.h"
#include "shash.h"
#include "timeval.h"
const char *target);
static void update_fail_open(struct connmgr *);
static int set_pvconns(struct pvconn ***pvconnsp, size_t *n_pvconnsp,
- const struct svec *);
+ const struct sset *);
/* Returns true if 'mgr' has any configured primary controllers.
*
const struct ofproto_controller *controllers,
size_t n_controllers)
{
+ bool had_controllers = connmgr_has_controllers(mgr);
struct shash new_controllers;
struct ofconn *ofconn, *next_ofconn;
struct ofservice *ofservice, *next_ofservice;
update_in_band_remotes(mgr);
update_fail_open(mgr);
+ if (had_controllers != connmgr_has_controllers(mgr)) {
+ ofproto_flush_flows(mgr->ofproto);
+ }
}
/* Drops the connections between 'mgr' and all of its primary and secondary
* A "snoop" is a pvconn to which every OpenFlow message to or from the most
* important controller on 'mgr' is mirrored. */
int
-connmgr_set_snoops(struct connmgr *mgr, const struct svec *snoops)
+connmgr_set_snoops(struct connmgr *mgr, const struct sset *snoops)
{
return set_pvconns(&mgr->snoops, &mgr->n_snoops, snoops);
}
/* Adds each of the snoops currently configured on 'mgr' to 'snoops'. */
void
-connmgr_get_snoops(const struct connmgr *mgr, struct svec *snoops)
+connmgr_get_snoops(const struct connmgr *mgr, struct sset *snoops)
{
size_t i;
for (i = 0; i < mgr->n_snoops; i++) {
- svec_add(snoops, pvconn_get_name(mgr->snoops[i]));
+ sset_add(snoops, pvconn_get_name(mgr->snoops[i]));
}
}
+/* Returns true if 'mgr' has at least one snoop, false if it has none. */
+bool
+connmgr_has_snoops(const struct connmgr *mgr)
+{
+ return mgr->n_snoops > 0;
+}
+
/* Creates a new controller for 'target' in 'mgr'. update_controller() needs
* to be called later to finish the new ofconn's configuration. */
static void
static int
set_pvconns(struct pvconn ***pvconnsp, size_t *n_pvconnsp,
- const struct svec *svec)
+ const struct sset *sset)
{
struct pvconn **pvconns = *pvconnsp;
size_t n_pvconns = *n_pvconnsp;
+ const char *name;
int retval = 0;
size_t i;
}
free(pvconns);
- pvconns = xmalloc(svec->n * sizeof *pvconns);
+ pvconns = xmalloc(sset_count(sset) * sizeof *pvconns);
n_pvconns = 0;
- for (i = 0; i < svec->n; i++) {
- const char *name = svec->names[i];
+ SSET_FOR_EACH (name, sset) {
struct pvconn *pvconn;
int error;
const struct flow *, struct ofpbuf *rw_packet);
/* Sends an OFPT_PORT_STATUS message with 'opp' and 'reason' to appropriate
- * controllers managed by 'mgr'.
- *
- * 'opp' is in *HOST* byte order. */
+ * controllers managed by 'mgr'. */
void
connmgr_send_port_status(struct connmgr *mgr, const struct ofp_phy_port *opp,
uint8_t reason)
ops = make_openflow_xid(sizeof *ops, OFPT_PORT_STATUS, 0, &b);
ops->reason = reason;
ops->desc = *opp;
- hton_ofp_phy_port(&ops->desc);
ofconn_send(ofconn, b, NULL);
}
}
void
connmgr_set_fail_mode(struct connmgr *mgr, enum ofproto_fail_mode fail_mode)
{
- mgr->fail_mode = fail_mode;
- update_fail_open(mgr);
+ if (mgr->fail_mode != fail_mode) {
+ mgr->fail_mode = fail_mode;
+ update_fail_open(mgr);
+ if (!connmgr_has_controllers(mgr)) {
+ ofproto_flush_flows(mgr->ofproto);
+ }
+ }
}
\f
/* Fail-open implementation. */
}
}
if (prev) {
- ofconn_send_reply(ofconn, packet);
+ ofconn_send_reply(prev, packet);
} else {
ofpbuf_delete(packet);
}
if (mgr->fail_open) {
fail_open_flushed(mgr->fail_open);
}
+
+ /* If there are no controllers and we're in standalone mode, set up a flow
+ * that matches every packet and directs them to OFPP_NORMAL (which goes to
+ * us). Otherwise, the switch is in secure mode and we won't pass any
+ * traffic until a controller has been defined and it tells us to do so. */
+ if (!connmgr_has_controllers(mgr)
+ && mgr->fail_mode == OFPROTO_FAIL_STANDALONE) {
+ union ofp_action action;
+ struct cls_rule rule;
+
+ memset(&action, 0, sizeof action);
+ action.type = htons(OFPAT_OUTPUT);
+ action.output.len = htons(sizeof action);
+ action.output.port = htons(OFPP_NORMAL);
+ cls_rule_init_catchall(&rule, 0);
+ ofproto_add_flow(mgr->ofproto, &rule, &action, 1);
+ }
}
\f
/* Creates a new ofservice for 'target' in 'mgr'. Returns 0 if successful,