The userspace CLONE action is now merged to OVS master, so you can rebase the patches to use that.
Jarno > On Jan 24, 2017, at 3:49 AM, Zoltán Balogh <zoltan.bal...@ericsson.com> wrote: > > Hi, > > All right, we will rebase the code once the patch is merged. > > Could you have a look at the code and review it, please? > So we could receive feedback in time. > > Furthermore it would be nice to get some help regarding the failing test > cases. > > 768: tunnel_push_pop - packet_out FAILED > (tunnel-push-pop.at:203) > 2261: ovn -- 3 HVs, 1 LS, 3 lports/HV FAILED (ovn.at:1295) > 2266: ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR FAILED (ovn.at:2468) > 2268: ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs FAILED (ovn.at:2979) > 2298: ovn -- 1 LR with distributed router gateway port FAILED (ovn.at:6480) > > The patches are available here: > https://patchwork.ozlabs.org/patch/717683/ > https://patchwork.ozlabs.org/patch/717681/ > > > Best regards, > Zoltan > > > >> On Jan 22, 2017, at 5:50 AM, Jan Scheurich <jan.scheur...@web.de> wrote: >> =20 >> How does the dpif-netdev CLONE action introduced here relate to the simil= > ar action already introduced in the context of the OpenFLow CLONE action (s= > ee for example https://mail.openvswitch.org/pipermail/ovs-dev/2017-January/= > 327808.html). >> =20 > > OpenFlow level clone action was added a bit earlier, the email you refer to= > is a dpif-netdev level clone action. > >> I assume these do comparable things and the native tunnel implementation = > should re-use the new CLONE action. >> =20 > > This is true. There were other needs for the datapath level clone action, a= > nd once that is merged this patch series should rebase to that. > > Jarno > >> /Jan >> =20 >> On 2017-01-20 14:40, Zolt=E1n Balogh wrote: >>> From: Sugesh Chandran <sugesh.chand...@intel.com> >>> =20 >>> Openvswitch datapath recirculates packets for tunneling, i.e. >>> the incoming packets are encapsulated at first pass. Further actions are >>> applied on encapsulated packets on the second pass after recirculating. >>> The proposed patch compute and append the post tunnel actions at the tim= > e of >>> translation itself instead of recirculating at datapath. These actions a= > re solely >>> depends on tunnel attributes so there is no need of datapath recirculati= > on. >>> By avoiding the recirculation at datapath, the patch offers upto 30% >>> performance improvement for VxLAN tunneling in our testing. >>> The action execution logic is also extended with new CLONE action to def= > ine >>> the packet cloning when the actions are combined. The lenght in the CLON= > E >>> action specifies the size of nested action set. >>> =20 >>> Signed-off-by: Sugesh Chandran <sugesh.chand...@intel.com> >>> Signed-off-by: Zolt=E1n Balogh <zoltan.bal...@ericsson.com> >>> Co-authored-by: Zolt=E1n Balogh <zoltan.bal...@ericsson.com> >>> --- >>> datapath/linux/compat/include/linux/openvswitch.h | 1 + >>> lib/dpif-netdev.c | 20 +- >>> lib/dpif.c | 1 + >>> lib/odp-execute.c | 57 ++++- >>> lib/odp-util.c | 96 +++++++- >>> lib/odp-util.h | 5 + >>> ofproto/ofproto-dpif-sflow.c | 1 + >>> ofproto/ofproto-dpif-xlate.c | 267 +++++++++++----= > ------- >>> 8 files changed, 288 insertions(+), 160 deletions(-) >>> =20 >>> diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapat= > h/linux/compat/include/linux/openvswitch.h >>> index 12260d8..91849d6 100644 >>> --- a/datapath/linux/compat/include/linux/openvswitch.h >>> +++ b/datapath/linux/compat/include/linux/openvswitch.h >>> @@ -818,6 +818,7 @@ enum ovs_action_attr { >>> #ifndef __KERNEL__ >>> =09OVS_ACTION_ATTR_TUNNEL_PUSH, /* struct ovs_action_push_tnl*/ >>> =09OVS_ACTION_ATTR_TUNNEL_POP, /* u32 port number. */ >>> +=09OVS_ACTION_ATTR_CLONE, >>> #endif >>> =09__OVS_ACTION_ATTR_MAX,=09 /* Nothing past this will be accepted >>> =09=09=09=09 * from userspace. */ >>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >>> index 3901129..0b85fe4 100644 >>> --- a/lib/dpif-netdev.c >>> +++ b/lib/dpif-netdev.c >>> @@ -4547,24 +4547,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch = > *packets_, >>> case OVS_ACTION_ATTR_TUNNEL_PUSH: >>> if (*depth < MAX_RECIRC_DEPTH) { >>> - struct dp_packet_batch tnl_pkt; >>> - struct dp_packet_batch *orig_packets_ =3D packets_; >>> - int err; >>> - >>> - if (!may_steal) { >>> - dp_packet_batch_clone(&tnl_pkt, packets_); >>> - packets_ =3D &tnl_pkt; >>> - dp_packet_batch_reset_cutlen(orig_packets_); >>> - } >>> - >>> dp_packet_batch_apply_cutlen(packets_); >>> - >>> - err =3D push_tnl_action(pmd, a, packets_); >>> - if (!err) { >>> - (*depth)++; >>> - dp_netdev_recirculate(pmd, packets_); >>> - (*depth)--; >>> - } >>> + push_tnl_action(pmd, a, packets_); >>> return; >>> } >>> break; >>> @@ -4714,6 +4698,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *= > packets_, >>> break; >>> } >>> + case OVS_ACTION_ATTR_CLONE: >>> + break; >>> case OVS_ACTION_ATTR_PUSH_VLAN: >>> case OVS_ACTION_ATTR_POP_VLAN: >>> case OVS_ACTION_ATTR_PUSH_MPLS: >>> diff --git a/lib/dpif.c b/lib/dpif.c >>> index 50c3382..b698da2 100644 >>> --- a/lib/dpif.c >>> +++ b/lib/dpif.c >>> @@ -1183,6 +1183,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packe= > t_batch *packets_, >>> case OVS_ACTION_ATTR_SAMPLE: >>> case OVS_ACTION_ATTR_TRUNC: >>> case OVS_ACTION_ATTR_UNSPEC: >>> + case OVS_ACTION_ATTR_CLONE: >>> case __OVS_ACTION_ATTR_MAX: >>> OVS_NOT_REACHED(); >>> } >>> diff --git a/lib/odp-execute.c b/lib/odp-execute.c >>> index 73e1016..77bca94 100644 >>> --- a/lib/odp-execute.c >>> +++ b/lib/odp-execute.c >>> @@ -541,6 +541,7 @@ requires_datapath_assistance(const struct nlattr *a) >>> case OVS_ACTION_ATTR_USERSPACE: >>> case OVS_ACTION_ATTR_RECIRC: >>> case OVS_ACTION_ATTR_CT: >>> + case OVS_ACTION_ATTR_CLONE: >>> return true; >>> case OVS_ACTION_ATTR_SET: >>> @@ -562,6 +563,29 @@ requires_datapath_assistance(const struct nlattr *a= > ) >>> return false; >>> } >>> +static inline size_t >>> +find_combine_action_end(const struct nlattr **actions_, size_t *actions= > _len, >>> + const struct nlattr **comb_start, >>> + bool *comb_last_action) >>> +{ >>> + const struct nlattr *a; >>> + const struct nlattr *actions =3D *actions_; >>> + unsigned int left; >>> + bool last_action; >>> + size_t comb_size =3D nl_attr_get_u32(actions); /* Size of combined = > actions */ >>> + *actions_len -=3D NLA_ALIGN(actions->nla_len); >>> + actions =3D nl_attr_next(actions); >>> + >>> + *comb_start =3D actions; >>> + a =3D (void *) ((uint8_t *) actions + NLA_ALIGN(comb_size)); >>> + left =3D (*actions_len) - comb_size; >>> + last_action =3D (left <=3D NLA_ALIGN(a->nla_len)); >>> + *actions_ =3D a; >>> + *comb_last_action =3D last_action ? true : false; >>> + *actions_len =3D left; >>> + return comb_size; >>> +} >>> + >>> void >>> odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal= > , >>> const struct nlattr *actions, size_t actions_len, >>> @@ -570,7 +594,7 @@ odp_execute_actions(void *dp, struct dp_packet_batch= > *batch, bool steal, >>> struct dp_packet **packets =3D batch->packets; >>> int cnt =3D batch->count; >>> const struct nlattr *a; >>> - unsigned int left; >>> + size_t left; >>> int i; >>> NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) { >>> @@ -582,7 +606,35 @@ odp_execute_actions(void *dp, struct dp_packet_batc= > h *batch, bool steal, >>> /* Allow 'dp_execute_action' to steal the packet data i= > f we do >>> * not need it any more. */ >>> bool may_steal =3D steal && last_action; >>> - >>> + if ((enum ovs_action_attr) type =3D=3D >>> + OVS_ACTION_ATTR_CLONE) { >>> + size_t comb_action_len; >>> + const struct nlattr *comb_actions =3D NULL; >>> + bool comb_last_action =3D true; >>> + comb_action_len =3D find_combine_action_end(&a, &le= > ft, >>> + &comb_actio= > ns, >>> + &comb_last_= > action); >>> + if (OVS_UNLIKELY(!comb_action_len)) { >>> + /* No combine present, execute current action *= > / >>> + goto execute; >>> + } >>> + if (OVS_LIKELY(comb_last_action)) { >>> + odp_execute_actions(dp, batch, 1, comb_actions, >>> + comb_action_len, dp_execute_act= > ion); >>> + return; >>> + } >>> + else { >>> + /* Packets to be duplicated for the sub action = > */ >>> + struct dp_packet_batch comb_pkt_batch; >>> + dp_packet_batch_clone(&comb_pkt_batch, batch); >>> + dp_packet_batch_reset_cutlen(batch); >>> + odp_execute_actions(dp, &comb_pkt_batch, steal, >>> + comb_actions, comb_action_len, >>> + dp_execute_action); >>> + } >>> + continue; >>> + } >>> +execute: >>> dp_execute_action(dp, batch, a, may_steal); >>> if (last_action) { >>> @@ -692,6 +744,7 @@ odp_execute_actions(void *dp, struct dp_packet_batch= > *batch, bool steal, >>> case OVS_ACTION_ATTR_RECIRC: >>> case OVS_ACTION_ATTR_CT: >>> case OVS_ACTION_ATTR_UNSPEC: >>> + case OVS_ACTION_ATTR_CLONE: >>> case __OVS_ACTION_ATTR_MAX: >>> OVS_NOT_REACHED(); >>> } >>> diff --git a/lib/odp-util.c b/lib/odp-util.c >>> index 1e70e3a..4a311d9 100644 >>> --- a/lib/odp-util.c >>> +++ b/lib/odp-util.c >>> @@ -121,6 +121,7 @@ odp_action_len(uint16_t type) >>> case OVS_ACTION_ATTR_SET_MASKED: return ATTR_LEN_VARIABLE; >>> case OVS_ACTION_ATTR_SAMPLE: return ATTR_LEN_VARIABLE; >>> case OVS_ACTION_ATTR_CT: return ATTR_LEN_VARIABLE; >>> + case OVS_ACTION_ATTR_CLONE: return sizeof(uint32_t); >>> case OVS_ACTION_ATTR_UNSPEC: >>> case __OVS_ACTION_ATTR_MAX: >>> @@ -509,7 +510,7 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs= > _action_push_tnl *data) >>> gnh->oam ? "oam," : "", >>> gnh->critical ? "crit," : "", >>> ntohl(get_16aligned_be32(&gnh->vni)) >> 8); >>> - >>> + >>> if (gnh->opt_len) { >>> ds_put_cstr(ds, ",options("); >>> format_geneve_opts(gnh->options, NULL, gnh->opt_len * 4, >>> @@ -865,6 +866,14 @@ format_odp_action(struct ds *ds, const struct nlatt= > r *a) >>> case OVS_ACTION_ATTR_CT: >>> format_odp_conntrack_action(ds, a); >>> break; >>> + case OVS_ACTION_ATTR_CLONE: { >>> + uint32_t comb_len; >>> + comb_len =3D nl_attr_get_u32(a); >>> + if (comb_len) { >>> + ds_put_cstr(ds,"{"); >>> + } >>> + break; >>> + } >>> case OVS_ACTION_ATTR_UNSPEC: >>> case __OVS_ACTION_ATTR_MAX: >>> default: >>> @@ -873,27 +882,81 @@ format_odp_action(struct ds *ds, const struct nlat= > tr *a) >>> } >>> } >>> +static void >>> +print_odp_actions(struct ds *ds, bool is_first_action, >>> + const struct nlattr **action_, >>> + size_t *action_len, size_t clone_len, b= > ool is_clone_ctx) >>> +{ >>> + >>> + enum ovs_action_attr type; >>> + const struct nlattr *action =3D *action_; >>> + const struct nlattr *curr_action =3D action; >>> + size_t curr_action_len; >>> + >>> + if (!nl_attr_is_valid(action, *action_len)) { >>> + return; >>> + } >>> + curr_action_len =3D nl_attr_len_pad(action, *action_len); >>> + type =3D nl_attr_type(action); >>> + if(!is_first_action) { >>> + ds_put_char(ds, ','); >>> + } >>> + else { >>> + /* Next iteration onwards, its not first action anymore. Reset = > flag >>> + * accordingly. >>> + */ >>> + is_first_action =3D 0; >>> + } >>> + >>> + format_odp_action(ds, action); >>> + >>> + action =3D nl_attr_next(action); >>> + *action_ =3D action; >>> + *action_len -=3D curr_action_len; >>> + if (type =3D=3D OVS_ACTION_ATTR_CLONE) { >>> + uint32_t comb_len; >>> + comb_len =3D nl_attr_get_u32(curr_action); >>> + if (comb_len) { >>> + print_odp_actions(ds, 1, action_, action_len, >>> + comb_len, true); >>> + ds_put_char(ds, '}'); >>> + } >>> + else { >>> + return;/* Error, cannot print anything. */ >>> + } >>> + } >>> + if (is_clone_ctx) { >>> + if(!clone_len) { >>> + return; >>> + } >>> + else { >>> + clone_len =3D (clone_len >=3D curr_action_len) ? >>> + clone_len - curr_action_len : >>> + 0; >>> + } >>> + } >>> + print_odp_actions(ds, is_first_action, action_, action_len, clone_l= > en, >>> + is_clone_ctx); >>> +} >>> + >>> void >>> format_odp_actions(struct ds *ds, const struct nlattr *actions, >>> size_t actions_len) >>> { >>> if (actions_len) { >>> const struct nlattr *a; >>> - unsigned int left; >>> + size_t left; >>> - NL_ATTR_FOR_EACH (a, left, actions, actions_len) { >>> - if (a !=3D actions) { >>> - ds_put_char(ds, ','); >>> - } >>> - format_odp_action(ds, a); >>> - } >>> + a =3D actions; >>> + left =3D actions_len; >>> + print_odp_actions(ds, 1, &a, &left, 0, false); >>> if (left) { >>> int i; >>> if (left =3D=3D actions_len) { >>> ds_put_cstr(ds, "<empty>"); >>> } >>> - ds_put_format(ds, ",***%u leftover bytes*** (", left); >>> + ds_put_format(ds, ",***%"PRIuSIZE" leftover bytes*** (", le= > ft); >>> for (i =3D 0; i < left; i++) { >>> ds_put_format(ds, "%02x", ((const uint8_t *) a)[i]); >>> } >>> @@ -5321,6 +5384,21 @@ odp_put_tunnel_action(const struct flow_tnl *tunn= > el, >>> } >>> void >>> +odp_put_combine_start_action(struct ofpbuf *odp_actions, uint32_t actio= > n_len) >>> +{ >>> + nl_msg_put_u32(odp_actions, OVS_ACTION_ATTR_CLONE, action_len); >>> +} >>> + >>> +void >>> +odp_update_combine_start_action(struct nlattr *start_combine, >>> + uint32_t combine_size) >>> +{ >>> + uint32_t *combine_len; >>> + combine_len =3D (uint32_t *)(start_combine + 1); >>> + *combine_len =3D combine_size; >>> +} >>> + >>> +void >>> odp_put_tnl_push_action(struct ofpbuf *odp_actions, >>> struct ovs_action_push_tnl *data) >>> { >>> diff --git a/lib/odp-util.h b/lib/odp-util.h >>> index 42011bc..a32dc76 100644 >>> --- a/lib/odp-util.h >>> +++ b/lib/odp-util.h >>> @@ -308,4 +308,9 @@ void odp_put_tunnel_action(const struct flow_tnl *tu= > nnel, >>> void odp_put_tnl_push_action(struct ofpbuf *odp_actions, >>> struct ovs_action_push_tnl *data); >>> +void odp_put_combine_start_action(struct ofpbuf *odp_actions, >>> + uint32_t action_len); >>> +void >>> +odp_update_combine_start_action(struct nlattr *start_combine, >>> + uint32_t combine_size); >>> #endif /* odp-util.h */ >>> diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c >>> index 37992b4..8d51374 100644 >>> --- a/ofproto/ofproto-dpif-sflow.c >>> +++ b/ofproto/ofproto-dpif-sflow.c >>> @@ -1163,6 +1163,7 @@ dpif_sflow_read_actions(const struct flow *flow, >>> =09} >>> =09case OVS_ACTION_ATTR_SAMPLE: >>> =09case OVS_ACTION_ATTR_UNSPEC: >>> + case OVS_ACTION_ATTR_CLONE: >>> =09case __OVS_ACTION_ATTR_MAX: >>> =09default: >>> =09 break; >>> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c >>> index 9a15ec3..ded0932 100644 >>> --- a/ofproto/ofproto-dpif-xlate.c >>> +++ b/ofproto/ofproto-dpif-xlate.c >>> @@ -408,6 +408,10 @@ static void xlate_action_set(struct xlate_ctx *ctx)= > ; >>> static void xlate_commit_actions(struct xlate_ctx *ctx); >>> static void >>> +group_actions(struct xlate_ctx *ctx, const struct xport *in_dev, >>> + struct xport *out_dev); >>> + >>> +static void >>> ctx_trigger_freeze(struct xlate_ctx *ctx) >>> { >>> ctx->exit =3D true; >>> @@ -3029,7 +3033,23 @@ build_tunnel_send(struct xlate_ctx *ctx, const st= > ruct xport *xport, >>> } >>> tnl_push_data.tnl_port =3D odp_to_u32(tunnel_odp_port); >>> tnl_push_data.out_port =3D odp_to_u32(out_dev->odp_port); >>> + >>> + struct nlattr *start_combine; >>> + uint32_t action_size =3D 0; >>> + uint32_t start_action_size =3D 0; >>> + uint32_t push_action_size =3D 0; >>> + start_action_size =3D ctx->odp_actions->size; >>> + odp_put_combine_start_action(ctx->odp_actions, 0); >>> + action_size =3D ctx->odp_actions->size; >>> odp_put_tnl_push_action(ctx->odp_actions, &tnl_push_data); >>> + push_action_size =3D ctx->odp_actions->size; >>> + group_actions(ctx, xport, out_dev); >>> + start_combine =3D ofpbuf_at(ctx->odp_actions, start_action_size, (N= > LA_HDRLEN)); >>> + if (ctx->odp_actions->size > push_action_size) { >>> + /* Update the combine action only when combined */ >>> + odp_update_combine_start_action(start_combine, >>> + (ctx->odp_actions->size - action_si= > ze)); >>> + } >>> return 0; >>> } >>> @@ -3071,6 +3091,119 @@ xlate_flow_is_protected(const struct xlate_ctx = > *ctx, const struct flow *flow, co >>> } >>> static void >>> +group_actions(struct xlate_ctx *ctx, const struct xport *in_dev, >>> + struct xport *out_dev) >>> +{ >>> + struct flow *flow =3D &ctx->xin->flow; >>> + struct flow old_flow =3D ctx->xin->flow; >>> + struct flow_tnl old_flow_tnl_wc =3D ctx->wc->masks.tunnel; >>> + bool old_conntrack =3D ctx->conntracked; >>> + bool old_was_mpls =3D ctx->was_mpls; >>> + ovs_version_t old_version =3D ctx->xin->tables_version; >>> + struct ofpbuf old_stack =3D ctx->stack; >>> + union mf_subvalue new_stack[1024 / sizeof(union mf_subvalue)]; >>> + struct ofpbuf old_action_set =3D ctx->action_set; >>> + uint64_t actset_stub[1024 / 8]; >>> + >>> + ofpbuf_use_stub(&ctx->stack, new_stack, sizeof new_stack); >>> + ofpbuf_use_stub(&ctx->action_set, actset_stub, sizeof actset_stub); >>> + flow->in_port.ofp_port =3D out_dev->ofp_port; >>> + flow->metadata =3D htonll(0); >>> + memset(&flow->tunnel, 0, sizeof flow->tunnel); >>> + memset(&ctx->wc->masks.tunnel, 0, sizeof ctx->wc->masks.tunnel); >>> + flow->tunnel.metadata.tab =3D ofproto_get_tun_tab(&out_dev->xbridge= > ->ofproto->up); >>> + ctx->wc->masks.tunnel.metadata.tab =3D flow->tunnel.metadata.tab; >>> + memset(flow->regs, 0, sizeof flow->regs); >>> + flow->actset_output =3D OFPP_UNSET; >>> + ctx->conntracked =3D false; >>> + clear_conntrack(ctx); >>> + mirror_mask_t old_mirrors =3D ctx->mirrors; >>> + bool independent_mirrors =3D out_dev->xbridge !=3D ctx->xbridge; >>> + if (independent_mirrors) { >>> + ctx->mirrors =3D 0; >>> + } >>> + ctx->xbridge =3D out_dev->xbridge; >>> + >>> + /* The bridge is now known so obtain its table version. */ >>> + ctx->xin->tables_version >>> + =3D ofproto_dpif_get_tables_version(ctx->xbridge->ofproto= > ); >>> + >>> + if (!process_special(ctx, out_dev) && may_receive(out_dev, ctx)) { >>> + if (xport_stp_forward_state(out_dev) && xport_rstp_forward_stat= > e(out_dev)) { >>> + xlate_table_action(ctx, flow->in_port.ofp_port, 0, true= > , true); >>> + if (!ctx->freezing) { >>> + xlate_action_set(ctx); >>> + } >>> + if (ctx->freezing) { >>> + finish_freezing(ctx); >>> + } >>> + } else { >>> + /* Forwarding is disabled by STP and RSTP. Let OFPP_NORMAL= > and >>> + * the learning action look at the packet, then drop it. */ >>> + struct flow old_base_flow =3D ctx->base_flow; >>> + size_t old_size =3D ctx->odp_actions->size; >>> + mirror_mask_t old_mirrors2 =3D ctx->mirrors; >>> + >>> + xlate_table_action(ctx, flow->in_port.ofp_port, 0, true, tr= > ue); >>> + ctx->mirrors =3D old_mirrors2; >>> + ctx->base_flow =3D old_base_flow; >>> + ctx->odp_actions->size =3D old_size; >>> + >>> + /* Undo changes that may have been done for freezing. */ >>> + ctx_cancel_freeze(ctx); >>> + } >>> + } >>> + >>> + if (independent_mirrors) { >>> + ctx->mirrors =3D old_mirrors; >>> + } >>> + ctx->xin->flow =3D old_flow; >>> + ctx->xbridge =3D in_dev->xbridge; >>> + ofpbuf_uninit(&ctx->action_set); >>> + ctx->action_set =3D old_action_set; >>> + ofpbuf_uninit(&ctx->stack); >>> + ctx->stack =3D old_stack; >>> + >>> + /* Restore calling bridge's lookup version. */ >>> + ctx->xin->tables_version =3D old_version; >>> + >>> + /* Restore to calling bridge tunneling information */ >>> + ctx->wc->masks.tunnel =3D old_flow_tnl_wc; >>> + >>> + /* The out bridge popping MPLS should have no effect on the origina= > l >>> + * bridge. */ >>> + ctx->was_mpls =3D old_was_mpls; >>> + >>> + /* The out bridge's conntrack execution should have no effect on th= > e >>> + * original bridge. */ >>> + ctx->conntracked =3D old_conntrack; >>> + >>> + /* The fact that the out bridge exits (for any reason) does not mea= > n >>> + * that the original bridge should exit. Specifically, if the out >>> + * bridge freezes translation, the original bridge must continue >>> + * processing with the original, not the frozen packet! */ >>> + ctx->exit =3D false; >>> + >>> + /* Out bridge errors do not propagate back. */ >>> + ctx->error =3D XLATE_OK; >>> + >>> + if (ctx->xin->resubmit_stats) { >>> + netdev_vport_inc_tx(in_dev->netdev, ctx->xin->resubmit_stats); >>> + netdev_vport_inc_rx(out_dev->netdev, ctx->xin->resubmit_stats); >>> + if (out_dev->bfd) { >>> + bfd_account_rx(out_dev->bfd, ctx->xin->resubmit_stats); >>> + } >>> + } >>> + if (ctx->xin->xcache) { >>> + struct xc_entry *entry; >>> + entry =3D xlate_cache_add_entry(ctx->xin->xcache, XC_NETDEV); >>> + entry->dev.tx =3D netdev_ref(in_dev->netdev); >>> + entry->dev.rx =3D netdev_ref(out_dev->netdev); >>> + entry->dev.bfd =3D bfd_ref(out_dev->bfd); >>> + } >>> +} >>> + >>> +static void >>> compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, >>> const struct xlate_bond_recirc *xr, bool check_= > stp) >>> { >>> @@ -3133,138 +3266,8 @@ compose_output_action__(struct xlate_ctx *ctx, o= > fp_port_t ofp_port, >>> } >>> if (xport->peer) { >>> - const struct xport *peer =3D xport->peer; >>> - struct flow old_flow =3D ctx->xin->flow; >>> - struct flow_tnl old_flow_tnl_wc =3D ctx->wc->masks.tunnel; >>> - bool old_conntrack =3D ctx->conntracked; >>> - bool old_was_mpls =3D ctx->was_mpls; >>> - ovs_version_t old_version =3D ctx->xin->tables_version; >>> - struct ofpbuf old_stack =3D ctx->stack; >>> - uint8_t new_stack[1024]; >>> - struct ofpbuf old_action_set =3D ctx->action_set; >>> - struct ovs_list *old_trace =3D ctx->xin->trace; >>> - uint64_t actset_stub[1024 / 8]; >>> - >>> - ofpbuf_use_stub(&ctx->stack, new_stack, sizeof new_stack); >>> - ofpbuf_use_stub(&ctx->action_set, actset_stub, sizeof actset_st= > ub); >>> - flow->in_port.ofp_port =3D peer->ofp_port; >>> - flow->metadata =3D htonll(0); >>> - memset(&flow->tunnel, 0, sizeof flow->tunnel); >>> - flow->tunnel.metadata.tab =3D ofproto_get_tun_tab( >>> - &peer->xbridge->ofproto->up); >>> - ctx->wc->masks.tunnel.metadata.tab =3D flow->tunnel.metadata.ta= > b; >>> - memset(flow->regs, 0, sizeof flow->regs); >>> - flow->actset_output =3D OFPP_UNSET; >>> - clear_conntrack(ctx); >>> - ctx->xin->trace =3D xlate_report(ctx, OFT_BRIDGE, >>> - "bridge(\"%s\")", peer->xbridge-= >> name); >>> - >>> - /* When the patch port points to a different bridge, then the m= > irrors >>> - * for that bridge clearly apply independently to the packet, s= > o we >>> - * reset the mirror bitmap to zero and then restore it after th= > e packet >>> - * returns. >>> - * >>> - * When the patch port points to the same bridge, this is more = > of a >>> - * design decision: can mirrors be re-applied to the packet aft= > er it >>> - * re-enters the bridge, or should we treat that as doubly mirr= > oring a >>> - * single packet? The former may be cleaner, since it respects= > the >>> - * model in which a patch port is like a physical cable plugged= > from >>> - * one switch port to another, but the latter may be less surpr= > ising to >>> - * users. We take the latter choice, for now at least. (To us= > e the >>> - * former choice, hard-code 'independent_mirrors' to "true".) *= > / >>> - mirror_mask_t old_mirrors =3D ctx->mirrors; >>> - bool independent_mirrors =3D peer->xbridge !=3D ctx->xbridge; >>> - if (independent_mirrors) { >>> - ctx->mirrors =3D 0; >>> - } >>> - ctx->xbridge =3D peer->xbridge; >>> - >>> - /* The bridge is now known so obtain its table version. */ >>> - ctx->xin->tables_version >>> - =3D ofproto_dpif_get_tables_version(ctx->xbridge->ofproto); >>> - >>> - if (!process_special(ctx, peer) && may_receive(peer, ctx)) { >>> - if (xport_stp_forward_state(peer) && xport_rstp_forward_sta= > te(peer)) { >>> - xlate_table_action(ctx, flow->in_port.ofp_port, 0, true= > , true); >>> - if (!ctx->freezing) { >>> - xlate_action_set(ctx); >>> - } >>> - if (ctx->freezing) { >>> - finish_freezing(ctx); >>> - } >>> - } else { >>> - /* Forwarding is disabled by STP and RSTP. Let OFPP_NO= > RMAL and >>> - * the learning action look at the packet, then drop it= > . */ >>> - struct flow old_base_flow =3D ctx->base_flow; >>> - size_t old_size =3D ctx->odp_actions->size; >>> - mirror_mask_t old_mirrors2 =3D ctx->mirrors; >>> - >>> - xlate_table_action(ctx, flow->in_port.ofp_port, 0, true= > , true); >>> - ctx->mirrors =3D old_mirrors2; >>> - ctx->base_flow =3D old_base_flow; >>> - ctx->odp_actions->size =3D old_size; >>> - >>> - /* Undo changes that may have been done for freezing. *= > / >>> - ctx_cancel_freeze(ctx); >>> - } >>> - } >>> - >>> - ctx->xin->trace =3D old_trace; >>> - if (independent_mirrors) { >>> - ctx->mirrors =3D old_mirrors; >>> - } >>> - ctx->xin->flow =3D old_flow; >>> - ctx->xbridge =3D xport->xbridge; >>> - ofpbuf_uninit(&ctx->action_set); >>> - ctx->action_set =3D old_action_set; >>> - ofpbuf_uninit(&ctx->stack); >>> - ctx->stack =3D old_stack; >>> - >>> - /* Restore calling bridge's lookup version. */ >>> - ctx->xin->tables_version =3D old_version; >>> - >>> - /* Since this packet came in on a patch port (from the perspect= > ive of >>> - * the peer bridge), it cannot have useful tunnel information. = > As a >>> - * result, any wildcards generated on that tunnel also cannot b= > e valid. >>> - * The tunnel wildcards must be restored to their original vers= > ion since >>> - * the peer bridge uses a separate tunnel metadata table and th= > erefore >>> - * any generated wildcards will be garbage in the context of ou= > r >>> - * metadata table. */ >>> - ctx->wc->masks.tunnel =3D old_flow_tnl_wc; >>> - >>> - /* The peer bridge popping MPLS should have no effect on the or= > iginal >>> - * bridge. */ >>> - ctx->was_mpls =3D old_was_mpls; >>> - >>> - /* The peer bridge's conntrack execution should have no effect = > on the >>> - * original bridge. */ >>> - ctx->conntracked =3D old_conntrack; >>> - >>> - /* The fact that the peer bridge exits (for any reason) does no= > t mean >>> - * that the original bridge should exit. Specifically, if the = > peer >>> - * bridge freezes translation, the original bridge must continu= > e >>> - * processing with the original, not the frozen packet! */ >>> - ctx->exit =3D false; >>> - >>> - /* Peer bridge errors do not propagate back. */ >>> - ctx->error =3D XLATE_OK; >>> - >>> - if (ctx->xin->resubmit_stats) { >>> - netdev_vport_inc_tx(xport->netdev, ctx->xin->resubmit_stats= > ); >>> - netdev_vport_inc_rx(peer->netdev, ctx->xin->resubmit_stats)= > ; >>> - if (peer->bfd) { >>> - bfd_account_rx(peer->bfd, ctx->xin->resubmit_stats); >>> - } >>> - } >>> - if (ctx->xin->xcache) { >>> - struct xc_entry *entry; >>> - >>> - entry =3D xlate_cache_add_entry(ctx->xin->xcache, XC_NETDEV= > ); >>> - entry->dev.tx =3D netdev_ref(xport->netdev); >>> - entry->dev.rx =3D netdev_ref(peer->netdev); >>> - entry->dev.bfd =3D bfd_ref(peer->bfd); >>> - } >>> - return; >>> + group_actions(ctx, xport, xport->peer); >>> + return; >>> } >>> flow_vlan_tci =3D flow->vlan_tci; >> =20 >> _______________________________________________ >> dev mailing list >> d...@openvswitch.org >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev