enum { TBL_INTERNAL = N_TABLES - 1 }; /* Used for internal hidden rules. */
BUILD_ASSERT_DECL(N_TABLES >= 2 && N_TABLES <= 255);
+/* No bfd/cfm status change. */
+#define NO_STATUS_CHANGE -1
+
struct flow_miss;
struct rule_dpif {
/* Work queues. */
struct guarded_list pins; /* Contains "struct ofputil_packet_in"s. */
+ struct seq *pins_seq; /* For notifying 'pins' reception. */
+ uint64_t pins_seqno;
};
/* All existing ofproto_dpif instances, indexed by ->up.name. */
free(CONST_CAST(void *, pin->up.packet));
free(pin);
}
+
+ /* Wakes up main thread for packet-in I/O. */
+ seq_change(ofproto->pins_seq);
}
/* The default "table-miss" behaviour for OpenFlow1.3+ is to drop the
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);
+
SHASH_FOR_EACH_SAFE (node, next, &init_ofp_ports) {
struct iface_hint *iface_hint = node->data;
ovs_mutex_destroy(&ofproto->stats_mutex);
ovs_mutex_destroy(&ofproto->vsp_mutex);
+ seq_destroy(ofproto->pins_seq);
+
close_dpif_backer(ofproto->backer);
}
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
uint64_t new_seq, new_dump_seq;
- const bool enable_recirc = ofproto_dpif_get_enable_recirc(ofproto);
if (mbridge_need_revalidate(ofproto->mbridge)) {
ofproto->backer->need_revalidate = REV_RECONFIGURE;
}
}
+ /* Always updates the ofproto->pins_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
+ * completes. */
+ ofproto->pins_seqno = seq_read(ofproto->pins_seq);
+
if (ofproto->netflow) {
netflow_run(ofproto->netflow);
}
/* All outstanding data in existing flows has been accounted, so it's a
* good time to do bond rebalancing. */
- if (enable_recirc && ofproto->has_bonded_bundles) {
+ if (ofproto->has_bonded_bundles) {
struct ofbundle *bundle;
HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
- struct bond *bond = bundle->bond;
-
- if (bond && bond_may_recirc(bond, NULL, NULL)) {
- bond_recirculation_account(bond);
- if (bond_rebalance(bundle->bond)) {
- bond_update_post_recirc_rules(bond, true);
- }
+ if (bundle->bond) {
+ bond_rebalance(bundle->bond);
}
}
}
}
seq_wait(udpif_dump_seq(ofproto->backer->udpif), ofproto->dump_seq);
+ seq_wait(ofproto->pins_seq, ofproto->pins_seqno);
}
static void
return error;
}
-static bool
+static int
get_cfm_status(const struct ofport *ofport_,
struct ofproto_cfm_status *status)
{
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ int ret = 0;
if (ofport->cfm) {
- status->faults = cfm_get_fault(ofport->cfm);
- status->flap_count = cfm_get_flap_count(ofport->cfm);
- status->remote_opstate = cfm_get_opup(ofport->cfm);
- status->health = cfm_get_health(ofport->cfm);
- cfm_get_remote_mpids(ofport->cfm, &status->rmps, &status->n_rmps);
- return true;
+ if (cfm_check_status_change(ofport->cfm)) {
+ status->faults = cfm_get_fault(ofport->cfm);
+ status->flap_count = cfm_get_flap_count(ofport->cfm);
+ status->remote_opstate = cfm_get_opup(ofport->cfm);
+ status->health = cfm_get_health(ofport->cfm);
+ cfm_get_remote_mpids(ofport->cfm, &status->rmps, &status->n_rmps);
+ } else {
+ ret = NO_STATUS_CHANGE;
+ }
} else {
- return false;
+ ret = ENOENT;
}
+
+ return ret;
}
static int
get_bfd_status(struct ofport *ofport_, struct smap *smap)
{
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ int ret = 0;
if (ofport->bfd) {
- bfd_get_status(ofport->bfd, smap);
- return 0;
+ if (bfd_check_status_change(ofport->bfd)) {
+ bfd_get_status(ofport->bfd, smap);
+ } else {
+ ret = NO_STATUS_CHANGE;
+ }
} else {
- return ENOENT;
+ ret = ENOENT;
}
+
+ return ret;
}
\f
/* Spanning Tree. */