diff options
author | Lilijun (Jerry) <jerry.lilijun@huawei.com> | 2018-01-19 08:12:30 +0000 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2018-01-22 10:21:35 -0800 |
commit | c781bd520364b20541acc87790ea3b0358c98e8e (patch) | |
tree | abaf924d058cee6bb358ddefc3f4d98b996d53fc | |
parent | 2eb0e01d58a02cb088a47f745fd0a1db94d6dfc1 (diff) | |
download | openvswitch-c781bd520364b20541acc87790ea3b0358c98e8e.tar.gz |
ofproto: Fix wrong datapath flow with same in_port and output port.
In my test, the new datapath flow which has the same in_port and actions
output port was found using ovs-appctl dpctl/dump-flows. Then the mac
address will move from one port to another and back it again in the
physical switch. This problem result in the VM's traffic become abnormal.
My test key steps:
1) There are three VM using ovs bridge and intel 82599 nics as uplink
port, deployed in different hosts connecting to the same physical
switch. They can be named using VM-A, VM-B and VM-C, Host-A, Host-B,
Host-C.
2) VM-A send many unicast packets to VM-B, and VM-B also send unicast
packets to VM-A.
3) VM-C ping VM-A continuously, and do ovs port add/delete testing in
Host-C ovs bridge.
4) In some abormal scence, the physical switch clear all the mac-entry
on each ports. Then Host-C ovs bridge's uplink port will receive two
direction packets(VM-A to VM-B, and VM-B to VM-A).
The expected result is that this two direction packets should be droppd in
the uplink port. Because the dst port of this packets is the uplink port
which is also the src port by looking ovs bridge's mac-entry table learned
by ovs NORMAL rules. But the truth is some packets being sent back to
uplink port and physical switch. And then VM-A's mac was moved to the
physical switch port of Host-C from the port of Host-A, as a reulst, VM-C
ping VM-A failed at this time. When this problem occurs, the abnormal ovs
datapath's flow "in_port(2) actions:2" was found by executing the command
"ovs-appctl dpctl/dump-flows".
Currently, xlate_normal() uses xbundle pointer compare to verify the
packet's dst port whether is same with its input port. This implemention
may be wrong while calling xlate_txn_start/xlate_txn_commit in type_run()
at the same time, because xcfg/xbridge/xbundle object was reallocated and
copied just before we lookup the dst mac_port and mac_xbundle. Then
mac_xbundle and in_xbundle are same related with the uplink port but not
same object pointer.
And we can fix this bug by adding ofbundle check conditions shown in my
patch.
Signed-off-by: Lilijun <jerry.lilijun@huawei.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r-- | ofproto/ofproto-dpif-xlate.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 6c55545cb..aee18bf33 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2603,7 +2603,9 @@ xlate_normal_mcast_send_rports(struct xlate_ctx *ctx, xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp); LIST_FOR_EACH(rport, node, &ms->rport_list) { mcast_xbundle = xbundle_lookup(xcfg, rport->port); - if (mcast_xbundle && mcast_xbundle != in_xbundle) { + if (mcast_xbundle + && mcast_xbundle != in_xbundle + && mcast_xbundle->ofbundle != in_xbundle->ofbundle) { xlate_report(ctx, OFT_DETAIL, "forwarding report to mcast flagged port"); output_normal(ctx, mcast_xbundle, xvlan); @@ -2625,6 +2627,7 @@ xlate_normal_flood(struct xlate_ctx *ctx, struct xbundle *in_xbundle, LIST_FOR_EACH (xbundle, list_node, &ctx->xbridge->xbundles) { if (xbundle != in_xbundle + && xbundle->ofbundle != in_xbundle->ofbundle && xbundle_includes_vlan(xbundle, xvlan) && xbundle->floodable && !xbundle_mirror_out(ctx->xbridge, xbundle)) { @@ -2832,7 +2835,9 @@ xlate_normal(struct xlate_ctx *ctx) if (mac_port) { struct xlate_cfg *xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp); struct xbundle *mac_xbundle = xbundle_lookup(xcfg, mac_port); - if (mac_xbundle && mac_xbundle != in_xbundle) { + if (mac_xbundle + && mac_xbundle != in_xbundle + && mac_xbundle->ofbundle != in_xbundle->ofbundle) { xlate_report(ctx, OFT_DETAIL, "forwarding to learned port"); output_normal(ctx, mac_xbundle, &xvlan); } else if (!mac_xbundle) { |