Even access port can carry packets on different VLANs when working with
OpenFlow. And VLANs can be selected for mirroring. So it is not needed
to check vlan when mirroring packets.

Signed-off-by: Hunt Xu <mhun...@gmail.com>
---
 ofproto/ofproto-dpif-xlate.c | 32 +++++++--------
 tests/ofproto-dpif.at        | 96 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 17 deletions(-)

diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index c533a4e..643b476 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -1606,18 +1606,8 @@ lookup_input_bundle(const struct xbridge *xbridge, 
ofp_port_t in_port,
  * given the packet is ingressing or egressing on 'xbundle', which has ingress
  * or egress (as appropriate) mirrors 'mirrors'. */
 static void
-mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
-              mirror_mask_t mirrors)
-{
-    /* Figure out what VLAN the packet is in (because mirrors can select
-     * packets on basis of VLAN). */
-    bool warn = ctx->xin->packet != NULL;
-    uint16_t vid = vlan_tci_to_vid(ctx->xin->flow.vlan_tci);
-    if (!input_vid_is_valid(vid, xbundle, warn)) {
-        return;
-    }
-    uint16_t vlan = input_vid_to_vlan(xbundle, vid);
-
+mirror_packet(struct xlate_ctx *ctx, mirror_mask_t mirrors, uint16_t vlan)
+{
     const struct xbridge *xbridge = ctx->xbridge;
 
     /* Don't mirror to destinations that we've already mirrored to. */
@@ -1706,8 +1696,15 @@ mirror_ingress_packet(struct xlate_ctx *ctx)
         struct xbundle *xbundle = lookup_input_bundle(
             ctx->xbridge, ctx->xin->flow.in_port.ofp_port, warn, NULL);
         if (xbundle) {
-            mirror_packet(ctx, xbundle,
-                          xbundle_mirror_src(ctx->xbridge, xbundle));
+            uint16_t vid = vlan_tci_to_vid(ctx->xin->flow.vlan_tci);
+            uint16_t vlan;
+            if (vid || xbundle->vlan_mode == PORT_VLAN_TRUNK) {
+                vlan = vid;
+            } else {
+                vlan = xbundle->vlan;
+            }
+            mirror_packet(ctx, xbundle_mirror_src(ctx->xbridge, xbundle),
+                          vlan);
         }
     }
 }
@@ -3159,9 +3156,10 @@ compose_output_action__(struct xlate_ctx *ctx, 
ofp_port_t ofp_port,
     }
 
     if (mbridge_has_mirrors(ctx->xbridge->mbridge) && xport->xbundle) {
-        mirror_packet(ctx, xport->xbundle,
-                      xbundle_mirror_dst(xport->xbundle->xbridge,
-                                         xport->xbundle));
+        uint16_t vlan = vlan_tci_to_vid(ctx->xin->flow.vlan_tci);
+        mirror_packet(ctx, xbundle_mirror_dst(xport->xbundle->xbridge,
+                                              xport->xbundle),
+                      vlan);
     }
 
  out:
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 123394d..24ea7fd 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -4286,6 +4286,102 @@ AT_CHECK([ovs-dpctl normalize-actions "$flow" 
"$actual"], [0], [expout])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto-dpif - mirroring, no ingress vlan checking])
+AT_KEYWORDS([mirror mirrors mirroring])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2 3
+ovs-vsctl \
+        set Bridge br0 mirrors=@m --\
+        --id=@p1 get Port p1 -- \
+        --id=@p3 get Port p3 -- \
+        --id=@m create Mirror name=mymirror select_src_port=@p1 
select_vlan=101,102 output_port=@p3 -- \
+        set Port p1 tag=100
+
+AT_DATA([flows.txt], [dnl
+in_port=1 priority=100,actions=normal
+in_port=1 priority=101,dl_vlan=101,actions=mod_vlan_vid:11,output:2
+in_port=1 priority=102,dl_vlan=102,actions=mod_vlan_vid:12,output:2
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="push_vlan(vid=100,pcp=0),2,100"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=101,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="3,pop_vlan,push_vlan(vid=11,pcp=0),2"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=102,pcp=1),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="3,pop_vlan,push_vlan(vid=12,pcp=1),2"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, no egress vlan checking])
+AT_KEYWORDS([mirror mirrors mirroring])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2 3
+ovs-vsctl \
+        set Bridge br0 mirrors=@m --\
+        --id=@p2 get Port p2 -- \
+        --id=@p3 get Port p3 -- \
+        --id=@m create Mirror name=mymirror select_dst_port=@p2 
select_vlan=10,11,12 output_port=@p3 -- \
+        set Port p2 trunks=8,9,10
+
+AT_DATA([flows.txt], [dnl
+in_port=1 priority=100,dl_vlan=10,actions=normal
+in_port=1 priority=101,dl_vlan=101,actions=mod_vlan_vid:11,output:2
+in_port=1 priority=102,dl_vlan=102,actions=mod_vlan_vid:12,output:2
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=10,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="2,3,100"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=101,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="pop_vlan,push_vlan(vid=11,pcp=0),2,3"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=102,pcp=1),encap(eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))"
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "$flow"], [0], [stdout])
+actual=`tail -1 stdout | sed 's/Datapath actions: //'`
+
+expected="pop_vlan,push_vlan(vid=12,pcp=1),2,3"
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$expected"], [0], [stdout])
+mv stdout expout
+AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 # This verifies that we don't get duplicate mirroring when mirror_packet()
 # might be invoked recursively, as a check against regression.
 AT_SETUP([ofproto-dpif - multiple VLAN output mirrors])
-- 
2.10.2

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to