[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