X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=f09c230d3c7b574149d287ddd014d363b5c0a4c5;hb=a281173e19918379832ec535b18aa2af58832efb;hp=fdef4afa56e41de48b0beccf7c86b54a93d9e971;hpb=f694937d4ec5342b218b760cabbf7a48d19110e8;p=openvswitch diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index fdef4afa..f09c230d 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -207,12 +207,8 @@ struct facet { * dpif_execute(). * * - 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 + * when its 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(). */ uint64_t packet_count; /* Number of packets received. */ uint64_t byte_count; /* Number of bytes received. */ @@ -224,10 +220,7 @@ struct facet { uint64_t rs_byte_count; /* Bytes pushed to resubmit children. */ long long int rs_used; /* Used time pushed to resubmit children. */ - /* Number of bytes passed to account_cb. This may include bytes that can - * currently obtained from the datapath (thus, it can be greater than - * byte_count). */ - uint64_t accounted_bytes; + uint64_t accounted_bytes; /* Bytes processed by facet_account(). */ struct hmap_node hmap_node; /* In owning ofproto's 'facets' hmap. */ struct list list_node; /* In owning rule's 'facets' list. */ @@ -269,10 +262,10 @@ static void facet_update_time(struct ofproto_dpif *, struct facet *, long long int used); static void facet_update_stats(struct ofproto_dpif *, struct facet *, const struct dpif_flow_stats *); +static void facet_reset_counters(struct facet *); static void facet_reset_dp_stats(struct facet *, struct dpif_flow_stats *); static void facet_push_stats(struct facet *); -static void facet_account(struct ofproto_dpif *, struct facet *, - uint64_t extra_bytes); +static void facet_account(struct ofproto_dpif *, struct facet *); static bool facet_is_controller_flow(struct facet *); @@ -566,6 +559,8 @@ run(struct ofproto *ofproto_) bundle_run(bundle); } + mac_learning_run(ofproto->ml, &ofproto->revalidate_set); + /* Now revalidate if there's anything to do. */ if (ofproto->need_revalidate || !tag_set_is_empty(&ofproto->revalidate_set)) { @@ -613,6 +608,7 @@ wait(struct ofproto *ofproto_) HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) { bundle_wait(bundle); } + mac_learning_wait(ofproto->ml); if (ofproto->need_revalidate) { /* Shouldn't happen, but if it does just go around again. */ VLOG_DBG_RL(&rl, "need revalidate in ofproto_wait_cb()"); @@ -664,7 +660,7 @@ static void get_tables(struct ofproto *ofproto_, struct ofp_table_stats *ots) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); - struct odp_stats s; + struct ovs_dp_stats s; strcpy(ots->name, "classifier"); @@ -1658,7 +1654,7 @@ handle_miss_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall) /* Check with in-band control to see if this packet should be sent * to the local port regardless of the flow table. */ if (connmgr_msg_in_hook(ofproto->up.connmgr, &flow, upcall->packet)) { - send_packet(ofproto, ODPP_LOCAL, upcall->packet); + send_packet(ofproto, OVSP_LOCAL, upcall->packet); } facet = facet_lookup_valid(ofproto, &flow); @@ -1821,7 +1817,7 @@ update_stats(struct ofproto_dpif *p) ds_init(&s); odp_flow_key_format(key, key_len, &s); - VLOG_WARN_RL(&rl, "failed to convert ODP flow key to flow: %s", + VLOG_WARN_RL(&rl, "failed to convert datapath flow key to flow: %s", ds_cstr(&s)); ds_destroy(&s); @@ -1848,7 +1844,7 @@ update_stats(struct ofproto_dpif *p) facet->dp_byte_count = stats->n_bytes; facet_update_time(p, facet, stats->used); - facet_account(p, facet, stats->n_bytes); + facet_account(p, facet); facet_push_stats(facet); } else { /* There's a flow in the datapath that we know nothing about. @@ -2063,7 +2059,7 @@ execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow, struct ofpbuf *packet) { if (actions_len == NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t)) - && odp_actions->nla_type == ODP_ACTION_ATTR_USERSPACE) { + && odp_actions->nla_type == OVS_ACTION_ATTR_USERSPACE) { /* As an optimization, avoid a round-trip from userspace to kernel to * userspace. This also avoids possibly filling up kernel packet * buffers along the way. */ @@ -2105,8 +2101,8 @@ execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow, * applying flow_extract() to 'packet' would yield the same flow as * 'facet->flow'. * - * 'facet' must have accurately composed ODP actions; that is, it must not be - * in need of revalidation. + * 'facet' must have accurately composed datapath actions; that is, it must + * not be in need of revalidation. * * Takes ownership of 'packet'. */ static void @@ -2142,7 +2138,7 @@ facet_remove(struct ofproto_dpif *ofproto, struct facet *facet) facet_free(facet); } -/* Composes the ODP actions for 'facet' based on its rule's actions. */ +/* Composes the datapath actions for 'facet' based on its rule's actions. */ static void facet_make_actions(struct ofproto_dpif *p, struct facet *facet, const struct ofpbuf *packet) @@ -2223,10 +2219,9 @@ vlan_tci_to_openflow_vlan(ovs_be16 vlan_tci) } static void -facet_account(struct ofproto_dpif *ofproto, - struct facet *facet, uint64_t extra_bytes) +facet_account(struct ofproto_dpif *ofproto, struct facet *facet) { - uint64_t total_bytes, n_bytes; + uint64_t n_bytes; struct ofbundle *in_bundle; const struct nlattr *a; tag_type dummy = 0; @@ -2234,12 +2229,11 @@ facet_account(struct ofproto_dpif *ofproto, ovs_be16 vlan_tci; int vlan; - total_bytes = facet->byte_count + extra_bytes; - if (total_bytes <= facet->accounted_bytes) { + if (facet->byte_count <= facet->accounted_bytes) { return; } - n_bytes = total_bytes - facet->accounted_bytes; - facet->accounted_bytes = total_bytes; + n_bytes = facet->byte_count - facet->accounted_bytes; + facet->accounted_bytes = facet->byte_count; /* Test that 'tags' is nonzero to ensure that only flows that include an * OFPP_NORMAL action are used for learning and bond slave rebalancing. @@ -2270,7 +2264,7 @@ facet_account(struct ofproto_dpif *ofproto, struct ofport_dpif *port; switch (nl_attr_type(a)) { - case ODP_ACTION_ATTR_OUTPUT: + case OVS_ACTION_ATTR_OUTPUT: port = get_odp_port(ofproto, nl_attr_get_u32(a)); if (port && port->bundle && port->bundle->bond) { bond_account(port->bundle->bond, &facet->flow, @@ -2278,11 +2272,11 @@ facet_account(struct ofproto_dpif *ofproto, } break; - case ODP_ACTION_ATTR_STRIP_VLAN: + case OVS_ACTION_ATTR_STRIP_VLAN: vlan_tci = htons(0); break; - case ODP_ACTION_ATTR_SET_DL_TCI: + case OVS_ACTION_ATTR_SET_DL_TCI: vlan_tci = nl_attr_get_be16(a); break; } @@ -2355,7 +2349,7 @@ facet_flush_stats(struct ofproto_dpif *ofproto, struct facet *facet) assert(!facet->dp_packet_count); facet_push_stats(facet); - facet_account(ofproto, facet, 0); + facet_account(ofproto, facet); if (ofproto->netflow && !facet_is_controller_flow(facet)) { struct ofexpired expired; @@ -2371,11 +2365,7 @@ facet_flush_stats(struct ofproto_dpif *ofproto, struct facet *facet) /* Reset counters to prevent double counting if 'facet' ever gets * reinstalled. */ - facet->packet_count = 0; - facet->byte_count = 0; - facet->rs_packet_count = 0; - facet->rs_byte_count = 0; - facet->accounted_bytes = 0; + facet_reset_counters(facet); netflow_flow_clear(&facet->nf_flow); } @@ -2450,7 +2440,7 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct facet *facet) return false; } - /* Calculate new ODP actions. + /* Calculate new datapath actions. * * We do not modify any 'facet' state yet, because we might need to, e.g., * emit a NetFlow expiration and, if so, we need to have the old state @@ -2462,8 +2452,8 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct facet *facet) || memcmp(facet->actions, odp_actions->data, facet->actions_len)); - /* If the ODP actions changed or the installability changed, then we need - * to talk to the datapath. */ + /* If the datapath actions changed or the installability changed, + * then we need to talk to the datapath. */ if (actions_changed || ctx.may_set_up_flow != facet->installed) { if (ctx.may_set_up_flow) { struct dpif_flow_stats stats; @@ -2537,6 +2527,16 @@ facet_update_stats(struct ofproto_dpif *ofproto, struct facet *facet, } } +static void +facet_reset_counters(struct facet *facet) +{ + facet->packet_count = 0; + facet->byte_count = 0; + facet->rs_packet_count = 0; + facet->rs_byte_count = 0; + facet->accounted_bytes = 0; +} + static void facet_push_stats(struct facet *facet) { @@ -2663,6 +2663,13 @@ rule_construct(struct rule *rule_) rule->facets = victim->facets; list_moved(&rule->facets); LIST_FOR_EACH (facet, list_node, &rule->facets) { + /* XXX: We're only clearing our local counters here. It's possible + * that quite a few packets are unaccounted for in the datapath + * statistics. These will be accounted to the new rule instead of + * cleared as required. This could be fixed by clearing out the + * datapath statistics for this facet, but currently it doesn't + * seem worth it. */ + facet_reset_counters(facet); facet->rule = rule; } } else { @@ -2784,7 +2791,7 @@ send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port, odp_flow_key_from_flow(&key, &flow); ofpbuf_init(&odp_actions, 32); - nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port); + nl_msg_put_u32(&odp_actions, OVS_ACTION_ATTR_OUTPUT, odp_port); error = dpif_execute(ofproto->dpif, key.data, key.size, odp_actions.data, odp_actions.size, @@ -2798,7 +2805,7 @@ send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port, return error; } -/* OpenFlow to ODP action translation. */ +/* OpenFlow to datapath action translation. */ static void do_xlate_actions(const union ofp_action *in, size_t n_in, struct action_xlate_ctx *ctx); @@ -2812,63 +2819,63 @@ commit_odp_actions(struct action_xlate_ctx *ctx) struct ofpbuf *odp_actions = ctx->odp_actions; if (base->tun_id != flow->tun_id) { - nl_msg_put_be64(odp_actions, ODP_ACTION_ATTR_SET_TUNNEL, flow->tun_id); + nl_msg_put_be64(odp_actions, OVS_ACTION_ATTR_SET_TUNNEL, flow->tun_id); base->tun_id = flow->tun_id; } if (base->nw_src != flow->nw_src) { - nl_msg_put_be32(odp_actions, ODP_ACTION_ATTR_SET_NW_SRC, flow->nw_src); + nl_msg_put_be32(odp_actions, OVS_ACTION_ATTR_SET_NW_SRC, flow->nw_src); base->nw_src = flow->nw_src; } if (base->nw_dst != flow->nw_dst) { - nl_msg_put_be32(odp_actions, ODP_ACTION_ATTR_SET_NW_DST, flow->nw_dst); + nl_msg_put_be32(odp_actions, OVS_ACTION_ATTR_SET_NW_DST, flow->nw_dst); base->nw_dst = flow->nw_dst; } if (base->nw_tos != flow->nw_tos) { - nl_msg_put_u8(odp_actions, ODP_ACTION_ATTR_SET_NW_TOS, flow->nw_tos); + nl_msg_put_u8(odp_actions, OVS_ACTION_ATTR_SET_NW_TOS, flow->nw_tos); base->nw_tos = flow->nw_tos; } if (base->vlan_tci != flow->vlan_tci) { if (!(flow->vlan_tci & htons(VLAN_CFI))) { - nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_STRIP_VLAN); + nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_STRIP_VLAN); } else { - nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_DL_TCI, + nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_SET_DL_TCI, flow->vlan_tci & ~htons(VLAN_CFI)); } base->vlan_tci = flow->vlan_tci; } if (base->tp_src != flow->tp_src) { - nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_TP_SRC, flow->tp_src); + nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_SET_TP_SRC, flow->tp_src); base->tp_src = flow->tp_src; } if (base->tp_dst != flow->tp_dst) { - nl_msg_put_be16(odp_actions, ODP_ACTION_ATTR_SET_TP_DST, flow->tp_dst); + nl_msg_put_be16(odp_actions, OVS_ACTION_ATTR_SET_TP_DST, flow->tp_dst); base->tp_dst = flow->tp_dst; } if (!eth_addr_equals(base->dl_src, flow->dl_src)) { - nl_msg_put_unspec(odp_actions, ODP_ACTION_ATTR_SET_DL_SRC, + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_SET_DL_SRC, flow->dl_src, ETH_ADDR_LEN); memcpy(base->dl_src, flow->dl_src, ETH_ADDR_LEN); } if (!eth_addr_equals(base->dl_dst, flow->dl_dst)) { - nl_msg_put_unspec(odp_actions, ODP_ACTION_ATTR_SET_DL_DST, + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_SET_DL_DST, flow->dl_dst, ETH_ADDR_LEN); memcpy(base->dl_dst, flow->dl_dst, ETH_ADDR_LEN); } if (ctx->base_priority != ctx->priority) { if (ctx->priority) { - nl_msg_put_u32(odp_actions, ODP_ACTION_ATTR_SET_PRIORITY, + nl_msg_put_u32(odp_actions, OVS_ACTION_ATTR_SET_PRIORITY, ctx->priority); } else { - nl_msg_put_flag(odp_actions, ODP_ACTION_ATTR_POP_PRIORITY); + nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_PRIORITY); } ctx->base_priority = ctx->priority; } @@ -2894,7 +2901,7 @@ add_output_action(struct action_xlate_ctx *ctx, uint16_t ofp_port) } commit_odp_actions(ctx); - nl_msg_put_u32(ctx->odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port); + nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_OUTPUT, odp_port); ctx->nf_output_iface = ofp_port; } @@ -2961,7 +2968,7 @@ flood_packets(struct action_xlate_ctx *ctx, ovs_be32 mask) HMAP_FOR_EACH (ofport, up.hmap_node, &ctx->ofproto->up.ports) { uint16_t ofp_port = ofport->up.ofp_port; if (ofp_port != ctx->flow.in_port && !(ofport->up.opp.config & mask)) { - nl_msg_put_u32(ctx->odp_actions, ODP_ACTION_ATTR_OUTPUT, + nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_OUTPUT, ofport->odp_port); } } @@ -2995,7 +3002,7 @@ xlate_output_action__(struct action_xlate_ctx *ctx, break; case OFPP_CONTROLLER: commit_odp_actions(ctx); - nl_msg_put_u64(ctx->odp_actions, ODP_ACTION_ATTR_USERSPACE, max_len); + nl_msg_put_u64(ctx->odp_actions, OVS_ACTION_ATTR_USERSPACE, max_len); break; case OFPP_LOCAL: add_output_action(ctx, OFPP_LOCAL); @@ -3055,14 +3062,14 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx, return; } - /* Figure out ODP output port. */ + /* Figure out datapath output port. */ ofp_port = ntohs(oae->port); if (ofp_port == OFPP_IN_PORT) { ofp_port = ctx->flow.in_port; } odp_port = ofp_port_to_odp_port(ofp_port); - /* Add ODP actions. */ + /* Add datapath actions. */ ctx_priority = ctx->priority; ctx->priority = priority; add_output_action(ctx, odp_port); @@ -3621,7 +3628,7 @@ compose_actions(struct action_xlate_ctx *ctx, uint16_t vlan, continue; } nl_msg_put_u32(ctx->odp_actions, - ODP_ACTION_ATTR_OUTPUT, dst->port->odp_port); + OVS_ACTION_ATTR_OUTPUT, dst->port->odp_port); } /* Then output the rest. */ @@ -3632,18 +3639,18 @@ compose_actions(struct action_xlate_ctx *ctx, uint16_t vlan, } if (dst->vlan != cur_vlan) { if (dst->vlan == OFP_VLAN_NONE) { - nl_msg_put_flag(ctx->odp_actions, ODP_ACTION_ATTR_STRIP_VLAN); + nl_msg_put_flag(ctx->odp_actions, OVS_ACTION_ATTR_STRIP_VLAN); } else { ovs_be16 tci; tci = htons(dst->vlan & VLAN_VID_MASK); tci |= ctx->flow.vlan_tci & htons(VLAN_PCP_MASK); nl_msg_put_be16(ctx->odp_actions, - ODP_ACTION_ATTR_SET_DL_TCI, tci); + OVS_ACTION_ATTR_SET_DL_TCI, tci); } cur_vlan = dst->vlan; } nl_msg_put_u32(ctx->odp_actions, - ODP_ACTION_ATTR_OUTPUT, dst->port->odp_port); + OVS_ACTION_ATTR_OUTPUT, dst->port->odp_port); } dst_set_free(&set); @@ -4018,6 +4025,20 @@ trace_format_flow(struct ds *result, int level, const char *title, ds_put_char(result, '\n'); } +static void +trace_format_regs(struct ds *result, int level, const char *title, + struct ofproto_trace *trace) +{ + size_t i; + + ds_put_char_multiple(result, '\t', level); + ds_put_format(result, "%s:", title); + for (i = 0; i < FLOW_N_REGS; i++) { + ds_put_format(result, " reg%zu=0x%"PRIx32, i, trace->flow.regs[i]); + } + ds_put_char(result, '\n'); +} + static void trace_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule) { @@ -4026,6 +4047,7 @@ trace_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule) ds_put_char(result, '\n'); trace_format_flow(result, ctx->recurse + 1, "Resubmitted flow", trace); + trace_format_regs(result, ctx->recurse + 1, "Resubmitted regs", trace); trace_format_rule(result, ctx->table_id, ctx->recurse + 1, rule); } @@ -4056,7 +4078,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_, /* ofproto/trace dpname flow */ int error; - /* Convert string to ODP key. */ + /* Convert string to datapath key. */ ofpbuf_init(&odp_key, 0); error = odp_flow_key_from_string(arg1, &odp_key); if (error) {