"Brandon Heller" <[EMAIL PROTECTED]> writes:

> I would expect there to be major issues when mixing 32b OF with 64b NOX,
> because some of the fields in openflow.h (at least as of v0.8.1 - haven't
> checked if this got updated) change size depending on 32/64b.  Some of the
> substructures in ofp messages, like flow_expiration, are not 64b multiples,
> and so padding gets inserted to ensure that all substructs start on 64b
> boundaries.   This will have to be addressed with v0.9.

When you were planning to point this out?  I was unaware of the
problems.  In fact, I thought I had carefully laid out the
structures to avoid such problems.  Obviously not, though.

Here is a pair of patches to fix it.  The first one (tested on
i386, x86_64, ia64, mips, s390, sparc64, armv5tel, alpha,
pa-risc, itanium2) fixes the actual problems[*].  The second one
ensures that they cannot recur.

[*] I have a surprising number of accounts in various places.

Review, anyone?

commit 31fe1b147f8d37a4a8e49a1009767277779b8cac
Author: Ben Pfaff <[EMAIL PROTECTED]>
Date:   Wed Jul 16 22:50:39 2008 -0700

    Adjust OpenFlow to have same structure layout on 32- and 64-bit platforms.
    
    Pointed out by "Brandon Heller" <[EMAIL PROTECTED]>.

diff --git a/include/openflow.h b/include/openflow.h
index e126dde..5e3e8c5 100644
--- a/include/openflow.h
+++ b/include/openflow.h
@@ -50,7 +50,7 @@
 /* The most significant bit being set in the version field indicates an
  * experimental OpenFlow version.  
  */
-#define OFP_VERSION   0x84
+#define OFP_VERSION   0x85
 
 #define OFP_MAX_TABLE_NAME_LEN 32
 #define OFP_MAX_PORT_NAME_LEN  16
@@ -179,6 +179,7 @@ struct ofp_switch_features {
     /* Features. */
     uint32_t capabilities;  /* Bitmap of support "ofp_capabilities". */
     uint32_t actions;       /* Bitmap of supported "ofp_action_type"s. */
+    uint8_t pad[4];         /* Align to 64-bits. */
 
     /* Port info.*/
     struct ofp_phy_port ports[0];   /* Port definitions.  The number of ports
@@ -261,7 +262,7 @@ struct ofp_action {
         struct ofp_action_output output; /* OFPAT_OUTPUT: output struct. */
         uint16_t vlan_id;                /* OFPAT_SET_DL_VLAN: VLAN id. */
         uint8_t  dl_addr[OFP_ETH_ALEN];  /* OFPAT_SET_DL_SRC/DST */
-        uint32_t nw_addr;                /* OFPAT_SET_NW_SRC/DST */
+        uint32_t nw_addr __attribute__((packed)); /* OFPAT_SET_NW_SRC/DST */
         uint16_t tp;                     /* OFPAT_SET_TP_SRC/DST */
     } arg;
 };
@@ -357,6 +358,7 @@ struct ofp_flow_expired {
     uint8_t pad[2];           /* Align to 32-bits. */
 
     uint32_t duration;        /* Time flow was alive in seconds. */
+    uint8_t pad2[4];          /* Align to 64-bits. */
     uint64_t packet_count;    
     uint64_t byte_count;
 };
@@ -426,11 +428,11 @@ struct ofp_flow_stats {
     uint8_t pad;
     struct ofp_match match;   /* Description of fields. */
     uint32_t duration;        /* Time flow has been alive in seconds. */
-    uint64_t packet_count;    /* Number of packets in flow. */
-    uint64_t byte_count;      /* Number of bytes in flow. */
     uint16_t priority;        /* Priority of the entry. Only meaningful
                                  when this is not an exact-match entry. */
     uint16_t max_idle;        /* Number of seconds idle before expiration. */
+    uint64_t packet_count;    /* Number of packets in flow. */
+    uint64_t byte_count;      /* Number of bytes in flow. */
     struct ofp_action actions[0]; /* Actions. */
 };
 
@@ -456,13 +458,14 @@ struct ofp_table_stats {
     char name[OFP_MAX_TABLE_NAME_LEN];
     uint32_t max_entries;    /* Max number of entries supported */
     uint32_t active_count;   /* Number of active entries */
+    uint8_t pad2[4];         /* Align to 64 bits. */
     uint64_t matched_count;  /* Number of packets that hit table */
 };
 
 /* Statistics about a particular port */
 struct ofp_port_stats {
     uint16_t port_no;
-    uint8_t pad[2];          /* Align to 32-bits */
+    uint8_t pad[6];          /* Align to 64-bits */
     uint64_t rx_count;       /* Number of received packets */
     uint64_t tx_count;       /* Number of transmitted packets */
     uint64_t drop_count;     /* Number of packets dropped by interface */

----------------------------------------------------------------------

commit c54907f7ec5762942aa99c574ef0eaa5f0d6f2f7
Author: Ben Pfaff <[EMAIL PROTECTED]>
Date:   Wed Jul 16 22:51:35 2008 -0700

    Assert on structure sizes in openflow.h.
    
    This causes the build to fail if structures are not the sizes that we
    expect.

diff --git a/include/openflow.h b/include/openflow.h
index 5e3e8c5..3525e16 100644
--- a/include/openflow.h
+++ b/include/openflow.h
@@ -42,6 +42,16 @@
 #include <stdint.h>
 #endif
 
+#ifndef __cplusplus
+/* Build-time assertion for use in a declaration context. */
+#define OFP_ASSERT(EXPR)                                                \
+        extern int (*build_assert(void))[ sizeof(struct {               \
+                    unsigned int build_assert_failed : (EXPR) ? 1 : -1; })]
+#else /* __cplusplus */
+#include <boost/static_assert.hpp>
+#define OFP_ASSERT BOOST_STATIC_ASSERT
+#endif /* __cplusplus */
+
 /* Maximum length of a OpenFlow packet. */
 #define OFP_MAXLEN (sizeof(struct ofp_switch_features) \
         + (sizeof(struct ofp_phy_port) * OFPP_MAX) + 200)
@@ -108,6 +118,7 @@ struct ofp_header {
                            Replies use the same id as was in the request
                            to facilitate pairing. */
 };
+OFP_ASSERT(sizeof(struct ofp_header) == 8);
 
 #define OFP_DEFAULT_MISS_SEND_LEN   128
 
@@ -123,6 +134,7 @@ struct ofp_switch_config {
     uint16_t miss_send_len;     /* Max bytes of new flow that datapath should
                                    send to the controller. */
 };
+OFP_ASSERT(sizeof(struct ofp_switch_config) == 12);
 
 /* Capabilities supported by the datapath. */
 enum ofp_capabilities {
@@ -160,6 +172,7 @@ struct ofp_phy_port {
     uint32_t speed;         /* Current speed in Mbps */
     uint32_t features;      /* Bitmap of supported "ofp_port_features"s. */
 };
+OFP_ASSERT(sizeof(struct ofp_phy_port) == 36);
 
 /* Switch features. */
 struct ofp_switch_features {
@@ -186,6 +199,7 @@ struct ofp_switch_features {
                                       is inferred from the length field in
                                       the header. */
 };
+OFP_ASSERT(sizeof(struct ofp_switch_features) == 48);
 
 /* What changed about the phsyical port */
 enum ofp_port_reason {
@@ -201,12 +215,14 @@ struct ofp_port_status {
     uint8_t pad[3];          /* Align to 32-bits */
     struct ofp_phy_port desc;
 };
+OFP_ASSERT(sizeof(struct ofp_port_status) == 48);
 
 /* Modify behavior of the physical port */
 struct ofp_port_mod {
     struct ofp_header header;
     struct ofp_phy_port desc;
 };
+OFP_ASSERT(sizeof(struct ofp_port_mod) == 44);
 
 /* Why is this packet being sent to the controller? */
 enum ofp_reason {
@@ -229,6 +245,7 @@ struct ofp_packet_in {
                                offsetof(struct ofp_packet_in, data) ==
                                sizeof(struct ofp_packet_in) - 2. */
 };
+OFP_ASSERT(sizeof(struct ofp_packet_in) == 20);
 
 enum ofp_action_type {
     OFPAT_OUTPUT,           /* Output to switch port. */
@@ -248,6 +265,7 @@ struct ofp_action_output {
     uint16_t max_len;
     uint16_t port;
 };
+OFP_ASSERT(sizeof(struct ofp_action_output) == 4);
 
 /* The VLAN id is 12-bits, so we'll use the entire 16 bits to indicate
  * special conditions.  All ones is used to indicate that no VLAN id was
@@ -266,6 +284,7 @@ struct ofp_action {
         uint16_t tp;                     /* OFPAT_SET_TP_SRC/DST */
     } arg;
 };
+OFP_ASSERT(sizeof(struct ofp_action) == 8);
 
 /* Send packet (controller -> datapath). */
 struct ofp_packet_out {
@@ -278,6 +297,7 @@ struct ofp_packet_out {
         uint8_t data[0];              /* buffer_id == -1 */
     } u;
 };
+OFP_ASSERT(sizeof(struct ofp_packet_out) == 16);
 
 enum ofp_flow_mod_command {
     OFPFC_ADD,              /* New flow. */
@@ -326,6 +346,7 @@ struct ofp_match {
     uint16_t tp_src;           /* TCP/UDP source port. */
     uint16_t tp_dst;           /* TCP/UDP destination port. */
 };
+OFP_ASSERT(sizeof(struct ofp_match) == 36);
 
 /* Value used in "max_idle" to indicate that the entry is permanent */
 #define OFP_FLOW_PERMANENT 0
@@ -348,6 +369,7 @@ struct ofp_flow_mod {
     struct ofp_action actions[0]; /* The number of actions is inferred from
                                     the length field in the header. */
 };
+OFP_ASSERT(sizeof(struct ofp_flow_mod) == 60);
 
 /* Flow expiration (datapath -> controller). */
 struct ofp_flow_expired {
@@ -362,6 +384,7 @@ struct ofp_flow_expired {
     uint64_t packet_count;    
     uint64_t byte_count;
 };
+OFP_ASSERT(sizeof(struct ofp_flow_expired) == 72);
 
 /* Error message (datapath -> controller). */
 struct ofp_error_msg {
@@ -372,6 +395,7 @@ struct ofp_error_msg {
     uint8_t data[0];          /* Variable-length data.  Interpreted based 
                                  on the type and code. */
 };
+OFP_ASSERT(sizeof(struct ofp_error_msg) == 12);
 
 enum ofp_stats_types {
     /* Individual flow statistics.
@@ -401,6 +425,7 @@ struct ofp_stats_request {
     uint16_t flags;             /* OFPSF_REQ_* flags (none yet defined). */
     uint8_t body[0];            /* Body of the request. */
 };
+OFP_ASSERT(sizeof(struct ofp_stats_request) == 12);
 
 enum ofp_stats_reply_flags {
     OFPSF_REPLY_MORE  = 1 << 0, /* More replies to follow */
@@ -412,6 +437,7 @@ struct ofp_stats_reply {
     uint16_t flags;             /* OFPSF_REPLY_* flags. */
     uint8_t body[0];            /* Body of the reply. */
 };
+OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
 
 /* Body for ofp_stats_request of type OFPST_FLOW. */
 struct ofp_flow_stats_request {
@@ -420,6 +446,7 @@ struct ofp_flow_stats_request {
                                  or 0xff for all tables. */
     uint8_t pad[3];           /* Align to 32 bits. */
 };
+OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 40);
 
 /* Body of reply to OFPST_FLOW request. */
 struct ofp_flow_stats {
@@ -435,6 +462,7 @@ struct ofp_flow_stats {
     uint64_t byte_count;      /* Number of bytes in flow. */
     struct ofp_action actions[0]; /* Actions. */
 };
+OFP_ASSERT(sizeof(struct ofp_flow_stats) == 64);
 
 /* Body for ofp_stats_request of type OFPST_AGGREGATE. */
 struct ofp_aggregate_stats_request {
@@ -443,13 +471,16 @@ struct ofp_aggregate_stats_request {
                                  or 0xff for all tables. */
     uint8_t pad[3];           /* Align to 32 bits. */
 };
+OFP_ASSERT(sizeof(struct ofp_aggregate_stats_request) == 40);
 
 /* Body of reply to OFPST_AGGREGATE request. */
 struct ofp_aggregate_stats_reply {
     uint64_t packet_count;    /* Number of packets in flows. */
     uint64_t byte_count;      /* Number of bytes in flows. */
     uint32_t flow_count;      /* Number of flows. */
+    uint8_t pad[4];           /* Align to 64 bits. */
 };
+OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
 
 /* Body of reply to OFPST_TABLE request. */
 struct ofp_table_stats {
@@ -461,6 +492,7 @@ struct ofp_table_stats {
     uint8_t pad2[4];         /* Align to 64 bits. */
     uint64_t matched_count;  /* Number of packets that hit table */
 };
+OFP_ASSERT(sizeof(struct ofp_table_stats) == 56);
 
 /* Statistics about a particular port */
 struct ofp_port_stats {
@@ -470,5 +502,6 @@ struct ofp_port_stats {
     uint64_t tx_count;       /* Number of transmitted packets */
     uint64_t drop_count;     /* Number of packets dropped by interface */
 };
+OFP_ASSERT(sizeof(struct ofp_port_stats) == 32);
 
 #endif /* openflow.h */

-- 
Ben Pfaff
Nicira Networks, Inc.

_______________________________________________
nox-dev mailing list
[email protected]
http://noxrepo.org/mailman/listinfo/nox-dev_noxrepo.org

Reply via email to