[ovs-dev] [no-slow 4/6] ofproto: Add 'ofproto_uuid' and 'ofp_in_port' to user action cookie.

Justin Pettit jpettit at ovn.org
Thu Dec 21 22:25:13 UTC 2017


Previously, the ofproto instance and OpenFlow port have been derived
based on the datapath port number.  This change explicitly declares them
both, which will be helpful in future commits that no longer can depend
on having a unique datapath port (e.g., a source port that represents
the controller).

Signed-off-by: Justin Pettit <jpettit at ovn.org>
---
 lib/odp-util.c                | 27 ++++++++++-------
 lib/odp-util.h                | 24 ++++++++++-----
 ofproto/ofproto-dpif-upcall.c | 70 +++++++++++++++++++++++++++----------------
 ofproto/ofproto-dpif-xlate.c  | 19 ++++++++----
 ofproto/ofproto-dpif.c        |  5 +---
 ofproto/ofproto-dpif.h        |  2 ++
 6 files changed, 95 insertions(+), 52 deletions(-)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index a3211118c17c..173a868e0728 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -431,7 +431,7 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr,
         bool userdata_unspec = true;
         union user_action_cookie cookie;
 
-        if (userdata_len >= sizeof cookie.type
+        if (userdata_len >= sizeof cookie.header.type
             && userdata_len <= sizeof cookie) {
 
             memset(&cookie, 0, sizeof cookie);
@@ -440,20 +440,20 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr,
             userdata_unspec = false;
 
             if (userdata_len == sizeof cookie.sflow
-                && cookie.type == USER_ACTION_COOKIE_SFLOW) {
+                && cookie.header.type == USER_ACTION_COOKIE_SFLOW) {
                 ds_put_format(ds, ",sFlow("
                               "vid=%"PRIu16",pcp=%d,output=%"PRIu32")",
                               vlan_tci_to_vid(cookie.sflow.vlan_tci),
                               vlan_tci_to_pcp(cookie.sflow.vlan_tci),
                               cookie.sflow.output);
             } else if (userdata_len == sizeof cookie.slow_path
-                       && cookie.type == USER_ACTION_COOKIE_SLOW_PATH) {
+                       && cookie.header.type == USER_ACTION_COOKIE_SLOW_PATH) {
                 ds_put_cstr(ds, ",slow_path(");
                 format_flags(ds, slow_path_reason_to_string,
                              cookie.slow_path.reason, ',');
                 ds_put_format(ds, ")");
             } else if (userdata_len == sizeof cookie.flow_sample
-                       && cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
+                      && cookie.header.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
                 ds_put_format(ds, ",flow_sample(probability=%"PRIu16
                               ",collector_set_id=%"PRIu32
                               ",obs_domain_id=%"PRIu32
@@ -472,7 +472,7 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr,
                 }
                 ds_put_char(ds, ')');
             } else if (userdata_len >= sizeof cookie.ipfix
-                       && cookie.type == USER_ACTION_COOKIE_IPFIX) {
+                       && cookie.header.type == USER_ACTION_COOKIE_IPFIX) {
                 ds_put_format(ds, ",ipfix(output_port=");
                 odp_portno_name_format(portno_names,
                                        cookie.ipfix.output_odp_port, ds);
@@ -1132,7 +1132,9 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
                 tci |= VLAN_CFI;
             }
 
-            cookie.type = USER_ACTION_COOKIE_SFLOW;
+            cookie.header.type = USER_ACTION_COOKIE_SFLOW;
+            cookie.header.ofp_in_port = OFPP_NONE;
+            cookie.header.ofproto_uuid = UUID_ZERO;
             cookie.sflow.vlan_tci = htons(tci);
             cookie.sflow.output = output;
             user_data = &cookie;
@@ -1140,8 +1142,9 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
         } else if (ovs_scan(&s[n], ",slow_path(%n",
                             &n1)) {
             n += n1;
-            cookie.type = USER_ACTION_COOKIE_SLOW_PATH;
-            cookie.slow_path.unused = 0;
+            cookie.header.type = USER_ACTION_COOKIE_SLOW_PATH;
+            cookie.header.ofp_in_port = OFPP_NONE;
+            cookie.header.ofproto_uuid = UUID_ZERO;
             cookie.slow_path.reason = 0;
 
             res = parse_odp_flags(&s[n], slow_path_reason_to_string,
@@ -1164,7 +1167,9 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
                             &output, &n1)) {
             n += n1;
 
-            cookie.type = USER_ACTION_COOKIE_FLOW_SAMPLE;
+            cookie.header.type = USER_ACTION_COOKIE_FLOW_SAMPLE;
+            cookie.header.ofp_in_port = OFPP_NONE;
+            cookie.header.ofproto_uuid = UUID_ZERO;
             cookie.flow_sample.probability = probability;
             cookie.flow_sample.collector_set_id = collector_set_id;
             cookie.flow_sample.obs_domain_id = obs_domain_id;
@@ -1190,7 +1195,9 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
         } else if (ovs_scan(&s[n], ",ipfix(output_port=%"SCNi32")%n",
                             &output, &n1) ) {
             n += n1;
-            cookie.type = USER_ACTION_COOKIE_IPFIX;
+            cookie.header.type = USER_ACTION_COOKIE_IPFIX;
+            cookie.header.ofp_in_port = OFPP_NONE;
+            cookie.header.ofproto_uuid = UUID_ZERO;
             cookie.ipfix.output_odp_port = u32_to_odp(output);
             user_data = &cookie;
             user_data_size = sizeof cookie.ipfix;
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 72a3c30d6d37..040334695835 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -25,6 +25,7 @@
 #include "hash.h"
 #include "openvswitch/hmap.h"
 #include "openvswitch/ofp-actions.h"
+#include "openvswitch/uuid.h"
 #include "odp-netlink.h"
 #include "openflow/openflow.h"
 #include "util.h"
@@ -295,24 +296,32 @@ enum user_action_cookie_type {
     USER_ACTION_COOKIE_IPFIX,        /* Packet for per-bridge IPFIX sampling. */
 };
 
+struct user_action_cookie_header {
+    enum user_action_cookie_type type; /* One of USER_ACTION_COOKIE_*" */
+    ofp_port_t ofp_in_port;            /* OpenFlow in port, or OFPP_NONE. */
+    struct uuid ofproto_uuid;          /* UUID of ofproto-dpif. */
+};
+
 /* user_action_cookie is passed as argument to OVS_ACTION_ATTR_USERSPACE. */
 union user_action_cookie {
-    uint16_t type;              /* enum user_action_cookie_type. */
+    struct user_action_cookie_header header;
 
     struct {
-        uint16_t type;          /* USER_ACTION_COOKIE_SFLOW. */
+        /* USER_ACTION_COOKIE_SFLOW. */
+        struct user_action_cookie_header header;
         ovs_be16 vlan_tci;      /* Destination VLAN TCI. */
         uint32_t output;        /* SFL_FLOW_SAMPLE_TYPE 'output' value. */
     } sflow;
 
     struct {
-        uint16_t type;          /* USER_ACTION_COOKIE_SLOW_PATH. */
-        uint16_t unused;
+        /* USER_ACTION_COOKIE_SLOW_PATH. */
+        struct user_action_cookie_header header;
         uint32_t reason;        /* enum slow_path_reason. */
     } slow_path;
 
     struct {
-        uint16_t type;          /* USER_ACTION_COOKIE_FLOW_SAMPLE. */
+        /* USER_ACTION_COOKIE_FLOW_SAMPLE. */
+        struct user_action_cookie_header header;
         uint16_t probability;   /* Sampling probability. */
         uint32_t collector_set_id; /* ID of IPFIX collector set. */
         uint32_t obs_domain_id; /* Observation Domain ID. */
@@ -322,11 +331,12 @@ union user_action_cookie {
     } flow_sample;
 
     struct {
-        uint16_t   type;            /* USER_ACTION_COOKIE_IPFIX. */
+        /* USER_ACTION_COOKIE_IPFIX. */
+        struct user_action_cookie_header header;
         odp_port_t output_odp_port; /* The output odp port. */
     } ipfix;
 };
-BUILD_ASSERT_DECL(sizeof(union user_action_cookie) == 24);
+BUILD_ASSERT_DECL(sizeof(union user_action_cookie) == 48);
 
 size_t odp_put_userspace_action(uint32_t pid,
                                 const void *userdata, size_t userdata_size,
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 46b75fe35a2b..88501803b5b8 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -38,6 +38,7 @@
 #include "packets.h"
 #include "openvswitch/poll-loop.h"
 #include "seq.h"
+#include "tunnel.h"
 #include "unixctl.h"
 #include "openvswitch/vlog.h"
 
@@ -207,7 +208,7 @@ struct upcall {
     const ovs_u128 *ufid;          /* Unique identifier for 'flow'. */
     unsigned pmd_id;               /* Datapath poll mode driver id. */
     const struct dp_packet *packet;   /* Packet associated with this upcall. */
-    ofp_port_t in_port;            /* OpenFlow in port, or OFPP_NONE. */
+    ofp_port_t ofp_in_port;        /* OpenFlow in port, or OFPP_NONE. */
     uint16_t mru;                  /* If !0, Maximum receive unit of
                                       fragmented IP packet */
 
@@ -998,7 +999,7 @@ classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata,
         return BAD_UPCALL;
     }
     userdata_len = nl_attr_get_size(userdata);
-    if (userdata_len < sizeof cookie->type
+    if (userdata_len < sizeof cookie->header.type
         || userdata_len > sizeof *cookie) {
         VLOG_WARN_RL(&rl, "action upcall cookie has unexpected size %"PRIuSIZE,
                      userdata_len);
@@ -1007,21 +1008,21 @@ classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata,
 
     memcpy(cookie, nl_attr_get(userdata), userdata_len);
 
-    if (userdata_len == MAX(8, sizeof cookie->sflow)
-        && cookie->type == USER_ACTION_COOKIE_SFLOW) {
+    if (userdata_len == sizeof cookie->sflow
+        && cookie->header.type == USER_ACTION_COOKIE_SFLOW) {
         return SFLOW_UPCALL;
-    } else if (userdata_len == MAX(8, sizeof cookie->slow_path)
-               && cookie->type == USER_ACTION_COOKIE_SLOW_PATH) {
+    } else if (userdata_len == sizeof cookie->slow_path
+               && cookie->header.type == USER_ACTION_COOKIE_SLOW_PATH) {
         return SLOW_PATH_UPCALL;
-    } else if (userdata_len == MAX(8, sizeof cookie->flow_sample)
-               && cookie->type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
+    } else if (userdata_len == sizeof cookie->flow_sample
+               && cookie->header.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {
         return FLOW_SAMPLE_UPCALL;
-    } else if (userdata_len == MAX(8, sizeof cookie->ipfix)
-               && cookie->type == USER_ACTION_COOKIE_IPFIX) {
+    } else if (userdata_len == sizeof cookie->ipfix
+               && cookie->header.type == USER_ACTION_COOKIE_IPFIX) {
         return IPFIX_UPCALL;
     } else {
         VLOG_WARN_RL(&rl, "invalid user cookie of type %"PRIu16
-                     " and size %"PRIuSIZE, cookie->type, userdata_len);
+                     " and size %"PRIuSIZE, cookie->header.type, userdata_len);
         return BAD_UPCALL;
     }
 }
@@ -1030,16 +1031,18 @@ classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata,
  * initialized with at least 128 bytes of space. */
 static void
 compose_slow_path(struct udpif *udpif, struct xlate_out *xout,
-                  const struct flow *flow, odp_port_t odp_in_port,
+                  const struct flow *flow,
+                  odp_port_t odp_in_port, ofp_port_t ofp_in_port,
                   struct ofpbuf *buf, uint32_t slowpath_meter_id,
-                  uint32_t controller_meter_id)
+                  uint32_t controller_meter_id, struct uuid *ofproto_uuid)
 {
     union user_action_cookie cookie;
     odp_port_t port;
     uint32_t pid;
 
-    cookie.type = USER_ACTION_COOKIE_SLOW_PATH;
-    cookie.slow_path.unused = 0;
+    cookie.header.type = USER_ACTION_COOKIE_SLOW_PATH;
+    cookie.header.ofp_in_port = ofp_in_port;
+    cookie.header.ofproto_uuid = *ofproto_uuid;
     cookie.slow_path.reason = xout->slow;
 
     port = xout->slow & (SLOW_CFM | SLOW_BFD | SLOW_LACP | SLOW_STP)
@@ -1086,12 +1089,23 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
     upcall->type = classify_upcall(type, userdata, &upcall->cookie);
     if (upcall->type == BAD_UPCALL) {
         return EAGAIN;
-    }
-
-    error = xlate_lookup(backer, flow, &upcall->ofproto, &upcall->ipfix,
-                         &upcall->sflow, NULL, &upcall->in_port);
-    if (error) {
-        return error;
+    } else if (upcall->type == MISS_UPCALL) {
+        error = xlate_lookup(backer, flow, &upcall->ofproto, &upcall->ipfix,
+                             &upcall->sflow, NULL, &upcall->ofp_in_port);
+        if (error) {
+            return error;
+        }
+    } else {
+        struct ofproto_dpif *ofproto
+             = ofproto_dpif_lookup_by_uuid(&upcall->cookie.header.ofproto_uuid);
+        if (!ofproto) {
+            VLOG_INFO_RL(&rl, "upcall could not find ofproto");
+            return ENODEV;
+        }
+        upcall->ofproto = ofproto;
+        upcall->ipfix = ofproto->ipfix;
+        upcall->sflow = ofproto->sflow;
+        upcall->ofp_in_port = upcall->cookie.header.ofp_in_port;
     }
 
     upcall->recirc = NULL;
@@ -1132,7 +1146,7 @@ upcall_xlate(struct udpif *udpif, struct upcall *upcall,
 
     xlate_in_init(&xin, upcall->ofproto,
                   ofproto_dpif_get_tables_version(upcall->ofproto),
-                  upcall->flow, upcall->in_port, NULL,
+                  upcall->flow, upcall->ofp_in_port, NULL,
                   stats.tcp_flags, upcall->packet, wc, odp_actions);
 
     if (upcall->type == MISS_UPCALL) {
@@ -1177,8 +1191,9 @@ upcall_xlate(struct udpif *udpif, struct upcall *upcall,
         uint32_t cmid = upcall->ofproto->up.controller_meter_id;
         /* upcall->put_actions already initialized by upcall_receive(). */
         compose_slow_path(udpif, &upcall->xout, upcall->flow,
-                          upcall->flow->in_port.odp_port,
-                          &upcall->put_actions, smid, cmid);
+                          upcall->flow->in_port.odp_port, upcall->ofp_in_port,
+                          &upcall->put_actions, smid, cmid,
+                          &upcall->ofproto->uuid);
     }
 
     /* This function is also called for slow-pathed flows.  As we are only
@@ -2045,13 +2060,16 @@ revalidate_ukey__(struct udpif *udpif, const struct udpif_key *ukey,
 
     if (xoutp->slow) {
         struct ofproto_dpif *ofproto;
-        ofproto = xlate_lookup_ofproto(udpif->backer, &ctx.flow, NULL);
+        ofp_port_t ofp_in_port;
+
+        ofproto = xlate_lookup_ofproto(udpif->backer, &ctx.flow,
+                                       &ofp_in_port);
         uint32_t smid = ofproto ? ofproto->up.slowpath_meter_id : UINT32_MAX;
         uint32_t cmid = ofproto ? ofproto->up.controller_meter_id : UINT32_MAX;
 
         ofpbuf_clear(odp_actions);
         compose_slow_path(udpif, xoutp, &ctx.flow, ctx.flow.in_port.odp_port,
-                          odp_actions, smid, cmid);
+                          ofp_in_port, odp_actions, smid, cmid, &ofproto->uuid);
     }
 
     if (odp_flow_key_to_mask(ukey->mask, ukey->mask_len, &dp_mask, &ctx.flow)
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 3bdd64d4d552..ec92c6a730bf 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2927,7 +2927,13 @@ compose_sflow_action(struct xlate_ctx *ctx)
         return 0;
     }
 
-    union user_action_cookie cookie = { .type = USER_ACTION_COOKIE_SFLOW };
+    union user_action_cookie cookie = {
+        .sflow = {
+            .header.type = USER_ACTION_COOKIE_SFLOW,
+            .header.ofp_in_port = ctx->xin->flow.in_port.ofp_port,
+            .header.ofproto_uuid = ctx->xbridge->ofproto->uuid
+        }
+    };
     return compose_sample_action(ctx, dpif_sflow_get_probability(sflow),
                                  &cookie, sizeof cookie.sflow, ODPP_NONE,
                                  true);
@@ -2970,7 +2976,9 @@ compose_ipfix_action(struct xlate_ctx *ctx, odp_port_t output_odp_port)
 
     union user_action_cookie cookie = {
         .ipfix = {
-            .type = USER_ACTION_COOKIE_IPFIX,
+            .header.type = USER_ACTION_COOKIE_IPFIX,
+            .header.ofp_in_port = ctx->xin->flow.in_port.ofp_port,
+            .header.ofproto_uuid = ctx->xbridge->ofproto->uuid,
             .output_odp_port = output_odp_port,
         }
     };
@@ -2992,9 +3000,8 @@ fix_sflow_action(struct xlate_ctx *ctx, unsigned int user_cookie_offset)
 
     cookie = ofpbuf_at(ctx->odp_actions, user_cookie_offset,
                        sizeof cookie->sflow);
-    ovs_assert(cookie->type == USER_ACTION_COOKIE_SFLOW);
+    ovs_assert(cookie->header.type == USER_ACTION_COOKIE_SFLOW);
 
-    cookie->type = USER_ACTION_COOKIE_SFLOW;
     cookie->sflow.vlan_tci = base->vlans[0].tci;
 
     /* See http://www.sflow.org/sflow_version_5.txt (search for "Input/output
@@ -5265,7 +5272,9 @@ xlate_sample_action(struct xlate_ctx *ctx,
 
     union user_action_cookie cookie = {
         .flow_sample = {
-            .type = USER_ACTION_COOKIE_FLOW_SAMPLE,
+            .header.type = USER_ACTION_COOKIE_FLOW_SAMPLE,
+            .header.ofp_in_port = ctx->xin->flow.in_port.ofp_port,
+            .header.ofproto_uuid = ctx->xbridge->ofproto->uuid,
             .probability = os->probability,
             .collector_set_id = os->collector_set_id,
             .obs_domain_id = os->obs_domain_id,
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 7d628e11328a..b0a1390d816b 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -161,9 +161,6 @@ struct ofport_dpif {
 static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *,
                                        ofp_port_t);
 
-static ofp_port_t odp_port_to_ofp_port(const struct ofproto_dpif *,
-                                       odp_port_t);
-
 static struct ofport_dpif *
 ofport_dpif_cast(const struct ofport *ofport)
 {
@@ -5622,7 +5619,7 @@ odp_port_to_ofport(const struct dpif_backer *backer, odp_port_t odp_port)
     return NULL;
 }
 
-static ofp_port_t
+ofp_port_t
 odp_port_to_ofp_port(const struct ofproto_dpif *ofproto, odp_port_t odp_port)
 {
     struct ofport_dpif *port;
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index 0bb07638c15e..0f7086824f3d 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -248,6 +248,8 @@ struct dpif_backer {
 extern struct shash all_dpif_backers;
 
 struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t);
+
+ofp_port_t odp_port_to_ofp_port(const struct ofproto_dpif *, odp_port_t);
 
 /* A bridge based on a "dpif" datapath. */
 
-- 
2.7.4



More information about the dev mailing list