This patch currently causes MPLS unittests failure, because it treats all pkts with 'recirc_id' as bond traffic. I'm thinking if we could reserve a range of 'recirc_id' for bonding so that 'recirc_id' used for other traffic will be unaffected,
Anyway, hope to hear any comments,~ Thanks, Alex Wang, On Wed, Dec 17, 2014 at 1:19 PM, Alex Wang <al...@nicira.com> wrote: > > After commit 0c7812e5e (recirculation: Do not drop packet when > there is no match from internal table.), if flow keys are modified > before the recirculation action (e.g. set vlan ID), the miss > handling of recirculated packets may take different path than the > ones. > > This commit adds an unittest that captures this bug. Moreover, > to solve this bug, this commit makes OVS directly input the > recirculated packets from local port of the bridge that owns > the correpsonding bond. Thus, those packets are always handled > from the correct bridge. > > Signed-off-by: Alex Wang <al...@nicira.com> > --- > ofproto/bond.c | 26 +++++++++++++++++++ > ofproto/bond.h | 2 ++ > ofproto/ofproto-dpif-xlate.c | 20 ++++++++++++-- > tests/ofproto-dpif.at | 59 > ++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 105 insertions(+), 2 deletions(-) > > diff --git a/ofproto/bond.c b/ofproto/bond.c > index c4b3a3a..08900fa 100644 > --- a/ofproto/bond.c > +++ b/ofproto/bond.c > @@ -254,6 +254,32 @@ bond_ref(const struct bond *bond_) > return bond; > } > > +struct ofproto_dpif * > +bond_get_ofproto(const struct bond *bond) > +{ > + return bond->ofproto; > +} > + > +/* Searches bond that uses 'recirc_id'. Returns an 'ref_count'ed > + * reference to 'bond'. */ > +struct bond * > +bond_find_by_recirc_id(const uint32_t recirc_id) > +{ > + struct bond *bond; > + > + ovs_rwlock_rdlock(&rwlock); > + HMAP_FOR_EACH (bond, hmap_node, all_bonds) { > + if (bond->recirc_id == recirc_id) { > + bond_ref(bond); > + ovs_rwlock_unlock(&rwlock); > + return bond; > + } > + } > + ovs_rwlock_unlock(&rwlock); > + > + return NULL; > +} > + > /* Frees 'bond'. */ > void > bond_unref(struct bond *bond) > diff --git a/ofproto/bond.h b/ofproto/bond.h > index c7b6308..43600df 100644 > --- a/ofproto/bond.h > +++ b/ofproto/bond.h > @@ -68,6 +68,8 @@ struct bond *bond_create(const struct bond_settings *, > struct ofproto_dpif *ofproto); > void bond_unref(struct bond *); > struct bond *bond_ref(const struct bond *); > +struct bond *bond_find_by_recirc_id(const uint32_t recirc_id); > +struct ofproto_dpif *bond_get_ofproto(const struct bond*); > > bool bond_reconfigure(struct bond *, const struct bond_settings *); > void bond_slave_register(struct bond *, void *slave_, ofp_port_t ofport, > struct netdev *); > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index c1327a6..dd0f329 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -981,9 +981,25 @@ static struct ofproto_dpif * > xlate_lookup_ofproto_(const struct dpif_backer *backer, const struct flow > *flow, > ofp_port_t *ofp_in_port, const struct xport > **xportp) > { > - const struct xport *xport; > + const struct xport *xport = NULL; > + > + /* If 'flow->recirc_id' is set, uses the OFPP_LOCAL port of the > + * 'xbridge' that owns the bond. Using 'OFPP_LOCAL' should be fine, > + * since the lookup only matches 'recirc_id' and 'dp_hash'. */ > + if (flow->recirc_id) { > + struct bond *bond = bond_find_by_recirc_id(flow->recirc_id); > + > + if (bond) { > + struct xlate_cfg *xcfg = ovsrcu_get(struct xlate_cfg *, > &xcfgp); > + struct ofproto_dpif *ofproto = bond_get_ofproto(bond); > > - *xportp = xport = xlate_lookup_xport(backer, flow); > + bond_unref(bond); > + *xportp = xport = get_ofp_port(xbridge_lookup(xcfg, ofproto), > + OFPP_LOCAL); > + } > + } else { > + *xportp = xport = xlate_lookup_xport(backer, flow); > + } > > if (xport) { > if (ofp_in_port) { > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > index baa942f..5e4e245 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -144,6 +144,65 @@ AT_CHECK([ovs-appctl dpif/dump-flows br1 |grep tcp > > br1_flows.txt]) > AT_CHECK([test `grep in_port.4 br1_flows.txt |wc -l` -gt 24]) > AT_CHECK([test `grep in_port.5 br1_flows.txt |wc -l` -gt 24]) > AT_CHECK([test `grep in_port.6 br1_flows.txt |wc -l` -gt 24]) > + > +OVS_VSWITCHD_STOP() > +AT_CLEANUP > + > +# Makes sure recirculation does not change the way packet is handled. > +AT_SETUP([ofproto-dpif, balance-tcp bonding, different recirc flow ]) > +OVS_VSWITCHD_START( > + [add-bond br0 bond0 p1 p2 bond_mode=balance-tcp lacp=active \ > + other-config:lacp-time=fast other-config:bond-rebalance-interval=0 > -- \ > + set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock > ofport_request=1 -- \ > + set interface p2 type=dummy options:pstream=punix:$OVS_RUNDIR/p2.sock > ofport_request=2 -- \ > + add-br br1 -- \ > + set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \ > + set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \ > + fail-mode=standalone -- \ > + add-bond br1 bond1 p3 p4 bond_mode=balance-tcp lacp=active \ > + other-config:lacp-time=fast other-config:bond-rebalance-interval=0 > -- \ > + set interface p3 type=dummy options:stream=unix:$OVS_RUNDIR/p1.sock > ofport_request=3 -- \ > + set interface p4 type=dummy options:stream=unix:$OVS_RUNDIR/p2.sock > ofport_request=4 -- \ > + add-port br1 br1- -- set interface br1- type=patch options:peer=br1+ > ofport_request=100 -- \ > + set port br1- tag=1 -- \ > + add-br br-int -- \ > + set bridge br-int other-config:hwaddr=aa:77:aa:77:00:00 -- \ > + set bridge br-int datapath-type=dummy other-config:datapath-id=1235 \ > + fail-mode=secure -- \ > + add-port br-int br1+ -- set interface br1+ type=patch > options:peer=br1- ofport_request=101 -- \ > + add-port br-int p5 -- set interface p5 ofport_request=5 type=dummy > +]) > +AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK > +]) > + > +# The dl_vlan flow should not be ever matched, > +# since recirculation should not change the flow handling. > +AT_DATA([flows.txt], [dnl > +table=0 priority=1 in_port=5 actions=output(101) > +table=0 priority=2 in_port=5 dl_vlan=1 actions=drop > +]) > +AT_CHECK([ovs-ofctl add-flows br-int flows.txt]) > + > +# Sends a packet to trigger recirculation. > +# Should generate recirc_id(0x12d),dp_hash(0xc1261ba2/0xff). > +AT_CHECK([ovs-appctl netdev-dummy/receive p5 > "in_port(5),eth(src=50:54:00:00:00:05,dst=50:54:00:00:01:00),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1)"]) > + > +# Collects flow stats. > +AT_CHECK([ovs-appctl revalidator/purge], [0]) > + > +# Checks the flow stats in br1, should only be one flow with non-zero > +# 'n_packets' from internal table. > +AT_CHECK([ovs-appctl bridge/dump-flows br1 | ofctl_strip | grep -- > "n_packets" | grep -- "table_id" | sed -e 's/output:[[0-9]]\+/output/'], > [0], [dnl > +table_id=254, n_packets=1, n_bytes=64, > priority=20,recirc_id=0x12d,dp_hash=0xa2/0xff,actions=output > +]) > + > +# Checks the flow stats in br-int, should be only one match. > +AT_CHECK([ovs-ofctl dump-flows br-int | ofctl_strip | sort], [0], [dnl > + n_packets=1, n_bytes=60, priority=1,in_port=5 actions=output:101 > + priority=2,in_port=5,dl_vlan=1 actions=drop > +NXST_FLOW reply: > +]) > + > OVS_VSWITCHD_STOP() > AT_CLEANUP > > -- > 1.7.9.5 > > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev