Alex and I had an off-line discussion. He will post a simpler version
of the patch soon.

On Fri, Dec 12, 2014 at 1:53 AM, Alex Wang <al...@nicira.com> wrote:
> Sorry, forgot to mention that this patch targets branch-2.3,
>
> Haven't tried, but should also be applicable to master~
>
> On Fri, Dec 12, 2014 at 1:55 AM, Alex Wang <al...@nicira.com> wrote:
>>
>> In current recirculation implementation, the flow misses (with
>> 'recirc_id' set) are always looked up on the receiving bridge's
>> internal flow table.  However, the bond port may actually reside
>> on another bridge which gets connected to the receiving bridge
>> via patch port.  Since the recirculation rules are pushed to the
>> other bridge's internal table, the flow lookup on the receiving
>> bridge will match nothing but the drop rule, causing unexpected
>> packet drops.
>>
>> This commit fixes the above bug via changing the lookup logic
>> such that the internal flow table is checked only when flow
>> miss handling reaches the bridge (ofproto) which owns the bond
>> port.
>>
>> VMware-BZ: 1362178
>>
>> Reported-by: Ansis Atteka <aatt...@nicira.com>
>> Signed-off-by: Alex Wang <al...@nicira.com>
>> ---
>>  ofproto/bond.c               |   25 +++++++++++++++++++++++++
>>  ofproto/bond.h               |    1 +
>>  ofproto/ofproto-dpif-xlate.c |   14 ++++++++++++--
>>  ofproto/ofproto-dpif.c       |   19 ++++++++++---------
>>  4 files changed, 48 insertions(+), 11 deletions(-)
>>
>> diff --git a/ofproto/bond.c b/ofproto/bond.c
>> index 44e9df1..93b28f8 100644
>> --- a/ofproto/bond.c
>> +++ b/ofproto/bond.c
>> @@ -946,6 +946,31 @@ bond_may_recirc(const struct bond *bond, uint32_t
>> *recirc_id,
>>      }
>>  }
>>
>> +/* Given the unique 'recirc_id', finds the corresponding 'bond' and
>> + * returns the 'bond->ofproto'. */
>> +struct ofproto_dpif *
>> +bond_get_ofproto_by_recirc_id(uint32_t recirc_id)
>> +{
>> +    struct bond *bond;
>> +
>> +    if (!recirc_id) {
>> +        goto err;
>> +    }
>> +
>> +    ovs_rwlock_rdlock(&rwlock);
>> +    HMAP_FOR_EACH (bond, hmap_node, all_bonds) {
>> +        if (bond->recirc_id == recirc_id) {
>> +            ovs_rwlock_unlock(&rwlock);
>> +
>> +            return bond->ofproto;
>> +        }
>> +    }
>> +    ovs_rwlock_unlock(&rwlock);
>> +
>> +err:
>> +    return NULL;
>> +}
>> +
>>  void
>>  bond_update_post_recirc_rules(struct bond* bond, const bool force)
>>  {
>> diff --git a/ofproto/bond.h b/ofproto/bond.h
>> index d7cb715..b03eadf 100644
>> --- a/ofproto/bond.h
>> +++ b/ofproto/bond.h
>> @@ -124,4 +124,5 @@ void bond_rebalance(struct bond *);
>>  void bond_update_post_recirc_rules(struct bond *, const bool force);
>>  bool bond_may_recirc(const struct bond *, uint32_t *recirc_id,
>>                       uint32_t *hash_bias);
>> +struct ofproto_dpif *bond_get_ofproto_by_recirc_id(uint32_t recirc_id);
>>  #endif /* bond.h */
>> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
>> index 4f77ac5..de9fa70 100644
>> --- a/ofproto/ofproto-dpif-xlate.c
>> +++ b/ofproto/ofproto-dpif-xlate.c
>> @@ -1846,8 +1846,16 @@ compose_output_action__(struct xlate_ctx *ctx,
>> ofp_port_t ofp_port,
>>          const struct xport *peer = xport->peer;
>>          struct flow old_flow = ctx->xin->flow;
>>          enum slow_path_reason special;
>> +        uint8_t table_id = 0;
>>
>>          ctx->xbridge = peer->xbridge;
>> +        /* If 'recirc_id' is set and 'ofproto' is the same as the bond's
>> +         * 'ofproto', starts the look up from internal table. */
>> +        if (flow->recirc_id
>> +            && (peer->xbridge->ofproto
>> +                == bond_get_ofproto_by_recirc_id(flow->recirc_id))) {
>> +            table_id = TBL_INTERNAL;
>> +        }
>>          flow->in_port.ofp_port = peer->ofp_port;
>>          flow->metadata = htonll(0);
>>          memset(&flow->tunnel, 0, sizeof flow->tunnel);
>> @@ -1859,14 +1867,16 @@ compose_output_action__(struct xlate_ctx *ctx,
>> ofp_port_t ofp_port,
>>              ctx->xout->slow |= special;
>>          } else if (may_receive(peer, ctx)) {
>>              if (xport_stp_forward_state(peer)) {
>> -                xlate_table_action(ctx, flow->in_port.ofp_port, 0, true,
>> true);
>> +                xlate_table_action(ctx, flow->in_port.ofp_port, table_id,
>> +                                   true, true);
>>              } else {
>>                  /* Forwarding is disabled by STP.  Let OFPP_NORMAL and
>> the
>>                   * learning action look at the packet, then drop it. */
>>                  struct flow old_base_flow = ctx->base_flow;
>>                  size_t old_size = ofpbuf_size(&ctx->xout->odp_actions);
>>                  mirror_mask_t old_mirrors = ctx->xout->mirrors;
>> -                xlate_table_action(ctx, flow->in_port.ofp_port, 0, true,
>> true);
>> +                xlate_table_action(ctx, flow->in_port.ofp_port, table_id,
>> +                                   true, true);
>>                  ctx->xout->mirrors = old_mirrors;
>>                  ctx->base_flow = old_base_flow;
>>                  ofpbuf_set_size(&ctx->xout->odp_actions, old_size);
>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
>> index 46595f8..bdc0f1c 100644
>> --- a/ofproto/ofproto-dpif.c
>> +++ b/ofproto/ofproto-dpif.c
>> @@ -3192,7 +3192,7 @@ rule_dpif_lookup(struct ofproto_dpif *ofproto,
>> struct flow *flow,
>>  {
>>      enum rule_dpif_lookup_verdict verdict;
>>      enum ofputil_port_config config = 0;
>> -    uint8_t table_id;
>> +    uint8_t table_id = 0;
>>
>>      if (ofproto_dpif_get_enable_recirc(ofproto)) {
>>          /* Always exactly match recirc_id since datapath supports
>> @@ -3201,17 +3201,18 @@ rule_dpif_lookup(struct ofproto_dpif *ofproto,
>> struct flow *flow,
>>              wc->masks.recirc_id = UINT32_MAX;
>>          }
>>
>> -        /* Start looking up from internal table for post recirculation
>> flows
>> -         * or packets. We can also simply send all, including normal
>> flows
>> -         * or packets to the internal table. They will not match any post
>> -         * recirculation rules except the 'catch all' rule that resubmit
>> -         * them to table 0.
>> +        /* If 'ofproto' is the same as 'bond's ofproto, starts looking up
>> +         * from internal table for post recirculation flows or packets.
>> +         * We can also simply send all, including normal flows or packets
>> +         * to the internal table. They will not match any post
>> recirculation
>> +         * rules except the 'catch all' rule that resubmit them to table
>> 0.
>>           *
>>           * As an optimization, we send normal flows and packets to table
>> 0
>>           * directly, saving one table lookup.  */
>> -        table_id = flow->recirc_id ? TBL_INTERNAL : 0;
>> -    } else {
>> -        table_id = 0;
>> +        if (flow->recirc_id
>> +            && ofproto == bond_get_ofproto_by_recirc_id(flow->recirc_id))
>> {
>> +            table_id = TBL_INTERNAL;
>> +        }
>>      }
>>
>>      verdict = rule_dpif_lookup_from_table(ofproto, flow, wc, true,
>> --
>> 1.7.9.5
>>
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to