X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=5c7a497ecd72a5cd05e5c2d1c8fb3f5ffda8973f;hb=82272eded1ede569bcec3ba4ab212e5e3fb632ff;hp=ea869f1ec781295915fbcdf5f057d3d6478d688f;hpb=996c1b3d7a4d6e82e1831ff8821e5fd7e1a5522c;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index ea869f1e..5c7a497e 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -206,7 +206,8 @@ struct facet { * * - Do include packets and bytes that were obtained from the datapath * when a flow was deleted (e.g. dpif_flow_del()) or when its - * statistics were reset (e.g. dpif_flow_put() with ODPPF_ZERO_STATS). + * statistics were reset (e.g. dpif_flow_put() with + * DPIF_FP_ZERO_STATS). * * - Do not include any packets or bytes that can currently be obtained * from the datapath by, e.g., dpif_flow_get(). @@ -248,7 +249,7 @@ static void facet_flush_stats(struct ofproto *, struct facet *); static void facet_make_actions(struct ofproto *, struct facet *, const struct ofpbuf *packet); static void facet_update_stats(struct ofproto *, struct facet *, - const struct odp_flow_stats *); + const struct dpif_flow_stats *); /* ofproto supports two kinds of OpenFlow connections: * @@ -300,7 +301,8 @@ struct ofconn { /* OFPT_PACKET_IN related data. */ struct rconn_packet_counter *packet_in_counter; /* # queued on 'rconn'. */ - struct pinsched *schedulers[2]; /* Indexed by reason code; see below. */ +#define N_SCHEDULERS 2 + struct pinsched *schedulers[N_SCHEDULERS]; struct pktbuf *pktbuf; /* OpenFlow packet buffers. */ int miss_send_len; /* Bytes to send of buffered packets. */ @@ -318,15 +320,6 @@ struct ofconn { enum ofproto_band band; /* In-band or out-of-band? */ }; -/* We use OFPR_NO_MATCH and OFPR_ACTION as indexes into struct ofconn's - * "schedulers" array. Their values are 0 and 1, and their meanings and values - * coincide with _ODPL_MISS_NR and _ODPL_ACTION_NR, so this is convenient. In - * case anything ever changes, check their values here. */ -#define N_SCHEDULERS 2 -BUILD_ASSERT_DECL(OFPR_NO_MATCH == 0); -BUILD_ASSERT_DECL(OFPR_NO_MATCH == _ODPL_MISS_NR); -BUILD_ASSERT_DECL(OFPR_ACTION == 1); -BUILD_ASSERT_DECL(OFPR_ACTION == _ODPL_ACTION_NR); static struct ofconn *ofconn_create(struct ofproto *, struct rconn *, enum ofconn_type); @@ -443,7 +436,10 @@ ofproto_create(const char *datapath, const char *datapath_type, VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error)); return error; } - error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION | ODPL_SFLOW); + error = dpif_recv_set_mask(dpif, + ((1u << DPIF_UC_MISS) | + (1u << DPIF_UC_ACTION) | + (1u << DPIF_UC_SAMPLE))); if (error) { VLOG_ERR("failed to listen on datapath %s: %s", datapath, strerror(error)); @@ -2098,7 +2094,7 @@ execute_odp_actions(struct ofproto *ofproto, const struct flow *flow, * buffers along the way. */ struct dpif_upcall upcall; - upcall.type = _ODPL_ACTION_NR; + upcall.type = DPIF_UC_ACTION; upcall.packet = packet; upcall.key = NULL; upcall.key_len = 0; @@ -2135,7 +2131,7 @@ static void facet_execute(struct ofproto *ofproto, struct facet *facet, struct ofpbuf *packet) { - struct odp_flow_stats stats; + struct dpif_flow_stats stats; assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in)); @@ -2306,24 +2302,25 @@ facet_make_actions(struct ofproto *p, struct facet *facet, } static int -facet_put__(struct ofproto *ofproto, struct facet *facet, int flags, - struct odp_flow_put *put) +facet_put__(struct ofproto *ofproto, struct facet *facet, + const struct nlattr *actions, size_t actions_len, + struct dpif_flow_stats *stats) { uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S]; + enum dpif_flow_put_flags flags; struct ofpbuf key; + flags = DPIF_FP_CREATE | DPIF_FP_MODIFY; + if (stats) { + flags |= DPIF_FP_ZERO_STATS; + } + ofpbuf_use_stack(&key, keybuf, sizeof keybuf); odp_flow_key_from_flow(&key, &facet->flow); assert(key.base == keybuf); - memset(&put->flow.stats, 0, sizeof put->flow.stats); - put->flow.key = key.data; - put->flow.key_len = key.size; - put->flow.actions = facet->actions; - put->flow.actions_len = facet->actions_len; - put->flow.flags = 0; - put->flags = flags; - return dpif_flow_put(ofproto->dpif, put); + return dpif_flow_put(ofproto->dpif, flags, key.data, key.size, + actions, actions_len, stats); } /* If 'facet' is installable, inserts or re-inserts it into 'p''s datapath. If @@ -2332,17 +2329,12 @@ facet_put__(struct ofproto *ofproto, struct facet *facet, int flags, static void facet_install(struct ofproto *p, struct facet *facet, bool zero_stats) { - if (facet->may_install) { - struct odp_flow_put put; - int flags; + struct dpif_flow_stats stats; - flags = ODPPF_CREATE | ODPPF_MODIFY; - if (zero_stats) { - flags |= ODPPF_ZERO_STATS; - } - if (!facet_put__(p, facet, flags, &put)) { - facet->installed = true; - } + if (facet->may_install + && !facet_put__(p, facet, facet->actions, facet->actions_len, + zero_stats ? &stats : NULL)) { + facet->installed = true; } } @@ -2370,20 +2362,15 @@ facet_uninstall(struct ofproto *p, struct facet *facet) { if (facet->installed) { uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S]; - struct odp_flow odp_flow; + struct dpif_flow_stats stats; struct ofpbuf key; ofpbuf_use_stack(&key, keybuf, sizeof keybuf); odp_flow_key_from_flow(&key, &facet->flow); assert(key.base == keybuf); - odp_flow.key = key.data; - odp_flow.key_len = key.size; - odp_flow.actions = NULL; - odp_flow.actions_len = 0; - odp_flow.flags = 0; - if (!dpif_flow_del(p->dpif, &odp_flow)) { - facet_update_stats(p, facet, &odp_flow.stats); + if (!dpif_flow_del(p->dpif, key.data, key.size, &stats)) { + facet_update_stats(p, facet, &stats); } facet->installed = false; } @@ -2512,25 +2499,13 @@ facet_revalidate(struct ofproto *ofproto, struct facet *facet) /* If the ODP actions changed or the installability changed, then we need * to talk to the datapath. */ - if (actions_changed || facet->may_install != facet->installed) { - if (facet->may_install) { - uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S]; - struct odp_flow_put put; - struct ofpbuf key; - - ofpbuf_use_stack(&key, keybuf, sizeof keybuf); - odp_flow_key_from_flow(&key, &facet->flow); - - memset(&put.flow.stats, 0, sizeof put.flow.stats); - put.flow.key = key.data; - put.flow.key_len = key.size; - put.flow.actions = odp_actions->data; - put.flow.actions_len = odp_actions->size; - put.flow.flags = 0; - put.flags = ODPPF_CREATE | ODPPF_MODIFY | ODPPF_ZERO_STATS; - dpif_flow_put(ofproto->dpif, &put); - - facet_update_stats(ofproto, facet, &put.flow.stats); + if (actions_changed || ctx.may_set_up_flow != facet->installed) { + if (ctx.may_set_up_flow) { + struct dpif_flow_stats stats; + + facet_put__(ofproto, facet, + odp_actions->data, odp_actions->size, &stats); + facet_update_stats(ofproto, facet, &stats); } else { facet_uninstall(ofproto, facet); } @@ -3487,9 +3462,7 @@ query_stats(struct ofproto *p, struct rule *rule, packet_count = rule->packet_count; byte_count = rule->byte_count; - /* Ask the datapath for statistics on all of the rule's facets. (We could - * batch up statistics requests using dpif_flow_get_multiple(), but that is - * not yet implemented.) + /* Ask the datapath for statistics on all of the rule's facets. * * Also, add any statistics that are not tracked by the datapath for each * facet. This includes, for example, statistics for packets that were @@ -3497,23 +3470,14 @@ query_stats(struct ofproto *p, struct rule *rule, * to a rule. */ ofpbuf_use_stack(&key, keybuf, sizeof keybuf); LIST_FOR_EACH (facet, list_node, &rule->facets) { - struct odp_flow odp_flow; + struct dpif_flow_stats stats; ofpbuf_clear(&key); odp_flow_key_from_flow(&key, &facet->flow); + dpif_flow_get(p->dpif, key.data, key.size, NULL, &stats); - odp_flow.key = key.data; - odp_flow.key_len = key.size; - odp_flow.actions = NULL; - odp_flow.actions_len = 0; - odp_flow.flags = 0; - if (!dpif_flow_get(p->dpif, &odp_flow)) { - packet_count += odp_flow.stats.n_packets; - byte_count += odp_flow.stats.n_bytes; - } - - packet_count += facet->packet_count; - byte_count += facet->byte_count; + packet_count += stats.n_packets + facet->packet_count; + byte_count += stats.n_bytes + facet->byte_count; } /* Return the stats to the caller. */ @@ -3884,17 +3848,11 @@ handle_queue_stats_request(struct ofconn *ofconn, const struct ofp_header *oh) return 0; } -static long long int -msec_from_nsec(uint64_t sec, uint32_t nsec) -{ - return !sec ? 0 : sec * 1000 + nsec / 1000000; -} - static void facet_update_time(struct ofproto *ofproto, struct facet *facet, - const struct odp_flow_stats *stats) + const struct dpif_flow_stats *stats) { - long long int used = msec_from_nsec(stats->used_sec, stats->used_nsec); + long long int used = stats->used; if (used > facet->used) { facet->used = used; if (used > facet->rule->used) { @@ -3912,7 +3870,7 @@ facet_update_time(struct ofproto *ofproto, struct facet *facet, * cleared out of the datapath. */ static void facet_update_stats(struct ofproto *ofproto, struct facet *facet, - const struct odp_flow_stats *stats) + const struct dpif_flow_stats *stats) { if (stats->n_packets) { facet_update_time(ofproto, facet, stats); @@ -4476,13 +4434,13 @@ handle_upcall(struct ofproto *p, struct dpif_upcall *upcall) struct flow flow; switch (upcall->type) { - case _ODPL_ACTION_NR: + case DPIF_UC_ACTION: COVERAGE_INC(ofproto_ctlr_action); odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow); send_packet_in(p, upcall, &flow, false); break; - case _ODPL_SFLOW_NR: + case DPIF_UC_SAMPLE: if (p->sflow) { odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow); ofproto_sflow_received(p->sflow, upcall, &flow); @@ -4490,7 +4448,7 @@ handle_upcall(struct ofproto *p, struct dpif_upcall *upcall) ofpbuf_delete(upcall->packet); break; - case _ODPL_MISS_NR: + case DPIF_UC_MISS: handle_miss_upcall(p, upcall); break; @@ -4548,31 +4506,21 @@ ofproto_expire(struct ofproto *ofproto) static void ofproto_update_used(struct ofproto *p) { + const struct dpif_flow_stats *stats; struct dpif_flow_dump dump; + const struct nlattr *key; + size_t key_len; dpif_flow_dump_start(&dump, p->dpif); - for (;;) { - uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S]; + while (dpif_flow_dump_next(&dump, &key, &key_len, NULL, NULL, &stats)) { struct facet *facet; - struct odp_flow f; struct flow flow; - memset(&f, 0, sizeof f); - f.key = (struct nlattr *) keybuf; - f.key_len = sizeof keybuf; - if (!dpif_flow_dump_next(&dump, &f)) { - break; - } - - if (f.key_len > sizeof keybuf) { - VLOG_WARN_RL(&rl, "ODP flow key overflowed buffer"); - continue; - } - if (odp_flow_key_to_flow(f.key, f.key_len, &flow)) { + if (odp_flow_key_to_flow(key, key_len, &flow)) { struct ds s; ds_init(&s); - odp_flow_key_format(f.key, f.key_len, &s); + odp_flow_key_format(key, key_len, &s); VLOG_WARN_RL(&rl, "failed to convert ODP flow key to flow: %s", ds_cstr(&s)); ds_destroy(&s); @@ -4582,13 +4530,13 @@ ofproto_update_used(struct ofproto *p) facet = facet_find(p, &flow); if (facet && facet->installed) { - facet_update_time(p, facet, &f.stats); - facet_account(p, facet, f.stats.n_bytes); + facet_update_time(p, facet, stats); + facet_account(p, facet, stats->n_bytes); } else { /* There's a flow in the datapath that we know nothing about. * Delete it. */ COVERAGE_INC(ofproto_unexpected_rule); - dpif_flow_del(p->dpif, &f); + dpif_flow_del(p->dpif, key, key_len, NULL); } } dpif_flow_dump_done(&dump); @@ -4690,39 +4638,19 @@ facet_active_timeout(struct ofproto *ofproto, struct facet *facet) if (ofproto->netflow && !facet_is_controller_flow(facet) && netflow_active_timeout_expired(ofproto->netflow, &facet->nf_flow)) { struct ofexpired expired; - struct odp_flow odp_flow; - /* Get updated flow stats. - * - * XXX We could avoid this call entirely if (1) ofproto_update_used() - * updated TCP flags and (2) the dpif_flow_list_all() in - * ofproto_update_used() zeroed TCP flags. */ - memset(&odp_flow, 0, sizeof odp_flow); if (facet->installed) { - uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S]; - struct ofpbuf key; + struct dpif_flow_stats stats; - ofpbuf_use_stack(&key, keybuf, sizeof keybuf); - odp_flow_key_from_flow(&key, &facet->flow); - - odp_flow.key = key.data; - odp_flow.key_len = key.size; - odp_flow.flags = ODPFF_ZERO_TCP_FLAGS; - dpif_flow_get(ofproto->dpif, &odp_flow); - - if (odp_flow.stats.n_packets) { - facet_update_time(ofproto, facet, &odp_flow.stats); - netflow_flow_update_flags(&facet->nf_flow, - odp_flow.stats.tcp_flags); - } + facet_put__(ofproto, facet, facet->actions, facet->actions_len, + &stats); + facet_update_stats(ofproto, facet, &stats); } expired.flow = facet->flow; - expired.packet_count = facet->packet_count + - odp_flow.stats.n_packets; - expired.byte_count = facet->byte_count + odp_flow.stats.n_bytes; + expired.packet_count = facet->packet_count; + expired.byte_count = facet->byte_count; expired.used = facet->used; - netflow_expire(ofproto->netflow, &facet->nf_flow, &expired); } } @@ -4876,9 +4804,10 @@ schedule_packet_in(struct ofconn *ofconn, struct dpif_upcall *upcall, int total_len, send_len; struct ofpbuf *packet; uint32_t buffer_id; + int idx; /* Get OpenFlow buffer_id. */ - if (upcall->type == _ODPL_ACTION_NR) { + if (upcall->type == DPIF_UC_ACTION) { buffer_id = UINT32_MAX; } else if (ofproto->fail_open && fail_open_is_active(ofproto->fail_open)) { buffer_id = pktbuf_get_null(); @@ -4893,7 +4822,7 @@ schedule_packet_in(struct ofconn *ofconn, struct dpif_upcall *upcall, if (buffer_id != UINT32_MAX) { send_len = MIN(send_len, ofconn->miss_send_len); } - if (upcall->type == _ODPL_ACTION_NR) { + if (upcall->type == DPIF_UC_ACTION) { send_len = MIN(send_len, upcall->userdata); } @@ -4912,18 +4841,19 @@ schedule_packet_in(struct ofconn *ofconn, struct dpif_upcall *upcall, opi->header.type = OFPT_PACKET_IN; opi->total_len = htons(total_len); opi->in_port = htons(odp_port_to_ofp_port(flow->in_port)); - opi->reason = upcall->type == _ODPL_MISS_NR ? OFPR_NO_MATCH : OFPR_ACTION; + opi->reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION; opi->buffer_id = htonl(buffer_id); update_openflow_length(packet); /* 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()). */ - pinsched_send(ofconn->schedulers[opi->reason], flow->in_port, + idx = upcall->type == DPIF_UC_MISS ? 0 : 1; + pinsched_send(ofconn->schedulers[idx], flow->in_port, packet, do_send_packet_in, ofconn); } -/* Given 'upcall', of type _ODPL_ACTION_NR or _ODPL_MISS_NR, sends an +/* Given 'upcall', of type DPIF_UC_ACTION or DPIF_UC_MISS, sends an * OFPT_PACKET_IN message to each OpenFlow controller as necessary according to * their individual configurations. *