The "ipfix" upcall is used to per-bridge packet sampling to IPFIX
collectors.

Signed-off-by: Romain Lenglet <rleng...@vmware.com>
---
 lib/odp-util.c         | 11 +++++++++++
 lib/odp-util.h         |  7 ++++++-
 ofproto/ofproto-dpif.c | 26 +++++++++++++++++++++++++-
 tests/odp.at           |  1 +
 4 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index 52923fc..b755c7a 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -300,6 +300,9 @@ format_odp_userspace_action(struct ds *ds, const struct 
nlattr *attr)
                               cookie.flow_sample.collector_set_id,
                               cookie.flow_sample.obs_domain_id,
                               cookie.flow_sample.obs_point_id);
+            } else if (userdata_len == sizeof cookie.ipfix
+                       && cookie.type == USER_ACTION_COOKIE_IPFIX) {
+                ds_put_format(ds, ",ipfix");
             } else {
                 userdata_unspec = true;
             }
@@ -535,6 +538,14 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
             odp_put_userspace_action(pid, &cookie, sizeof cookie.flow_sample,
                                      actions);
             return n;
+        } else if (sscanf(s, "userspace(pid=%lli,ipfix)%n", &pid, &n) > 0
+                   && n > 0) {
+            union user_action_cookie cookie;
+
+            cookie.type = USER_ACTION_COOKIE_IPFIX;
+            odp_put_userspace_action(pid, &cookie, sizeof cookie.ipfix,
+                                     actions);
+            return n;
         } else if (sscanf(s, "userspace(pid=%lli,userdata(%n", &pid, &n) > 0
                    && n > 0) {
             struct ofpbuf buf;
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 0198a54..0b34383 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -127,9 +127,10 @@ 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_SFLOW,        /* Packet for per-bridge sFlow sampling. 
*/
     USER_ACTION_COOKIE_SLOW_PATH,    /* Userspace must process this flow. */
     USER_ACTION_COOKIE_FLOW_SAMPLE,  /* Packet for per-flow sampling. */
+    USER_ACTION_COOKIE_IPFIX,        /* Packet for per-bridge IPFIX sampling. 
*/
 };
 
 /* user_action_cookie is passed as argument to OVS_ACTION_ATTR_USERSPACE.
@@ -156,6 +157,10 @@ union user_action_cookie {
         uint32_t obs_domain_id; /* Observation Domain ID. */
         uint32_t obs_point_id;  /* Observation Point ID. */
     } flow_sample;
+
+    struct {
+        uint16_t type;          /* USER_ACTION_COOKIE_IPFIX. */
+    } ipfix;
 };
 BUILD_ASSERT_DECL(sizeof(union user_action_cookie) == 16);
 
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 8708d0f..c11e3c3 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -4007,7 +4007,8 @@ handle_miss_upcalls(struct dpif_backer *backer, struct 
dpif_upcall *upcalls,
     hmap_destroy(&todo);
 }
 
-static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL, FLOW_SAMPLE_UPCALL }
+static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL, FLOW_SAMPLE_UPCALL,
+              IPFIX_UPCALL }
 classify_upcall(const struct dpif_upcall *upcall)
 {
     size_t userdata_len;
@@ -4050,6 +4051,9 @@ classify_upcall(const struct dpif_upcall *upcall)
     } else if (userdata_len == sizeof cookie.flow_sample
                && cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
         return FLOW_SAMPLE_UPCALL;
+    } else if (userdata_len == sizeof cookie.ipfix
+               && cookie.type == USER_ACTION_COOKIE_IPFIX) {
+        return IPFIX_UPCALL;
     } else {
         VLOG_WARN_RL(&rl, "invalid user cookie of type %"PRIu16
                      " and size %zu", cookie.type, userdata_len);
@@ -4085,6 +4089,13 @@ handle_flow_sample_upcall(struct dpif_backer *backer 
OVS_UNUSED,
     /* TODO: Send a IPFIX flow record to each IPFIX collector. */
 }
 
+static void
+handle_ipfix_upcall(struct dpif_backer *backer OVS_UNUSED,
+                    const struct dpif_upcall *upcall OVS_UNUSED)
+{
+    /* TODO: Send IPFIX flow records. */
+}
+
 static int
 handle_upcalls(struct dpif_backer *backer, unsigned int max_batch)
 {
@@ -4127,6 +4138,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;
@@ -5933,6 +5949,14 @@ compose_flow_sample_cookie(uint16_t probability, 
uint32_t collector_set_id,
     cookie->flow_sample.obs_point_id = obs_point_id;
 }
 
+static void compose_ipfix_cookie(union user_action_cookie *) OVS_UNUSED;
+
+static void
+compose_ipfix_cookie(union user_action_cookie *cookie)
+{
+    cookie->type = USER_ACTION_COOKIE_IPFIX;
+}
+
 /* SAMPLE action must be first action in any given list of actions.
  * At this point we do not have all information required to build it. So try to
  * build sample action as complete as possible. */
diff --git a/tests/odp.at b/tests/odp.at
index ec99ec5..a6bcdf5 100644
--- a/tests/odp.at
+++ b/tests/odp.at
@@ -90,6 +90,7 @@ userspace(pid=9765,slow_path(cfm))
 userspace(pid=9765,slow_path(cfm,match))
 userspace(pid=1234567,userdata(0102030405060708090a0b0c0d0e0f))
 
userspace(pid=6633,flow_sample(probability=123,collector_set_id=1234,obs_domain_id=2345,obs_point_id=3456))
+userspace(pid=6633,ipfix)
 set(in_port(2))
 set(eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15))
 set(eth_type(0x1234))
-- 
1.8.1.3

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to