#include "ofproto/ofproto.h"
#include "ovs-numa.h"
#include "poll-loop.h"
+#include "if-notifier.h"
#include "seq.h"
#include "sha1.h"
#include "shash.h"
#define AA_REFRESH_INTERVAL (1000) /* In milliseconds. */
static long long int aa_refresh_timer = LLONG_MIN;
-/* In some datapaths, creating and destroying OpenFlow ports can be extremely
- * expensive. This can cause bridge_reconfigure() to take a long time during
- * which no other work can be done. To deal with this problem, we limit port
- * adds and deletions to a window of OFP_PORT_ACTION_WINDOW milliseconds per
- * call to bridge_reconfigure(). If there is more work to do after the limit
- * is reached, 'need_reconfigure', is flagged and it's done on the next loop.
- * This allows the rest of the code to catch up on important things like
- * forwarding packets. */
-#define OFP_PORT_ACTION_WINDOW 10
+/* Whenever system interfaces are added, removed or change state, the bridge
+ * will be reconfigured.
+ */
+static struct if_notifier *ifnotifier;
+static bool ifaces_changed = false;
static void add_del_bridges(const struct ovsrec_open_vswitch *);
static void bridge_run__(void);
shash_destroy_free_data(&iface_hints);
initialized = true;
}
+
+static void
+if_change_cb(void *aux OVS_UNUSED)
+{
+ ifaces_changed = true;
+}
\f
/* Public functions. */
lacp_init();
bond_init();
cfm_init();
+ bfd_init();
ovs_numa_init();
stp_init();
lldp_init();
rstp_init();
+ ifnotifier = if_notifier_create(if_change_cb, NULL);
}
void
{
struct bridge *br, *next_br;
+ if_notifier_destroy(ifnotifier);
HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
bridge_destroy(br);
}
* should not be and in fact is not directly involved in that. But
* ovs-vswitchd needs to make sure that ovsdb-server can reach the managers, so
* it has to tell in-band control where the managers are to enable that.
- * (Thus, only managers connected in-band are collected.)
+ * (Thus, only managers connected in-band and with non-loopback addresses
+ * are collected.)
*/
static void
collect_in_band_managers(const struct ovsrec_open_vswitch *ovs_cfg,
struct sockaddr_in in;
} sa;
+ /* Ignore loopback. */
if (stream_parse_target_with_default_port(target, OVSDB_PORT,
&sa.ss)
- && sa.ss.ss_family == AF_INET) {
+ && sa.ss.ss_family == AF_INET
+ && sa.in.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
managers[n_managers++] = sa.in;
}
}
smap_get_int(&ovs_cfg->other_config, "n-handler-threads", 0),
smap_get_int(&ovs_cfg->other_config, "n-revalidator-threads", 0));
- if (ovs_cfg) {
- discover_types(ovs_cfg);
- }
-
/* Destroy "struct bridge"s, "struct port"s, and "struct iface"s according
* to 'ovs_cfg', with only very minimal configuration otherwise.
*
ovsdb_idl_run(idl);
+ if_notifier_run();
+
if (ovsdb_idl_is_lock_contended(idl)) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
struct bridge *br, *next_br;
}
}
- if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed) {
+ if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed
+ || ifaces_changed) {
struct ovsdb_idl_txn *txn;
+ ifaces_changed = false;
+
idl_seqno = ovsdb_idl_get_seqno(idl);
txn = ovsdb_idl_txn_create(idl);
bridge_reconfigure(cfg ? cfg : &null_cfg);
ovsdb_idl_txn_wait(daemonize_txn);
}
+ if_notifier_wait();
+ if (ifaces_changed) {
+ poll_immediate_wake();
+ }
+
sset_init(&types);
ofproto_enumerate_types(&types);
SSET_FOR_EACH (type, &types) {
s.name = NULL;
s.max_flows = UINT_MAX;
s.groups = NULL;
+ s.enable_eviction = false;
s.n_groups = 0;
s.n_prefix_fields = 0;
memset(s.prefix_fields, ~0, sizeof(s.prefix_fields));
if (cfg->n_flow_limit && *cfg->flow_limit < UINT_MAX) {
s.max_flows = *cfg->flow_limit;
}
- if (cfg->overflow_policy
- && !strcmp(cfg->overflow_policy, "evict")) {
+ s.enable_eviction = (cfg->overflow_policy
+ && !strcmp(cfg->overflow_policy, "evict"));
+ if (cfg->n_groups) {
s.groups = xmalloc(cfg->n_groups * sizeof *s.groups);
for (k = 0; k < cfg->n_groups; k++) {
const char *string = cfg->groups[k];
}
}
}
+
/* Prefix lookup fields. */
s.n_prefix_fields = 0;
for (k = 0; k < cfg->n_prefixes; k++) {
bridge_aa_refresh_queued(struct bridge *br)
{
struct ovs_list *list = xmalloc(sizeof *list);
- struct bridge_aa_vlan *node;
+ struct bridge_aa_vlan *node, *next;
list_init(list);
ofproto_aa_vlan_get_queued(br->ofproto, list);
- LIST_FOR_EACH(node, list_node, list) {
+ LIST_FOR_EACH_SAFE (node, next, list_node, list) {
struct port *port;
VLOG_INFO("ifname=%s, vlan=%u, oper=%u", node->port_name, node->vlan,