X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=b924af58774c4dfdc742e165ee58aad48185b704;hb=fff1b9c0e004f9cf516c40805d923cb444276933;hp=90890b9e8ee12a198a2754be9df74fc6def4cd9a;hpb=e73e916510ce46af85fee4dd52127a699a244820;p=cascardo%2Fovs.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 90890b9e8..b924af587 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1122,6 +1122,7 @@ check_variable_length_userdata(struct dpif_backer *backer) execute.packet = &packet; execute.needs_help = false; execute.probe = true; + execute.mtu = 0; error = dpif_execute(backer->dpif, &execute); @@ -1220,6 +1221,7 @@ check_masked_set_action(struct dpif_backer *backer) execute.packet = &packet; execute.needs_help = false; execute.probe = true; + execute.mtu = 0; error = dpif_execute(backer->dpif, &execute); @@ -1234,6 +1236,47 @@ check_masked_set_action(struct dpif_backer *backer) 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) +CHECK_FEATURE(ct_mark) +CHECK_FEATURE__(ct_label, ct_label.u64.lo) + +#undef CHECK_FEATURE +#undef CHECK_FEATURE__ + static void check_support(struct dpif_backer *backer) { @@ -1245,6 +1288,11 @@ 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); + backer->support.odp.ct_mark = check_ct_mark(backer); + backer->support.odp.ct_label = check_ct_label(backer); } static int @@ -3682,7 +3730,10 @@ ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto, xin.resubmit_stats = &stats; xin.recurse = recurse; xin.resubmits = resubmits; - xlate_actions(&xin, &xout); + if (xlate_actions(&xin, &xout) != XLATE_OK) { + error = EINVAL; + goto out; + } execute.actions = odp_actions.data; execute.actions_len = odp_actions.size; @@ -3691,6 +3742,7 @@ ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto, execute.packet = packet; execute.needs_help = (xout.slow & SLOW_ACTION) != 0; execute.probe = false; + execute.mtu = 0; /* Fix up in_port. */ in_port = flow->in_port.ofp_port; @@ -3700,7 +3752,7 @@ ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto, execute.packet->md.in_port.odp_port = ofp_port_to_odp_port(ofproto, in_port); error = dpif_execute(ofproto->backer->dpif, &execute); - +out: xlate_out_uninit(&xout); ofpbuf_uninit(&odp_actions); @@ -3962,11 +4014,52 @@ rule_dealloc(struct rule *rule_) free(rule); } +static enum ofperr +rule_check(struct rule *rule) +{ + uint16_t ct_state, ct_zone; + const ovs_u128 *labelp; + ovs_u128 ct_label = { { 0, 0 } }; + uint32_t ct_mark; + + ct_state = MINIFLOW_GET_U16(rule->cr.match.flow, ct_state); + ct_zone = MINIFLOW_GET_U16(rule->cr.match.flow, ct_zone); + ct_mark = MINIFLOW_GET_U32(rule->cr.match.flow, ct_mark); + labelp = MINIFLOW_GET_U128_PTR(rule->cr.match.flow, ct_label); + if (labelp) { + ct_label = *labelp; + } + + if (ct_state || ct_zone || ct_mark + || !ovs_u128_is_zero(&ct_label)) { + 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) + || (ct_mark && !support->ct_mark) + || (!ovs_u128_is_zero(&ct_label) && !support->ct_label)) { + 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; @@ -4450,7 +4543,7 @@ ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, name, sizeof name); ds_put_format(&ds, "%5s %4d ", name, grp->vlan); - print_ipv6_mapped(&ds, &grp->addr); + ipv6_format_mapped(&grp->addr, &ds); ds_put_format(&ds, " %3d\n", mcast_bundle_age(ofproto->ms, b)); } @@ -4856,13 +4949,18 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc, goto exit; } if (enforce_consistency) { - retval = ofpacts_check_consistency(ofpacts.data, ofpacts.size, - &flow, u16_to_ofp(ofproto->up.max_ports), - 0, 0, usable_protocols); + retval = ofpacts_check_consistency(ofpacts.data, ofpacts.size, &flow, + u16_to_ofp(ofproto->up.max_ports), + 0, ofproto->up.n_tables, + usable_protocols); } else { retval = ofpacts_check(ofpacts.data, ofpacts.size, &flow, - u16_to_ofp(ofproto->up.max_ports), 0, 0, - &usable_protocols); + u16_to_ofp(ofproto->up.max_ports), 0, + ofproto->up.n_tables, &usable_protocols); + } + if (!retval) { + retval = ofproto_check_ofpacts(&ofproto->up, ofpacts.data, + ofpacts.size); } if (retval) { @@ -4898,6 +4996,7 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, struct ds *ds) { struct trace_ctx trace; + enum xlate_error error; ds_put_format(ds, "Bridge: %s\n", ofproto->up.name); ds_put_cstr(ds, "Flow: "); @@ -4917,8 +5016,7 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, trace.xin.resubmit_hook = trace_resubmit; trace.xin.report_hook = trace_report_valist; - xlate_actions(&trace.xin, &trace.xout); - + error = xlate_actions(&trace.xin, &trace.xout); ds_put_char(ds, '\n'); trace_format_flow(ds, 0, "Final flow", &trace); trace_format_megaflow(ds, 0, "Megaflow", &trace); @@ -4926,7 +5024,10 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, ds_put_cstr(ds, "Datapath actions: "); format_odp_actions(ds, trace.odp_actions.data, trace.odp_actions.size); - if (trace.xout.slow) { + if (error != XLATE_OK) { + ds_put_format(ds, "\nTranslation failed (%s), packet is dropped.\n", + xlate_strerror(error)); + } else if (trace.xout.slow) { enum slow_path_reason slow; ds_put_cstr(ds, "\nThis flow is handled by the userspace "