X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=8cb9a2dbba65331b776ae22e435874f65698ddaa;hb=9daf23484fb1f0d8fe8bf807a82c3d5b571a3dea;hp=d06d76588c1c6b62037bc9b2ec2e9d8c2edaf8fa;hpb=0fc1f5c04c8c1a9ac461da8c6ab88dee680a5ab3;p=cascardo%2Fovs.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index d06d76588..8cb9a2dbb 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -515,6 +515,12 @@ lookup_ofproto_dpif_by_port_name(const char *name) return NULL; } +bool +ofproto_dpif_backer_enabled(struct dpif_backer* backer) +{ + return backer->recv_set_enable; +} + static int type_run(const char *type) { @@ -1228,6 +1234,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) { @@ -1239,6 +1286,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 @@ -1829,7 +1881,7 @@ port_modified(struct ofport *port_) } ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm, - port->lldp, port->up.pp.hw_addr); + port->lldp, &port->up.pp.hw_addr); dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf); @@ -1965,7 +2017,7 @@ out: ofproto->backer->need_revalidate = REV_RECONFIGURE; } ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm, - ofport->lldp, ofport->up.pp.hw_addr); + ofport->lldp, &ofport->up.pp.hw_addr); return error; } @@ -2007,7 +2059,7 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg) ofproto->backer->need_revalidate = REV_RECONFIGURE; } ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm, - ofport->lldp, ofport->up.pp.hw_addr); + ofport->lldp, &ofport->up.pp.hw_addr); return 0; } @@ -2063,7 +2115,7 @@ set_lldp(struct ofport *ofport_, ofport->bfd, ofport->cfm, ofport->lldp, - ofport->up.pp.hw_addr); + &ofport->up.pp.hw_addr); return error; } @@ -2119,7 +2171,7 @@ rstp_send_bpdu_cb(struct dp_packet *pkt, void *ofport_, void *ofproto_) struct ofport_dpif *ofport = ofport_; struct eth_header *eth = dp_packet_l2(pkt); - netdev_get_etheraddr(ofport->up.netdev, eth->eth_src); + netdev_get_etheraddr(ofport->up.netdev, ð->eth_src); if (eth_addr_is_zero(eth->eth_src)) { VLOG_WARN_RL(&rl, "%s port %d: cannot send RSTP BPDU on a port which " "does not have a configured source MAC address.", @@ -2144,7 +2196,7 @@ send_bpdu_cb(struct dp_packet *pkt, int port_num, void *ofproto_) } else { struct eth_header *eth = dp_packet_l2(pkt); - netdev_get_etheraddr(ofport->up.netdev, eth->eth_src); + netdev_get_etheraddr(ofport->up.netdev, ð->eth_src); if (eth_addr_is_zero(eth->eth_src)) { VLOG_WARN_RL(&rl, "%s: cannot send BPDU on port %d " "with unknown MAC", ofproto->up.name, port_num); @@ -2290,9 +2342,14 @@ rstp_run(struct ofproto_dpif *ofproto) } if (rstp_shift_root_learned_address(ofproto->rstp)) { - bundle_move(((struct ofport_dpif *)rstp_get_old_root_aux(ofproto->rstp))->bundle, - ((struct ofport_dpif *)rstp_get_new_root_aux(ofproto->rstp))->bundle); - rstp_reset_root_changed(ofproto->rstp); + struct ofport_dpif *old_root_aux = + (struct ofport_dpif *)rstp_get_old_root_aux(ofproto->rstp); + struct ofport_dpif *new_root_aux = + (struct ofport_dpif *)rstp_get_new_root_aux(ofproto->rstp); + if (old_root_aux != NULL && new_root_aux != NULL) { + bundle_move(old_root_aux->bundle, new_root_aux->bundle); + rstp_reset_root_changed(ofproto->rstp); + } } } } @@ -2532,8 +2589,11 @@ set_rstp_port(struct ofport *ofport_, if (!s || !s->enable) { if (rp) { - rstp_port_unref(rp); + rstp_port_set_aux(rp, NULL); + rstp_port_set_state(rp, RSTP_DISABLED); + rstp_port_set_mac_operational(rp, false); ofport->rstp_port = NULL; + rstp_port_unref(rp); update_rstp_port_state(ofport); } return; @@ -2978,10 +3038,10 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10); struct ofport_dpif *port = port_; - uint8_t ea[ETH_ADDR_LEN]; + struct eth_addr ea; int error; - error = netdev_get_etheraddr(port->up.netdev, ea); + error = netdev_get_etheraddr(port->up.netdev, &ea); if (!error) { struct dp_packet packet; void *packet_pdu; @@ -3636,14 +3696,13 @@ rule_expire(struct rule_dpif *rule) } } -/* Executes, within 'ofproto', the actions in 'rule' or 'ofpacts' on 'packet'. - * 'flow' must reflect the data in 'packet'. */ int -ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, - const struct flow *flow, - struct rule_dpif *rule, - const struct ofpact *ofpacts, size_t ofpacts_len, - struct dp_packet *packet) +ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto, + const struct flow *flow, + struct rule_dpif *rule, + const struct ofpact *ofpacts, size_t ofpacts_len, + int recurse, int resubmits, + struct dp_packet *packet) { struct dpif_flow_stats stats; struct xlate_out xout; @@ -3660,15 +3719,19 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, rule_dpif_credit_stats(rule, &stats); } + uint64_t odp_actions_stub[1024 / 8]; + struct ofpbuf odp_actions = OFPBUF_STUB_INITIALIZER(odp_actions_stub); xlate_in_init(&xin, ofproto, flow, flow->in_port.ofp_port, rule, - stats.tcp_flags, packet); + stats.tcp_flags, packet, NULL, &odp_actions); xin.ofpacts = ofpacts; xin.ofpacts_len = ofpacts_len; xin.resubmit_stats = &stats; + xin.recurse = recurse; + xin.resubmits = resubmits; xlate_actions(&xin, &xout); - execute.actions = xout.odp_actions->data; - execute.actions_len = xout.odp_actions->size; + execute.actions = odp_actions.data; + execute.actions_len = odp_actions.size; pkt_metadata_from_flow(&packet->md, flow); execute.packet = packet; @@ -3685,10 +3748,24 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, error = dpif_execute(ofproto->backer->dpif, &execute); xlate_out_uninit(&xout); + ofpbuf_uninit(&odp_actions); return error; } +/* Executes, within 'ofproto', the actions in 'rule' or 'ofpacts' on 'packet'. + * 'flow' must reflect the data in 'packet'. */ +int +ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto, + const struct flow *flow, + struct rule_dpif *rule, + const struct ofpact *ofpacts, size_t ofpacts_len, + struct dp_packet *packet) +{ + return ofproto_dpif_execute_actions__(ofproto, flow, rule, ofpacts, + ofpacts_len, 0, 0, packet); +} + void rule_dpif_credit_stats(struct rule_dpif *rule, const struct dpif_flow_stats *stats) @@ -3762,29 +3839,19 @@ ofproto_dpif_get_tables_version(struct ofproto_dpif *ofproto OVS_UNUSED) } /* The returned rule (if any) is valid at least until the next RCU quiescent - * period. If the rule needs to stay around longer, a non-zero 'take_ref' - * must be passed in to cause a reference to be taken on it. + * period. If the rule needs to stay around longer, the caller should take + * a reference. * * 'flow' is non-const to allow for temporary modifications during the lookup. * Any changes are restored before returning. */ static struct rule_dpif * rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, cls_version_t version, uint8_t table_id, struct flow *flow, - struct flow_wildcards *wc, bool take_ref) + struct flow_wildcards *wc) { struct classifier *cls = &ofproto->up.tables[table_id].cls; - const struct cls_rule *cls_rule; - struct rule_dpif *rule; - - do { - cls_rule = classifier_lookup(cls, version, flow, wc); - - rule = rule_dpif_cast(rule_from_cls_rule(cls_rule)); - - /* Try again if the rule was released before we get the reference. */ - } while (rule && take_ref && !rule_dpif_try_ref(rule)); - - return rule; + return rule_dpif_cast(rule_from_cls_rule(classifier_lookup(cls, version, + flow, wc))); } /* Look up 'flow' in 'ofproto''s classifier version 'version', starting from @@ -3804,9 +3871,8 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, cls_version_t version, * '*table_id'. * * The rule is returned in '*rule', which is valid at least until the next - * RCU quiescent period. If the '*rule' needs to stay around longer, - * a non-zero 'take_ref' must be passed in to cause a reference to be taken - * on it before this returns. + * RCU quiescent period. If the '*rule' needs to stay around longer, the + * caller must take a reference. * * 'in_port' allows the lookup to take place as if the in port had the value * 'in_port'. This is needed for resubmit action support. @@ -3816,7 +3882,7 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, cls_version_t version, struct rule_dpif * rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, cls_version_t version, struct flow *flow, - struct flow_wildcards *wc, bool take_ref, + struct flow_wildcards *wc, const struct dpif_flow_stats *stats, uint8_t *table_id, ofp_port_t in_port, bool may_packet_in, bool honor_table_miss) @@ -3839,9 +3905,6 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, /* Must be OFPC_FRAG_DROP (we don't have OFPC_FRAG_REASM). * Use the drop_frags_rule (which cannot disappear). */ rule = ofproto->drop_frags_rule; - if (take_ref) { - rule_dpif_ref(rule); - } if (stats) { struct oftable *tbl = &ofproto->up.tables[*table_id]; unsigned long orig; @@ -3868,8 +3931,7 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, next_id++, next_id += (next_id == TBL_INTERNAL)) { *table_id = next_id; - rule = rule_dpif_lookup_in_table(ofproto, version, next_id, flow, wc, - take_ref); + rule = rule_dpif_lookup_in_table(ofproto, version, next_id, flow, wc); if (stats) { struct oftable *tbl = &ofproto->up.tables[next_id]; unsigned long orig; @@ -3908,9 +3970,6 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, rule = ofproto->miss_rule; } } - if (take_ref) { - rule_dpif_ref(rule); - } out: /* Restore port numbers, as they may have been modified above. */ flow->tp_src = old_tp_src; @@ -3949,11 +4008,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; @@ -4464,8 +4564,9 @@ struct trace_ctx { struct xlate_in xin; const struct flow *key; struct flow flow; - struct flow_wildcards wc; struct ds *result; + struct flow_wildcards wc; + struct ofpbuf odp_actions; }; static void @@ -4532,7 +4633,7 @@ static void trace_format_odp(struct ds *result, int level, const char *title, struct trace_ctx *trace) { - struct ofpbuf *odp_actions = trace->xout.odp_actions; + struct ofpbuf *odp_actions = &trace->odp_actions; ds_put_char_multiple(result, '\t', level); ds_put_format(result, "%s: ", title); @@ -4548,7 +4649,6 @@ trace_format_megaflow(struct ds *result, int level, const char *title, ds_put_char_multiple(result, '\t', level); ds_put_format(result, "%s: ", title); - flow_wildcards_or(&trace->wc, &trace->xout.wc, &trace->wc); match_init(&match, trace->key, &trace->wc); match_format(&match, result, OFP_DEFAULT_PRIORITY); ds_put_char(result, '\n'); @@ -4891,13 +4991,14 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, flow_format(ds, flow); ds_put_char(ds, '\n'); - flow_wildcards_init_catchall(&trace.wc); + ofpbuf_init(&trace.odp_actions, 0); trace.result = ds; trace.key = flow; /* Original flow key, used for megaflow. */ trace.flow = *flow; /* May be modified by actions. */ xlate_in_init(&trace.xin, ofproto, flow, flow->in_port.ofp_port, NULL, - ntohs(flow->tcp_flags), packet); + ntohs(flow->tcp_flags), packet, &trace.wc, + &trace.odp_actions); trace.xin.ofpacts = ofpacts; trace.xin.ofpacts_len = ofpacts_len; trace.xin.resubmit_hook = trace_resubmit; @@ -4910,8 +5011,7 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, trace_format_megaflow(ds, 0, "Megaflow", &trace); ds_put_cstr(ds, "Datapath actions: "); - format_odp_actions(ds, trace.xout.odp_actions->data, - trace.xout.odp_actions->size); + format_odp_actions(ds, trace.odp_actions.data, trace.odp_actions.size); if (trace.xout.slow) { enum slow_path_reason slow; @@ -4931,6 +5031,7 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, } xlate_out_uninit(&trace.xout); + ofpbuf_uninit(&trace.odp_actions); } /* Store the current ofprotos in 'ofproto_shash'. Returns a sorted list @@ -5516,7 +5617,7 @@ ofproto_dpif_add_internal_flow(struct ofproto_dpif *ofproto, rule = rule_dpif_lookup_in_table(ofproto, ofproto_dpif_get_tables_version(ofproto), TBL_INTERNAL, &ofm.fm.match.flow, - &ofm.fm.match.wc, false); + &ofm.fm.match.wc); if (rule) { *rulep = &rule->up; } else {