[ovs-dev] [PATCH 2/4] ofproto: Translate NXAST_SAMPLE_IPFIX actions into SAMPLE dp actions
Romain Lenglet
rlenglet at vmware.com
Fri Jan 11 17:55:42 UTC 2013
Signed-off-by: Romain Lenglet <rlenglet at vmware.com>
---
lib/odp-util.c | 19 ++++++++++++
lib/odp-util.h | 9 +++++-
ofproto/ofproto-dpif.c | 83 +++++++++++++++++++++++++++++++++++++++++---------
tests/odp.at | 1 +
4 files changed, 97 insertions(+), 15 deletions(-)
diff --git a/lib/odp-util.c b/lib/odp-util.c
index e2f21da..e8b3748 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -279,6 +279,13 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr)
ds_put_format(ds, ")");
break;
+ case USER_ACTION_COOKIE_IPFIX:
+ ds_put_format(ds, ",IPFIX(probability=%"PRIu16
+ ",obs_point_id=%"PRIu32")",
+ cookie.ipfix.probability,
+ cookie.ipfix.obs_point_id);
+ break;
+
case USER_ACTION_COOKIE_UNSPEC:
default:
ds_put_format(ds, ",userdata=0x%"PRIx64, userdata);
@@ -419,6 +426,8 @@ parse_odp_action(const char *s, const struct simap *port_names,
{
unsigned long long int pid;
unsigned long long int output;
+ unsigned long long int probability;
+ unsigned long long int obs_point_id;
char userdata_s[32];
int vid, pcp;
int n = -1;
@@ -464,6 +473,16 @@ parse_odp_action(const char *s, const struct simap *port_names,
odp_put_userspace_action(pid, &cookie, actions);
return n;
+ } else if (sscanf(s, "userspace(pid=%lli,IPFIX(probability=%lli,"
+ "obs_point_id=%lli))%n",
+ &pid, &probability, &obs_point_id, &n) > 0 && n > 0) {
+ union user_action_cookie cookie;
+
+ cookie.type = USER_ACTION_COOKIE_IPFIX;
+ cookie.ipfix.probability = probability;
+ cookie.ipfix.obs_point_id = obs_point_id;
+ odp_put_userspace_action(pid, &cookie, actions);
+ return n;
} else if (sscanf(s, "userspace(pid=%lli,userdata="
"%31[x0123456789abcdefABCDEF])%n", &pid, userdata_s,
&n) > 0 && n > 0) {
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 9d38f33..bcf4d0e 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -119,7 +119,8 @@ void commit_odp_actions(const struct flow *, struct flow *base,
enum user_action_cookie_type {
USER_ACTION_COOKIE_UNSPEC,
USER_ACTION_COOKIE_SFLOW, /* Packet for sFlow sampling. */
- USER_ACTION_COOKIE_SLOW_PATH /* Userspace must process this flow. */
+ USER_ACTION_COOKIE_SLOW_PATH, /* Userspace must process this flow. */
+ USER_ACTION_COOKIE_IPFIX /* Packet for IPFIX sampling. */
};
/* user_action_cookie is passed as argument to OVS_ACTION_ATTR_USERSPACE.
@@ -138,6 +139,12 @@ union user_action_cookie {
uint16_t unused;
uint32_t reason; /* enum slow_path_reason. */
} slow_path;
+
+ struct {
+ uint16_t type; /* USER_ACTION_COOKIE_IPFIX. */
+ uint16_t probability; /* Sampling probability. */
+ uint32_t obs_point_id; /* Observation Point ID. */
+ } ipfix;
};
BUILD_ASSERT_DECL(sizeof(union user_action_cookie) == 8);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 57470e0..dc0a5f1 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3595,7 +3595,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
hmap_destroy(&todo);
}
-static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL }
+static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL, IPFIX_UPCALL }
classify_upcall(const struct dpif_upcall *upcall)
{
union user_action_cookie cookie;
@@ -3623,6 +3623,9 @@ classify_upcall(const struct dpif_upcall *upcall)
case USER_ACTION_COOKIE_SLOW_PATH:
return MISS_UPCALL;
+ case USER_ACTION_COOKIE_IPFIX:
+ return IPFIX_UPCALL;
+
case USER_ACTION_COOKIE_UNSPEC:
default:
VLOG_WARN_RL(&rl, "invalid user cookie : 0x%"PRIx64, upcall->userdata);
@@ -3650,6 +3653,13 @@ handle_sflow_upcall(struct dpif_backer *backer,
odp_in_port, &cookie);
}
+static void
+handle_ipfix_upcall(struct dpif_backer *backer OVS_UNUSED,
+ const struct dpif_upcall *upcall OVS_UNUSED)
+{
+ /* TODO: Send an IPFIX sample. */
+}
+
static int
handle_upcalls(struct dpif_backer *backer, unsigned int max_batch)
{
@@ -3687,6 +3697,11 @@ handle_upcalls(struct dpif_backer *backer, unsigned int max_batch)
ofpbuf_uninit(buf);
break;
+ case IPFIX_UPCALL:
+ handle_ipfix_upcall(backer, upcall);
+ ofpbuf_uninit(buf);
+ break;
+
case BAD_UPCALL:
ofpbuf_uninit(buf);
break;
@@ -5294,6 +5309,32 @@ put_userspace_action(const struct ofproto_dpif *ofproto,
return odp_put_userspace_action(pid, cookie, odp_actions);
}
+/* Compose SAMPLE action for sFlow or IPFIX. The given probability is
+ * the number of packets out of UINT32_MAX to sample. The given
+ * cookie is passed back in the callback for each sampled packet.
+ */
+static size_t
+compose_sample_action(const struct ofproto_dpif *ofproto,
+ struct ofpbuf *odp_actions,
+ const struct flow *flow,
+ const uint32_t probability,
+ const union user_action_cookie *cookie)
+{
+ size_t sample_offset, actions_offset;
+ int cookie_offset;
+
+ sample_offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SAMPLE);
+
+ nl_msg_put_u32(odp_actions, OVS_SAMPLE_ATTR_PROBABILITY, probability);
+
+ actions_offset = nl_msg_start_nested(odp_actions, OVS_SAMPLE_ATTR_ACTIONS);
+ cookie_offset = put_userspace_action(ofproto, odp_actions, flow, cookie);
+
+ nl_msg_end_nested(odp_actions, actions_offset);
+ nl_msg_end_nested(odp_actions, sample_offset);
+ return cookie_offset;
+}
+
static void
compose_sflow_cookie(const struct ofproto_dpif *ofproto,
ovs_be16 vlan_tci, uint32_t odp_port,
@@ -5335,27 +5376,26 @@ compose_sflow_action(const struct ofproto_dpif *ofproto,
{
uint32_t probability;
union user_action_cookie cookie;
- size_t sample_offset, actions_offset;
- int cookie_offset;
if (!ofproto->sflow || flow->in_port == OFPP_NONE) {
return 0;
}
- sample_offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SAMPLE);
-
- /* Number of packets out of UINT_MAX to sample. */
probability = dpif_sflow_get_probability(ofproto->sflow);
- nl_msg_put_u32(odp_actions, OVS_SAMPLE_ATTR_PROBABILITY, probability);
-
- actions_offset = nl_msg_start_nested(odp_actions, OVS_SAMPLE_ATTR_ACTIONS);
compose_sflow_cookie(ofproto, htons(0), odp_port,
odp_port == OVSP_NONE ? 0 : 1, &cookie);
- cookie_offset = put_userspace_action(ofproto, odp_actions, flow, &cookie);
- nl_msg_end_nested(odp_actions, actions_offset);
- nl_msg_end_nested(odp_actions, sample_offset);
- return cookie_offset;
+ return compose_sample_action(ofproto, odp_actions, flow, probability,
+ &cookie);
+}
+
+static void
+compose_ipfix_cookie(uint16_t probability, uint32_t obs_point_id,
+ union user_action_cookie *cookie)
+{
+ cookie->type = USER_ACTION_COOKIE_IPFIX;
+ cookie->ipfix.probability = probability;
+ cookie->ipfix.obs_point_id = obs_point_id;
}
/* SAMPLE action must be first action in any given list of actions.
@@ -5863,6 +5903,21 @@ xlate_fin_timeout(struct action_xlate_ctx *ctx,
}
}
+static void
+xlate_sample_ipfix_action(struct action_xlate_ctx *ctx,
+ const struct ofpact_sample_ipfix *osi)
+{
+ if (osi->probability > 0) {
+ union user_action_cookie cookie;
+ /* Scale the probability from 16-bit to 32-bit while
+ * representing the exact same percentage. */
+ uint32_t probability = (osi->probability << 16) | osi->probability;
+ compose_ipfix_cookie(osi->probability, osi->obs_point_id, &cookie);
+ compose_sample_action(ctx->ofproto, ctx->odp_actions, &ctx->flow,
+ probability, &cookie);
+ }
+}
+
static bool
may_receive(const struct ofport_dpif *port, struct action_xlate_ctx *ctx)
{
@@ -6075,7 +6130,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
}
case OFPACT_SAMPLE_IPFIX:
- /* TODO: Actually implement the translation here. */
+ xlate_sample_ipfix_action(ctx, ofpact_get_SAMPLE_IPFIX(a));
break;
}
}
diff --git a/tests/odp.at b/tests/odp.at
index 009ac36..dd03fd9 100644
--- a/tests/odp.at
+++ b/tests/odp.at
@@ -76,6 +76,7 @@ userspace(pid=9765,slow_path())
userspace(pid=9765,slow_path(cfm))
userspace(pid=9765,slow_path(cfm,match))
userspace(pid=9123,userdata=0x815309)
+userspace(pid=6633,IPFIX(probability=123,obs_point_id=12345))
set(tun_id(0x7f10354))
set(in_port(2))
set(eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15))
--
1.8.1
More information about the dev
mailing list