return !error;
}
+#define CHECK_FEATURE__(NAME, FIELD) \
+static bool \
+check_##NAME(struct dpif_backer *backer) \
+{ \
+ struct flow flow; \
+ struct odputil_keybuf keybuf; \
+ struct ofpbuf key; \
+ bool enable; \
+ struct odp_flow_key_parms odp_parms = { \
+ .flow = &flow, \
+ .support = { \
+ .NAME = true, \
+ }, \
+ }; \
+ \
+ memset(&flow, 0, sizeof flow); \
+ flow.FIELD = 1; \
+ \
+ ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); \
+ odp_flow_key_from_flow(&odp_parms, &key); \
+ enable = dpif_probe_feature(backer->dpif, #NAME, &key, NULL); \
+ \
+ if (enable) { \
+ VLOG_INFO("%s: Datapath supports "#NAME, dpif_name(backer->dpif)); \
+ } else { \
+ VLOG_INFO("%s: Datapath does not support "#NAME, \
+ dpif_name(backer->dpif)); \
+ } \
+ \
+ return enable; \
+}
+#define CHECK_FEATURE(FIELD) CHECK_FEATURE__(FIELD, FIELD)
+
+CHECK_FEATURE(ct_state)
+CHECK_FEATURE(ct_zone)
+
+#undef CHECK_FEATURE
+#undef CHECK_FEATURE__
+
static void
check_support(struct dpif_backer *backer)
{
backer->support.masked_set_action = check_masked_set_action(backer);
backer->support.ufid = check_ufid(backer);
backer->support.tnl_push_pop = dpif_supports_tnl_push_pop(backer->dpif);
+
+ backer->support.odp.ct_state = check_ct_state(backer);
+ backer->support.odp.ct_zone = check_ct_zone(backer);
}
static int
free(rule);
}
+static enum ofperr
+rule_check(struct rule *rule)
+{
+ uint16_t ct_state, ct_zone;
+
+ ct_state = MINIFLOW_GET_U16(rule->cr.match.flow, ct_state);
+ ct_zone = MINIFLOW_GET_U16(rule->cr.match.flow, ct_zone);
+
+ if (ct_state || ct_zone) {
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->ofproto);
+ const struct odp_support *support = &ofproto_dpif_get_support(ofproto)->odp;
+
+ if ((ct_state && !support->ct_state)
+ || (ct_zone && !support->ct_zone)) {
+ return OFPERR_OFPBMC_BAD_FIELD;
+ }
+ if (ct_state & CS_UNSUPPORTED_MASK) {
+ return OFPERR_OFPBMC_BAD_MASK;
+ }
+ }
+ return 0;
+}
+
static enum ofperr
rule_construct(struct rule *rule_)
OVS_NO_THREAD_SAFETY_ANALYSIS
{
struct rule_dpif *rule = rule_dpif_cast(rule_);
+ int error;
+
+ error = rule_check(rule_);
+ if (error) {
+ return error;
+ }
+
ovs_mutex_init_adaptive(&rule->stats_mutex);
rule->stats.n_packets = 0;
rule->stats.n_bytes = 0;