X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=32ce4f241d811aeca4b0f296dbc586528b842652;hb=27d34fce499f0f6b904fd27e84e81ecd44d67cfd;hp=b35139cbafdde42cea58ca6369af111311349805;hpb=7a0efeb5ad32fc685640b3815da4e20a7f11e3c5;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index b35139cb..32ce4f24 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -161,8 +161,7 @@ static void rule_install(struct ofproto *, struct rule *, struct rule *displaced_rule); static void rule_uninstall(struct ofproto *, struct rule *); static void rule_post_uninstall(struct ofproto *, struct rule *); -static void send_flow_removed(struct ofproto *p, struct rule *rule, - long long int now, uint8_t reason); +static void send_flow_removed(struct ofproto *, struct rule *, uint8_t reason); /* ofproto supports two kinds of OpenFlow connections: * @@ -210,6 +209,7 @@ struct ofconn { struct list node; /* In struct ofproto's "all_conns" list. */ struct rconn *rconn; /* OpenFlow connection. */ enum ofconn_type type; /* Type. */ + int flow_format; /* One of NXFF_*. */ /* OFPT_PACKET_IN related data. */ struct rconn_packet_counter *packet_in_counter; /* # queued on 'rconn'. */ @@ -244,7 +244,7 @@ BUILD_ASSERT_DECL(OFPR_ACTION == _ODPL_ACTION_NR); static struct ofconn *ofconn_create(struct ofproto *, struct rconn *, enum ofconn_type); static void ofconn_destroy(struct ofconn *); -static void ofconn_run(struct ofconn *, struct ofproto *); +static void ofconn_run(struct ofconn *); static void ofconn_wait(struct ofconn *); static bool ofconn_receives_async_msgs(const struct ofconn *); static char *ofconn_make_name(const struct ofproto *, const char *target); @@ -290,7 +290,6 @@ struct ofproto { bool need_revalidate; long long int next_expiration; struct tag_set revalidate_set; - bool tun_id_from_cookie; /* OpenFlow connections. */ struct hmap controllers; /* Controller "struct ofconn"s. */ @@ -326,8 +325,7 @@ static void revalidate_cb(struct cls_rule *rule_, void *p_); static void handle_odp_msg(struct ofproto *, struct ofpbuf *); -static void handle_openflow(struct ofconn *, struct ofproto *, - struct ofpbuf *); +static void handle_openflow(struct ofconn *, struct ofpbuf *); static struct ofport *get_port(const struct ofproto *, uint16_t odp_port); static void update_port(struct ofproto *, const char *devname); @@ -1093,7 +1091,7 @@ ofproto_run1(struct ofproto *p) } LIST_FOR_EACH_SAFE (ofconn, next_ofconn, node, &p->all_conns) { - ofconn_run(ofconn, p); + ofconn_run(ofconn); } /* Fail-open maintenance. Do this after processing the ofconns since @@ -1634,6 +1632,7 @@ ofconn_create(struct ofproto *p, struct rconn *rconn, enum ofconn_type type) list_push_back(&p->all_conns, &ofconn->node); ofconn->rconn = rconn; ofconn->type = type; + ofconn->flow_format = NXFF_OPENFLOW10; ofconn->role = NX_ROLE_OTHER; ofconn->packet_in_counter = rconn_packet_counter_create (); ofconn->pktbuf = NULL; @@ -1660,8 +1659,9 @@ ofconn_destroy(struct ofconn *ofconn) } static void -ofconn_run(struct ofconn *ofconn, struct ofproto *p) +ofconn_run(struct ofconn *ofconn) { + struct ofproto *p = ofconn->ofproto; int iteration; size_t i; @@ -1698,7 +1698,7 @@ ofconn_run(struct ofconn *ofconn, struct ofproto *p) if (p->fail_open) { fail_open_maybe_recover(p->fail_open); } - handle_openflow(ofconn, p, of_msg); + handle_openflow(ofconn, of_msg); ofpbuf_delete(of_msg); } } @@ -2329,15 +2329,14 @@ handle_echo_request(struct ofconn *ofconn, struct ofp_header *oh) } static int -handle_features_request(struct ofproto *p, struct ofconn *ofconn, - struct ofp_header *oh) +handle_features_request(struct ofconn *ofconn, struct ofp_header *oh) { struct ofp_switch_features *osf; struct ofpbuf *buf; struct ofport *port; osf = make_openflow_xid(sizeof *osf, OFPT_FEATURES_REPLY, oh->xid, &buf); - osf->datapath_id = htonll(p->datapath_id); + osf->datapath_id = htonll(ofconn->ofproto->datapath_id); osf->n_buffers = htonl(pktbuf_capacity()); osf->n_tables = 2; osf->capabilities = htonl(OFPC_FLOW_STATS | OFPC_TABLE_STATS | @@ -2355,7 +2354,7 @@ handle_features_request(struct ofproto *p, struct ofconn *ofconn, (1u << OFPAT_SET_TP_DST) | (1u << OFPAT_ENQUEUE)); - HMAP_FOR_EACH (port, hmap_node, &p->ports) { + HMAP_FOR_EACH (port, hmap_node, &ofconn->ofproto->ports) { hton_ofp_phy_port(ofpbuf_put(buf, &port->opp, sizeof port->opp)); } @@ -2364,8 +2363,7 @@ handle_features_request(struct ofproto *p, struct ofconn *ofconn, } static int -handle_get_config_request(struct ofproto *p, struct ofconn *ofconn, - struct ofp_header *oh) +handle_get_config_request(struct ofconn *ofconn, struct ofp_header *oh) { struct ofpbuf *buf; struct ofp_switch_config *osc; @@ -2373,7 +2371,7 @@ handle_get_config_request(struct ofproto *p, struct ofconn *ofconn, bool drop_frags; /* Figure out flags. */ - dpif_get_drop_frags(p->dpif, &drop_frags); + dpif_get_drop_frags(ofconn->ofproto->dpif, &drop_frags); flags = drop_frags ? OFPC_FRAG_DROP : OFPC_FRAG_NORMAL; /* Send reply. */ @@ -2386,8 +2384,7 @@ handle_get_config_request(struct ofproto *p, struct ofconn *ofconn, } static int -handle_set_config(struct ofproto *p, struct ofconn *ofconn, - struct ofp_switch_config *osc) +handle_set_config(struct ofconn *ofconn, struct ofp_switch_config *osc) { uint16_t flags; int error; @@ -2401,10 +2398,10 @@ handle_set_config(struct ofproto *p, struct ofconn *ofconn, if (ofconn->type == OFCONN_PRIMARY && ofconn->role != NX_ROLE_SLAVE) { switch (flags & OFPC_FRAG_MASK) { case OFPC_FRAG_NORMAL: - dpif_set_drop_frags(p->dpif, false); + dpif_set_drop_frags(ofconn->ofproto->dpif, false); break; case OFPC_FRAG_DROP: - dpif_set_drop_frags(p->dpif, true); + dpif_set_drop_frags(ofconn->ofproto->dpif, true); break; default: VLOG_WARN_RL(&rl, "requested bad fragment mode (flags=%"PRIx16")", @@ -2868,18 +2865,14 @@ xlate_actions(const union ofp_action *in, size_t n_in, * error message code (composed with ofp_mkerr()) for the caller to propagate * upward. Otherwise, returns 0. * - * 'oh' is used to make log messages more informative. */ + * The log message mentions 'msg_type'. */ static int -reject_slave_controller(struct ofconn *ofconn, const struct ofp_header *oh) +reject_slave_controller(struct ofconn *ofconn, const const char *msg_type) { if (ofconn->type == OFCONN_PRIMARY && ofconn->role == NX_ROLE_SLAVE) { static struct vlog_rate_limit perm_rl = VLOG_RATE_LIMIT_INIT(1, 5); - char *type_name; - - type_name = ofp_message_type_to_string(oh->type); VLOG_WARN_RL(&perm_rl, "rejecting %s message from slave controller", - type_name); - free(type_name); + msg_type); return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM); } else { @@ -2888,9 +2881,9 @@ reject_slave_controller(struct ofconn *ofconn, const struct ofp_header *oh) } static int -handle_packet_out(struct ofproto *p, struct ofconn *ofconn, - struct ofp_header *oh) +handle_packet_out(struct ofconn *ofconn, struct ofp_header *oh) { + struct ofproto *p = ofconn->ofproto; struct ofp_packet_out *opo; struct ofpbuf payload, *buffer; struct odp_actions actions; @@ -2899,7 +2892,7 @@ handle_packet_out(struct ofproto *p, struct ofconn *ofconn, uint16_t in_port; int error; - error = reject_slave_controller(ofconn, oh); + error = reject_slave_controller(ofconn, "OFPT_PACKET_OUT"); if (error) { return error; } @@ -2959,14 +2952,14 @@ update_port_config(struct ofproto *p, struct ofport *port, } static int -handle_port_mod(struct ofproto *p, struct ofconn *ofconn, - struct ofp_header *oh) +handle_port_mod(struct ofconn *ofconn, struct ofp_header *oh) { + struct ofproto *p = ofconn->ofproto; const struct ofp_port_mod *opm; struct ofport *port; int error; - error = reject_slave_controller(ofconn, oh); + error = reject_slave_controller(ofconn, "OFPT_PORT_MOD"); if (error) { return error; } @@ -3024,9 +3017,10 @@ append_stats_reply(size_t nbytes, struct ofconn *ofconn, struct ofpbuf **msgp) } static int -handle_desc_stats_request(struct ofproto *p, struct ofconn *ofconn, - struct ofp_stats_request *request) +handle_desc_stats_request(struct ofconn *ofconn, + struct ofp_stats_request *request) { + struct ofproto *p = ofconn->ofproto; struct ofp_desc_stats *ods; struct ofpbuf *msg; @@ -3044,9 +3038,10 @@ handle_desc_stats_request(struct ofproto *p, struct ofconn *ofconn, } static int -handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn, +handle_table_stats_request(struct ofconn *ofconn, struct ofp_stats_request *request) { + struct ofproto *p = ofconn->ofproto; struct ofp_table_stats *ots; struct ofpbuf *msg; struct rule *rule; @@ -3066,8 +3061,8 @@ handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn, ots = append_stats_reply(sizeof *ots, ofconn, &msg); memset(ots, 0, sizeof *ots); strcpy(ots->name, "classifier"); - ots->wildcards = p->tun_id_from_cookie ? htonl(OVSFW_ALL) - : htonl(OFPFW_ALL); + ots->wildcards = (ofconn->flow_format == NXFF_OPENFLOW10 + ? htonl(OFPFW_ALL) : htonl(OVSFW_ALL)); ots->max_entries = htonl(1024 * 1024); /* An arbitrary big number. */ ots->active_count = htonl(n_rules); ots->lookup_count = htonll(0); /* XXX */ @@ -3107,10 +3102,10 @@ append_port_stat(struct ofport *port, struct ofconn *ofconn, } static int -handle_port_stats_request(struct ofproto *p, struct ofconn *ofconn, - struct ofp_stats_request *osr, +handle_port_stats_request(struct ofconn *ofconn, struct ofp_stats_request *osr, size_t arg_size) { + struct ofproto *p = ofconn->ofproto; struct ofp_port_stats_request *psr; struct ofp_port_stats *ops; struct ofpbuf *msg; @@ -3138,7 +3133,6 @@ handle_port_stats_request(struct ofproto *p, struct ofconn *ofconn, } struct flow_stats_cbdata { - struct ofproto *ofproto; struct ofconn *ofconn; ovs_be16 out_port; struct ofpbuf *msg; @@ -3198,6 +3192,14 @@ query_stats(struct ofproto *p, struct rule *rule, *byte_countp = byte_count; } +static void +calc_flow_duration(long long int start, ovs_be32 *sec, ovs_be32 *nsec) +{ + long long int msecs = time_msec() - start; + *sec = htonl(msecs / 1000); + *nsec = htonl((msecs % 1000) * (1000 * 1000)); +} + static void flow_stats_cb(struct cls_rule *rule_, void *cbdata_) { @@ -3206,9 +3208,6 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_) struct ofp_flow_stats *ofs; uint64_t packet_count, byte_count; size_t act_len, len; - long long int tdiff = time_msec() - rule->created; - uint32_t sec = tdiff / 1000; - uint32_t msec = tdiff - (sec * 1000); if (rule_is_hidden(rule) || !rule_has_out_port(rule, cbdata->out_port)) { return; @@ -3217,16 +3216,15 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_) act_len = sizeof *rule->actions * rule->n_actions; len = offsetof(struct ofp_flow_stats, actions) + act_len; - query_stats(cbdata->ofproto, rule, &packet_count, &byte_count); + query_stats(cbdata->ofconn->ofproto, rule, &packet_count, &byte_count); ofs = append_stats_reply(len, cbdata->ofconn, &cbdata->msg); ofs->length = htons(len); ofs->table_id = 0; ofs->pad = 0; flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, - cbdata->ofproto->tun_id_from_cookie, &ofs->match); - ofs->duration_sec = htonl(sec); - ofs->duration_nsec = htonl(msec * 1000000); + cbdata->ofconn->flow_format, &ofs->match); + calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec); ofs->cookie = rule->flow_cookie; ofs->priority = htons(rule->cr.priority); ofs->idle_timeout = htons(rule->idle_timeout); @@ -3246,9 +3244,8 @@ table_id_to_include(uint8_t table_id) } static int -handle_flow_stats_request(struct ofproto *p, struct ofconn *ofconn, - const struct ofp_stats_request *osr, - size_t arg_size) +handle_flow_stats_request(struct ofconn *ofconn, + const struct ofp_stats_request *osr, size_t arg_size) { struct ofp_flow_stats_request *fsr; struct flow_stats_cbdata cbdata; @@ -3260,12 +3257,11 @@ handle_flow_stats_request(struct ofproto *p, struct ofconn *ofconn, fsr = (struct ofp_flow_stats_request *) osr->body; COVERAGE_INC(ofproto_flows_req); - cbdata.ofproto = p; cbdata.ofconn = ofconn; cbdata.out_port = fsr->out_port; cbdata.msg = start_stats_reply(osr, 1024); - cls_rule_from_match(&fsr->match, 0, false, 0, &target); - classifier_for_each_match(&p->cls, &target, + cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target); + classifier_for_each_match(&ofconn->ofproto->cls, &target, table_id_to_include(fsr->table_id), flow_stats_cb, &cbdata); queue_tx(cbdata.msg, ofconn, ofconn->reply_counter); @@ -3294,7 +3290,7 @@ flow_stats_ds_cb(struct cls_rule *rule_, void *cbdata_) query_stats(cbdata->ofproto, rule, &packet_count, &byte_count); flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, - cbdata->ofproto->tun_id_from_cookie, &match); + NXFF_OPENFLOW10, &match); ds_put_format(results, "duration=%llds, ", (time_msec() - rule->created) / 1000); @@ -3325,7 +3321,7 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results) cbdata.ofproto = p; cbdata.results = results; - cls_rule_from_match(&match, 0, false, 0, &target); + cls_rule_from_match(&match, 0, NXFF_OPENFLOW10, 0, &target); classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, flow_stats_ds_cb, &cbdata); } @@ -3356,38 +3352,50 @@ aggregate_stats_cb(struct cls_rule *rule_, void *cbdata_) cbdata->n_flows++; } +static void +query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target, + uint16_t out_port, uint8_t table_id, + struct ofp_aggregate_stats_reply *oasr) +{ + struct aggregate_stats_cbdata cbdata; + + COVERAGE_INC(ofproto_agg_request); + cbdata.ofproto = ofproto; + cbdata.out_port = out_port; + cbdata.packet_count = 0; + cbdata.byte_count = 0; + cbdata.n_flows = 0; + classifier_for_each_match(&ofproto->cls, target, + table_id_to_include(table_id), + aggregate_stats_cb, &cbdata); + + oasr->flow_count = htonl(cbdata.n_flows); + oasr->packet_count = htonll(cbdata.packet_count); + oasr->byte_count = htonll(cbdata.byte_count); + memset(oasr->pad, 0, sizeof oasr->pad); +} + static int -handle_aggregate_stats_request(struct ofproto *p, struct ofconn *ofconn, +handle_aggregate_stats_request(struct ofconn *ofconn, const struct ofp_stats_request *osr, size_t arg_size) { - struct ofp_aggregate_stats_request *asr; + struct ofp_aggregate_stats_request *request; struct ofp_aggregate_stats_reply *reply; - struct aggregate_stats_cbdata cbdata; struct cls_rule target; struct ofpbuf *msg; - if (arg_size != sizeof *asr) { + if (arg_size != sizeof *request) { return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } - asr = (struct ofp_aggregate_stats_request *) osr->body; + request = (struct ofp_aggregate_stats_request *) osr->body; - COVERAGE_INC(ofproto_agg_request); - cbdata.ofproto = p; - cbdata.out_port = asr->out_port; - cbdata.packet_count = 0; - cbdata.byte_count = 0; - cbdata.n_flows = 0; - cls_rule_from_match(&asr->match, 0, false, 0, &target); - classifier_for_each_match(&p->cls, &target, - table_id_to_include(asr->table_id), - aggregate_stats_cb, &cbdata); + cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0, &target); msg = start_stats_reply(osr, sizeof *reply); reply = append_stats_reply(sizeof *reply, ofconn, &msg); - reply->flow_count = htonl(cbdata.n_flows); - reply->packet_count = htonll(cbdata.packet_count); - reply->byte_count = htonll(cbdata.byte_count); + query_aggregate_stats(ofconn->ofproto, &target, request->out_port, + request->table_id, reply); queue_tx(msg, ofconn, ofconn->reply_counter); return 0; } @@ -3441,10 +3449,11 @@ handle_queue_stats_for_port(struct ofport *port, uint32_t queue_id, } static int -handle_queue_stats_request(struct ofproto *ofproto, struct ofconn *ofconn, +handle_queue_stats_request(struct ofconn *ofconn, const struct ofp_stats_request *osr, size_t arg_size) { + struct ofproto *ofproto = ofconn->ofproto; struct ofp_queue_stats_request *qsr; struct queue_stats_cbdata cbdata; struct ofport *port; @@ -3482,8 +3491,7 @@ handle_queue_stats_request(struct ofproto *ofproto, struct ofconn *ofconn, } static int -handle_stats_request(struct ofproto *p, struct ofconn *ofconn, - struct ofp_header *oh) +handle_stats_request(struct ofconn *ofconn, struct ofp_header *oh) { struct ofp_stats_request *osr; size_t arg_size; @@ -3498,22 +3506,22 @@ handle_stats_request(struct ofproto *p, struct ofconn *ofconn, switch (ntohs(osr->type)) { case OFPST_DESC: - return handle_desc_stats_request(p, ofconn, osr); + return handle_desc_stats_request(ofconn, osr); case OFPST_FLOW: - return handle_flow_stats_request(p, ofconn, osr, arg_size); + return handle_flow_stats_request(ofconn, osr, arg_size); case OFPST_AGGREGATE: - return handle_aggregate_stats_request(p, ofconn, osr, arg_size); + return handle_aggregate_stats_request(ofconn, osr, arg_size); case OFPST_TABLE: - return handle_table_stats_request(p, ofconn, osr); + return handle_table_stats_request(ofconn, osr); case OFPST_PORT: - return handle_port_stats_request(p, ofconn, osr, arg_size); + return handle_port_stats_request(ofconn, osr, arg_size); case OFPST_QUEUE: - return handle_queue_stats_request(p, ofconn, osr, arg_size); + return handle_queue_stats_request(ofconn, osr, arg_size); case OFPST_VENDOR: return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR); @@ -3559,15 +3567,16 @@ update_stats(struct ofproto *ofproto, struct rule *rule, * in which no matching flow already exists in the flow table. * * Adds the flow specified by 'ofm', which is followed by 'n_actions' - * ofp_actions, to 'p''s flow table. Returns 0 on success or an OpenFlow error - * code as encoded by ofp_mkerr() on failure. + * ofp_actions, to ofconn->ofproto's flow table. Returns 0 on success or an + * OpenFlow error code as encoded by ofp_mkerr() on failure. * * 'ofconn' is used to retrieve the packet buffer specified in ofm->buffer_id, * if any. */ static int -add_flow(struct ofproto *p, struct ofconn *ofconn, - const struct ofp_flow_mod *ofm, size_t n_actions) +add_flow(struct ofconn *ofconn, const struct ofp_flow_mod *ofm, + size_t n_actions) { + struct ofproto *p = ofconn->ofproto; struct ofpbuf *packet; struct rule *rule; uint16_t in_port; @@ -3577,7 +3586,7 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, struct cls_rule cr; cls_rule_from_match(&ofm->match, ntohs(ofm->priority), - p->tun_id_from_cookie, ofm->cookie, &cr); + ofconn->flow_format, ofm->cookie, &cr); if (classifier_rule_overlaps(&p->cls, &cr)) { return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP); } @@ -3588,7 +3597,7 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, ntohs(ofm->hard_timeout), ofm->cookie, ofm->flags & htons(OFPFF_SEND_FLOW_REM)); cls_rule_from_match(&ofm->match, ntohs(ofm->priority), - p->tun_id_from_cookie, ofm->cookie, &rule->cr); + ofconn->flow_format, ofm->cookie, &rule->cr); error = 0; if (ofm->buffer_id != htonl(UINT32_MAX)) { @@ -3604,17 +3613,18 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, } static struct rule * -find_flow_strict(struct ofproto *p, const struct ofp_flow_mod *ofm) +find_flow_strict(struct ofconn *ofconn, const struct ofp_flow_mod *ofm) { + struct ofproto *p = ofconn->ofproto; struct cls_rule target; cls_rule_from_match(&ofm->match, ntohs(ofm->priority), - p->tun_id_from_cookie, ofm->cookie, &target); + ofconn->flow_format, ofm->cookie, &target); return rule_from_cls_rule(classifier_find_rule_exactly(&p->cls, &target)); } static int -send_buffered_packet(struct ofproto *ofproto, struct ofconn *ofconn, +send_buffered_packet(struct ofconn *ofconn, struct rule *rule, const struct ofp_flow_mod *ofm) { struct ofpbuf *packet; @@ -3633,7 +3643,7 @@ send_buffered_packet(struct ofproto *ofproto, struct ofconn *ofconn, } flow_extract(packet, 0, in_port, &flow); - rule_execute(ofproto, rule, packet, &flow); + rule_execute(ofconn->ofproto, rule, packet, &flow); return 0; } @@ -3657,30 +3667,30 @@ static void modify_flows_cb(struct cls_rule *, void *cbdata_); * 'ofconn' is used to retrieve the packet buffer specified in ofm->buffer_id, * if any. */ static int -modify_flows_loose(struct ofproto *p, struct ofconn *ofconn, +modify_flows_loose(struct ofconn *ofconn, const struct ofp_flow_mod *ofm, size_t n_actions) { struct modify_flows_cbdata cbdata; struct cls_rule target; - cbdata.ofproto = p; + cbdata.ofproto = ofconn->ofproto; cbdata.ofm = ofm; cbdata.n_actions = n_actions; cbdata.match = NULL; - cls_rule_from_match(&ofm->match, 0, p->tun_id_from_cookie, ofm->cookie, - &target); + cls_rule_from_match(&ofm->match, 0, ofconn->flow_format, + ofm->cookie, &target); - classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, + classifier_for_each_match(&ofconn->ofproto->cls, &target, CLS_INC_ALL, modify_flows_cb, &cbdata); if (cbdata.match) { /* This credits the packet to whichever flow happened to happened to * match last. That's weird. Maybe we should do a lookup for the * flow that actually matches the packet? Who knows. */ - send_buffered_packet(p, ofconn, cbdata.match, ofm); + send_buffered_packet(ofconn, cbdata.match, ofm); return 0; } else { - return add_flow(p, ofconn, ofm, n_actions); + return add_flow(ofconn, ofm, n_actions); } } @@ -3690,15 +3700,15 @@ modify_flows_loose(struct ofproto *p, struct ofconn *ofconn, * 'ofconn' is used to retrieve the packet buffer specified in ofm->buffer_id, * if any. */ static int -modify_flow_strict(struct ofproto *p, struct ofconn *ofconn, - struct ofp_flow_mod *ofm, size_t n_actions) +modify_flow_strict(struct ofconn *ofconn, struct ofp_flow_mod *ofm, + size_t n_actions) { - struct rule *rule = find_flow_strict(p, ofm); + struct rule *rule = find_flow_strict(ofconn, ofm); if (rule && !rule_is_hidden(rule)) { - modify_flow(p, ofm, n_actions, rule); - return send_buffered_packet(p, ofconn, rule, ofm); + modify_flow(ofconn->ofproto, ofm, n_actions, rule); + return send_buffered_packet(ofconn, rule, ofm); } else { - return add_flow(p, ofconn, ofm, n_actions); + return add_flow(ofconn, ofm, n_actions); } } @@ -3762,28 +3772,28 @@ static void delete_flow(struct ofproto *, struct rule *, ovs_be16 out_port); /* Implements OFPFC_DELETE. */ static void -delete_flows_loose(struct ofproto *p, const struct ofp_flow_mod *ofm) +delete_flows_loose(struct ofconn *ofconn, const struct ofp_flow_mod *ofm) { struct delete_flows_cbdata cbdata; struct cls_rule target; - cbdata.ofproto = p; + cbdata.ofproto = ofconn->ofproto; cbdata.out_port = ofm->out_port; - cls_rule_from_match(&ofm->match, 0, p->tun_id_from_cookie, ofm->cookie, - &target); + cls_rule_from_match(&ofm->match, 0, ofconn->flow_format, + ofm->cookie, &target); - classifier_for_each_match(&p->cls, &target, CLS_INC_ALL, + classifier_for_each_match(&ofconn->ofproto->cls, &target, CLS_INC_ALL, delete_flows_cb, &cbdata); } /* Implements OFPFC_DELETE_STRICT. */ static void -delete_flow_strict(struct ofproto *p, struct ofp_flow_mod *ofm) +delete_flow_strict(struct ofconn *ofconn, struct ofp_flow_mod *ofm) { - struct rule *rule = find_flow_strict(p, ofm); + struct rule *rule = find_flow_strict(ofconn, ofm); if (rule) { - delete_flow(p, rule, ofm->out_port); + delete_flow(ofconn->ofproto, rule, ofm->out_port); } } @@ -3816,19 +3826,18 @@ delete_flow(struct ofproto *p, struct rule *rule, ovs_be16 out_port) return; } - send_flow_removed(p, rule, time_msec(), OFPRR_DELETE); + send_flow_removed(p, rule, OFPRR_DELETE); rule_remove(p, rule); } static int -handle_flow_mod(struct ofproto *p, struct ofconn *ofconn, - struct ofp_flow_mod *ofm) +handle_flow_mod(struct ofconn *ofconn, struct ofp_flow_mod *ofm) { struct ofp_match orig_match; size_t n_actions; int error; - error = reject_slave_controller(ofconn, &ofm->header); + error = reject_slave_controller(ofconn, "OFPT_FLOW_MOD"); if (error) { return error; } @@ -3870,27 +3879,27 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn, } error = validate_actions((const union ofp_action *) ofm->actions, - n_actions, p->max_ports); + n_actions, ofconn->ofproto->max_ports); if (error) { return error; } switch (ntohs(ofm->command)) { case OFPFC_ADD: - return add_flow(p, ofconn, ofm, n_actions); + return add_flow(ofconn, ofm, n_actions); case OFPFC_MODIFY: - return modify_flows_loose(p, ofconn, ofm, n_actions); + return modify_flows_loose(ofconn, ofm, n_actions); case OFPFC_MODIFY_STRICT: - return modify_flow_strict(p, ofconn, ofm, n_actions); + return modify_flow_strict(ofconn, ofm, n_actions); case OFPFC_DELETE: - delete_flows_loose(p, ofm); + delete_flows_loose(ofconn, ofm); return 0; case OFPFC_DELETE_STRICT: - delete_flow_strict(p, ofm); + delete_flow_strict(ofconn, ofm); return 0; default: @@ -3899,7 +3908,7 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn, } static int -handle_tun_id_from_cookie(struct ofproto *p, struct nxt_tun_id_cookie *msg) +handle_tun_id_from_cookie(struct ofconn *ofconn, struct nxt_tun_id_cookie *msg) { int error; @@ -3908,13 +3917,12 @@ handle_tun_id_from_cookie(struct ofproto *p, struct nxt_tun_id_cookie *msg) return error; } - p->tun_id_from_cookie = !!msg->set; + ofconn->flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10; return 0; } static int -handle_role_request(struct ofproto *ofproto, - struct ofconn *ofconn, struct nicira_header *msg) +handle_role_request(struct ofconn *ofconn, struct nicira_header *msg) { struct nx_role_request *nrr; struct nx_role_request *reply; @@ -3946,7 +3954,7 @@ handle_role_request(struct ofproto *ofproto, if (role == NX_ROLE_MASTER) { struct ofconn *other; - HMAP_FOR_EACH (other, hmap_node, &ofproto->controllers) { + HMAP_FOR_EACH (other, hmap_node, &ofconn->ofproto->controllers) { if (other->role == NX_ROLE_MASTER) { other->role = NX_ROLE_SLAVE; } @@ -3963,8 +3971,9 @@ handle_role_request(struct ofproto *ofproto, } static int -handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg) +handle_vendor(struct ofconn *ofconn, void *msg) { + struct ofproto *p = ofconn->ofproto; struct ofp_vendor_header *ovh = msg; struct nicira_header *nh; @@ -3991,10 +4000,10 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg) msg); case NXT_TUN_ID_FROM_COOKIE: - return handle_tun_id_from_cookie(p, msg); + return handle_tun_id_from_cookie(ofconn, msg); case NXT_ROLE_REQUEST: - return handle_role_request(p, ofconn, msg); + return handle_role_request(ofconn, msg); } return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); @@ -4014,8 +4023,7 @@ handle_barrier_request(struct ofconn *ofconn, struct ofp_header *oh) } static void -handle_openflow(struct ofconn *ofconn, struct ofproto *p, - struct ofpbuf *ofp_msg) +handle_openflow(struct ofconn *ofconn, struct ofpbuf *ofp_msg) { struct ofp_header *oh = ofp_msg->data; int error; @@ -4031,35 +4039,35 @@ handle_openflow(struct ofconn *ofconn, struct ofproto *p, break; case OFPT_FEATURES_REQUEST: - error = handle_features_request(p, ofconn, oh); + error = handle_features_request(ofconn, oh); break; case OFPT_GET_CONFIG_REQUEST: - error = handle_get_config_request(p, ofconn, oh); + error = handle_get_config_request(ofconn, oh); break; case OFPT_SET_CONFIG: - error = handle_set_config(p, ofconn, ofp_msg->data); + error = handle_set_config(ofconn, ofp_msg->data); break; case OFPT_PACKET_OUT: - error = handle_packet_out(p, ofconn, ofp_msg->data); + error = handle_packet_out(ofconn, ofp_msg->data); break; case OFPT_PORT_MOD: - error = handle_port_mod(p, ofconn, oh); + error = handle_port_mod(ofconn, oh); break; case OFPT_FLOW_MOD: - error = handle_flow_mod(p, ofconn, ofp_msg->data); + error = handle_flow_mod(ofconn, ofp_msg->data); break; case OFPT_STATS_REQUEST: - error = handle_stats_request(p, ofconn, oh); + error = handle_stats_request(ofconn, oh); break; case OFPT_VENDOR: - error = handle_vendor(p, ofconn, ofp_msg->data); + error = handle_vendor(ofconn, ofp_msg->data); break; case OFPT_BARRIER_REQUEST: @@ -4463,7 +4471,7 @@ rule_expire(struct cls_rule *cls_rule, void *cbdata_) /* Get rid of the rule. */ if (!rule_is_hidden(rule)) { - send_flow_removed(cbdata->ofproto, rule, now, + send_flow_removed(cbdata->ofproto, rule, (now >= hard_expire ? OFPRR_HARD_TIMEOUT : OFPRR_IDLE_TIMEOUT)); } @@ -4514,23 +4522,19 @@ revalidate_rule(struct ofproto *p, struct rule *rule) } static struct ofpbuf * -compose_flow_removed(struct ofproto *p, const struct rule *rule, - long long int now, uint8_t reason) +compose_flow_removed(struct ofconn *ofconn, const struct rule *rule, + uint8_t reason) { struct ofp_flow_removed *ofr; struct ofpbuf *buf; - long long int tdiff = now - rule->created; - uint32_t sec = tdiff / 1000; - uint32_t msec = tdiff - (sec * 1000); ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf); - flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, p->tun_id_from_cookie, + flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, ofconn->flow_format, &ofr->match); ofr->cookie = rule->flow_cookie; ofr->priority = htons(rule->cr.priority); ofr->reason = reason; - ofr->duration_sec = htonl(sec); - ofr->duration_nsec = htonl(msec * 1000000); + calc_flow_duration(rule->created, &ofr->duration_sec, &ofr->duration_nsec); ofr->idle_timeout = htons(rule->idle_timeout); ofr->packet_count = htonll(rule->packet_count); ofr->byte_count = htonll(rule->byte_count); @@ -4539,8 +4543,7 @@ compose_flow_removed(struct ofproto *p, const struct rule *rule, } static void -send_flow_removed(struct ofproto *p, struct rule *rule, - long long int now, uint8_t reason) +send_flow_removed(struct ofproto *p, struct rule *rule, uint8_t reason) { struct ofconn *ofconn; @@ -4548,12 +4551,6 @@ send_flow_removed(struct ofproto *p, struct rule *rule, return; } - /* We limit the maximum number of queued flow expirations it by accounting - * them under the counter for replies. That works because preventing - * OpenFlow requests from being processed also prevents new flows from - * being added (and expiring). (It also prevents processing OpenFlow - * requests that would not add new flows, so it is imperfect.) */ - LIST_FOR_EACH (ofconn, node, &p->all_conns) { struct ofpbuf *msg; @@ -4562,7 +4559,13 @@ send_flow_removed(struct ofproto *p, struct rule *rule, continue; } - msg = compose_flow_removed(p, rule, now, reason); + msg = compose_flow_removed(ofconn, rule, reason); + + /* Account flow expirations under ofconn->reply_counter, the counter + * for replies to OpenFlow requests. That works because preventing + * OpenFlow requests from being processed also prevents new flows from + * being added (and expiring). (It also prevents processing OpenFlow + * requests that would not add new flows, so it is imperfect.) */ queue_tx(msg, ofconn, ofconn->reply_counter); } }