X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=cbd8928158a96392b3292f57d7a5335525a6740b;hb=0ff2282245a87f253843bf357988d7230139888f;hp=4d4c23201b42e4904b6fe3ca333c3bda22b422e7;hpb=073e2a6f2383cf7c17f78b8fa29e6e5293f60ba0;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 4d4c2320..cbd89281 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -135,8 +135,8 @@ static void ofproto_rule_send_removed(struct rule *, uint8_t reason); static void ofopgroup_destroy(struct ofopgroup *); -static int add_flow(struct ofproto *, struct ofconn *, struct flow_mod *, - const struct ofp_header *); +static int add_flow(struct ofproto *, struct ofconn *, + struct ofputil_flow_mod *, const struct ofp_header *); /* This return value tells handle_openflow() that processing of the current * OpenFlow message must be postponed until some ongoing operations have @@ -289,10 +289,10 @@ ofproto_create(const char *datapath_name, const char *datapath_type, struct ofproto **ofprotop) { const struct ofproto_class *class; + struct classifier *table; struct ofproto *ofproto; int n_tables; int error; - int i; *ofprotop = NULL; @@ -324,6 +324,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type, ofproto->datapath_id = 0; ofproto_set_flow_eviction_threshold(ofproto, OFPROTO_FLOW_EVICTON_THRESHOLD_DEFAULT); + ofproto->forward_bpdu = false; ofproto->fallback_dpid = pick_fallback_dpid(); ofproto->mfr_desc = xstrdup(DEFAULT_MFR_DESC); ofproto->hw_desc = xstrdup(DEFAULT_HW_DESC); @@ -350,8 +351,8 @@ ofproto_create(const char *datapath_name, const char *datapath_type, assert(n_tables >= 1 && n_tables <= 255); ofproto->n_tables = n_tables; ofproto->tables = xmalloc(n_tables * sizeof *ofproto->tables); - for (i = 0; i < n_tables; i++) { - classifier_init(&ofproto->tables[i]); + OFPROTO_FOR_EACH_TABLE (table, ofproto) { + classifier_init(table); } ofproto->datapath_id = pick_datapath_id(ofproto); @@ -429,6 +430,21 @@ ofproto_set_flow_eviction_threshold(struct ofproto *ofproto, unsigned threshold) } } +/* If forward_bpdu is true, the NORMAL action will forward frames with + * reserved (e.g. STP) destination Ethernet addresses. if forward_bpdu is false, + * the NORMAL action will drop these frames. */ +void +ofproto_set_forward_bpdu(struct ofproto *ofproto, bool forward_bpdu) +{ + bool old_val = ofproto->forward_bpdu; + ofproto->forward_bpdu = forward_bpdu; + if (old_val != ofproto->forward_bpdu) { + if (ofproto->ofproto_class->forward_bpdu_changed) { + ofproto->ofproto_class->forward_bpdu_changed(ofproto); + } + } +} + void ofproto_set_desc(struct ofproto *p, const char *mfr_desc, const char *hw_desc, @@ -675,8 +691,7 @@ ofproto_flush__(struct ofproto *ofproto) } group = ofopgroup_create(ofproto); - for (table = ofproto->tables; table < &ofproto->tables[ofproto->n_tables]; - table++) { + OFPROTO_FOR_EACH_TABLE (table, ofproto) { struct rule *rule, *next_rule; struct cls_cursor cursor; @@ -695,7 +710,7 @@ ofproto_flush__(struct ofproto *ofproto) static void ofproto_destroy__(struct ofproto *ofproto) { - size_t i; + struct classifier *table; assert(list_is_empty(&ofproto->pending)); @@ -712,9 +727,9 @@ ofproto_destroy__(struct ofproto *ofproto) hmap_destroy(&ofproto->ports); shash_destroy(&ofproto->port_by_name); - for (i = 0; i < ofproto->n_tables; i++) { - assert(classifier_is_empty(&ofproto->tables[i])); - classifier_destroy(&ofproto->tables[i]); + OFPROTO_FOR_EACH_TABLE (table, ofproto) { + assert(classifier_is_empty(table)); + classifier_destroy(table); } free(ofproto->tables); @@ -1033,7 +1048,7 @@ ofproto_add_flow(struct ofproto *ofproto, const struct cls_rule *cls_rule, &ofproto->tables[0], cls_rule)); if (!rule || !ofputil_actions_equal(rule->actions, rule->n_actions, actions, n_actions)) { - struct flow_mod fm; + struct ofputil_flow_mod fm; memset(&fm, 0, sizeof fm); fm.cr = *cls_rule; @@ -1884,7 +1899,7 @@ handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_stats_msg *osm) { struct ofproto *ofproto = ofconn_get_ofproto(ofconn); - struct flow_stats_request fsr; + struct ofputil_flow_stats_request fsr; struct list replies; struct list rules; struct rule *rule; @@ -1956,7 +1971,7 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results) { struct classifier *cls; - for (cls = &p->tables[0]; cls < &p->tables[p->n_tables]; cls++) { + OFPROTO_FOR_EACH_TABLE (cls, p) { struct cls_cursor cursor; struct rule *rule; @@ -1988,12 +2003,31 @@ ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port) : -1); } +/* Gets the MPIDs of the remote maintenance points broadcasting to 'ofp_port' + * within 'ofproto'. Populates 'rmps' with an array of MPIDs owned by + * 'ofproto', and 'n_rmps' with the number of MPIDs in 'rmps'. Returns a + * number less than 0 if CFM is not enabled on 'ofp_port'. */ +int +ofproto_port_get_cfm_remote_mpids(const struct ofproto *ofproto, + uint16_t ofp_port, const uint64_t **rmps, + size_t *n_rmps) +{ + struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); + + *rmps = NULL; + *n_rmps = 0; + return (ofport && ofproto->ofproto_class->get_cfm_remote_mpids + ? ofproto->ofproto_class->get_cfm_remote_mpids(ofport, rmps, + n_rmps) + : -1); +} + static int handle_aggregate_stats_request(struct ofconn *ofconn, const struct ofp_stats_msg *osm) { struct ofproto *ofproto = ofconn_get_ofproto(ofconn); - struct flow_stats_request request; + struct ofputil_flow_stats_request request; struct ofputil_aggregate_stats stats; bool unknown_packets, unknown_bytes; struct ofpbuf *reply; @@ -2159,8 +2193,8 @@ is_flow_deletion_pending(const struct ofproto *ofproto, * 'ofconn' is used to retrieve the packet buffer specified in ofm->buffer_id, * if any. */ static int -add_flow(struct ofproto *ofproto, struct ofconn *ofconn, struct flow_mod *fm, - const struct ofp_header *request) +add_flow(struct ofproto *ofproto, struct ofconn *ofconn, + struct ofputil_flow_mod *fm, const struct ofp_header *request) { struct classifier *table; struct ofopgroup *group; @@ -2182,7 +2216,7 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, struct flow_mod *fm, /* Pick table. */ if (fm->table_id == 0xff) { uint8_t table_id; - if (ofproto->n_tables > 1) { + if (ofproto->ofproto_class->rule_choose_table) { error = ofproto->ofproto_class->rule_choose_table(ofproto, &fm->cr, &table_id); if (error) { @@ -2263,7 +2297,7 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, struct flow_mod *fm, * * Returns 0 on success, otherwise an OpenFlow error code. */ static int -modify_flows__(struct ofconn *ofconn, const struct flow_mod *fm, +modify_flows__(struct ofconn *ofconn, const struct ofputil_flow_mod *fm, const struct ofp_header *request, struct list *rules) { struct ofopgroup *group; @@ -2293,7 +2327,7 @@ modify_flows__(struct ofconn *ofconn, const struct flow_mod *fm, * 'ofconn' is used to retrieve the packet buffer specified in fm->buffer_id, * if any. */ static int -modify_flows_loose(struct ofconn *ofconn, struct flow_mod *fm, +modify_flows_loose(struct ofconn *ofconn, struct ofputil_flow_mod *fm, const struct ofp_header *request) { struct ofproto *p = ofconn_get_ofproto(ofconn); @@ -2312,7 +2346,7 @@ modify_flows_loose(struct ofconn *ofconn, struct flow_mod *fm, * 'ofconn' is used to retrieve the packet buffer specified in fm->buffer_id, * if any. */ static int -modify_flow_strict(struct ofconn *ofconn, struct flow_mod *fm, +modify_flow_strict(struct ofconn *ofconn, struct ofputil_flow_mod *fm, const struct ofp_header *request) { struct ofproto *p = ofconn_get_ofproto(ofconn); @@ -2355,7 +2389,7 @@ delete_flows__(struct ofconn *ofconn, const struct ofp_header *request, /* Implements OFPFC_DELETE. */ static int -delete_flows_loose(struct ofconn *ofconn, const struct flow_mod *fm, +delete_flows_loose(struct ofconn *ofconn, const struct ofputil_flow_mod *fm, const struct ofp_header *request) { struct ofproto *p = ofconn_get_ofproto(ofconn); @@ -2371,7 +2405,7 @@ delete_flows_loose(struct ofconn *ofconn, const struct flow_mod *fm, /* Implements OFPFC_DELETE_STRICT. */ static int -delete_flow_strict(struct ofconn *ofconn, struct flow_mod *fm, +delete_flow_strict(struct ofconn *ofconn, struct ofputil_flow_mod *fm, const struct ofp_header *request) { struct ofproto *p = ofconn_get_ofproto(ofconn); @@ -2433,7 +2467,7 @@ static int handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) { struct ofproto *ofproto = ofconn_get_ofproto(ofconn); - struct flow_mod fm; + struct ofputil_flow_mod fm; int error; error = reject_slave_controller(ofconn, "flow_mod"); @@ -2813,8 +2847,29 @@ ofoperation_destroy(struct ofoperation *op) * indicate success or an OpenFlow error code (constructed with * e.g. ofp_mkerr()). * - * If 'op' is a "delete flow" operation, 'error' must be 0. That is, flow - * deletions are not allowed to fail. + * If 'error' is 0, indicating success, the operation will be committed + * permanently to the flow table. There is one interesting subcase: + * + * - If 'op' is an "add flow" operation that is replacing an existing rule in + * the flow table (the "victim" rule) by a new one, then the caller must + * have uninitialized any derived state in the victim rule, as in step 5 in + * the "Life Cycle" in ofproto/ofproto-provider.h. ofoperation_complete() + * performs steps 6 and 7 for the victim rule, most notably by calling its + * ->rule_dealloc() function. + * + * If 'error' is nonzero, then generally the operation will be rolled back: + * + * - If 'op' is an "add flow" operation, ofproto removes the new rule or + * restores the original rule. The caller must have uninitialized any + * derived state in the new rule, as in step 5 of in the "Life Cycle" in + * ofproto/ofproto-provider.h. ofoperation_complete() performs steps 6 and + * and 7 for the new rule, calling its ->rule_dealloc() function. + * + * - If 'op' is a "modify flow" operation, ofproto restores the original + * actions. + * + * - 'op' must not be a "delete flow" operation. Removing a rule is not + * allowed to fail. It must always succeed. * * Please see the large comment in ofproto/ofproto-provider.h titled * "Asynchronous Operation Support" for more information. */