[ovs-dev] [PATCH v2 1/2] tunneling: Avoid recirculation on datapath by computing the recirculate actions at translate time.

Jarno Rajahalme jarno at ovn.org
Tue Jan 24 20:59:24 UTC 2017


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.balogh at 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.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