From a835cab0ea0bfbea738adcd357aeaf4f5544c8ef Mon Sep 17 00:00:00 2001
From: Justin Pettit <jpettit@nicira.com>
Date: Mon, 13 Oct 2008 17:49:34 -0700
Subject: [PATCH] Return error message when a flow can't be added due to full
 tables.

When a flow cannot be added to any tables because they are full, send
a message with type OFPET_FLOW_MOD_FAILED and code OFPFMFC_ALL_TABLES_FULL.
---
 datapath/forward.c | 6 +++++-
 include/openflow.h | 9 ++++++++-
 lib/ofp-print.c    | 3 +++
 switch/datapath.c  | 6 +++++-
 4 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/datapath/forward.c b/datapath/forward.c
index f28ac2b96..ea53d1545 100644
--- a/datapath/forward.c
+++ b/datapath/forward.c
@@ -240,7 +240,11 @@ add_flow(struct sw_chain *chain, const struct sender *sender,
 
 	/* Act. */
 	error = chain_insert(chain, flow);
-	if (error)
+	if (error == -ENOBUFS) {
+		dp_send_error_msg(chain->dp, sender, OFPET_FLOW_MOD_FAILED, 
+				OFPFMFC_ALL_TABLES_FULL, ofm, ntohs(ofm->header.length));
+		goto error_free_flow;
+	} else if (error)
 		goto error_free_flow;
 	error = 0;
 	if (ntohl(ofm->buffer_id) != (uint32_t) -1) {
diff --git a/include/openflow.h b/include/openflow.h
index 2a5f8b912..b067811e7 100644
--- a/include/openflow.h
+++ b/include/openflow.h
@@ -556,7 +556,8 @@ OFP_ASSERT(sizeof(struct ofp_flow_expired) == 72);
 enum ofp_error_type {
     OFPET_HELLO_FAILED,         /* Hello protocol failed. */
     OFPET_BAD_REQUEST,          /* Request was not understood. */
-    OFPET_BAD_ACTION            /* Error in action description. */
+    OFPET_BAD_ACTION,           /* Error in action description. */
+    OFPET_FLOW_MOD_FAILED       /* Problem modifying flow entry. */
 };
 
 /* ofp_error_msg 'code' values for OFPET_HELLO_FAILED.  'data' contains an
@@ -587,6 +588,12 @@ enum ofp_bad_action_code {
     OFPBAC_BAD_ARGUMENT        /* Bad action argument. */
 };
 
+/* ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED.  'data' contains 
+ * at least the first 64 bytes of the failed request. */
+enum ofp_flow_mod_failed_code {
+    OFPFMFC_ALL_TABLES_FULL    /* Flow not added because of full tables. */
+};
+
 /* OFPT_ERROR: Error message (datapath -> controller). */
 struct ofp_error_msg {
     struct ofp_header header;
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 9dcb8b1b5..75f5b5cc8 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -851,6 +851,9 @@ static const struct error_type error_types[] = {
     ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR),
     ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE),
     ERROR_CODE(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT),
+
+    ERROR_TYPE(OFPET_FLOW_MOD_FAILED),
+    ERROR_CODE(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL)
 };
 #define N_ERROR_TYPES ARRAY_SIZE(error_types)
 
diff --git a/switch/datapath.c b/switch/datapath.c
index ce9c31e27..9ec768d62 100644
--- a/switch/datapath.c
+++ b/switch/datapath.c
@@ -1008,7 +1008,11 @@ add_flow(struct datapath *dp, const struct sender *sender,
 
     /* Act. */
     error = chain_insert(dp->chain, flow);
-    if (error) {
+    if (error == -ENOBUFS) {
+        dp_send_error_msg(dp, sender, OFPET_FLOW_MOD_FAILED, 
+                OFPFMFC_ALL_TABLES_FULL, ofm, ntohs(ofm->header.length));
+        goto error_free_flow; 
+    } else if (error) {
         goto error_free_flow; 
     }
     error = 0;
-- 
2.47.0