Previously, as part of ofproto-dpif run() processing, we would loop
through all ports and poll for changes to carrier, bfd, cfm and lacp
status. This information is used to determine whether bundles may be
enabled, and to perform revalidation when needed.
This patch makes the bfd, cfm, lacp and stp modules aware of the new
global connectivity_seq, notifying on changes in port status. We can
then use connectivity_seq to check if anything has changed before
looping through all ports in ofproto-dpif. In a test environment of 5000
internal ports and 50 tunnel ports with bfd, this reduces average CPU
usage of the main thread from about 35% to about 25%.
Signed-off-by: Joe Stringer <joestringer@nicira.com>
Signed-off-by: Ethan Jackson <ethan@nicira.com>
Acked-by: Ethan Jackson <ethan@nicira.com>
#include <netinet/ip.h>
#include "byte-order.h"
#include <netinet/ip.h>
#include "byte-order.h"
+#include "connectivity.h"
#include "csum.h"
#include "dpif.h"
#include "dynamic-string.h"
#include "csum.h"
#include "dpif.h"
#include "dynamic-string.h"
#include "packets.h"
#include "poll-loop.h"
#include "random.h"
#include "packets.h"
#include "poll-loop.h"
#include "random.h"
#include "smap.h"
#include "timeval.h"
#include "unaligned.h"
#include "smap.h"
#include "timeval.h"
#include "unaligned.h"
if (bfd->state > STATE_DOWN && now >= bfd->detect_time) {
bfd_set_state(bfd, STATE_DOWN, DIAG_EXPIRED);
if (bfd->state > STATE_DOWN && now >= bfd->detect_time) {
bfd_set_state(bfd, STATE_DOWN, DIAG_EXPIRED);
/* Decay may only happen when state is STATE_UP, bfd->decay_min_rx is
* configured, and decay_detect_time is reached. */
/* Decay may only happen when state is STATE_UP, bfd->decay_min_rx is
* configured, and decay_detect_time is reached. */
&& bfd->rmt_diag != DIAG_RCPATH_DOWN;
if (bfd->last_forwarding != last_forwarding) {
bfd->flap_count++;
&& bfd->rmt_diag != DIAG_RCPATH_DOWN;
if (bfd->last_forwarding != last_forwarding) {
bfd->flap_count++;
+ seq_change(connectivity_seq_get());
}
return bfd->last_forwarding;
}
}
return bfd->last_forwarding;
}
if (bfd->state == STATE_UP && bfd->decay_min_rx) {
bfd_decay_update(bfd);
}
if (bfd->state == STATE_UP && bfd->decay_min_rx) {
bfd_decay_update(bfd);
}
+
+ seq_change(connectivity_seq_get());
#include <string.h>
#include "byte-order.h"
#include <string.h>
#include "byte-order.h"
+#include "connectivity.h"
#include "dynamic-string.h"
#include "flow.h"
#include "hash.h"
#include "dynamic-string.h"
#include "flow.h"
#include "hash.h"
#include "packets.h"
#include "poll-loop.h"
#include "random.h"
#include "packets.h"
#include "poll-loop.h"
#include "random.h"
#include "timer.h"
#include "timeval.h"
#include "unixctl.h"
#include "timer.h"
#include "timeval.h"
#include "unixctl.h"
long long int interval = cfm_fault_interval(cfm);
struct remote_mp *rmp, *rmp_next;
bool old_cfm_fault = cfm->fault;
long long int interval = cfm_fault_interval(cfm);
struct remote_mp *rmp, *rmp_next;
bool old_cfm_fault = cfm->fault;
+ bool old_rmp_opup = cfm->remote_opup;
bool demand_override;
bool rmp_set_opup = false;
bool rmp_set_opdown = false;
bool demand_override;
bool rmp_set_opup = false;
bool rmp_set_opdown = false;
cfm->health = 0;
} else {
int exp_ccm_recvd;
cfm->health = 0;
} else {
int exp_ccm_recvd;
+ int old_health = cfm->health;
rmp = CONTAINER_OF(hmap_first(&cfm->remote_mps),
struct remote_mp, node);
rmp = CONTAINER_OF(hmap_first(&cfm->remote_mps),
struct remote_mp, node);
cfm->health = MIN(cfm->health, 100);
rmp->num_health_ccm = 0;
ovs_assert(cfm->health >= 0 && cfm->health <= 100);
cfm->health = MIN(cfm->health, 100);
rmp->num_health_ccm = 0;
ovs_assert(cfm->health >= 0 && cfm->health <= 100);
+
+ if (cfm->health != old_health) {
+ seq_change(connectivity_seq_get());
+ }
}
cfm->health_interval = 0;
}
}
cfm->health_interval = 0;
}
cfm->remote_opup = true;
}
cfm->remote_opup = true;
}
+ if (old_rmp_opup != cfm->remote_opup) {
+ seq_change(connectivity_seq_get());
+ }
+
if (hmap_is_empty(&cfm->remote_mps)) {
cfm->fault |= CFM_FAULT_RECV;
}
if (hmap_is_empty(&cfm->remote_mps)) {
cfm->fault |= CFM_FAULT_RECV;
}
if (old_cfm_fault == false || cfm->fault == false) {
cfm->flap_count++;
}
if (old_cfm_fault == false || cfm->fault == false) {
cfm->flap_count++;
}
+
+ seq_change(connectivity_seq_get());
+#include "connectivity.h"
#include "dynamic-string.h"
#include "hash.h"
#include "hmap.h"
#include "ofpbuf.h"
#include "packets.h"
#include "poll-loop.h"
#include "dynamic-string.h"
#include "hash.h"
#include "hmap.h"
#include "ofpbuf.h"
#include "packets.h"
#include "poll-loop.h"
#include "shash.h"
#include "timer.h"
#include "timeval.h"
#include "shash.h"
#include "timer.h"
#include "timeval.h"
ovs_mutex_lock(&mutex);
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
if (timer_expired(&slave->rx)) {
ovs_mutex_lock(&mutex);
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
if (timer_expired(&slave->rx)) {
+ enum slave_status old_status = slave->status;
+
if (slave->status == LACP_CURRENT) {
slave_set_expired(slave);
} else if (slave->status == LACP_EXPIRED) {
slave_set_defaulted(slave);
}
if (slave->status == LACP_CURRENT) {
slave_set_expired(slave);
} else if (slave->status == LACP_EXPIRED) {
slave_set_defaulted(slave);
}
+ if (slave->status != old_status) {
+ seq_change(connectivity_seq_get());
+ }
: LACP_SLOW_TIME_TX);
timer_set_duration(&slave->tx, duration);
: LACP_SLOW_TIME_TX);
timer_set_duration(&slave->tx, duration);
+ seq_change(connectivity_seq_get());
}
}
ovs_mutex_unlock(&mutex);
}
}
ovs_mutex_unlock(&mutex);
#include <inttypes.h>
#include <stdlib.h>
#include "byte-order.h"
#include <inttypes.h>
#include <stdlib.h>
#include "byte-order.h"
+#include "connectivity.h"
#include "ofpbuf.h"
#include "packets.h"
#include "ofpbuf.h"
#include "packets.h"
#include "unixctl.h"
#include "util.h"
#include "vlog.h"
#include "unixctl.h"
#include "util.h"
#include "vlog.h"
{
stp_root_selection(stp);
stp_designated_port_selection(stp);
{
stp_root_selection(stp);
stp_designated_port_selection(stp);
+ seq_change(connectivity_seq_get());
if (p < p->stp->first_changed_port) {
p->stp->first_changed_port = p;
}
if (p < p->stp->first_changed_port) {
p->stp->first_changed_port = p;
}
+ seq_change(connectivity_seq_get());
}
stp->fdb_needs_flush = true;
stp->topology_change_detected = true;
}
stp->fdb_needs_flush = true;
stp->topology_change_detected = true;
+ seq_change(connectivity_seq_get());
VLOG_INFO_RL(&rl, "%s: detected topology change.", stp->name);
}
VLOG_INFO_RL(&rl, "%s: detected topology change.", stp->name);
}
#include "bond.h"
#include "bundle.h"
#include "byte-order.h"
#include "bond.h"
#include "bundle.h"
#include "byte-order.h"
+#include "connectivity.h"
#include "connmgr.h"
#include "coverage.h"
#include "cfm.h"
#include "connmgr.h"
#include "coverage.h"
#include "cfm.h"
#include "ofproto-dpif-upcall.h"
#include "ofproto-dpif-xlate.h"
#include "poll-loop.h"
#include "ofproto-dpif-upcall.h"
#include "ofproto-dpif-xlate.h"
#include "poll-loop.h"
#include "simap.h"
#include "smap.h"
#include "timer.h"
#include "simap.h"
#include "smap.h"
#include "timer.h"
struct sset ghost_ports; /* Ports with no datapath port. */
struct sset port_poll_set; /* Queued names for port_poll() reply. */
int port_poll_errno; /* Last errno for port_poll() reply. */
struct sset ghost_ports; /* Ports with no datapath port. */
struct sset port_poll_set; /* Queued names for port_poll() reply. */
int port_poll_errno; /* Last errno for port_poll() reply. */
+ uint64_t change_seq; /* Connectivity status changes. */
/* Per ofproto's dpif stats. */
uint64_t n_hit;
/* Per ofproto's dpif stats. */
uint64_t n_hit;
sset_init(&ofproto->ghost_ports);
sset_init(&ofproto->port_poll_set);
ofproto->port_poll_errno = 0;
sset_init(&ofproto->ghost_ports);
sset_init(&ofproto->port_poll_set);
ofproto->port_poll_errno = 0;
+ ofproto->change_seq = 0;
SHASH_FOR_EACH_SAFE (node, next, &init_ofp_ports) {
struct iface_hint *iface_hint = node->data;
SHASH_FOR_EACH_SAFE (node, next, &init_ofp_ports) {
struct iface_hint *iface_hint = node->data;
run(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
run(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct ofport_dpif *ofport;
int error;
if (mbridge_need_revalidate(ofproto->mbridge)) {
int error;
if (mbridge_need_revalidate(ofproto->mbridge)) {
dpif_ipfix_run(ofproto->ipfix);
}
dpif_ipfix_run(ofproto->ipfix);
}
- HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
- port_run(ofport);
+ new_seq = seq_read(connectivity_seq_get());
+ if (ofproto->change_seq != new_seq) {
+ struct ofport_dpif *ofport;
+
+ HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
+ port_run(ofport);
+ }
+
+ ofproto->change_seq = new_seq;
}
HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
bundle_run(bundle);
}
HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
bundle_run(bundle);