Extend 'may_learn' attribute to also control the treatment of FIN_TIMEOUT action and asynchronous messages (packet ins, continuations), so that when 'may_learn' is 'false' and 'resubmit_stats' is 'NULL', no OpenFlow-visible side effects are generated by the translation.
Correspondingly, add support for one-time asynchronous messages to xlate cache, so that all side-effects of the translation may be executed at a later stage. This will be useful for bundle commits. Signed-off-by: Jarno Rajahalme <ja...@ovn.org> --- ofproto/ofproto-dpif-xlate.c | 53 +++++++++++++++++++++++++++++++++++++++----- ofproto/ofproto-dpif-xlate.h | 12 +++++++--- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 2683464..83fdff7 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3595,6 +3595,10 @@ execute_controller_action(struct xlate_ctx *ctx, int len, return; } + if (!ctx->xin->may_learn && !ctx->xin->xcache) { + return; + } + packet = dp_packet_clone(ctx->xin->packet); packet_batch_init_packet(&batch, packet); odp_execute_actions(NULL, &batch, false, @@ -3633,13 +3637,26 @@ execute_controller_action(struct xlate_ctx *ctx, int len, }; flow_get_metadata(&ctx->xin->flow, &am->pin.up.public.flow_metadata); - ofproto_dpif_send_async_msg(ctx->xbridge->ofproto, am); - dp_packet_delete(packet); + /* Async messages are only sent once, so if we send one now, no + * xlate cache entry is created. */ + if (ctx->xin->may_learn) { + ofproto_dpif_send_async_msg(ctx->xbridge->ofproto, am); + } else /* xcache */ { + struct xc_entry *entry; + + entry = xlate_cache_add_entry(ctx->xin->xcache, XC_CONTROLLER); + entry->u.controller.ofproto = ctx->xbridge->ofproto; + entry->u.controller.am = am; + } } static void emit_continuation(struct xlate_ctx *ctx, const struct frozen_state *state) { + if (!ctx->xin->may_learn && !ctx->xin->xcache) { + return; + } + struct ofproto_async_msg *am = xmalloc(sizeof *am); *am = (struct ofproto_async_msg) { .controller_id = ctx->pause->controller_id, @@ -3671,7 +3688,18 @@ emit_continuation(struct xlate_ctx *ctx, const struct frozen_state *state) }, }; flow_get_metadata(&ctx->xin->flow, &am->pin.up.public.flow_metadata); - ofproto_dpif_send_async_msg(ctx->xbridge->ofproto, am); + + /* Async messages are only sent once, so if we send one now, no + * xlate cache entry is created. */ + if (ctx->xin->may_learn) { + ofproto_dpif_send_async_msg(ctx->xbridge->ofproto, am); + } else /* xcache */ { + struct xc_entry *entry; + + entry = xlate_cache_add_entry(ctx->xin->xcache, XC_CONTROLLER); + entry->u.controller.ofproto = ctx->xbridge->ofproto; + entry->u.controller.am = am; + } } static void @@ -4121,8 +4149,10 @@ xlate_fin_timeout(struct xlate_ctx *ctx, const struct ofpact_fin_timeout *oft) { if (ctx->rule) { - xlate_fin_timeout__(ctx->rule, ctx->xin->tcp_flags, - oft->fin_idle_timeout, oft->fin_hard_timeout); + if (ctx->xin->may_learn) { + xlate_fin_timeout__(ctx->rule, ctx->xin->tcp_flags, + oft->fin_idle_timeout, oft->fin_hard_timeout); + } if (ctx->xin->xcache) { struct xc_entry *entry; @@ -5810,6 +5840,13 @@ xlate_push_stats_entry(struct xc_entry *entry, tnl_neigh_lookup(entry->u.tnl_neigh_cache.br_name, &entry->u.tnl_neigh_cache.d_ipv6, &dmac); break; + case XC_CONTROLLER: + if (entry->u.controller.am) { + ofproto_dpif_send_async_msg(entry->u.controller.ofproto, + entry->u.controller.am); + entry->u.controller.am = NULL; /* One time only. */ + } + break; default: OVS_NOT_REACHED(); } @@ -5890,6 +5927,12 @@ xlate_cache_clear_entry(struct xc_entry *entry) break; case XC_TNL_NEIGH: break; + case XC_CONTROLLER: + if (entry->u.controller.am) { + ofproto_async_msg_free(entry->u.controller.am); + entry->u.controller.am = NULL; + } + break; default: OVS_NOT_REACHED(); } diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 7faa199..14d81f6 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -43,11 +43,12 @@ enum xc_type { XC_NETDEV, XC_NETFLOW, XC_MIRROR, - XC_LEARN, + XC_LEARN, /* Calls back to ofproto. */ XC_NORMAL, - XC_FIN_TIMEOUT, + XC_FIN_TIMEOUT, /* Calls back to ofproto. */ XC_GROUP, XC_TNL_NEIGH, + XC_CONTROLLER, }; /* xlate_cache entries hold enough information to perform the side effects of @@ -104,6 +105,10 @@ struct xc_entry { char br_name[IFNAMSIZ]; struct in6_addr d_ipv6; } tnl_neigh_cache; + struct { + struct ofproto_dpif *ofproto; + struct ofproto_async_msg *am; + } controller; } u; }; @@ -135,7 +140,8 @@ struct xlate_in { const struct dp_packet *packet; /* Should OFPP_NORMAL update the MAC learning table? Should "learn" - * actions update the flow table? + * actions update the flow table? Should FIN_TIMEOUT change the + * timeouts? Or should controller action send packet to the controller? * * We want to update these tables if we are actually processing a packet, * or if we are accounting for packets that the datapath has processed, but -- 2.1.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev