[ovs-dev] [PATCH v2 1/2] tunneling: Avoid recirculation on datapath by computing the recirculate actions at translate time.
Zoltán Balogh
zoltan.balogh at ericsson.com
Tue Jan 24 11:49:42 UTC 2017
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.scheurich at 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.chandran at 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.chandran at intel.com>
>> Signed-off-by: Zolt=E1n Balogh <zoltan.balogh at ericsson.com>
>> Co-authored-by: Zolt=E1n Balogh <zoltan.balogh at 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
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
_______________________________________________
dev mailing list
dev at openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev
More information about the dev
mailing list