mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
dpif-linux: Use hash instead of sorted array.
With 1000 network devices being added or removed, sorting the array was a profiling hot spot. Using a hash makes it drop off the profile.
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
#include "ofpbuf.h"
|
#include "ofpbuf.h"
|
||||||
#include "poll-loop.h"
|
#include "poll-loop.h"
|
||||||
#include "rtnetlink.h"
|
#include "rtnetlink.h"
|
||||||
|
#include "shash.h"
|
||||||
#include "svec.h"
|
#include "svec.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ struct dpif_linux {
|
|||||||
|
|
||||||
/* Change notification. */
|
/* Change notification. */
|
||||||
int local_ifindex; /* Ifindex of local port. */
|
int local_ifindex; /* Ifindex of local port. */
|
||||||
struct svec changed_ports; /* Ports that have changed. */
|
struct shash changed_ports; /* Ports that have changed. */
|
||||||
struct rtnetlink_notifier port_notifier;
|
struct rtnetlink_notifier port_notifier;
|
||||||
bool change_error;
|
bool change_error;
|
||||||
};
|
};
|
||||||
@@ -172,7 +173,7 @@ dpif_linux_close(struct dpif *dpif_)
|
|||||||
{
|
{
|
||||||
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
||||||
rtnetlink_notifier_unregister(&dpif->port_notifier);
|
rtnetlink_notifier_unregister(&dpif->port_notifier);
|
||||||
svec_destroy(&dpif->changed_ports);
|
shash_destroy(&dpif->changed_ports);
|
||||||
free(dpif->local_ifname);
|
free(dpif->local_ifname);
|
||||||
close(dpif->fd);
|
close(dpif->fd);
|
||||||
free(dpif);
|
free(dpif);
|
||||||
@@ -330,10 +331,12 @@ dpif_linux_port_poll(const struct dpif *dpif_, char **devnamep)
|
|||||||
|
|
||||||
if (dpif->change_error) {
|
if (dpif->change_error) {
|
||||||
dpif->change_error = false;
|
dpif->change_error = false;
|
||||||
svec_clear(&dpif->changed_ports);
|
shash_clear(&dpif->changed_ports);
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
} else if (dpif->changed_ports.n) {
|
} else if (!shash_is_empty(&dpif->changed_ports)) {
|
||||||
*devnamep = dpif->changed_ports.names[--dpif->changed_ports.n];
|
struct shash_node *node = shash_first(&dpif->changed_ports);
|
||||||
|
*devnamep = xstrdup(node->name);
|
||||||
|
shash_delete(&dpif->changed_ports, node);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return EAGAIN;
|
return EAGAIN;
|
||||||
@@ -344,7 +347,7 @@ static void
|
|||||||
dpif_linux_port_poll_wait(const struct dpif *dpif_)
|
dpif_linux_port_poll_wait(const struct dpif *dpif_)
|
||||||
{
|
{
|
||||||
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
||||||
if (dpif->changed_ports.n || dpif->change_error) {
|
if (!shash_is_empty(&dpif->changed_ports) || dpif->change_error) {
|
||||||
poll_immediate_wake();
|
poll_immediate_wake();
|
||||||
} else {
|
} else {
|
||||||
rtnetlink_notifier_wait();
|
rtnetlink_notifier_wait();
|
||||||
@@ -786,7 +789,7 @@ open_minor(int minor, struct dpif **dpifp)
|
|||||||
dpif->local_ifname = NULL;
|
dpif->local_ifname = NULL;
|
||||||
dpif->minor = minor;
|
dpif->minor = minor;
|
||||||
dpif->local_ifindex = 0;
|
dpif->local_ifindex = 0;
|
||||||
svec_init(&dpif->changed_ports);
|
shash_init(&dpif->changed_ports);
|
||||||
dpif->change_error = false;
|
dpif->change_error = false;
|
||||||
*dpifp = &dpif->dpif;
|
*dpifp = &dpif->dpif;
|
||||||
} else {
|
} else {
|
||||||
@@ -813,10 +816,7 @@ dpif_linux_port_changed(const struct rtnetlink_change *change, void *dpif_)
|
|||||||
{
|
{
|
||||||
/* Our datapath changed, either adding a new port or deleting an
|
/* Our datapath changed, either adding a new port or deleting an
|
||||||
* existing one. */
|
* existing one. */
|
||||||
if (!svec_contains(&dpif->changed_ports, change->ifname)) {
|
shash_add_once(&dpif->changed_ports, change->ifname, NULL);
|
||||||
svec_add(&dpif->changed_ports, change->ifname);
|
|
||||||
svec_sort(&dpif->changed_ports);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dpif->change_error = true;
|
dpif->change_error = true;
|
||||||
|
Reference in New Issue
Block a user