sflow: Improve user-visible string.
[openvswitch] / ofproto / ofproto-sflow.c
index cf63c65501d5cb1168cff978133efd636f7de13c..208ad8c765762831108ba8fbfbec1aa1ce768201 100644 (file)
@@ -54,6 +54,12 @@ struct ofproto_sflow {
 
 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)
@@ -63,14 +69,15 @@ ofproto_sflow_options_equal(const struct ofproto_sflow_options *a,
             && 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;
@@ -80,6 +87,7 @@ static void
 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);
@@ -140,12 +148,14 @@ sflow_agent_get_counters(void *os_, SFLPoller *poller,
     counters->ifIndex = SFL_DS_INDEX(poller->dsi);
     counters->ifType = 6;
     if (!netdev_get_features(osp->netdev, &current, 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;
@@ -349,6 +359,13 @@ ofproto_sflow_set_options(struct ofproto_sflow *os,
     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));
 
@@ -361,7 +378,8 @@ ofproto_sflow_set_options(struct ofproto_sflow *os,
         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;
         }
@@ -400,10 +418,10 @@ ofproto_sflow_set_options(struct ofproto_sflow *os,
                    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
@@ -535,6 +553,9 @@ ofproto_sflow_received(struct ofproto_sflow *os, struct odp_msg *msg)
             break;
         }
     }
+
+    /* 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. */