Sflow support for ONOS

sFlow is a technology for monitoring traffic in data networks
containing switches and routers.  In particular, it defines the
sampling mechanisms implemented in an sFlow Agent for monitoring
traffic, the sFlow MIB for controlling the sFlow Agent, and the
format of sample data used by the sFlow Agent when forwarding data to
a central data collector.

Rfc: rfc3176
Change-Id: I74ce40d86c0cea1defe5f8c0947d1512b5843eb5
diff --git a/apps/ipflow-monitor/sflow/BUILD b/apps/ipflow-monitor/sflow/BUILD
new file mode 100644
index 0000000..ac31f51
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/BUILD
@@ -0,0 +1,13 @@
+BUNDLES = [
+    "//apps/ipflow-monitor/sflow/api:onos-apps-ipflow-monitor-sflow-api",
+    "//apps/ipflow-monitor/sflow/app:onos-apps-ipflow-monitor-sflow-app",
+]
+
+onos_app(
+    category = "Traffic Monitoring",
+    description = "Provides handling of sflow traffic.",
+    included_bundles = BUNDLES,
+    origin = "ONOS Community",
+    title = "Sflow traffic monitoring",
+    url = "http://onosproject.org",
+)
diff --git a/apps/ipflow-monitor/sflow/api/BUILD b/apps/ipflow-monitor/sflow/api/BUILD
new file mode 100644
index 0000000..f72e3bc
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/api/BUILD
@@ -0,0 +1,3 @@
+osgi_jar_with_tests(
+    deps = CORE_DEPS,
+)
diff --git a/apps/ipflow-monitor/sflow/api/src/main/java/org/onosproject/sflow/SflowController.java b/apps/ipflow-monitor/sflow/api/src/main/java/org/onosproject/sflow/SflowController.java
new file mode 100644
index 0000000..fa0572e
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/api/src/main/java/org/onosproject/sflow/SflowController.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.sflow;
+
+/**
+ * sFlow is a technology for monitoring traffic in data networks containing switches and routers.
+ * In particular, it defines the traffic sampling mechanisms implemented in
+ * sFlow Agents, the sFlow MIB for configuring sFlow Agents, and the format
+ * of the sFlow Datagram that carries traffic measurement data from sFlow
+ * Agents to an sFlow Collector.
+ * Ref : https://datatracker.ietf.org/doc/html/rfc3176
+ */
+public interface SflowController {
+
+    /**
+     * Get total sFlow sample packets counter.
+     * Total packets is a count of all the packets that could
+     * have been sampled.
+     *
+     * @return total number sFlow sample packet counter.
+     */
+    int getSampleCount();
+
+}
diff --git a/apps/ipflow-monitor/sflow/api/src/main/java/org/onosproject/sflow/package-info.java b/apps/ipflow-monitor/sflow/api/src/main/java/org/onosproject/sflow/package-info.java
new file mode 100644
index 0000000..9e56648
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/api/src/main/java/org/onosproject/sflow/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Base interfaces for sFlow collector application.
+ */
+package org.onosproject.sflow;
\ No newline at end of file
diff --git a/apps/ipflow-monitor/sflow/app/BUILD b/apps/ipflow-monitor/sflow/app/BUILD
new file mode 100644
index 0000000..611a03c
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/app/BUILD
@@ -0,0 +1,10 @@
+COMPILE_DEPS = CORE_DEPS + KRYO + CLI + [
+    "//core/store/serializers:onos-core-serializers",
+    "//apps/ipflow-monitor/sflow/api:onos-apps-ipflow-monitor-sflow-api",
+    "@io_netty_netty_common//jar",
+    "@io_netty_netty//jar",
+]
+
+osgi_jar(
+    deps = COMPILE_DEPS,
+)
diff --git a/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/Controller.java b/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/Controller.java
new file mode 100644
index 0000000..ef689c3
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/Controller.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sflow.impl;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executors;
+
+import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelFactory;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
+import org.jboss.netty.channel.FixedReceiveBufferSizePredictor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.onosproject.sflow.SflowController;
+
+/**
+ * The main controller class. Handles all setup and network listeners -
+ * Ownership of sflow message receiver.
+ */
+public class Controller {
+
+    private static final Logger log = LoggerFactory.getLogger(Controller.class);
+
+    private ChannelGroup channelGroup;
+    private Channel serverChannel;
+
+    // Configuration options
+    protected static final short SFLOW_PORT_NUM = 6343;
+    private final int workerThreads = 16;
+
+    // Start time of the controller
+    private long systemStartTime;
+
+    private ChannelFactory serverExecFactory;
+
+    private static final int BUFFER_SIZE = 5 * 1024;
+
+    private SflowController controller;
+
+    /**
+     * Constructor to initialize the values.
+     *
+     * @param controller sFlow controller instance
+     */
+    public Controller(SflowController controller) {
+        this.controller = controller;
+    }
+
+    /**
+     * To get system start time.
+     *
+     * @return system start time in milliseconds
+     */
+    public long getSystemStartTime() {
+        return (this.systemStartTime);
+    }
+
+    /**
+     * Initialize timer.
+     */
+    public void init() {
+        this.systemStartTime = System.currentTimeMillis();
+    }
+
+    /**
+     * Gets run time memory.
+     *
+     * @return run time memory
+     */
+    public Map<String, Long> getMemory() {
+        Map<String, Long> m = new HashMap<>();
+        Runtime runtime = Runtime.getRuntime();
+        m.put("total", runtime.totalMemory());
+        m.put("free", runtime.freeMemory());
+        return m;
+    }
+
+    /**
+     * Gets UP time.
+     *
+     * @return UP time
+     */
+    public Long getUptime() {
+        RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
+        return rb.getUptime();
+    }
+
+    /**
+     * sFlow collector it will receive message from sFlow exporter.
+     */
+    public void run() {
+
+        try {
+
+            final ConnectionlessBootstrap bootstrap = createServerBootStrap();
+
+            bootstrap.setOption("reuseAddress", false);
+            bootstrap.setOption("child.reuseAddress", false);
+            bootstrap.setOption("readBufferSize", BUFFER_SIZE);
+            bootstrap.setOption("receiveBufferSizePredictor",
+                    new FixedReceiveBufferSizePredictor(BUFFER_SIZE));
+            bootstrap.setOption("receiveBufferSizePredictorFactory",
+                    new FixedReceiveBufferSizePredictorFactory(BUFFER_SIZE));
+            ChannelPipelineFactory pfact = new SflowPipelineFactory(this.controller);
+
+            bootstrap.setPipelineFactory(pfact);
+            InetSocketAddress inetSocketAddress = new InetSocketAddress(SFLOW_PORT_NUM);
+            channelGroup = new DefaultChannelGroup();
+            serverChannel = bootstrap.bind(inetSocketAddress);
+            channelGroup.add(serverChannel);
+            log.info("Listening for sFlow exporter connection on {}", inetSocketAddress);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Creates server boot strap.
+     *
+     * @return ServerBootStrap
+     */
+    private ConnectionlessBootstrap createServerBootStrap() {
+
+        if (workerThreads == 0) {
+            serverExecFactory = new NioDatagramChannelFactory(
+                    Executors.newFixedThreadPool(2));
+            return new ConnectionlessBootstrap(serverExecFactory);
+        } else {
+            serverExecFactory = new NioDatagramChannelFactory(
+                    Executors.newFixedThreadPool(2),
+                    workerThreads);
+            return new ConnectionlessBootstrap(serverExecFactory);
+        }
+    }
+
+    /**
+     * Stops the sFlow collector.
+     */
+    public void stop() {
+        log.info("Stopped");
+        channelGroup.close();
+    }
+
+    /**
+     * Starts the sFlow collector.
+     */
+    public void start() {
+        log.info("Started");
+        this.run();
+    }
+}
diff --git a/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/SflowPipelineFactory.java b/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/SflowPipelineFactory.java
new file mode 100644
index 0000000..6c70337
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/SflowPipelineFactory.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.sflow.impl;
+
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.onosproject.sflow.SflowController;
+
+/**
+ * Creates a ChannelPipeline for a server-side sFlow message channel.
+ */
+public class SflowPipelineFactory implements ChannelPipelineFactory {
+
+    private SflowController controller;
+
+    /**
+     * Constructor to initialize the values.
+     *
+     * @param controller sFlow controller.
+     */
+    public SflowPipelineFactory(SflowController controller) {
+        super();
+        this.controller = controller;
+    }
+
+    /**
+     * Get server-side pipe line channel.
+     *
+     * @return ChannelPipeline server-side pipe line channel
+     * @throws Exception on while getting pipe line
+     */
+    @Override
+    public ChannelPipeline getPipeline() throws Exception {
+        ChannelPipeline pipeline = Channels.pipeline();
+        return pipeline;
+    }
+
+}
+
diff --git a/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/package-info.java b/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/package-info.java
new file mode 100644
index 0000000..ecb00c7
--- /dev/null
+++ b/apps/ipflow-monitor/sflow/app/src/main/java/org/onosproject/sflow/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Sflow collector application components.
+ */
+package org.onosproject.sflow.impl;
\ No newline at end of file
diff --git a/tools/build/bazel/modules.bzl b/tools/build/bazel/modules.bzl
index ce5cca2..8452919 100644
--- a/tools/build/bazel/modules.bzl
+++ b/tools/build/bazel/modules.bzl
@@ -223,6 +223,7 @@
     "//apps/mlb:onos-apps-mlb-oar": ["sdfabric"],
     "//apps/mobility:onos-apps-mobility-oar": [],
     "//apps/ipflow-monitor/netflow:onos-apps-ipflow-monitor-netflow-oar": [],
+    "//apps/ipflow-monitor/sflow:onos-apps-ipflow-monitor-sflow-oar": [],
     "//apps/network-troubleshoot:onos-apps-network-troubleshoot-oar": [],
     "//apps/newoptical:onos-apps-newoptical-oar": [],
     "//apps/nodemetrics:onos-apps-nodemetrics-oar": [],