@@ -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;
@@ -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,
@@ -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);
@@ -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 *);
@@ -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;
@@ -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);
}
@@ -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`
@@ -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):
@@ -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
@@ -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]))
@@ -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()
@@ -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)]
+)
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@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(-)