#include "ofproto-dpif-governor.h"
#include "ofproto-dpif-ipfix.h"
#include "ofproto-dpif-mirror.h"
+#include "ofproto-dpif-monitor.h"
#include "ofproto-dpif-sflow.h"
#include "ofproto-dpif-upcall.h"
#include "ofproto-dpif-xlate.h"
VLOG_DEFINE_THIS_MODULE(ofproto_dpif);
COVERAGE_DEFINE(ofproto_dpif_expired);
-COVERAGE_DEFINE(facet_changed_rule);
COVERAGE_DEFINE(facet_revalidate);
COVERAGE_DEFINE(facet_unexpected);
-COVERAGE_DEFINE(facet_suppress);
+COVERAGE_DEFINE(facet_create);
+COVERAGE_DEFINE(facet_remove);
+COVERAGE_DEFINE(subfacet_create);
+COVERAGE_DEFINE(subfacet_destroy);
COVERAGE_DEFINE(subfacet_install_fail);
COVERAGE_DEFINE(packet_in_overflow);
-COVERAGE_DEFINE(flow_mod_overflow);
/* Number of implemented OpenFlow tables. */
enum { N_TABLES = 255 };
}
static void port_run(struct ofport_dpif *);
-static void port_run_fast(struct ofport_dpif *);
-static void port_wait(struct ofport_dpif *);
static int set_bfd(struct ofport *, const struct smap *);
static int set_cfm(struct ofport *, const struct cfm_settings *);
static void ofport_update_peer(struct ofport_dpif *);
unsigned avg_n_subfacet; /* Average number of flows. */
long long int avg_subfacet_life; /* Average life span of subfacets. */
- /* The average number of subfacets... */
- struct avg_subfacet_rates hourly; /* ...over the last hour. */
- struct avg_subfacet_rates daily; /* ...over the last day. */
- struct avg_subfacet_rates lifetime; /* ...over the switch lifetime. */
- long long int last_minute; /* Last time 'hourly' was updated. */
-
- /* Number of subfacets added or deleted since 'last_minute'. */
- unsigned subfacet_add_count;
- unsigned subfacet_del_count;
-
- /* Number of subfacets added or deleted from 'created' to 'last_minute.' */
- unsigned long long int total_subfacet_add_count;
- unsigned long long int total_subfacet_del_count;
-
/* Number of upcall handling threads. */
unsigned int n_handler_threads;
};
static struct shash all_dpif_backers = SHASH_INITIALIZER(&all_dpif_backers);
static void drop_key_clear(struct dpif_backer *);
-static void update_moving_averages(struct dpif_backer *backer);
struct ofproto_dpif {
struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */
struct classifier facets; /* Contains 'struct facet's. */
long long int consistency_rl;
- struct netdev_stats stats; /* To account packets generated and consumed in
- * userspace. */
+ struct ovs_mutex stats_mutex;
+ struct netdev_stats stats OVS_GUARDED; /* To account packets generated and
+ * consumed in userspace. */
/* Spanning tree. */
struct stp *stp;
/* NetFlow. */
static void send_netflow_active_timeouts(struct ofproto_dpif *);
-/* Utilities. */
-static int send_packet(const struct ofport_dpif *, struct ofpbuf *packet);
-
/* Global variables. */
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
backer->max_n_subfacet = 0;
backer->created = time_msec();
- backer->last_minute = backer->created;
- memset(&backer->hourly, 0, sizeof backer->hourly);
- memset(&backer->daily, 0, sizeof backer->daily);
- memset(&backer->lifetime, 0, sizeof backer->lifetime);
- backer->subfacet_add_count = 0;
- backer->subfacet_del_count = 0;
- backer->total_subfacet_add_count = 0;
- backer->total_subfacet_del_count = 0;
backer->avg_n_subfacet = 0;
backer->avg_subfacet_life = 0;
ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
ofproto->mbridge = mbridge_create();
ofproto->has_bonded_bundles = false;
+ ovs_mutex_init(&ofproto->stats_mutex);
ovs_mutex_init(&ofproto->vsp_mutex);
classifier_init(&ofproto->facets);
sset_destroy(&ofproto->ghost_ports);
sset_destroy(&ofproto->port_poll_set);
+ ovs_mutex_destroy(&ofproto->stats_mutex);
ovs_mutex_destroy(&ofproto->vsp_mutex);
close_dpif_backer(ofproto->backer);
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct ofputil_packet_in *pin, *next_pin;
- struct ofport_dpif *ofport;
struct list pins;
/* Do not perform any periodic activity required by 'ofproto' while
free(pin);
}
- HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
- port_run_fast(ofport);
- }
-
+ ofproto_dpif_monitor_run_fast();
return 0;
}
dpif_ipfix_run(ofproto->ipfix);
}
+ ofproto_dpif_monitor_run_fast();
+ ofproto_dpif_monitor_run();
+
HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
port_run(ofport);
}
wait(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct ofport_dpif *ofport;
struct ofbundle *bundle;
if (ofproto_get_flow_restore_wait()) {
if (ofproto->ipfix) {
dpif_ipfix_wait(ofproto->ipfix);
}
- HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
- port_wait(ofport);
- }
+ ofproto_dpif_monitor_wait();
HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
bundle_wait(bundle);
}
bfd_set_netdev(port->bfd, port->up.netdev);
}
+ ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm,
+ port->up.pp.hw_addr);
+
if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
port->odp_port)) {
ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
{
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
- int error;
+ int error = 0;
- if (!s) {
- error = 0;
- } else {
+ if (s) {
if (!ofport->cfm) {
struct ofproto_dpif *ofproto;
}
if (cfm_configure(ofport->cfm, s)) {
- return 0;
+ error = 0;
+ goto out;
}
error = EINVAL;
}
cfm_unref(ofport->cfm);
ofport->cfm = NULL;
+out:
+ ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
+ ofport->up.pp.hw_addr);
return error;
}
if (ofport->bfd != old) {
ofproto->backer->need_revalidate = REV_RECONFIGURE;
}
-
+ ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
+ ofport->up.pp.hw_addr);
return 0;
}
VLOG_WARN_RL(&rl, "%s: cannot send BPDU on port %d "
"with unknown MAC", ofproto->up.name, port_num);
} else {
- send_packet(ofport, pkt);
+ ofproto_dpif_send_packet(ofport, pkt);
}
}
ofpbuf_delete(pkt);
pdu_size);
memcpy(packet_pdu, pdu, pdu_size);
- send_packet(port, &packet);
+ ofproto_dpif_send_packet(port, &packet);
ofpbuf_uninit(&packet);
} else {
VLOG_ERR_RL(&rl, "port %s: cannot obtain Ethernet address of iface "
LIST_FOR_EACH (learning_packet, list_node, &packets) {
int ret;
- ret = send_packet(learning_packet->private_p, learning_packet);
+ ret = ofproto_dpif_send_packet(learning_packet->private_p, learning_packet);
if (ret) {
error = ret;
n_errors++;
free(peer_name);
}
-static void
-port_run_fast(struct ofport_dpif *ofport)
-{
- if (ofport->cfm && cfm_should_send_ccm(ofport->cfm)) {
- struct ofpbuf packet;
-
- ofpbuf_init(&packet, 0);
- cfm_compose_ccm(ofport->cfm, &packet, ofport->up.pp.hw_addr);
- send_packet(ofport, &packet);
- ofpbuf_uninit(&packet);
- }
-
- if (ofport->bfd && bfd_should_send_packet(ofport->bfd)) {
- struct ofpbuf packet;
-
- ofpbuf_init(&packet, 0);
- bfd_put_packet(ofport->bfd, &packet, ofport->up.pp.hw_addr);
- send_packet(ofport, &packet);
- ofpbuf_uninit(&packet);
- }
-}
-
static void
port_run(struct ofport_dpif *ofport)
{
ofport->carrier_seq = carrier_seq;
- port_run_fast(ofport);
-
if (ofport->cfm) {
int cfm_opup = cfm_get_opup(ofport->cfm);
- cfm_run(ofport->cfm);
cfm_enable = !cfm_get_fault(ofport->cfm);
if (cfm_opup >= 0) {
}
if (ofport->bfd) {
- bfd_run(ofport->bfd);
bfd_enable = bfd_forwarding(ofport->bfd);
}
ofport->may_enable = enable;
}
-static void
-port_wait(struct ofport_dpif *ofport)
-{
- if (ofport->cfm) {
- cfm_wait(ofport->cfm);
- }
-
- if (ofport->bfd) {
- bfd_wait(ofport->bfd);
- }
-}
-
static int
port_query_by_name(const struct ofproto *ofproto_, const char *devname,
struct ofproto_port *ofproto_port)
if (!error && ofport_->ofp_port == OFPP_LOCAL) {
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+ ovs_mutex_lock(&ofproto->stats_mutex);
/* ofproto->stats.tx_packets represents packets that we created
* internally and sent to some port (e.g. packets sent with
- * send_packet()). Account for them as if they had come from
- * OFPP_LOCAL and got forwarded. */
+ * ofproto_dpif_send_packet()). Account for them as if they had
+ * come from OFPP_LOCAL and got forwarded. */
if (stats->rx_packets != UINT64_MAX) {
stats->rx_packets += ofproto->stats.tx_packets;
if (stats->tx_bytes != UINT64_MAX) {
stats->tx_bytes += ofproto->stats.rx_bytes;
}
+ ovs_mutex_unlock(&ofproto->stats_mutex);
}
return error;
hash = flow_hash_in_wildcards(&miss->flow, &miss->xout.wc, 0);
return governor_should_install_flow(backer->governor, hash,
- list_size(&miss->upcalls));
+ miss->stats.n_packets);
}
/* Handles 'miss', which matches 'facet'. May add any required datapath
{
struct facet *facet;
- miss->ofproto->n_missed += list_size(&miss->upcalls);
+ miss->ofproto->n_missed += miss->stats.n_packets;
facet = facet_lookup_valid(miss->ofproto, &miss->flow);
if (!facet) {
}
}
-static void
-handle_sflow_upcall(struct dpif_backer *backer,
- const struct dpif_upcall *upcall)
-{
- struct ofproto_dpif *ofproto;
- union user_action_cookie cookie;
- struct flow flow;
- odp_port_t odp_in_port;
-
- if (xlate_receive(backer, upcall->packet, upcall->key, upcall->key_len,
- &flow, NULL, &ofproto, &odp_in_port)
- || !ofproto->sflow) {
- return;
- }
-
- memset(&cookie, 0, sizeof cookie);
- memcpy(&cookie, nl_attr_get(upcall->userdata), sizeof cookie.sflow);
- dpif_sflow_received(ofproto->sflow, upcall->packet, &flow,
- odp_in_port, &cookie);
-}
-
-static void
-handle_flow_sample_upcall(struct dpif_backer *backer,
- const struct dpif_upcall *upcall)
-{
- struct ofproto_dpif *ofproto;
- union user_action_cookie cookie;
- struct flow flow;
-
- if (xlate_receive(backer, upcall->packet, upcall->key, upcall->key_len,
- &flow, NULL, &ofproto, NULL)
- || !ofproto->ipfix) {
- return;
- }
-
- memset(&cookie, 0, sizeof cookie);
- memcpy(&cookie, nl_attr_get(upcall->userdata), sizeof cookie.flow_sample);
-
- /* The flow reflects exactly the contents of the packet. Sample
- * the packet using it. */
- dpif_ipfix_flow_sample(ofproto->ipfix, upcall->packet, &flow,
- cookie.flow_sample.collector_set_id,
- cookie.flow_sample.probability,
- cookie.flow_sample.obs_domain_id,
- cookie.flow_sample.obs_point_id);
-}
-
-static void
-handle_ipfix_upcall(struct dpif_backer *backer,
- const struct dpif_upcall *upcall)
-{
- struct ofproto_dpif *ofproto;
- struct flow flow;
-
- if (xlate_receive(backer, upcall->packet, upcall->key, upcall->key_len,
- &flow, NULL, &ofproto, NULL)
- || !ofproto->ipfix) {
- return;
- }
-
- /* The flow reflects exactly the contents of the packet. Sample
- * the packet using it. */
- dpif_ipfix_bridge_sample(ofproto->ipfix, upcall->packet, &flow);
-}
-
static void
handle_upcalls(struct dpif_backer *backer)
{
struct flow_miss_batch *fmb;
int n_processed;
- for (n_processed = 0; n_processed < FLOW_MISS_MAX_BATCH; n_processed++) {
- struct upcall *upcall = upcall_next(backer->udpif);
-
- if (!upcall) {
- break;
- }
-
- switch (upcall->type) {
- case SFLOW_UPCALL:
- handle_sflow_upcall(backer, &upcall->dpif_upcall);
- break;
-
- case FLOW_SAMPLE_UPCALL:
- handle_flow_sample_upcall(backer, &upcall->dpif_upcall);
- break;
-
- case IPFIX_UPCALL:
- handle_ipfix_upcall(backer, &upcall->dpif_upcall);
- break;
-
- case BAD_UPCALL:
- break;
-
- case MISS_UPCALL:
- NOT_REACHED();
- }
-
- upcall_destroy(upcall);
- }
-
for (n_processed = 0; n_processed < FLOW_MISS_MAX_BATCH; n_processed++) {
struct drop_key *drop_key = drop_key_next(backer->udpif);
if (!drop_key) {
run_fast_rl();
}
dpif_flow_dump_done(&dump);
-
- update_moving_averages(backer);
}
/* Calculates and returns the number of milliseconds of idle time after which
struct facet *facet;
struct match match;
+ COVERAGE_INC(facet_create);
facet = xzalloc(sizeof *facet);
facet->ofproto = miss->ofproto;
facet->used = miss->stats.used;
}
}
-/* Executes, within 'ofproto', the 'n_actions' actions in 'actions' on
- * 'packet', which arrived on 'in_port'. */
-static bool
-execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow,
- const struct nlattr *odp_actions, size_t actions_len,
- struct ofpbuf *packet)
+/* 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 ofpbuf *packet)
{
struct odputil_keybuf keybuf;
+ struct dpif_flow_stats stats;
+ struct xlate_out xout;
+ struct xlate_in xin;
+ ofp_port_t in_port;
struct ofpbuf key;
int error;
+ ovs_assert((rule != NULL) != (ofpacts != NULL));
+
+ dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
+ if (rule) {
+ rule_dpif_credit_stats(rule, &stats);
+ }
+
+ xlate_in_init(&xin, ofproto, flow, rule, stats.tcp_flags, packet);
+ xin.ofpacts = ofpacts;
+ xin.ofpacts_len = ofpacts_len;
+ xin.resubmit_stats = &stats;
+ xlate_actions(&xin, &xout);
+
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, flow,
- ofp_port_to_odp_port(ofproto, flow->in_port.ofp_port));
+ in_port = flow->in_port.ofp_port;
+ if (in_port == OFPP_NONE) {
+ in_port = OFPP_LOCAL;
+ }
+ odp_flow_key_from_flow(&key, flow, ofp_port_to_odp_port(ofproto, in_port));
error = dpif_execute(ofproto->backer->dpif, key.data, key.size,
- odp_actions, actions_len, packet);
- return !error;
+ xout.odp_actions.data, xout.odp_actions.size, packet,
+ (xout.slow & SLOW_ACTION) != 0);
+ xlate_out_uninit(&xout);
+
+ return error;
}
/* Remove 'facet' from its ofproto and free up the associated memory:
{
struct subfacet *subfacet, *next_subfacet;
+ COVERAGE_INC(facet_remove);
ovs_assert(!list_is_empty(&facet->subfacets));
/* First uninstall all of the subfacets to get final statistics. */
struct xlate_out xout;
struct xlate_in xin;
-
- struct rule_dpif *rule;
bool ok;
/* Check the datapath actions for consistency. */
- rule_dpif_lookup(facet->ofproto, &facet->flow, NULL, &rule);
- xlate_in_init(&xin, facet->ofproto, &facet->flow, rule, 0, NULL);
+ xlate_in_init(&xin, facet->ofproto, &facet->flow, NULL, 0, NULL);
xlate_actions(&xin, &xout);
- rule_dpif_unref(rule);
ok = ofpbuf_equal(&facet->xout.odp_actions, &xout.odp_actions)
&& facet->xout.slow == xout.slow;
struct dpif_flow_stats *stats, bool may_learn)
{
struct ofport_dpif *in_port;
- struct rule_dpif *rule;
struct xlate_in xin;
in_port = get_ofp_port(ofproto, flow->in_port.ofp_port);
netdev_vport_inc_rx(in_port->up.netdev, stats);
}
- rule_dpif_lookup(ofproto, flow, NULL, &rule);
- rule_dpif_credit_stats(rule, stats);
- xlate_in_init(&xin, ofproto, flow, rule, stats->tcp_flags, NULL);
+ xlate_in_init(&xin, ofproto, flow, NULL, stats->tcp_flags, NULL);
xin.resubmit_stats = stats;
xin.may_learn = may_learn;
xlate_actions_for_side_effects(&xin);
- rule_dpif_unref(rule);
}
static void
subfacet = xmalloc(sizeof *subfacet);
}
+ COVERAGE_INC(subfacet_create);
hmap_insert(&backer->subfacets, &subfacet->hmap_node, key_hash);
list_push_back(&facet->subfacets, &subfacet->list_node);
subfacet->facet = facet;
subfacet->path = SF_NOT_INSTALLED;
subfacet->backer = backer;
- backer->subfacet_add_count++;
return subfacet;
}
subfacet_destroy__(struct subfacet *subfacet)
{
struct facet *facet = subfacet->facet;
- struct ofproto_dpif *ofproto = facet->ofproto;
-
- /* Update ofproto stats before uninstall the subfacet. */
- ofproto->backer->subfacet_del_count++;
+ COVERAGE_INC(subfacet_destroy);
subfacet_uninstall(subfacet);
hmap_remove(&subfacet->backer->subfacets, &subfacet->hmap_node);
list_remove(&subfacet->list_node);
struct ofpbuf *packet)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
- struct dpif_flow_stats stats;
- struct xlate_out xout;
- struct xlate_in xin;
-
- dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
- rule_dpif_credit_stats(rule, &stats);
- xlate_in_init(&xin, ofproto, flow, rule, stats.tcp_flags, packet);
- xin.resubmit_stats = &stats;
- xlate_actions(&xin, &xout);
-
- execute_odp_actions(ofproto, flow, xout.odp_actions.data,
- xout.odp_actions.size, packet);
-
- xlate_out_uninit(&xout);
+ ofproto_dpif_execute_actions(ofproto, flow, rule, NULL, 0, packet);
}
static enum ofperr
/* Sends 'packet' out 'ofport'.
* May modify 'packet'.
* Returns 0 if successful, otherwise a positive errno value. */
-static int
-send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
+int
+ofproto_dpif_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
- uint64_t odp_actions_stub[1024 / 8];
- struct ofpbuf key, odp_actions;
- struct dpif_flow_stats stats;
- struct odputil_keybuf keybuf;
- struct ofpact_output output;
- struct xlate_out xout;
- struct xlate_in xin;
- struct flow flow;
- union flow_in_port in_port_;
int error;
- ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub);
- ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-
- /* Use OFPP_NONE as the in_port to avoid special packet processing. */
- in_port_.ofp_port = OFPP_NONE;
- flow_extract(packet, 0, 0, NULL, &in_port_, &flow);
- odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(ofproto,
- OFPP_LOCAL));
- dpif_flow_stats_extract(&flow, packet, time_msec(), &stats);
-
- ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output);
- output.port = ofport->up.ofp_port;
- output.max_len = 0;
-
- xlate_in_init(&xin, ofproto, &flow, NULL, 0, packet);
- xin.ofpacts_len = sizeof output;
- xin.ofpacts = &output.ofpact;
- xin.resubmit_stats = &stats;
- xlate_actions(&xin, &xout);
-
- error = dpif_execute(ofproto->backer->dpif,
- key.data, key.size,
- xout.odp_actions.data, xout.odp_actions.size,
- packet);
- xlate_out_uninit(&xout);
-
- if (error) {
- VLOG_WARN_RL(&rl, "%s: failed to send packet on port %s (%s)",
- ofproto->up.name, netdev_get_name(ofport->up.netdev),
- ovs_strerror(error));
- }
+ error = xlate_send_packet(ofport, packet);
+ ovs_mutex_lock(&ofproto->stats_mutex);
ofproto->stats.tx_packets++;
ofproto->stats.tx_bytes += packet->size;
+ ovs_mutex_unlock(&ofproto->stats_mutex);
return error;
}
const struct ofpact *ofpacts, size_t ofpacts_len)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct odputil_keybuf keybuf;
- struct dpif_flow_stats stats;
- struct xlate_out xout;
- struct xlate_in xin;
- struct ofpbuf key;
-
-
- ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
- odp_flow_key_from_flow(&key, flow,
- ofp_port_to_odp_port(ofproto,
- flow->in_port.ofp_port));
-
- dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
-
- xlate_in_init(&xin, ofproto, flow, NULL, stats.tcp_flags, packet);
- xin.resubmit_stats = &stats;
- xin.ofpacts_len = ofpacts_len;
- xin.ofpacts = ofpacts;
-
- xlate_actions(&xin, &xout);
- dpif_execute(ofproto->backer->dpif, key.data, key.size,
- xout.odp_actions.data, xout.odp_actions.size, packet);
- xlate_out_uninit(&xout);
+ ofproto_dpif_execute_actions(ofproto, flow, NULL, ofpacts,
+ ofpacts_len, packet);
return 0;
}
\f
ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
void *aux OVS_UNUSED)
{
- const struct dpif_backer *backer;
+ const struct dpif_backer *backer = NULL;
struct ofproto_dpif *ofproto;
struct ofpbuf odp_key, odp_mask;
struct ofpbuf *packet;
struct ds result;
struct flow flow;
+ struct simap port_names;
char *s;
packet = NULL;
ds_init(&result);
ofpbuf_init(&odp_key, 0);
ofpbuf_init(&odp_mask, 0);
+ simap_init(&port_names);
/* Handle "-generate" or a hex string as the last argument. */
if (!strcmp(argv[argc - 1], "-generate")) {
}
}
+ /* odp_flow can have its in_port specified as a name instead of port no.
+ * We do not yet know whether a given flow is a odp_flow or a br_flow.
+ * But, to know whether a flow is odp_flow through odp_flow_from_string(),
+ * we need to create a simap of name to port no. */
+ if (argc == 3) {
+ const char *dp_type;
+ if (!strncmp(argv[1], "ovs-", 4)) {
+ dp_type = argv[1] + 4;
+ } else {
+ dp_type = argv[1];
+ }
+ backer = shash_find_data(&all_dpif_backers, dp_type);
+ } else {
+ struct shash_node *node;
+ if (shash_count(&all_dpif_backers) == 1) {
+ node = shash_first(&all_dpif_backers);
+ backer = node->data;
+ }
+ }
+ if (backer && backer->dpif) {
+ struct dpif_port dpif_port;
+ struct dpif_port_dump port_dump;
+ DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, backer->dpif) {
+ simap_put(&port_names, dpif_port.name,
+ odp_to_u32(dpif_port.port_no));
+ }
+ }
+
/* Parse the flow and determine whether a datapath or
* bridge is specified. If function odp_flow_key_from_string()
* returns 0, the flow is a odp_flow. If function
* parse_ofp_exact_flow() returns 0, the flow is a br_flow. */
- if (!odp_flow_from_string(argv[argc - 1], NULL, &odp_key, &odp_mask)) {
- /* If the odp_flow is the second argument,
- * the datapath name is the first argument. */
- if (argc == 3) {
- const char *dp_type;
- if (!strncmp(argv[1], "ovs-", 4)) {
- dp_type = argv[1] + 4;
- } else {
- dp_type = argv[1];
- }
- backer = shash_find_data(&all_dpif_backers, dp_type);
- if (!backer) {
- unixctl_command_reply_error(conn, "Cannot find datapath "
- "of this name");
- goto exit;
- }
- } else {
- /* No datapath name specified, so there should be only one
- * datapath. */
- struct shash_node *node;
- if (shash_count(&all_dpif_backers) != 1) {
- unixctl_command_reply_error(conn, "Must specify datapath "
- "name, there is more than one type of datapath");
- goto exit;
- }
- node = shash_first(&all_dpif_backers);
- backer = node->data;
+ if (!odp_flow_from_string(argv[argc - 1], &port_names, &odp_key, &odp_mask)) {
+ if (!backer) {
+ unixctl_command_reply_error(conn, "Cannot find the datapath");
+ goto exit;
}
if (xlate_receive(backer, NULL, odp_key.data, odp_key.size, &flow,
ofpbuf_delete(packet);
ofpbuf_uninit(&odp_key);
ofpbuf_uninit(&odp_mask);
+ simap_destroy(&port_names);
}
static void
trace.xout.odp_actions.size);
if (trace.xout.slow) {
+ enum slow_path_reason slow;
+
ds_put_cstr(ds, "\nThis flow is handled by the userspace "
"slow path because it:");
- switch (trace.xout.slow) {
- case SLOW_CFM:
- ds_put_cstr(ds, "\n\t- Consists of CFM packets.");
- break;
- case SLOW_LACP:
- ds_put_cstr(ds, "\n\t- Consists of LACP packets.");
- break;
- case SLOW_STP:
- ds_put_cstr(ds, "\n\t- Consists of STP packets.");
- break;
- case SLOW_BFD:
- ds_put_cstr(ds, "\n\t- Consists of BFD packets.");
- break;
- case SLOW_CONTROLLER:
- ds_put_cstr(ds, "\n\t- Sends \"packet-in\" messages "
- "to the OpenFlow controller.");
- break;
- case __SLOW_MAX:
- NOT_REACHED();
+
+ slow = trace.xout.slow;
+ while (slow) {
+ enum slow_path_reason bit = rightmost_1bit(slow);
+
+ ds_put_format(ds, "\n\t- %s.",
+ slow_path_reason_to_explanation(bit));
+
+ slow &= ~bit;
}
}
ds_destroy(&ds);
}
-static void
-show_dp_rates(struct ds *ds, const char *heading,
- const struct avg_subfacet_rates *rates)
-{
- ds_put_format(ds, "%s add rate: %5.3f/min, del rate: %5.3f/min\n",
- heading, rates->add_rate, rates->del_rate);
-}
-
static void
dpif_show_backer(const struct dpif_backer *backer, struct ds *ds)
{
struct ofproto_dpif *ofproto;
struct shash ofproto_shash;
uint64_t n_hit, n_missed;
- long long int minutes;
size_t i;
n_hit = n_missed = 0;
backer->avg_n_subfacet, backer->max_n_subfacet,
backer->avg_subfacet_life);
- minutes = (time_msec() - backer->created) / (1000 * 60);
- if (minutes >= 60) {
- show_dp_rates(ds, "\thourly avg:", &backer->hourly);
- }
- if (minutes >= 60 * 24) {
- show_dp_rates(ds, "\tdaily avg:", &backer->daily);
- }
- show_dp_rates(ds, "\toverall avg:", &backer->lifetime);
-
shash_init(&ofproto_shash);
ofprotos = get_ofprotos(&ofproto_shash);
for (i = 0; i < shash_count(&ofproto_shash); i++) {
}
odp_flow_format(subfacet->key, subfacet->key_len,
- mask.data, mask.size, &ds, false);
+ mask.data, mask.size, NULL, &ds, false);
ds_put_format(&ds, ", packets:%"PRIu64", bytes:%"PRIu64", used:",
subfacet->dp_packet_count, subfacet->dp_byte_count);
}
}
-/* Compute exponentially weighted moving average, adding 'new' as the newest,
- * most heavily weighted element. 'base' designates the rate of decay: after
- * 'base' further updates, 'new''s weight in the EWMA decays to about 1/e
- * (about .37). */
-static void
-exp_mavg(double *avg, int base, double new)
-{
- *avg = (*avg * (base - 1) + new) / base;
-}
-
-static void
-update_moving_averages(struct dpif_backer *backer)
-{
- const int min_ms = 60 * 1000; /* milliseconds in one minute. */
- long long int minutes = (time_msec() - backer->created) / min_ms;
-
- if (minutes > 0) {
- backer->lifetime.add_rate = (double) backer->total_subfacet_add_count
- / minutes;
- backer->lifetime.del_rate = (double) backer->total_subfacet_del_count
- / minutes;
- } else {
- backer->lifetime.add_rate = 0.0;
- backer->lifetime.del_rate = 0.0;
- }
-
- /* Update hourly averages on the minute boundaries. */
- if (time_msec() - backer->last_minute >= min_ms) {
- exp_mavg(&backer->hourly.add_rate, 60, backer->subfacet_add_count);
- exp_mavg(&backer->hourly.del_rate, 60, backer->subfacet_del_count);
-
- /* Update daily averages on the hour boundaries. */
- if ((backer->last_minute - backer->created) / min_ms % 60 == 59) {
- exp_mavg(&backer->daily.add_rate, 24, backer->hourly.add_rate);
- exp_mavg(&backer->daily.del_rate, 24, backer->hourly.del_rate);
- }
-
- backer->total_subfacet_add_count += backer->subfacet_add_count;
- backer->total_subfacet_del_count += backer->subfacet_del_count;
- backer->subfacet_add_count = 0;
- backer->subfacet_del_count = 0;
- backer->last_minute += min_ms;
- }
-}
-
const struct ofproto_class ofproto_dpif_class = {
init,
enumerate_types,