[ovs-dev] [PATCH] ovs-ofctl: Implementation of eviction on the basis of Importance

Hiteshi Madan hiteshi.madan at tcs.com
Mon Nov 3 11:24:50 UTC 2014


From: root <root at TCS.(none)>

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

ovs-ofctl mod-table <bridge> <table> evict
Enable eviction on <table> of <bridge>. Eviction adds a mechanism
enabling the switch to automatically eliminate entries of lower
importance to make space for newer entries. This enables to smoother
degradation of behaviour when the table is full. If want to enable eviction
on all tables, user can set the <table> as 'all'.

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

Signed-off-by:saloni.jain at tcs.com
---
 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                 |   59 +++++++++
 lib/ofp-util.c                  |  275 ++++++++++++++++++++++++++++++++++++++-
 lib/ofp-util.h                  |   47 +++++++
 lib/rconn.c                     |    2 +
 ofproto/ofproto-provider.h      |    1 +
 ofproto/ofproto.c               |  134 +++++++++++++++++--
 tests/ofproto.at                |  105 +++++++++++++++
 utilities/ovs-ofctl.c           |   20 +++
 12 files changed, 655 insertions(+), 14 deletions(-)

diff --git a/include/openflow/openflow-1.4.h b/include/openflow/openflow-1.4.h
index 2a765cf..dcb4439 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 e3b48d5..5b8ac07 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -438,6 +438,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 a78747e..18a6f32 100644
--- a/lib/ofp-msgs.h
+++ b/lib/ofp-msgs.h
@@ -367,6 +367,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. */
@@ -598,6 +604,10 @@ enum ofptype {
     OFPTYPE_TABLE_FEATURES_STATS_REQUEST, /* OFPRAW_OFPST13_TABLE_FEATURES_REQUEST. */
 
     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 f7cf10d..d99069f 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -867,6 +867,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 90df745..3559486 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -978,6 +978,27 @@ 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, const struct ofputil_table_desc *td)
+{
+    switch (td->config) {
+    case OFPUTIL_TABLE_CONFIG_EVICTION:
+        ds_put_cstr(string, "Eviction");
+        if (td->evict.flags & OFPUTIL_TABLE_EVICTION_IMPORTANCE) {
+            ds_put_cstr(string, "    flag: Importance\n");
+        }  
+        break;
+    case OFPUTIL_TABLE_CONFIG_NO_EVICTION:
+    case OFPUTIL_TABLE_CONFIG_DEFAULT:
+        ds_put_cstr(string, "No Eviction\n");
+        break;
+    default:
+        ds_put_format(string, "Unknown (%d)\n", td->config);
+     ÿÿ break;
+ÿÿÿ }
+}
+
ÿstatic void
ÿofp_print_table_mod(struct ds *string, const struct ofp_header *oh)
ÿ{
@@ -1002,6 +1023,17 @@ ofp_print_table_mod(struct ds *string, const struct ofp_header *oh)
ÿÿÿÿ }
ÿ}
ÿ
+/* 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);
+}
+
ÿstatic void
ÿofp_print_queue_get_config_request(struct ds *string,
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ const struct ofp_header *oh)
@@ -2496,6 +2528,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)
ÿ{
@@ -2624,6 +2678,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 02d102d..a7e5f9b 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -53,11 +53,54 @@ 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);
+
+static const struct ovstableprop_map *get_ovsprop_map(void);
+
+ovs_be32 ovsprop_bitmap_to_openflow(uint32_t ovsprop_bitmap);
+
ÿstruct ofp_prop_header {
ÿÿÿÿ ovs_be16 type;
ÿÿÿÿ ovs_be16 len;
ÿ};
ÿ
+/* Two-way translation between OFPUTIL eviction flag and representation of
+ * eviction flags "OFPTMPEF_*" used in OpenFlow specification. */
+struct ovstableprop_map {
+ÿÿÿ enum ofputil_table_mod_prop_eviction_flag flag; /* Internal name for eviction flag. */
+ÿÿÿ int ofp_flag;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ /* OFPTMPEF_* number from OpenFlow spec. */
+};
+
+static const struct ovstableprop_map *
+get_ovsprop_map()
+{
+ÿÿÿ /* OpenFlow 1.4 eviction flags. */
+ÿÿÿ static const struct ovstableprop_map of14[] = {
+ÿÿÿÿÿÿÿ { OFPUTIL_TABLE_EVICTION_OTHER, 1 },
+ÿÿÿÿÿÿÿ { OFPUTIL_TABLE_EVICTION_IMPORTANCE, 2 },
+ÿÿÿÿÿÿÿ { OFPUTIL_TABLE_EVICTION_LIFETIME, 4 },
+ÿÿÿÿÿÿÿ { 0, -1 },
+ÿÿÿ };
+ÿÿÿ return of14;
+}
+
+/* Converts 'ovstableprop_bitmap', a bitmap whose bits correspond to OFPUTIL_*
+ * values, into a bitmap of eviction flags. */
+ovs_be32
+ovsprop_bitmap_to_openflow(uint32_t ovsprop_bitmap)
+{
+ÿÿÿ uint32_t ofpevict_bitmap = 0;
+ÿÿÿ const struct ovstableprop_map *x;
+
+ÿÿÿ for (x = get_ovsprop_map(); x->ofp_flag >= 0; x++) {
+ÿÿÿÿÿÿÿ if (ovsprop_bitmap & (1u << x->flag)) {
+ÿÿÿÿÿÿÿÿÿÿÿ ofpevict_bitmap |= 1u << x->ofp_flag;
+ÿÿÿÿÿÿÿ }
+ÿÿÿ }
+ÿÿÿ return htonl(ofpevict_bitmap);
+}
+
ÿ/* Pulls a property, beginning with struct ofp_prop_header, from the beginning
ÿ * of 'msg'.ÿ Stores the type of the property in '*typep' and, if 'property' is
ÿ * nonnull, the entire property, including the header, in '*property'.ÿ Returns
@@ -4552,6 +4595,25 @@ parse_instruction_ids(struct ofpbuf *payload, bool loose, uint32_t *insts)
ÿ}
ÿ
ÿstatic enum ofperr
+parse_table_property(struct ofpbuf *payload, uint32_t *flags)
+{
+ÿÿÿ *flags = 0;
+ÿÿÿ while (ofpbuf_size(payload) > 0) {
+ÿÿÿÿÿÿÿ enum ofperr error;
+ÿÿÿÿÿÿÿ uint16_t ofp_flags = 0;
+ÿÿÿÿÿÿÿ error = ofputil_pull_property__(payload, NULL, 1, &ofp_flags);
+ÿÿÿÿÿÿÿ if (error) {
+ÿÿÿÿÿÿÿÿÿÿÿ return error;
+ÿÿÿÿÿÿÿ }
+ÿÿÿÿÿÿ /* ofp_flags contains the bitmap sent from vswitchd containing value of type eviction flags OFPTMPEF_*
+ * flags are calculated from this value of ofp_flags.
+ */ÿÿÿ 
+ÿÿÿÿÿÿ *flags |= 1u << ofp_flags;
+ÿÿÿ }
+ÿÿÿ return 0;
+}
+
+static enum ofperr
ÿparse_table_features_next_table(struct ofpbuf *payload,
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ unsigned long int *next_tables)
ÿ{
@@ -4785,6 +4847,32 @@ ofputil_encode_table_features_request(enum ofp_version ofp_version)
ÿÿÿÿ return request;
ÿ}
ÿ
+/* 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;
+
+ÿÿÿ switch (ofp_version) {
+ÿÿÿ case OFP10_VERSION:
+ÿÿÿ case OFP11_VERSION:
+ÿÿÿ case OFP12_VERSION:
+ÿÿÿÿÿÿÿ ovs_fatal(0, "dump-table-desc needs OpenFlow 1.3 or later "
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ "(\'-O OpenFlow13\')");
+ÿÿÿ case OFP13_VERSION:
+ÿÿÿ case OFP14_VERSION:
+ÿÿÿ case OFP15_VERSION:
+ÿÿÿÿÿÿÿ request = ofpraw_alloc(OFPRAW_OFPST14_TABLE_DESC_REQUEST,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ofp_version, 0);
+ÿÿÿÿÿÿÿ break;
+ÿÿÿ default:
+ÿÿÿÿÿÿÿ OVS_NOT_REACHED();
+ÿÿÿ }
+
+ÿÿÿ return request;
+}
+
ÿstatic void
ÿput_fields_property(struct ofpbuf *reply,
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ const struct mf_bitmap *fields,
@@ -4850,6 +4938,17 @@ put_table_instruction_features(
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ OFPTFPT13_APPLY_SETFIELD, miss_offset, version);
ÿ}
ÿ
+static void
+put_table_mod_eviction_property(struct ofpbuf *reply,
+ const struct ofputil_table_mod_prop_eviction *tme)
+{
+ÿÿÿ size_t start_ofs;
+ÿÿÿ start_ofs = start_property(reply, OFPTMPT14_EVICTION);
+ÿÿÿ put_bitmap_properties(reply,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ntohl(ovsprop_bitmap_to_openflow(tme->flags)));
+ÿÿÿ end_property(reply, start_ofs);
+}
+
ÿvoid
ÿofputil_append_table_features_reply(const struct ofputil_table_features *tf,
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ struct list *replies)
@@ -4880,6 +4979,29 @@ ofputil_append_table_features_reply(const struct ofputil_table_features *tf,
ÿÿÿÿ ofpmp_postappend(replies, start_ofs);
ÿ}
ÿ
+/* Function to append Table desc information in a reply list. */
+void
+ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ struct list *replies)
+{
+ÿÿÿ struct ofpbuf *reply = ofpbuf_from_list(list_back(replies));
+ÿÿÿ enum ofp_version version = ofpmp_version(replies);
+ÿÿÿ size_t start_ofs = ofpbuf_size(reply);
+ÿÿÿ struct ofp14_table_desc *otd;
+ÿÿÿ enum ofputil_table_config config;
+
+ÿÿÿ otd = ofpbuf_put_zeros(reply, sizeof *otd);
+ÿÿÿ otd->table_id = td->table_id;
+ÿÿÿ config = ofputil_table_utilconfig_to_config(td->config, version);
+ÿÿÿ otd->config = config;
+ÿÿÿ if (td->config == OFPUTIL_TABLE_CONFIG_EVICTION) {
+ÿÿÿÿÿÿÿ put_table_mod_eviction_property(reply, &td->evict);
+ÿÿÿ }
+ÿÿÿ otd = ofpbuf_at_assert(reply, start_ofs, sizeof *otd);
+ÿÿÿ otd->length = htons(ofpbuf_size(reply) - start_ofs);
+ÿÿÿ ofpmp_postappend(replies, start_ofs);
+}
+
ÿ/* ofputil_table_mod */
ÿ
ÿ/* Given 'config', taken from an OpenFlow 'version' message that specifies
@@ -4910,6 +5032,32 @@ ofputil_table_miss_from_config(ovs_be32 config_, enum ofp_version version)
ÿÿÿÿ }
ÿ}
ÿ
+
+/* 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;
+ÿÿÿÿÿÿÿ case OFPTC11_TABLE_MISS_CONTROLLER:ÿ /* for handling Default Value 0 */
+ÿÿÿÿÿÿÿÿÿÿÿ return OFPUTIL_TABLE_CONFIG_DEFAULT;
+ÿÿÿÿÿÿÿ default:
+ÿÿÿÿÿÿÿÿÿÿÿ VLOG_WARN_RL(&bad_ofmsg_rl, "bad table config %d", config);
+ÿÿÿÿÿÿÿÿÿÿÿ return OFPUTIL_TABLE_CONFIG_DEFAULT;
+ÿÿÿÿÿÿÿ }
+ÿÿÿ } else {
+ÿÿÿÿÿÿÿ return OFPUTIL_TABLE_CONFIG_DEFAULT;
+ÿÿÿ }
+}
+
ÿ/* Given a table miss configuration, returns the corresponding OpenFlow table
ÿ * configuration for use in an OpenFlow message of the given 'version'. */
ÿovs_be32
@@ -4936,6 +5084,33 @@ ofputil_table_miss_to_config(enum ofputil_table_miss miss,
ÿÿÿÿ }
ÿ}
ÿ
+/* 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);
+ÿÿÿ }
+}
+
+
ÿ/* Decodes the OpenFlow "table mod" message in '*oh' into an abstract form in
ÿ * '*pm'.ÿ Returns 0 if successful, otherwise an OFPERR_* value. */
ÿenum ofperr
@@ -4960,8 +5135,8 @@ 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);
-ÿÿÿÿÿÿÿ /* We do not understand any properties yet, so we do not bother
-ÿÿÿÿÿÿÿÿ * parsing them. */
+ÿÿÿÿÿÿÿ pm->config = ofputil_table_utilconfig_from_config(otm->config,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ oh->version);
ÿÿÿÿ } else {
ÿÿÿÿÿÿÿÿ return OFPERR_OFPBRC_BAD_TYPE;
ÿÿÿÿ }
@@ -4969,6 +5144,75 @@ ofputil_decode_table_mod(const struct ofp_header *oh,
ÿÿÿÿ return 0;
ÿ}
ÿ
+
+/* Decodes the OpenFlow "table desc" message in '*oh' into an abstract form in
+ * '*pd'.ÿ Returns 0 if successful, otherwise an OFPERR_* value. */
+int
+ofputil_decode_table_desc(struct ofpbuf *msg,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ struct ofputil_table_desc *td)
+{
+ÿÿÿ const struct ofp_header *oh;
+ÿÿÿ struct ofp14_table_desc *otd;
+ÿÿÿ struct ofpbuf properties;
+ÿÿÿ unsigned int len;
+
+ÿÿÿ memset(td, 0, sizeof *td);
+
+ÿÿÿ if (!msg->frame) {
+ÿÿÿÿÿÿÿ ofpraw_pull_assert(msg);
+ÿÿÿ }
+ÿÿÿ oh = ofpbuf_l2(msg);
+
+ÿÿÿ if (!ofpbuf_size(msg)) {
+ÿÿÿÿÿÿÿ return EOF;
+ÿÿÿ }
+
+ÿÿÿ if (ofpbuf_size(msg) < sizeof *otd) {
+ÿÿÿÿÿÿÿ return OFPERR_OFPBPC_BAD_LEN;
+ÿÿÿ }
+
+ÿÿÿ otd = ofpbuf_data(msg);
+ÿÿÿ len = ntohs(otd->length);
+ÿÿÿ if (len < sizeof *otd || len % 8 || len > ofpbuf_size(msg)) {
+ÿÿÿÿÿÿÿ return OFPERR_OFPBPC_BAD_LEN;
+ÿÿÿ }
+ÿÿÿ ofpbuf_use_const(&properties, ofpbuf_pull(msg, len), len);
+ÿÿÿ ofpbuf_pull(&properties, sizeof *otd);
+
+ÿÿÿ td->table_id = otd->table_id;
+ÿÿÿ if (td->table_id == OFPTT_ALL) {
+ÿÿÿÿÿÿÿ return OFPERR_OFPTFFC_BAD_TABLE;
+ÿÿÿ }
+
+ÿÿÿ td->config = ofputil_table_utilconfig_from_config(otd->config,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ oh->version);
+ÿÿÿÿ while (ofpbuf_size(&properties) > 0) {
+ÿÿÿÿÿÿÿ struct ofpbuf payload;
+ÿÿÿÿÿÿÿ enum ofperr error;
+ÿÿÿÿÿÿÿ uint16_t type;
+
+ÿÿÿÿÿÿÿ error = pull_table_feature_property(&properties, &payload, &type);
+ÿÿÿÿÿÿÿ if (error) {
+ÿÿÿÿÿÿÿÿÿÿÿ return error;
+ÿÿÿÿÿÿÿ }
+ÿÿÿÿÿÿÿ switch ((enum ofp14_table_mod_prop_type) type) {
+ÿÿÿÿÿÿÿ case OFPTMPT14_EVICTION:
+ÿÿÿÿÿÿÿÿÿÿÿ error = parse_table_property(&payload, &td->evict.flags);
+ÿÿÿÿÿÿÿÿÿÿÿ break;
+ÿÿÿÿÿÿÿ case OFPTMPT14_VACANCY:
+ÿÿÿÿÿÿÿ case OFPTMPT14_EXPERIMENTER:
+ÿÿÿÿÿÿÿ default:
+ÿÿÿÿÿÿÿÿÿÿÿ log_property(true, "unknown table features property %"PRIu16,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ type);
+ÿÿÿÿÿÿÿÿÿÿÿ break;
+ÿÿÿÿÿÿÿ }
+ÿÿÿÿÿÿÿ if (error) {
+ÿÿÿÿÿÿÿÿÿÿÿ return error;
+ÿÿÿÿÿÿÿ }
+ÿÿÿ }
+ÿÿÿ return 0;
+}
+
ÿ/* Converts the abstract form of a "table mod" message in '*pm' into an OpenFlow
ÿ * message suitable for 'protocol', and returns that encoded form in a buffer
ÿ * owned by the caller. */
@@ -5000,12 +5244,25 @@ ofputil_encode_table_mod(const struct ofputil_table_mod *pm,
ÿÿÿÿ case OFP14_VERSION:
ÿÿÿÿ case OFP15_VERSION: {
ÿÿÿÿÿÿÿÿ struct ofp14_table_mod *otm;
+ÿÿÿÿÿÿÿ enum ofputil_table_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,
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ofp_version);
+ otm = ofpbuf_put_zeros(b, sizeof *otm);
+ otm->table_id = pm->table_id;
+ÿÿÿÿÿÿÿ /* As per the openflow specification miss_config is handled only for
+ * versions lessÿ than OFP13_VERSION so this handling is not required here.
+ÿÿÿÿÿÿÿ 
+ miss_config = ofputil_table_miss_to_config(pm->miss_config,
+ ofp_version);*/
+
+ config = ofputil_table_utilconfig_to_config(pm->config,
+ ofp_version);
+
+ÿÿÿÿÿÿ /* Mod -table arguments are miss-config and config fields.
+ÿÿÿÿÿÿÿÿÿ for handling both in Standard structure, we are doing following */
+ //otm->config = (miss_config | config);
+
+ otm->config = config;
ÿÿÿÿÿÿÿÿ break;
ÿÿÿÿ }
ÿÿÿÿ default:
@@ -5378,6 +5635,12 @@ ofputil_encode_table_stats_reply(const struct ofp_header *request)
ÿÿÿÿ return ofpraw_alloc_stats_reply(request, 0);
ÿ}
ÿ
+struct ofpbuf *
+ofputil_encode_table_desc_reply(const struct ofp_header *request)
+{
+ÿÿÿ return ofpraw_alloc_stats_reply(request, 0);
+}
+
ÿvoid
ÿofputil_append_table_stats_reply(struct ofpbuf *reply,
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ const struct ofputil_table_stats *stats,
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index e3e11b4..cfe5de5 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -607,15 +607,43 @@ 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,ÿÿÿÿÿ /*ÿ Table Config default behaviour*/
+ÿÿÿ OFPUTIL_TABLE_CONFIG_EVICTION,ÿÿÿÿ /*ÿ Eviction for importance Configured */
+ÿÿÿ OFPUTIL_TABLE_CONFIG_NO_EVICTION,ÿ /*ÿ No Eviction for Table*/
+};
+
+/* Abstract version of OFPTMPEF_* */ÿ 
+enum ofputil_table_mod_prop_eviction_flag{
+ÿÿÿ OFPUTIL_TABLE_EVICTION_OTHER =ÿ 1,ÿÿÿÿÿÿ /*ÿ Eviction Enabled Using other Factors */
+ÿÿÿ OFPUTIL_TABLE_EVICTION_IMPORTANCE = 2,ÿ /*ÿ Eviction Enabled Using flow entry importance */
+ÿÿÿ OFPUTIL_TABLE_EVICTION_LIFETIME = 4,ÿÿÿ /*ÿ Eviction Enabled Using flow entry lifetime */
+};
+
ÿ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;
ÿ};
ÿ
+/* Abstract ofp14_table_desc. */
+struct ofputil_table_desc{
+ÿÿÿ uint8_t table_id;ÿÿÿÿÿÿÿÿ /* ID of the table, 0xff indicates all tables. */
+ÿÿÿ enum ofputil_table_config config;
+ÿÿÿ struct ofputil_table_mod_prop_eviction{
+ÿÿÿÿÿÿÿ uint32_t flags;
+ÿÿÿ }evict;
+};
+
ÿenum ofperr ofputil_decode_table_mod(const struct ofp_header *,
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ struct ofputil_table_mod *);
ÿstruct ofpbuf *ofputil_encode_table_mod(const struct ofputil_table_mod *,
@@ -682,11 +710,27 @@ struct ofputil_table_features {
ÿ
ÿint ofputil_decode_table_features(struct ofpbuf *,
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ struct ofputil_table_features *, bool loose);
+
+/* Eviction_Changes_1.4*/
+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 list *replies);
ÿ
+/* Eviction_Changes_1.4*/
+void
+ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ struct list *replies);
+
+/* Eviction_Changes_1.4
+void
+ofputil_append_table_desc_reply(struct ofpbuf *buf,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ const struct ofputil_table_desc *td);*/
+
+
ÿ/* Meter band configuration for all supported band types. */
ÿstruct ofputil_meter_band {
ÿÿÿÿ uint16_t type;
@@ -813,6 +857,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 5c28806..46f08ff 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:
ÿÿÿÿ case OFPTYPE_BUNDLE_CONTROL:
ÿÿÿÿ case OFPTYPE_BUNDLE_ADD_MESSAGE:
ÿÿÿÿÿÿÿÿ return false;
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 8204862..69f878b 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -243,6 +243,7 @@ struct oftable {
ÿ
ÿÿÿÿ /* Table configuration. */
ÿÿÿÿ ATOMIC(enum ofputil_table_miss) miss_config;
+ÿÿÿ ATOMIC(enum ofputil_table_config) config;
ÿ
ÿÿÿÿ atomic_ulong n_matched;
ÿÿÿÿ atomic_ulong n_missed;
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index fd9822b..fa35a31 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -88,6 +88,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);
ÿstatic void oftable_remove_rule__(struct ofproto *, struct rule *)
ÿÿÿÿ OVS_REQUIRES(ofproto_mutex);
@@ -1286,7 +1288,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);
@@ -3329,6 +3331,54 @@ 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->evict.flags = OFPUTIL_TABLE_EVICTION_IMPORTANCE;
+ÿÿÿÿÿÿÿÿ }
+ÿÿÿ }
+}
+
+/* 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 list replies;
+ÿÿÿ struct ofpbuf msg;
+ÿÿÿ size_t i;
+
+ÿÿÿ ofpbuf_use_const(&msg, request, ntohs(request->length));
+ÿÿÿ ofpraw_pull_assert(&msg);
+ÿÿÿ if (ofpbuf_size(&msg) || ofpmp_more(request)) {
+ÿÿÿÿÿÿÿ return OFPERR_OFPTFFC_EPERM;
+ÿÿÿ }
+ÿÿÿ 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 list *replies)
ÿ{
@@ -5932,26 +5982,69 @@ ofproto_table_get_miss_config(const struct ofproto *ofproto, uint8_t table_id)
ÿÿÿÿ return value;
ÿ}
ÿ
+/* 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 explicitely 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) {
+ÿÿÿ } else if (tm->config == OFPUTIL_TABLE_CONFIG_EVICTION) {
ÿÿÿÿÿÿÿÿ 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);
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ atomic_store_relaxed(&ofproto->tables[i].config,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ tm->config);
+ÿÿÿÿÿÿÿ enable_eviction_for_importance(&ofproto->tables[i]);
+ÿÿÿ }
+ } else {
+ÿÿÿ atomic_store_relaxed(&ofproto->tables[tm->table_id].config,
+ tm->config);
+ÿÿÿÿÿÿÿÿÿÿÿ enable_eviction_for_importance(&ofproto->tables[tm->table_id]);
+ }
+ÿÿÿ } else if (tm->config == OFPUTIL_TABLE_CONFIG_NO_EVICTION) {
+ÿÿÿÿÿÿÿ if (tm->table_id == OFPTT_ALL) {
+ÿÿÿÿÿÿÿÿÿÿÿ int i;
+ÿÿÿÿÿÿÿÿÿÿÿ for (i = 0; i < ofproto->n_tables; i++) {
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ atomic_store_relaxed(&ofproto->tables[i].config,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ tm->config);
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ oftable_disable_eviction(&ofproto->tables[i]);
ÿÿÿÿÿÿÿÿÿÿÿÿ }
ÿÿÿÿÿÿÿÿ } else {
-ÿÿÿÿÿÿÿÿÿÿÿ atomic_store_relaxed(&ofproto->tables[tm->table_id].miss_config,
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ tm->miss_config);
+ÿÿÿÿÿÿÿÿÿÿÿ atomic_store_relaxed(&ofproto->tables[tm->table_id].config,
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ tm->config);
+ÿÿÿÿÿÿÿÿÿÿÿ oftable_disable_eviction(&ofproto->tables[tm->table_id]);
ÿÿÿÿÿÿÿÿ }
ÿÿÿÿ }
+ÿÿÿ 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);
+ÿÿÿÿÿÿÿÿÿÿÿ }
+ÿÿÿ }
ÿÿÿÿ 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)
ÿ{
@@ -6139,6 +6232,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);
ÿ
@@ -6204,6 +6300,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)) {
@@ -6457,7 +6554,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 only 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)
@@ -6465,12 +6562,26 @@ 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;
ÿÿÿÿ }
@@ -6512,12 +6623,18 @@ 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));
@@ -6539,6 +6656,7 @@ oftable_init(struct oftable *table)
ÿÿÿÿ classifier_init(&table->cls, flow_segment_u32s);
ÿÿÿÿ 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/ofproto.at b/tests/ofproto.at
index 69f8dc9..6879e74 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -1269,6 +1269,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.c b/utilities/ovs-ofctl.c
index 67465ce..95d0616 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -699,6 +699,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 *);
@@ -3474,6 +3492,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",
-- 
1.7.9.5
=====-----=====-----=====
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





More information about the dev mailing list