X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=b963ff2017822ec9d848c3bb0981f5a56a0db31b;hb=8b8ef592521e32d0e32581bf39c5d2a5cd445977;hp=e76d8fe9a6a05a06e26984a2af29dec752c8ee3f;hpb=1b43cf9e68f4dd0dab4f9d3fa9dd80aeb642c139;p=cascardo%2Fovs.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index e76d8fe9a..b963ff201 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -296,6 +296,10 @@ struct ofproto_dpif { struct ofproto up; struct dpif_backer *backer; + /* Unique identifier for this instantiation of this bridge in this running + * process. */ + struct uuid uuid; + ATOMIC(cls_version_t) tables_version; /* For classifier lookups. */ uint64_t dump_seq; /* Last read of udpif_dump_seq(). */ @@ -303,7 +307,7 @@ struct ofproto_dpif { /* Special OpenFlow rules. */ struct rule_dpif *miss_rule; /* Sends flow table misses to controller. */ struct rule_dpif *no_packet_in_rule; /* Drops flow table misses. */ - struct rule_dpif *drop_frags_rule; /* Used in OFPC_FRAG_DROP mode. */ + struct rule_dpif *drop_frags_rule; /* Used in OFPUTIL_FRAG_DROP mode. */ /* Bridging. */ struct netflow *netflow; @@ -341,9 +345,9 @@ struct ofproto_dpif { uint64_t change_seq; /* Connectivity status changes. */ /* Work queues. */ - struct guarded_list pins; /* Contains "struct ofputil_packet_in"s. */ - struct seq *pins_seq; /* For notifying 'pins' reception. */ - uint64_t pins_seqno; + struct guarded_list ams; /* Contains "struct ofproto_async_msgs"s. */ + struct seq *ams_seq; /* For notifying 'ams' reception. */ + uint64_t ams_seqno; }; /* All existing ofproto_dpif instances, indexed by ->up.name. */ @@ -400,20 +404,19 @@ ofproto_dpif_flow_mod(struct ofproto_dpif *ofproto, ofproto_flow_mod(&ofproto->up, &ofm); } -/* Appends 'pin' to the queue of "packet ins" to be sent to the controller. - * Takes ownership of 'pin' and pin->packet. */ +/* Appends 'am' to the queue of asynchronous messages to be sent to the + * controller. Takes ownership of 'am' and any data it points to. */ void -ofproto_dpif_send_packet_in(struct ofproto_dpif *ofproto, - struct ofproto_packet_in *pin) +ofproto_dpif_send_async_msg(struct ofproto_dpif *ofproto, + struct ofproto_async_msg *am) { - if (!guarded_list_push_back(&ofproto->pins, &pin->list_node, 1024)) { + if (!guarded_list_push_back(&ofproto->ams, &am->list_node, 1024)) { COVERAGE_INC(packet_in_overflow); - free(CONST_CAST(void *, pin->up.packet)); - free(pin); + ofproto_async_msg_free(am); } /* Wakes up main thread for packet-in I/O. */ - seq_change(ofproto->pins_seq); + seq_change(ofproto->ams_seq); } /* The default "table-miss" behaviour for OpenFlow1.3+ is to drop the @@ -561,7 +564,7 @@ type_run(const char *type) udpif_set_threads(backer->udpif, n_handlers, n_revalidators); } - dpif_poll_threads_set(backer->dpif, n_dpdk_rxqs, pmd_cpu_mask); + dpif_poll_threads_set(backer->dpif, pmd_cpu_mask); if (backer->need_revalidate) { struct ofproto_dpif *ofproto; @@ -1236,7 +1239,7 @@ check_masked_set_action(struct dpif_backer *backer) return !error; } -#define CHECK_FEATURE__(NAME, FIELD) \ +#define CHECK_FEATURE__(NAME, SUPPORT, FIELD, VALUE) \ static bool \ check_##NAME(struct dpif_backer *backer) \ { \ @@ -1247,12 +1250,12 @@ check_##NAME(struct dpif_backer *backer) \ struct odp_flow_key_parms odp_parms = { \ .flow = &flow, \ .support = { \ - .NAME = true, \ + .SUPPORT = true, \ }, \ }; \ \ memset(&flow, 0, sizeof flow); \ - flow.FIELD = 1; \ + flow.FIELD = VALUE; \ \ ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); \ odp_flow_key_from_flow(&odp_parms, &key); \ @@ -1267,12 +1270,13 @@ check_##NAME(struct dpif_backer *backer) \ \ return enable; \ } -#define CHECK_FEATURE(FIELD) CHECK_FEATURE__(FIELD, FIELD) +#define CHECK_FEATURE(FIELD) CHECK_FEATURE__(FIELD, FIELD, FIELD, 1) CHECK_FEATURE(ct_state) CHECK_FEATURE(ct_zone) CHECK_FEATURE(ct_mark) -CHECK_FEATURE__(ct_label, ct_label.u64.lo) +CHECK_FEATURE__(ct_label, ct_label, ct_label.u64.lo, 1) +CHECK_FEATURE__(ct_state_nat, ct_state, ct_state, CS_TRACKED|CS_SRC_NAT) #undef CHECK_FEATURE #undef CHECK_FEATURE__ @@ -1293,6 +1297,8 @@ check_support(struct dpif_backer *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); + + backer->support.odp.ct_state_nat = check_ct_state_nat(backer); } static int @@ -1310,6 +1316,7 @@ construct(struct ofproto *ofproto_) return error; } + uuid_generate(&ofproto->uuid); atomic_init(&ofproto->tables_version, CLS_MIN_VERSION); ofproto->netflow = NULL; ofproto->sflow = NULL; @@ -1326,7 +1333,7 @@ construct(struct ofproto *ofproto_) ovs_mutex_init_adaptive(&ofproto->stats_mutex); ovs_mutex_init(&ofproto->vsp_mutex); - guarded_list_init(&ofproto->pins); + guarded_list_init(&ofproto->ams); hmap_init(&ofproto->vlandev_map); hmap_init(&ofproto->realdev_vid_map); @@ -1336,8 +1343,8 @@ construct(struct ofproto *ofproto_) sset_init(&ofproto->port_poll_set); ofproto->port_poll_errno = 0; ofproto->change_seq = 0; - ofproto->pins_seq = seq_create(); - ofproto->pins_seqno = seq_read(ofproto->pins_seq); + ofproto->ams_seq = seq_create(); + ofproto->ams_seqno = seq_read(ofproto->ams_seq); SHASH_FOR_EACH_SAFE (node, next, &init_ofp_ports) { @@ -1403,8 +1410,8 @@ add_internal_flows(struct ofproto_dpif *ofproto) controller = ofpact_put_CONTROLLER(&ofpacts); controller->max_len = UINT16_MAX; controller->controller_id = 0; - controller->reason = OFPR_NO_MATCH; - ofpact_pad(&ofpacts); + controller->reason = OFPR_IMPLICIT_MISS; + ofpact_finish(&ofpacts, &controller->ofpact); error = add_internal_miss_flow(ofproto, id++, &ofpacts, &ofproto->miss_rule); @@ -1442,10 +1449,10 @@ static void destruct(struct ofproto *ofproto_) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); - struct ofproto_packet_in *pin; + struct ofproto_async_msg *am; struct rule_dpif *rule; struct oftable *table; - struct ovs_list pins; + struct ovs_list ams; ofproto->backer->need_revalidate = REV_RECONFIGURE; xlate_txn_start(); @@ -1465,12 +1472,11 @@ destruct(struct ofproto *ofproto_) } ofproto_group_delete_all(&ofproto->up); - guarded_list_pop_all(&ofproto->pins, &pins); - LIST_FOR_EACH_POP (pin, list_node, &pins) { - free(CONST_CAST(void *, pin->up.packet)); - free(pin); + guarded_list_pop_all(&ofproto->ams, &ams); + LIST_FOR_EACH_POP (am, list_node, &ams) { + ofproto_async_msg_free(am); } - guarded_list_destroy(&ofproto->pins); + guarded_list_destroy(&ofproto->ams); recirc_free_ofproto(ofproto, ofproto->up.name); @@ -1493,7 +1499,7 @@ destruct(struct ofproto *ofproto_) ovs_mutex_destroy(&ofproto->stats_mutex); ovs_mutex_destroy(&ofproto->vsp_mutex); - seq_destroy(ofproto->pins_seq); + seq_destroy(ofproto->ams_seq); close_dpif_backer(ofproto->backer); } @@ -1512,23 +1518,22 @@ run(struct ofproto *ofproto_) mcast_snooping_mdb_flush(ofproto->ms); } - /* Always updates the ofproto->pins_seqno to avoid frequent wakeup during + /* Always updates the ofproto->ams_seqno to avoid frequent wakeup during * flow restore. Even though nothing is processed during flow restore, - * all queued 'pins' will be handled immediately when flow restore + * all queued 'ams' will be handled immediately when flow restore * completes. */ - ofproto->pins_seqno = seq_read(ofproto->pins_seq); + ofproto->ams_seqno = seq_read(ofproto->ams_seq); /* Do not perform any periodic activity required by 'ofproto' while * waiting for flow restore to complete. */ if (!ofproto_get_flow_restore_wait()) { - struct ofproto_packet_in *pin; - struct ovs_list pins; + struct ofproto_async_msg *am; + struct ovs_list ams; - guarded_list_pop_all(&ofproto->pins, &pins); - LIST_FOR_EACH_POP (pin, list_node, &pins) { - connmgr_send_packet_in(ofproto->up.connmgr, pin); - free(CONST_CAST(void *, pin->up.packet)); - free(pin); + guarded_list_pop_all(&ofproto->ams, &ams); + LIST_FOR_EACH_POP (am, list_node, &ams) { + connmgr_send_async_msg(ofproto->up.connmgr, am); + ofproto_async_msg_free(am); } } @@ -1639,7 +1644,7 @@ wait(struct ofproto *ofproto_) } seq_wait(udpif_dump_seq(ofproto->backer->udpif), ofproto->dump_seq); - seq_wait(ofproto->pins_seq, ofproto->pins_seqno); + seq_wait(ofproto->ams_seq, ofproto->ams_seqno); } static void @@ -1798,7 +1803,7 @@ port_construct(struct ofport *port_) } static void -port_destruct(struct ofport *port_) +port_destruct(struct ofport *port_, bool del) { struct ofport_dpif *port = ofport_dpif_cast(port_); struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto); @@ -1813,7 +1818,7 @@ port_destruct(struct ofport *port_) dp_port_name = netdev_vport_get_dpif_port(port->up.netdev, namebuf, sizeof namebuf); - if (dpif_port_exists(ofproto->backer->dpif, dp_port_name)) { + if (del && dpif_port_exists(ofproto->backer->dpif, dp_port_name)) { /* The underlying device is still there, so delete it. This * happens when the ofproto is being destroyed, since the caller * assumes that removal of attached ports will happen as part of @@ -3900,13 +3905,13 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, /* We always unwildcard nw_frag (for IP), so they * need not be unwildcarded here. */ if (flow->nw_frag & FLOW_NW_FRAG_ANY - && ofproto->up.frag_handling != OFPC_FRAG_NX_MATCH) { - if (ofproto->up.frag_handling == OFPC_FRAG_NORMAL) { + && ofproto->up.frag_handling != OFPUTIL_FRAG_NX_MATCH) { + if (ofproto->up.frag_handling == OFPUTIL_FRAG_NORMAL) { /* We must pretend that transport ports are unavailable. */ flow->tp_src = htons(0); flow->tp_dst = htons(0); } else { - /* Must be OFPC_FRAG_DROP (we don't have OFPC_FRAG_REASM). + /* Must be OFPUTIL_FRAG_DROP (we don't have OFPUTIL_FRAG_REASM). * Use the drop_frags_rule (which cannot disappear). */ rule = ofproto->drop_frags_rule; if (stats) { @@ -4023,7 +4028,7 @@ check_mask(struct ofproto_dpif *ofproto, const struct miniflow *flow) support = &ofproto_dpif_get_support(ofproto)->odp; ct_state = MINIFLOW_GET_U16(flow, ct_state); if (support->ct_state && support->ct_zone && support->ct_mark - && support->ct_label) { + && support->ct_label && support->ct_state_nat) { return ct_state & CS_UNSUPPORTED_MASK ? OFPERR_OFPBMC_BAD_MASK : 0; } @@ -4033,6 +4038,7 @@ check_mask(struct ofproto_dpif *ofproto, const struct miniflow *flow) if ((ct_state && !support->ct_state) || (ct_state & CS_UNSUPPORTED_MASK) + || ((ct_state & (CS_SRC_NAT | CS_DST_NAT)) && !support->ct_state_nat) || (ct_zone && !support->ct_zone) || (ct_mark && !support->ct_mark) || (!ovs_u128_is_zero(&ct_label) && !support->ct_label)) { @@ -4070,6 +4076,12 @@ check_actions(const struct ofproto_dpif *ofproto, OFPACT_FOR_EACH(a, ct->actions, ofpact_ct_get_action_len(ct)) { const struct mf_field *dst = ofpact_get_mf_dst(a); + if (a->type == OFPACT_NAT && !support->ct_state_nat) { + /* The backer doesn't seem to support the NAT bits in + * 'ct_state': assume that it doesn't support the NAT + * action. */ + return OFPERR_OFPBAC_BAD_TYPE; + } if (dst && ((dst->id == MFF_CT_MARK && !support->ct_mark) || (dst->id == MFF_CT_LABEL && !support->ct_label))) { return OFPERR_OFPBAC_BAD_SET_ARGUMENT; @@ -4391,10 +4403,10 @@ get_datapath_version(const struct ofproto *ofproto_) static bool set_frag_handling(struct ofproto *ofproto_, - enum ofp_config_flags frag_handling) + enum ofputil_frag_handling frag_handling) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); - if (frag_handling != OFPC_FRAG_REASM) { + if (frag_handling != OFPUTIL_FRAG_REASM) { ofproto->backer->need_revalidate = REV_RECONFIGURE; return true; } else { @@ -4413,6 +4425,39 @@ packet_out(struct ofproto *ofproto_, struct dp_packet *packet, ofpacts_len, packet); return 0; } + +static enum ofperr +nxt_resume(struct ofproto *ofproto_, + const struct ofputil_packet_in_private *pin) +{ + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); + + /* Translate pin into datapath actions. */ + uint64_t odp_actions_stub[1024 / 8]; + struct ofpbuf odp_actions = OFPBUF_STUB_INITIALIZER(odp_actions_stub); + enum slow_path_reason slow; + enum ofperr error = xlate_resume(ofproto, pin, &odp_actions, &slow); + + /* Steal 'pin->packet' and put it into a dp_packet. */ + struct dp_packet packet; + dp_packet_init(&packet, pin->public.packet_len); + dp_packet_put(&packet, pin->public.packet, pin->public.packet_len); + + /* Execute the datapath actions on the packet. */ + struct dpif_execute execute = { + .actions = odp_actions.data, + .actions_len = odp_actions.size, + .needs_help = (slow & SLOW_ACTION) != 0, + .packet = &packet, + }; + dpif_execute(ofproto->backer->dpif, &execute); + + /* Clean up. */ + ofpbuf_uninit(&odp_actions); + dp_packet_uninit(&packet); + + return error; +} /* NetFlow. */ @@ -5318,6 +5363,8 @@ disable_tnl_push_pop(struct unixctl_conn *conn OVS_UNUSED, int argc OVS_UNUSED, ofproto_use_tnl_push_pop = true; unixctl_command_reply(conn, "Tunnel push-pop on"); ofproto_revalidate_all_backers(); + } else { + unixctl_command_reply_error(conn, "Invalid argument"); } } @@ -5648,22 +5695,17 @@ ofproto_dpif_add_internal_flow(struct ofproto_dpif *ofproto, struct rule_dpif *rule; int error; - ofm.fm.match = *match; - ofm.fm.priority = priority; - ofm.fm.new_cookie = htonll(0); - ofm.fm.cookie = htonll(0); - ofm.fm.cookie_mask = htonll(0); - ofm.fm.modify_cookie = false; - ofm.fm.table_id = TBL_INTERNAL; - ofm.fm.command = OFPFC_ADD; - ofm.fm.idle_timeout = idle_timeout; - ofm.fm.hard_timeout = 0; - ofm.fm.importance = 0; - ofm.fm.buffer_id = 0; - ofm.fm.out_port = 0; - ofm.fm.flags = OFPUTIL_FF_HIDDEN_FIELDS | OFPUTIL_FF_NO_READONLY; - ofm.fm.ofpacts = ofpacts->data; - ofm.fm.ofpacts_len = ofpacts->size; + ofm.fm = (struct ofputil_flow_mod) { + .match = *match, + .priority = priority, + .table_id = TBL_INTERNAL, + .command = OFPFC_ADD, + .idle_timeout = idle_timeout, + .flags = OFPUTIL_FF_HIDDEN_FIELDS | OFPUTIL_FF_NO_READONLY, + .ofpacts = ofpacts->data, + .ofpacts_len = ofpacts->size, + .delete_reason = OVS_OFPRR_NONE, + }; error = ofproto_flow_mod(&ofproto->up, &ofm); if (error) { @@ -5692,15 +5734,13 @@ ofproto_dpif_delete_internal_flow(struct ofproto_dpif *ofproto, struct ofproto_flow_mod ofm; int error; - ofm.fm.match = *match; - ofm.fm.priority = priority; - ofm.fm.new_cookie = htonll(0); - ofm.fm.cookie = htonll(0); - ofm.fm.cookie_mask = htonll(0); - ofm.fm.modify_cookie = false; - ofm.fm.table_id = TBL_INTERNAL; - ofm.fm.flags = OFPUTIL_FF_HIDDEN_FIELDS | OFPUTIL_FF_NO_READONLY; - ofm.fm.command = OFPFC_DELETE_STRICT; + ofm.fm = (struct ofputil_flow_mod) { + .match = *match, + .priority = priority, + .table_id = TBL_INTERNAL, + .flags = OFPUTIL_FF_HIDDEN_FIELDS | OFPUTIL_FF_NO_READONLY, + .command = OFPFC_DELETE_STRICT, + }; error = ofproto_flow_mod(&ofproto->up, &ofm); if (error) { @@ -5712,6 +5752,12 @@ ofproto_dpif_delete_internal_flow(struct ofproto_dpif *ofproto, return 0; } +const struct uuid * +ofproto_dpif_get_uuid(const struct ofproto_dpif *ofproto) +{ + return &ofproto->uuid; +} + const struct ofproto_class ofproto_dpif_class = { init, enumerate_types, @@ -5759,6 +5805,7 @@ const struct ofproto_class ofproto_dpif_class = { rule_execute, set_frag_handling, packet_out, + nxt_resume, set_netflow, get_netflow_ids, set_sflow,