[ovs-dev] [PATCHv6 2/3] ofproto-dpif-sflow: Add snaplen for sample action and sFlow.

William Tu u9012063 at gmail.com
Wed Jun 8 05:53:53 UTC 2016


This patch adds a 'snaplen' field in sample action.  Currently, sample
action is used by sFlow and IPFIX. For IPFIX, nothing is changed.  For
sFlow configuration, the patch translates header=N to a sample action with
snaplen=N, then the snaplen=N translates to trunc(N) in kernel datapath.
Thus, only N bytes instead of full-packet size will be copied from kernel
to userspace, saving the copying overhead.

Signed-off-by: William Tu <u9012063 at gmail.com>
---
 include/openvswitch/ofp-actions.h |  1 +
 lib/ofp-actions.c                 | 10 ++++++++-
 ofproto/ofproto-dpif-sflow.c      | 19 ++++++++++++++---
 ofproto/ofproto-dpif-sflow.h      |  2 ++
 ofproto/ofproto-dpif-upcall.c     |  4 +++-
 ofproto/ofproto-dpif-xlate.c      | 25 ++++++++++++++++++++--
 tests/odp.at                      |  2 ++
 tests/ofp-actions.at              |  8 +++----
 tests/ofproto-dpif.at             | 17 +++++++++++++++
 tests/ovs-ofctl.at                | 24 ++++++++++-----------
 tests/system-traffic.at           | 45 +++++++++++++++++++++++++++++++++++++++
 tests/system-userspace-macros.at  |  9 ++++++++
 12 files changed, 143 insertions(+), 23 deletions(-)

diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h
index 11e48ff..2634868 100644
--- a/include/openvswitch/ofp-actions.h
+++ b/include/openvswitch/ofp-actions.h
@@ -789,6 +789,7 @@ struct ofpact_note {
 struct ofpact_sample {
     struct ofpact ofpact;
     uint16_t probability;  // Always >0.
+    uint16_t snaplen;
     uint32_t collector_set_id;
     uint32_t obs_domain_id;
     uint32_t obs_point_id;
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 7fb6869..27af9b9 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -4736,8 +4736,10 @@ struct nx_action_sample {
     ovs_be32 collector_set_id;      /* ID of collector set in OVSDB. */
     ovs_be32 obs_domain_id;         /* ID of sampling observation domain. */
     ovs_be32 obs_point_id;          /* ID of sampling observation point. */
+    ovs_be16 snaplen;               /* Max sampled packet size in byte. */
+    uint8_t pad[6];
 };
-OFP_ASSERT(sizeof(struct nx_action_sample) == 24);
+OFP_ASSERT(sizeof(struct nx_action_sample) == 32);
 
 static enum ofperr
 decode_NXAST_RAW_SAMPLE(const struct nx_action_sample *nas,
@@ -4751,6 +4753,7 @@ decode_NXAST_RAW_SAMPLE(const struct nx_action_sample *nas,
     sample->collector_set_id = ntohl(nas->collector_set_id);
     sample->obs_domain_id = ntohl(nas->obs_domain_id);
     sample->obs_point_id = ntohl(nas->obs_point_id);
+    sample->snaplen = ntohs(nas->snaplen);
 
     if (sample->probability == 0) {
         return OFPERR_OFPBAC_BAD_ARGUMENT;
@@ -4770,6 +4773,7 @@ encode_SAMPLE(const struct ofpact_sample *sample,
     nas->collector_set_id = htonl(sample->collector_set_id);
     nas->obs_domain_id = htonl(sample->obs_domain_id);
     nas->obs_point_id = htonl(sample->obs_point_id);
+    nas->snaplen = htons(sample->snaplen);
 }
 
 /* Parses 'arg' as the argument to a "sample" action, and appends such an
@@ -4798,6 +4802,8 @@ parse_SAMPLE(char *arg, struct ofpbuf *ofpacts,
             error = str_to_u32(value, &os->obs_domain_id);
         } else if (!strcmp(key, "obs_point_id")) {
             error = str_to_u32(value, &os->obs_point_id);
+        } else if (!strcmp(key, "snaplen")) {
+            error = str_to_u16(value, "snaplen", &os->snaplen);
         } else {
             error = xasprintf("invalid key \"%s\" in \"sample\" argument",
                               key);
@@ -4816,11 +4822,13 @@ static void
 format_SAMPLE(const struct ofpact_sample *a, struct ds *s)
 {
     ds_put_format(s, "%ssample(%s%sprobability=%s%"PRIu16
+                  ",%ssnaplen=%s%"PRIu16
                   ",%scollector_set_id=%s%"PRIu32
                   ",%sobs_domain_id=%s%"PRIu32
                   ",%sobs_point_id=%s%"PRIu32"%s)%s",
                   colors.paren, colors.end,
                   colors.param, colors.end, a->probability,
+                  colors.param, colors.end, a->snaplen,
                   colors.param, colors.end, a->collector_set_id,
                   colors.param, colors.end, a->obs_domain_id,
                   colors.param, colors.end, a->obs_point_id,
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index 5d26b7c..ae0b1ec 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -556,6 +556,16 @@ dpif_sflow_get_probability(const struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
     return probability;
 }
 
+uint16_t
+dpif_sflow_get_header_len(const struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
+{
+    uint16_t header_len;
+    ovs_mutex_lock(&mutex);
+    header_len = ds->options->header_len;
+    ovs_mutex_unlock(&mutex);
+    return header_len;
+}
+
 void
 dpif_sflow_unref(struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
 {
@@ -1223,6 +1233,7 @@ dpif_sflow_cookie_num_outputs(const union user_action_cookie *cookie)
 void
 dpif_sflow_received(struct dpif_sflow *ds, const struct dp_packet *packet,
 		    const struct flow *flow, odp_port_t odp_in_port,
+		    const uint16_t cutlen,
 		    const union user_action_cookie *cookie,
 		    const struct dpif_sflow_actions *sflow_actions)
     OVS_EXCLUDED(mutex)
@@ -1268,11 +1279,13 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct dp_packet *packet,
     header = &hdrElem.flowType.header;
     header->header_protocol = SFLHEADER_ETHERNET_ISO8023;
     /* The frame_length should include the Ethernet FCS (4 bytes),
-     * but it has already been stripped,  so we need to add 4 here. */
-    header->frame_length = dp_packet_size(packet) + 4;
+     * but it has already been stripped,  so we need to add 4 here.
+     * The frame might be truncated by cutlen byte before upcall,
+     * so we need to add it back. */
+    header->frame_length = dp_packet_size(packet) + cutlen + 4;
     /* Ethernet FCS stripped off. */
     header->stripped = 4;
-    header->header_length = MIN(dp_packet_size(packet),
+    header->header_length = MIN(dp_packet_size(packet) + cutlen,
                                 sampler->sFlowFsMaximumHeaderSize);
     header->header_bytes = dp_packet_data(packet);
 
diff --git a/ofproto/ofproto-dpif-sflow.h b/ofproto/ofproto-dpif-sflow.h
index 014e6cc..e7d6c3f 100644
--- a/ofproto/ofproto-dpif-sflow.h
+++ b/ofproto/ofproto-dpif-sflow.h
@@ -56,6 +56,7 @@ struct dpif_sflow *dpif_sflow_ref(const struct dpif_sflow *);
 void dpif_sflow_unref(struct dpif_sflow *);
 
 uint32_t dpif_sflow_get_probability(const struct dpif_sflow *);
+uint16_t dpif_sflow_get_header_len(const struct dpif_sflow *);
 
 void dpif_sflow_set_options(struct dpif_sflow *,
                             const struct ofproto_sflow_options *);
@@ -75,6 +76,7 @@ void dpif_sflow_read_actions(const struct flow *,
 
 void dpif_sflow_received(struct dpif_sflow *, const struct dp_packet *,
                          const struct flow *, odp_port_t odp_port,
+                         const uint16_t cutlen,
                          const union user_action_cookie *,
 			 const struct dpif_sflow_actions *);
 
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 61e7494..96e8d79 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -1238,7 +1238,9 @@ process_upcall(struct udpif *udpif, struct upcall *upcall,
                 }
             }
             dpif_sflow_received(upcall->sflow, packet, flow,
-                                flow->in_port.odp_port, &cookie,
+                                flow->in_port.odp_port,
+                                upcall->cutlen,
+                                &cookie,
                                 actions_len > 0 ? &sflow_actions : NULL);
         }
         break;
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index a2cf7ed..bd99dd3 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2598,7 +2598,8 @@ xlate_normal(struct xlate_ctx *ctx)
 
 /* Appends a "sample" action for sFlow or IPFIX to 'ctx->odp_actions'.  The
  * 'probability' is the number of packets out of UINT32_MAX to sample.  The
- * 'cookie' (of length 'cookie_size' bytes) is passed back in the callback for
+ * 'snaplen' is the maximum sampled packet size in bytes.  The 'cookie'
+ * (of length 'cookie_size' bytes) is passed back in the callback for
  * each sampled packet.  'tunnel_out_port', if not ODPP_NONE, is added as the
  * OVS_USERSPACE_ATTR_EGRESS_TUN_PORT attribute.  If 'include_actions', an
  * OVS_USERSPACE_ATTR_ACTIONS attribute is added.
@@ -2606,6 +2607,7 @@ xlate_normal(struct xlate_ctx *ctx)
 static size_t
 compose_sample_action(struct xlate_ctx *ctx,
                       const uint32_t probability,
+                      const uint16_t snaplen,
                       const union user_action_cookie *cookie,
                       const size_t cookie_size,
                       const odp_port_t tunnel_out_port,
@@ -2619,6 +2621,21 @@ compose_sample_action(struct xlate_ctx *ctx,
     size_t actions_offset = nl_msg_start_nested(ctx->odp_actions,
                                                 OVS_SAMPLE_ATTR_ACTIONS);
 
+    /* Enable only when it is kernel datapath with truncate action support.
+     * Userspace datapath does not need this optimization. */
+    bool support_trunc = ctx->xbridge->support.trunc;
+    if (!strcmp(dpif_type(ctx->xbridge->dpif), "system") &&
+            support_trunc) {
+        if (snaplen > 0 && snaplen < UINT16_MAX) {
+            struct ovs_action_trunc *trunc;
+
+            trunc = nl_msg_put_unspec_uninit(ctx->odp_actions,
+                            OVS_ACTION_ATTR_TRUNC,
+                            sizeof *trunc);
+            trunc->max_len = snaplen;
+        }
+    }
+
     odp_port_t odp_port = ofp_port_to_odp_port(
         ctx->xbridge, ctx->xin->flow.in_port.ofp_port);
     uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port,
@@ -2651,6 +2668,7 @@ compose_sflow_action(struct xlate_ctx *ctx)
 
     union user_action_cookie cookie = { .type = USER_ACTION_COOKIE_SFLOW };
     return compose_sample_action(ctx, dpif_sflow_get_probability(sflow),
+                                 dpif_sflow_get_header_len(sflow),
                                  &cookie, sizeof cookie.sflow, ODPP_NONE,
                                  true);
 }
@@ -2696,6 +2714,7 @@ compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port)
     };
     compose_sample_action(ctx,
                           dpif_ipfix_get_bridge_exporter_probability(ipfix),
+                          0, /* snaplen = 0 means 65535. */
                           &cookie, sizeof cookie.ipfix, tunnel_out_port,
                           false);
 }
@@ -4197,6 +4216,7 @@ xlate_sample_action(struct xlate_ctx *ctx,
     /* Scale the probability from 16-bit to 32-bit while representing
      * the same percentage. */
     uint32_t probability = (os->probability << 16) | os->probability;
+    uint16_t snaplen = os->snaplen;
 
     if (!ctx->xbridge->support.variable_length_userdata) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
@@ -4218,7 +4238,8 @@ xlate_sample_action(struct xlate_ctx *ctx,
             .obs_point_id = os->obs_point_id,
         }
     };
-    compose_sample_action(ctx, probability, &cookie, sizeof cookie.flow_sample,
+    compose_sample_action(ctx, probability, snaplen, &cookie,
+                          sizeof cookie.flow_sample,
                           ODPP_NONE, false);
 }
 
diff --git a/tests/odp.at b/tests/odp.at
index 9be730a..926a908 100644
--- a/tests/odp.at
+++ b/tests/odp.at
@@ -330,6 +330,8 @@ ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random))
 ct(commit,nat(src=[[fe80::20c:29ff:fe88:1]]-[[fe80::20c:29ff:fe88:a18b]]:255-4096,random))
 ct(commit,helper=ftp,nat(src=10.1.1.240-10.1.1.255))
 trunc(100)
+sample(sample=9.7%,actions(trunc(100)))
+sample(sample=9.7%,actions(trunc(100),userspace(pid=6633,sFlow(vid=9,pcp=7,output=10),actions)))
 ])
 AT_CHECK_UNQUOTED([ovstest test-odp parse-actions < actions.txt], [0],
   [`cat actions.txt`
diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
index bd9cf41..bc44c32 100644
--- a/tests/ofp-actions.at
+++ b/tests/ofp-actions.at
@@ -124,8 +124,8 @@ ffff 0040 00002320 0025   000000000000 dnl
 # actions=dec_ttl(32768,12345,90,765,1024)
 ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000
 
-# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
-ffff 0018 00002320 001d 3039 00005BA0 00008707 0000B26E
+# actions=sample(probability=12345,snaplen=100,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+ffff 0020 00002320 001d 3039 00005BA0 00008707 0000B26E 0064 000000000000
 
 # bad OpenFlow10 actions: OFPBAC_BAD_LEN
 & ofp_actions|WARN|OpenFlow action OFPAT_OUTPUT length 240 exceeds action buffer length 8
@@ -410,8 +410,8 @@ ffff 0010 00002320 0014 04d2 162e 02 00
 # actions=dec_ttl(32768,12345,90,765,1024)
 ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000
 
-# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
-ffff 0018 00002320 001d 3039 00005BA0 00008707 0000B26E
+# actions=sample(probability=12345,snaplen=100,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+ffff 0020 00002320 001d 3039 00005BA0 00008707 0000B26E 0064 000000000000
 
 # bad OpenFlow11 actions: OFPBAC_BAD_OUT_PORT
 & ofp_actions|WARN|bad action at offset 0 (OFPBAC_BAD_OUT_PORT):
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 399c895..5c1605f 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -5446,6 +5446,23 @@ AT_CHECK([tail -1 stdout], [0],
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto-dpif - truncate and userspace])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2
+AT_CHECK([ovs-vsctl -- --id=@s create sFlow agent=br0 \
+            target=\"127.0.0.1:6344\" header=64 sampling=1 polling=1 \
+            -- set bridge br0 sflow=@s], [0], [stdout])
+
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy '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=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+
+dnl truncate and userspace only work when it is under kernel datapath.
+dnl Thus, the datapath actions here shows no truncate action.
+AT_CHECK([tail -1 stdout], [0],
+   [Datapath actions: sample(sample=100.0%,actions(userspace(pid=0,sFlow(vid=0,pcp=0,output=1073742080),actions)))
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto-dpif - sFlow packet sampling - IPv4 collector])
 CHECK_SFLOW_SAMPLING_PACKET([127.0.0.1])
 AT_CLEANUP
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index fa7ed48..70bbfb9 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -159,7 +159,7 @@ ip,actions=set_field:10.4.3.77->ip_src
 sctp actions=drop
 sctp actions=drop
 in_port=0 actions=resubmit:0
-actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 actions=ct(nat)
 actions=ct(commit,nat(dst))
 actions=ct(commit,nat(src))
@@ -189,7 +189,7 @@ OFPT_FLOW_MOD: ADD ip actions=mod_nw_src:10.4.3.77
 OFPT_FLOW_MOD: ADD sctp actions=drop
 OFPT_FLOW_MOD: ADD sctp actions=drop
 OFPT_FLOW_MOD: ADD in_port=0 actions=resubmit:0
-OFPT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+OFPT_FLOW_MOD: ADD actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 OFPT_FLOW_MOD: ADD actions=ct(nat)
 OFPT_FLOW_MOD: ADD actions=ct(commit,nat(dst))
 OFPT_FLOW_MOD: ADD actions=ct(commit,nat(src))
@@ -218,7 +218,7 @@ ip,actions=mod_nw_ttl:1,set_field:10.4.3.77->ip_src
 sctp actions=drop
 sctp actions=drop
 in_port=0 actions=resubmit:0
-actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl --protocols OpenFlow11 parse-flows flows.txt
@@ -237,7 +237,7 @@ OFPT_FLOW_MOD (OF1.1): ADD ip actions=mod_nw_ttl:1,mod_nw_src:10.4.3.77
 OFPT_FLOW_MOD (OF1.1): ADD sctp actions=drop
 OFPT_FLOW_MOD (OF1.1): ADD sctp actions=drop
 OFPT_FLOW_MOD (OF1.1): ADD in_port=0 actions=resubmit:0
-OFPT_FLOW_MOD (OF1.1): ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+OFPT_FLOW_MOD (OF1.1): ADD actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -259,7 +259,7 @@ udp actions=mod_tp_src:1111
 ip actions=mod_nw_src:10.1.1.2,mod_nw_dst:192.168.10.1,mod_nw_ttl:1,mod_nw_tos:16,mod_nw_ecn:2
 in_port=0 actions=mod_dl_src:11:22:33:44:55:66,mod_dl_dst:10:20:30:40:50:60
 in_port=0 actions=resubmit:0
-actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl --protocols OpenFlow12 parse-flows flows.txt
@@ -282,7 +282,7 @@ OFPT_FLOW_MOD (OF1.2): ADD udp actions=set_field:1111->udp_src
 OFPT_FLOW_MOD (OF1.2): ADD ip actions=set_field:10.1.1.2->ip_src,set_field:192.168.10.1->ip_dst,mod_nw_ttl:1,set_field:4->ip_dscp,set_field:2->nw_ecn
 OFPT_FLOW_MOD (OF1.2): ADD in_port=0 actions=set_field:11:22:33:44:55:66->eth_src,set_field:10:20:30:40:50:60->eth_dst
 OFPT_FLOW_MOD (OF1.2): ADD in_port=0 actions=resubmit:0
-OFPT_FLOW_MOD (OF1.2): ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+OFPT_FLOW_MOD (OF1.2): ADD actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -374,7 +374,7 @@ send_flow_rem,actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[
 check_overlap,actions=output:1,exit,output:2
 tcp,actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 actions=controller(max_len=123,reason=invalid_ttl,id=555)
-actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ip,actions=ct(commit,zone=5)
 ip,actions=ct(commit,exec(load(1->NXM_NX_CT_MARK[])))
 ip,actions=ct(commit,exec(load(0x1->NXM_NX_CT_LABEL[])))
@@ -418,7 +418,7 @@ NXT_FLOW_MOD: ADD table:255 send_flow_rem actions=output:1,output:NXM_NX_REG0[],
 NXT_FLOW_MOD: ADD table:255 check_overlap actions=output:1,exit,output:2
 NXT_FLOW_MOD: ADD table:255 tcp actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 NXT_FLOW_MOD: ADD table:255 actions=controller(reason=invalid_ttl,max_len=123,id=555)
-NXT_FLOW_MOD: ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+NXT_FLOW_MOD: ADD table:255 actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 NXT_FLOW_MOD: ADD table:255 ip actions=ct(commit,zone=5)
 NXT_FLOW_MOD: ADD table:255 ip actions=ct(commit,exec(load:0x1->NXM_NX_CT_MARK[]))
 NXT_FLOW_MOD: ADD table:255 ip actions=ct(commit,exec(load:0x1->NXM_NX_CT_LABEL[0..63],load:0->NXM_NX_CT_LABEL[64..127]))
@@ -460,7 +460,7 @@ dl_dst=01:00:00:00:00:00/01:00:00:00:00:00,actions=drop
 dl_dst=00:00:00:00:00:00/01:00:00:00:00:00,actions=drop
 dl_dst=aa:bb:cc:dd:ee:ff/fe:ff:ff:ff:ff:ff,actions=drop
 dl_dst=aa:bb:cc:dd:ee:ff/00:00:00:00:00:00,actions=drop
-actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ip,actions=ct(commit,zone=5)
 ip,actions=ct(commit,exec(load(1->NXM_NX_CT_MARK[[]])))
 ip,actions=ct(commit,exec(load(0x1->NXM_NX_CT_LABEL[[]])))
@@ -496,7 +496,7 @@ NXT_FLOW_MOD: ADD dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=drop
 NXT_FLOW_MOD: ADD dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=drop
 NXT_FLOW_MOD: ADD dl_dst=aa:bb:cc:dd:ee:ff/fe:ff:ff:ff:ff:ff actions=drop
 NXT_FLOW_MOD: ADD actions=drop
-NXT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+NXT_FLOW_MOD: ADD actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 NXT_FLOW_MOD: ADD ip actions=ct(commit,zone=5)
 NXT_FLOW_MOD: ADD ip actions=ct(commit,exec(load:0x1->NXM_NX_CT_MARK[[]]))
 NXT_FLOW_MOD: ADD ip actions=ct(commit,exec(load:0x1->NXM_NX_CT_LABEL[[0..63]],load:0->NXM_NX_CT_LABEL[[64..127]]))
@@ -532,7 +532,7 @@ reg0=123,actions=move:NXM_NX_REG0[0..5]->NXM_NX_REG1[26..31],load:55->NXM_NX_REG
 actions=move:OXM_OF_ETH_DST[]->OXM_OF_ETH_SRC[]
 actions=push:NXM_NX_REG0[0..31],pop:NXM_NX_REG0[]
 vlan_tci=0x1123/0x1fff,actions=drop
-actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ip,actions=ct(commit,zone=5)
 ip,actions=ct(commit,exec(load(1->NXM_NX_CT_MARK[])))
 ip,actions=ct(commit,exec(load(1->NXM_NX_CT_LABEL[])))
@@ -568,7 +568,7 @@ NXT_FLOW_MOD: ADD NXM_NX_REG0(0000007b) actions=move:NXM_NX_REG0[0..5]->NXM_NX_R
 NXT_FLOW_MOD: ADD <any> actions=move:NXM_OF_ETH_DST[]->NXM_OF_ETH_SRC[]
 NXT_FLOW_MOD: ADD <any> actions=push:NXM_NX_REG0[],pop:NXM_NX_REG0[]
 NXT_FLOW_MOD: ADD NXM_OF_VLAN_TCI_W(1123/1fff) actions=drop
-NXT_FLOW_MOD: ADD <any> actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+NXT_FLOW_MOD: ADD <any> actions=sample(probability=12345,snaplen=0,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800) actions=ct(commit,zone=5)
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800) actions=ct(commit,exec(load:0x1->NXM_NX_CT_MARK[]))
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800) actions=ct(commit,exec(load:0x1->NXM_NX_CT_LABEL[0..63],load:0->NXM_NX_CT_LABEL[64..127]))
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index 7c82514..0300cbd 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -418,6 +418,51 @@ n_bytes=100
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([datapath - truncate and userspace action])
+dnl Demonstrate that when truncate happens at kernel datapath, the
+dnl upcall netlink packet size is no longer the original size.
+CHECK_TRUNC_USERSPACE()
+OVS_TRAFFIC_VSWITCHD_START()
+
+dnl skip if it is check-userspace
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.2 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl setup sflow
+AT_CHECK([ovs-vsctl -- \
+    --id=@s create sFlow agent=br0 target=\"127.0.0.1:6344\" \
+    header=64 sampling=1 polling=1 -- set bridge br0 sflow=@s
+], [0], [stdout])
+
+dnl ofproto/trace
+AT_CHECK([ovs-appctl ofproto/trace ovs-system '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=6,tos=4,ttl=128,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
+AT_CHECK([tail -1 stdout | sed 's/pid=[[0-9]]*/pid=/g'], [0],
+    [Datapath actions: sample(sample=100.0%,actions(trunc(64),userspace(pid=,sFlow(vid=0,pcp=0,output=2147483650),actions))),1,3
+])
+AT_CHECK([ovs-appctl vlog/set netlink_socket::DBG])
+
+dnl send ping with 1024 bytes
+NS_CHECK_EXEC([at_ns0], [ping -s 1024 -q -c 3 -i 0.3 -w 2 10.1.1.2 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl filter out nl_sock_recv__ message with userspace action (cmd=2)
+AT_CHECK([grep "nl_sock_recv__.*ovs_packet.*cmd=2" ovs-vswitchd.log > nl_sock.log])
+AT_CHECK([sed -n 's/.*len:\([[0-9]]*\).*/\1/p' nl_sock.log | sort -r | tail -1 > max_pkt_size])
+max_pkt_size=$(cat max_pkt_size)
+dnl with truncate, ping -s 1024 should generate the nl packet size less than 1000 bytes
+AT_CHECK([if [[ "$max_pkt_size" -gt "1000" ]]; then exit 1; fi], [0])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([conntrack - controller])
 CHECK_CONNTRACK()
 OVS_TRAFFIC_VSWITCHD_START()
diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at
index c09a4aa..e7c7628 100644
--- a/tests/system-userspace-macros.at
+++ b/tests/system-userspace-macros.at
@@ -66,3 +66,12 @@ m4_define([CONFIGURE_VETH_OFFLOADS],
 m4_define([CHECK_CONNTRACK],
     [AT_SKIP_IF(true)]
 )
+
+# CHECK_TRUNC_USERSPACE()
+#
+# Skip truncate and userspace action, used by sFlow, when testsuite
+# is running in userspace.
+#
+m4_define([CHECK_TRUNC_USERSPACE],
+    [AT_SKIP_IF(true)]
+)
-- 
2.5.0




More information about the dev mailing list