static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+static bool
+nullable_string_is_equal(const char *a, const char *b)
+{
+ return a ? b && !strcmp(a, b) : !b;
+}
+
static bool
ofproto_sflow_options_equal(const struct ofproto_sflow_options *a,
const struct ofproto_sflow_options *b)
&& a->polling_interval == b->polling_interval
&& a->header_len == b->header_len
&& a->sub_id == b->sub_id
- && !strcmp(a->agent_device, b->agent_device)
- && !strcmp(a->control_ip, b->control_ip));
+ && nullable_string_is_equal(a->agent_device, b->agent_device)
+ && nullable_string_is_equal(a->control_ip, b->control_ip));
}
static struct ofproto_sflow_options *
ofproto_sflow_options_clone(const struct ofproto_sflow_options *old)
{
struct ofproto_sflow_options *new = xmemdup(old, sizeof *old);
+ svec_clone(&new->targets, &old->targets);
new->agent_device = old->agent_device ? xstrdup(old->agent_device) : NULL;
new->control_ip = old->control_ip ? xstrdup(old->control_ip) : NULL;
return new;
ofproto_sflow_options_destroy(struct ofproto_sflow_options *options)
{
if (options) {
+ svec_destroy(&options->targets);
free(options->agent_device);
free(options->control_ip);
free(options);
counters->ifIndex = SFL_DS_INDEX(poller->dsi);
counters->ifType = 6;
if (!netdev_get_features(osp->netdev, ¤t, NULL, NULL, NULL)) {
+ /* The values of ifDirection come from MAU MIB (RFC 2668): 0 = unknown,
+ 1 = full-duplex, 2 = half-duplex, 3 = in, 4=out */
counters->ifSpeed = netdev_features_to_bps(current);
counters->ifDirection = (netdev_features_is_full_duplex(current)
? 1 : 2);
} else {
counters->ifSpeed = 100000000;
- counters->ifDirection = 1;
+ counters->ifDirection = 0;
}
if (!netdev_get_flags(osp->netdev, &flags) && flags & NETDEV_UP) {
bool carrier;
time_t now;
int error;
+ if (!options->targets.n || !options->sampling_rate) {
+ /* No point in doing any work if there are no targets or nothing to
+ * sample. */
+ ofproto_sflow_clear(os);
+ return;
+ }
+
options_changed = (!os->options
|| !ofproto_sflow_options_equal(options, os->options));
error = collectors_create(&options->targets,
SFL_DEFAULT_COLLECTOR_PORT, &os->collectors);
if (os->collectors == NULL) {
- VLOG_WARN_RL(&rl, "no configured collectors, sFlow disabled");
+ VLOG_WARN_RL(&rl, "no collectors could be initialized, "
+ "sFlow disabled");
ofproto_sflow_clear(os);
return;
}
sflow_agent_send_packet_cb);
receiver = sfl_agent_addReceiver(os->sflow_agent);
- sfl_receiver_set_sFlowRcvrOwner(receiver, "OpenVSwitch sFlow");
+ sfl_receiver_set_sFlowRcvrOwner(receiver, "Open vSwitch sFlow");
sfl_receiver_set_sFlowRcvrTimeout(receiver, 0xffffffff);
- /* Add a single sampler to represent the whole switch (special <ifIndex>:0
+ /* Add a single sampler to represent the datapath (special <ifIndex>:0
* datasource). The alternative is to model a physical switch more closely
* and instantiate a separate sampler object for each interface, but then
* unicasts would have to be offered to two samplers, and
break;
}
}
- if (n_outputs > 1 || !fs.output) {
+
+ /* Set output port, as defined by http://www.sflow.org/sflow_version_5.txt
+ (search for "Input/output port information"). */
+ if (!n_outputs) {
+ /* This value indicates that the packet was dropped for an unknown
+ * reason. */
+ fs.output = 0x40000000 | 256;
+ } else if (n_outputs > 1 || !fs.output) {
/* Setting the high bit means "multiple output ports". */
fs.output = 0x80000000 | n_outputs;
}