From: Joe Stringer Date: Fri, 13 Dec 2013 03:33:47 +0000 (+0000) Subject: ofproto-dpif: Don't poll ports when nothing changes X-Git-Tag: sliver-openvswitch-2.1.90-1~10^2~206 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=f23d157c05649d369c5456e9a18bb47716306893;hp=da4a619179d6d6e9e6a82977c41cfcc2d1533ad8;p=sliver-openvswitch.git ofproto-dpif: Don't poll ports when nothing changes 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 Signed-off-by: Ethan Jackson Acked-by: Ethan Jackson --- diff --git a/lib/bfd.c b/lib/bfd.c index 1df5acd05..5ac20d6df 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -21,6 +21,7 @@ #include #include "byte-order.h" +#include "connectivity.h" #include "csum.h" #include "dpif.h" #include "dynamic-string.h" @@ -37,6 +38,7 @@ #include "packets.h" #include "poll-loop.h" #include "random.h" +#include "seq.h" #include "smap.h" #include "timeval.h" #include "unaligned.h" @@ -505,8 +507,8 @@ bfd_run(struct bfd *bfd) OVS_EXCLUDED(mutex) if (bfd->state > STATE_DOWN && now >= bfd->detect_time) { bfd_set_state(bfd, STATE_DOWN, DIAG_EXPIRED); - bfd_forwarding__(bfd); } + bfd_forwarding__(bfd); /* Decay may only happen when state is STATE_UP, bfd->decay_min_rx is * configured, and decay_detect_time is reached. */ @@ -851,6 +853,7 @@ bfd_forwarding__(struct bfd *bfd) OVS_REQUIRES(mutex) && bfd->rmt_diag != DIAG_RCPATH_DOWN; if (bfd->last_forwarding != last_forwarding) { bfd->flap_count++; + seq_change(connectivity_seq_get()); } return bfd->last_forwarding; } @@ -1052,6 +1055,8 @@ bfd_set_state(struct bfd *bfd, enum state state, enum diag diag) if (bfd->state == STATE_UP && bfd->decay_min_rx) { bfd_decay_update(bfd); } + + seq_change(connectivity_seq_get()); } } diff --git a/lib/cfm.c b/lib/cfm.c index 9c65b3489..8ba0c4477 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -22,6 +22,7 @@ #include #include "byte-order.h" +#include "connectivity.h" #include "dynamic-string.h" #include "flow.h" #include "hash.h" @@ -31,6 +32,7 @@ #include "packets.h" #include "poll-loop.h" #include "random.h" +#include "seq.h" #include "timer.h" #include "timeval.h" #include "unixctl.h" @@ -396,6 +398,7 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) 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; @@ -420,6 +423,7 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) 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); @@ -434,6 +438,10 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) 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; } @@ -476,6 +484,10 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) 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; } @@ -497,6 +509,8 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) if (old_cfm_fault == false || cfm->fault == false) { cfm->flap_count++; } + + seq_change(connectivity_seq_get()); } cfm->booted = true; diff --git a/lib/lacp.c b/lib/lacp.c index fce65b31d..07f1e101a 100644 --- a/lib/lacp.c +++ b/lib/lacp.c @@ -18,12 +18,14 @@ #include +#include "connectivity.h" #include "dynamic-string.h" #include "hash.h" #include "hmap.h" #include "ofpbuf.h" #include "packets.h" #include "poll-loop.h" +#include "seq.h" #include "shash.h" #include "timer.h" #include "timeval.h" @@ -509,11 +511,16 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex) 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 != old_status) { + seq_change(connectivity_seq_get()); + } } } @@ -544,6 +551,7 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex) : LACP_SLOW_TIME_TX); timer_set_duration(&slave->tx, duration); + seq_change(connectivity_seq_get()); } } ovs_mutex_unlock(&mutex); diff --git a/lib/stp.c b/lib/stp.c index 725bfffdc..8b9d26ae7 100644 --- a/lib/stp.c +++ b/lib/stp.c @@ -26,8 +26,10 @@ #include #include #include "byte-order.h" +#include "connectivity.h" #include "ofpbuf.h" #include "packets.h" +#include "seq.h" #include "unixctl.h" #include "util.h" #include "vlog.h" @@ -1127,6 +1129,7 @@ stp_configuration_update(struct stp *stp) OVS_REQUIRES(mutex) { stp_root_selection(stp); stp_designated_port_selection(stp); + seq_change(connectivity_seq_get()); } static bool @@ -1257,6 +1260,7 @@ stp_set_port_state(struct stp_port *p, enum stp_state state) if (p < p->stp->first_changed_port) { p->stp->first_changed_port = p; } + seq_change(connectivity_seq_get()); } p->state = state; } @@ -1275,6 +1279,7 @@ stp_topology_change_detection(struct stp *stp) OVS_REQUIRES(mutex) } 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); } diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 086f676ab..616aa3c10 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -25,6 +25,7 @@ #include "bond.h" #include "bundle.h" #include "byte-order.h" +#include "connectivity.h" #include "connmgr.h" #include "coverage.h" #include "cfm.h" @@ -57,6 +58,7 @@ #include "ofproto-dpif-upcall.h" #include "ofproto-dpif-xlate.h" #include "poll-loop.h" +#include "seq.h" #include "simap.h" #include "smap.h" #include "timer.h" @@ -505,6 +507,7 @@ struct ofproto_dpif { 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; @@ -1262,6 +1265,7 @@ construct(struct ofproto *ofproto_) 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; @@ -1467,8 +1471,8 @@ static int run(struct ofproto *ofproto_) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); - struct ofport_dpif *ofport; struct ofbundle *bundle; + uint64_t new_seq; int error; if (mbridge_need_revalidate(ofproto->mbridge)) { @@ -1501,8 +1505,15 @@ run(struct ofproto *ofproto_) 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);