[ovs-dev] [PATCH 2/2] ofproto: Translate NXAST_SAMPLE actions into SAMPLE datapath actions
Romain Lenglet
rlenglet at vmware.com
Mon Dec 10 23:24:06 UTC 2012
---
lib/odp-util.c | 14 ++++++++
lib/odp-util.h | 9 +++++-
ofproto/ofproto-dpif.c | 86 ++++++++++++++++++++++++++++++++++++++++----------
tests/odp.at | 1 +
4 files changed, 93 insertions(+), 17 deletions(-)
diff --git a/lib/odp-util.c b/lib/odp-util.c
index de97fd2..50feeb5 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -279,6 +279,11 @@ 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(obs_point_id=%"PRIu32")",
+ cookie.ipfix.obs_point_id);
+ break;
+
case USER_ACTION_COOKIE_UNSPEC:
default:
ds_put_format(ds, ",userdata=0x%"PRIx64, userdata);
@@ -419,6 +424,7 @@ 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 obs_point_id;
char userdata_s[32];
int vid, pcp;
int n = -1;
@@ -464,6 +470,14 @@ 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(obs_point_id=%lli))%n",
+ &pid, &obs_point_id, &n) > 0 && n > 0) {
+ union user_action_cookie cookie;
+
+ cookie.type = USER_ACTION_COOKIE_IPFIX;
+ 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..44cde1d 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 unused;
+ 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 854ad29..c585038 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3552,7 +3552,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;
@@ -3580,6 +3580,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);
@@ -3624,6 +3627,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)
{
@@ -3661,6 +3671,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;
@@ -5268,6 +5283,30 @@ put_userspace_action(const struct ofproto_dpif *ofproto,
return odp_put_userspace_action(pid, cookie, odp_actions);
}
+/* Compose SAMPLE action for sFlow or IPFIX. */
+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);
+
+ /* Number of packets out of UINT_MAX to 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,
@@ -5309,27 +5348,24 @@ 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(uint32_t obs_point_id, union user_action_cookie *cookie)
+{
+ cookie->type = USER_ACTION_COOKIE_IPFIX;
+ cookie->ipfix.obs_point_id = obs_point_id;
}
/* SAMPLE action must be first action in any given list of actions.
@@ -5841,6 +5877,16 @@ xlate_fin_timeout(struct action_xlate_ctx *ctx,
}
}
+static void
+xlate_sample_action(struct action_xlate_ctx *ctx,
+ const struct ofpact_sample *os)
+{
+ union user_action_cookie cookie;
+ compose_ipfix_cookie(os->obs_point_id, &cookie);
+ compose_sample_action(ctx->ofproto, ctx->odp_actions, &ctx->flow,
+ os->probability, &cookie);
+}
+
static bool
may_receive(const struct ofport_dpif *port, struct action_xlate_ctx *ctx)
{
@@ -5869,6 +5915,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
const struct ofport_dpif *port;
bool was_evictable = true;
const struct ofpact *a;
+ int non_sample_actions_count = 0;
port = get_ofp_port(ctx->ofproto, ctx->flow.in_port);
if (port && !may_receive(port, ctx)) {
@@ -6053,11 +6100,18 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
}
case OFPACT_SAMPLE:
- /* TODO: Check that SAMPLE actions are always the first
- * actions in a flow. */
- /* TODO: Actually implement the translation here. */
+ /* SAMPLE actions should be the first in a flow's actions. */
+ if (non_sample_actions_count > 0) {
+ VLOG_WARN_RL(&rl,
+ "sample action not at beginning of action list");
+ }
+ xlate_sample_action(ctx, ofpact_get_SAMPLE(a));
break;
}
+
+ if (a->type != OFPACT_SAMPLE) {
+ non_sample_actions_count++;
+ }
}
out:
diff --git a/tests/odp.at b/tests/odp.at
index a5f6dbe..bcc32bf 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(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.0.1
More information about the dev
mailing list