X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=ofproto%2Fconnmgr.c;h=4d9e7582513c16cfc94d8c461a4fccbcaa02b65c;hb=3a225db7079158d1c46e56dced7ac3103a8864e2;hp=166ef8c3f3cd2093142d70c45222f647f97bad9e;hpb=19a87e3637f8c278e1bc16bb9a7ab32af0a21d6b;p=openvswitch diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index 166ef8c3..4d9e7582 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -319,7 +319,7 @@ static struct ofconn *find_controller_by_target(struct connmgr *, 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. * @@ -390,6 +390,7 @@ connmgr_set_controllers(struct connmgr *mgr, 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; @@ -451,6 +452,9 @@ connmgr_set_controllers(struct connmgr *mgr, 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 @@ -470,22 +474,29 @@ connmgr_reconnect(const struct connmgr *mgr) * 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 @@ -583,10 +594,11 @@ update_fail_open(struct connmgr *mgr) 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; @@ -595,10 +607,9 @@ set_pvconns(struct pvconn ***pvconnsp, size_t *n_pvconnsp, } 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; @@ -918,9 +929,7 @@ static void schedule_packet_in(struct ofconn *, const struct dpif_upcall *, 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) @@ -942,7 +951,6 @@ connmgr_send_port_status(struct connmgr *mgr, const struct ofp_phy_port *opp, 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); } } @@ -1074,8 +1082,13 @@ connmgr_get_fail_mode(const struct connmgr *mgr) 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); + } + } } /* Fail-open implementation. */ @@ -1164,7 +1177,7 @@ connmgr_broadcast(struct connmgr *mgr, struct ofpbuf *packet) } } if (prev) { - ofconn_send_reply(ofconn, packet); + ofconn_send_reply(prev, packet); } else { ofpbuf_delete(packet); } @@ -1258,6 +1271,23 @@ connmgr_flushed(struct connmgr *mgr) 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); + } } /* Creates a new ofservice for 'target' in 'mgr'. Returns 0 if successful,