When OF11+ only actions is introduced, ofpacts_put_openflow10() will be
unable to handle all ofp-actions. So allow it return error in that case.

Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp>
---
v4
- newly introduced
---
 lib/learning-switch.c |   35 +++++++++++++++++++++++++----
 lib/ofp-actions.c     |   11 ++++++--
 lib/ofp-actions.h     |    4 +-
 lib/ofp-util.c        |   59 ++++++++++++++++++++++++++++++++++++++----------
 lib/ofp-util.h        |   15 ++++++-----
 ofproto/connmgr.c     |   16 ++++++++++--
 ofproto/ofproto.c     |   13 +++++++++-
 utilities/ovs-ofctl.c |   35 +++++++++++++++++++++++++----
 8 files changed, 148 insertions(+), 40 deletions(-)

diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index 887a365..c7b5a96 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -171,8 +171,15 @@ lswitch_create(struct rconn *rconn, const struct 
lswitch_config *cfg)
         }
 
         for (i = 0; !error && i < cfg->n_default_flows; i++) {
-            msg = ofputil_encode_flow_mod(&cfg->default_flows[i], protocol);
-            error = rconn_send(rconn, msg, NULL);
+            enum ofperr err;
+            err = ofputil_encode_flow_mod(&cfg->default_flows[i], protocol,
+                                            &msg);
+            if (err) {
+                VLOG_INFO_RL(&rl, "ofputil_encode_flow_mod returned error: %s",
+                             ofperr_get_name(error));
+            } else {
+                error = rconn_send(rconn, msg, NULL);
+            }
         }
 
         if (error) {
@@ -453,6 +460,7 @@ process_packet_in(struct lswitch *sw, struct rconn *rconn,
 
     struct ofpbuf pkt;
     struct flow flow;
+    struct ofpbuf *packet_out;
 
     error = ofputil_decode_packet_in(&pi, oh);
     if (error) {
@@ -518,19 +526,36 @@ process_packet_in(struct lswitch *sw, struct rconn *rconn,
         fm.out_port = OFPP_NONE;
         fm.ofpacts = ofpacts.data;
         fm.ofpacts_len = ofpacts.size;
-        buffer = ofputil_encode_flow_mod(&fm, sw->protocol);
+        error = ofputil_encode_flow_mod(&fm, sw->protocol, &buffer);
+        if (error) {
+            VLOG_ERR("ofputil_encode_flow_mod returned error: %s",
+                     ofperr_get_name(error));
+            return;
+        }
 
         queue_tx(sw, rconn, buffer);
 
         /* If the switch didn't buffer the packet, we need to send a copy. */
         if (pi.buffer_id == UINT32_MAX && out_port != OFPP_NONE) {
-            queue_tx(sw, rconn, ofputil_encode_packet_out(&po));
+            error = ofputil_encode_packet_out(&po, &packet_out);
+            if (error) {
+                VLOG_ERR("ofputil_encode_packet_out returns error %s",
+                         ofperr_get_name(error));
+            } else {
+                queue_tx(sw, rconn, packet_out);
+            }
         }
     } else {
         /* We don't know that MAC, or we don't set up flows.  Send along the
          * packet without setting up a flow. */
         if (pi.buffer_id != UINT32_MAX || out_port != OFPP_NONE) {
-            queue_tx(sw, rconn, ofputil_encode_packet_out(&po));
+            error = ofputil_encode_packet_out(&po, &packet_out);
+            if (error) {
+                VLOG_ERR("ofputil_encode_packet_out returns error %s",
+                         ofperr_get_name(error));
+            } else {
+                queue_tx(sw, rconn, packet_out);
+            }
         }
     }
 }
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 0874cc4..8d9f0ba 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1191,7 +1191,7 @@ ofpact_enqueue_to_openflow10(const struct ofpact_enqueue 
*enqueue,
     oae->queue_id = htonl(enqueue->queue);
 }
 
-static void
+static enum ofperr
 ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
 {
     switch (a->type) {
@@ -1271,20 +1271,25 @@ ofpact_to_openflow10(const struct ofpact *a, struct 
ofpbuf *out)
         ofpact_to_nxast(a, out);
         break;
     }
+    return 0;
 }
 
 /* Converts the 'ofpacts_len' bytes of ofpacts in 'ofpacts' into OpenFlow 1.0
  * actions in 'openflow', appending the actions to any existing data in
  * 'openflow'. */
-void
+enum ofperr
 ofpacts_put_openflow10(const struct ofpact ofpacts[], size_t ofpacts_len,
                        struct ofpbuf *openflow)
 {
     const struct ofpact *a;
 
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        ofpact_to_openflow10(a, openflow);
+        enum ofperr error = ofpact_to_openflow10(a, openflow);
+        if (error) {
+            return error;
+        }
     }
+    return 0;
 }
 
 /* Converting ofpacts to OpenFlow 1.1. */
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 7c9cb05..af1792a 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -394,8 +394,8 @@ enum ofperr ofpacts_check(const struct ofpact[], size_t 
ofpacts_len,
                           const struct flow *, int max_ports);
 
 /* Converting ofpacts to OpenFlow. */
-void ofpacts_put_openflow10(const struct ofpact[], size_t ofpacts_len,
-                            struct ofpbuf *openflow);
+enum ofperr ofpacts_put_openflow10(const struct ofpact[], size_t ofpacts_len,
+                                   struct ofpbuf *openflow);
 void ofpacts_put_openflow11_actions(const struct ofpact[], size_t ofpacts_len,
                                     struct ofpbuf *openflow);
 void ofpacts_put_openflow11_instructions(const struct ofpact[],
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index ac12b1b..c6e0e74 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -1262,9 +1262,9 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
 
 /* Converts 'fm' into an OFPT_FLOW_MOD or NXT_FLOW_MOD message according to
  * 'protocol' and returns the message. */
-struct ofpbuf *
+enum ofperr
 ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
-                        enum ofputil_protocol protocol)
+                        enum ofputil_protocol protocol, struct ofpbuf **msgp)
 {
     struct ofpbuf *msg;
     uint16_t command;
@@ -1322,10 +1322,17 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod 
*fm,
     }
 
     if (fm->ofpacts) {
-        ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
+        enum ofperr error = ofpacts_put_openflow10(fm->ofpacts,
+                                                   fm->ofpacts_len, msg);
+        if (error) {
+            *msgp = NULL;
+            ofpbuf_delete(msg);
+            return error;
+        }
     }
     ofpmsg_update_length(msg);
-    return msg;
+    *msgp = msg;
+    return 0;
 }
 
 /* Returns a bitmask with a 1-bit for each protocol that could be used to
@@ -1640,7 +1647,7 @@ unknown_to_zero(uint64_t count)
 /* Appends an OFPST_FLOW or NXST_FLOW reply that contains the data in 'fs' to
  * those already present in the list of ofpbufs in 'replies'.  'replies' should
  * have been initialized with ofputil_start_stats_reply(). */
-void
+enum ofperr
 ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
                                 struct list *replies)
 {
@@ -1651,9 +1658,14 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
     ofpraw_decode_partial(&raw, reply->data, reply->size);
     if (raw == OFPRAW_OFPST_FLOW_REPLY) {
         struct ofp10_flow_stats *ofs;
+        enum ofperr error;
 
         ofpbuf_put_uninit(reply, sizeof *ofs);
-        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
+        error = ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
+        if (error) {
+            reply->size = start_ofs;
+            return error;
+        }
 
         ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
         ofs->length = htons(reply->size - start_ofs);
@@ -1674,10 +1686,15 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
     } else if (raw == OFPRAW_NXST_FLOW_REPLY) {
         struct nx_flow_stats *nfs;
         int match_len;
+        enum ofperr error;
 
         ofpbuf_put_uninit(reply, sizeof *nfs);
         match_len = nx_put_match(reply, false, &fs->rule, 0, 0);
-        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
+        error = ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
+        if (error) {
+            reply->size = start_ofs;
+            return error;
+        }
 
         nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
         nfs->length = htons(reply->size - start_ofs);
@@ -1703,6 +1720,7 @@ ofputil_append_flow_stats_reply(const struct 
ofputil_flow_stats *fs,
     }
 
     ofpmp_postappend(replies, start_ofs);
+    return 0;
 }
 
 /* Converts abstract ofputil_aggregate_stats 'stats' into an OFPST_AGGREGATE or
@@ -2958,7 +2976,7 @@ ofputil_start_flow_update(struct list *replies)
     list_push_back(replies, &msg->list_node);
 }
 
-void
+enum ofperr
 ofputil_append_flow_update(const struct ofputil_flow_update *update,
                            struct list *replies)
 {
@@ -2977,11 +2995,17 @@ ofputil_append_flow_update(const struct 
ofputil_flow_update *update,
     } else {
         struct nx_flow_update_full *nfuf;
         int match_len;
+        enum ofperr error;
 
         ofpbuf_put_zeros(msg, sizeof *nfuf);
         match_len = nx_put_match(msg, false, update->match,
                                  htonll(0), htonll(0));
-        ofpacts_put_openflow10(update->ofpacts, update->ofpacts_len, msg);
+        error = ofpacts_put_openflow10(update->ofpacts, update->ofpacts_len,
+                                       msg);
+        if (error) {
+            msg->size = start_ofs;
+            return error;
+        }
 
         nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
         nfuf->reason = htons(update->reason);
@@ -2998,14 +3022,17 @@ ofputil_append_flow_update(const struct 
ofputil_flow_update *update,
     nfuh->event = htons(update->event);
 
     ofpmp_postappend(replies, start_ofs);
+    return 0;
 }
 
-struct ofpbuf *
-ofputil_encode_packet_out(const struct ofputil_packet_out *po)
+enum ofperr
+ofputil_encode_packet_out(const struct ofputil_packet_out *po,
+                          struct ofpbuf **msgp)
 {
     struct ofp_packet_out *opo;
     size_t actions_ofs;
     struct ofpbuf *msg;
+    enum ofperr error;
     size_t size;
 
     size = po->ofpacts_len;
@@ -3016,7 +3043,12 @@ ofputil_encode_packet_out(const struct 
ofputil_packet_out *po)
     msg = ofpraw_alloc(OFPRAW_OFPT10_PACKET_OUT, OFP10_VERSION, size);
     ofpbuf_put_zeros(msg, sizeof *opo);
     actions_ofs = msg->size;
-    ofpacts_put_openflow10(po->ofpacts, po->ofpacts_len, msg);
+    error = ofpacts_put_openflow10(po->ofpacts, po->ofpacts_len, msg);
+    if (error) {
+        ofpbuf_delete(msg);
+        *msgp = NULL;
+        return error;
+    }
 
     opo = msg->l3;
     opo->buffer_id = htonl(po->buffer_id);
@@ -3029,7 +3061,8 @@ ofputil_encode_packet_out(const struct ofputil_packet_out 
*po)
 
     ofpmsg_update_length(msg);
 
-    return msg;
+    *msgp = msg;
+    return 0;
 }
 
 /* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 032b156..b9d71f0 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -177,8 +177,8 @@ enum ofperr ofputil_decode_flow_mod(struct ofputil_flow_mod 
*,
                                     const struct ofp_header *,
                                     enum ofputil_protocol,
                                     struct ofpbuf *ofpacts);
-struct ofpbuf *ofputil_encode_flow_mod(const struct ofputil_flow_mod *,
-                                       enum ofputil_protocol);
+enum ofperr ofputil_encode_flow_mod(const struct ofputil_flow_mod *,
+                                    enum ofputil_protocol, struct ofpbuf **);
 
 enum ofputil_protocol ofputil_flow_mod_usable_protocols(
     const struct ofputil_flow_mod *fms, size_t n_fms);
@@ -221,8 +221,8 @@ int ofputil_decode_flow_stats_reply(struct 
ofputil_flow_stats *,
                                     struct ofpbuf *msg,
                                     bool flow_age_extension,
                                     struct ofpbuf *ofpacts);
-void ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *,
-                                     struct list *replies);
+enum ofperr ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *,
+                                            struct list *replies);
 
 /* Aggregate stats reply, independent of protocol. */
 struct ofputil_aggregate_stats {
@@ -297,7 +297,8 @@ struct ofputil_packet_out {
 enum ofperr ofputil_decode_packet_out(struct ofputil_packet_out *,
                                       const struct ofp_header *,
                                       struct ofpbuf *ofpacts);
-struct ofpbuf *ofputil_encode_packet_out(const struct ofputil_packet_out *);
+enum ofperr ofputil_encode_packet_out(const struct ofputil_packet_out *,
+                                      struct ofpbuf **);
 
 enum ofputil_port_config {
     /* OpenFlow 1.0 and 1.1 share these values for these port config bits. */
@@ -481,8 +482,8 @@ struct ofputil_flow_update {
 int ofputil_decode_flow_update(struct ofputil_flow_update *,
                                struct ofpbuf *msg, struct ofpbuf *ofpacts);
 void ofputil_start_flow_update(struct list *replies);
-void ofputil_append_flow_update(const struct ofputil_flow_update *,
-                                struct list *replies);
+enum ofperr ofputil_append_flow_update(const struct ofputil_flow_update *,
+                                       struct list *replies);
 
 /* Abstract nx_flow_monitor_cancel. */
 uint32_t ofputil_decode_flow_monitor_cancel(const struct ofp_header *);
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index 5ce77c0..54404b4 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -1777,6 +1777,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule,
     LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
         enum nx_flow_monitor_flags flags = 0;
         struct ofmonitor *m;
+        enum ofperr error;
 
         if (ofconn->monitor_paused) {
             /* Only send NXFME_DELETED notifications for flows that were added
@@ -1819,15 +1820,24 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule,
                     fu.ofpacts = NULL;
                     fu.ofpacts_len = 0;
                 }
-                ofputil_append_flow_update(&fu, &ofconn->updates);
+                error = ofputil_append_flow_update(&fu, &ofconn->updates);
+                if (error) {
+                    VLOG_ERR("ofputil_append_flow_update: %s",
+                             ofperr_get_name(error));
+                }
             } else if (!ofconn->sent_abbrev_update) {
                 struct ofputil_flow_update fu;
 
                 fu.event = NXFME_ABBREV;
                 fu.xid = abbrev_xid;
-                ofputil_append_flow_update(&fu, &ofconn->updates);
+                error = ofputil_append_flow_update(&fu, &ofconn->updates);
 
-                ofconn->sent_abbrev_update = true;
+                if (error) {
+                    VLOG_ERR("ofputil_append_flow_update: %s",
+                             ofperr_get_name(error));
+                } else {
+                    ofconn->sent_abbrev_update = true;
+                }
             }
         }
     }
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 0f24fd0..af1ef16 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2531,7 +2531,11 @@ handle_flow_stats_request(struct ofconn *ofconn,
                                                &fs.byte_count);
         fs.ofpacts = rule->ofpacts;
         fs.ofpacts_len = rule->ofpacts_len;
-        ofputil_append_flow_stats_reply(&fs, &replies);
+        error = ofputil_append_flow_stats_reply(&fs, &replies);
+        if (error) {
+            ofpbuf_list_delete(&replies);
+            return error;
+        }
     }
     ofconn_send_replies(ofconn, &replies);
 
@@ -3441,6 +3445,7 @@ ofproto_compose_flow_refresh_update(const struct rule 
*rule,
 {
     struct ofoperation *op = rule->pending;
     struct ofputil_flow_update fu;
+    enum ofperr error;
 
     if (op && op->type == OFOPERATION_ADD && !op->victim) {
         /* We'll report the final flow when the operation completes.  Reporting
@@ -3495,7 +3500,11 @@ ofproto_compose_flow_refresh_update(const struct rule 
*rule,
     if (list_is_empty(msgs)) {
         ofputil_start_flow_update(msgs);
     }
-    ofputil_append_flow_update(&fu, msgs);
+    error = ofputil_append_flow_update(&fu, msgs);
+    if (error) {
+        VLOG_ERR("ofputil_append_flow_update returned error: %s",
+                 ofperr_get_name(error));
+    }
 }
 
 void
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 00ba06b..08dd312 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -1029,8 +1029,15 @@ ofctl_flow_mod__(const char *remote, struct 
ofputil_flow_mod *fms,
 
     for (i = 0; i < n_fms; i++) {
         struct ofputil_flow_mod *fm = &fms[i];
+        enum ofperr error;
+        struct ofpbuf *flow_mod;
 
-        transact_noreply(vconn, ofputil_encode_flow_mod(fm, protocol));
+        error = ofputil_encode_flow_mod(fm, protocol, &flow_mod);
+        if (error) {
+            ovs_fatal(0, "ofputil_encode_flow_mod returned error: %s",
+                      ofperr_get_name(error));
+        }
+        transact_noreply(vconn, flow_mod);
         free(fm->ofpacts);
     }
     vconn_close(vconn);
@@ -1472,6 +1479,7 @@ ofctl_packet_out(int argc, char *argv[])
     for (i = 4; i < argc; i++) {
         struct ofpbuf *packet, *opo;
         const char *error_msg;
+        enum ofperr error;
 
         error_msg = eth_from_hex(argv[i], &packet);
         if (error_msg) {
@@ -1480,7 +1488,11 @@ ofctl_packet_out(int argc, char *argv[])
 
         po.packet = packet->data;
         po.packet_len = packet->size;
-        opo = ofputil_encode_packet_out(&po);
+        error = ofputil_encode_packet_out(&po, &opo);
+        if (error) {
+            ovs_fatal(0, "ofputil_encode_packet_out: %s",
+                      ofperr_get_name(error));
+        }
         transact_noreply(vconn, opo);
         ofpbuf_delete(packet);
     }
@@ -1962,6 +1974,7 @@ fte_make_flow_mod(const struct fte *fte, int index, 
uint16_t command,
     const struct fte_version *version = fte->versions[index];
     struct ofputil_flow_mod fm;
     struct ofpbuf *ofm;
+    enum ofperr error;
 
     fm.cr = fte->rule;
     fm.cookie = htonll(0);
@@ -1983,7 +1996,11 @@ fte_make_flow_mod(const struct fte *fte, int index, 
uint16_t command,
         fm.ofpacts_len = 0;
     }
 
-    ofm = ofputil_encode_flow_mod(&fm, protocol);
+    error = ofputil_encode_flow_mod(&fm, protocol, &ofm);
+    if (error) {
+        ovs_fatal(0, "ofputil_encode_flow_mod returned error: %s",
+                  ofperr_get_name(error));
+    }
     list_push_back(packets, &ofm->list_node);
 }
 
@@ -2134,8 +2151,13 @@ ofctl_parse_flows__(struct ofputil_flow_mod *fms, size_t 
n_fms)
     for (i = 0; i < n_fms; i++) {
         struct ofputil_flow_mod *fm = &fms[i];
         struct ofpbuf *msg;
+        enum ofperr error;
 
-        msg = ofputil_encode_flow_mod(fm, protocol);
+        error = ofputil_encode_flow_mod(fm, protocol, &msg);
+        if (error) {
+            ovs_fatal(0, "ofputil_encode_flow_mod: %s",
+                      ofperr_get_name(error));
+        }
         ofp_print(stdout, msg->data, msg->size, verbosity);
         ofpbuf_delete(msg);
 
@@ -2301,7 +2323,10 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char 
*argv[] OVS_UNUSED)
 
         /* Convert back to ofp10 actions and print differences from input. */
         ofpbuf_init(&of10_out, 0);
-        ofpacts_put_openflow10(ofpacts.data, ofpacts.size, &of10_out);
+        error = ofpacts_put_openflow10(ofpacts.data, ofpacts.size, &of10_out);
+        if (error) {
+            ovs_fatal(0, "bad OF1.1 encoding: %s\n\n", ofperr_get_name(error));
+        }
 
         print_differences("", of10_in.data, of10_in.size,
                           of10_out.data, of10_out.size);
-- 
1.7.1.1

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

Reply via email to