This patch allows ofp_packet_out messages to be added to bundles. In a 
multi controller scenario, packet_out messages inside bundles can serve 
as a commit_reply for other controllers - since the original commit_reply 
is only forwarded to the controller that sent the commit_request.

Tested with make check and external controller adding packet_out messages 
to a bundle with different destinations (hosts and controllers). Also tested 
grouping packet_out with port_mod messages in the same bundle. After 
committing the bundle, the destinations received the packet_out.

Signed-off-by: Andre Mantas <aman...@lasige.di.fc.ul.pt>
Submitted-at: https://github.com/openvswitch/ovs/pull/117
---
 lib/ofp-util.c             |  2 +-
 ofproto/bundles.h          |  5 ++++
 ofproto/ofproto-provider.h |  7 +++++
 ofproto/ofproto.c          | 70 ++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index c5353cc..6725220 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -9578,6 +9578,7 @@ ofputil_is_bundlable(enum ofptype type)
         /* Minimum required by OpenFlow 1.4. */
     case OFPTYPE_PORT_MOD:
     case OFPTYPE_FLOW_MOD:
+    case OFPTYPE_PACKET_OUT:
         return true;
 
         /* Nice to have later. */
@@ -9585,7 +9586,6 @@ ofputil_is_bundlable(enum ofptype type)
     case OFPTYPE_GROUP_MOD:
     case OFPTYPE_TABLE_MOD:
     case OFPTYPE_METER_MOD:
-    case OFPTYPE_PACKET_OUT:
     case OFPTYPE_NXT_TLV_TABLE_MOD:
 
         /* Not to be bundlable. */
diff --git a/ofproto/bundles.h b/ofproto/bundles.h
index d045031..61c1b48 100644
--- a/ofproto/bundles.h
+++ b/ofproto/bundles.h
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 
 #include "connmgr.h"
+#include "dp-packet.h"
 #include "ofproto-provider.h"
 #include "openvswitch/ofp-msgs.h"
 #include "openvswitch/ofp-util.h"
@@ -37,6 +38,7 @@ struct ofp_bundle_entry {
     union {
         struct ofproto_flow_mod ofm;   /* ofm.fm.ofpacts must be malloced. */
         struct ofproto_port_mod opm;
+        struct ofproto_packet_out opo; /* opo.po.ofpacts must be malloced */
     };
 
     /* OpenFlow header and some of the message contents for error reporting. */
@@ -89,6 +91,9 @@ ofp_bundle_entry_free(struct ofp_bundle_entry *entry)
     if (entry) {
         if (entry->type == OFPTYPE_FLOW_MOD) {
             free(entry->ofm.fm.ofpacts);
+        } else if (entry->type == OFPTYPE_PACKET_OUT) {
+            dp_packet_delete(entry->opo.payload);
+            free(entry->opo.po.ofpacts);
         }
         free(entry);
     }
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index daa0077..c98f110 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -1814,6 +1814,13 @@ struct ofproto_port_mod {
     struct ofport *port;                /* Affected port. */
 };
 
+/* packet_out with execution context. */
+struct ofproto_packet_out {
+    struct ofputil_packet_out po;
+    struct dp_packet *payload;
+    struct flow flow;
+};
+
 enum ofperr ofproto_flow_mod(struct ofproto *, struct ofproto_flow_mod *)
     OVS_EXCLUDED(ofproto_mutex);
 void ofproto_add_flow(struct ofproto *, const struct match *, int priority,
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index ff6affd..c5a6097 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -6996,6 +6996,8 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, 
uint16_t flags)
                  * effect. */
                 be->ofm.version = version;
                 error = ofproto_flow_mod_start(ofproto, &be->ofm);
+            } else if (be->type == OFPTYPE_PACKET_OUT) {
+                prev_is_port_mod = false;
             } else {
                 OVS_NOT_REACHED();
             }
@@ -7016,7 +7018,7 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, 
uint16_t flags)
                 if (be->type == OFPTYPE_FLOW_MOD) {
                     ofproto_flow_mod_revert(ofproto, &be->ofm);
                 }
-                /* Nothing needs to be reverted for a port mod. */
+                /* Nothing needs to be reverted for a port mod or packet out. 
*/
             }
         } else {
             /* 4. Finish. */
@@ -7042,6 +7044,18 @@ do_bundle_commit(struct ofconn *ofconn, uint32_t id, 
uint16_t flags)
                      * also from OVSDB changes asynchronously to all upcall
                      * processing. */
                     port_mod_finish(ofconn, &be->opm.pm, be->opm.port);
+                } else if (be->type == OFPTYPE_PACKET_OUT) {
+                    /* Try to send the packet. The bundle is committed
+                     * regardless of errors */
+                    error = ofproto->ofproto_class->packet_out(ofproto,
+                                                        be->opo.payload,
+                                                        &(be->opo.flow),
+                                                        be->opo.po.ofpacts,
+                                                        
be->opo.po.ofpacts_len);
+                    if (error) {
+                        VLOG_INFO("Error sending packet out while committing a 
"
+                                  "bundle: %d", error);
+                    }
                 }
             }
         }
@@ -7150,6 +7164,58 @@ handle_bundle_add(struct ofconn *ofconn, const struct 
ofp_header *oh)
             error = ofproto_check_ofpacts(ofproto, bmsg->ofm.fm.ofpacts,
                                           bmsg->ofm.fm.ofpacts_len);
         }
+    } else if (type == OFPTYPE_PACKET_OUT) {
+        uint64_t ofpacts_stub[1024 / 8];
+        struct ofpbuf ofpacts;
+
+        /* Decode message. */
+        ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
+        error = ofputil_decode_packet_out(&(bmsg->opo.po), badd.msg, &ofpacts);
+        /* Same validation steps as in handle_packet_out  */
+        if (error) {
+            goto exit;
+        }
+
+        /* Move actions to heap. */
+        bmsg->opo.po.ofpacts = ofpbuf_steal_data(&ofpacts);
+
+        if (ofp_to_u16(bmsg->opo.po.in_port) >= ofproto->max_ports
+            && ofp_to_u16(bmsg->opo.po.in_port) < ofp_to_u16(OFPP_MAX)) {
+            error = OFPERR_OFPBRC_BAD_PORT;
+            goto exit;
+        }
+
+        /* Get payload. */
+        if (bmsg->opo.po.buffer_id != UINT32_MAX) {
+            error = ofconn_pktbuf_retrieve(ofconn, bmsg->opo.po.buffer_id,
+                                           &(bmsg->opo.payload), NULL);
+            if (error) {
+                goto exit;
+            }
+        } else {
+            /* Ensure that the L3 header is 32-bit aligned. */
+            bmsg->opo.payload = dp_packet_clone_data_with_headroom(
+                                                        bmsg->opo.po.packet,
+                                                        
bmsg->opo.po.packet_len,
+                                                        2);
+        }
+
+        /* Verify actions against packet */
+        flow_extract(bmsg->opo.payload, &(bmsg->opo.flow));
+        bmsg->opo.flow.in_port.ofp_port = bmsg->opo.po.in_port;
+        /* Check actions like for flow mods. */
+        error = ofpacts_check_consistency(bmsg->opo.po.ofpacts,
+                                          bmsg->opo.po.ofpacts_len,
+                                          &(bmsg->opo.flow),
+                                          u16_to_ofp(ofproto->max_ports),
+                                          0, ofproto->n_tables,
+                                          ofconn_get_protocol(ofconn));
+        if (error) {
+            goto exit;
+        }
+
+        error = ofproto_check_ofpacts(ofproto, bmsg->opo.po.ofpacts,
+                                      bmsg->opo.po.ofpacts_len);
     } else {
         OVS_NOT_REACHED();
     }
@@ -7158,7 +7224,7 @@ handle_bundle_add(struct ofconn *ofconn, const struct 
ofp_header *oh)
         error = ofp_bundle_add_message(ofconn, badd.bundle_id, badd.flags,
                                        bmsg);
     }
-
+exit:
     if (error) {
         ofp_bundle_entry_free(bmsg);
     }
-- 
2.5.0

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

Reply via email to