From: Saloni Jain <saloni.j...@tcs.com>

This commit enables the eviction mechanism on the basis of importance as
per the openflow specification 1.4.

        ovs-ofctl -O OpenFlow14 mod-table <switch> <table> evict
-Enable eviction on <table> of <switch>. Eviction adds a mechanism
 enabling the switch to automatically eliminate entries of lower
 importance to make space for newer entries.If want to enable eviction
 on all tables, user can set the <table> as 'ALL'.

        ovs-ofctl -O OpenFlow14 mod-table <switch> <table> noevict
-Disable eviction on <table> of <switch>.

        ovs-ofctl -O OpenFlow14 dump-tables-desc <switch>
-This command provides a way to list the current configuration
 (eviction for importance) of the tables on a <switch>, which is set
 using the mod-table command.

Signed-off-by: Saloni Jain <saloni.j...@tcs.com>
Signed-off-by: Hiteshi Kalra <hiteshi.ka...@tcs.com>
---
 DESIGN.md                       |  19 ++--
 NEWS                            |   2 +
 include/openflow/openflow-1.4.h |  10 ++
 lib/learning-switch.c           |   2 +
 lib/ofp-msgs.h                  |  10 ++
 lib/ofp-parse.c                 |   4 +
 lib/ofp-print.c                 |  63 ++++++++++-
 lib/ofp-util.c                  | 236 +++++++++++++++++++++++++++++++++++++++-
 lib/ofp-util.h                  |  32 ++++++
 lib/rconn.c                     |   2 +
 ofproto/ofproto-provider.h      |   2 +
 ofproto/ofproto.c               | 158 +++++++++++++++++++++++++--
 tests/ofp-print.at              |   1 +
 tests/ofproto.at                | 105 ++++++++++++++++++
 utilities/ovs-ofctl.8.in        |  25 ++++-
 utilities/ovs-ofctl.c           |  21 ++++
 16 files changed, 671 insertions(+), 21 deletions(-)

diff --git a/DESIGN.md b/DESIGN.md
index ff5bdf4..11cb642 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -276,13 +276,18 @@ The table for 1.3 is the same as the one shown above for 
1.2.
 
 
 OpenFlow 1.4
-------------
-
-OpenFlow 1.4 adds the "importance" field to flow_mods, but it does not
-explicitly specify which kinds of flow_mods set the importance.For
-consistency, Open vSwitch uses the same rule for importance as for
-idle_timeout and hard_timeout, that is, only an "ADD" flow_mod sets
-the importance.  (This issue has been filed with the ONF as EXT-496.)
+-----------
+OpenFlow 1.4 makes these changes:
+
+  - Adds the "importance" field to flow_mods, but it does not
+    explicitly specify which kinds of flow_mods set the importance.
+    For consistency, Open vSwitch uses the same rule for importance
+    as for idle_timeout and hard_timeout, that is, only an "ADD"
+    flow_mod sets the importance.  (This issue has been filed with
+    the ONF as EXT-496.)
+
+  - Eviction Mechanism to automatically delete entries of lower
+    importance to make space for newer entries.
 
 OFPT_PACKET_IN
 ==============
diff --git a/NEWS b/NEWS
index 7c0e262..2c6469f 100644
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,8 @@ Post-v2.3.0
        is executed last, and only if the action set has no "output" or "group"
        action.
      * OpenFlow 1.4+ flow "importance" is now maintained in the flow table.
+     * OpenFlow 1.4+ table-mod flow eviction on basis of importance and
+       table-description requests are now supported.
    - ovs-pki: Changed message digest algorithm from MD5 to SHA-1 because
      MD5 is no longer secure and some operating systems have started to disable
      it in OpenSSL.
diff --git a/include/openflow/openflow-1.4.h b/include/openflow/openflow-1.4.h
index 7631e47..c1ac227 100644
--- a/include/openflow/openflow-1.4.h
+++ b/include/openflow/openflow-1.4.h
@@ -155,6 +155,16 @@ struct ofp14_table_mod {
 };
 OFP_ASSERT(sizeof(struct ofp14_table_mod) == 8);
 
+/* Body of reply to OFPMP_TABLE_DESC request. */
+struct ofp14_table_desc {
+    ovs_be16 length;       /* Length is padded to 64 bits. */
+    uint8_t table_id;      /* Identifier of table. Lower numbered tables are 
consulted first. */
+    uint8_t pad[1];        /* Align to 32-bits. */
+    ovs_be32 config;   /* Bitmap of OFPTC_* values. */
+    /* Followed by 0 or more OFPTMPT14_* properties. */
+};
+OFP_ASSERT(sizeof(struct ofp14_table_desc) == 8);
+
 
 /* ## ---------------- ## */
 /* ## ofp14_port_stats ## */
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index 1423ac4..27273ad 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -439,6 +439,8 @@ lswitch_process_packet(struct lswitch *sw, const struct 
ofpbuf *msg)
     case OFPTYPE_METER_FEATURES_STATS_REPLY:
     case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
     case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
+    case OFPTYPE_TABLE_DESC_REQUEST:
+    case OFPTYPE_TABLE_DESC_REPLY:
     case OFPTYPE_BUNDLE_CONTROL:
     case OFPTYPE_BUNDLE_ADD_MESSAGE:
     default:
diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h
index 23c334a..d14c569 100644
--- a/lib/ofp-msgs.h
+++ b/lib/ofp-msgs.h
@@ -369,6 +369,12 @@ enum ofpraw {
     /* OFPST 1.3+ (12): struct ofp13_table_features, uint8_t[8][]. */
     OFPRAW_OFPST13_TABLE_FEATURES_REPLY,
 
+    /* OFPST 1.4+ (15): void. */
+    OFPRAW_OFPST14_TABLE_DESC_REQUEST,
+
+    /* OFPST 1.4+ (15): struct ofp14_table_desc, uint8_t[8][]. */
+    OFPRAW_OFPST14_TABLE_DESC_REPLY,
+
     /* OFPST 1.0-1.4 (13): void. */
     OFPRAW_OFPST10_PORT_DESC_REQUEST,
     /* OFPST 1.5+ (13): ovs_be32. */
@@ -602,6 +608,10 @@ enum ofptype {
 
     OFPTYPE_TABLE_FEATURES_STATS_REPLY, /* 
OFPRAW_OFPST13_TABLE_FEATURES_REPLY. */
 
+    OFPTYPE_TABLE_DESC_REQUEST,      /* OFPRAW_OFPST14_TABLE_DESC_REQUEST. */
+
+    OFPTYPE_TABLE_DESC_REPLY,        /* OFPRAW_OFPST14_TABLE_DESC_REPLY. */
+
     OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_DESC_REQUEST.
                                       * OFPRAW_OFPST15_PORT_DESC_REQUEST. */
 
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 9acf6a4..ac0f7d7 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -866,6 +866,10 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const 
char *table_id,
         tm->miss_config = OFPUTIL_TABLE_MISS_CONTINUE;
     } else if (strcmp(flow_miss_handling, "drop") == 0) {
         tm->miss_config = OFPUTIL_TABLE_MISS_DROP;
+    } else if (strcmp(flow_miss_handling, "evict") == 0) {
+        tm->config = OFPUTIL_TABLE_CONFIG_EVICTION;
+    } else if (strcmp(flow_miss_handling, "noevict") == 0) {
+        tm->config = OFPUTIL_TABLE_CONFIG_NO_EVICTION;
     } else {
         return xasprintf("invalid flow_miss_handling %s", flow_miss_handling);
     }
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index f4c5bc6..d7d7f97 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -987,6 +987,23 @@ ofp_print_table_miss_config(struct ds *string, enum 
ofputil_table_miss miss)
     }
 }
 
+/* This Function will print the config properties of table set through
+ *  mod-table command */
+static void
+ofp_print_table_config(struct ds *string, enum ofputil_table_config config,
+                       uint32_t flags)
+{
+    if (config & OFPUTIL_TABLE_CONFIG_EVICTION) {
+       ds_put_cstr(string, "Eviction");
+       if (flags & OFPTMPEF14_IMPORTANCE) {
+           ds_put_cstr(string, "    flag: Importance\n");
+       }
+    } else if ((config & OFPUTIL_TABLE_CONFIG_NO_EVICTION) ||
+               (config & OFPUTIL_TABLE_CONFIG_DEFAULT)) {
+       ds_put_cstr(string, "No Eviction\n");
+    }
+}
+
 static void
 ofp_print_table_mod(struct ds *string, const struct ofp_header *oh)
 {
@@ -1006,11 +1023,26 @@ ofp_print_table_mod(struct ds *string, const struct 
ofp_header *oh)
     }
 
     if (pm.miss_config != OFPUTIL_TABLE_MISS_DEFAULT) {
-        ds_put_cstr(string, ", flow_miss_config=");
-        ofp_print_table_miss_config(string, pm.miss_config);
+       ds_put_cstr(string, ", flow_miss_config=");
+       ofp_print_table_miss_config(string, pm.miss_config);
+    }
+    if (oh->version >= OFP14_VERSION) {
+       ds_put_cstr(string, "\n   config = ");
+        ofp_print_table_config(string, pm.config, pm.eviction_flags);
     }
 }
 
+/* This function will print the Table description properties */
+static void
+ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td)
+{
+    ds_put_format(string, "\n  table %"PRIu8, td->table_id);
+    ds_put_cstr(string, ":\n");
+
+    ds_put_cstr(string, "   config = ");
+    ofp_print_table_config(string, td->config, td->eviction_flags);
+}
+
 static void
 ofp_print_queue_get_config_request(struct ds *string,
                                    const struct ofp_header *oh)
@@ -2562,6 +2594,28 @@ ofp_print_table_features_reply(struct ds *s, const 
struct ofp_header *oh)
     }
 }
 
+static void
+ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh)
+{
+    struct ofpbuf b;
+
+    ofpbuf_use_const(&b, oh, ntohs(oh->length));
+
+    for (;;) {
+        struct ofputil_table_desc td;
+        int retval;
+
+        retval = ofputil_decode_table_desc(&b, &td);
+        if (retval) {
+            if (retval != EOF) {
+                ofp_print_error(s, retval);
+            }
+            return;
+        }
+        ofp_print_table_desc(s, &td);
+    }
+}
+
 static const char *
 bundle_flags_to_name(uint32_t bit)
 {
@@ -2690,6 +2744,11 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw 
raw,
         ofp_print_table_features_reply(string, oh);
         break;
 
+    case OFPTYPE_TABLE_DESC_REQUEST:
+    case OFPTYPE_TABLE_DESC_REPLY:
+        ofp_print_table_desc_reply(string, oh);
+        break;
+
     case OFPTYPE_HELLO:
         ofp_print_hello(string, oh);
         break;
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 2270a93..157c0fd 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -54,6 +54,9 @@ static struct vlog_rate_limit bad_ofmsg_rl = 
VLOG_RATE_LIMIT_INIT(1, 5);
 static enum ofputil_table_miss ofputil_table_miss_from_config(
     ovs_be32 config_, enum ofp_version);
 
+static enum ofputil_table_config ofputil_table_utilconfig_from_config(
+    ovs_be32 config_, enum ofp_version version);
+
 struct ofp_prop_header {
     ovs_be16 type;
     ovs_be16 len;
@@ -4903,7 +4906,192 @@ ofputil_append_table_features_reply(const struct 
ofputil_table_features *tf,
     ofpmp_postappend(replies, start_ofs);
 }
 
+/* Decodes the OpenFlow "table desc" message in '*msg' into an abstract form in
+ * '*td'.  Returns 0 if successful, otherwise an OFPERR_* value. */
+int
+ofputil_decode_table_desc(struct ofpbuf *msg,
+                          struct ofputil_table_desc *td)
+{
+    struct ofp14_table_desc *otd;
+    size_t length;
+    size_t property_length;
+
+    memset(td, 0, sizeof *td);
+
+    if (!msg->frame) {
+        ofpraw_pull_assert(msg);
+    }
+
+    if (!ofpbuf_size(msg)) {
+        return EOF;
+    }
+
+    otd = ofpbuf_try_pull(msg, sizeof *otd);
+
+    if (!otd) {
+        VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply has %"PRIu32" "
+                     "leftover bytes at end", ofpbuf_size(msg));
+        return OFPERR_OFPBRC_BAD_LEN;
+    }
+
+    td->table_id = otd->table_id;
+    td->config = ntohl(otd->config);
+    length = ntohs(otd->length);
+
+    if (length < sizeof *otd || length - sizeof *otd > ofpbuf_size(msg)) {
+        VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC reply claims invalid "
+                     "length %"PRIuSIZE, length);
+        return OFPERR_OFPBRC_BAD_LEN;
+    }
+
+    property_length = length - sizeof *otd;
+
+    while (property_length > 0) {
+        size_t prop_len;
+
+        if (td->config & OFPUTIL_TABLE_CONFIG_EVICTION) {
+            struct ofp14_table_mod_prop_eviction *ote;
+
+            ote = (property_length >= sizeof *ote
+                  ? ofpbuf_try_pull(msg, sizeof *ote)
+                  : NULL);
+
+            if (!ote) {
+                VLOG_WARN_RL(&bad_ofmsg_rl, "OFP14_TABLE_DESC property end 
with"
+                            "%"PRIuSIZE" leftover bytes", property_length);
+                return OFPERR_OFPBRC_BAD_LEN;
+            }
+
+            prop_len = ntohs(ote->length);
+            if (prop_len != sizeof *ote) {
+                VLOG_WARN_RL(&bad_ofmsg_rl, "Table property length "
+                             "%"PRIuSIZE" is not valid", prop_len);
+                return OFPERR_OFPBRC_BAD_LEN;
+            }
+
+            td->eviction_flags = ntohl(ote->flags);
+            property_length = property_length - prop_len;
+        }
+    }
+
+    return 0;
+}
+
+/* Encodes and returns a request to obtain the table desc feature of a switch.
+ * The message is encoded for OpenFlow version 'ofp_version'.*/
+struct ofpbuf *
+ofputil_encode_table_desc_request(enum ofp_version ofp_version)
+{
+    struct ofpbuf *request = NULL;
+
+    if (ofp_version >= OFP14_VERSION) {
+        request = ofpraw_alloc(OFPRAW_OFPST14_TABLE_DESC_REQUEST,
+                               ofp_version, 0);
+    } else {
+        ovs_fatal(0, "dump-table-desc needs OpenFlow 1.4 or later "
+                     "(\'-O OpenFlow14\')");
+    }
+
+    return request;
+}
+
+/* Function to append Table desc information in a reply list. */
+void
+ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
+                                struct ovs_list *replies)
+{
+    struct ofpbuf *reply = ofpbuf_from_list(list_back(replies));
+    size_t start_otd;
+    struct ofp14_table_desc *otd;
+
+    start_otd = ofpbuf_size(reply);
+    ofpbuf_put_zeros(reply, sizeof *otd);
+    if (td->config & OFPUTIL_TABLE_CONFIG_EVICTION) {
+        struct  ofp14_table_mod_prop_eviction *ote;
+        size_t start_ote;
+
+        start_ote = ofpbuf_size(reply);
+        ofpbuf_put_zeros(reply, sizeof *ote);
+        ote = ofpbuf_at_assert(reply, start_ote, sizeof *ote);
+        ote->type = htons(OFPTMPT14_EVICTION);
+        ote->length = htons(ofpbuf_size(reply) - start_ote);
+        ote->flags = htonl(td->eviction_flags);
+    }
+
+    otd = ofpbuf_at_assert(reply, start_otd, sizeof *otd);
+    otd->length = htons(ofpbuf_size(reply) - start_otd);
+    otd->table_id = td->table_id;
+    otd->config = htonl(td->config);
+    ofpmp_postappend(replies, start_otd);
+}
+
+/* Given 'config', taken from an OpenFlow 'version' message that specifies
+ * table configuration (a table mod message),
+ * returns the table configuration that it specifies.  */
+static enum ofputil_table_config
+ofputil_table_utilconfig_from_config(ovs_be32 config_, enum ofp_version 
version)
+{
+    uint32_t config = ntohl(config_);
+
+    if (version >= OFP14_VERSION) {
+        switch (config) {
+        case OFPTC14_EVICTION:
+            return OFPUTIL_TABLE_CONFIG_EVICTION;
+
+        case OFPTC11_TABLE_MISS_MASK:
+            return OFPUTIL_TABLE_CONFIG_NO_EVICTION;
+
+        default:
+            return OFPUTIL_TABLE_CONFIG_DEFAULT;
+        }
+    } else {
+        return OFPUTIL_TABLE_CONFIG_DEFAULT;
+    }
+}
+
+/* Given a table configuration, returns the corresponding OpenFlow table
+ * configuration for use in an OpenFlow message of the given 'version'.
+   Point for using Miss Mask as return value of No Eviction
+ * OFPTC11_TABLE_MISS_MASK is using same value as OFPTC14_DEPRECATED_MASK
+ * as defined in Openflow 1.4. In openflow-common.h, OFPTC14_DEPRECATED_MASK
+ * is not defined. Hence using MISS_MASK value*/
+ovs_be32
+ofputil_table_utilconfig_to_config(enum ofputil_table_config config,
+                             enum ofp_version version)
+{
+    if (version >= OFP14_VERSION) {
+        switch (config) {
+        case OFPUTIL_TABLE_CONFIG_EVICTION:
+            return htonl(OFPTC14_EVICTION);
+
+        case OFPUTIL_TABLE_CONFIG_NO_EVICTION:
+            return htonl(OFPTC11_TABLE_MISS_MASK);
+
+        case OFPUTIL_TABLE_CONFIG_DEFAULT:
+            return htonl(0);
+
+        default:
+            OVS_NOT_REACHED();
+        }
+    } else {
+        return htonl(0);
+    }
+}
+
 /* ofputil_table_mod */
+static enum ofperr
+parse_table_mod_eviction_property(struct ofpbuf *property,
+                                  struct ofputil_table_mod *tm)
+{
+    struct ofp14_table_mod_prop_eviction *ote = ofpbuf_data(property);
+
+    if (ofpbuf_size(property) != sizeof *ote) {
+        return OFPERR_OFPBRC_BAD_LEN;
+    }
+
+    tm->eviction_flags = ntohl(ote->flags);
+    return 0;
+}
 
 /* Given 'config', taken from an OpenFlow 'version' message that specifies
  * table configuration (a table mod, table stats, or table features message),
@@ -4968,6 +5156,7 @@ ofputil_decode_table_mod(const struct ofp_header *oh,
     enum ofpraw raw;
     struct ofpbuf b;
 
+    memset(pm, 0, sizeof *pm);
     ofpbuf_use_const(&b, oh, ntohs(oh->length));
     raw = ofpraw_pull_assert(&b);
 
@@ -4983,8 +5172,34 @@ ofputil_decode_table_mod(const struct ofp_header *oh,
         pm->table_id = otm->table_id;
         pm->miss_config = ofputil_table_miss_from_config(otm->config,
                                                          oh->version);
+        pm->config = ofputil_table_utilconfig_from_config(otm->config,
+                                                         oh->version);
         /* We do not understand any properties yet, so we do not bother
          * parsing them. */
+        while (ofpbuf_size(&b) > 0) {
+            struct ofpbuf property;
+            enum ofperr error;
+            uint16_t type;
+
+            error = ofputil_pull_property(&b, &property, &type);
+            if (error) {
+                return error;
+            }
+
+            switch (type) {
+            case OFPTMPT14_EVICTION:
+                error = parse_table_mod_eviction_property(&property, pm);
+                break;
+
+            default:
+                error = OFPERR_OFPBRC_BAD_TYPE;
+                break;
+            }
+
+            if (error) {
+                return error;
+            }
+        }
     } else {
         return OFPERR_OFPBRC_BAD_TYPE;
     }
@@ -5023,12 +5238,25 @@ ofputil_encode_table_mod(const struct ofputil_table_mod 
*pm,
     case OFP14_VERSION:
     case OFP15_VERSION: {
         struct ofp14_table_mod *otm;
+        struct ofp14_table_mod_prop_eviction *ote;
+        ovs_be32 miss_config, config;
 
         b = ofpraw_alloc(OFPRAW_OFPT14_TABLE_MOD, ofp_version, 0);
-        otm = ofpbuf_put_zeros(b, sizeof *otm);
-        otm->table_id = pm->table_id;
-        otm->config = ofputil_table_miss_to_config(pm->miss_config,
+       otm = ofpbuf_put_zeros(b, sizeof *otm);
+       otm->table_id = pm->table_id;
+        miss_config = ofputil_table_miss_to_config(pm->miss_config,
                                                    ofp_version);
+       config = ofputil_table_utilconfig_to_config(pm->config,
+                                                   ofp_version);
+        otm->config = config | miss_config;
+
+        if (pm->config & OFPUTIL_TABLE_CONFIG_EVICTION) {
+            ote = ofpbuf_put_zeros(b, sizeof *ote);
+            ote->type = htons(OFPTMPT14_EVICTION);
+            ote->length = htons(sizeof *ote);
+            ote->flags = htonl(OFPTMPEF14_IMPORTANCE);
+        }
+
         break;
     }
     default:
@@ -8525,6 +8753,7 @@ ofputil_is_bundlable(enum ofptype type)
     case OFPTYPE_AGGREGATE_STATS_REQUEST:
     case OFPTYPE_TABLE_STATS_REQUEST:
     case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
+    case OFPTYPE_TABLE_DESC_REQUEST:
     case OFPTYPE_PORT_STATS_REQUEST:
     case OFPTYPE_QUEUE_STATS_REQUEST:
     case OFPTYPE_PORT_DESC_STATS_REQUEST:
@@ -8566,6 +8795,7 @@ ofputil_is_bundlable(enum ofptype type)
     case OFPTYPE_METER_CONFIG_STATS_REPLY:
     case OFPTYPE_METER_FEATURES_STATS_REPLY:
     case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
+    case OFPTYPE_TABLE_DESC_REPLY:
     case OFPTYPE_ROLE_STATUS:
         break;
     }
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index d7cf5ca..fc23078 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -606,13 +606,33 @@ enum ofputil_table_miss {
     OFPUTIL_TABLE_MISS_DROP,       /* Drop the packet. */
 };
 
+/* Abstract version of OFPTC14_TABLE_CONFIG*.*/
+enum ofputil_table_config {
+    OFPUTIL_TABLE_CONFIG_DEFAULT     = 1 << 0,   /*  Table Config default 
behaviour*/
+    OFPUTIL_TABLE_CONFIG_NO_EVICTION = 1 << 1,   /*  No Eviction for Table*/
+    OFPUTIL_TABLE_CONFIG_EVICTION    = 1 << 2,   /*  Eviction for importance 
Configured */
+};
+
 ovs_be32 ofputil_table_miss_to_config(enum ofputil_table_miss,
                                       enum ofp_version);
 
+ovs_be32 ofputil_table_utilconfig_to_config(enum ofputil_table_config config,
+                                            enum ofp_version version);
+
+
 /* Abstract ofp_table_mod. */
 struct ofputil_table_mod {
     uint8_t table_id;         /* ID of the table, 0xff indicates all tables. */
+    enum ofputil_table_config config;
     enum ofputil_table_miss miss_config;
+    uint32_t eviction_flags;
+};
+
+/* Abstract ofp14_table_desc. */
+struct ofputil_table_desc {
+    uint8_t table_id;         /* ID of the table. */
+    enum ofputil_table_config config;
+    uint32_t eviction_flags;
 };
 
 enum ofperr ofputil_decode_table_mod(const struct ofp_header *,
@@ -681,11 +701,20 @@ struct ofputil_table_features {
 
 int ofputil_decode_table_features(struct ofpbuf *,
                                   struct ofputil_table_features *, bool loose);
+
+int ofputil_decode_table_desc(struct ofpbuf *,
+                              struct ofputil_table_desc *);
+
 struct ofpbuf *ofputil_encode_table_features_request(enum ofp_version);
 
+struct ofpbuf *ofputil_encode_table_desc_request(enum ofp_version);
+
 void ofputil_append_table_features_reply(
     const struct ofputil_table_features *tf, struct ovs_list *replies);
 
+void ofputil_append_table_desc_reply(
+    const struct ofputil_table_desc *td, struct ovs_list *replies);
+
 /* Meter band configuration for all supported band types. */
 struct ofputil_meter_band {
     uint16_t type;
@@ -812,6 +841,9 @@ struct ofputil_table_stats {
 };
 
 struct ofpbuf *ofputil_encode_table_stats_reply(const struct ofp_header *rq);
+
+struct ofpbuf *ofputil_encode_table_desc_reply(const struct ofp_header *rq);
+
 void ofputil_append_table_stats_reply(struct ofpbuf *reply,
                                       const struct ofputil_table_stats *,
                                       const struct ofputil_table_features *);
diff --git a/lib/rconn.c b/lib/rconn.c
index 2686c3a..62a230a 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -1389,6 +1389,8 @@ is_admitted_msg(const struct ofpbuf *b)
     case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
     case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
     case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
+    case OFPTYPE_TABLE_DESC_REQUEST:
+    case OFPTYPE_TABLE_DESC_REPLY:
         return false;
 
     case OFPTYPE_PACKET_IN:
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index d114390..2c421b4 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -243,6 +243,8 @@ struct oftable {
 
     /* Table configuration. */
     ATOMIC(enum ofputil_table_miss) miss_config;
+    ATOMIC(enum ofputil_table_config) config;
+    uint32_t eviction_flags;  /* Flags of value OFPTMPEF14_* */
 
     atomic_ulong n_matched;
     atomic_ulong n_missed;
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index ba4263e..8fd0af4 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -69,6 +69,8 @@ COVERAGE_DEFINE(ofproto_recv_openflow);
 COVERAGE_DEFINE(ofproto_reinit_ports);
 COVERAGE_DEFINE(ofproto_update_port);
 
+# define CLEAR_EVICTION_BIT 0x8
+
 /* Default fields to use for prefix tries in each flow table, unless something
  * else is configured. */
 const enum mf_field_id default_prefix_fields[2] =
@@ -88,6 +90,8 @@ static void oftable_enable_eviction(struct oftable *,
                                     const struct mf_subfield *fields,
                                     size_t n_fields);
 
+static void enable_eviction_for_importance(struct oftable *);
+
 static void oftable_remove_rule(struct rule *rule) OVS_REQUIRES(ofproto_mutex);
 
 /* A set of rules within a single OpenFlow table (oftable) that have the same
@@ -1302,7 +1306,7 @@ ofproto_configure_table(struct ofproto *ofproto, int 
table_id,
         return;
     }
 
-    if (s->groups) {
+    if (s->groups || (table->config & OFPUTIL_TABLE_CONFIG_EVICTION)) {
         oftable_enable_eviction(table, s->groups, s->n_groups);
     } else {
         oftable_disable_eviction(table);
@@ -3349,6 +3353,48 @@ handle_table_features_request(struct ofconn *ofconn,
     return 0;
 }
 
+/* This function queries the database for dumping table-desc*/
+static void
+query_tables_desc(struct ofproto *ofproto,
+                  struct ofputil_table_desc **descp)
+{
+    struct  ofputil_table_desc *table_desc;
+    size_t i;
+    table_desc = *descp =  xcalloc(ofproto->n_tables, sizeof *table_desc);
+    for (i = 0; i < ofproto->n_tables; i++) {
+        struct ofputil_table_desc *td = &table_desc[i];
+         td->table_id = i;
+         atomic_read_relaxed(&ofproto->tables[i].config, &td->config);
+         if (td->config & OFPUTIL_TABLE_CONFIG_EVICTION) {
+            td->eviction_flags = ofproto->tables[i].eviction_flags;
+        }
+    }
+}
+
+/* Function to handle dump-table-desc request */
+static enum ofperr
+handle_table_desc_request(struct ofconn *ofconn,
+                          const struct ofp_header *request)
+{
+    struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
+    struct  ofputil_table_desc *table_desc;
+    struct ovs_list replies;
+    size_t i;
+
+    query_tables_desc(ofproto, &table_desc);
+
+    ofpmp_init(&replies, request);
+    for (i = 0; i < ofproto->n_tables; i++) {
+        if (!(ofproto->tables[i].flags & OFTABLE_HIDDEN)) {
+             ofputil_append_table_desc_reply(&table_desc[i], &replies);
+        }
+    }
+    ofconn_send_replies(ofconn, &replies);
+    free(table_desc);
+
+    return 0;
+}
+
 static void
 append_port_stat(struct ofport *port, struct ovs_list *replies)
 {
@@ -6175,26 +6221,89 @@ ofproto_table_get_miss_config(const struct ofproto 
*ofproto, uint8_t table_id)
     return value;
 }
 
+/* This function configures or deconfigures eviction for all tables or
+ * for given table-id
+ * CLEAR_EVICTION_BIT - BIT-MASK for clearing the eviction/noeviction
+ * configuration and will have significance for other table configuartion
+ * properties */
+static void configure_eviction(const struct ofputil_table_mod *tm,
+                               struct ofproto *ofproto)
+{
+    enum ofputil_table_config table_config;
+    if (tm->table_id == OFPTT_ALL) {
+       int i;
+       for (i = 0; i < ofproto->n_tables; i++) {
+           atomic_read_relaxed(&ofproto->tables[i].config, &table_config);
+          table_config = table_config & CLEAR_EVICTION_BIT;
+          table_config = table_config | tm->config;
+          atomic_store_relaxed(&ofproto->tables[i].config,
+                  table_config);
+          ofproto->tables[i].eviction_flags = tm->eviction_flags;
+          if (tm->config & OFPUTIL_TABLE_CONFIG_EVICTION) {
+               enable_eviction_for_importance(&ofproto->tables[i]);
+           } else if (tm->config & OFPUTIL_TABLE_CONFIG_NO_EVICTION) {
+               oftable_disable_eviction(&ofproto->tables[i]);
+           }
+       }
+    } else {
+       atomic_read_relaxed(&ofproto->tables[tm->table_id].config,
+               &table_config);
+       table_config = table_config & CLEAR_EVICTION_BIT;
+       table_config = table_config | tm->config;
+       atomic_store_relaxed(&ofproto->tables[tm->table_id].config,
+               table_config);
+       ofproto->tables[tm->table_id].eviction_flags = tm->eviction_flags;
+       if (tm->config & OFPUTIL_TABLE_CONFIG_EVICTION) {
+           enable_eviction_for_importance(&ofproto->tables[tm->table_id]);
+       } else if (tm->config & OFPUTIL_TABLE_CONFIG_NO_EVICTION) {
+           oftable_disable_eviction(&ofproto->tables[tm->table_id]);
+       }
+    }
+}
+
+/* OFPUTIL_TABLE_CONFIG_NO_EVICTION and OFPUTIL_TABLE_CONFIG_DEFAULT
+ * these two values are considered different because we have to understand in 
switch
+ * that user wants to disable Eviction by explicitly giving Noevict or no 
value is passed
+ * at all which is default case */
 static enum ofperr
 table_mod(struct ofproto *ofproto, const struct ofputil_table_mod *tm)
 {
     if (!check_table_id(ofproto, tm->table_id)) {
         return OFPERR_OFPTMFC_BAD_TABLE;
-    } else if (tm->miss_config != OFPUTIL_TABLE_MISS_DEFAULT) {
+    }
+
+    if ((tm->config & OFPUTIL_TABLE_CONFIG_EVICTION) ||
+        (tm->config & OFPUTIL_TABLE_CONFIG_NO_EVICTION)) {
+        configure_eviction(tm, ofproto);
+    }
+
+    if (tm->miss_config != OFPUTIL_TABLE_MISS_DEFAULT) {
         if (tm->table_id == OFPTT_ALL) {
             int i;
             for (i = 0; i < ofproto->n_tables; i++) {
                 atomic_store_relaxed(&ofproto->tables[i].miss_config,
                                      tm->miss_config);
+           }
+       } else {
+           atomic_store_relaxed(&ofproto->tables[tm->table_id].miss_config,
+                               tm->miss_config);
             }
-        } else {
-            atomic_store_relaxed(&ofproto->tables[tm->table_id].miss_config,
-                                 tm->miss_config);
-        }
     }
     return 0;
 }
 
+/* This function is only used when eviction is performed on the
+   basis of importance. This function enables eviction on a particular table 
given */
+static void
+enable_eviction_for_importance(struct oftable *tables)
+{
+    struct mf_subfield *field = NULL;
+    size_t n_field = 0;
+
+    field = xmalloc(n_field* sizeof *field);
+    oftable_enable_eviction(tables, field, n_field);
+}
+
 static enum ofperr
 handle_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
 {
@@ -6392,6 +6501,9 @@ handle_openflow__(struct ofconn *ofconn, const struct 
ofpbuf *msg)
     case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
         return handle_table_features_request(ofconn, oh);
 
+    case OFPTYPE_TABLE_DESC_REQUEST:
+        return handle_table_desc_request(ofconn, oh);
+
     case OFPTYPE_PORT_STATS_REQUEST:
         return handle_port_stats_request(ofconn, oh);
 
@@ -6457,6 +6569,7 @@ handle_openflow__(struct ofconn *ofconn, const struct 
ofpbuf *msg)
     case OFPTYPE_METER_CONFIG_STATS_REPLY:
     case OFPTYPE_METER_FEATURES_STATS_REPLY:
     case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
+    case OFPTYPE_TABLE_DESC_REPLY:
     case OFPTYPE_ROLE_STATUS:
     default:
         if (ofpmsg_is_stat_request(oh)) {
@@ -6710,7 +6823,7 @@ eviction_group_find(struct oftable *table, uint32_t id)
 /* Returns an eviction priority for 'rule'.  The return value should be
  * interpreted so that higher priorities make a rule more attractive candidates
  * for eviction.
- * Called only if have a timeout. */
+ * Called if have a timeout and for eviction on basis of importance */
 static uint32_t
 rule_eviction_priority(struct ofproto *ofproto, struct rule *rule)
     OVS_REQUIRES(ofproto_mutex)
@@ -6718,12 +6831,30 @@ rule_eviction_priority(struct ofproto *ofproto, struct 
rule *rule)
     long long int expiration = LLONG_MAX;
     long long int modified;
     uint32_t expiration_offset;
+    struct oftable *table = &ofproto->tables[rule->table_id];
+    bool has_eviction_by_importance;
 
     /* 'modified' needs protection even when we hold 'ofproto_mutex'. */
     ovs_mutex_lock(&rule->mutex);
     modified = rule->modified;
     ovs_mutex_unlock(&rule->mutex);
 
+   /* For eviction on basis of importance only those entries will be added
+    * which have eviction fields set, importance parameter given in flow
+    * entry and table config parameter for eviction is set. */
+    has_eviction_by_importance = (table->eviction_fields &&
+                                  rule->importance &&
+                                  (table->config &
+                                  OFPUTIL_TABLE_CONFIG_EVICTION));
+
+   /* As per the openflow specification 1.4, flow entries with lesser 
importance
+    * will be evicted before flow entries with higher importance.So invert the
+    * value of importance for calculating the rule eviction priority as higher
+    * priorities make a rule more attractive candidates for eviction. */
+    if (has_eviction_by_importance) {
+       return UINT32_MAX - (rule->importance);
+    }
+
     if (rule->hard_timeout) {
         expiration = modified + rule->hard_timeout * 1000;
     }
@@ -6765,12 +6896,22 @@ eviction_group_add_rule(struct rule *rule)
     struct ofproto *ofproto = rule->ofproto;
     struct oftable *table = &ofproto->tables[rule->table_id];
     bool has_timeout;
+    bool has_eviction_by_importance;
 
     /* Timeouts may be modified only when holding 'ofproto_mutex'.  We have it
      * so no additional protection is needed. */
     has_timeout = rule->hard_timeout || rule->idle_timeout;
 
-    if (table->eviction_fields && has_timeout) {
+   /* For eviction on basis of importance only those entries will be added
+    * which have eviction fields set, importance parameter is not zero in flow
+    * entry and table config parameter for eviction is set. All rules are added
+    * in a single group when eviction is done on basis of importance. */
+    has_eviction_by_importance = (table->eviction_fields &&
+                                  rule->importance &&
+                                  (table->config &
+                                  OFPUTIL_TABLE_CONFIG_EVICTION));
+
+    if ((table->eviction_fields && has_timeout) || has_eviction_by_importance) 
{
         struct eviction_group *evg;
 
         evg = eviction_group_find(table, eviction_group_hash_rule(rule));
@@ -6792,6 +6933,7 @@ oftable_init(struct oftable *table)
     classifier_init(&table->cls, flow_segment_u64s);
     table->max_flows = UINT_MAX;
     atomic_init(&table->miss_config, OFPUTIL_TABLE_MISS_DEFAULT);
+    atomic_init(&table->config, OFPUTIL_TABLE_CONFIG_DEFAULT);
 
     classifier_set_prefix_fields(&table->cls, default_prefix_fields,
                                  ARRAY_SIZE(default_prefix_fields));
diff --git a/tests/ofp-print.at b/tests/ofp-print.at
index dc809e2..6753e21 100644
--- a/tests/ofp-print.at
+++ b/tests/ofp-print.at
@@ -1133,6 +1133,7 @@ AT_CHECK([ovs-ofctl ofp-print "\
 05 11 00 10 00 00 00 02 02 00 00 00 00 00 00 00 \
 " 3], [0], [dnl
 OFPT_TABLE_MOD (OF1.4) (xid=0x2): table_id=2
+   config = No Eviction
 ])
 AT_CLEANUP
 
diff --git a/tests/ofproto.at b/tests/ofproto.at
index 2a2111f..1732083 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -1568,6 +1568,111 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 dump-table-features 
br0 | sed '/^$/d
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto - table description (OpenFlow 1.4)])
+OVS_VSWITCHD_START
+(x=0
+ while test $x -lt 254; do
+   y=`expr $x + 1`
+   echo "  table $x:
+   config = No Eviction"
+   x=$y
+ done) > expout
+AT_CHECK([ovs-ofctl -O OpenFlow14 dump-table-desc br0 | sed '/^$/d
+/^OFPST_TABLE_DESC/d'], [0], [expout])
+
+# Change the configuration.
+AT_CHECK([ovs-ofctl -O Openflow14 mod-table br0 0 evict])
+# Check that the configuration was updated.
+mv expout orig-expout
+FLAG_STRING="    flag: Importance"
+sed -e "2s/No Eviction/Eviction/
+2s/$/$FLAG_STRING/" <orig-expout > expout
+AT_CHECK([ovs-ofctl -O OpenFlow14 dump-table-desc br0 | sed '/^$/d
+/^OFPST_TABLE_DESC/d'], [0], [expout])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - eviction using importance upon table overflow (OpenFlow 
1.4)])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+  [ovs-vsctl \
+     -- --id=@t0 create Flow_Table flow-limit=4 \
+     -- set bridge br0 flow_tables:0=@t0 \
+   | ${PERL} $srcdir/uuidfilt.pl],
+  [0], [<0>
+])
+# set the Eviction configuration.
+AT_CHECK([ovs-ofctl -O Openflow14 mod-table br0 0 evict])
+# Add 4 flows.
+for in_port in 4 3 2 1; do
+    ovs-ofctl -O Openflow14 add-flow br0 importance=$((in_port + 
30)),priority=$((in_port + 5)),hard_timeout=$((in_port + 500)),actions=drop
+done
+AT_CHECK([ovs-ofctl -O Openflow14 dump-flows br0 | ofctl_strip | sort], [0], 
[dnl
+ hard_timeout=501, importance=31, priority=6 actions=drop
+ hard_timeout=502, importance=32, priority=7 actions=drop
+ hard_timeout=503, importance=33, priority=8 actions=drop
+ hard_timeout=504, importance=34, priority=9 actions=drop
+OFPST_FLOW reply (OF1.4):
+])
+# Adding another flow will cause the one with lowest importance to be evicted.
+AT_CHECK([ovs-ofctl -O Openflow14 add-flow br0 
hard_timeout=505,importance=35,priority=10,in_port=2,actions=drop])
+AT_CHECK([ovs-ofctl -O Openflow14 dump-flows br0 | ofctl_strip | sort], [0], 
[dnl
+ hard_timeout=502, importance=32, priority=7 actions=drop
+ hard_timeout=503, importance=33, priority=8 actions=drop
+ hard_timeout=504, importance=34, priority=9 actions=drop
+ hard_timeout=505, importance=35, priority=10,in_port=2 actions=drop
+OFPST_FLOW reply (OF1.4):
+])
+# Disable the Eviction configuration.
+AT_CHECK([ovs-ofctl -O Openflow14 mod-table br0 0 noevict])
+# Adding another flow will cause the system to give error for FULL TABLE.
+AT_CHECK([ovs-ofctl -O Openflow14 add-flow br0 
hard_timeout=506,importance=36,priority=11,actions=drop],[1], [], [stderr])
+AT_CHECK([head -n 1 stderr | ofctl_strip], [0],
+ [OFPT_ERROR (OF1.4): OFPFMFC_TABLE_FULL
+])
+#Dump flows. It should show only the old values
+AT_CHECK([ovs-ofctl -O Openflow14 dump-flows br0 | ofctl_strip | sort], [0], 
[dnl
+ hard_timeout=502, importance=32, priority=7 actions=drop
+ hard_timeout=503, importance=33, priority=8 actions=drop
+ hard_timeout=504, importance=34, priority=9 actions=drop
+ hard_timeout=505, importance=35, priority=10,in_port=2 actions=drop
+OFPST_FLOW reply (OF1.4):
+])
+# mod-flow that would modify a flow will be done successfully.
+AT_CHECK([ovs-ofctl -O Openflow14 mod-flows br0 in_port=2,actions=NORMAL])
+AT_CHECK([ovs-ofctl -O Openflow14 dump-flows br0 | ofctl_strip | sort], [0], 
[dnl
+ hard_timeout=502, importance=32, priority=7 actions=drop
+ hard_timeout=503, importance=33, priority=8 actions=drop
+ hard_timeout=504, importance=34, priority=9 actions=drop
+ hard_timeout=505, importance=35, priority=10,in_port=2 actions=NORMAL
+OFPST_FLOW reply (OF1.4):
+])
+# Also a mod-flow that would add a flow will be refused.
+AT_CHECK([ovs-ofctl mod-flows br0 in_port=5,actions=drop], [1], [], [stderr])
+AT_CHECK([head -n 1 stderr | ofctl_strip], [0],
+  [OFPT_ERROR: OFPFMFC_TABLE_FULL
+])
+# Now set the eviction on timeout basis.
+AT_CHECK(
+  [ovs-vsctl \
+     -- --id=@t0 create Flow_Table flow-limit=4 overflow-policy=evict \
+     -- set bridge br0 flow_tables:0=@t0 \
+   | ${PERL} $srcdir/uuidfilt.pl],
+  [0], [<0>
+])
+#Now add a new flow
+AT_CHECK([ovs-ofctl -O Openflow14 add-flow br0 
importance=37,hard_timeout=507,priority=11,in_port=6,actions=drop])
+AT_CHECK([ovs-ofctl -O Openflow14 dump-flows br0 | ofctl_strip | sort], [0], 
[dnl
+ hard_timeout=503, importance=33, priority=8 actions=drop
+ hard_timeout=504, importance=34, priority=9 actions=drop
+ hard_timeout=505, importance=35, priority=10,in_port=2 actions=NORMAL
+ hard_timeout=507, importance=37, priority=11,in_port=6 actions=drop
+OFPST_FLOW reply (OF1.4):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto - hard limits on flow table size (OpenFlow 1.0)])
 OVS_VSWITCHD_START
 # Configure a maximum of 4 flows.
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index b73c24c..2a2305c 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -62,8 +62,14 @@ Prints to the console statistics for each of the flow tables 
used by
 \fBdump\-table\-features \fIswitch\fR
 Prints to the console features for each of the flow tables used by
 \fIswitch\fR.
+.TP
+\fBdump\-table\-desc \fIswitch\fR
+Prints to the console configuration for each of the flow tables used
+by \fIswitch\fR for OpenFlow 1.4+.
 .
-.IP "\fBmod\-table \fIswitch\fR \fItable_id\fR  \fIflow_miss_handling\fR"
+.IP "\fBmod\-table \fIswitch\fR \fItable_id\fR \fIflow_miss_handling/config\fR"
+.RS
+.IP \fIflow_miss_handling\fR
 An OpenFlow 1.0 switch looks up each packet that arrives at the switch
 in table 0, then in table 1 if there is no match in table 0, then in
 table 2, and so on until the packet finds a match in some table.
@@ -87,6 +93,23 @@ tables other than the last one.)
 Send to controller.  (This is how an OpenFlow 1.0 switch always
 handles packets that do not match any flow in the last table.)
 .RE
+.IP \fIconfig\fR
+An OpenFlow  1.4+ switch configures the behaviour of the table when the
+table is full.
+.IP
+This command configures the flow table configuration for table
+\fItable_id\fR in \fIswitch\fR.  \fItable_id\fR may be an OpenFlow
+table number between 0 and 254, inclusive, or the keyword \fBALL\fR to
+modify all tables.  \fIconfig\fR may be any one of the following:
+.RS
+.IP \fBevict\fR
+Enable eviction on \fItable_id\fR of \fIswitch\fR on the basis of
+importance.
+.IP \fBnoevict\fR
+Disable eviction on \fItable_id\fR of \fIswitch\fR on the basis of
+importance.
+.RE
+.RE
 .
 .TP
 \fBdump\-ports \fIswitch\fR [\fInetdev\fR]
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index b5ace5a..7278674 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -316,6 +316,7 @@ usage(void)
            "  dump-desc SWITCH            print switch description\n"
            "  dump-tables SWITCH          print table stats\n"
            "  dump-table-features SWITCH  print table features\n"
+           "  dump-tables-desc SWITCH     print table description\n"
            "  mod-port SWITCH IFACE ACT   modify port behavior\n"
            "  mod-table SWITCH MOD        modify flow table behavior\n"
            "  get-frags SWITCH            print fragment handling behavior\n"
@@ -701,6 +702,24 @@ ofctl_dump_table_features(int argc OVS_UNUSED, char 
*argv[])
     vconn_close(vconn);
 }
 
+/* ovs-ofctl dump-table-desc provides a way to list the current configuration 
of
+ * the tables on a switch, which is set using the ovs-ofctl table-mod command. 
*/
+static void
+ofctl_dump_table_desc(int argc OVS_UNUSED, char *argv[])
+{
+    struct ofpbuf *request;
+    struct vconn *vconn;
+
+    open_vconn(argv[1], &vconn);
+    request = ofputil_encode_table_desc_request(vconn_get_version(vconn));
+    if (request) {
+        dump_stats_transaction(vconn, request);
+    }
+
+    vconn_close(vconn);
+}
+
+
 static bool fetch_port_by_stats(struct vconn *,
                                 const char *port_name, ofp_port_t port_no,
                                 struct ofputil_phy_port *);
@@ -3496,6 +3515,8 @@ static const struct command all_commands[] = {
       1, 1, ofctl_dump_tables },
     { "dump-table-features", "switch",
       1, 1, ofctl_dump_table_features },
+    { "dump-table-desc", "switch",
+      1, 1, ofctl_dump_table_desc},
     { "dump-flows", "switch",
       1, 2, ofctl_dump_flows },
     { "dump-aggregate", "switch",
-- 
2.2.1

=====-----=====-----=====
Notice: The information contained in this e-mail
message and/or attachments to it may contain 
confidential or privileged information. If you are 
not the intended recipient, any dissemination, use, 
review, distribution, printing or copying of the 
information contained in this e-mail message 
and/or attachments to it are strictly prohibited. If 
you have received this communication in error, 
please notify us by reply e-mail or telephone and 
immediately and permanently delete the message 
and any attachments. Thank you


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

Reply via email to