X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=ofproto%2Fofproto.c;h=08d80d89ae6334ae80b3ffd49388d427ac67fd41;hb=f7cd0081f525dd1d45fafc68397b5393196e978d;hp=d6ed160132da3ed68e9e2738d0401cec7fd4e2fc;hpb=856081f683d3e7d5b5fa07af4233d285eb205c47;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index d6ed1601..08d80d89 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: * @@ -429,7 +430,6 @@ ofproto_create(const char *datapath, const char *datapath_type, const struct ofhooks *ofhooks, void *aux, struct ofproto **ofprotop) { - struct odp_stats stats; struct ofproto *p; struct dpif *dpif; int error; @@ -444,13 +444,6 @@ ofproto_create(const char *datapath, const char *datapath_type, VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error)); return error; } - error = dpif_get_dp_stats(dpif, &stats); - if (error) { - VLOG_ERR("failed to obtain stats for datapath %s: %s", - datapath, strerror(error)); - dpif_close(dpif); - return error; - } error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION | ODPL_SFLOW); if (error) { VLOG_ERR("failed to listen on datapath %s: %s", @@ -476,7 +469,7 @@ ofproto_create(const char *datapath, const char *datapath_type, p->netdev_monitor = netdev_monitor_create(); hmap_init(&p->ports); shash_init(&p->port_by_name); - p->max_ports = stats.max_ports; + p->max_ports = dpif_get_max_ports(dpif); /* Initialize submodules. */ p->switch_status = switch_status_create(p); @@ -1536,12 +1529,11 @@ ofproto_flush_flows(struct ofproto *ofproto) static void reinit_ports(struct ofproto *p) { + struct dpif_port_dump dump; struct shash_node *node; struct shash devnames; struct ofport *ofport; - struct odp_port *odp_ports; - size_t n_odp_ports; - size_t i; + struct dpif_port dpif_port; COVERAGE_INC(ofproto_reinit_ports); @@ -1549,11 +1541,9 @@ reinit_ports(struct ofproto *p) HMAP_FOR_EACH (ofport, hmap_node, &p->ports) { shash_add_once (&devnames, ofport->opp.name, NULL); } - dpif_port_list(p->dpif, &odp_ports, &n_odp_ports); - for (i = 0; i < n_odp_ports; i++) { - shash_add_once (&devnames, odp_ports[i].devname, NULL); + DPIF_PORT_FOR_EACH (&dpif_port, &dump, p->dpif) { + shash_add_once (&devnames, dpif_port.name, NULL); } - free(odp_ports); SHASH_FOR_EACH (node, &devnames) { update_port(p, node->name); @@ -1562,7 +1552,7 @@ reinit_ports(struct ofproto *p) } static struct ofport * -make_ofport(const struct odp_port *odp_port) +make_ofport(const struct dpif_port *dpif_port) { struct netdev_options netdev_options; enum netdev_flags flags; @@ -1571,27 +1561,25 @@ make_ofport(const struct odp_port *odp_port) int error; memset(&netdev_options, 0, sizeof netdev_options); - netdev_options.name = odp_port->devname; - netdev_options.type = odp_port->type; + netdev_options.name = dpif_port->name; + netdev_options.type = dpif_port->type; netdev_options.ethertype = NETDEV_ETH_TYPE_NONE; error = netdev_open(&netdev_options, &netdev); if (error) { VLOG_WARN_RL(&rl, "ignoring port %s (%"PRIu16") because netdev %s " "cannot be opened (%s)", - odp_port->devname, odp_port->port, - odp_port->devname, strerror(error)); + dpif_port->name, dpif_port->port_no, + dpif_port->name, strerror(error)); return NULL; } ofport = xmalloc(sizeof *ofport); ofport->netdev = netdev; - ofport->odp_port = odp_port->port; - ofport->opp.port_no = odp_port_to_ofp_port(odp_port->port); + ofport->odp_port = dpif_port->port_no; + ofport->opp.port_no = odp_port_to_ofp_port(dpif_port->port_no); netdev_get_etheraddr(netdev, ofport->opp.hw_addr); - memcpy(ofport->opp.name, odp_port->devname, - MIN(sizeof ofport->opp.name, sizeof odp_port->devname)); - ofport->opp.name[sizeof ofport->opp.name - 1] = '\0'; + ovs_strlcpy(ofport->opp.name, dpif_port->name, sizeof ofport->opp.name); netdev_get_flags(netdev, &flags); ofport->opp.config = flags & NETDEV_UP ? 0 : OFPPC_PORT_DOWN; @@ -1605,15 +1593,15 @@ make_ofport(const struct odp_port *odp_port) } static bool -ofport_conflicts(const struct ofproto *p, const struct odp_port *odp_port) +ofport_conflicts(const struct ofproto *p, const struct dpif_port *dpif_port) { - if (get_port(p, odp_port->port)) { + if (get_port(p, dpif_port->port_no)) { VLOG_WARN_RL(&rl, "ignoring duplicate port %"PRIu16" in datapath", - odp_port->port); + dpif_port->port_no); return true; - } else if (shash_find(&p->port_by_name, odp_port->devname)) { + } else if (shash_find(&p->port_by_name, dpif_port->name)) { VLOG_WARN_RL(&rl, "ignoring duplicate device %s in datapath", - odp_port->devname); + dpif_port->name); return true; } else { return false; @@ -1714,7 +1702,7 @@ get_port(const struct ofproto *ofproto, uint16_t odp_port) static void update_port(struct ofproto *p, const char *devname) { - struct odp_port odp_port; + struct dpif_port dpif_port; struct ofport *old_ofport; struct ofport *new_ofport; int error; @@ -1722,7 +1710,7 @@ update_port(struct ofproto *p, const char *devname) COVERAGE_INC(ofproto_update_port); /* Query the datapath for port information. */ - error = dpif_port_query_by_name(p->dpif, devname, &odp_port); + error = dpif_port_query_by_name(p->dpif, devname, &dpif_port); /* Find the old ofport. */ old_ofport = shash_find_data(&p->port_by_name, devname); @@ -1738,20 +1726,20 @@ update_port(struct ofproto *p, const char *devname) * reliably but more portably by comparing the old port's MAC * against the new port's MAC. However, this code isn't that smart * and always sends an OFPPR_MODIFY (XXX). */ - old_ofport = get_port(p, odp_port.port); + old_ofport = get_port(p, dpif_port.port_no); } } else if (error != ENOENT && error != ENODEV) { VLOG_WARN_RL(&rl, "dpif_port_query_by_name returned unexpected error " "%s", strerror(error)); - return; + goto exit; } /* Create a new ofport. */ - new_ofport = !error ? make_ofport(&odp_port) : NULL; + new_ofport = !error ? make_ofport(&dpif_port) : NULL; /* Eliminate a few pathological cases. */ if (!old_ofport && !new_ofport) { - return; + goto exit; } else if (old_ofport && new_ofport) { /* Most of the 'config' bits are OpenFlow soft state, but * OFPPC_PORT_DOWN is maintained by the kernel. So transfer the @@ -1762,7 +1750,7 @@ update_port(struct ofproto *p, const char *devname) if (ofport_equal(old_ofport, new_ofport)) { /* False alarm--no change. */ ofport_free(new_ofport); - return; + goto exit; } } @@ -1778,31 +1766,26 @@ update_port(struct ofproto *p, const char *devname) : !new_ofport ? OFPPR_DELETE : OFPPR_MODIFY)); ofport_free(old_ofport); + +exit: + dpif_port_destroy(&dpif_port); } static int init_ports(struct ofproto *p) { - struct odp_port *ports; - size_t n_ports; - size_t i; - int error; + struct dpif_port_dump dump; + struct dpif_port dpif_port; - error = dpif_port_list(p->dpif, &ports, &n_ports); - if (error) { - return error; - } - - for (i = 0; i < n_ports; i++) { - const struct odp_port *odp_port = &ports[i]; - if (!ofport_conflicts(p, odp_port)) { - struct ofport *ofport = make_ofport(odp_port); + DPIF_PORT_FOR_EACH (&dpif_port, &dump, p->dpif) { + if (!ofport_conflicts(p, &dpif_port)) { + struct ofport *ofport = make_ofport(&dpif_port); if (ofport) { ofport_install(p, ofport); } } } - free(ports); + return 0; } @@ -2153,7 +2136,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)); @@ -2324,24 +2307,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 @@ -2350,17 +2334,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; } } @@ -2388,20 +2367,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; } @@ -2530,25 +2504,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); } @@ -3505,9 +3467,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 @@ -3515,23 +3475,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. */ @@ -3902,17 +3853,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) { @@ -3930,7 +3875,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); @@ -4566,31 +4511,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); @@ -4600,13 +4535,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); @@ -4708,39 +4643,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; - - ofpbuf_use_stack(&key, keybuf, sizeof keybuf); - odp_flow_key_from_flow(&key, &facet->flow); + struct dpif_flow_stats stats; - 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); } }