@@ -789,6 +789,7 @@ struct ofpact_note {
struct ofpact_sample {
struct ofpact ofpact;
uint16_t probability; /* Always positive. */
+ uint16_t snaplen;
uint32_t collector_set_id;
uint32_t obs_domain_id;
uint32_t obs_point_id;
@@ -1969,7 +1969,8 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
[OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_UNSPEC, .optional = true },
[OVS_PACKET_ATTR_EGRESS_TUN_KEY] = { .type = NL_A_NESTED, .optional = true },
[OVS_PACKET_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
- [OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = true }
+ [OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = true },
+ [OVS_PACKET_ATTR_LEN] = { .type = NL_A_U32, .optional = true },
};
struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
@@ -2002,6 +2003,7 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
upcall->out_tun_key = a[OVS_PACKET_ATTR_EGRESS_TUN_KEY];
upcall->actions = a[OVS_PACKET_ATTR_ACTIONS];
upcall->mru = a[OVS_PACKET_ATTR_MRU];
+ upcall->len = a[OVS_PACKET_ATTR_LEN];
/* Allow overwriting the netlink attribute header without reallocating. */
dp_packet_use_stub(&upcall->packet,
@@ -784,7 +784,7 @@ struct dpif_upcall {
size_t key_len; /* Length of 'key' in bytes. */
ovs_u128 ufid; /* Unique flow identifier for 'key'. */
struct nlattr *mru; /* Maximum receive unit. */
- struct nlattr *cutlen; /* Number of bytes shrink from the end. */
+ struct nlattr *len; /* Original packet length. */
/* DPIF_UC_ACTION only. */
struct nlattr *userdata; /* Argument to OVS_ACTION_ATTR_USERSPACE. */
@@ -4756,7 +4756,8 @@ struct nx_action_sample2 {
ovs_be32 obs_domain_id; /* ID of sampling observation domain. */
ovs_be32 obs_point_id; /* ID of sampling observation point. */
ovs_be16 sampling_port; /* Sampling port. */
- uint8_t pad[6]; /* Pad to a multiple of 8 bytes */
+ ovs_be16 snaplen; /* Max sampled packet size in byte. */
+ uint8_t pad[4]; /* Pad to a multiple of 8 bytes */
};
OFP_ASSERT(sizeof(struct nx_action_sample2) == 32);
@@ -4797,6 +4798,7 @@ decode_NXAST_RAW_SAMPLE2(const struct nx_action_sample2 *nas,
sample->obs_domain_id = ntohl(nas->obs_domain_id);
sample->obs_point_id = ntohl(nas->obs_point_id);
sample->sampling_port = u16_to_ofp(ntohs(nas->sampling_port));
+ sample->snaplen = ntohs(nas->snaplen);
if (sample->probability == 0) {
return OFPERR_OFPBAC_BAD_ARGUMENT;
@@ -4813,6 +4815,7 @@ encode_SAMPLE(const struct ofpact_sample *sample,
|| sample->sampling_port != OFPP_NONE) {
struct nx_action_sample2 *nas = put_NXAST_SAMPLE2(out);
nas->probability = htons(sample->probability);
+ nas->snaplen = htons(sample->snaplen);
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);
@@ -4857,6 +4860,8 @@ parse_SAMPLE(char *arg, struct ofpbuf *ofpacts,
if (!ofputil_port_from_string(value, &os->sampling_port)) {
error = xasprintf("%s: unknown port", value);
}
+ } else if (!strcmp(key, "snaplen")) {
+ error = str_to_u16(value, "snaplen", &os->snaplen);
} else {
error = xasprintf("invalid key \"%s\" in \"sample\" argument",
key);
@@ -4884,6 +4889,11 @@ format_SAMPLE(const struct ofpact_sample *a, struct ds *s)
colors.param, colors.end, a->collector_set_id,
colors.param, colors.end, a->obs_domain_id,
colors.param, colors.end, a->obs_point_id);
+
+ if (a->ofpact.raw == NXAST_RAW_SAMPLE2) {
+ ds_put_format(s, ",%ssnaplen=%s%"PRIu16,
+ colors.param, colors.end, a->snaplen);
+ }
if (a->sampling_port != OFPP_NONE) {
ds_put_format(s, ",%ssampling_port=%s%"PRIu16,
colors.param, colors.end, a->sampling_port);
@@ -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 uint32_t len,
const union user_action_cookie *cookie,
const struct dpif_sflow_actions *sflow_actions)
OVS_EXCLUDED(mutex)
@@ -1269,11 +1280,10 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct dp_packet *packet,
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;
+ header->frame_length = len + 4;
/* Ethernet FCS stripped off. */
header->stripped = 4;
- header->header_length = MIN(dp_packet_size(packet),
- sampler->sFlowFsMaximumHeaderSize);
+ header->header_length = MIN(len, sampler->sFlowFsMaximumHeaderSize);
header->header_bytes = dp_packet_data(packet);
/* Add extended switch element. */
@@ -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 uint32_t cutlen,
const union user_action_cookie *,
const struct dpif_sflow_actions *);
@@ -207,6 +207,7 @@ struct upcall {
ofp_port_t in_port; /* OpenFlow in port, or OFPP_NONE. */
uint16_t mru; /* If !0, Maximum receive unit of
fragmented IP packet */
+ uint32_t len; /* Original packet length. */
enum dpif_upcall_type type; /* Datapath type of the upcall. */
const struct nlattr *userdata; /* Userdata for DPIF_UC_ACTION Upcalls. */
@@ -350,7 +351,7 @@ static enum upcall_type classify_upcall(enum dpif_upcall_type type,
static int upcall_receive(struct upcall *, const struct dpif_backer *,
const struct dp_packet *packet, enum dpif_upcall_type,
const struct nlattr *userdata, const struct flow *,
- const unsigned int mru,
+ const unsigned int mru, const uint32_t cutlen,
const ovs_u128 *ufid, const unsigned pmd_id);
static void upcall_uninit(struct upcall *);
@@ -746,6 +747,7 @@ recv_upcalls(struct handler *handler)
struct upcall *upcall = &upcalls[n_upcalls];
struct flow *flow = &flows[n_upcalls];
unsigned int mru;
+ uint32_t len;
int error;
ofpbuf_use_stub(recv_buf, recv_stubs[n_upcalls],
@@ -766,9 +768,14 @@ recv_upcalls(struct handler *handler)
mru = 0;
}
+ if (dupcall->len) {
+ len = nl_attr_get_u32(dupcall->len);
+ } else {
+ len = 0;
+ }
error = upcall_receive(upcall, udpif->backer, &dupcall->packet,
dupcall->type, dupcall->userdata, flow, mru,
- &dupcall->ufid, PMD_ID_NULL);
+ len, &dupcall->ufid, PMD_ID_NULL);
if (error) {
if (error == ENODEV) {
/* Received packet on datapath port for which we couldn't
@@ -1009,7 +1016,7 @@ static int
upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
const struct dp_packet *packet, enum dpif_upcall_type type,
const struct nlattr *userdata, const struct flow *flow,
- const unsigned int mru,
+ const unsigned int mru, const unsigned int len,
const ovs_u128 *ufid, const unsigned pmd_id)
{
int error;
@@ -1039,6 +1046,7 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
upcall->key = NULL;
upcall->key_len = 0;
upcall->mru = mru;
+ upcall->len = len;
upcall->out_tun_key = NULL;
upcall->actions = NULL;
@@ -1150,7 +1158,8 @@ upcall_cb(const struct dp_packet *packet, const struct flow *flow, ovs_u128 *ufi
atomic_read_relaxed(&udpif->flow_limit, &flow_limit);
error = upcall_receive(&upcall, udpif->backer, packet, type, userdata,
- flow, 0, ufid, pmd_id);
+ flow, 0, dp_packet_size(packet) + packet->cutlen,
+ ufid, pmd_id);
if (error) {
return error;
}
@@ -1237,7 +1246,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->len,
+ &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. If 'emit_set_tunnel',
@@ -2609,6 +2610,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,
@@ -2622,6 +2624,18 @@ compose_sample_action(struct xlate_ctx *ctx,
size_t actions_offset = nl_msg_start_nested(ctx->odp_actions,
OVS_SAMPLE_ATTR_ACTIONS);
+ bool support_trunc = ctx->xbridge->support.trunc;
+ if (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,
@@ -2654,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);
}
@@ -2701,6 +2716,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 UINT16_MAX. */
&cookie, sizeof cookie.ipfix, tunnel_out_port,
false);
}
@@ -4212,6 +4228,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);
@@ -4278,7 +4295,8 @@ xlate_sample_action(struct xlate_ctx *ctx,
.output_odp_port = output_odp_port,
}
};
- compose_sample_action(ctx, probability, &cookie, sizeof cookie.flow_sample,
+ compose_sample_action(ctx, probability, snaplen,
+ &cookie, sizeof cookie.flow_sample,
tunnel_out_port, false);
}
@@ -127,8 +127,8 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
-ffff 0020 00002320 0026 3039 00005BA0 00008707 0000B26E DDD50000 00000000
+# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
+ffff 0020 00002320 0026 3039 00005BA0 00008707 0000B26E DDD50064 00000000
# bad OpenFlow10 actions: OFPBAC_BAD_LEN
& ofp_actions|WARN|OpenFlow action OFPAT_OUTPUT length 240 exceeds action buffer length 8
@@ -160,7 +160,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
actions=ct(nat)
actions=ct(commit,nat(dst))
actions=ct(commit,nat(src))
@@ -191,7 +191,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+OFPT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
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))
@@ -221,7 +221,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
]])
AT_CHECK([ovs-ofctl --protocols OpenFlow11 parse-flows flows.txt
@@ -241,7 +241,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+OFPT_FLOW_MOD (OF1.1): ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
]])
AT_CLEANUP
@@ -264,7 +264,7 @@ ip actions=mod_nw_src:10.1.1.2,mod_nw_dst:192.168.10.1,mod_nw_ttl:1,mod_nw_tos:1
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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
]])
AT_CHECK([ovs-ofctl --protocols OpenFlow12 parse-flows flows.txt
@@ -288,7 +288,7 @@ OFPT_FLOW_MOD (OF1.2): ADD ip actions=set_field:10.1.1.2->ip_src,set_field:192.1
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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+OFPT_FLOW_MOD (OF1.2): ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
]])
AT_CLEANUP
@@ -381,7 +381,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
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[])))
@@ -428,7 +428,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+NXT_FLOW_MOD: ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
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]))
@@ -473,7 +473,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
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[[]])))
@@ -510,7 +510,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+NXT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
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]]))
@@ -547,7 +547,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
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[])))
@@ -584,7 +584,7 @@ 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,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+NXT_FLOW_MOD: ADD <any> actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,snaplen=100,sampling_port=56789)
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]))
@@ -497,6 +497,37 @@ 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.
+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 br0 "in_port=2,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,tp_src=8,tp_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,2
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([conntrack - controller])
CHECK_CONNTRACK()
OVS_TRAFFIC_VSWITCHD_START()
This patch adds a 'snaplen' field in sample action (nx_action_sample2). 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. Also, the patch parses OVS_PACKET_ATTR_LEN from nlattr to upcall related structures so the sFlow receiver knows the original packet size before it is truncated. Tested-at: https://travis-ci.org/williamtu/ovs-travis/builds/141704344 Signed-off-by: William Tu <u9012063@gmail.com> --- v1->v2 http://openvswitch.org/pipermail/dev/2016-June/072404.html - Add snaplen to nx_action_sample2 - Since truncate then userspace action is supported in userspace datapath, ,commit aaca4fe0ce9e (ofp-actions: Add truncate action.), remove datapath-specific implementation and testcase. --- include/openvswitch/ofp-actions.h | 1 + lib/dpif-netlink.c | 4 +++- lib/dpif.h | 2 +- lib/ofp-actions.c | 12 +++++++++++- ofproto/ofproto-dpif-sflow.c | 16 +++++++++++++--- ofproto/ofproto-dpif-sflow.h | 2 ++ ofproto/ofproto-dpif-upcall.c | 21 ++++++++++++++++----- ofproto/ofproto-dpif-xlate.c | 22 ++++++++++++++++++++-- tests/ofp-actions.at | 4 ++-- tests/ovs-ofctl.at | 24 ++++++++++++------------ tests/system-traffic.at | 31 +++++++++++++++++++++++++++++++ 11 files changed, 112 insertions(+), 27 deletions(-)