This patch adds a new field to "struct ofproto" to track which protocols are active on that bridge. This is updated whenever bfd, cfm, lacp or stp is enabled. In instant_stats_run(), we query this to determine whether it is worthwhile to poll a port's status for each of these protocols.
In a test environment running 5000 tunnel ports with only bfd running, we would previously see about 60% CPU usage when a port flapped twice per second. With this patch, average CPU usage decreases to around 55% in this case. Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- ofproto/ofproto-dpif.c | 9 +++++++++ ofproto/ofproto-provider.h | 1 + ofproto/ofproto.c | 12 ++++++++++++ ofproto/ofproto.h | 12 ++++++++++++ vswitchd/bridge.c | 46 +++++++++++++++++++++++++++----------------- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index c33a008..d6b5764 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1940,6 +1940,9 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s) } if (cfm_configure(ofport->cfm, s)) { + if (ofport->cfm) { + ofproto_set_active_modules(ofport->up.ofproto, PSM_CFM); + } error = 0; goto out; } @@ -1987,6 +1990,10 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg) } ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm, ofport->up.pp.hw_addr); + + if (ofport->bfd) { + ofproto_set_active_modules(&ofproto->up, PSM_BFD); + } return 0; } @@ -2053,6 +2060,7 @@ set_stp(struct ofproto *ofproto_, const struct ofproto_stp_settings *s) stp_set_hello_time(ofproto->stp, s->hello_time); stp_set_max_age(ofproto->stp, s->max_age); stp_set_forward_delay(ofproto->stp, s->fwd_delay); + ofproto_set_active_modules(ofproto_, PSM_STP); } else { struct ofport *ofport; @@ -2459,6 +2467,7 @@ bundle_set(struct ofproto *ofproto_, void *aux, if (!bundle->lacp) { ofproto->backer->need_revalidate = REV_RECONFIGURE; bundle->lacp = lacp_create(); + ofproto_set_active_modules(ofproto_, PSM_LACP); } lacp_configure(bundle->lacp, s->lacp); } else { diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index cad12ef..4026955 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -77,6 +77,7 @@ struct ofproto { char *serial_desc; /* Serial number (NULL for default). */ char *dp_desc; /* Datapath description (NULL for default). */ enum ofp_config_flags frag_handling; /* One of OFPC_*. */ + uint16_t active_modules; /* Active modules such as bfd, cfm, etc. */ /* Datapath. */ struct hmap ports; /* Contains "struct ofport"s. */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 1eae517..3804e9c 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -505,6 +505,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type, ofproto->serial_desc = NULL; ofproto->dp_desc = NULL; ofproto->frag_handling = OFPC_FRAG_NORMAL; + ofproto->active_modules = 0; hmap_init(&ofproto->ports); hmap_init(&ofproto->ofport_usage); shash_init(&ofproto->port_by_name); @@ -812,6 +813,17 @@ ofproto_get_flow_restore_wait(void) } +void +ofproto_set_active_modules(struct ofproto *ofproto, enum port_status_modules m) +{ + ofproto->active_modules |= m; +} + +uint16_t +ofproto_get_active_modules(const struct ofproto *ofproto) +{ + return ofproto->active_modules; +} /* Spanning Tree Protocol (STP) configuration. */ /* Configures STP on 'ofproto' using the settings defined in 's'. If diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 903d1f4..bf74709 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -423,6 +423,18 @@ struct ofproto_cfm_status { bool ofproto_port_get_cfm_status(const struct ofproto *, ofp_port_t ofp_port, struct ofproto_cfm_status *); + +/* Active modules that may affect port status. This is used by the bridge to + * determine what kind of status updates it needs to gather. */ +enum port_status_modules { + PSM_CFM = 1 << 0, + PSM_BFD = 1 << 1, + PSM_STP = 1 << 2, + PSM_LACP = 1 << 3, +}; + +void ofproto_set_active_modules(struct ofproto *, enum port_status_modules); +uint16_t ofproto_get_active_modules(const struct ofproto *ofproto); /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index fdf0000..08a8c53 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2221,6 +2221,7 @@ instant_stats_run(void) struct iface *iface; struct port *port; uint64_t seq; + uint16_t status_mask = ofproto_get_active_modules(br->ofproto); seq = netdev_change_seq(); if (seq == br->change_seq) { @@ -2229,10 +2230,12 @@ instant_stats_run(void) br->change_seq = seq; } - br_refresh_stp_status(br); + if (status_mask | PSM_STP) { + br_refresh_stp_status(br); - HMAP_FOR_EACH (port, hmap_node, &br->ports) { - port_refresh_stp_status(port); + HMAP_FOR_EACH (port, hmap_node, &br->ports) { + port_refresh_stp_status(port); + } } HMAP_FOR_EACH (iface, name_node, &br->iface_by_name) { @@ -2246,15 +2249,7 @@ instant_stats_run(void) continue; } - current = ofproto_port_is_lacp_current(br->ofproto, - iface->ofp_port); - if (current >= 0) { - bool bl = current; - ovsrec_interface_set_lacp_current(iface->cfg, &bl, 1); - } else { - ovsrec_interface_set_lacp_current(iface->cfg, NULL, 0); - } - + /* Admin and carrier status is always performed. */ error = netdev_get_flags(iface->netdev, &flags); if (!error) { const char *state = flags & NETDEV_UP ? "up" : "down"; @@ -2269,13 +2264,28 @@ instant_stats_run(void) link_resets = netdev_get_carrier_resets(iface->netdev); ovsrec_interface_set_link_resets(iface->cfg, &link_resets, 1); - iface_refresh_cfm_stats(iface); + if (status_mask | PSM_LACP) { + current = ofproto_port_is_lacp_current(br->ofproto, + iface->ofp_port); + if (current >= 0) { + bool bl = current; + ovsrec_interface_set_lacp_current(iface->cfg, &bl, 1); + } else { + ovsrec_interface_set_lacp_current(iface->cfg, NULL, 0); + } + } - smap_init(&smap); - ofproto_port_get_bfd_status(br->ofproto, iface->ofp_port, - &smap); - ovsrec_interface_set_bfd_status(iface->cfg, &smap); - smap_destroy(&smap); + if (status_mask | PSM_CFM) { + iface_refresh_cfm_stats(iface); + } + + if (status_mask | PSM_BFD) { + smap_init(&smap); + ofproto_port_get_bfd_status(br->ofproto, iface->ofp_port, + &smap); + ovsrec_interface_set_bfd_status(iface->cfg, &smap); + smap_destroy(&smap); + } } } } -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev