X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=78cb186a6a884961725ef41d7cabe9c538a1aea1;hb=079b5942276a04b2b18f1ec5bd2e07170e3ab9bd;hp=10d450ec5e6d65db2d2524519d9f26702f66f912;hpb=42edbe39dd2dcb94ef2f43dacb3e43a01bcf1f86;p=openvswitch diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 10d450ec..78cb186a 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -110,6 +110,8 @@ static struct rule_dpif *rule_dpif_lookup(struct ofproto_dpif *, static struct rule_dpif *rule_dpif_lookup__(struct ofproto_dpif *, const struct flow *, uint8_t table); +static struct rule_dpif *rule_dpif_miss_rule(struct ofproto_dpif *ofproto, + const struct flow *flow); static void rule_credit_stats(struct rule_dpif *, const struct dpif_flow_stats *); @@ -368,7 +370,8 @@ struct subfacet { static struct subfacet *subfacet_create(struct facet *, enum odp_key_fitness, const struct nlattr *key, - size_t key_len, ovs_be16 initial_tci); + size_t key_len, ovs_be16 initial_tci, + long long int now); static struct subfacet *subfacet_find(struct ofproto_dpif *, const struct nlattr *key, size_t key_len); static void subfacet_destroy(struct subfacet *); @@ -2866,6 +2869,7 @@ handle_flow_miss_without_facet(struct flow_miss *miss, struct flow_miss_op *ops, size_t *n_ops) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); + long long int now = time_msec(); struct action_xlate_ctx ctx; struct ofpbuf *packet; @@ -2878,7 +2882,7 @@ handle_flow_miss_without_facet(struct flow_miss *miss, ofpbuf_use_stub(&odp_actions, op->stub, sizeof op->stub); - dpif_flow_stats_extract(&miss->flow, packet, &stats); + dpif_flow_stats_extract(&miss->flow, packet, now, &stats); rule_credit_stats(rule, &stats); action_xlate_ctx_init(&ctx, ofproto, &miss->flow, miss->initial_tci, @@ -2903,9 +2907,17 @@ handle_flow_miss_without_facet(struct flow_miss *miss, } /* Handles 'miss', which matches 'facet'. May add any required datapath - * operations to 'ops', incrementing '*n_ops' for each new op. */ + * operations to 'ops', incrementing '*n_ops' for each new op. + * + * All of the packets in 'miss' are considered to have arrived at time 'now'. + * This is really important only for new facets: if we just called time_msec() + * here, then the new subfacet or its packets could look (occasionally) as + * though it was used some time after the facet was used. That can make a + * one-packet flow look like it has a nonzero duration, which looks odd in + * e.g. NetFlow statistics. */ static void handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet, + long long int now, struct flow_miss_op *ops, size_t *n_ops) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto); @@ -2915,7 +2927,7 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet, subfacet = subfacet_create(facet, miss->key_fitness, miss->key, miss->key_len, - miss->initial_tci); + miss->initial_tci, now); LIST_FOR_EACH (packet, list_node, &miss->packets) { struct flow_miss_op *op = &ops[*n_ops]; @@ -2929,7 +2941,7 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet, subfacet_make_actions(subfacet, packet, &odp_actions); } - dpif_flow_stats_extract(&facet->flow, packet, &stats); + dpif_flow_stats_extract(&facet->flow, packet, now, &stats); subfacet_update_stats(subfacet, &stats); if (subfacet->actions_len) { @@ -2983,6 +2995,7 @@ handle_flow_miss(struct ofproto_dpif *ofproto, struct flow_miss *miss, struct flow_miss_op *ops, size_t *n_ops) { struct facet *facet; + long long int now; uint32_t hash; /* The caller must ensure that miss->hmap_node.hash contains @@ -2999,8 +3012,11 @@ handle_flow_miss(struct ofproto_dpif *ofproto, struct flow_miss *miss, } facet = facet_create(rule, &miss->flow, hash); + now = facet->used; + } else { + now = time_msec(); } - handle_flow_miss_with_facet(miss, facet, ops, n_ops); + handle_flow_miss_with_facet(miss, facet, now, ops, n_ops); } /* Like odp_flow_key_to_flow(), this function converts the 'key_len' bytes of @@ -4247,7 +4263,8 @@ subfacet_find__(struct ofproto_dpif *ofproto, * subfacet_make_actions(). */ static struct subfacet * subfacet_create(struct facet *facet, enum odp_key_fitness key_fitness, - const struct nlattr *key, size_t key_len, ovs_be16 initial_tci) + const struct nlattr *key, size_t key_len, + ovs_be16 initial_tci, long long int now) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto); uint32_t key_hash = odp_flow_key_hash(key, key_len); @@ -4255,14 +4272,6 @@ subfacet_create(struct facet *facet, enum odp_key_fitness key_fitness, if (list_is_empty(&facet->subfacets)) { subfacet = &facet->one_subfacet; - - /* This subfacet should conceptually be created, and have its first - * packet pass through, at the same time that its facet was created. - * If we called time_msec() here, then the subfacet could look - * (occasionally) as though it was used some time after the facet was - * used. That can make a one-packet flow look like it has a nonzero - * duration, which looks odd in e.g. NetFlow statistics. */ - subfacet->used = facet->used; } else { subfacet = subfacet_find__(ofproto, key, key_len, key_hash, &facet->flow); @@ -4277,7 +4286,6 @@ subfacet_create(struct facet *facet, enum odp_key_fitness key_fitness, } subfacet = xmalloc(sizeof *subfacet); - subfacet->used = time_msec(); } hmap_insert(&ofproto->subfacets, &subfacet->hmap_node, key_hash); @@ -4291,6 +4299,7 @@ subfacet_create(struct facet *facet, enum odp_key_fitness key_fitness, subfacet->key = NULL; subfacet->key_len = 0; } + subfacet->used = now; subfacet->dp_packet_count = 0; subfacet->dp_byte_count = 0; subfacet->actions_len = 0; @@ -4538,7 +4547,6 @@ subfacet_update_stats(struct subfacet *subfacet, static struct rule_dpif * rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow) { - struct ofport_dpif *port; struct rule_dpif *rule; rule = rule_dpif_lookup__(ofproto, flow, 0); @@ -4546,16 +4554,7 @@ rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow) return rule; } - port = get_ofp_port(ofproto, flow->in_port); - if (!port) { - VLOG_WARN_RL(&rl, "packet-in on unknown port %"PRIu16, flow->in_port); - return ofproto->miss_rule; - } - - if (port->up.pp.config & OFPUTIL_PC_NO_PACKET_IN) { - return ofproto->no_packet_in_rule; - } - return ofproto->miss_rule; + return rule_dpif_miss_rule(ofproto, flow); } static struct rule_dpif * @@ -4584,6 +4583,23 @@ rule_dpif_lookup__(struct ofproto_dpif *ofproto, const struct flow *flow, return rule_dpif_cast(rule_from_cls_rule(cls_rule)); } +static struct rule_dpif * +rule_dpif_miss_rule(struct ofproto_dpif *ofproto, const struct flow *flow) +{ + struct ofport_dpif *port; + + port = get_ofp_port(ofproto, flow->in_port); + if (!port) { + VLOG_WARN_RL(&rl, "packet-in on unknown port %"PRIu16, flow->in_port); + return ofproto->miss_rule; + } + + if (port->up.pp.config & OFPUTIL_PC_NO_PACKET_IN) { + return ofproto->no_packet_in_rule; + } + return ofproto->miss_rule; +} + static void complete_operation(struct rule_dpif *rule) { @@ -4708,7 +4724,7 @@ rule_execute(struct rule *rule_, const struct flow *flow, uint64_t odp_actions_stub[1024 / 8]; struct ofpbuf odp_actions; - dpif_flow_stats_extract(flow, packet, &stats); + dpif_flow_stats_extract(flow, packet, time_msec(), &stats); rule_credit_stats(rule, &stats); ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub); @@ -4988,7 +5004,7 @@ compose_output_action(struct action_xlate_ctx *ctx, uint16_t ofp_port) static void xlate_table_action(struct action_xlate_ctx *ctx, - uint16_t in_port, uint8_t table_id) + uint16_t in_port, uint8_t table_id, bool may_packet_in) { if (ctx->recurse < MAX_RESUBMIT_RECURSION) { struct ofproto_dpif *ofproto = ctx->ofproto; @@ -5024,6 +5040,17 @@ xlate_table_action(struct action_xlate_ctx *ctx, ctx->resubmit_hook(ctx, rule); } + if (rule == NULL && may_packet_in) { + /* TODO:XXX + * check if table configuration flags + * OFPTC_TABLE_MISS_CONTROLLER, default. + * OFPTC_TABLE_MISS_CONTINUE, + * OFPTC_TABLE_MISS_DROP + * When OF1.0, OFPTC_TABLE_MISS_CONTINUE is used. What to do? + */ + rule = rule_dpif_miss_rule(ofproto, &ctx->flow); + } + if (rule) { struct rule_dpif *old_rule = ctx->rule; @@ -5065,7 +5092,7 @@ xlate_ofpact_resubmit(struct action_xlate_ctx *ctx, table_id = ctx->table_id; } - xlate_table_action(ctx, in_port, table_id); + xlate_table_action(ctx, in_port, table_id, false); } static void @@ -5182,7 +5209,7 @@ compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_cnt_ids *ids) static void xlate_output_action(struct action_xlate_ctx *ctx, - uint16_t port, uint16_t max_len) + uint16_t port, uint16_t max_len, bool may_packet_in) { uint16_t prev_nf_output_iface = ctx->nf_output_iface; @@ -5193,7 +5220,7 @@ xlate_output_action(struct action_xlate_ctx *ctx, compose_output_action(ctx, ctx->flow.in_port); break; case OFPP_TABLE: - xlate_table_action(ctx, ctx->flow.in_port, 0); + xlate_table_action(ctx, ctx->flow.in_port, 0, may_packet_in); break; case OFPP_NORMAL: xlate_normal(ctx); @@ -5233,7 +5260,7 @@ xlate_output_reg_action(struct action_xlate_ctx *ctx, { uint64_t port = mf_get_subfield(&or->src, &ctx->flow); if (port <= UINT16_MAX) { - xlate_output_action(ctx, port, or->max_len); + xlate_output_action(ctx, port, or->max_len, false); } } @@ -5250,7 +5277,7 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx, error = dpif_queue_to_priority(ctx->ofproto->dpif, queue_id, &priority); if (error) { /* Fall back to ordinary output action. */ - xlate_output_action(ctx, enqueue->port, 0); + xlate_output_action(ctx, enqueue->port, 0, false); return; } @@ -5345,7 +5372,7 @@ xlate_bundle_action(struct action_xlate_ctx *ctx, if (bundle->dst.field) { nxm_reg_load(&bundle->dst, port, &ctx->flow); } else { - xlate_output_action(ctx, port, 0); + xlate_output_action(ctx, port, 0, false); } } @@ -5443,7 +5470,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, switch (a->type) { case OFPACT_OUTPUT: xlate_output_action(ctx, ofpact_get_OUTPUT(a)->port, - ofpact_get_OUTPUT(a)->max_len); + ofpact_get_OUTPUT(a)->max_len, true); break; case OFPACT_CONTROLLER: @@ -6434,7 +6461,7 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet, ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); odp_flow_key_from_flow(&key, flow); - dpif_flow_stats_extract(flow, packet, &stats); + dpif_flow_stats_extract(flow, packet, time_msec(), &stats); action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, NULL, packet_get_tcp_flags(packet, flow), packet);