- Add support for OpenFlow error message type.
authorJustin Pettit <jpettit@nicira.com>
Thu, 1 May 2008 00:38:03 +0000 (17:38 -0700)
committerJustin Pettit <jpettit@nicira.com>
Thu, 1 May 2008 00:38:03 +0000 (17:38 -0700)
- Ensure OpenFlow messages fit in 16-bit length field.

datapath/datapath.c
datapath/datapath.h
include/openflow.h
lib/ofp-print.c
switch/datapath.c

index 7d2a44c0815ddcd21ed14a4e0a5f47745448762d..cfebab803b9c96992c2d1e14ffbae78d3ecd4c66 100644 (file)
@@ -46,6 +46,7 @@
 #define BRIDGE_PORT_NO_FLOOD   0x00000001 
 
 #define UINT32_MAX                       4294967295U
+#define UINT16_MAX                       65535
 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
 
 struct net_bridge_port {
@@ -169,6 +170,13 @@ alloc_openflow_skb(struct datapath *dp, size_t openflow_len, uint8_t type,
        struct sk_buff *skb;
        int max_openflow_len;
 
+       if ((openflow_len + sizeof(struct ofp_header)) > UINT16_MAX) {
+               if (net_ratelimit())
+                       printk("alloc_openflow_skb: openflow message too large: %d\n", 
+                                       openflow_len);
+               return NULL;
+       }
+
        genl_len = nlmsg_total_size(GENL_HDRLEN + dp_genl_family.hdrsize);
        genl_len += nla_total_size(sizeof(uint32_t)); /* DP_GENL_A_DP_IDX */
        genl_len += nla_total_size(openflow_len);    /* DP_GENL_A_OPENFLOW */
@@ -804,6 +812,26 @@ dp_send_flow_expired(struct datapath *dp, struct sw_flow *flow)
        return send_openflow_skb(skb, NULL);
 }
 
+int
+dp_send_error_msg(struct datapath *dp, const struct sender *sender, 
+               uint16_t type, uint16_t code, const uint8_t *data, size_t len)
+{
+       struct sk_buff *skb;
+       struct ofp_error_msg *oem;
+
+
+       oem = alloc_openflow_skb(dp, sizeof(*oem)+len, OFPT_ERROR_MSG, 
+                       sender, &skb);
+       if (!oem)
+               return -ENOMEM;
+
+       oem->type = htons(type);
+       oem->code = htons(code);
+       memcpy(oem->data, data, len);
+
+       return send_openflow_skb(skb, sender);
+}
+
 static void
 fill_flow_stats(struct ofp_flow_stats *ofs, struct sw_flow *flow,
                int table_idx)
index 3e765e2cd5d7f83c11709a431ecc67626136de91..76798ef8e72dc8c66a05ea1b4ff13aab8c78c9e1 100644 (file)
@@ -65,16 +65,18 @@ struct sender {
 };
 
 int dp_output_port(struct datapath *, struct sk_buff *, int out_port);
-int dp_output_control(struct datapath *, struct sk_buff *,
-                          uint32_t buffer_id, size_t max_len, int reason);
+int dp_output_control(struct datapath *, struct sk_buff *, uint32_t, 
+                       size_t, int);
 int dp_set_origin(struct datapath *, uint16_t, struct sk_buff *);
 int dp_send_features_reply(struct datapath *, const struct sender *);
 int dp_send_config_reply(struct datapath *, const struct sender *);
 int dp_send_flow_expired(struct datapath *, struct sw_flow *);
 int dp_send_flow_stats(struct datapath *, const struct sender *,
-                      const struct ofp_match *);
+                       const struct ofp_match *);
 int dp_send_table_stats(struct datapath *, const struct sender *);
 int dp_send_port_stats(struct datapath *, const struct sender *);
+int dp_send_error_msg(struct datapath *, const struct sender *, 
+                       uint16_t, uint16_t, const uint8_t *, size_t);
 int dp_update_port_flags(struct datapath *dp, const struct ofp_phy_port *opp);
 
 /* Should hold at least RCU read lock when calling */
index 648a36073b616a7d4a28c6412444c46b32364cd5..c8253e304d781fad75be2901b03893074d1e839d 100644 (file)
@@ -92,12 +92,13 @@ enum ofp_type {
     OFPT_TABLE,               /*  9 Controller/switch message */
     OFPT_PORT_MOD,            /* 10 Controller/switch message */
     OFPT_PORT_STATUS,         /* 11 Async message */
-    OFPT_FLOW_STATS_REQUEST,  /* 12 Controller/switch message */
-    OFPT_FLOW_STATS_REPLY,    /* 13 Controller/switch message */
-    OFPT_TABLE_STATS_REQUEST, /* 14 Controller/switch message */
-    OFPT_TABLE_STATS_REPLY,   /* 15 Controller/switch message */
-    OFPT_PORT_STATS_REQUEST,  /* 16 Controller/switch message */
-    OFPT_PORT_STATS_REPLY     /* 17 Controller/switch message */
+    OFPT_ERROR_MSG,           /* 12 Async message */
+    OFPT_FLOW_STATS_REQUEST,  /* 13 Controller/switch message */
+    OFPT_FLOW_STATS_REPLY,    /* 14 Controller/switch message */
+    OFPT_TABLE_STATS_REQUEST, /* 15 Controller/switch message */
+    OFPT_TABLE_STATS_REPLY,   /* 16 Controller/switch message */
+    OFPT_PORT_STATS_REQUEST,  /* 17 Controller/switch message */
+    OFPT_PORT_STATS_REPLY     /* 18 Controller/switch message */
 };
 
 /* Header on all OpenFlow packets. */
@@ -358,6 +359,16 @@ struct ofp_flow_expired {
     uint64_t byte_count;
 };
 
+/* Error message (datapath -> controller). */
+struct ofp_error_msg {
+    struct ofp_header header;
+
+    uint16_t type;
+    uint16_t code;
+    uint8_t data[0];          /* Variable-length data.  Interpreted based 
+                                 on the type and code. */
+};
+
 /* Statistics about flows that match the "match" field */
 struct ofp_flow_stats {
     struct ofp_match match;   /* Description of fields */
index 7fa4cec068e4519f59bc77b72ea5b3fea8f13e81..8b2da7e0402ce1754212a8f92b47d4c8ed780f65 100644 (file)
@@ -410,6 +410,18 @@ ofp_print_flow_expired(struct ds *string, const void *oh, size_t len,
          ntohll(ofe->packet_count), ntohll(ofe->byte_count));
 }
 
+/* Pretty-print the OFPT_ERROR_MSG packet of 'len' bytes at 'oh' to 'string'
+ * at the given 'verbosity' level. */
+static void
+ofp_print_error_msg(struct ds *string, const void *oh, size_t len, 
+                       int verbosity)
+{
+    const struct ofp_error_msg *oem = oh;
+
+    ds_put_format(string, 
+         " type%d code%d\n", ntohs(oem->type), ntohs(oem->code));
+}
+
 /* Pretty-print the OFPT_PORT_STATUS packet of 'len' bytes at 'oh' to 'string'
  * at the given 'verbosity' level. */
 static void
@@ -591,6 +603,11 @@ static const struct openflow_packet packets[] = {
         sizeof (struct ofp_port_status),
         ofp_print_port_status
     },
+    [OFPT_ERROR_MSG] = {
+        "error_msg",
+        sizeof (struct ofp_error_msg),
+        ofp_print_error_msg,
+    },
     [OFPT_FLOW_STATS_REQUEST] = {
         "flow_stats_request",
         sizeof (struct ofp_flow_stats_request),
index a3efa1a5c3affea90841c965e9a68ada45351539..c3ae0991bda119fe1533ec72bebb33bca0af7e2f 100644 (file)
@@ -627,6 +627,20 @@ send_flow_expired(struct datapath *dp, struct sw_flow *flow)
     send_openflow_buffer(dp, buffer, NULL);
 }
 
+void
+dp_send_error_msg(struct datapath *dp, const struct sender *sender,
+        uint16_t type, uint16_t code, const uint8_t *data, size_t len)
+{
+    struct buffer *buffer;
+    struct ofp_error_msg *oem;
+    oem = alloc_openflow_buffer(dp, sizeof(*oem)+len, OFPT_ERROR_MSG, 
+                                sender, &buffer);
+    oem->type = htons(type);
+    oem->code = htons(code);
+    memcpy(oem->data, data, len);
+    send_openflow_buffer(dp, buffer, sender);
+}
+
 static void
 fill_flow_stats(struct ofp_flow_stats *ofs, struct sw_flow *flow,
                 int table_idx, time_t now)