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); +}