return error;
}
-/* Convert 'table_id' and 'flow_miss_handling' (as described for the
- * "mod-table" command in the ovs-ofctl man page) into 'tm' for sending the
- * specified table_mod 'command' to a switch.
+/* Convert 'table_id' and 'setting' (as described for the "mod-table" command
+ * in the ovs-ofctl man page) into 'tm' for sending a table_mod command to a
+ * switch.
+ *
+ * Stores a bitmap of the OpenFlow versions that are usable for 'tm' into
+ * '*usable_versions'.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
* error. The caller is responsible for freeing the returned string. */
char * OVS_WARN_UNUSED_RESULT
parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id,
- const char *flow_miss_handling,
- enum ofputil_protocol *usable_protocols)
+ const char *setting, uint32_t *usable_versions)
{
- /* Table mod requires at least OF 1.1. */
- *usable_protocols = OFPUTIL_P_OF11_UP;
-
+ *usable_versions = 0;
if (!strcasecmp(table_id, "all")) {
tm->table_id = OFPTT_ALL;
} else {
}
}
- if (strcmp(flow_miss_handling, "controller") == 0) {
- tm->miss_config = OFPUTIL_TABLE_MISS_CONTROLLER;
- } else if (strcmp(flow_miss_handling, "continue") == 0) {
- tm->miss_config = OFPUTIL_TABLE_MISS_CONTINUE;
- } else if (strcmp(flow_miss_handling, "drop") == 0) {
- tm->miss_config = OFPUTIL_TABLE_MISS_DROP;
+ tm->miss = OFPUTIL_TABLE_MISS_DEFAULT;
+ tm->eviction = OFPUTIL_TABLE_EVICTION_DEFAULT;
+ tm->eviction_flags = UINT32_MAX;
+
+ /* Only OpenFlow 1.1 and 1.2 can configure table-miss via table_mod.
+ * Only OpenFlow 1.4+ can configure eviction via table_mod.
+ *
+ * (OpenFlow 1.4+ can also configure vacancy events via table_mod, but OVS
+ * doesn't support those yet and they're also logically a per-OpenFlow
+ * session setting so it wouldn't make sense to support them here anyway.)
+ */
+ if (!strcmp(setting, "controller")) {
+ tm->miss = OFPUTIL_TABLE_MISS_CONTROLLER;
+ *usable_versions = (1u << OFP11_VERSION) | (1u << OFP12_VERSION);
+ } else if (!strcmp(setting, "continue")) {
+ tm->miss = OFPUTIL_TABLE_MISS_CONTINUE;
+ *usable_versions = (1u << OFP11_VERSION) | (1u << OFP12_VERSION);
+ } else if (!strcmp(setting, "drop")) {
+ tm->miss = OFPUTIL_TABLE_MISS_DROP;
+ *usable_versions = (1u << OFP11_VERSION) | (1u << OFP12_VERSION);
+ } else if (!strcmp(setting, "evict")) {
+ tm->eviction = OFPUTIL_TABLE_EVICTION_ON;
+ *usable_versions = (1 << OFP14_VERSION) | (1u << OFP15_VERSION);
+ } else if (!strcmp(setting, "noevict")) {
+ tm->eviction = OFPUTIL_TABLE_EVICTION_OFF;
+ *usable_versions = (1 << OFP14_VERSION) | (1u << OFP15_VERSION);
} else {
- return xasprintf("invalid flow_miss_handling %s", flow_miss_handling);
+ return xasprintf("invalid table_mod setting %s", setting);
}
if (tm->table_id == 0xfe
- && tm->miss_config == OFPUTIL_TABLE_MISS_CONTINUE) {
+ && tm->miss == OFPUTIL_TABLE_MISS_CONTINUE) {
return xstrdup("last table's flow miss handling can not be continue");
}
}
return NULL;
}
+
+char * OVS_WARN_UNUSED_RESULT
+parse_ofp_geneve_table_mod_str(struct ofputil_geneve_table_mod *gtm,
+ uint16_t command, const char *s,
+ enum ofputil_protocol *usable_protocols)
+{
+ *usable_protocols = OFPUTIL_P_NXM_OXM_ANY;
+
+ gtm->command = command;
+ list_init(>m->mappings);
+
+ while (*s) {
+ struct ofputil_geneve_map *map = xmalloc(sizeof *map);
+ int n;
+
+ if (*s == ',') {
+ s++;
+ }
+
+ list_push_back(>m->mappings, &map->list_node);
+
+ if (!ovs_scan(s, "{class=%"SCNi16",type=%"SCNi8",len=%"SCNi8"}->tun_metadata%"SCNi16"%n",
+ &map->option_class, &map->option_type, &map->option_len,
+ &map->index, &n)) {
+ ofputil_uninit_geneve_table(>m->mappings);
+ return xstrdup("invalid geneve mapping");
+ }
+
+ s += n;
+ }
+
+ return NULL;
+}