diff --git a/include/gatekeeper_rhhh.h b/include/gatekeeper_rhhh.h
new file mode 100644
index 000000000..04c27ac08
--- /dev/null
+++ b/include/gatekeeper_rhhh.h
@@ -0,0 +1,465 @@
+/*
+ * Gatekeeper - DoS protection system.
+ * Copyright (C) 2016 Digirati LTDA.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _GATEKEEPER_RHHH1D_H_
+#define _GATEKEEPER_RHHH1D_H_
+
+#include "space_saving.h"
+
+#ifndef DIMENSION
+#define DIMENSION 1
+#endif
+
+#ifndef NUM_V4_COUNTERS
+#define NUM_V4_COUNTERS 5
+#endif
+
+#ifndef NUM_V6_COUNTERS
+#define NUM_V6_COUNTERS 17
+#endif
+
+#if NUM_V4_COUNTERS == 5 /* IPv4 byte heirarchies. */
+/* Masks for IPv4 byte heirarchies. */
+uint32_t mask_v4[NUM_V4_COUNTERS] = {
+ 0xFFFFFFFFu, 0xFFFFFF00u, 0xFFFF0000u, 0xFF000000u, 0x00000000u
+};
+
+uint8_t leveleps_v4[NUM_V4_COUNTERS] = { 32, 24, 16, 8, 0 };
+
+#elif NUM_V4_COUNTERS == 33 /* IPv4 bit heirarchies. */
+/* Mask for IPv4 bit heirarchies. */
+uint32_t mask_v4[NUM_V4_COUNTERS] = {
+ 0xFFFFFFFFu << 0, 0xFFFFFFFFu << 1, 0xFFFFFFFFu << 2,
+ 0xFFFFFFFFu << 3, 0xFFFFFFFFu << 4, 0xFFFFFFFFu << 5,
+ 0xFFFFFFFFu << 6, 0xFFFFFFFFu << 7, 0xFFFFFFFFu << 8,
+ 0xFFFFFFFFu << 9, 0xFFFFFFFFu << 10, 0xFFFFFFFFu << 11,
+ 0xFFFFFFFFu << 12, 0xFFFFFFFFu << 13, 0xFFFFFFFFu << 14,
+ 0xFFFFFFFFu << 15, 0xFFFFFFFFu << 16, 0xFFFFFFFFu << 17,
+ 0xFFFFFFFFu << 18, 0xFFFFFFFFu << 19, 0xFFFFFFFFu << 20,
+ 0xFFFFFFFFu << 21, 0xFFFFFFFFu << 22, 0xFFFFFFFFu << 23,
+ 0xFFFFFFFFu << 24, 0xFFFFFFFFu << 25, 0xFFFFFFFFu << 26,
+ 0xFFFFFFFFu << 27, 0xFFFFFFFFu << 28, 0xFFFFFFFFu << 29,
+ 0xFFFFFFFFu << 30, 0xFFFFFFFFu << 31, 0x00000000u
+};
+
+uint8_t leveleps_v4[NUM_V4_COUNTERS] = {
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
+ 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+#endif /* IPv4 heirarchies */
+
+#if NUM_V6_COUNTERS == 17 /* IPv6 byte heirarchies. */
+/* Mask for IPv6 byte heirarchies. */
+uint8_t mask_v6[NUM_V6_COUNTERS][16] = {
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u}
+};
+
+uint8_t leveleps_v6[NUM_V6_COUNTERS] = { 64, 56, 48, 40, 32, 24, 16, 8, 0 };
+
+#elif NUM_V6_COUNTERS == 129 /* IPv6 bit heirarchies. */
+/* Mask for IPv6 bit heirarchies. */
+uint8_t mask_v6[NUM_V6_COUNTERS][16] = {
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0x80u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFEu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xFCu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xF8u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xF0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xE0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0xC0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0x80u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0x80u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFEu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xFCu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xF8u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xF0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xE0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0xC0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0x80u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFEu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xFCu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xF8u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xF0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xE0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0xC0u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0x80u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u},
+ {0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
+ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u}
+};
+
+uint8_t leveleps_v6[NUM_V6_COUNTERS] = {
+ 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47,
+ 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29,
+ 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
+ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+#endif /* IPv6 heirarchies */
+
+typedef struct heavyhitter {
+ struct ip_key key;
+
+ union {
+ /* Mask for IPv4 packets */
+ struct {
+ uint32_t src_mask;
+ uint32_t dst_mask;
+ } v4;
+
+ /* Mask for IPv6 packets */
+ struct {
+ uint8_t src_mask[16];
+ uint8_t dst_mask[16];
+ } v6;
+ } msk;
+
+ uint32_t upr_bnd;
+ uint32_t lwr_bnd;
+} HeavyHitter;
+
+typedef struct descendant {
+ struct ip_key key;
+ union {
+ /* Mask for IPv4 packet. */
+ struct {
+ uint32_t src_mask;
+ uint32_t dst_mask;
+ } v4;
+
+ /* Mask for IPv6 packet. */
+ struct {
+ uint8_t src_mask[16];
+ uint8_t dst_mask[16];
+ } v6;
+ } msk;
+} Descendant;
+
+double dblmax(double a, double b);
+
+double two_to_the_minus_k(int k);
+
+static int
+rhhh_init(unsigned int socket_id, uint16_t proto, double prob);
+
+void
+rhhh_deinit(uint16_t proto);
+
+static int
+rhhh_update(unsigned int socket_id, struct ip_key *key);
+
+static int
+setup_dblcounter_params(unsigned int socket_id, uint16_t proto,
+ int dblcounter_size, int dblcounter_id,
+ struct rte_hash_parameters *dblcounter_params);
+
+static
+struct rte_hash *
+create_dblcounter(unsigned int socket_id, uint16_t proto, int dblcounter_id,
+ int dblcounter_size);
+
+//static
+int
+rhhh1D_v4_output(double threshold, unsigned int socket_id);
+
+static int
+calcPred2D_v4(struct ip_key *key, uint32_t src_mask, uint32_t dst_mask);
+
+//static
+int
+rhhh2D_v4_output(double threshold, unsigned int socket_id);
+
+//static
+int
+rhhh1D_v6_output(double threshold, unsigned int socket_id);
+
+/*static int
+calcPred2D_v6(struct ip_key *key, uint32_t src_mask, uint32_t dst_mask);
+
+//static
+int
+rhhh2D_v6_output(double threshold, unsigned int socket_id);
+*/
+
+extern HeavyHitter *rhhh_output;
+extern int numhitters;
+
+#endif /* _GATEKEEPER_RHHH1D_H_ */
diff --git a/include/space_saving.h b/include/space_saving.h
index c432fde52..35f95f211 100755
--- a/include/space_saving.h
+++ b/include/space_saving.h
@@ -21,15 +21,38 @@
#define OVRFLOW 1000000
+#include
+
+#include
#include
+#include
#include "list.h"
-#include "gatekeeper_gk.h"
-#include "gatekeeper_net.h"
-#include "gatekeeper_flow.h"
+//#include "gatekeeper_gk.h"
+//#include "gatekeeper_net.h"
+//#include "gatekeeper_flow.h"
+
+#define DEFAULT_HASH_FUNC rte_jhash
-extern struct list_head bkt_head;
+extern struct list_head bkt_head_ip4;
+extern struct list_head bkt_head_ip6;
extern int streamlen;
+extern int mx;
+
+struct ip_key {
+ uint16_t proto;
+ union {
+ struct v4{
+ struct in_addr src;
+ struct in_addr dst;
+ } v4;
+
+ struct v6{
+ struct in6_addr src;
+ struct in6_addr dst;
+ } v6;
+ } k;
+};
/* Data structure for Counter bucket. */
struct counter_bucket
@@ -53,49 +76,41 @@ struct ip_data
{
int err;
int bkt_id;
- struct rte_flow *flow;
- struct counter_bucket *ct_bucket;
+ struct ip_key key;
+ struct counter_bucket ct_bucket;
};
-/* Set up parameters of a counter table. */
-static int
-setup_counter_params(unsigned int socket_id, int counter_id, uint16_t proto,
- int ht_size, struct rte_hash_parameters *ct_hash_params);
-
/*
* Create a counter table of size = 1.0/epsion.
* @epsilon is the error parameter for space saving algorithm.
*/
-//static
struct rte_hash *
create_counter_table(unsigned int socket_id, uint16_t proto, int counter_id,
- double epsilon);
+ int ht_size);
/* Destroy a counter table. */
void destroy_counter_table(uint16_t proto, int counter_id);
-/* Set up the parameters of a counter bucket. */
-static int
-setup_bucket_params(unsigned int socket_id, int bkt_id, int bkt_size,
- uint16_t proto, struct rte_hash_parameters *bkt_hash_params);
-
/*
* Create a counter bucket.
* Size of each bucket is set to 100 by default.
* TODO: Find a way to vary the size of a bucket to ensure
* optimum memory usage.
*/
-static int
-create_bucket(unsigned int socket_id, uint16_t proto, int bkt_id,
- struct counter_bucket *ct_bkt);
+struct rte_hash *
+create_bucket(unsigned int socket_id, uint16_t proto, int bkt_id);
/* Increment Counter Algorithm. */
static int
-increment_counter(unsigned int socket_id, uint16_t proto, struct ip_data *element);
+increment_counter(unsigned int socket_id, uint16_t proto, struct ip_data **element);
/* Space Saving algorithm. */
//static
-int space_saving(unsigned int socket_id, uint16_t proto, struct rte_flow *flow,
+int space_saving(unsigned int socket_id, uint16_t proto, struct ip_key *key,
struct rte_hash *ct_table);
-#endif /* _SPACE_SAVING_H */
\ No newline at end of file
+int SSEstLow(struct rte_hash *ct_table, struct ip_key *key);
+
+int SSEstUpp(struct rte_hash *ct_table, struct ip_key *key);
+
+#endif /* _SPACE_SAVING_H */
diff --git a/lib/rhhh.c b/lib/rhhh.c
new file mode 100644
index 000000000..636bd48ac
--- /dev/null
+++ b/lib/rhhh.c
@@ -0,0 +1,704 @@
+/*
+ * Gatekeeper - DoS protection system.
+ * Copyright (C) 2016 Digirati LTDA.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/*
+ * Implementation of RHHH algorithm in Gatekeeper.
+ *
+ * The script is based on reserch paper on Randomized Hierarchical Heavy Hitters
+ * algorithm by Ran Ben Basat, Gil Einziger, Roy Friedman, Marcelo C. Luizelli
+ * and Erez Waisbard. https://arxiv.org/pdf/1707.06778.pdf.
+ */
+
+#include
+#include
+#include
+
+#include
+
+#include "gatekeeper_rhhh.h"
+#include "space_saving.h"
+
+/* TODO 1: Implement RHHH algorithm for IPv6. */
+
+/* TODO 2: Test the code for correctness. */
+
+#ifndef VMULT
+#define VMULT 1
+#endif
+
+#if VMULT>1
+#define PROB
+#endif
+
+struct rte_hash *counter_ip4[NUM_V4_COUNTERS];
+struct rte_hash *counter_ip6[NUM_V6_COUNTERS];
+
+struct rte_ring *ip4_hhh;
+struct rte_ring *ip6_hhh;
+
+HeavyHitter *output_v4;
+HeavyHitter *output_v6;
+Descendant *Hp_table_v4;
+Descendant *Hp_table_v6;
+
+double ss_epsilon = 0.0001;
+int opspace;
+int hpspace;
+int numhit;
+int numdesc;
+
+#ifdef PROB
+double ignoreProb;
+double logIgnoreProb;
+double minusQuantity;
+int nrIgnore;
+#endif
+
+double dblmax(double a, double b)
+{
+ return (a >= b ? a : b);
+}
+
+double two_to_the_minus_k(int k)
+{
+ double ans = 1;
+ while (k > 0)
+ {
+ ans /= 2;
+ k--;
+ }
+ return ans;
+}
+
+static int
+rhhh_init(unsigned int socket_id, uint16_t proto, double prob)
+{
+ int ret;
+ int i;
+ srand(time(0));
+
+ #ifdef PROB
+ ignoreProb = 1.0 - prob;
+ logIgnoreProb = log(ignoreProb);
+ minusQuantity = log(RAND_MAX) / logIgnoreProb;
+ nrIgnore = log((double)rand()) / logIgnoreProb - minusQuantity;
+ #endif
+ if (proto == ETHER_TYPE_IPv4) {
+ for(i = 0; i < NUM_V4_COUNTERS; i++) {
+ counter_ip4[i] = create_counter_table(socket_id,
+ proto, i, max(ss_epsilon,
+ two_to_the_minus_k(leveleps_v4[i])));
+ if (counter_ip4[i] == NULL) {
+ ret = -1;
+ goto out;
+ }
+ }
+ } else if (proto == ETHER_TYPE_IPv6) {
+ for(i = 0; i < NUM_V6_COUNTERS; i++) {
+ counter_ip6[i] = create_counter_table(socket_id,
+ proto, i, max(ss_epsilon,
+ two_to_the_minus_k(leveleps_v6[i])));
+ if (counter_ip6[i] == NULL) {
+ ret = -1;
+ goto out;
+ }
+ }
+ } else {
+ ret = -1;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+void
+rhhh_deinit(uint16_t proto)
+{
+ int i;
+ if(proto == ETHER_TYPE_IPv4) {
+ for(i = 0; i < NUM_V4_COUNTERS; i++)
+ rte_hash_free(counter_ip4[i]);
+ } else if(proto == ETHER_TYPE_IPv6) {
+ for(i = 0; i < NUM_V6_COUNTERS; i++)
+ rte_hash_free(counter_ip6[i]);
+ }
+}
+
+static int
+rhhh_update(unsigned int socket_id, struct ip_key *key)
+{
+ int ret;
+
+ #ifdef PROB
+ if (nrIgnore--) return;
+ nrIgnore = log((double)rand()) / logIgnoreProb - minusQuantity;
+ #endif
+ if (key->proto == ETHER_TYPE_IPv4) {
+ short i = rand() % NUM_V4_COUNTERS;
+ #if DIMENSION == 1
+ key->k.v4.src.s_addr = key->k.v4.src.s_addr & mask_v4[i];
+ #else
+ int src_ptr = 0, dst_ptr = 0;
+ src_ptr = i % NUM_V4_COUNTERS;
+ dst_ptr = i / NUM_V4_COUNTERS;
+ key->k.v4.src.s_addr = key->k.v4.src.s_addr & mask_v4[src_ptr];
+ key->k.v4.src.s_addr = key->k.v4.src.s_addr & mask_v4[dst_ptr];
+ #endif
+ ret = space_saving(socket_id, key->proto,
+ key, counter_ip4[i]);
+
+ } else if (key->proto == ETHER_TYPE_IPv6) {
+ short i = rand() % NUM_V6_COUNTERS;
+ #if DIMENSION == 1
+ int j;
+ for(j = 0; j < 16; j++) {
+ uint8_t src_bits = key->k.v6.src.s6_addr[j];
+ src_bits = src_bits & mask_v6[i][j];
+ key->k.v6.src.s6_addr[j] = src_bits;
+ }
+ #else
+ int src_ptr = 0, dst_ptr = 0, j;
+ src_ptr = i % NUM_V6_COUNTERS;
+ dst_ptr = i / NUM_V6_COUNTERS;
+ for(j = 0; j < 16; j++) {
+ uint8_t src_bits = key->k.v6.src.s6_addr[j];
+ uint8_t dst_bits = key->k.v6.dst.s6_addr[j];
+ src_bits = src_bits & mask_v6[src_ptr][j];
+ dst_bits = dst_bits & mask_v6[dst_ptr][j];
+ key->k.v6.src.s6_addr[j] = src_bits;
+ key->k.v6.dst.s6_addr[j] = dst_bits;
+ }
+ #endif
+ ret = space_saving(socket_id, key->proto,
+ key, counter_ip6[i]);
+ } else
+ ret = -1;
+
+ return ret;
+}
+
+static int
+setup_dblcounter_params(unsigned int socket_id, uint16_t proto,
+ int dblcounter_size, int dblcounter_id,
+ struct rte_hash_parameters *dblcounter_params)
+{
+ int ret;
+ int key_len = proto == ETHER_TYPE_IPv4 ?
+ sizeof(struct in_addr) : sizeof(struct in6_addr);
+
+ dblcounter_params->name = NULL;
+ dblcounter_params->entries = dblcounter_size;
+ dblcounter_params->key_len = key_len;
+ dblcounter_params->hash_func = DEFAULT_HASH_FUNC;
+ dblcounter_params->hash_func_init_val = 0;
+ dblcounter_params->reserved = 0;
+
+ char dblcounter_name[64];
+ ret = snprintf(dblcounter_name, sizeof(dblcounter_name),
+ "Double_Counter_%d_%d", proto, dblcounter_id);
+ RTE_VERIFY(ret > 0 && ret < (int)sizeof(dblcounter_name));
+
+ dblcounter_params->name = dblcounter_name;
+ dblcounter_params->socket_id = socket_id;
+
+ return ret;
+}
+
+static
+struct rte_hash *
+create_dblcounter(unsigned int socket_id, uint16_t proto, int dblcounter_id,
+ int dblcounter_size)
+{
+ int ret;
+
+ int key_len = proto == ETHER_TYPE_IPv4 ?
+ 2 * sizeof(struct in_addr) : 2 * sizeof(struct in6_addr);
+
+ char dblcounter_name[64];
+ ret = snprintf(dblcounter_name, sizeof(dblcounter_name),
+ "Double_Counter_%d_%d", proto, dblcounter_id);
+ RTE_VERIFY(ret > 0 && ret < (int)sizeof(dblcounter_name));
+
+ struct rte_hash_parameters dblcounter_params = {
+ .name = dblcounter_name,
+ .entries = dblcounter_size,
+ .key_len = key_len,
+ .hash_func = DEFAULT_HASH_FUNC,
+ .hash_func_init_val = 0,
+ .reserved = 0,
+ .socket_id = socket_id,
+ };
+
+ if(proto == ETHER_TYPE_IPv4) {
+ struct rte_hash *dblcounter = rte_hash_create(&dblcounter_params);
+ if(dblcounter == NULL) {
+ RTE_LOG(ERR, HASH, "Double_counter_%d_%d cannot "
+ "be created!\n", proto, dblcounter_id);
+ ret = -1;
+ }
+ //free(dblcounter_params);
+ return dblcounter;
+ }
+
+ if(proto == ETHER_TYPE_IPv6) {
+ struct rte_hash *dblcounter = rte_hash_create(&dblcounter_params);
+ if(dblcounter == NULL) {
+ RTE_LOG(ERR, HASH, "Double_Counter_%d_%d cannot "
+ "be created!\n", proto, dblcounter_id);
+ ret = -1;
+ }
+ //free(dblcounter_params);
+ return dblcounter;
+ }
+
+ return NULL;
+}
+
+//static
+int
+rhhh1D_v4_output(double threshold, unsigned int socket_id)
+{
+ int ret;
+ //struct counter_bucket ct_bkt;
+ //struct ip_key key;
+ //struct ip_data element;
+ //uint32_t next = 0;
+ int src_ptr;
+ double SSepsval = 0.001;
+
+ int htsize = (((int)(1.0/SSepsval)) + 1) | 1;
+ struct rte_hash *hashtable = create_dblcounter(socket_id, ETHER_TYPE_IPv4, 0, htsize);
+
+#ifdef PROB
+ double adjustedThreshold =
+ (1 - ignoreProb) * (threshold / ((double)NUM_V4_COUNTERS));
+#else
+ double adjustedThreshold = threshold / ((double) NUM_V4_COUNTERS);
+#endif
+
+ numhit = 0;
+ int output_space = 2;
+
+ int i, j;
+
+ unsigned long long * tmp;
+
+ int d_cnt;
+ int z = 4;
+
+ output_v4 = (HeavyHitter *) calloc(sizeof(HeavyHitter), output_space);
+
+ for (i = 0; i < NUM_V4_COUNTERS; i++) {
+ for (j = (int)adjustedThreshold; j < streamlen; j++) {
+
+ struct counter_bucket *entry, *next;
+ src_ptr = i;
+ //dst_ptr = i % 5;
+ list_for_each_entry_safe(entry, next, &bkt_head_ip4, list) {
+ struct rte_hash *bkt_ip4 = entry->bkt.bkt_ip4;
+ struct ip_key * key;
+ struct ip_data *element;
+ uint32_t next = 0;
+ while(1) {
+ ret = rte_hash_iterate(bkt_ip4, (const void **)&key, (void **)&element,
+ &next);
+ if(ret < 0)
+ break;
+
+ int cnt = element->bkt_id;
+ if(cnt < adjustedThreshold)
+ continue;
+
+ //dblcount = calcPred2D(key, mask_v4[src_ptr],
+ // mask_v4[dst_ptr]);
+
+ uint64_t src = (key->k.v4.src.s_addr);
+ uint64_t src_key = (src << 32)|((uint64_t)i);
+
+ ret = rte_hash_lookup_data(hashtable,
+ (const void *)&src_key, (void **)&d_cnt);
+ if(ret < 0)
+ continue;
+
+ ret = rte_hash_del_key(hashtable, &src_key);
+ if(ret < 0)
+ goto out;
+
+ int freq;
+ #ifdef PROB
+ freq = (j-d_cnt)+(2*z*sqrt((1-ignoreProb)*2*j);
+ #else
+ freq = (j-d_cnt)+(2*z*sqrt(2*j));
+ #endif
+ if(freq >= adjustedThreshold) {
+ while(output_space <= numhit)
+ output_space *= 2;
+ output_v4 = (HeavyHitter *)
+ realloc (output_v4,
+ output_space*sizeof(HeavyHitter));
+ output_v4[numhit].key = *key;
+ output_v4[numhit].msk.v4.src_mask = i;
+ output_v4[numhit].upr_bnd = j;
+ output_v4[numhit].lwr_bnd =
+ j-element->err;
+ d_cnt = output_v4[numhit].lwr_bnd;
+ numhit++;
+ }
+
+ if(d_cnt > 0 && i+1 < NUM_V4_COUNTERS) {
+ uint64_t pkey = ((src&mask_v4[i+1]) <<32)|
+ (i+1);
+ ret = rte_hash_add_key_data(hashtable,
+ &pkey, (void **)&d_cnt);
+ if(ret < 0)
+ goto out;
+ }
+ }
+ }
+ }
+ }
+
+ rte_hash_free(hashtable);
+ output_v4 = (HeavyHitter *)realloc(output_v4, (numhit)*sizeof(HeavyHitter));
+
+ return ret;
+out:
+ RTE_LOG(ERR, HASH, "Heavy Hitter output could not be generated!\n");
+ ret = -1;
+
+}
+
+static int
+calcPred2D_v4(struct ip_key *key, uint32_t src_mask, uint32_t dst_mask)
+{
+ int ret;
+ int i, j, k, dblcount, src_msk_ptr, dst_msk_ptr, cntr;
+ numdesc = 0;
+ struct ip_key newIP;
+
+ for(i = 0; i < numhit; i++) {
+ uint32_t src = key->k.v4.src.s_addr;
+ uint32_t dst = key->k.v4.dst.s_addr;
+ uint32_t hhh_src = output_v4[i].key.k.v4.src.s_addr;
+ uint32_t hhh_dst = output_v4[i].key.k.v4.dst.s_addr;
+ uint32_t hhh_src_mask = mask_v4[output_v4[i].msk.v4.src_mask];
+ uint32_t hhh_dst_mask = mask_v4[output_v4[i].msk.v4.dst_mask];
+
+ if (
+ (src_mask & hhh_src_mask) == src_mask &&
+ (dst_mask & hhh_dst_mask) == dst_mask &&
+ (src & src_mask) == (hhh_src & src_mask) &&
+ (dst & dst_mask) == (hhh_dst & dst_mask)
+ ) {
+ j = 0;
+ for(k = 0; k < numdesc; k++) {
+ uint32_t Hp_src = Hp_table_v4[k].key.k.v4.src.s_addr;
+ uint32_t Hp_dst = Hp_table_v4[k].key.k.v4.dst.s_addr;
+ uint32_t Hp_src_mask =
+ mask_v4[Hp_table_v4[k].msk.v4.src_mask];
+ uint32_t Hp_dst_mask =
+ mask_v4[Hp_table_v4[k].msk.v4.dst_mask];
+ hhh_src = output_v4[k].key.k.v4.src.s_addr;
+ hhh_dst = output_v4[k].key.k.v4.dst.s_addr;
+ hhh_src_mask =
+ mask_v4[output_v4[k].msk.v4.src_mask];
+ hhh_dst_mask =
+ mask_v4[output_v4[k].msk.v4.dst_mask];
+
+ Hp_table_v4[j] = Hp_table_v4[k];
+ if (
+ (src_mask&Hp_src_mask != src_mask) ||
+ (dst_mask&Hp_dst_mask != dst_mask) ||
+ (Hp_src&hhh_src_mask != hhh_src&hhh_src_mask) ||
+ (Hp_dst & hhh_dst_mask != hhh_dst & hhh_dst_mask)
+ )
+ j++;
+ }
+ numdesc = j;
+ Hp_table_v4[numdesc].msk.v4.src_mask =
+ output_v4[i].msk.v4.src_mask;
+ Hp_table_v4[numdesc].msk.v4.dst_mask =
+ output_v4[i].msk.v4.dst_mask;
+ Hp_table_v4[numdesc].key = output_v4[i].key;
+ numdesc++;
+ while(numdesc >= hpspace)
+ hpspace *= 2;
+ Hp_table_v4 = (Descendant *) realloc(
+ Hp_table_v4, sizeof(Descendant) * hpspace);
+ }
+ }
+
+ dblcount = 0;
+ for(i = 0; i < numdesc; i++) {
+ dblcount += SSEstLow(counter_ip4[i], &Hp_table_v4[i].key);
+ }
+
+ for(i = 0; i < numdesc; i++) {
+ uint32_t Hp_src1 = Hp_table_v4[i].key.k.v4.src.s_addr;
+ uint32_t Hp_dst1 = Hp_table_v4[i].key.k.v4.dst.s_addr;
+ uint32_t Hp_src_mask1 = mask_v4[Hp_table_v4[i].msk.v4.src_mask];
+ uint32_t Hp_dst_mask1 = mask_v4[Hp_table_v4[i].msk.v4.dst_mask];
+ for(j = i + 1; j < numdesc; j++) {
+ uint32_t Hp_src2 = Hp_table_v4[j].key.k.v4.src.s_addr;
+ uint32_t Hp_dst2 = Hp_table_v4[j].key.k.v4.dst.s_addr;
+ uint32_t Hp_src_mask2 =
+ mask_v4[Hp_table_v4[j].msk.v4.src_mask];
+ uint32_t Hp_dst_mask2 =
+ mask_v4[Hp_table_v4[j].msk.v4.dst_mask];
+ uint32_t src_msk = Hp_src_mask1 & Hp_src_mask2;
+ uint32_t dst_msk = Hp_dst_mask1 & Hp_dst_mask2;
+ uint32_t src_or = Hp_src1 | Hp_src2;
+ uint32_t dst_or = Hp_dst1 | Hp_dst2;
+ uint32_t src_msk_or = Hp_src_mask1 | Hp_src_mask2;
+ uint32_t dst_msk_or = Hp_dst_mask1 | Hp_dst_mask2;
+
+ if (
+ (Hp_src1 & src_msk) != (Hp_src2 & src_msk) ||
+ (Hp_dst1 & dst_msk) != (Hp_dst2 & dst_msk)
+ ) {
+ /* There is no IP common to subnets i and j. */
+ continue;
+ }
+
+ newIP.proto = ETHER_TYPE_IPv4;
+ newIP.k.v4.src.s_addr = src_or;
+ newIP.k.v4.dst.s_addr = dst_or;
+
+ /* Compute the right mask for new IP. */
+ src_msk_ptr = 0;
+ while(mask_v4[src_msk_ptr] != src_msk_or) {
+ dst_msk_ptr = 0;
+ while(mask_v4[dst_msk_ptr] != dst_msk_or)
+ dst_msk_ptr++;
+ src_msk_ptr++;
+ }
+ assert( (mask_v4[src_msk_ptr] == src_msk_or) &&
+ (mask_v4[dst_msk_ptr] == dst_msk_or));
+
+ cntr = (src_msk_ptr * NUM_V4_COUNTERS) + dst_msk_ptr;
+ dblcount -= SSEstUpp(counter_ip4[cntr], &newIP);
+ }
+ }
+ return dblcount;
+}
+
+//static
+int
+rhhh2D_v4_output(double threshold, unsigned int socket_id)
+{
+ int ret;
+ int i, bkt_ptr, element_ptr, dblcount, src_ptr, dst_ptr;
+ int z = 4;
+ numhit = 0;;
+
+ struct counter_bucket* min_bkt = list_first_entry(&bkt_head_ip4,
+ struct counter_bucket, list);
+ int min_bkt_id = min_bkt->bkt_id;
+
+#ifdef PROB
+ double adjustedThreshold =
+ (1 - ignoreProb) * (threshold / ((double)NUM_V4_COUNTERS));
+#else
+ double adjustedThreshold = threshold / ((double) NUM_V4_COUNTERS);
+#endif
+
+ output_v4 = (HeavyHitter *) calloc(opspace, sizeof(HeavyHitter));
+ Hp_table_v4 = (Descendant *) calloc(hpspace, sizeof(Descendant));
+
+ for(i = 0; i < NUM_V4_COUNTERS; i++) {
+ struct counter_bucket *entry, *next;
+ src_ptr = i / 5;
+ dst_ptr = i % 5;
+ list_for_each_entry_safe(entry, next, &bkt_head_ip4, list) {
+ struct rte_hash *bkt_ip4 = entry->bkt.bkt_ip4;
+ struct ip_key * key;
+ struct ip_data *element;
+ uint32_t next = 0;
+ while(1) {
+ ret = rte_hash_iterate(bkt_ip4, (const void **)&key, (void **)&element,
+ &next);
+ if(ret < 0)
+ break;
+
+ int cnt = element->bkt_id;
+ if(cnt < adjustedThreshold)
+ continue;
+
+ dblcount = calcPred2D_v4(key, mask_v4[src_ptr],
+ mask_v4[dst_ptr]);
+
+ double freq;
+#ifdef PROB
+ freq = (cnt - dblcount) + (2 * z * sqrt(
+ (1 - ignoreProb) * 2 * dblcount);
+#else
+ freq = (cnt - dblcount) +
+ (2 * z * sqrt(2 * dblcount));
+#endif
+ if(freq >= adjustedThreshold) {
+ while(opspace <= numhit)
+ opspace *= 2;
+ output_v4 = (HeavyHitter *)realloc(output_v4,
+ opspace*sizeof(HeavyHitter));
+ output_v4[numhit].key = *key;
+ output_v4[numhit].msk.v4.src_mask = i;
+ output_v4[numhit].upr_bnd = cnt;
+ output_v4[numhit].lwr_bnd =
+ cnt - element->err;
+ numhit++;
+ }
+
+ }
+ }
+ }
+
+ free(Hp_table_v4);
+ return ret;
+}
+
+//static
+int
+rhhh1D_v6_output(double threshold, unsigned int socket_id)
+{
+ /* TODO : Implement 1D RHHH output function for IPV6. */
+ int ret;
+ //struct counter_bucket ct_bkt;
+ //struct ip_key key;
+ //struct ip_data element;
+ //uint32_t next = 0;
+ int src_ptr;
+ double SSepsval = 0.001;
+
+ int htsize = (((int)(1.0/SSepsval)) + 1) | 1;
+ struct rte_hash *hashtable = create_dblcounter(socket_id, ETHER_TYPE_IPv6, 0, htsize);
+
+#ifdef PROB
+ double adjustedThreshold =
+ (1 - ignoreProb) * (threshold / ((double)NUM_V6_COUNTERS));
+#else
+ double adjustedThreshold = threshold / ((double) NUM_V6_COUNTERS);
+#endif
+
+ numhit = 0;
+ int output_space = 2;
+
+ int i, j, k;
+
+ unsigned long long * tmp;
+
+ int d_cnt;
+ int z = 4;
+
+ output_v6 = (HeavyHitter *) calloc(sizeof(HeavyHitter), output_space);
+
+ for (i = 0; i < NUM_V6_COUNTERS; i++) {
+ for (j = (int)adjustedThreshold; j < streamlen; j++) {
+
+ struct counter_bucket *entry, *next;
+ src_ptr = i;
+ //dst_ptr = i % 5;
+ list_for_each_entry_safe(entry, next, &bkt_head_ip4, list) {
+ struct rte_hash *bkt_ip4 = entry->bkt.bkt_ip4;
+ struct ip_key *key;
+ struct ip_data *element;
+ uint32_t next = 0;
+ while(1) {
+ ret = rte_hash_iterate(bkt_ip4, (const void **)&key, (void **)&element,
+ &next);
+ if(ret < 0)
+ break;
+
+ int cnt = element->bkt_id;
+ if(cnt < adjustedThreshold)
+ continue;
+
+ //dblcount = calcPred1D(key, mask_v6[src_ptr],
+ // mask_v6[dst_ptr]);
+
+ uint16_t src[16], src_key[16];
+
+ for (k = 0; k < 16; k++) {
+ src[k] = (key->k.v6.src.s6_addr[k]);
+ src_key[k] = (src[k] << 8)|((uint16_t)i);
+ }
+
+ ret = rte_hash_lookup_data(hashtable,
+ (const void *)&src_key, (void **)&d_cnt);
+ if(ret < 0)
+ continue;
+
+ ret = rte_hash_del_key(hashtable, &src_key);
+ if(ret < 0)
+ goto out;
+
+ int freq;
+ #ifdef PROB
+ freq = (j-d_cnt)+(2*z*sqrt((1-ignoreProb)*2*j);
+ #else
+ freq = (j-d_cnt)+(2*z*sqrt(2*j));
+ #endif
+ if(freq >= adjustedThreshold) {
+ while(output_space <= numhit)
+ output_space *= 2;
+ output_v6 = (HeavyHitter *)
+ realloc (output_v6,
+ output_space*sizeof(HeavyHitter));
+ output_v6[numhit].key = *key;
+ int l;
+ for(l = 0; l < 16; l++)
+ output_v6[numhit].msk.v6.src_mask[l] = mask_v6[i][l];
+ output_v6[numhit].upr_bnd = j;
+ output_v6[numhit].lwr_bnd =
+ j-element->err;
+ d_cnt = output_v6[numhit].lwr_bnd;
+ numhit++;
+ }
+
+ if(d_cnt > 0 && i+1 < NUM_V6_COUNTERS) {
+ uint16_t pkey[NUM_V6_COUNTERS];
+ for(k = 0; k < 16; k++)
+ pkey[k] = ((src[k]&(uint16_t)mask_v6[i+1][k]) << 8)|
+ (i+1);
+ ret = rte_hash_add_key_data(hashtable,
+ &pkey, (void **)&d_cnt);
+ if(ret < 0)
+ goto out;
+ }
+ }
+ }
+ }
+ }
+
+ rte_hash_free(hashtable);
+ output_v6 = (HeavyHitter *)realloc(output_v6, (numhit)*sizeof(HeavyHitter));
+
+ return ret;
+out:
+ RTE_LOG(ERR, HASH, "Heavy Hitter output could not be generated!\n");
+ ret = -1;
+}
+
+//static
+/*int
+rhhh2D_v6_output(double threshold, unsigned int socket_id)
+{
+ // TODO : Implement 2D RHHH output function for IPV6.
+ int ret;
+ return ret;
+}*/
diff --git a/lib/space_saving.c b/lib/space_saving.c
index 956eada22..55c3cc95c 100755
--- a/lib/space_saving.c
+++ b/lib/space_saving.c
@@ -28,83 +28,60 @@
#include
#include
+#include
+
#include "space_saving.h"
-struct list_head bkt_head = LIST_HEAD_INIT(bkt_head);
+struct list_head bkt_head_ip4 = LIST_HEAD_INIT(bkt_head_ip4);
+struct list_head bkt_head_ip6 = LIST_HEAD_INIT(bkt_head_ip6);
int streamlen = 0;
+int mx = 0;
-static int
-setup_counter_params(unsigned int socket_id, int counter_id, uint16_t proto,
- int ht_size, struct rte_hash_parameters *ct_hash_params)
-{
- int ret;
- char ct_name[64];
- int key_len = proto == ETHER_TYPE_IPv4 ?
- sizeof(struct in_addr) : sizeof(struct in6_addr);
-
- ct_hash_params->name = NULL;
- ct_hash_params->entries = ht_size;
- ct_hash_params->key_len = key_len;
- ct_hash_params->hash_func = DEFAULT_HASH_FUNC;
- ct_hash_params->hash_func_init_val = 0;
- ct_hash_params->reserved = 0;
-
- ret = snprintf(ct_name, sizeof(ct_name), "counter_hash_%d_%d",
- proto, counter_id);
- RTE_VERIFY(ret > 0 && ret < (int)sizeof(ct_name));
-
- ct_hash_params->name = ct_name;
- ct_hash_params->socket_id = socket_id;
-
- return ret;
+int max(int a, int b);
+int max(int a, int b) {
+ return (a > b) ? a : b;
}
-//static
struct rte_hash *
create_counter_table(unsigned int socket_id, uint16_t proto, int counter_id,
- double epsilon)
+ int ht_size)
{
+
int ret;
- struct rte_hash_parameters *ct_hash_params = rte_malloc("hash_params",
- sizeof(*ct_hash_params), 0);
+ char ct_name[64];
+ ret = snprintf(ct_name, sizeof(ct_name), "counter_hash_%d_%d",
+ proto, counter_id);
+ RTE_VERIFY(ret > 0 && ret < (int)sizeof(ct_name));
- if (proto == ETHER_TYPE_IPv4) {
+ int key_len = proto == ETHER_TYPE_IPv4 ? 2 * sizeof(struct in_addr) : 2 * sizeof(struct in6_addr);
+
+ struct rte_hash_parameters ct_hash_params = {
+ .name = ct_name,
+ .entries = ht_size,
+ .key_len = key_len,
+ .hash_func = rte_jhash,
+ .hash_func_init_val = 0,
+ .reserved = 0,
+ .socket_id = socket_id,
+ };
+
+ if(proto == ETHER_TYPE_IPv4) {
/* Create IPv4 counter table. */
- ret = setup_counter_params(socket_id, counter_id,
- ETHER_TYPE_IPv4, (int)1.0/epsilon, ct_hash_params);
- if (ret < 0) {
- RTE_LOG(ERR, HASH, "Counter table parameters cannot "
- "be set\n");
- return NULL;
- }
- struct rte_hash *ct_table = rte_hash_create(ct_hash_params);
+ struct rte_hash *ct_table = rte_hash_create(&ct_hash_params);
if (ct_table == NULL) {
- RTE_LOG(ERR, HASH, "Counter table %d_%d cannot be "
+ RTE_LOG(ERR, HASH,"Counter table %d_%d cannot be "
"created\n", proto, counter_id);
- ret = -1;
}
- free(ct_hash_params);
return ct_table;
-
} else if (proto == ETHER_TYPE_IPv6) {
/* Create IPv6 counter table. */
- ret = setup_counter_params(socket_id, counter_id,
- ETHER_TYPE_IPv6, (int)1.0/epsilon, ct_hash_params);
- if (ret < 0) {
- RTE_LOG(ERR, HASH, "Counter table parameters cannot "
- "be set\n");
- return NULL;
- }
- struct rte_hash *ct_table = rte_hash_create(ct_hash_params);
+ struct rte_hash *ct_table = rte_hash_create(&ct_hash_params);
if (ct_table == NULL) {
RTE_LOG(ERR, HASH, "Counter table %d_%d cannot be "
"created\n", proto, counter_id);
- ret = -1;
}
- free(ct_hash_params);
return ct_table;
}
-
RTE_LOG(ERR, HASH, "Unsupported Protocol\n");
return NULL;
}
@@ -126,223 +103,231 @@ destroy_counter_table(uint16_t proto, int counter_id)
rte_free(ct_table);
}
-static int
-setup_bucket_params(unsigned int socket_id, int bkt_id, int bkt_size,
- uint16_t proto, struct rte_hash_parameters *bkt_hash_params)
+struct rte_hash *
+create_bucket(unsigned int socket_id, uint16_t proto, int bkt_id)
{
+ //printf("Socket id = %d, proto = %d, bkt_id = %d\n", socket_id, proto, bkt_id);
int ret;
char bkt_name[64];
- int key_len = proto == ETHER_TYPE_IPv4 ?
- sizeof(struct in_addr) : sizeof(struct in6_addr);
-
- bkt_hash_params->name = NULL;
- bkt_hash_params->entries = bkt_size;
- bkt_hash_params->key_len = key_len;
- bkt_hash_params->hash_func = DEFAULT_HASH_FUNC;
- bkt_hash_params->hash_func_init_val = 0;
- bkt_hash_params->reserved = 0;
-
- ret = snprintf(bkt_name, sizeof(bkt_name), "Bucket_number_%d_%d",
+ ret = snprintf(bkt_name, sizeof(bkt_name), "Bucket_hash_%d_%d",
proto, bkt_id);
- RTE_VERIFY(ret > 0 && ret < (int)sizeof(bkt_name));
+ RTE_VERIFY(ret > 0 && ret < (int)sizeof(bkt_name));
- bkt_hash_params->name = bkt_name;
- bkt_hash_params->socket_id = socket_id;
-
- return ret;
-}
-
-static int
-create_bucket(unsigned int socket_id, uint16_t proto, int bkt_id,
- struct counter_bucket *ct_bkt)
-{
- int ret = 0;
- /* TODO: Add support for configuring bucket size. */
- int bkt_size = 100;
- ct_bkt->bkt_id = bkt_id;
- INIT_LIST_HEAD(&ct_bkt->list);
- struct rte_hash_parameters *bkt_hash_params = rte_malloc("hash_params",
- sizeof(bkt_hash_params), 0);
+ int key_len = proto == ETHER_TYPE_IPv4 ? 2 * sizeof(struct in_addr) : 2 * sizeof(struct in6_addr);
- if (proto == ETHER_TYPE_IPv4) {
- ct_bkt->proto = ETHER_TYPE_IPv4;
- ret = setup_bucket_params(socket_id, bkt_id, bkt_size,
- ETHER_TYPE_IPv4, bkt_hash_params);
- if (ret < 0) {
- RTE_LOG(ERR, HASH, "The bucket parameters "
- "can't be set\n");
- goto out;
- }
- ct_bkt->bkt.bkt_ip4 = rte_hash_create(bkt_hash_params);
- if (ct_bkt->bkt.bkt_ip4 == NULL) {
- RTE_LOG(ERR, HASH, "Bucket number %d could not be "
- "created\n",bkt_id);
- ret = -1;
- goto out;
+ struct rte_hash_parameters bkt_hash_params = {
+ .name = bkt_name,
+ .entries = 2048,
+ .key_len = key_len,
+ .hash_func = rte_jhash,
+ .hash_func_init_val = 0,
+ .reserved = 0,
+ .socket_id = socket_id,
+ };
+
+ if(proto == ETHER_TYPE_IPv4) {
+ /* Create IPv4 counter table. */
+ struct rte_hash *ct_bkt = rte_hash_create(&bkt_hash_params);
+ if (ct_bkt == NULL) {
+ RTE_LOG(ERR, HASH,"Counter bucket %d_%d cannot be "
+ "created\n", proto, bkt_id);
+ printf("%d\n", streamlen);
}
-
+ return ct_bkt;
} else if (proto == ETHER_TYPE_IPv6) {
- ct_bkt->proto = ETHER_TYPE_IPv6;
- ret = setup_bucket_params(socket_id, bkt_id, bkt_size,
- ETHER_TYPE_IPv6, bkt_hash_params);
- if (ret < 0) {
- RTE_LOG(ERR, HASH, "The bucket parameters "
- "can't be set\n");
- goto out;
- }
-
- ct_bkt->bkt.bkt_ip6 = rte_hash_create(bkt_hash_params);
- if (ct_bkt->bkt.bkt_ip6 == NULL) {
- RTE_LOG(ERR, HASH, "Bucket number %d could not be "
- "created\n",bkt_id);
- ret = -1;
- goto out;
+ /* Create IPv6 counter table. */
+ struct rte_hash *ct_bkt = rte_hash_create(&bkt_hash_params);
+ if (ct_bkt == NULL) {
+ RTE_LOG(ERR, HASH, "Counter bucket %d_%d cannot be "
+ "created\n", proto, bkt_id);
+ printf("%d\n", streamlen);
}
+ return ct_bkt;
}
-out:
- free(bkt_hash_params);
- return ret;
+ RTE_LOG(ERR, HASH, "Unsupported Protocol\n");
+ return NULL;
}
+
static int
-increment_counter(unsigned int socket_id, uint16_t proto, struct ip_data *element)
+increment_counter(unsigned int socket_id, uint16_t proto, struct ip_data **element1)
{
+ //
int ret;
+ struct ip_data *element = *element1;
element->bkt_id++;
+
+ mx = max(mx, element->bkt_id);
- struct counter_bucket *cur_bkt = element->ct_bucket;
- struct counter_bucket *nxt_bkt = list_first_entry(
- &element->ct_bucket->list, struct counter_bucket, list);
+ if(streamlen == 100000) {
+ printf("MAx = %d %u\n", mx, sizeof(struct ip_data));
+ }
+ //printf("Incrementing counter for src = %u, dst = %u\n", element->key.k.v4.src.s_addr, element->key.k.v4.dst.s_addr);
- if (proto == ETHER_TYPE_IPv4)
- ret = rte_hash_del_key(cur_bkt->bkt.bkt_ip4, element->flow);
- else if (proto == ETHER_TYPE_IPv6)
- ret = rte_hash_del_key(cur_bkt->bkt.bkt_ip6, element->flow);
- else
- ret = -1;
- if (ret < 0)
- return ret;
+ struct counter_bucket *cur_bkt = &element->ct_bucket;
+ struct counter_bucket *nxt_bkt = list_first_entry(
+ &element->ct_bucket.list, struct counter_bucket, list);
+ //printf("Curr bkt_id = %d Nxt bkt id = %d\n", cur_bkt->bkt_id, nxt_bkt->bkt_id);
- if ((nxt_bkt != NULL) || (element->bkt_id == nxt_bkt->bkt_id)) {
- element->ct_bucket = nxt_bkt;
+ if(element->bkt_id > 1) {
+ // Min bkt_id > 1.
+ //printf("Key exists\n");
if (proto == ETHER_TYPE_IPv4)
- ret = rte_hash_add_key_data(nxt_bkt->bkt.bkt_ip4,
- element->flow, element);
+ ret = rte_hash_del_key(cur_bkt->bkt.bkt_ip4, &element->key.k.v4);
else if (proto == ETHER_TYPE_IPv6)
- ret = rte_hash_add_key_data(nxt_bkt->bkt.bkt_ip6,
- element->flow, element);
+ ret = rte_hash_del_key(cur_bkt->bkt.bkt_ip6, &element->key.k.v6);
else
ret = -1;
if (ret < 0)
- return ret;
-
- } else {
- struct counter_bucket *bkt_new = (struct counter_bucket *)
- rte_malloc("new_bucket", sizeof(*bkt_new), 0);
- ret = create_bucket(socket_id, proto, element->bkt_id, bkt_new);
- if (ret < 0)
- return ret;
-
- element->ct_bucket = bkt_new;
-
+ return ret;
+ }
+
+ if ((nxt_bkt->bkt_id != 0) && (element->bkt_id == nxt_bkt->bkt_id)) {
+ //printf("Bucket exists\n");
+ element->ct_bucket = *nxt_bkt;
if (proto == ETHER_TYPE_IPv4)
- ret = rte_hash_add_key_data(bkt_new->bkt.bkt_ip4,
- element->flow, element);
+ ret = rte_hash_add_key_data(element->ct_bucket.bkt.bkt_ip4,
+ &element->key.k.v4, element);
else if (proto == ETHER_TYPE_IPv6)
- ret = rte_hash_add_key_data(bkt_new->bkt.bkt_ip6,
- element->flow, element);
+ ret = rte_hash_add_key_data(element->ct_bucket.bkt.bkt_ip6,
+ &element->key.k.v6, element);
else
ret = -1;
if (ret < 0)
return ret;
- list_add(&element->ct_bucket->list, &cur_bkt->list);
+ } else {
+ //printf("Bucket doesn't exist\n");
+ element->ct_bucket.proto = proto;
+ element->ct_bucket.bkt_id = element->bkt_id;
+ INIT_LIST_HEAD(&element->ct_bucket.list);
+
+ char bkt_name[64];
+ ret = snprintf(bkt_name, sizeof(bkt_name), "Bucket_hash_%d_%d",
+ proto, element->bkt_id);
+ struct rte_hash *ct_bkt = rte_hash_find_existing(bkt_name);
+
+ if(proto == ETHER_TYPE_IPv4) {
+ //bkt_new->bkt.bkt_ip4 = create_bucket(socket_id, proto, element->bkt_id);
+ if(ct_bkt != NULL)
+ element->ct_bucket.bkt.bkt_ip4 = ct_bkt;
+ else
+ element->ct_bucket.bkt.bkt_ip4 = create_bucket(socket_id, proto, element->bkt_id);
+ if(element->ct_bucket.bkt.bkt_ip4 == NULL)
+ return -1;
+ ret = rte_hash_add_key_data(element->ct_bucket.bkt.bkt_ip4,
+ &element->key.k.v4, element);
+ } else if(proto == ETHER_TYPE_IPv6) {
+ //bkt_new->bkt.bkt_ip4 = create_bucket(socket_id, proto, element->bkt_id);
+ if(ct_bkt != NULL)
+ element->ct_bucket.bkt.bkt_ip6 = ct_bkt;
+ else
+ element->ct_bucket.bkt.bkt_ip6 = create_bucket(socket_id, proto, element->bkt_id);
+ if(element->ct_bucket.bkt.bkt_ip6 == NULL)
+ return -1;
+ ret = rte_hash_add_key_data(element->ct_bucket.bkt.bkt_ip6,
+ &element->key.k.v6, element);
+ } else {
+ RTE_LOG(ERR, HASH, "Unsupported protocol\n");
+ return -1;
+ }
+ list_add(&element->ct_bucket.list, &cur_bkt->list);
+
}
-
- struct ip_flow key = { 0 };
- struct ip_data data = { 0 };
- if (proto == ETHER_TYPE_IPv4)
- ret = rte_hash_iterate(cur_bkt->bkt.bkt_ip4,
- (const void **)&key, (void **)&data, 0);
- else if (proto == ETHER_TYPE_IPv6)
- ret = rte_hash_iterate(cur_bkt->bkt.bkt_ip6,
- (const void **)&key, (void **)&data, 0);
- else
- ret = -1;
- if (ret == -ENOENT) {
- list_del(&cur_bkt->list);
- free(cur_bkt);
+
+ void *key, *data;
+ uint32_t next = 0;
+ if(cur_bkt->bkt_id > 1) {
+ //printf("Cleaning Up\n");
+ //printf("%d \n",cur_bkt->bkt_id);
+ if (proto == ETHER_TYPE_IPv4) {
+ struct rte_hash *bkt_ip4 = cur_bkt->bkt.bkt_ip4;
+ if(bkt_ip4 != NULL)
+ ret = rte_hash_iterate(bkt_ip4,
+ (const void **)&key, (void **)&data, &next);
+ } else if (proto == ETHER_TYPE_IPv6) {
+ struct rte_hash *bkt_ip6 = cur_bkt->bkt.bkt_ip6;
+ if(bkt_ip6 != NULL)
+ ret = rte_hash_iterate(bkt_ip6,
+ (const void **)&key, (void **)&data, &next);
+ } else
+ ret = -1;
+ if (ret == -ENOENT) {
+ //printf("Deleting\n");
+ list_del(&cur_bkt->list);
+ free(cur_bkt);
+ }
}
return ret;
}
-//static
int
-space_saving(unsigned int socket_id, uint16_t proto, struct rte_flow *flow,
+space_saving(unsigned int socket_id, uint16_t proto, struct ip_key *key,
struct rte_hash *ct_table)
{
+
int ret;
streamlen++;
-
// Check if flow is monitored.
- struct ip_data *element = (struct ip_data *)rte_malloc("element",
- sizeof(*element), 0);
- ret = rte_hash_lookup_data(ct_table, flow, (void **)element);
+ //struct ip_flow key = { 0 };
+ struct ip_data chk;// = (struct ip_data *)malloc(sizeof(struct ip_data));
+ struct ip_data *element = (struct ip_data *)malloc(sizeof(struct ip_data));
+
+ //key.proto = flow->proto;
+ //key.f = flow->f;
+
+ //printf("Src = %u Dst = %u\n", key->k.v4.src.s_addr, key->k.v4.dst.s_addr);
+ if(proto == ETHER_TYPE_IPv4)
+ ret = rte_hash_lookup_data(ct_table, (const void *)&key->k.v4, (void **)&chk);
+ else if(proto == ETHER_TYPE_IPv6)
+ ret = rte_hash_lookup_data(ct_table, (const void *)&key->k.v6, (void **)&chk);
+ else {
+ RTE_LOG(ERR, HASH, "Unsupported Protocol!\n");
+ return -1;
+ }
+ //printf("Src = %d Dst = %d Ret = %d Bkt = %d\n", chk.key.k.v4.src, chk.key.k.v4.dst, ret, chk.bkt_id);
if (ret == -EINVAL) {
RTE_LOG(ERR, HASH, "Invalid Parameters!\n");
return ret;
- } else if (ret == 0) {
+ } else if (ret >= 0) {
// If flow is monitored, increment its bucket id.
- increment_counter(socket_id, proto, element);
-
+ //printf("Bkt id = %d, Err = %d\n", chk.bkt_id, chk.err);
+ increment_counter(socket_id, proto, &chk);
+ //printf("Flow monitored\n");
+
} else if (ret == -ENOENT) {
// Flow is not monitored.
- if (streamlen < OVRFLOW) {
- struct counter_bucket *ct_bkt = list_first_entry(
- &bkt_head, struct counter_bucket, list);
- if (ct_bkt->bkt_id > 1) {
- ret = create_bucket(socket_id, proto, 1,
- ct_bkt);
- if (ret < 0)
- return ret;
- }
-
- element->err = 0;
- element->bkt_id = 1;
- element->flow = flow;
- element->ct_bucket = ct_bkt;
-
- if (proto == ETHER_TYPE_IPv4)
- ret = rte_hash_add_key_data(
- ct_bkt->bkt.bkt_ip4, element->flow,
- element);
- else if (proto == ETHER_TYPE_IPv6)
- ret = rte_hash_add_key_data(
- ct_bkt->bkt.bkt_ip6, element->flow,
- element);
- else
- ret = -1;
- if (ret < 0)
- return ret;
-
- list_add(&element->ct_bucket->list, &bkt_head);
-
+ //printf("Flow not monitored\n");
+ struct counter_bucket *ct_bkt;
+ if(proto == ETHER_TYPE_IPv4)
+ ct_bkt = list_first_entry(&bkt_head_ip4, struct counter_bucket, list);
+ else if(proto == ETHER_TYPE_IPv6)
+ ct_bkt = list_first_entry(&bkt_head_ip6, struct counter_bucket, list);
+ else {
+ RTE_LOG(ERR, HASH, "Unsupported Protocol!\n");
+ return -1;
+ }
+ //streamlen = 1e6 + 19;
+ if(streamlen < OVRFLOW) {
+ element->err = 0;
+ element->bkt_id = 0;
+ //element->src = key->k.v4.src.s_addr,
+ //element->dst = key->k.v4.dst.s_addr,
+ element->key = *key;
+ element->ct_bucket = *ct_bkt;
} else {
- struct counter_bucket *ct_bkt = list_first_entry(
- &bkt_head, struct counter_bucket, list);
- struct ip_flow *key = (struct ip_flow *) rte_malloc
- ("key", sizeof(*key), 0);
+ struct ip_key key; //= (struct ip_flow *) rte_malloc
+ //("key", sizeof(*key), 0);
uint32_t next = 0;
-
if (proto == ETHER_TYPE_IPv4)
ret = rte_hash_iterate(ct_bkt->bkt.bkt_ip4,
- (const void **)key, (void *)element,
+ (const void **)&key.k.v4, (void **)&element,
&next);
else if (proto == ETHER_TYPE_IPv6)
ret = rte_hash_iterate(ct_bkt->bkt.bkt_ip6,
- (const void **)key, (void *)element,
+ (const void **)&key.k.v6, (void **)&element,
&next);
if (ret == -EINVAL) {
RTE_LOG(ERR, HASH, "Invalid parameters!\n");
@@ -351,15 +336,44 @@ space_saving(unsigned int socket_id, uint16_t proto, struct rte_flow *flow,
RTE_LOG(ERR, HASH, "Counter bucket empty!\n");
return ret;
} else if (ret == 0) {
-
element->err = element->bkt_id;
- element->flow = flow;
- ret = increment_counter(socket_id, proto,
- element);
- if (ret < 0)
- return ret;
+ element->key = key;
+ //element->src = key->k.v4.src;
+ //element->dst = key->k.v4.dst;
}
- }
+ }
+ ret = increment_counter(socket_id, proto, &element);
+ if (ret < 0)
+ return ret;
+ if(proto == ETHER_TYPE_IPv4)
+ ret = rte_hash_add_key_data(ct_table, &element->key.k.v4, element);
+ else if(proto == ETHER_TYPE_IPv6)
+ ret = rte_hash_add_key_data(ct_table, &element->key.k.v6, element);
+ if(ret < 0)
+ return ret;
+ //printf("Element src = %d, dst = %d\n", element->key.k.v4.src, element->key.k.v4.dst);
}
return ret;
}
+
+int SSEstUpp(struct rte_hash *ct_table, struct ip_key *key)
+{
+ int ret;
+ struct ip_data element;
+
+ ret = rte_hash_lookup_data(ct_table, (void *)&key, (void **)&element);
+ if(ret < 0)
+ return 0;
+ return element.bkt_id;
+}
+
+int SSEstLow(struct rte_hash *ct_table, struct ip_key *key)
+{
+ int ret;
+ struct ip_data element;
+
+ ret = rte_hash_lookup_data(ct_table, (void *)&key, (void **)&element);
+ if(ret < 0)
+ return 0;
+ return (element.bkt_id - element.err);
+}