> On Jun 1, 2015, at 2:48 PM, Ben Pfaff <b...@nicira.com> wrote:
> 
> On Mon, Jun 01, 2015 at 01:58:41PM -0700, Jarno Rajahalme wrote:
>> 
>>> On Jun 1, 2015, at 1:47 PM, Jarno Rajahalme <jrajaha...@nicira.com> wrote:
>>> 
>>> 
>>>> On May 29, 2015, at 5:38 PM, Ben Pfaff <b...@nicira.com> wrote:
>>>> 
>>>> On Mon, May 18, 2015 at 04:10:15PM -0700, Jarno Rajahalme wrote:
>>>>> OpenFlow bundle messages should be decoded and validated at the time
>>>>> they are added to the bundle.  This commit does this for flow mod and
>>>>> port mod messages.
>>>>> 
>>>>> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
>>>> 
>>>> It's pretty expensive to give every ofp_bundle_entry a 1-kB stub for
>>>> actions, when there might be many thousands of them allocated at a time
>>>> into a bundle.  It might be better to accumulate the actions into a
>>>> function-local stub then use ofpbuf_clone() or similar to allocate a
>>>> correctly sized buffer for ofp_bundle_entry.
>>>> 
>>>> I guess that it would be even cheaper, memory-wise (struct match by
>>>> itself is almost 1/2 kB!), to just decode the raw message a second time
>>>> when we apply the bundle, but maybe that is not worth the extra trouble.
>>> 
>>> I???ll look if I can get the actual replacement rule created at the 
>>> validation time for the versioned case (after patch 17). For this patch, 
>>> I???ll just make the stub smaller (64 bytes?).
>>> 
>> 
>> Are you OK with deferring further optimization to the end of the series? 
>> I.e., can I push this with a smaller stub?
> 
> Why bother with a stub at all in the struct?  I suggest using a
> function-local stub on the stack when decoding the flow_mod, then
> ofpbuf_steal_data() to put that data into the ofp_bundle.


OK, I got it now :-) Incremental:

diff --git a/ofproto/bundles.h b/ofproto/bundles.h
index 7084b08..c8ce5c9 100644
--- a/ofproto/bundles.h
+++ b/ofproto/bundles.h
@@ -33,13 +33,11 @@ extern "C" {
 struct ofp_bundle_entry {
     struct ovs_list   node;
     ovs_be32          xid;   /* For error returns. */
-    enum ofptype      type;
+    enum ofptype      type;  /* OFPTYPE_FLOW_MOD or OFPTYPE_PORT_MOD. */
     union {
-        struct ofputil_flow_mod fm;
+        struct ofputil_flow_mod fm;   /* 'fm.ofpacts' must be malloced. */
         struct ofputil_port_mod pm;
     };
-    struct ofpbuf ofpacts;
-    uint64_t ofpacts_stub[64 / 8];
 };
 
 static inline struct ofp_bundle_entry *ofp_bundle_entry_alloc(
@@ -59,8 +57,6 @@ ofp_bundle_entry_alloc(enum ofptype type, ovs_be32 xid)
 {
     struct ofp_bundle_entry *entry = xmalloc(sizeof *entry);
 
-    ofpbuf_use_stub(&entry->ofpacts, entry->ofpacts_stub,
-                    sizeof entry->ofpacts_stub);
     entry->xid = xid;
     entry->type = type;
 
@@ -70,7 +66,9 @@ ofp_bundle_entry_alloc(enum ofptype type, ovs_be32 xid)
 static inline void ofp_bundle_entry_free(struct ofp_bundle_entry *entry)
 {
     if (entry) {
-        ofpbuf_uninit(&entry->ofpacts);
+        if (entry->type == OFPTYPE_FLOW_MOD) {
+            free(entry->fm.ofpacts);
+        }
         free(entry);
     }
 }
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 54d66b6..0a8c82a 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -6378,20 +6378,26 @@ handle_bundle_add(struct ofconn *ofconn, const struct 
ofp_header *oh)
     if (type == OFPTYPE_PORT_MOD) {
         error = ofputil_decode_port_mod(badd.msg, &bmsg->pm, false);
     } else if (type == OFPTYPE_FLOW_MOD) {
+        struct ofpbuf ofpacts;
+        uint64_t ofpacts_stub[1024 / 8];
+
+        ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
         error = ofputil_decode_flow_mod(&bmsg->fm, badd.msg,
                                         ofconn_get_protocol(ofconn),
-                                        &bmsg->ofpacts,
+                                        &ofpacts,
                                         u16_to_ofp(ofproto->max_ports),
                                         ofproto->n_tables);
+        /* Move actions to heap. */
+        bmsg->fm.ofpacts = ofpbuf_steal_data(&ofpacts);
+
+        if (!error && bmsg->fm.ofpacts_len) {
+            error = ofproto_check_ofpacts(ofproto, bmsg->fm.ofpacts,
+                                          bmsg->fm.ofpacts_len);
+        }
     } else {
         OVS_NOT_REACHED();
     }
 
-    if (!error && bmsg->ofpacts.size) {
-        error = ofproto_check_ofpacts(ofproto, bmsg->ofpacts.data,
-                                      bmsg->ofpacts.size);
-    }
-
     if (!error) {
         error = ofp_bundle_add_message(ofconn, badd.bundle_id, badd.flags,
                                        bmsg);


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

Reply via email to