[ovs-dev] [PATCHv3] ofproto-dpif-mirror: Add mirror snaplen support.

William Tu u9012063 at gmail.com
Wed Jun 29 21:38:02 UTC 2016


This patch adds a 'snaplen' config for mirroring table.  A mirrored packet
with size larger than snaplen bytes will be truncated in datapath before
sending to the mirror output port.  A snaplen of 0 equals 65535, which means
no truncation applied.

Tested-at: https://travis-ci.org/williamtu/ovs-travis/builds/141186839
Signed-off-by: William Tu <u9012063 at gmail.com>
---
v2->v3
- fix min and max number in schema
  http://openvswitch.org/pipermail/dev/2016-June/072630.html
v1->v2
- use UINT16_MAX instead of (uint16_t) - 1
  http://openvswitch.org/pipermail/dev/2016-June/072297.html
---
 ofproto/ofproto-dpif-mirror.c |   9 +-
 ofproto/ofproto-dpif-mirror.h |   4 +-
 ofproto/ofproto-dpif-xlate.c  |  31 +++++-
 ofproto/ofproto-dpif.c        |   3 +-
 ofproto/ofproto.h             |   2 +
 tests/ofproto-dpif.at         | 224 ++++++++++++++++++++++++++++++++++++++++++
 vswitchd/bridge.c             |   6 ++
 vswitchd/vswitch.ovsschema    |   7 +-
 vswitchd/vswitch.xml          |   9 ++
 9 files changed, 287 insertions(+), 8 deletions(-)

diff --git a/ofproto/ofproto-dpif-mirror.c b/ofproto/ofproto-dpif-mirror.c
index 6f8079a..84b7845 100644
--- a/ofproto/ofproto-dpif-mirror.c
+++ b/ofproto/ofproto-dpif-mirror.c
@@ -61,6 +61,8 @@ struct mirror {
     /* Output (exactly one of out == NULL and out_vlan == -1 is true). */
     struct mbundle *out;        /* Output port or NULL. */
     int out_vlan;               /* Output VLAN or -1. */
+    uint16_t snaplen;           /* Max per mirrored packet size in byte,
+                                   set to 0 equals 65535. */
     mirror_mask_t dup_mirrors;  /* Bitmap of mirrors with the same output. */
 
     /* Counters. */
@@ -203,6 +205,7 @@ mirror_set(struct mbridge *mbridge, void *aux, const char *name,
            struct ofbundle **srcs, size_t n_srcs,
            struct ofbundle **dsts, size_t n_dsts,
            unsigned long *src_vlans, struct ofbundle *out_bundle,
+           uint16_t snaplen,
            uint16_t out_vlan)
 {
     struct mbundle *mbundle, *out;
@@ -227,6 +230,7 @@ mirror_set(struct mbridge *mbridge, void *aux, const char *name,
         mirror->idx = idx;
         mirror->aux = aux;
         mirror->out_vlan = -1;
+        mirror->snaplen = 0;
     }
 
     /* Get the new configuration. */
@@ -266,6 +270,7 @@ mirror_set(struct mbridge *mbridge, void *aux, const char *name,
 
     mirror->out = out;
     mirror->out_vlan = out_vlan;
+    mirror->snaplen = snaplen;
 
     /* Update mbundles. */
     mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
@@ -388,7 +393,8 @@ mirror_update_stats(struct mbridge *mbridge, mirror_mask_t mirrors,
  * receives the output VLAN (if any). */
 bool
 mirror_get(struct mbridge *mbridge, int index, const unsigned long **vlans,
-           mirror_mask_t *dup_mirrors, struct ofbundle **out, int *out_vlan)
+           mirror_mask_t *dup_mirrors, struct ofbundle **out,
+           int *snaplen, int *out_vlan)
 {
     struct mirror *mirror;
 
@@ -405,6 +411,7 @@ mirror_get(struct mbridge *mbridge, int index, const unsigned long **vlans,
     *dup_mirrors = mirror->dup_mirrors;
     *out = mirror->out ? mirror->out->ofbundle : NULL;
     *out_vlan = mirror->out_vlan;
+    *snaplen = mirror->snaplen;
     return true;
 }
 
diff --git a/ofproto/ofproto-dpif-mirror.h b/ofproto/ofproto-dpif-mirror.h
index 6e0dc88..b00536a 100644
--- a/ofproto/ofproto-dpif-mirror.h
+++ b/ofproto/ofproto-dpif-mirror.h
@@ -42,7 +42,7 @@ int mirror_set(struct mbridge *, void *aux, const char *name,
                struct ofbundle **srcs, size_t n_srcs,
                struct ofbundle **dsts, size_t n_dsts,
                unsigned long *src_vlans, struct ofbundle *out_bundle,
-               uint16_t out_vlan);
+               uint16_t snaplen, uint16_t out_vlan);
 void mirror_destroy(struct mbridge *, void *aux);
 int mirror_get_stats(struct mbridge *, void *aux, uint64_t *packets,
                      uint64_t *bytes);
@@ -50,6 +50,6 @@ void mirror_update_stats(struct mbridge*, mirror_mask_t, uint64_t packets,
                          uint64_t bytes);
 bool mirror_get(struct mbridge *, int index, const unsigned long **vlans,
                 mirror_mask_t *dup_mirrors, struct ofbundle **out,
-                int *out_vlan);
+                int *snaplen, int *out_vlan);
 
 #endif /* ofproto-dpif-mirror.h */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index d46a52c..82c40bd 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -238,6 +238,7 @@ struct xlate_ctx {
     ofp_port_t nf_output_iface; /* Output interface index for NetFlow. */
     bool exit;                  /* No further actions should be processed. */
     mirror_mask_t mirrors;      /* Bitmap of associated mirrors. */
+    int mirror_snaplen;         /* Max size of a mirror packet in byte. */
 
    /* Freezing Translation
     * ====================
@@ -1702,12 +1703,15 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
         mirror_mask_t dup_mirrors;
         struct ofbundle *out;
         int out_vlan;
+        int snaplen;
 
         /* Get the details of the mirror represented by the rightmost 1-bit. */
         bool has_mirror = mirror_get(xbridge->mbridge, raw_ctz(mirrors),
-                                     &vlans, &dup_mirrors, &out, &out_vlan);
+                                     &vlans, &dup_mirrors,
+                                     &out, &snaplen, &out_vlan);
         ovs_assert(has_mirror);
 
+
         /* If this mirror selects on the basis of VLAN, and it does not select
          * 'vlan', then discard this mirror and go on to the next one. */
         if (vlans) {
@@ -1723,6 +1727,7 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
          * done now to ensure that output_normal(), below, doesn't recursively
          * output to the same mirrors. */
         ctx->mirrors |= dup_mirrors;
+        ctx->mirror_snaplen = snaplen;
 
         /* Send the packet to the mirror. */
         if (out) {
@@ -1746,6 +1751,7 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
         /* output_normal() could have recursively output (to different
          * mirrors), so make sure that we don't send duplicates. */
         mirrors &= ~ctx->mirrors;
+        ctx->mirror_snaplen = 0;
     }
 }
 
@@ -3010,6 +3016,9 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
     } else if (xport->config & OFPUTIL_PC_NO_FWD) {
         xlate_report(ctx, "OFPPC_NO_FWD set, skipping output");
         return;
+    } else if (ctx->mirror_snaplen != 0 && xport->odp_port == ODPP_NONE) {
+        xlate_report(ctx, "Mirror truncate to ODPP_NONE, skipping output");
+        return;
     } else if (check_stp) {
         if (is_stp(&ctx->base_flow)) {
             if (!xport_stp_should_forward_bpdu(xport) &&
@@ -3226,11 +3235,27 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
                     /* Tunnel push-pop action is not compatible with
                      * IPFIX action. */
                     compose_ipfix_action(ctx, out_port);
+
+                    /* Handle truncation of the mirrored packet. */
+                    if (ctx->mirror_snaplen > 0 &&
+                        ctx->mirror_snaplen < UINT16_MAX) {
+                        bool support_trunc = ctx->xbridge->support.trunc;
+                        struct ovs_action_trunc *trunc;
+
+                        trunc = nl_msg_put_unspec_uninit(ctx->odp_actions,
+                                    OVS_ACTION_ATTR_TRUNC,
+                                    sizeof *trunc);
+                        trunc->max_len = ctx->mirror_snaplen;
+                        if (!support_trunc) {
+                            ctx->xout->slow |= SLOW_ACTION;
+                        }
+                    }
+
                     nl_msg_put_odp_port(ctx->odp_actions,
                                         OVS_ACTION_ATTR_OUTPUT,
                                         out_port);
-               }
-           }
+                }
+            }
         }
 
         ctx->sflow_odp_port = odp_port;
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 0cd1c25..0297a6d 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3216,7 +3216,8 @@ mirror_set__(struct ofproto *ofproto_, void *aux,
 
     error = mirror_set(ofproto->mbridge, aux, s->name, srcs, s->n_srcs, dsts,
                        s->n_dsts, s->src_vlans,
-                       bundle_lookup(ofproto, s->out_bundle), s->out_vlan);
+                       bundle_lookup(ofproto, s->out_bundle),
+                       s->snaplen, s->out_vlan);
     free(srcs);
     free(dsts);
     return error;
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index 26c687c..a60327a 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -427,6 +427,8 @@ struct ofproto_mirror_settings {
     /* Output (mutually exclusive). */
     void *out_bundle;           /* A registered ofbundle handle or NULL. */
     uint16_t out_vlan;          /* Output VLAN, only if out_bundle is NULL. */
+    uint16_t snaplen;           /* Max packet size of a mirrored packet
+                                   in byte, set to 0 equals 65535. */
 };
 
 int ofproto_mirror_register(struct ofproto *, void *aux,
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 773d099..8287d90 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -4224,6 +4224,230 @@ AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 4
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+# Tests below verify the snaplen support for mirroring
+AT_SETUP([ofproto-dpif - mirroring, select_all with snaplen])
+AT_KEYWORDS([mirror mirrors mirroring])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2 3
+ovs-vsctl \
+        set Bridge br0 mirrors=@m --\
+        --id=@p3 get Port p3 --\
+        --id=@m create Mirror name=mymirror select_all=true output_port=@p3 snaplen=100
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=output:1
+])
+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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: trunc(100),3,2
+])
+
+flow="in_port(2),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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: trunc(100),3,1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, select_src with snaplen])
+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 output_port=@p3 snaplen=100
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=output:1
+])
+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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: trunc(100),3,2
+])
+
+flow="in_port(2),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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: 1
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, OFPP_NONE ingress port with snaplen])
+AT_KEYWORDS([mirror mirrors mirroring])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2
+ovs-vsctl \
+        set Bridge br0 mirrors=@m --\
+        --id=@p2 get Port p2 --\
+        --id=@m create Mirror name=mymirror select_all=true output_port=@p2 snaplen=100
+
+AT_CHECK([ovs-ofctl add-flow br0 action=output:1])
+
+# "in_port" defaults to OFPP_NONE if it's not specified.
+flow="icmp,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_ttl=128,icmp_type=8,icmp_code=0"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: 1,trunc(100),2
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, select_dst with snaplen])
+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 output_port=@p3 snaplen=100
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=output:1
+])
+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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: 2,trunc(100),3
+])
+
+flow="in_port(2),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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: 1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, select_vlan with snaplen])
+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_all=true select_vlan=11 output_port=@p3 snaplen=100
+
+AT_DATA([flows.txt], [dnl
+in_port=1, actions=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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: 2
+])
+
+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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: 2
+])
+
+flow="in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x8100),vlan(vid=11,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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: trunc(100),3,2
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, output_port with snaplen])
+AT_KEYWORDS([mirror mirrors mirroring])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2 3
+ovs-vsctl \
+        set Bridge br0 mirrors=@m --\
+        --id=@p3 get Port p3 --\
+        --id=@m create Mirror name=mymirror select_all=true output_port=@p3 snaplen=100
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=mod_vlan_vid:17,output:2
+in_port=2 actions=output:1
+])
+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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: trunc(100),3,push_vlan(vid=17,pcp=0),2
+])
+
+flow="in_port(2),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])
+AT_CHECK_UNQUOTED([tail -1 stdout], [0],
+  [Datapath actions: trunc(100),3,1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - mirroring, output_vlan with snaplen])
+AT_KEYWORDS([mirror mirrors mirroring])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2
+ovs-vsctl \
+        set Bridge br0 mirrors=@m --\
+        --id=@m create Mirror name=mymirror select_all=true output_vlan=12 snaplen=100
+
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:2
+in_port=2 actions=mod_vlan_vid:17,output:1
+])
+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: //'`
+dnl Expect: "trunc(100),100,trunc(100),2,trunc(100),1", with different order
+AT_CHECK([echo "$actual" | sed -n 's/.*\(trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*\)/\1/p'], [0])
+
+flow="in_port(2),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: //'`
+AT_CHECK([echo "$actual" | sed -n 's/.*\(trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*,trunc([0-9]*),[0-9]*\)/\1/p'], [0])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - multiple VLAN output mirrors with snaplen])
+AT_KEYWORDS([mirror mirrors mirroring])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2 3
+ovs-vsctl \
+        -- set Bridge br0 fail-mode=standalone mirrors=@m1, at m2 \
+       -- --id=@m1 create Mirror name=m1 select_all=true output_vlan=500 snaplen=200 \
+       -- --id=@m2 create Mirror name=m2 select_all=true output_vlan=501 snaplen=300 \
+       -- set Port br0 tag=0 \
+       -- set Port p1 tag=0 \
+       -- set Port p2 tag=500 \
+       -- set Port p3 tag=501
+
+flow="in_port=1"
+AT_CHECK([ovs-appctl ofproto/trace br0 "$flow"], [0], [stdout])
+AT_CHECK([tail -1 stdout | egrep "trunc\(200\),2,trunc\(300\),3,100|trunc\(300\),3,trunc\(200\),2,100"], [0], [stdout])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 # This test verifies that the table ID is preserved across recirculation
 # when a resubmit action requires it (because the action is relative to
 # the current table rather than specifying a table).
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 8ebfc66..52adc18 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -4760,6 +4760,12 @@ mirror_configure(struct mirror *m)
         return false;
     }
 
+    if (cfg->snaplen) {
+        s.snaplen = *cfg->snaplen;
+    } else {
+        s.snaplen = 0;
+    }
+
     /* Get port selection. */
     if (cfg->select_all) {
         size_t n_ports = hmap_count(&m->bridge->ports);
diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema
index e0937f4..32fdf28 100644
--- a/vswitchd/vswitch.ovsschema
+++ b/vswitchd/vswitch.ovsschema
@@ -1,6 +1,6 @@
 {"name": "Open_vSwitch",
  "version": "7.13.0",
- "cksum": "2202834738 22577",
+ "cksum": "889248633 22774",
  "tables": {
    "Open_vSwitch": {
      "columns": {
@@ -405,6 +405,11 @@
                           "minInteger": 1,
                           "maxInteger": 4095},
                   "min": 0, "max": 1}},
+       "snaplen": {
+         "type": {"key": {"type": "integer",
+                          "minInteger": 14,
+                          "maxInteger": 65535},
+                  "min": 0, "max": 1}},
        "statistics": {
          "type": {"key": "string", "value": "integer",
                   "min": 0, "max": "unlimited"},
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index aad4904..72f629e 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -3692,6 +3692,15 @@
           VLAN and should generally be preferred.
         </p>
       </column>
+
+      <column name="snaplen">
+        <p>Maximum per mirrored packet size in bytes.</p>
+        <p>A mirrored packet with size larger than <ref column="snaplen"/>
+           will be truncated in datapath to <ref column="snaplen"/> bytes
+           before sending to the mirror output port.  A snaplen of 0 equals
+           65535, which means no truncation applied.
+        </p>
+      </column>
     </group>
 
     <group title="Statistics: Mirror counters">
-- 
2.5.0




More information about the dev mailing list