Adjust sFlow packet samplers to better reflect the underlying per-bridge
sampling that is really happening,  rather than modeling it as per-interface
sampling. This fixes an aliasing issue: tunnel traffic sampled on different
bridges was all being reported against the same sFlow datasource.

The sFlow counter samples remain unchanged,  reporting only on interfaces
that have valid ifIndex numbers.

See definition of SFlowDataSource in http://sflow.org/sflow_version_5.txt.

Signed-off-by: Neil McKee <neil.mc...@inmon.com>

---
 lib/sflow.h                  |  7 ++++
 ofproto/ofproto-dpif-sflow.c | 76 +++++++++++++++++++++-----------------------
 tests/ofproto-dpif.at        | 48 ++++++++++++++--------------
 3 files changed, 68 insertions(+), 63 deletions(-)

diff --git a/lib/sflow.h b/lib/sflow.h
index 8ea9693..4a222d2 100644
--- a/lib/sflow.h
+++ b/lib/sflow.h
@@ -8,6 +8,13 @@
 #ifndef SFLOW_H
 #define SFLOW_H 1
 
+typedef enum {
+  SFL_DSCLASS_IFINDEX=0,
+  SFL_DSCLASS_VLAN=1,
+  SFL_DSCLASS_PHYSICAL_ENTITY=2,
+  SFL_DSCLASS_LOGICAL_ENTITY=3
+} SFL_DSCLASS;
+
 enum SFLAddress_type {
     SFLADDRESSTYPE_IP_V4 = 1,
     SFLADDRESSTYPE_IP_V6 = 2
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index 69362ab..6521d10 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -341,15 +341,6 @@ dpif_sflow_add_poller(struct dpif_sflow *ds, struct 
dpif_sflow_port *dsp)
     sfl_poller_set_bridgePort(poller, dsp->odp_port);
 }
 
-static void
-dpif_sflow_add_sampler(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
-{
-    SFLSampler *sampler = sfl_agent_addSampler(ds->sflow_agent, &dsp->dsi);
-    sfl_sampler_set_sFlowFsPacketSamplingRate(sampler, 
ds->options->sampling_rate);
-    sfl_sampler_set_sFlowFsMaximumHeaderSize(sampler, ds->options->header_len);
-    sfl_sampler_set_sFlowFsReceiver(sampler, RECEIVER_INDEX);
-}
-
 void
 dpif_sflow_add_port(struct dpif_sflow *ds, struct ofport *ofport,
                     uint32_t odp_port)
@@ -359,21 +350,23 @@ dpif_sflow_add_port(struct dpif_sflow *ds, struct ofport 
*ofport,
 
     dpif_sflow_del_port(ds, odp_port);
 
-    /* Add to table of ports. */
-    dsp = xmalloc(sizeof *dsp);
     ifindex = netdev_get_ifindex(ofport->netdev);
-    if (ifindex <= 0) {
-        ifindex = (ds->sflow_agent->subId << 16) + odp_port;
+
+    if ((int32_t)ifindex <= 0) {
+      /* Not an ifindex port, so do not add a cross-reference to it here */
+      return;
     }
+
+    /* Add to table of ports. */
+    dsp = xmalloc(sizeof *dsp);
     dsp->ofport = ofport;
     dsp->odp_port = odp_port;
-    SFL_DS_SET(dsp->dsi, 0, ifindex, 0);
+    SFL_DS_SET(dsp->dsi, SFL_DSCLASS_IFINDEX, ifindex, 0);
     hmap_insert(&ds->ports, &dsp->hmap_node, hash_int(odp_port, 0));
 
-    /* Add poller and sampler. */
+    /* Add poller. */
     if (ds->sflow_agent) {
         dpif_sflow_add_poller(ds, dsp);
-        dpif_sflow_add_sampler(ds, dsp);
     }
 }
 
@@ -406,6 +399,9 @@ dpif_sflow_set_options(struct dpif_sflow *ds,
     SFLReceiver *receiver;
     SFLAddress agentIP;
     time_t now;
+    SFLDataSource_instance dsi;
+    uint32_t dsIndex;
+    SFLSampler *sampler;
 
     if (sset_is_empty(&options->targets) || !options->sampling_rate) {
         /* No point in doing any work if there are no targets or nothing to
@@ -473,10 +469,20 @@ dpif_sflow_set_options(struct dpif_sflow *ds,
     /* Set the sampling_rate down in the datapath. */
     ds->probability = MAX(1, UINT32_MAX / ds->options->sampling_rate);
 
-    /* Add samplers and pollers for the currently known ports. */
+    /* Add a single sampler for the bridge. This appears as a PHYSICAL_ENTITY
+       because it is associated with the hypervisor, and interacts with the 
server
+       hardware directly.  The sub_id is used to distinguish this sampler from
+       others on other bridges within the same agent. */
+    dsIndex = 1000 + options->sub_id;
+    SFL_DS_SET(dsi, SFL_DSCLASS_PHYSICAL_ENTITY, dsIndex, 0);
+    sampler = sfl_agent_addSampler(ds->sflow_agent, &dsi);
+    sfl_sampler_set_sFlowFsPacketSamplingRate(sampler, 
ds->options->sampling_rate);
+    sfl_sampler_set_sFlowFsMaximumHeaderSize(sampler, ds->options->header_len);
+    sfl_sampler_set_sFlowFsReceiver(sampler, RECEIVER_INDEX);
+
+    /* Add pollers for the currently known ifindex-ports */
     HMAP_FOR_EACH (dsp, hmap_node, &ds->ports) {
         dpif_sflow_add_poller(ds, dsp);
-        dpif_sflow_add_sampler(ds, dsp);
     }
 }
 
@@ -499,35 +505,27 @@ dpif_sflow_received(struct dpif_sflow *ds, struct ofpbuf 
*packet,
     SFLFlow_sample_element switchElem;
     SFLSampler *sampler;
     struct dpif_sflow_port *in_dsp;
-    struct netdev_stats stats;
     ovs_be16 vlan_tci;
-    int error;
+
+    sampler = ds->sflow_agent->samplers;
+    if(!sampler) {
+      return;
+    }
 
     /* Build a flow sample */
     memset(&fs, 0, sizeof fs);
 
+    /* look up the input ifIndex if this port has one. Otherwise just
+       leave it as 0 (meaning 'unknown') and continue */
     in_dsp = dpif_sflow_find_port(ds, odp_in_port);
-    if (!in_dsp) {
-        return;
+    if(in_dsp) {
+      fs.input = SFL_DS_INDEX(in_dsp->dsi);
     }
-    fs.input = SFL_DS_INDEX(in_dsp->dsi);
 
-    error = ofproto_port_get_stats(in_dsp->ofport, &stats);
-    if (error) {
-        VLOG_WARN_RL(&rl, "netdev get-stats error %s", strerror(error));
-        return;
-    }
-    fs.sample_pool = stats.rx_packets;
-
-    /* We are going to give it to the sampler that represents this input port.
-     * By implementing "ingress-only" sampling like this we ensure that we
-     * never have to offer the same sample to more than one sampler. */
-    sampler = sfl_agent_getSamplerByIfIndex(ds->sflow_agent, fs.input);
-    if (!sampler) {
-        VLOG_WARN_RL(&rl, "no sampler for input ifIndex (%"PRIu32")",
-                     fs.input);
-        return;
-    }
+    /* Make the assumption that the random number generator in the datapath 
converges
+       to the configured mean, and just increment the samplePool by the 
configured
+       sampling rate every time. */
+    sampler->samplePool += sfl_sampler_get_sFlowFsPacketSamplingRate(sampler);
 
     /* Sampled header. */
     memset(&hdrElem, 0, sizeof hdrElem);
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index b1d2f26..b813fd0 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -1252,7 +1252,7 @@ AT_CHECK([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 
's/ /\
        /g']], [0], [dnl
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1003
+       ds=127.0.0.1>2:1000
        fsSeqNo=1
        in_vlan=0
        in_priority=0
@@ -1261,7 +1261,7 @@ HEADER
        meanSkip=1
        samplePool=1
        dropEvents=0
-       in_ifindex=1003
+       in_ifindex=1004
        in_format=0
        out_ifindex=2
        out_format=2
@@ -1269,10 +1269,10 @@ HEADER
        pkt_len=64
        stripped=4
        hdr_len=60
-       
hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-07-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-07-C0-A8-00-01-00-00-00-00-00-00-C0-A8-00-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       
hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-05-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-05-C0-A8-00-02-00-00-00-00-00-00-C0-A8-00-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1003
+       ds=127.0.0.1>2:1000
        fsSeqNo=2
        in_vlan=0
        in_priority=0
@@ -1283,16 +1283,16 @@ HEADER
        dropEvents=0
        in_ifindex=1003
        in_format=0
-       out_ifindex=1004
-       out_format=0
+       out_ifindex=2
+       out_format=2
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       
hdr=50-54-00-00-00-05-50-54-00-00-00-07-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-02-C0-A8-00-01-00-00-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       
hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-07-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-07-C0-A8-00-01-00-00-00-00-00-00-C0-A8-00-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1003
+       ds=127.0.0.1>2:1000
        fsSeqNo=3
        in_vlan=0
        in_priority=0
@@ -1301,55 +1301,55 @@ HEADER
        meanSkip=1
        samplePool=3
        dropEvents=0
-       in_ifindex=1003
+       in_ifindex=1004
        in_format=0
-       out_ifindex=1004
+       out_ifindex=1003
        out_format=0
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       
hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       
hdr=50-54-00-00-00-07-50-54-00-00-00-05-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-01-C0-A8-00-02-08-00-F7-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1004
-       fsSeqNo=1
+       ds=127.0.0.1>2:1000
+       fsSeqNo=4
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
-       samplePool=1
+       samplePool=4
        dropEvents=0
-       in_ifindex=1004
+       in_ifindex=1003
        in_format=0
-       out_ifindex=2
-       out_format=2
+       out_ifindex=1004
+       out_format=0
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       
hdr=FF-FF-FF-FF-FF-FF-50-54-00-00-00-05-08-06-00-01-08-00-06-04-00-01-50-54-00-00-00-05-C0-A8-00-02-00-00-00-00-00-00-C0-A8-00-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       
hdr=50-54-00-00-00-05-50-54-00-00-00-07-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-02-C0-A8-00-01-00-00-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 HEADER
        dgramSeqNo=1
-       ds=127.0.0.1>0:1004
-       fsSeqNo=2
+       ds=127.0.0.1>2:1000
+       fsSeqNo=5
        in_vlan=0
        in_priority=0
        out_vlan=0
        out_priority=0
        meanSkip=1
-       samplePool=2
+       samplePool=5
        dropEvents=0
-       in_ifindex=1004
+       in_ifindex=1003
        in_format=0
-       out_ifindex=1003
+       out_ifindex=1004
        out_format=0
        hdr_prot=1
        pkt_len=64
        stripped=4
        hdr_len=60
-       
hdr=50-54-00-00-00-07-50-54-00-00-00-05-08-00-45-00-00-1C-00-00-00-00-40-01-F9-8D-C0-A8-00-01-C0-A8-00-02-08-00-F7-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+       
hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 ])
 
 AT_CHECK([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\
-- 
1.8.1.4


_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to