#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
+#include "async-append.h"
#include "bfd.h"
#include "bitmap.h"
#include "bond.h"
static void bridge_add_del_ports(struct bridge *,
const unsigned long int *splinter_vlans);
static void bridge_refresh_ofp_port(struct bridge *);
+static void bridge_configure_flow_miss_model(const char *opt);
static void bridge_configure_datapath_id(struct bridge *);
static void bridge_configure_netflow(struct bridge *);
static void bridge_configure_forward_bpdu(struct bridge *);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_state);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_resets);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mac_in_use);
+ ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ifindex);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mtu);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ofport);
ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_statistics);
smap_get_int(&ovs_cfg->other_config, "flow-eviction-threshold",
OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT));
+ ofproto_set_n_handler_threads(
+ smap_get_int(&ovs_cfg->other_config, "n-handler-threads", 0));
+
+ bridge_configure_flow_miss_model(smap_get(&ovs_cfg->other_config,
+ "force-miss-model"));
+
/* Destroy "struct bridge"s, "struct port"s, and "struct iface"s according
* to 'ovs_cfg' while update the "if_cfg_queue", with only very minimal
* configuration otherwise.
error = ofproto_port_del(br2->ofproto, ofproto_port.ofp_port);
if (error) {
VLOG_ERR("failed to delete port %s: %s", ofproto_port.name,
- strerror(error));
+ ovs_strerror(error));
}
ofproto_port_destroy(&ofproto_port);
}
error = ofproto_create(br->name, br->type, &br->ofproto);
if (error) {
VLOG_ERR("failed to create bridge %s: %s", br->name,
- strerror(error));
+ ovs_strerror(error));
bridge_destroy(br);
}
}
free(s.lacp_slaves);
}
+static void
+bridge_configure_flow_miss_model(const char *opt)
+{
+ enum ofproto_flow_miss_model model = OFPROTO_HANDLE_MISS_AUTO;
+
+ if (opt) {
+ if (strcmp(opt, "with-facets")) {
+ model = OFPROTO_HANDLE_MISS_WITH_FACETS;
+ } else if (strcmp(opt, "without-facets")) {
+ model = OFPROTO_HANDLE_MISS_WITHOUT_FACETS;
+ }
+ }
+
+ ofproto_set_flow_miss_model(model);
+}
+
/* Pick local port hardware address and datapath ID for 'br'. */
static void
bridge_configure_datapath_id(struct bridge *br)
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_ERR_RL(&rl, "bridge %s: failed to set bridge "
"Ethernet address: %s",
- br->name, strerror(error));
+ br->name, ovs_strerror(error));
}
}
memcpy(br->ea, ea, ETH_ADDR_LEN);
sset_destroy(&oso.targets);
}
+/* Returns whether a Flow_Sample_Collector_Set row is valid. */
+static bool
+ovsrec_fscs_is_valid(const struct ovsrec_flow_sample_collector_set *fscs,
+ const struct bridge *br)
+{
+ return fscs->ipfix && fscs->bridge == br->cfg;
+}
+
/* Set IPFIX configuration on 'br'. */
static void
bridge_configure_ipfix(struct bridge *br)
size_t n_fe_opts = 0;
OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) {
- if (fe_cfg->bridge == br->cfg) {
+ if (ovsrec_fscs_is_valid(fe_cfg, br)) {
n_fe_opts++;
}
}
if (be_cfg->obs_point_id) {
be_opts.obs_point_id = *be_cfg->obs_point_id;
}
+ if (be_cfg->cache_active_timeout) {
+ be_opts.cache_active_timeout = *be_cfg->cache_active_timeout;
+ }
+ if (be_cfg->cache_max_flows) {
+ be_opts.cache_max_flows = *be_cfg->cache_max_flows;
+ }
}
if (n_fe_opts > 0) {
fe_opts = xcalloc(n_fe_opts, sizeof *fe_opts);
opts = fe_opts;
OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) {
- if (fe_cfg->bridge == br->cfg) {
+ if (ovsrec_fscs_is_valid(fe_cfg, br)) {
opts->collector_set_id = fe_cfg->id;
sset_init(&opts->targets);
sset_add_array(&opts->targets, fe_cfg->ipfix->targets,
fe_cfg->ipfix->n_targets);
+ opts->cache_active_timeout = fe_cfg->ipfix->cache_active_timeout
+ ? *fe_cfg->ipfix->cache_active_timeout : 0;
+ opts->cache_max_flows = fe_cfg->ipfix->cache_max_flows
+ ? *fe_cfg->ipfix->cache_max_flows : 0;
opts++;
}
}
error = netdev_set_config(netdev, &iface_cfg->options);
if (error) {
VLOG_WARN("could not configure network device %s (%s)",
- iface_cfg->name, strerror(error));
+ iface_cfg->name, ovs_strerror(error));
}
return error;
}
iface_get_type(iface_cfg, br->cfg), &netdev);
if (error) {
VLOG_WARN("could not open network device %s (%s)",
- iface_cfg->name, strerror(error));
+ iface_cfg->name, ovs_strerror(error));
goto error;
}
netdev_close(netdev);
} else {
VLOG_WARN("could not open network device %s (%s)",
- port->name, strerror(error));
+ port->name, ovs_strerror(error));
}
} else {
/* Already exists, nothing to do. */
int mtu;
int64_t mtu_64;
uint8_t mac[ETH_ADDR_LEN];
+ int64_t ifindex64;
int error;
if (iface_is_synthetic(iface)) {
} else {
ovsrec_interface_set_mac_in_use(iface->cfg, NULL);
}
+
+ /* The netdev may return a negative number (such as -EOPNOTSUPP)
+ * if there is no valid ifindex number. */
+ ifindex64 = netdev_get_ifindex(iface->netdev);
+ if (ifindex64 < 0) {
+ ifindex64 = 0;
+ }
+ ovsrec_interface_set_ifindex(iface->cfg, &ifindex64, 1);
}
/* Writes 'iface''s CFM statistics to the database. 'iface' must not be
} else {
ovsrec_interface_set_cfm_health(cfg, NULL, 0);
}
+
+ free(status.rmps);
}
}
iface_refresh_cfm_stats(iface);
smap_init(&smap);
- if (!ofproto_port_get_bfd_status(br->ofproto, iface->ofp_port,
- &smap)) {
- ovsrec_interface_set_bfd_status(iface->cfg, &smap);
- smap_destroy(&smap);
- }
+ ofproto_port_get_bfd_status(br->ofproto, iface->ofp_port,
+ &smap);
+ ovsrec_interface_set_bfd_status(iface->cfg, &smap);
+ smap_destroy(&smap);
}
}
}
* process that forked us to exit successfully. */
daemonize_complete();
+ vlog_enable_async();
+
VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION);
}
}
};
static void
-qos_unixctl_show_cb(unsigned int queue_id,
- const struct smap *details,
- void *aux)
+qos_unixctl_show_queue(unsigned int queue_id,
+ const struct smap *details,
+ struct iface *iface,
+ struct ds *ds)
{
- struct qos_unixctl_show_cbdata *data = aux;
- struct ds *ds = data->ds;
- struct iface *iface = data->iface;
struct netdev_queue_stats stats;
struct smap_node *node;
int error;
}
} else {
ds_put_format(ds, "\tFailed to get statistics for queue %u: %s",
- queue_id, strerror(error));
+ queue_id, ovs_strerror(error));
}
}
struct iface *iface;
const char *type;
struct smap_node *node;
- struct qos_unixctl_show_cbdata data;
- int error;
iface = iface_find(argv[1]);
if (!iface) {
netdev_get_qos(iface->netdev, &type, &smap);
if (*type != '\0') {
+ struct netdev_queue_dump dump;
+ struct smap details;
+ unsigned int queue_id;
+
ds_put_format(&ds, "QoS: %s %s\n", iface->name, type);
SMAP_FOR_EACH (node, &smap) {
ds_put_format(&ds, "%s: %s\n", node->key, node->value);
}
- data.ds = &ds;
- data.iface = iface;
- error = netdev_dump_queues(iface->netdev, qos_unixctl_show_cb, &data);
-
- if (error) {
- ds_put_format(&ds, "failed to dump queues: %s", strerror(error));
+ smap_init(&details);
+ NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &dump, iface->netdev) {
+ qos_unixctl_show_queue(queue_id, &details, iface, &ds);
}
+ smap_destroy(&details);
+
unixctl_command_reply(conn, ds_cstr(&ds));
} else {
ds_put_format(&ds, "QoS not configured on %s\n", iface->name);
int error = netdev_set_etheraddr(iface->netdev, ea);
if (error) {
VLOG_ERR("interface %s: setting MAC failed (%s)",
- iface->name, strerror(error));
+ iface->name, ovs_strerror(error));
}
}
}
ovsrec_interface_set_cfm_remote_mpids(if_cfg, NULL, 0);
ovsrec_interface_set_lacp_current(if_cfg, NULL, 0);
ovsrec_interface_set_statistics(if_cfg, NULL, NULL, 0);
+ ovsrec_interface_set_ifindex(if_cfg, NULL, 0);
}
}
-struct iface_delete_queues_cbdata {
- struct netdev *netdev;
- const struct ovsdb_datum *queues;
-};
-
static bool
queue_ids_include(const struct ovsdb_datum *queues, int64_t target)
{
return ovsdb_datum_find_key(queues, &atom, OVSDB_TYPE_INTEGER) != UINT_MAX;
}
-static void
-iface_delete_queues(unsigned int queue_id,
- const struct smap *details OVS_UNUSED, void *cbdata_)
-{
- struct iface_delete_queues_cbdata *cbdata = cbdata_;
-
- if (!queue_ids_include(cbdata->queues, queue_id)) {
- netdev_delete_queue(cbdata->netdev, queue_id);
- }
-}
-
static void
iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos)
{
if (!qos || qos->type[0] == '\0' || qos->n_queues < 1) {
netdev_set_qos(iface->netdev, NULL, NULL);
} else {
- struct iface_delete_queues_cbdata cbdata;
+ const struct ovsdb_datum *queues;
+ struct netdev_queue_dump dump;
+ unsigned int queue_id;
+ struct smap details;
bool queue_zero;
size_t i;
netdev_set_qos(iface->netdev, qos->type, &qos->other_config);
/* Deconfigure queues that were deleted. */
- cbdata.netdev = iface->netdev;
- cbdata.queues = ovsrec_qos_get_queues(qos, OVSDB_TYPE_INTEGER,
- OVSDB_TYPE_UUID);
- netdev_dump_queues(iface->netdev, iface_delete_queues, &cbdata);
+ queues = ovsrec_qos_get_queues(qos, OVSDB_TYPE_INTEGER,
+ OVSDB_TYPE_UUID);
+ smap_init(&details);
+ NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &dump, iface->netdev) {
+ if (!queue_ids_include(queues, queue_id)) {
+ netdev_delete_queue(iface->netdev, queue_id);
+ }
+ }
+ smap_destroy(&details);
/* Configure queues for 'iface'. */
queue_zero = false;
if (!netdev_open(vlan_dev->name, "system", &netdev)) {
if (!netdev_get_in4(netdev, NULL, NULL) ||
!netdev_get_in6(netdev, NULL)) {
- vlandev_del(vlan_dev->name);
- } else {
/* It has an IP address configured, so we don't own
* it. Don't delete it. */
+ } else {
+ vlandev_del(vlan_dev->name);
}
netdev_close(netdev);
}