aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/sflow/sflow.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/sflow/sflow.h')
-rw-r--r--src/plugins/sflow/sflow.h198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/plugins/sflow/sflow.h b/src/plugins/sflow/sflow.h
new file mode 100644
index 00000000000..609ff723816
--- /dev/null
+++ b/src/plugins/sflow/sflow.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2024 InMon Corp.
+ * 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.
+ */
+#ifndef __included_sflow_h__
+#define __included_sflow_h__
+
+#include <vnet/vnet.h>
+#include <vnet/ip/ip.h>
+#include <vnet/ethernet/ethernet.h>
+
+#include <vppinfra/hash.h>
+#include <vppinfra/error.h>
+#include <sflow/sflow_common.h>
+#include <sflow/sflow_vapi.h>
+#include <sflow/sflow_psample.h>
+#include <sflow/sflow_usersock.h>
+
+#define SFLOW_DEFAULT_SAMPLING_N 10000
+#define SFLOW_DEFAULT_POLLING_S 20
+#define SFLOW_DEFAULT_HEADER_BYTES 128
+#define SFLOW_MAX_HEADER_BYTES 256
+#define SFLOW_MIN_HEADER_BYTES 64
+#define SFLOW_HEADER_BYTES_STEP 32
+
+#define SFLOW_FIFO_DEPTH 2048 // must be power of 2
+#define SFLOW_POLL_WAIT_S 0.001
+#define SFLOW_READ_BATCH 100
+
+// use PSAMPLE group number to distinguish VPP samples from others
+// (so that hsflowd will know to remap the ifIndex numbers if necessary)
+#define SFLOW_VPP_PSAMPLE_GROUP_INGRESS 3
+#define SFLOW_VPP_PSAMPLE_GROUP_EGRESS 4
+
+#define foreach_sflow_error \
+ _ (PROCESSED, "sflow packets processed") \
+ _ (SAMPLED, "sflow packets sampled") \
+ _ (DROPPED, "sflow packets dropped") \
+ _ (PSAMPLE_SEND, "sflow PSAMPLE sent") \
+ _ (PSAMPLE_SEND_FAIL, "sflow PSAMPLE send failed")
+
+typedef enum
+{
+#define _(sym, str) SFLOW_ERROR_##sym,
+ foreach_sflow_error
+#undef _
+ SFLOW_N_ERROR,
+} sflow_error_t;
+
+typedef struct
+{
+ u32 counters[SFLOW_N_ERROR];
+} sflow_err_ctrs_t;
+
+/* packet sample */
+typedef struct
+{
+ u32 samplingN;
+ u32 input_if_index;
+ u32 output_if_index;
+ u32 header_protocol;
+ u32 sampled_packet_size;
+ u32 header_bytes;
+ u8 header[SFLOW_MAX_HEADER_BYTES];
+} sflow_sample_t;
+
+// Define SPSC FIFO for sending samples worker-to-main.
+// (I did try to use VPP svm FIFO, but couldn't
+// understand why it was sometimes going wrong).
+typedef struct
+{
+ volatile u32 tx; // can change under consumer's feet
+ volatile u32 rx; // can change under producer's feet
+ sflow_sample_t samples[SFLOW_FIFO_DEPTH];
+} sflow_fifo_t;
+
+#define SFLOW_FIFO_NEXT(slot) ((slot + 1) & (SFLOW_FIFO_DEPTH - 1))
+static inline int
+sflow_fifo_enqueue (sflow_fifo_t *fifo, sflow_sample_t *sample)
+{
+ u32 curr_rx = clib_atomic_load_acq_n (&fifo->rx);
+ u32 curr_tx = fifo->tx; // clib_atomic_load_acq_n(&fifo->tx);
+ u32 next_tx = SFLOW_FIFO_NEXT (curr_tx);
+ if (next_tx == curr_rx)
+ return false; // full
+ memcpy (&fifo->samples[next_tx], sample, sizeof (*sample));
+ clib_atomic_store_rel_n (&fifo->tx, next_tx);
+ return true;
+}
+
+static inline int
+sflow_fifo_dequeue (sflow_fifo_t *fifo, sflow_sample_t *sample)
+{
+ u32 curr_rx = fifo->rx; // clib_atomic_load_acq_n(&fifo->rx);
+ u32 curr_tx = clib_atomic_load_acq_n (&fifo->tx);
+ if (curr_rx == curr_tx)
+ return false; // empty
+ memcpy (sample, &fifo->samples[curr_rx], sizeof (*sample));
+ u32 next_rx = SFLOW_FIFO_NEXT (curr_rx);
+ clib_atomic_store_rel_n (&fifo->rx, next_rx);
+ return true;
+}
+
+/* private to worker */
+typedef struct
+{
+ u32 smpN;
+ u32 skip;
+ u32 pool;
+ u32 seed;
+ u32 smpl;
+ u32 drop;
+ CLIB_CACHE_LINE_ALIGN_MARK (_fifo);
+ sflow_fifo_t fifo;
+} sflow_per_thread_data_t;
+
+typedef struct
+{
+ /* API message ID base */
+ u16 msg_id_base;
+
+ /* convenience */
+ vlib_main_t *vlib_main;
+ vnet_main_t *vnet_main;
+ ethernet_main_t *ethernet_main;
+
+ /* sampling state */
+ u32 samplingN;
+ u32 pollingS;
+ u32 headerB;
+ u32 total_threads;
+ sflow_per_interface_data_t *per_interface_data;
+ sflow_per_thread_data_t *per_thread_data;
+
+ /* psample channel (packet samples) */
+ SFLOWPS sflow_psample;
+ /* usersock channel (periodic counters) */
+ SFLOWUS sflow_usersock;
+#define SFLOW_NETLINK_USERSOCK_MULTICAST 29
+ /* dropmon channel (packet drops) */
+ // SFLOWDM sflow_dropmon;
+
+ /* sample-processing */
+ u32 now_mono_S;
+
+ /* running control */
+ int running;
+ u32 interfacesEnabled;
+
+ /* main-thread counters */
+ u32 psample_seq_ingress;
+ u32 psample_seq_egress;
+ u32 psample_send_drops;
+ u32 csample_send;
+ u32 csample_send_drops;
+ u32 unixsock_seq;
+#ifdef SFLOW_USE_VAPI
+ /* vapi query helper thread (transient) */
+ CLIB_CACHE_LINE_ALIGN_MARK (_vapi);
+ sflow_vapi_client_t vac;
+ int vapi_requests;
+#endif
+} sflow_main_t;
+
+extern sflow_main_t sflow_main;
+
+extern vlib_node_registration_t sflow_node;
+
+static inline u32
+sflow_next_random_skip (sflow_per_thread_data_t *sfwk)
+{
+ /* skip==1 means "take the next packet" so this
+ fn must never return 0 */
+ if (sfwk->smpN <= 1)
+ return 1;
+ u32 lim = (2 * sfwk->smpN) - 1;
+ return (random_u32 (&sfwk->seed) % lim) + 1;
+}
+
+#endif /* __included_sflow_h__ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */