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