├── README.md ├── cpp ├── README.md ├── Robustness_Experiments │ ├── README.md │ ├── robustness.cpp │ ├── robustness_kchance.cpp │ └── robustness_rate.cpp ├── Simulation_Experiments │ ├── README.md │ ├── analysis │ │ ├── parameter.py │ │ ├── sw_map │ │ └── swlog_handler.py │ ├── sim │ │ └── tracegen.py │ ├── sketch │ │ ├── BOBHash32.cpp │ │ ├── BOBHash32.h │ │ ├── EMSFD.h │ │ ├── Makefile │ │ ├── cm.cpp │ │ ├── cm.h │ │ ├── cu.cpp │ │ ├── cu.h │ │ ├── hcu.cpp │ │ ├── hcu.h │ │ ├── main.cpp │ │ ├── minheap.cpp │ │ ├── minheap.h │ │ ├── sketch.h │ │ ├── utils.cpp │ │ └── utils.h │ └── topology │ │ ├── fattree.py │ │ ├── fattree4.json │ │ └── parameter.py └── SuMax_Experiments │ ├── README.md │ ├── delay_distribution │ ├── BOBHash32.h │ ├── EMFSD.h │ ├── Sketch.h │ ├── compute_wmre.sh │ ├── delay_chi2_wmre_vs_memory.cpp │ ├── delay_distribution_wmre_with_topk.cpp │ ├── delay_mixed_wmre_vs_memory.cpp │ ├── delay_union_wmre_vs_memory.cpp │ ├── distribution.h │ └── param.h │ ├── flowsize │ ├── BOBHash32.h │ ├── EMFSD.h │ ├── Sketch.h │ ├── card_dist_ent_vs_memory.cpp │ ├── distribution.h │ ├── flowsize_ARE_vs_memory.cpp │ ├── flowsize_estimation.sh │ └── param.h │ ├── last_arrival-time │ ├── BOBHash32.h │ ├── Interval.h │ ├── compute_last_arrival-time.sh │ ├── last_arrival.cpp │ ├── packet.h │ └── param.h │ └── max_inter-arrival │ ├── BOBHash32.h │ ├── Interval.h │ ├── Interval_old.h │ ├── compute_inter-arrival.sh │ ├── max_interval_vs_memory.cpp │ ├── max_interval_vs_topk.cpp │ ├── packet.h │ └── param.h ├── mininet ├── README.md ├── client │ ├── client_flowsize │ │ ├── Makefile │ │ ├── aggregator.h │ │ ├── config.sh │ │ ├── distri.txt │ │ ├── header.h │ │ ├── host.h │ │ ├── receiver.h │ │ ├── sender.h │ │ └── traffic.cpp │ ├── client_interval │ │ ├── Makefile │ │ ├── aggregator.h │ │ ├── config.sh │ │ ├── header.h │ │ ├── host.h │ │ ├── receiver.h │ │ ├── sender.h │ │ └── traffic.cpp │ └── client_simple │ │ ├── Makefile │ │ ├── aggregator.h │ │ ├── config.sh │ │ ├── header.h │ │ ├── host.h │ │ ├── receiver.h │ │ ├── sender.h │ │ ├── traffic.config │ │ └── traffic.cpp └── switch │ ├── README.md │ ├── include │ ├── headers.p4 │ └── parsers.p4 │ ├── p4src_maximum │ ├── ecmp.p4 │ ├── ecmp_priority.p4 │ └── p4app.json │ ├── p4src_simple │ ├── ecmp.p4 │ ├── headers.p4 │ ├── iface_moniter.py │ ├── iface_moniter.sh │ ├── parsers.p4 │ └── routing_controller.py │ ├── p4src_sum │ ├── ecmp.p4 │ ├── ecmp_priority.p4 │ └── p4app.json │ └── scripts │ ├── error.py │ ├── log_generator.py │ ├── monitor.py │ ├── routing_controller.py │ ├── simple_receiver.py │ ├── simple_sender.py │ └── visor.py ├── testbed ├── README.md ├── Tofino_maximum │ ├── README.md │ ├── ggs.txt │ ├── includes │ │ └── header_and_parser.p4 │ ├── timeSF.p4 │ └── timeSF.py ├── Tofino_sum │ ├── README.md │ ├── flowSF.p4 │ ├── flowSF.py │ ├── ggs.txt │ └── includes │ │ └── header_and_parser.p4 └── analyzer │ ├── README.md │ ├── analyzer_INT.cpp │ └── analyzer_LG.cpp └── utils └── utils.py /README.md: -------------------------------------------------------------------------------- 1 | # LightGuardian 2 | 3 | ## Introduction 4 | Network traffic measurement is central to successful network operations, especially for today’s hyper-scale networks. Although existing works have made great contributions, they fail to achieve full-visibility, low overhead, and robustness simultaneously. We design LightGuardian to meet these three criteria. Our key innovation is a (small) constant-sized data structure, called sketchlet, which can be embedded in packet headers. Specifically, we design a novel SuMax sketch to accurately capture flow-level information. SuMax can be divided into sketchlets, which are carried in-band by passing packets to the end-hosts for aggregation, reconstruction, and analysis. We have fully implemented a LightGuardian prototype on a testbed with 10 programmable switches and 8 end-hosts in a FatTree topology, and conduct extensive experiments and evaluations. Experimental results show that LightGuardian can obtain per-flow per-hop flow-level information within 1.0~1.5 seconds with consistently low overhead, using only 0.07% total bandwidth capacity of the network. We believe LightGuardian is the first system to collect per-flow per-hop information for all flows in the network with negligible overhead. 5 | 6 | ## About this Repo 7 | - `cpp`: contains the codes implemented on CPU platform. We evaluate the performance of our SuMax sketch and LightGuardian's robustness on CPU platform. 8 | - `mininet` contains the codes implemented on Mininet. We evaluate LightGuardian’s performance in locating blackholes, loops, and abnormal jitters through Mininet case studies. 9 | - `testbed` contains the codes related to our testbed. We have fully implemented our SuMax on a Tofino-40GbE switch, and implemented the three key functions on the endhosts (sending packets, receiving packets, reconstruction and performing analysis). 10 | - `utils`: miscellaneous functions. 11 | 12 | 13 | -------------------------------------------------------------------------------- /cpp/README.md: -------------------------------------------------------------------------------- 1 | ## File Descriptions 2 | 3 | - ``Robustness_Experiments`` contains the codes to confirm LightGuardian's robustness. 4 | - ``Simulation_Experiments`` contains the codes to simulate the behavirous of LightGuardian. 5 | - ``SuMax_Experiments`` contains the codes to evaluate the performance of our SuMax sketch. 6 | 7 | -------------------------------------------------------------------------------- /cpp/Robustness_Experiments/README.md: -------------------------------------------------------------------------------- 1 | ## File Description 2 | 3 | * ```robustness.cpp``` simulates the transimission and reconstruction procedure when some end-hosts break down. We use random selection as the sketchlet selection strategy. 4 | * ```robustness_kchance.cpp``` simulates the transimission and reconstruction procedure when some end-hosts break down. We use k+chance selection as the sketchlets selection strategy. 5 | * ```robustness_rate.cpp``` calculates *the probability that all sketches can be reconstructed* and *the percentage of sketches that can be fully reconstructed* as the number of the broken end-hosts changes. 6 | 7 | ## Usage 8 | 9 | We describe the inputs to the three programs as follows. 10 | 11 | * ```robustness.cpp``` 12 | * \# sketchlets. 13 | * \# broken end-hosts. 14 | * A random seed. 15 | * ```robustness_kchance.cpp``` 16 | * \# sketchlets. 17 | * A parameter *k*,which refers to the program using *k+chance* selection algorithm. 18 | * \# the broken end-hosts. 19 | * A random seed. 20 | * ```robustness_rate.cpp``` 21 | * \# sketchlets. 22 | * \# broken end-hosts. 23 | 24 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/README.md: -------------------------------------------------------------------------------- 1 | ## File Description 2 | - `topology`: Generate json config file for mininet simulation with specific topology. 3 | - `sketch`: A `C++` based sketch algorithm benchmark, loading datasets generated by mininet or direct simulation, and test the accuracy of sketches on these traces. 4 | - `analysis`: Several helper functions to analyze log files generated by mininet. 5 | - `sim`: Direct simulation in Python without mininet. 6 | 7 | ## Usages 8 | There are four main usages. 9 | 10 | 1. Generate topology for mininet simulation. 11 | - In `topology` folder, modify `parameter.py` to change some parameters. 12 | - Type `python3 fattree.py > $(output_file)` to generate json config file for mininet, where `$(output_file)` is the name of output file. 13 | 2. Convert mininet log files into traces for sketch benchmark. 14 | - In `analysis` folder, modify `parameter.py` to change some parameters. 15 | - Modify `swlog_hanlder.py` and use `handle_swlog()` and `create_meta()` methods. 16 | - Run `python3 swlog_handler.py` to generate traces for sketch benchmark. 17 | 3. Perform simulations in C++ directly and generate traces. 18 | - In `sim` folder, modify parameters in `tracegen.py`. 19 | - Run `python3 tracegen.py` to generate traces for sketch benchmark. 20 | 4. Test the accuracy of sketches on traces. 21 | - In `sketch` folder, type `make` to build. 22 | - Change parameters of sketches and type of the test in `main()` funciton. 23 | - Run it by `./benchmark`. 24 | 25 | ## Requirements 26 | - Python3 27 | - g++ -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/analysis/parameter.py: -------------------------------------------------------------------------------- 1 | num_switch = 20 # number of switches 2 | num_eth = 5 # number of ports 3 | swmap_file = './sw_map' # map file of switch names (lsr to wrx) 4 | swlog_dir = '../sim/switch_log_loop/' # path to switch logs 5 | swlog_iface_dir = './iface_log/' 6 | trace_dir = '../trace/interval/' # path to generated traces 7 | meta_file = '../sim/meta.log' 8 | output_suffix = '_interval_10k.dat' -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/analysis/sw_map: -------------------------------------------------------------------------------- 1 | 0 s9 2 | 1 s8 3 | 2 s3 4 | 3 s2 5 | 4 s1 6 | 5 s10 7 | 6 s7 8 | 7 s6 9 | 8 s5 10 | 9 s4 -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/BOBHash32.cpp: -------------------------------------------------------------------------------- 1 | #include "BOBHash32.h" 2 | 3 | BOBHash32::BOBHash32() 4 | { 5 | this->prime32Num = 0; 6 | } 7 | 8 | BOBHash32::BOBHash32(uint32_t prime32Num) 9 | { 10 | this->prime32Num = prime32Num; 11 | } 12 | 13 | void BOBHash32::initialize(uint32_t prime32Num) 14 | { 15 | this->prime32Num = prime32Num; 16 | } 17 | 18 | uint32_t BOBHash32::run(const char * str, uint32_t len) 19 | { 20 | //register ub4 a,b,c,len; 21 | uint32_t a,b,c; 22 | // uint32_t initval = 0; 23 | /* Set up the internal state */ 24 | //len = length; 25 | a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ 26 | c = prime32[this->prime32Num]; /* the previous hash value */ 27 | 28 | /*---------------------------------------- handle most of the key */ 29 | while (len >= 12) 30 | { 31 | a += (str[0] +((uint32_t)str[1]<<8) +((uint32_t)str[2]<<16) +((uint32_t)str[3]<<24)); 32 | b += (str[4] +((uint32_t)str[5]<<8) +((uint32_t)str[6]<<16) +((uint32_t)str[7]<<24)); 33 | c += (str[8] +((uint32_t)str[9]<<8) +((uint32_t)str[10]<<16)+((uint32_t)str[11]<<24)); 34 | mix(a,b,c); 35 | str += 12; len -= 12; 36 | } 37 | 38 | /*------------------------------------- handle the last 11 bytes */ 39 | c += len; 40 | switch(len) /* all the case statements fall through */ 41 | { 42 | case 11: c+=((uint32_t)str[10]<<24); 43 | // fall through 44 | case 10: c+=((uint32_t)str[9]<<16); 45 | // fall through 46 | case 9 : c+=((uint32_t)str[8]<<8); 47 | /* the first byte of c is reserved for the length */ 48 | // fall through 49 | case 8 : b+=((uint32_t)str[7]<<24); 50 | // fall through 51 | case 7 : b+=((uint32_t)str[6]<<16); 52 | // fall through 53 | case 6 : b+=((uint32_t)str[5]<<8); 54 | // fall through 55 | case 5 : b+=str[4]; 56 | // fall through 57 | case 4 : a+=((uint32_t)str[3]<<24); 58 | // fall through 59 | case 3 : a+=((uint32_t)str[2]<<16); 60 | // fall through 61 | case 2 : a+=((uint32_t)str[1]<<8); 62 | // fall through 63 | case 1 : a+=str[0]; 64 | /* case 0: nothing left to add */ 65 | } 66 | mix(a,b,c); 67 | /*-------------------------------------------- report the result */ 68 | return c; 69 | } 70 | 71 | BOBHash32::~BOBHash32() 72 | { 73 | 74 | } 75 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/Makefile: -------------------------------------------------------------------------------- 1 | OBJECT = main.o cm.o cu.o hcu.o minheap.o BOBHash32.o utils.o 2 | INCLUDE = ./include 3 | LIBRARY = ./lib 4 | GCC = g++ 5 | CPP_FLAGS = -O2 -std=c++11 6 | 7 | benchmark : $(OBJECT) 8 | g++ -o benchmark $(OBJECT) -lboost_program_options $(CPP_FLAGS) 9 | main.o : main.cpp 10 | g++ -c main.cpp -I$(INCLUDE) $(CPP_FLAGS) 11 | cm.o : cm.cpp cm.h sketch.h 12 | g++ -c cm.cpp -I$(INCLUDE) $(CPP_FLAGS) 13 | cu.o : cu.cpp cu.h sketch.h 14 | g++ -c cu.cpp -I$(INCLUDE) $(CPP_FLAGS) 15 | hcu.o : hcu.cpp hcu.h sketch.h 16 | g++ -c hcu.cpp -I$(INCLUDE) $(CPP_FLAGS) 17 | minheap.o : minheap.cpp minheap.h sketch.h 18 | g++ -c minheap.cpp -I$(INCLUDE) $(CPP_FLAGS) 19 | BOBHash32.o : BOBHash32.cpp BOBHash32.h 20 | g++ -c BOBHash32.cpp -I$(INCLUDE) $(CPP_FLAGS) 21 | utils.o : utils.cpp utils.h 22 | g++ -c utils.cpp $(CPP_FLAGS) 23 | clean : 24 | find . -name "*.o" | xargs rm -f 25 | rm benchmark 26 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/cm.cpp: -------------------------------------------------------------------------------- 1 | #include "cm.h" 2 | #include "utils.h" 3 | #include "EMSFD.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | CMSketch::CMSketch(int size, int num_hash) : 10 | size(size), num_hash(num_hash) 11 | { 12 | sprintf(name, "CMSketch"); 13 | 14 | if (size <= 0 || num_hash <= 0) 15 | { 16 | panic("SIZE & NUM_HASH must be POSITIVE integers."); 17 | } 18 | cnt = new int[size]; 19 | fp = new int[size]; 20 | hash = new BOBHash32[num_hash]; 21 | 22 | row_size = size / num_hash; 23 | } 24 | 25 | CMSketch::~CMSketch() 26 | { 27 | if (cnt) 28 | delete [] cnt; 29 | if (fp) 30 | delete [] fp; 31 | if (hash) 32 | delete [] hash; 33 | } 34 | 35 | void 36 | CMSketch::init() 37 | { 38 | memset(cnt, 0, size * sizeof(int)); 39 | memset(fp, 0, size * sizeof(int)); 40 | 41 | for (int i = 0; i < num_hash; ++i) 42 | { 43 | hash[i].initialize(rand() % MAX_PRIME32); 44 | } 45 | } 46 | 47 | void 48 | CMSketch::status() 49 | { 50 | printf("bucket: %d hash: %d\n", size, num_hash); 51 | } 52 | 53 | void 54 | CMSketch::insert(int x, int v) 55 | { 56 | int i = 0, base = 0; 57 | 58 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 59 | { 60 | int pos = hash[i].run((char*)&x, sizeof(int)) % row_size + base; 61 | cnt[pos] += v; 62 | } 63 | } 64 | 65 | int 66 | CMSketch::query_freq(int v) 67 | { 68 | int ans = INT_MAX; 69 | int i = 0, base = 0; 70 | 71 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 72 | { 73 | int pos = hash[i].run((char*)&v, sizeof(int)) % row_size + base; 74 | ans = min(ans, cnt[pos]); 75 | } 76 | 77 | return ans; 78 | } 79 | 80 | vector 81 | CMSketch::query_heavyhitter(int threshold) 82 | { 83 | vector tmp, ans; 84 | 85 | tmp = hp.topk(hp.get_maxsize()); 86 | 87 | for (int i = 0; i < tmp.size(); ++i) 88 | { 89 | printf("%d %d\n", tmp[i].first, tmp[i].second); 90 | } 91 | 92 | int sz = tmp.size(); 93 | for (int i = 0; i < sz; ++i) 94 | { 95 | if (tmp[i].first < threshold) break; 96 | ans.push_back(tmp[i]); 97 | } 98 | 99 | return ans; 100 | } 101 | 102 | vector 103 | CMSketch::query_topk(int k) 104 | { 105 | return hp.topk(k); 106 | } 107 | 108 | void 109 | CMSketch::query_distribution(vector& ans) 110 | { 111 | if (num_hash != 1) 112 | { 113 | printf("The answer may be wrong because NUM_HASH is not equal to 1.\n"); 114 | } 115 | 116 | uint32_t *tmp_cnt; 117 | tmp_cnt = new uint32_t[size]; 118 | 119 | for (int i = 0; i < size; ++i) 120 | tmp_cnt[i] = cnt[i]; 121 | 122 | EMFSD *em_fsd_algo; 123 | em_fsd_algo = new EMFSD(); 124 | em_fsd_algo->set_counters(size, tmp_cnt); 125 | 126 | for (int i = 0; i < 10; ++i) 127 | { 128 | printf("epoch %d\n", i); 129 | em_fsd_algo->next_epoch(); 130 | } 131 | 132 | delete [] tmp_cnt; 133 | 134 | ans = em_fsd_algo->ns; 135 | } 136 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/cm.h: -------------------------------------------------------------------------------- 1 | #ifndef CMS_HEADER 2 | #define CMS_HEADER 3 | 4 | #include "sketch.h" 5 | #include "minheap.h" 6 | #include "BOBHash32.h" 7 | 8 | class CMSketch : public Sketch 9 | { 10 | private: 11 | int size, num_hash, row_size; 12 | 13 | int *cnt, *fp; 14 | BOBHash32 *hash; 15 | 16 | MinHeap hp; 17 | 18 | public: 19 | CMSketch(int size, int num_hash); 20 | ~CMSketch(); 21 | void init(); 22 | void insert(int x, int v); 23 | int query_freq(int v); 24 | vector query_heavyhitter(int threshold); 25 | vector query_topk(int k); 26 | void status(); 27 | void query_distribution(vector& ans); 28 | }; 29 | 30 | #endif -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/cu.cpp: -------------------------------------------------------------------------------- 1 | #include "cu.h" 2 | #include "utils.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | CUSketch::CUSketch(int size, int num_hash) : 9 | size(size), num_hash(num_hash) 10 | { 11 | sprintf(name, "CUSketch"); 12 | 13 | if (size <= 0 || num_hash <= 0) 14 | { 15 | panic("SIZE & NUM_HASH must be POSITIVE integers."); 16 | } 17 | cnt = new int[size]; 18 | fp = new int[size]; 19 | hash = new BOBHash32[num_hash]; 20 | 21 | row_size = size / num_hash; 22 | } 23 | 24 | CUSketch::~CUSketch() 25 | { 26 | if (cnt) 27 | delete [] cnt; 28 | if (fp) 29 | delete [] fp; 30 | if (hash) 31 | delete [] hash; 32 | } 33 | 34 | void 35 | CUSketch::init() 36 | { 37 | memset(cnt, 0, size * sizeof(int)); 38 | memset(fp, 0, size * sizeof(int)); 39 | 40 | for (int i = 0; i < num_hash; ++i) 41 | { 42 | hash[i].initialize(rand() % MAX_PRIME32); 43 | } 44 | } 45 | 46 | void 47 | CUSketch::status() 48 | { 49 | printf("bucket: %d hash: %d\n", size, num_hash); 50 | } 51 | 52 | void 53 | CUSketch::insert(int x, int v) 54 | { 55 | while (v) 56 | { 57 | int minus = v; 58 | 59 | int minp = INT_MAX, secp = INT_MAX; 60 | int i = 0, base = 0; 61 | int sav_pos[10]; 62 | 63 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 64 | { 65 | int pos = hash[i].run((char*)&x, sizeof(int)) % row_size + base; 66 | sav_pos[i] = pos; 67 | minp = min(minp, cnt[pos]); 68 | } 69 | 70 | for (i = 0; i < num_hash; ++i) 71 | { 72 | int pos = sav_pos[i]; 73 | if (cnt[pos] != minp) 74 | secp = min(secp, cnt[pos]); 75 | } 76 | 77 | minus = min(minus, secp - minp); 78 | 79 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 80 | { 81 | int pos = sav_pos[i]; 82 | // int pos = hash[i].run((char*)&v, sizeof(int)) % row_size + base; 83 | if (cnt[pos] == minp) 84 | cnt[pos] += minus; 85 | } 86 | 87 | v -= minus; 88 | } 89 | } 90 | 91 | int 92 | CUSketch::query_freq(int v) 93 | { 94 | int ans = INT_MAX; 95 | int i = 0, base = 0; 96 | 97 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 98 | { 99 | int pos = hash[i].run((char*)&v, sizeof(int)) % row_size + base; 100 | ans = min(ans, cnt[pos]); 101 | } 102 | 103 | return ans; 104 | } 105 | 106 | CUSketch* 107 | CUSketch::merge(CUSketch *q) 108 | { 109 | if (size != q->size || num_hash != q->num_hash) 110 | { 111 | printf("error! size must be equal.\n"); 112 | return NULL; 113 | } 114 | 115 | CUSketch * mrg = new CUSketch(size, num_hash); 116 | mrg->init(); 117 | 118 | int base, i; 119 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 120 | { 121 | for (int j = 0; j < row_size; ++j) 122 | { 123 | int pos = base + j; 124 | mrg->cnt[pos] = cnt[pos] + q->cnt[pos]; 125 | } 126 | } 127 | 128 | return mrg; 129 | } 130 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/cu.h: -------------------------------------------------------------------------------- 1 | #ifndef CUS_HEADER 2 | #define CUS_HEADER 3 | 4 | #include "sketch.h" 5 | #include "BOBHash32.h" 6 | 7 | class CUSketch : public Sketch 8 | { 9 | private: 10 | int size, num_hash, row_size; 11 | 12 | int *cnt, *fp; 13 | BOBHash32 *hash; 14 | 15 | public: 16 | CUSketch(int size, int num_hash); 17 | ~CUSketch(); 18 | void init(); 19 | void insert(int x, int v); 20 | int query_freq(int v); 21 | void status(); 22 | CUSketch* merge(CUSketch *q); 23 | }; 24 | 25 | #endif -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/hcu.cpp: -------------------------------------------------------------------------------- 1 | #include "hcu.h" 2 | #include "utils.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | HCUSketch::HCUSketch(int size, int num_hash) : 9 | size(size), num_hash(num_hash) 10 | { 11 | sprintf(name, "Half CUSketch"); 12 | 13 | if (size <= 0 || num_hash <= 0) 14 | { 15 | panic("SIZE & NUM_HASH must be POSITIVE integers."); 16 | } 17 | cnt = new int[size]; 18 | fp = new int[size]; 19 | prev = new LL[size]; 20 | hash = new BOBHash32[num_hash]; 21 | 22 | row_size = size / num_hash; 23 | } 24 | 25 | HCUSketch::~HCUSketch() 26 | { 27 | if (cnt) 28 | delete [] cnt; 29 | if (fp) 30 | delete [] fp; 31 | if (prev) 32 | delete [] prev; 33 | if (hash) 34 | delete [] hash; 35 | } 36 | 37 | void 38 | HCUSketch::init() 39 | { 40 | memset(cnt, 0, size * sizeof(int)); 41 | memset(fp, 0, size * sizeof(int)); 42 | memset(prev, 0, size * sizeof(LL)); 43 | 44 | for (int i = 0; i < num_hash; ++i) 45 | { 46 | hash[i].initialize(rand() % MAX_PRIME32); 47 | } 48 | } 49 | 50 | void 51 | HCUSketch::status() 52 | { 53 | printf("bucket: %d hash: %d\n", size, num_hash); 54 | } 55 | 56 | void 57 | HCUSketch::insert(int x, int v) 58 | { 59 | while (v) 60 | { 61 | int minus = v; 62 | 63 | int minp = INT_MAX, secp = INT_MAX; 64 | int i = 0, base = 0; 65 | int sav_pos[10]; 66 | 67 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 68 | { 69 | int pos = hash[i].run((char*)&x, sizeof(int)) % row_size + base; 70 | sav_pos[i] = pos; 71 | if (minp >= cnt[pos]) 72 | { 73 | minp = cnt[pos]; 74 | } 75 | else 76 | { 77 | secp = min(secp, cnt[pos]); 78 | minus = min(minus, secp - minp); 79 | } 80 | } 81 | 82 | minp = INT_MAX; 83 | for (i = 0; i < num_hash; ++i) 84 | { 85 | int pos = sav_pos[i]; 86 | minp = min(minp, cnt[pos]); 87 | if (cnt[pos] == minp) 88 | cnt[pos] += minus; 89 | } 90 | 91 | v -= minus; 92 | } 93 | } 94 | 95 | void 96 | HCUSketch::insert_interval(int v, LL now) 97 | { 98 | int i = 0, base = 0; 99 | 100 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 101 | { 102 | int pos = hash[i].run((char*)&v, sizeof(int)) % row_size + base; 103 | if (prev[pos] != 0 && now - prev[pos] < 10000000) 104 | { 105 | LL interval = (now - prev[pos]) / 10; 106 | if (interval > INT_MAX) 107 | { 108 | printf("help!\n"); 109 | } 110 | cnt[pos] = max(cnt[pos], int(interval)); 111 | // printf("in! %d(%lld %lld) ", cnt[pos], prev[pos], now); 112 | } 113 | if(now == 0) 114 | printf("!!!!!!!!!!!!!\n"); 115 | prev[pos] = now; 116 | } 117 | // printf("\n"); 118 | } 119 | 120 | int 121 | HCUSketch::query_freq(int v) 122 | { 123 | int ans = INT_MAX; 124 | int i = 0, base = 0; 125 | 126 | for (i = 0, base = 0; i < num_hash; ++i, base += row_size) 127 | { 128 | int pos = hash[i].run((char*)&v, sizeof(int)) % row_size + base; 129 | ans = min(ans, cnt[pos]); 130 | } 131 | 132 | return ans; 133 | } 134 | 135 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/hcu.h: -------------------------------------------------------------------------------- 1 | #ifndef HCUS_HEADER 2 | #define HCUS_HEADER 3 | 4 | #include "sketch.h" 5 | #include "BOBHash32.h" 6 | 7 | class HCUSketch : public Sketch 8 | { 9 | private: 10 | int size, num_hash, row_size; 11 | 12 | int *cnt, *fp; 13 | LL *prev; 14 | BOBHash32 *hash; 15 | 16 | public: 17 | HCUSketch(int size, int num_hash); 18 | ~HCUSketch(); 19 | void init(); 20 | void insert(int x, int v); 21 | void insert_interval(int x, LL now); 22 | int query_freq(int v); 23 | void status(); 24 | }; 25 | 26 | #endif -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/minheap.cpp: -------------------------------------------------------------------------------- 1 | #include "minheap.h" 2 | #include "utils.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using std::map; 10 | 11 | bool 12 | MinHeap::insert(int fp, int v) 13 | { 14 | // existence 15 | bool flag = false; 16 | { 17 | set::iterator it = rdx.lower_bound(mp(fp, 0)); 18 | if (it != rdx.end() && (*it).ft == fp) 19 | { 20 | int old_v = (*it).sc; 21 | rdx.erase(it); 22 | data.erase(data.lower_bound(mp(old_v, fp))); 23 | flag = true; 24 | } 25 | } 26 | 27 | 28 | if (data.size() < max_size) 29 | { 30 | rdx.insert(mp(fp, v)); 31 | data.insert(mp(v, fp)); 32 | return true; 33 | } 34 | 35 | set::iterator min_ele = data.begin(); 36 | if((*min_ele).ft < v) 37 | { 38 | int old_fp = (*min_ele).sc; 39 | int old_v = (*min_ele).ft; 40 | rdx.erase(rdx.lower_bound(mp(old_fp, old_v))); 41 | data.erase(min_ele); 42 | 43 | rdx.insert(mp(fp, v)); 44 | data.insert(mp(v, fp)); 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | 51 | vector 52 | MinHeap::topk(int k) 53 | { 54 | set::iterator it = data.end(); 55 | vector ans; 56 | 57 | if (data.size() < k) 58 | k = (int)data.size(); 59 | while (k--) 60 | { 61 | it--; 62 | ans.push_back((*it)); 63 | } 64 | // reverse(ans.begin(), ans.end()); 65 | 66 | return ans; 67 | } -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/minheap.h: -------------------------------------------------------------------------------- 1 | #ifndef MINHEAP_HEADER 2 | #define MINHEAP_HEADER 3 | 4 | #include "sketch.h" 5 | #include 6 | using std::set; 7 | 8 | class MinHeap 9 | { 10 | private: 11 | set data, rdx; 12 | int max_size; 13 | public: 14 | MinHeap() { max_size = 300; }; 15 | MinHeap(int x) : max_size(x) {}; 16 | ~MinHeap() {}; 17 | int size() { return data.size(); } 18 | void init() { data.clear(); rdx.clear(); } 19 | void set_maxsize(int x) { max_size = x; } 20 | int get_maxsize() { return max_size; } 21 | PII top() { return data.size()==0? mp(0, 0):(*data.begin()); } 22 | bool insert(int fp, int v); // try to push, return 1 if success. 23 | vector topk(int k); // return topk of the heap 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/sketch.h: -------------------------------------------------------------------------------- 1 | #ifndef IMPL_HEADER 2 | #define IMPL_HEADER 3 | 4 | #include 5 | #include 6 | using std::vector; 7 | using std::pair; 8 | 9 | typedef pair PII; 10 | typedef long long LL; 11 | #define mp std::make_pair 12 | #define ft first 13 | #define sc second 14 | 15 | class Sketch 16 | { 17 | public: 18 | char name[100]; 19 | 20 | virtual void init() 21 | { 22 | std::cout << "No init function." << std::endl; 23 | } 24 | 25 | virtual void insert(int x, int v) 26 | { 27 | std::cout << "No insert function." << std::endl; 28 | } 29 | 30 | virtual void insert_interval(int x, LL now) 31 | { 32 | std::cout << "No insert function." << std::endl; 33 | } 34 | 35 | virtual void remove() 36 | { 37 | std::cout << "No remove function." << std::endl; 38 | } 39 | 40 | virtual bool query_exist(int x) 41 | { 42 | std::cout << "No query function." << std::endl; 43 | } 44 | 45 | virtual int query_max(int x) 46 | { 47 | std::cout << "No query function." << std::endl; 48 | } 49 | 50 | virtual int query_freq(int x) 51 | { 52 | std::cout << "No query function." << std::endl; 53 | } 54 | 55 | virtual vector query_topk(int k) 56 | { 57 | std::cout << "No query function." << std::endl; 58 | } 59 | 60 | virtual vector query_heavyhitter(int threshold) 61 | { 62 | std::cout << "No query function." << std::endl; 63 | } 64 | 65 | virtual void query_distribution(vector& ans) 66 | { 67 | std::cout << "No query function." << std::endl; 68 | } 69 | 70 | virtual void status() 71 | { 72 | std::cout << "No status function." << std::endl; 73 | } 74 | }; 75 | 76 | #endif -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utils.h" 5 | 6 | bool verbose = false; 7 | bool debug = false; 8 | 9 | void 10 | dprintf(char *format, ...) 11 | { 12 | if (debug) 13 | { 14 | va_list ap; 15 | va_start(ap, format); 16 | vfprintf(stdout, format, ap); 17 | va_end(ap); 18 | fflush(stdout); 19 | } 20 | } 21 | 22 | void 23 | vprintf(char *format, ...) 24 | { 25 | if (verbose) 26 | { 27 | va_list ap; 28 | va_start(ap, format); 29 | vfprintf(stdout, format, ap); 30 | va_end(ap); 31 | fflush(stdout); 32 | } 33 | } 34 | 35 | void 36 | panic(char *format, ...) 37 | { 38 | va_list ap; 39 | va_start(ap, format); 40 | vfprintf(stdout, format, ap); 41 | va_end(ap); 42 | fflush(stdout); 43 | exit(-1); 44 | } 45 | 46 | 47 | Timer::Timer() 48 | { 49 | Start(); 50 | } 51 | 52 | Timer::~Timer() 53 | { 54 | 55 | } 56 | 57 | void 58 | Timer::Start() 59 | { 60 | gettimeofday(&st_time, NULL); 61 | ls_time.tv_sec = st_time.tv_sec; 62 | ls_time.tv_usec = st_time.tv_usec; 63 | stopped = false; 64 | } 65 | 66 | double 67 | Timer::StepTime() 68 | { 69 | struct timeval tmp; 70 | gettimeofday(&tmp, NULL); 71 | double res = (tmp.tv_sec - ls_time.tv_sec) + (double)(tmp.tv_usec - ls_time.tv_usec) / 1000000; 72 | ls_time.tv_sec = tmp.tv_sec; 73 | ls_time.tv_usec = tmp.tv_usec; 74 | return res; 75 | } 76 | 77 | double 78 | Timer::Finish(bool force_update) 79 | { 80 | if (!stopped || force_update) 81 | { 82 | stopped = true; 83 | gettimeofday(&ed_time, NULL); 84 | } 85 | return this -> WholeTime(); 86 | } 87 | 88 | double 89 | Timer::WholeTime() 90 | { 91 | double res = (ed_time.tv_sec - st_time.tv_sec) + (double)(ed_time.tv_usec - st_time.tv_usec) / 1000000; 92 | return res; 93 | } -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/sketch/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_HEADER 2 | #define UTILS_HEADER 3 | 4 | #include 5 | 6 | extern bool verbose; 7 | extern bool debug; 8 | 9 | #define ASSERT(condition) \ 10 | if (!(condition)) { \ 11 | fprintf(stderr, "Assertion failed: line %d, file \"%s\"\n", \ 12 | __LINE__, __FILE__); \ 13 | fflush(stderr); \ 14 | exit(-1); \ 15 | } 16 | 17 | void dprintf(char *format, ...); 18 | void vprintf(char *format, ...); 19 | void panic(char *format, ...); 20 | 21 | class Timer 22 | { 23 | public: 24 | Timer(); 25 | ~Timer(); 26 | 27 | void Start(); 28 | double StepTime(); // return step process time (sec) 29 | double Finish(bool force_update=false); 30 | double WholeTime(); 31 | 32 | private: 33 | struct timeval st_time, ed_time, ls_time; 34 | bool stopped; 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/topology/fattree.py: -------------------------------------------------------------------------------- 1 | from parameter import * 2 | import math 3 | import os 4 | import sys 5 | import json 6 | 7 | # Parameters for Fat-tree 8 | num_pod = 4 9 | bandwidth = 2 10 | 11 | 12 | 13 | obj = {} 14 | obj['program'] = para_program 15 | obj['switch'] = para_switch 16 | obj['compiler'] = para_compiler 17 | obj['options'] = para_options 18 | obj['switch_cli'] = para_switch_cli 19 | obj['cli'] = True 20 | obj['pcap_dump'] = False 21 | obj['enable_log'] = False 22 | 23 | topo_module = {'file_path': '', \ 24 | 'module_name': 'p4utils.mininetlib.apptopo', \ 25 | 'object_name': 'AppTopoStrategies'} 26 | obj['topo_module'] = topo_module 27 | 28 | obj['controller_module'] = None 29 | 30 | topodb_module = {'file_path': '', \ 31 | 'module_name': 'p4utils.utils.topology', \ 32 | 'object_name': 'Topology'} 33 | obj['topodb_module'] = topodb_module 34 | 35 | mininet_module = {'file_path': '', \ 36 | 'module_name': 'p4utils.mininetlib.p4net', \ 37 | 'object_name': 'P4Mininet'} 38 | obj['mininet_module'] = mininet_module 39 | 40 | # build network topology 41 | topology = {} 42 | topology['assignment_strategy'] = 'l3' 43 | 44 | # Link - 3 levels 45 | # ------------------------ 46 | # k/2 * k/2 core 47 | # k/2 * k aggregation 48 | # k/2 * k edge 49 | # k/2 * k * k/2 servers 50 | 51 | links = [] 52 | half_pod = num_pod//2 53 | core_base = 1 54 | agg_base = core_base + half_pod**2 55 | edge_base = agg_base + half_pod*num_pod 56 | 57 | num_switch = edge_base + half_pod*num_pod - core_base 58 | num_host = (half_pod**2) * num_pod 59 | 60 | # core -- aggregation 61 | for i in range(half_pod) : 62 | for j in range(half_pod) : 63 | core_id = 's' + str(i * half_pod + j + core_base) 64 | for k in range(num_pod) : 65 | agg_id = 's' + str(k * half_pod + i + agg_base) 66 | links.append([core_id, agg_id, {'bw' : bandwidth}]) 67 | 68 | # aggregation -- edge 69 | for i in range(num_pod) : 70 | for j in range(half_pod) : 71 | agg_id = 's' + str(i * half_pod + j + agg_base) 72 | for k in range(half_pod) : 73 | edge_id = 's' + str(i * half_pod + k + edge_base) 74 | links.append([agg_id, edge_id, {'bw' : bandwidth}]) 75 | 76 | # edge -- servers 77 | for i in range(num_pod) : 78 | for j in range(half_pod) : 79 | edge_id = 's' + str(i * half_pod + j + edge_base) 80 | for k in range(half_pod) : 81 | sev_id = 'h' + str((i*half_pod+j)*half_pod + k + 1) 82 | links.append([edge_id, sev_id, {'bw' : bandwidth}]) 83 | 84 | topology['links'] = links 85 | 86 | hosts = {} 87 | for i in range(num_host): 88 | host_id = 'h' + str(i+1) 89 | hosts[host_id] = {} 90 | topology['hosts'] = hosts 91 | 92 | switches = {} 93 | for i in range(num_switch): 94 | switch_id = 's' + str(i+1) 95 | switches[switch_id] = {'cpu_port' : True} 96 | topology['switches'] = switches 97 | 98 | obj['topology'] = topology 99 | 100 | json_str = json.dumps(obj, indent=4, separators=(',', ': ')) 101 | print(json_str) 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /cpp/Simulation_Experiments/topology/parameter.py: -------------------------------------------------------------------------------- 1 | para_program = 'p4src/ecmp.p4' 2 | para_switch = 'simple_switch' 3 | para_compiler = 'p4c' 4 | para_options = '--target bmv2 --arch v1model --std p4-16' 5 | para_switch_cli = 'simple_switch_CLI' 6 | -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/README.md: -------------------------------------------------------------------------------- 1 | ## Verification of Our SuMax Sketch 2 | 3 | - We emulate and test the performance of our SuMax sketch using CAIDA2018 dataset. 4 | 5 | 6 | ### File Descriptions 7 | 8 | - ``delay_distribution`` contains the codes to calculate WMRE of the delay_distribution of SuMax, CM and CU. 9 | - ``delay_chi2_wmre_vs_memory.cpp`` is able to emulate WMRE of Sumax, CM and CU with different memory. The ground truth obeys a Chi-Square distribution. 10 | - ``delay_union_wmre_vs_memory.cpp`` accomplishes the above task with uniform distributed ground truth. 11 | - ``delay_mixed_wmre_vs_memory.cpp`` accomplishes the above task with mixed distributed ground truth. 12 | - ``delay_distribution_wmre_with_topk.cpp`` accomplishes the task of different top-k flows. 13 | 14 | - ``flowsize`` contains the codes to calculate RE of flowsize, RE of cardinality, RE of entropy and WMRE of flowsize distribution. 15 | - ``flowsize_ARE_vs_memory.cpp`` is able to calculate ARE of flowsize of SuMax, CM and CU with different memory. 16 | - ``card_dist_ent_vs_memory.cpp`` is able to calculate cardinality RE, flowsize distribution WMRE and entropy RE of SuMax, CM and CU with different memory. 17 | 18 | - ``last_arrival-time`` contains the codes to calculate the correctness rate and ARE of last arrival-time of SuMax. ``last_arrival.cpp`` is the main file. 19 | 20 | - ``max_inter-arrival`` contains the codes to calculate ARE of maximum inter-arrival time of SuMax. 21 | - ``max_interval_vs_memory.cpp`` is able to calculate ARE of maximum inter-arrival time with different memory. 22 | - ``max_interval_vs_topk.cpp`` is able to calculate ARE of maximum inter-arrival time with different top-k flows. 23 | 24 | ### How to Run 25 | - ``cd \task\path`` 26 | 27 | - Change macro ``datapath`` as the path of your CAIDA2018 dataset. 28 | 29 | ``#define datapath "\your\path"`` 30 | 31 | - Run the ``.sh`` file in the folder. 32 | 33 | ``/bin/sh *.sh`` 34 | -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/delay_distribution/compute_wmre.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | g++ delay_union_wmre_vs_memory.cpp --std=c++11 -o union.out && ./union.out & 3 | g++ delay_mixed_wmre_vs_memory.cpp --std=c++11 -o mixed.out && ./mixed.out & 4 | g++ delay_chi2_wmre_vs_memory.cpp --std=c++11 -o chi2.out && ./chi2.out & 5 | g++ delay_distribution_wmre_with_topk.cpp --std=c++11 -o topk.out && ./topk.out & 6 | -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/delay_distribution/delay_chi2_wmre_vs_memory.cpp: -------------------------------------------------------------------------------- 1 | #include"Sketch.h" 2 | #include"distribution.h" 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int N = 1000000; 8 | int topkthres = 100; 9 | 10 | bool Cmp_By_Value(const pair & lhs, const pair & rhs){ 11 | return lhs.second > rhs.second; 12 | } 13 | 14 | int print_uint128(__uint128_t n) { 15 | if (n == 0) return printf("0"); 16 | 17 | char str[40] = {0}; // log10(1 << 128) + '\0' 18 | char *s = str + sizeof(str) - 1; // start at the end 19 | while (n != 0) { 20 | if (s == str) return -1; // never happens 21 | 22 | *--s = "0123456789"[n % 10]; // save last digit 23 | n /= 10; // drop it 24 | } 25 | return printf("%s", s); 26 | } 27 | 28 | void calcu(ofstream & stlog){ 29 | 30 | gtmap GT; 31 | map flowmap; 32 | srand(time(0)); 33 | halfCUSketch* sketch; 34 | CMSketch* CMsketch; 35 | CUSketch* CUsketch; 36 | sketch = new halfCUSketch(); 37 | CMsketch = new CMSketch(); 38 | CUsketch = new CUSketch(); 39 | 40 | ifstream fin(datapath, std::ios::binary); 41 | timestamp_t k1; 42 | flow_t k2_128; 43 | BOBHash32 *delay_hash; delay_hash = new BOBHash32(3); 44 | 45 | 46 | rep2(i, 0, N){ 47 | 48 | fin.read((char*)&k2_128, 13); 49 | fin.read((char*)&k1, sizeof(timestamp_t)); 50 | unsigned delay; 51 | int tmp = delay_hash->run((char*)&k2_128, 13)%2; 52 | delay = get_ChiSquare(1, 3); 53 | 54 | int delay_lev = get_delay_lev(delay); 55 | sketch->insert(k2_128, delay); 56 | CMsketch->insert(k2_128, delay); 57 | CUsketch->insert(k2_128, delay); 58 | 59 | if(flowmap.find(k2_128) == flowmap.end()){ 60 | flowmap.insert(make_pair(k2_128, 1)); 61 | } 62 | else{ 63 | flowmap[k2_128] += 1; 64 | } 65 | 66 | if(GT.find(k2_128) == GT.end()){ 67 | GT.insert(make_pair(k2_128, vector(begin(Zeros), end(Zeros)))); 68 | GT[k2_128][delay_lev] += 1; 69 | } 70 | else{ 71 | GT[k2_128][delay_lev] += 1; 72 | } 73 | 74 | } 75 | 76 | fin.close(); 77 | vector > keyvalue(flowmap.begin(), flowmap.end()); 78 | sort(keyvalue.begin(), keyvalue.end(), Cmp_By_Value); 79 | cout << "flow number is " << keyvalue.size() << endl; 80 | unsigned flow_num = keyvalue.size(); 81 | 82 | cout << "********* statistical analysis *********" << endl; 83 | double aae_sum = 0; 84 | double are_sum = 0; 85 | double wmre = 0; 86 | double wmre_tmp1 = 0; 87 | double wmre_tmp2 = 0; 88 | int aae_num = flow_num; 89 | int are_num = topkthres; 90 | 91 | rep2(i, 0, aae_num){ 92 | rep2(j, 0, Lev_Num){ 93 | aae_sum += (double)ABS((sketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 94 | } 95 | } 96 | rep2(i, 0, are_num){ 97 | rep2(j, 0, Lev_Num){ 98 | are_sum += ((double)ABS((sketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j]))+1.0) / (GT[keyvalue[i].first][j]+1.0); 99 | wmre_tmp1 += (double)ABS((sketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 100 | wmre_tmp2 += (double)(sketch->query_lev(keyvalue[i].first, j) + GT[keyvalue[i].first][j])/2.0; 101 | } 102 | wmre += wmre_tmp1/wmre_tmp2; 103 | } 104 | wmre /= (double) are_num; 105 | aae_sum = aae_sum / (double)(aae_num*Lev_Num); 106 | are_sum = are_sum / (double)(are_num*Lev_Num); 107 | cout << "aae: " << aae_sum << " of top " << aae_num << " flows" << endl; 108 | cout << "are: " << are_sum << " of top " << are_num << " flows" << endl; 109 | stlog << Buck_Num_PerRow*4*8*3/1024 << ',' << wmre << ','; 110 | 111 | //compute CM 112 | aae_sum = 0; 113 | are_sum = 0; 114 | wmre = 0; 115 | wmre_tmp1 = 0; 116 | wmre_tmp2 = 0; 117 | rep2(i, 0, aae_num){ 118 | rep2(j, 0, Lev_Num){ 119 | aae_sum += (double)ABS((CMsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 120 | } 121 | } 122 | rep2(i, 0, are_num){ 123 | rep2(j, 0, Lev_Num){ 124 | are_sum += ((double)ABS((CMsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j]))+1.0) / (GT[keyvalue[i].first][j]+1.0); 125 | wmre_tmp1 += (double)ABS((CMsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 126 | wmre_tmp2 += (double)(CMsketch->query_lev(keyvalue[i].first, j) + GT[keyvalue[i].first][j])/2.0; 127 | } 128 | wmre += wmre_tmp1/wmre_tmp2; 129 | } 130 | wmre /= (double) are_num; 131 | 132 | aae_sum = aae_sum / (double)(aae_num*Lev_Num); 133 | are_sum = are_sum / (double)(are_num*Lev_Num); 134 | 135 | stlog << wmre << ','; 136 | 137 | //compute CU 138 | aae_sum = 0; 139 | are_sum = 0; 140 | wmre = 0; 141 | wmre_tmp1 = 0; 142 | wmre_tmp2 = 0; 143 | rep2(i, 0, aae_num){ 144 | rep2(j, 0, Lev_Num){ 145 | aae_sum += (double)ABS((CUsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 146 | } 147 | } 148 | rep2(i, 0, are_num){ 149 | rep2(j, 0, Lev_Num){ 150 | are_sum += ((double)ABS((CUsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j]))+1.0) / (GT[keyvalue[i].first][j]+1.0); 151 | wmre_tmp1 += (double)ABS((CUsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 152 | wmre_tmp2 += (double)(CUsketch->query_lev(keyvalue[i].first, j) + GT[keyvalue[i].first][j])/2.0; 153 | } 154 | wmre += wmre_tmp1/wmre_tmp2; 155 | } 156 | wmre /= (double) are_num; 157 | aae_sum = aae_sum / (double)(aae_num*Lev_Num); 158 | are_sum = are_sum / (double)(are_num*Lev_Num); 159 | stlog << wmre << endl; 160 | 161 | if(sketch) delete sketch; 162 | if(CMsketch) delete CMsketch; 163 | if(CUsketch) delete CUsketch; 164 | if(delay_hash) delete delay_hash; 165 | 166 | } 167 | 168 | void testGetOpt(int argc, char *argv[], int &a, int &b, int &c) { 169 | int opt; 170 | const char *optstring = "a:b:c:"; 171 | 172 | while ((opt = getopt(argc, argv, optstring)) != -1) { 173 | printf("opt = %c\n", opt); 174 | printf("optarg = %s\n", optarg); 175 | printf("optind = %d\n", optind); 176 | printf("argv[optind - 1] = %s\n\n", argv[optind - 1]); 177 | if(opt=='a') a = atoi(optarg); 178 | if(opt=='b') b = atoi(optarg); 179 | if(opt=='c') c = atoi(optarg); 180 | } 181 | } 182 | 183 | int main(int argc, char *argv[]){ 184 | 185 | topkthres = 1000; 186 | 187 | char outpath[100] = "./union_delay_wmre_vs_memory"; 188 | //strcat(outpath,to_ssssstring(Row_Num).c_str()); 189 | strcat(outpath, ".csv"); 190 | ofstream stlog(outpath, std::ios::out | std::ios::trunc); 191 | 192 | stlog << "memory(KB), acu wmre, cm wmre, cu wmre" << endl; 193 | Buck_Num_PerRow = 1024; 194 | while(Buck_Num_PerRow <= 65536*2){ 195 | //Buck_Num_PerRow = (int)((double)basic_Buck_Num_PerRow*3/(double)Row_Num); 196 | calcu(stlog); 197 | Buck_Num_PerRow *= 2; 198 | } 199 | stlog.close(); 200 | 201 | return 0; 202 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/delay_distribution/delay_mixed_wmre_vs_memory.cpp: -------------------------------------------------------------------------------- 1 | #include"Sketch.h" 2 | #include"distribution.h" 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int N = 1000000; 8 | int topkthres = 100; 9 | 10 | bool Cmp_By_Value(const pair & lhs, const pair & rhs){ 11 | return lhs.second > rhs.second; 12 | } 13 | 14 | int print_uint128(__uint128_t n) { 15 | if (n == 0) return printf("0"); 16 | 17 | char str[40] = {0}; // log10(1 << 128) + '\0' 18 | char *s = str + sizeof(str) - 1; // start at the end 19 | while (n != 0) { 20 | if (s == str) return -1; // never happens 21 | 22 | *--s = "0123456789"[n % 10]; // save last digit 23 | n /= 10; // drop it 24 | } 25 | return printf("%s", s); 26 | } 27 | 28 | void calcu(ofstream & stlog){ 29 | 30 | gtmap GT; 31 | map flowmap; 32 | srand(time(0)); 33 | halfCUSketch* sketch; 34 | CMSketch* CMsketch; 35 | CUSketch* CUsketch; 36 | sketch = new halfCUSketch(); 37 | CMsketch = new CMSketch(); 38 | CUsketch = new CUSketch(); 39 | 40 | ifstream fin(datapath, std::ios::binary); 41 | timestamp_t k1; 42 | flow_t k2_128; 43 | BOBHash32 *delay_hash; delay_hash = new BOBHash32(3); 44 | 45 | 46 | rep2(i, 0, N){ 47 | 48 | fin.read((char*)&k2_128, 13); 49 | fin.read((char*)&k1, sizeof(timestamp_t)); 50 | unsigned delay; 51 | int tmp = delay_hash->run((char*)&k2_128, 13)%2; 52 | if(tmp!=0) {delay = get_ChiSquare(1, 3);} 53 | else {delay = get_Union(0, 80);} 54 | 55 | 56 | int delay_lev = get_delay_lev(delay); 57 | sketch->insert(k2_128, delay); 58 | CMsketch->insert(k2_128, delay); 59 | CUsketch->insert(k2_128, delay); 60 | 61 | if(flowmap.find(k2_128) == flowmap.end()){ 62 | flowmap.insert(make_pair(k2_128, 1)); 63 | } 64 | else{ 65 | flowmap[k2_128] += 1; 66 | } 67 | 68 | if(GT.find(k2_128) == GT.end()){ 69 | GT.insert(make_pair(k2_128, vector(begin(Zeros), end(Zeros)))); 70 | GT[k2_128][delay_lev] += 1; 71 | } 72 | else{ 73 | GT[k2_128][delay_lev] += 1; 74 | } 75 | 76 | } 77 | 78 | fin.close(); 79 | vector > keyvalue(flowmap.begin(), flowmap.end()); 80 | sort(keyvalue.begin(), keyvalue.end(), Cmp_By_Value); 81 | cout << "flow number is " << keyvalue.size() << endl; 82 | unsigned flow_num = keyvalue.size(); 83 | 84 | cout << "********* statistical analysis *********" << endl; 85 | double aae_sum = 0; 86 | double are_sum = 0; 87 | double wmre = 0; 88 | double wmre_tmp1 = 0; 89 | double wmre_tmp2 = 0; 90 | int aae_num = flow_num; 91 | int are_num = topkthres; 92 | 93 | rep2(i, 0, aae_num){ 94 | rep2(j, 0, Lev_Num){ 95 | aae_sum += (double)ABS((sketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 96 | } 97 | } 98 | rep2(i, 0, are_num){ 99 | rep2(j, 0, Lev_Num){ 100 | are_sum += ((double)ABS((sketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j]))+1.0) / (GT[keyvalue[i].first][j]+1.0); 101 | wmre_tmp1 += (double)ABS((sketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 102 | wmre_tmp2 += (double)(sketch->query_lev(keyvalue[i].first, j) + GT[keyvalue[i].first][j])/2.0; 103 | } 104 | wmre += wmre_tmp1/wmre_tmp2; 105 | } 106 | wmre /= (double) are_num; 107 | aae_sum = aae_sum / (double)(aae_num*Lev_Num); 108 | are_sum = are_sum / (double)(are_num*Lev_Num); 109 | cout << "aae: " << aae_sum << " of top " << aae_num << " flows" << endl; 110 | cout << "are: " << are_sum << " of top " << are_num << " flows" << endl; 111 | stlog << Buck_Num_PerRow*4*8*3/1024 << ',' << wmre << ','; 112 | 113 | //compute CM 114 | aae_sum = 0; 115 | are_sum = 0; 116 | wmre = 0; 117 | wmre_tmp1 = 0; 118 | wmre_tmp2 = 0; 119 | rep2(i, 0, aae_num){ 120 | rep2(j, 0, Lev_Num){ 121 | aae_sum += (double)ABS((CMsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 122 | } 123 | } 124 | rep2(i, 0, are_num){ 125 | rep2(j, 0, Lev_Num){ 126 | are_sum += ((double)ABS((CMsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j]))+1.0) / (GT[keyvalue[i].first][j]+1.0); 127 | wmre_tmp1 += (double)ABS((CMsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 128 | wmre_tmp2 += (double)(CMsketch->query_lev(keyvalue[i].first, j) + GT[keyvalue[i].first][j])/2.0; 129 | } 130 | wmre += wmre_tmp1/wmre_tmp2; 131 | } 132 | wmre /= (double) are_num; 133 | 134 | aae_sum = aae_sum / (double)(aae_num*Lev_Num); 135 | are_sum = are_sum / (double)(are_num*Lev_Num); 136 | 137 | stlog << wmre << ','; 138 | 139 | //compute CU 140 | aae_sum = 0; 141 | are_sum = 0; 142 | wmre = 0; 143 | wmre_tmp1 = 0; 144 | wmre_tmp2 = 0; 145 | rep2(i, 0, aae_num){ 146 | rep2(j, 0, Lev_Num){ 147 | aae_sum += (double)ABS((CUsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 148 | } 149 | } 150 | rep2(i, 0, are_num){ 151 | rep2(j, 0, Lev_Num){ 152 | are_sum += ((double)ABS((CUsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j]))+1.0) / (GT[keyvalue[i].first][j]+1.0); 153 | wmre_tmp1 += (double)ABS((CUsketch->query_lev(keyvalue[i].first, j) - GT[keyvalue[i].first][j])); 154 | wmre_tmp2 += (double)(CUsketch->query_lev(keyvalue[i].first, j) + GT[keyvalue[i].first][j])/2.0; 155 | } 156 | wmre += wmre_tmp1/wmre_tmp2; 157 | } 158 | wmre /= (double) are_num; 159 | aae_sum = aae_sum / (double)(aae_num*Lev_Num); 160 | are_sum = are_sum / (double)(are_num*Lev_Num); 161 | stlog << wmre << endl; 162 | 163 | if(sketch) delete sketch; 164 | if(CMsketch) delete CMsketch; 165 | if(CUsketch) delete CUsketch; 166 | if(delay_hash) delete delay_hash; 167 | 168 | } 169 | 170 | void testGetOpt(int argc, char *argv[], int &a, int &b, int &c) { 171 | int opt; 172 | const char *optstring = "a:b:c:"; 173 | 174 | while ((opt = getopt(argc, argv, optstring)) != -1) { 175 | printf("opt = %c\n", opt); 176 | printf("optarg = %s\n", optarg); 177 | printf("optind = %d\n", optind); 178 | printf("argv[optind - 1] = %s\n\n", argv[optind - 1]); 179 | if(opt=='a') a = atoi(optarg); 180 | if(opt=='b') b = atoi(optarg); 181 | if(opt=='c') c = atoi(optarg); 182 | } 183 | } 184 | 185 | int main(int argc, char *argv[]){ 186 | 187 | topkthres = 1000; 188 | 189 | char outpath[100] = "./union_delay_wmre_vs_memory"; 190 | //strcat(outpath,to_ssssstring(Row_Num).c_str()); 191 | strcat(outpath, ".csv"); 192 | ofstream stlog(outpath, std::ios::out | std::ios::trunc); 193 | 194 | stlog << "memory(KB), acu wmre, cm wmre, cu wmre" << endl; 195 | Buck_Num_PerRow = 1024; 196 | while(Buck_Num_PerRow <= 65536*2){ 197 | //Buck_Num_PerRow = (int)((double)basic_Buck_Num_PerRow*3/(double)Row_Num); 198 | calcu(stlog); 199 | Buck_Num_PerRow *= 2; 200 | } 201 | stlog.close(); 202 | 203 | return 0; 204 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/delay_distribution/distribution.h: -------------------------------------------------------------------------------- 1 | //#include"param.h" 2 | #include 3 | #include 4 | unsigned get_ChiSquare(int n, int scale){ 5 | unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); 6 | std::default_random_engine gen(seed); 7 | std::normal_distribution dis(0,1); 8 | double result = 0; 9 | for(int i = 0; i < n; i++){ 10 | double tmp = (double)scale * dis(gen); 11 | result += tmp * tmp; 12 | } 13 | return (unsigned)round(result); 14 | } 15 | 16 | unsigned get_Union(int a, int b){ 17 | int Range = b - a; 18 | return a + (rand() % Range); 19 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/delay_distribution/param.h: -------------------------------------------------------------------------------- 1 | #ifndef Param 2 | #define Param 3 | #include 4 | #include"BOBHash32.h" 5 | 6 | #define fi first 7 | #define se second 8 | #define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 9 | #define rep2(i,a,b) for(int (i)=(a);(i)<(b);(i)++) 10 | #define END_FILE_NO 1 11 | #define START_FILE_NO 0 12 | #define KEY_LENGTH 8 13 | #define ITEM_LENGTH 16 14 | #define MAX(a,b) ((a)>(b)?(a):(b)) 15 | #define MIN(a,b) ((a)<(b)?(a):(b)) 16 | #define ABS(a) ((a)>0?(a):(-(a))) 17 | 18 | #define Lev_Num 8 19 | //#define Row_Num 3 20 | 21 | #define ChangeBuckNum 22 | #ifndef ChangeBuckNum 23 | #define Buck_Num_PerRow 100000 24 | #else 25 | int Buck_Num_PerRow = 65536; 26 | int Row_Num = 3; 27 | double collect_rate = 1.0; 28 | #endif 29 | 30 | #define small 31 | //#define lab 32 | 33 | // path of CAIDA2018 dataset 34 | #define datapath "/usr/share/dataset/CAIDA2018/dataset/130000.dat" 35 | 36 | typedef __uint128_t flow_t; 37 | typedef double_t timestamp_t; 38 | typedef map<__uint128_t, vector > gtmap; 39 | __uint128_t mistake = 0; 40 | unsigned delayLevThres[Lev_Num] = {10, 20, 30, 40, 50, 60, 70, 80}; 41 | unsigned Zeros[Lev_Num] = {0, 0, 0, 0, 0, 0, 0, 0}; 42 | #endif -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/flowsize/card_dist_ent_vs_memory.cpp: -------------------------------------------------------------------------------- 1 | #include"Sketch.h" 2 | #include"distribution.h" 3 | #include 4 | 5 | using namespace std; 6 | 7 | //const int N = 1000000; 8 | const int N = 100000; 9 | int topkthres = 100; 10 | 11 | bool Cmp_By_Value(const pair & lhs, const pair & rhs){ 12 | return lhs.second > rhs.second; 13 | } 14 | 15 | int print_uint128(__uint128_t n) { 16 | if (n == 0) return printf("0"); 17 | 18 | char str[40] = {0}; // log10(1 << 128) + '\0' 19 | char *s = str + sizeof(str) - 1; // start at the end 20 | while (n != 0) { 21 | if (s == str) return -1; // never happens 22 | 23 | *--s = "0123456789"[n % 10]; // save last digit 24 | n /= 10; // drop it 25 | } 26 | return printf("%s", s); 27 | } 28 | 29 | void calcu(ofstream & stlog){ 30 | 31 | gtmap GT; 32 | map flowmap; 33 | srand(time(0)); 34 | halfCUSketch* sketch; 35 | CMSketch* CMsketch; 36 | CUSketch* CUsketch; 37 | sketch = new halfCUSketch(); 38 | CMsketch = new CMSketch(); 39 | CUsketch = new CUSketch(); 40 | 41 | ifstream fin(datapath, std::ios::binary); 42 | timestamp_t k1; 43 | flow_t k2_128; 44 | BOBHash32 *delay_hash; delay_hash = new BOBHash32(3); 45 | 46 | 47 | rep2(i, 0, N){ 48 | fin.read((char*)&k2_128, 13); 49 | fin.read((char*)&k1, sizeof(timestamp_t)); 50 | unsigned delay; 51 | int tmp = delay_hash->run((char*)&k2_128, 13)%2; 52 | /* 53 | if(tmp!=0) {delay = get_ChiSquare(1, 3);} 54 | else {delay = get_Union(0, 80);} 55 | */ 56 | //delay = get_Union(0, 80); 57 | delay = get_ChiSquare(1, 3); 58 | 59 | int delay_lev = get_delay_lev(delay); 60 | sketch->insert(k2_128, delay); 61 | CMsketch->insert(k2_128, delay); 62 | CUsketch->insert(k2_128, delay); 63 | 64 | if(flowmap.find(k2_128) == flowmap.end()){ 65 | flowmap.insert(make_pair(k2_128, 1)); 66 | } 67 | else{ 68 | flowmap[k2_128] += 1; 69 | } 70 | 71 | if(GT.find(k2_128) == GT.end()){ 72 | GT.insert(make_pair(k2_128, vector(begin(Zeros), end(Zeros)))); 73 | GT[k2_128][delay_lev] += 1; 74 | } 75 | else{ 76 | GT[k2_128][delay_lev] += 1; 77 | } 78 | 79 | } 80 | 81 | fin.close(); 82 | vector > keyvalue(flowmap.begin(), flowmap.end()); 83 | sort(keyvalue.begin(), keyvalue.end(), Cmp_By_Value); 84 | cout << "flow number is " << keyvalue.size() << endl; 85 | unsigned flow_num = keyvalue.size(); 86 | 87 | cout << "********* statistical analysis *********" << endl; 88 | double aae_sum = 0; 89 | double are_sum = 0; 90 | int aae_num = flow_num; 91 | int are_num = topkthres; 92 | 93 | are_sum = 0; aae_sum = 0; 94 | 95 | /* 96 | Cardinality ARE 97 | */ 98 | double card_re = ABS(flow_num-sketch->get_cardinality())/(double)flow_num; 99 | 100 | vector real_dist; 101 | int maxflowsize = keyvalue[0].second; 102 | real_dist.resize(maxflowsize+1); 103 | rep2(i, 0, flow_num){ 104 | real_dist[keyvalue[i].second]++; 105 | } 106 | 107 | /* 108 | distribution 109 | */ 110 | vector dist; 111 | vector mice_dist; 112 | double dist_wmre; 113 | sketch->get_distribution(dist, mice_dist); 114 | double tmp1 = 0; double tmp2 = 0; 115 | int maximum_flowsize = max(dist.size(), real_dist.size()); 116 | rep2(i, 1, maximum_flowsize){ 117 | double n = 0; double n_hat = 0; 118 | if(i < dist.size()) n_hat = (double)dist[i]; 119 | if(i < real_dist.size()) n = (double)real_dist[i]; 120 | tmp1 += ABS(n_hat - n); 121 | tmp2 += (n_hat + n)/2; 122 | } 123 | dist_wmre = tmp1 / tmp2; 124 | /* 125 | entropy 126 | */ 127 | double entropy = 0; double real_entropy = 0; 128 | int tot; double entr; 129 | sketch->get_entropy(tot, entr, dist); 130 | int real_tot; double real_entr; 131 | sketch->get_entropy(real_tot, real_entr, real_dist); 132 | entropy = -entr/tot + log2(tot); 133 | real_entropy = -real_entr/real_tot + log2(real_tot); 134 | 135 | double entr_re = ABS(real_entropy-entropy)/real_entropy; 136 | stlog << (Buck_Num_PerRow*3*4/1024) << ',' << card_re << ',' << dist_wmre << ',' << entr_re << endl; 137 | 138 | if(sketch) delete sketch; 139 | if(CMsketch) delete CMsketch; 140 | if(CUsketch) delete CUsketch; 141 | if(delay_hash) delete delay_hash; 142 | 143 | } 144 | 145 | void testGetOpt(int argc, char *argv[], int &a, int &b, int &c) { 146 | int opt; 147 | const char *optstring = "a:b:c:"; 148 | 149 | while ((opt = getopt(argc, argv, optstring)) != -1) { 150 | printf("opt = %c\n", opt); 151 | printf("optarg = %s\n", optarg); 152 | printf("optind = %d\n", optind); 153 | printf("argv[optind - 1] = %s\n\n", argv[optind - 1]); 154 | if(opt=='a') a = atoi(optarg); 155 | if(opt=='b') b = atoi(optarg); 156 | if(opt=='c') c = atoi(optarg); 157 | } 158 | } 159 | 160 | int main(int argc, char *argv[]){ 161 | 162 | topkthres = 1000; 163 | ofstream stlog("./card_dist_ent_vs_memory.csv", std::ios::out | std::ios::trunc); 164 | Row_Num = 3; 165 | //Buck_Num_PerRow = (int)((double)65536*3/(double)Row_Num); 166 | stlog << "memory(KB), cardinality RE, distribution WMRE, entropy RE" << endl; 167 | Buck_Num_PerRow = 1024; 168 | while(Buck_Num_PerRow <= 65536){ 169 | calcu(stlog); 170 | Buck_Num_PerRow *= 2; 171 | } 172 | 173 | stlog.close(); 174 | return 0; 175 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/flowsize/distribution.h: -------------------------------------------------------------------------------- 1 | //#include"param.h" 2 | #include 3 | #include 4 | unsigned get_ChiSquare(int n, int scale){ 5 | unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); 6 | std::default_random_engine gen(seed); 7 | std::normal_distribution dis(0,1); 8 | double result = 0; 9 | for(int i = 0; i < n; i++){ 10 | double tmp = (double)scale * dis(gen); 11 | result += tmp * tmp; 12 | } 13 | return (unsigned)round(result); 14 | } 15 | 16 | unsigned get_Union(int a, int b){ 17 | int Range = b - a; 18 | return a + (rand() % Range); 19 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/flowsize/flowsize_estimation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | g++ flowsize_ARE_vs_memory.cpp --std=c++11 -o flow.out && ./flow.out & 3 | g++ card_dist_ent_vs_memory.cpp --std=c++11 -o cde.out && ./cde.out & -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/flowsize/param.h: -------------------------------------------------------------------------------- 1 | #ifndef Param 2 | #define Param 3 | #include 4 | #include"BOBHash32.h" 5 | 6 | #define fi first 7 | #define se second 8 | #define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 9 | #define rep2(i,a,b) for(int (i)=(a);(i)<(b);(i)++) 10 | #define END_FILE_NO 1 11 | #define START_FILE_NO 0 12 | #define KEY_LENGTH 8 13 | #define ITEM_LENGTH 16 14 | #define MAX(a,b) ((a)>(b)?(a):(b)) 15 | #define MIN(a,b) ((a)<(b)?(a):(b)) 16 | #define ABS(a) ((a)>0?(a):(-(a))) 17 | 18 | #define Lev_Num 8 19 | //#define Row_Num 3 20 | 21 | #define ChangeBuckNum 22 | #ifndef ChangeBuckNum 23 | #define Buck_Num_PerRow 100000 24 | #else 25 | int Buck_Num_PerRow = 65536; 26 | int Row_Num = 3; 27 | double collect_rate = 1.0; 28 | #endif 29 | 30 | #define small 31 | //#define lab 32 | 33 | // path of CAIDA2018 dataset 34 | #define datapath "/usr/share/dataset/CAIDA2018/dataset/130000.dat" 35 | 36 | typedef __uint128_t flow_t; 37 | typedef double_t timestamp_t; 38 | typedef map<__uint128_t, vector > gtmap; 39 | __uint128_t mistake = 0; 40 | unsigned delayLevThres[Lev_Num] = {10, 20, 30, 40, 50, 60, 70, 80}; 41 | unsigned Zeros[Lev_Num] = {0, 0, 0, 0, 0, 0, 0, 0}; 42 | #endif -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/last_arrival-time/Interval.h: -------------------------------------------------------------------------------- 1 | 2 | class ts_buck{ 3 | public: 4 | double ts; 5 | ts_buck(double timestamp){ 6 | ts = timestamp; 7 | } 8 | ~ts_buck(){} 9 | void insert(double timestamp){ 10 | ts = timestamp; 11 | } 12 | double query(){ 13 | return ts; 14 | } 15 | }; 16 | class int_buck{ 17 | public: 18 | double ts; 19 | int_buck(double timestamp){ 20 | ts = timestamp; 21 | } 22 | ~int_buck(){} 23 | void insert(double timestamp){ 24 | ts = max(ts, timestamp); 25 | 26 | } 27 | double query(){ 28 | return ts; 29 | } 30 | }; 31 | class ts_row{ 32 | public: 33 | ts_buck ** bucket; 34 | BOBHash32 *bobhash; 35 | ts_row(unsigned seed, double ts = 0.0){ 36 | bucket = new ts_buck*[Buck_Num_PerRow]; 37 | rep2(i, 0, Buck_Num_PerRow){ 38 | bucket[i] = new ts_buck(ts); 39 | } 40 | bobhash = new BOBHash32((unsigned)seed); 41 | } 42 | ~ts_row(){ 43 | rep2(i, 0, Buck_Num_PerRow) if(bucket[i]) delete bucket[i]; 44 | if(bobhash) delete bobhash; 45 | delete bucket; 46 | } 47 | unsigned get_hash(const flow_t flow){ 48 | return bobhash->run((char*)&flow, 13) % Buck_Num_PerRow; 49 | } 50 | void insert(const flow_t flow, const timestamp_t timestamp){ 51 | unsigned pos = get_hash(flow); 52 | bucket[pos]->insert(timestamp); 53 | } 54 | double query(const flow_t flow){ 55 | unsigned pos = get_hash(flow); 56 | return bucket[pos]->query(); 57 | } 58 | }; 59 | class int_row{ 60 | public: 61 | int_buck ** bucket; 62 | BOBHash32 *bobhash; 63 | int_row(unsigned seed, double ts = 0.0){ 64 | bucket = new int_buck*[Buck_Num_PerRow]; 65 | rep2(i, 0, Buck_Num_PerRow){ 66 | bucket[i] = new int_buck(ts); 67 | } 68 | bobhash = new BOBHash32((unsigned)seed); 69 | } 70 | ~int_row(){ 71 | rep2(i, 0, Buck_Num_PerRow) if(bucket[i]) delete bucket[i]; 72 | if(bobhash) delete bobhash; 73 | delete bucket; 74 | } 75 | unsigned get_hash(const flow_t flow){ 76 | return bobhash->run((char*)&flow, 13) % Buck_Num_PerRow; 77 | } 78 | void insert(const flow_t flow, const timestamp_t timestamp){ 79 | unsigned pos = get_hash(flow); 80 | bucket[pos]->insert(timestamp); 81 | } 82 | double query(const flow_t flow){ 83 | unsigned pos = get_hash(flow); 84 | return bucket[pos]->query(); 85 | } 86 | }; 87 | 88 | class MinMaxSketch{ 89 | public: 90 | ts_row ** tsRow; 91 | int_row ** intRow; 92 | MinMaxSketch(double ts = 0){ 93 | tsRow = new ts_row*[Row_Num]; 94 | intRow = new int_row*[Row_Num]; 95 | rep2(i, 0, Row_Num){ 96 | tsRow[i] = new ts_row((unsigned)(i+rand())%25, ts); 97 | intRow[i] = new int_row((unsigned)((i+5)*2)%25, ts); 98 | } 99 | } 100 | ~MinMaxSketch(){ 101 | rep2(i, 0, Row_Num){ 102 | if(tsRow[i]) delete tsRow[i]; 103 | if(intRow[i]) delete intRow[i]; 104 | } 105 | if(tsRow) delete tsRow; 106 | if(intRow) delete intRow; 107 | } 108 | void insert(const flow_t &flow, const timestamp_t &ts){ 109 | rep2(i, 0, Row_Num){ 110 | double last_ts = tsRow[i]->query(flow); 111 | double tmp = ts - last_ts; 112 | 113 | if(ABS(last_ts)<1e-5){ 114 | tsRow[i]->insert(flow, ts); 115 | } 116 | else{ 117 | double delta_ts = ts - last_ts; 118 | intRow[i]->insert(flow, delta_ts); 119 | tsRow[i]->insert(flow, ts); 120 | } 121 | } 122 | } 123 | double query(const flow_t &flow){ 124 | double Min = 1e10; 125 | rep2(i, 0, Row_Num){ 126 | double delta_ts = intRow[i]->query(flow); 127 | if(delta_ts < Min) Min = delta_ts; 128 | } 129 | return Min; 130 | } 131 | double last_arrival(const flow_t &flow){ 132 | double Min = 1e100; 133 | rep2(i, 0, Row_Num){ 134 | double last_ts = tsRow[i]->query(flow); 135 | if(last_ts < Min) Min = last_ts; 136 | } 137 | return Min; 138 | } 139 | }; -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/last_arrival-time/compute_last_arrival-time.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | g++ last_arrival.cpp --std=c++11 -o lastarr.out && ./lastarr.out & -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/last_arrival-time/last_arrival.cpp: -------------------------------------------------------------------------------- 1 | //#include"Interval_old.h" 2 | #include 3 | #include "param.h" 4 | #include"Interval.h" 5 | #include"packet.h" 6 | using namespace std; 7 | 8 | const int N = 1000000; 9 | //const int N = 1000; 10 | 11 | map> GT; 12 | map flowmap; 13 | 14 | bool Cmp_By_Value(const pair & lhs, const pair & rhs){ 15 | return lhs.second > rhs.second; 16 | } 17 | 18 | int print_uint128(__uint128_t n) { 19 | if (n == 0) return printf("0"); 20 | 21 | char str[40] = {0}; // log10(1 << 128) + '\0' 22 | char *s = str + sizeof(str) - 1; // start at the end 23 | while (n != 0) { 24 | if (s == str) return -1; // never happens 25 | 26 | *--s = "0123456789"[n % 10]; // save last digit 27 | n /= 10; // drop it 28 | } 29 | return printf("%s", s); 30 | } 31 | 32 | int calcu(ofstream &stlog){ 33 | srand(time(0)); 34 | MinMaxSketch* sketch; 35 | sketch = new MinMaxSketch(0); 36 | ifstream fin(datapath, std::ios::binary); 37 | timestamp_t k1 = 0; 38 | flow_t k2_128 = 0; 39 | BOBHash32 *delay_hash; delay_hash = new BOBHash32(ABS(rand()%10)); 40 | cout << 1 << endl; 41 | double GTMAX = 0; 42 | fin.read((char*)&k2_128, 13); 43 | fin.read((char*)&k1, sizeof(timestamp_t)); 44 | if(flowmap.find(k2_128) == flowmap.end()){ 45 | flowmap.insert(make_pair(k2_128, 1)); 46 | } 47 | else{ 48 | flowmap[k2_128] += 1; 49 | } 50 | 51 | map sketch_flow_last_timestamp; 52 | map sketch_flow_max_interval; 53 | double aae = 0; 54 | double correct_cnt = 0; 55 | double allcnt = 0; 56 | rep2(i, 1, N){ 57 | if(i %(N/10) == 0) std::cout << "Loading... "<< i/(N/100) << '%' << endl; 58 | k2_128 = 0, k1 = 0; 59 | fin.read((char*)&k2_128, 13); 60 | fin.read((char*)&k1, 8); 61 | //if(k2_128 != mistake) continue; 62 | if(flowmap.find(k2_128) == flowmap.end()){ 63 | flowmap.insert(make_pair(k2_128, 1)); 64 | } 65 | else{ 66 | flowmap[k2_128] += 1; 67 | } 68 | 69 | double sketch_last_ts = sketch->last_arrival(k2_128); 70 | sketch->insert(k2_128, k1); 71 | //sketch_old->insert(k2_128,k1); 72 | //initialize ground truth 73 | double gt_last_ts = 0; 74 | if(sketch_flow_last_timestamp.find(k2_128)==sketch_flow_last_timestamp.end()){ 75 | sketch_flow_last_timestamp.insert(make_pair(k2_128, k1)); 76 | gt_last_ts = 0; 77 | } 78 | else{ 79 | gt_last_ts = sketch_flow_last_timestamp[k2_128]; 80 | } 81 | if(ABS(gt_last_ts)>1e-9){ 82 | aae += ABS(gt_last_ts-sketch_last_ts); 83 | if(ABS(gt_last_ts-sketch_last_ts) < 1e-9) correct_cnt += 1; 84 | allcnt += 1; 85 | } 86 | 87 | if(sketch_flow_max_interval.find(k2_128)==sketch_flow_max_interval.end()){ 88 | sketch_flow_max_interval.insert(make_pair(k2_128, 0)); 89 | } 90 | double gt_interval = ABS(k1 - sketch_flow_last_timestamp[k2_128]); 91 | sketch_flow_max_interval[k2_128] = max(sketch_flow_max_interval[k2_128], gt_interval); 92 | sketch_flow_last_timestamp[k2_128] = k1; 93 | //if(gt_interval>GTMAX) GTMAX = gt_interval; 94 | } 95 | aae /= allcnt; 96 | correct_cnt /= allcnt; 97 | stlog << Row_Num*Buck_Num_PerRow*2*8/1024 << ',' << correct_cnt << ',' << aae << endl; 98 | 99 | if(sketch) delete sketch; 100 | if(delay_hash) delete delay_hash; 101 | return 0; 102 | } 103 | 104 | int main(){ 105 | ofstream stlog("./row3_lastarrival_memory.csv", std::ios::out | std::ios::trunc); 106 | double basic_buck_num = 2048; 107 | Row_Num = 3; 108 | stlog << "Memory(kB), Correct Rate, AAE" << endl; 109 | while(basic_buck_num <= 1024*1024*4){ 110 | Buck_Num_PerRow = (int)((double)basic_buck_num*3/(double)Row_Num); 111 | cout << Buck_Num_PerRow << endl; 112 | calcu(stlog); 113 | basic_buck_num *= 2; 114 | } 115 | return 0; 116 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/last_arrival-time/packet.h: -------------------------------------------------------------------------------- 1 | #include"param.h" 2 | 3 | typedef vector > packet_in; 4 | typedef vector, packet_in>> packet_full; 5 | double get_delay(){ 6 | int tmp = rand() % 10000; 7 | return 0.1; 8 | return tmp*0.000001; 9 | } 10 | bool Comp_pair(const tuple & a, const tuple & b){ 11 | return get<1>(a) < get<1>(b); 12 | } 13 | bool Comp(const pair &a, const pair &b){ 14 | return a.second > b.second; 15 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/last_arrival-time/param.h: -------------------------------------------------------------------------------- 1 | #ifndef Param 2 | #define Param 3 | #include 4 | #include"BOBHash32.h" 5 | 6 | #define fi first 7 | #define se second 8 | #define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 9 | #define rep2(i,a,b) for(int (i)=(a);(i)<(b);(i)++) 10 | #define END_FILE_NO 1 11 | #define START_FILE_NO 0 12 | #define KEY_LENGTH 8 13 | #define ITEM_LENGTH 16 14 | #define MAX(a,b) ((a)>(b)?(a):(b)) 15 | #define MIN(a,b) ((a)<(b)?(a):(b)) 16 | #define ABS(a) ((a)>0?(a):(-(a))) 17 | 18 | #define Lev_Num 8 19 | //#define Row_Num 3 20 | 21 | #define ChangeBuckNum 22 | #ifndef ChangeBuckNum 23 | #define Buck_Num_PerRow 100000 24 | #else 25 | int Buck_Num_PerRow = 65536; 26 | int Row_Num = 3; 27 | double collect_rate = 1.0; 28 | #endif 29 | 30 | #define small 31 | //#define lab 32 | 33 | // Path of dataset 34 | #define datapath "/usr/share/dataset/CAIDA2018/dataset/130000.dat" 35 | 36 | typedef __uint128_t flow_t; 37 | typedef double_t timestamp_t; 38 | typedef map<__uint128_t, vector > gtmap; 39 | __uint128_t mistake = 0; 40 | unsigned delayLevThres[Lev_Num] = {10, 20, 30, 40, 50, 60, 70, 80}; 41 | unsigned Zeros[Lev_Num] = {0, 0, 0, 0, 0, 0, 0, 0}; 42 | #endif -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/max_inter-arrival/Interval.h: -------------------------------------------------------------------------------- 1 | class ts_buck{ 2 | public: 3 | double ts; 4 | ts_buck(double timestamp){ 5 | ts = timestamp; 6 | } 7 | ~ts_buck(){} 8 | void insert(double timestamp){ 9 | ts = timestamp; 10 | } 11 | double query(){ 12 | return ts; 13 | } 14 | }; 15 | class int_buck{ 16 | public: 17 | double ts; 18 | int_buck(double timestamp){ 19 | ts = timestamp; 20 | } 21 | ~int_buck(){} 22 | void insert(double timestamp){ 23 | ts = max(ts, timestamp); 24 | 25 | } 26 | double query(){ 27 | return ts; 28 | } 29 | }; 30 | class ts_row{ 31 | public: 32 | ts_buck ** bucket; 33 | BOBHash32 *bobhash; 34 | ts_row(unsigned seed, double ts = 0.0){ 35 | bucket = new ts_buck*[Buck_Num_PerRow]; 36 | rep2(i, 0, Buck_Num_PerRow){ 37 | bucket[i] = new ts_buck(ts); 38 | } 39 | bobhash = new BOBHash32((unsigned)seed); 40 | } 41 | ~ts_row(){ 42 | rep2(i, 0, Buck_Num_PerRow) if(bucket[i]) delete bucket[i]; 43 | if(bobhash) delete bobhash; 44 | delete bucket; 45 | } 46 | unsigned get_hash(const flow_t flow){ 47 | return bobhash->run((char*)&flow, 13) % Buck_Num_PerRow; 48 | } 49 | void insert(const flow_t flow, const timestamp_t timestamp){ 50 | unsigned pos = get_hash(flow); 51 | bucket[pos]->insert(timestamp); 52 | } 53 | double query(const flow_t flow){ 54 | unsigned pos = get_hash(flow); 55 | return bucket[pos]->query(); 56 | } 57 | }; 58 | class int_row{ 59 | public: 60 | int_buck ** bucket; 61 | BOBHash32 *bobhash; 62 | int_row(unsigned seed, double ts = 0.0){ 63 | bucket = new int_buck*[Buck_Num_PerRow]; 64 | rep2(i, 0, Buck_Num_PerRow){ 65 | bucket[i] = new int_buck(ts); 66 | } 67 | bobhash = new BOBHash32((unsigned)seed); 68 | } 69 | ~int_row(){ 70 | rep2(i, 0, Buck_Num_PerRow) if(bucket[i]) delete bucket[i]; 71 | if(bobhash) delete bobhash; 72 | delete bucket; 73 | } 74 | unsigned get_hash(const flow_t flow){ 75 | return bobhash->run((char*)&flow, 13) % Buck_Num_PerRow; 76 | } 77 | void insert(const flow_t flow, const timestamp_t timestamp){ 78 | unsigned pos = get_hash(flow); 79 | bucket[pos]->insert(timestamp); 80 | } 81 | double query(const flow_t flow){ 82 | unsigned pos = get_hash(flow); 83 | return bucket[pos]->query(); 84 | } 85 | }; 86 | 87 | class MinMaxSketch{ 88 | public: 89 | ts_row ** tsRow; 90 | int_row ** intRow; 91 | MinMaxSketch(double ts = 0){ 92 | tsRow = new ts_row*[Row_Num]; 93 | intRow = new int_row*[Row_Num]; 94 | rep2(i, 0, Row_Num){ 95 | tsRow[i] = new ts_row((unsigned)(i+rand())%25, ts); 96 | intRow[i] = new int_row((unsigned)((i+5)*2)%25, ts); 97 | } 98 | } 99 | ~MinMaxSketch(){ 100 | rep2(i, 0, Row_Num){ 101 | if(tsRow[i]) delete tsRow[i]; 102 | if(intRow[i]) delete intRow[i]; 103 | } 104 | if(tsRow) delete tsRow; 105 | if(intRow) delete intRow; 106 | } 107 | void insert(const flow_t &flow, const timestamp_t &ts){ 108 | rep2(i, 0, Row_Num){ 109 | double last_ts = tsRow[i]->query(flow); 110 | double tmp = ts - last_ts; 111 | 112 | if(ABS(last_ts)<1e-5){ 113 | tsRow[i]->insert(flow, ts); 114 | } 115 | else{ 116 | double delta_ts = ts - last_ts; 117 | intRow[i]->insert(flow, delta_ts); 118 | tsRow[i]->insert(flow, ts); 119 | } 120 | } 121 | } 122 | double query(const flow_t &flow){ 123 | double Min = 1e10; 124 | rep2(i, 0, Row_Num){ 125 | double delta_ts = intRow[i]->query(flow); 126 | if(delta_ts < Min) Min = delta_ts; 127 | } 128 | return Min; 129 | } 130 | }; -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/max_inter-arrival/Interval_old.h: -------------------------------------------------------------------------------- 1 | #include"param.h" 2 | 3 | int get_delay_lev(unsigned delay){ 4 | rep2(i, 0, 9){ 5 | if(delay < delayLevThres[i]) return i; 6 | } 7 | return 9; 8 | } 9 | 10 | class buck{ 11 | public: 12 | double delta_t; 13 | double last_ts; 14 | buck(double lt = 0.0){ 15 | delta_t = 0.0, last_ts = 0; 16 | } 17 | void insert(double ts){ 18 | if(last_ts < 1) last_ts = ts; 19 | else{ 20 | double tmp = (ts - last_ts); 21 | delta_t = max(delta_t, tmp); 22 | last_ts = ts; 23 | } 24 | } 25 | void init(double ts){ 26 | last_ts = ts; 27 | } 28 | double query(){ 29 | //cout << delta_t << endl; 30 | return delta_t; 31 | } 32 | ~buck(){ } 33 | }; 34 | 35 | class row{ 36 | public: 37 | buck **bucket; 38 | BOBHash32 *bobhash; 39 | 40 | row(double ts, unsigned seed){ 41 | cout << "row" << endl; 42 | cout << Buck_Num_PerRow << endl; 43 | bucket = new buck*[(unsigned)Buck_Num_PerRow]; 44 | cout << Buck_Num_PerRow << endl; 45 | rep2(i, 0, Buck_Num_PerRow){ 46 | bucket[i] = new buck(ts); 47 | } 48 | bobhash = new BOBHash32((unsigned)seed); 49 | cout << "row end" << endl; 50 | } 51 | ~row(){ 52 | rep2(i, 0, Buck_Num_PerRow) if(bucket[i]) delete bucket[i]; 53 | if(bobhash) delete bobhash; 54 | if(bucket) delete bucket; 55 | } 56 | 57 | int get_hash(const flow_t flow){ 58 | return bobhash->run((char*)&flow, 13) % Buck_Num_PerRow; 59 | } 60 | void insert(const flow_t flow, const double timestamp){ 61 | int pos = get_hash(flow); 62 | bucket[pos]->insert(timestamp); 63 | } 64 | double query(const flow_t flow){ 65 | int pos = get_hash(flow); 66 | //cout << "pos " << pos << endl; 67 | return bucket[pos]->query(); 68 | } 69 | }; 70 | 71 | class interval_Sketch{ 72 | public: 73 | row **Row; 74 | interval_Sketch(double ts = 0.0){ 75 | cout << "inter" << endl; 76 | Row = new row*[Row_Num]; 77 | rep2(i, 0, Row_Num){ 78 | Row[i] = new row(ts,(unsigned)(i+rand())%25); 79 | } 80 | cout << "inter end" << endl; 81 | } 82 | ~interval_Sketch(){ 83 | rep2(i, 0, Row_Num) if(Row[i]) delete Row[i]; 84 | if(Row) delete Row; 85 | } 86 | 87 | void insert(const flow_t flow, const double timestamp){ 88 | rep2(i, 0, Row_Num){ 89 | Row[i]->insert(flow, timestamp); 90 | } 91 | } 92 | double query(const flow_t flow){ 93 | double Min = 1e12; 94 | double Max = 0; 95 | rep2(i, 0, Row_Num){ 96 | double curr = Row[i]->query(flow); 97 | if(curr >= Max) Max = curr; 98 | if(curr <= Min) Min = curr; 99 | } 100 | //return Max; 101 | return Min; 102 | } 103 | }; -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/max_inter-arrival/compute_inter-arrival.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | g++ max_interval_vs_memory.cpp --std=c++11 -o maxint_mem.out && ./maxint_mem.out & 3 | g++ max_interval_vs_topk.cpp --std=c++11 -o maxint_topk.out && ./maxint_topk.out & -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/max_inter-arrival/max_interval_vs_memory.cpp: -------------------------------------------------------------------------------- 1 | #include"Interval_old.h" 2 | #include"Interval.h" 3 | #include"packet.h" 4 | 5 | using namespace std; 6 | 7 | const int N = 1000000; 8 | int topkthres = 1000; 9 | map> GT; 10 | map flowmap; 11 | 12 | bool Cmp_By_Value(const pair & lhs, const pair & rhs){ 13 | return lhs.second > rhs.second; 14 | } 15 | 16 | int print_uint128(__uint128_t n) { 17 | if (n == 0) return printf("0"); 18 | 19 | char str[40] = {0}; // log10(1 << 128) + '\0' 20 | char *s = str + sizeof(str) - 1; // start at the end 21 | while (n != 0) { 22 | if (s == str) return -1; // never happens 23 | 24 | *--s = "0123456789"[n % 10]; // save last digit 25 | n /= 10; // drop it 26 | } 27 | return printf("%s", s); 28 | } 29 | 30 | double calcu(ofstream &stlog){ 31 | srand(time(0)); 32 | MinMaxSketch* sketch; 33 | sketch = new MinMaxSketch(0); 34 | 35 | ifstream fin(datapath, std::ios::binary); 36 | timestamp_t k1 = 0; 37 | flow_t k2_128 = 0; 38 | BOBHash32 *delay_hash; delay_hash = new BOBHash32(ABS(rand()%10)); 39 | cout << 1 << endl; 40 | double GTMAX = 0; 41 | fin.read((char*)&k2_128, 13); 42 | fin.read((char*)&k1, sizeof(timestamp_t)); 43 | if(flowmap.find(k2_128) == flowmap.end()){ 44 | flowmap.insert(make_pair(k2_128, 1)); 45 | } 46 | else{ 47 | flowmap[k2_128] += 1; 48 | } 49 | 50 | map sketch_flow_last_timestamp; 51 | map sketch_flow_max_interval; 52 | 53 | rep2(i, 1, N){ 54 | if(i %(N/10) == 0) std::cout << "Loading... "<< i/(N/100) << '%' << endl; 55 | k2_128 = 0, k1 = 0; 56 | fin.read((char*)&k2_128, 13); 57 | fin.read((char*)&k1, 8); 58 | 59 | if(flowmap.find(k2_128) == flowmap.end()){ 60 | flowmap.insert(make_pair(k2_128, 1)); 61 | } 62 | else{ 63 | flowmap[k2_128] += 1; 64 | } 65 | sketch->insert(k2_128, k1); 66 | 67 | if(sketch_flow_last_timestamp.find(k2_128)==sketch_flow_last_timestamp.end()){ 68 | sketch_flow_last_timestamp.insert(make_pair(k2_128, k1)); 69 | } 70 | if(sketch_flow_max_interval.find(k2_128)==sketch_flow_max_interval.end()){ 71 | sketch_flow_max_interval.insert(make_pair(k2_128, 0)); 72 | } 73 | double gt_interval = ABS(k1 - sketch_flow_last_timestamp[k2_128]); 74 | sketch_flow_max_interval[k2_128] = max(sketch_flow_max_interval[k2_128], gt_interval); 75 | sketch_flow_last_timestamp[k2_128] = k1; 76 | } 77 | double are = 0; 78 | double are_old = 0; 79 | double cnt = 0.0; 80 | double correct_cnt = 0.0; 81 | double wrong_cnt = 0.0; 82 | 83 | int topk = topkthres; 84 | int falsecnt = 0; 85 | vector> sorttmp; 86 | map::iterator sortit = flowmap.begin(); 87 | while(sortit != flowmap.end()){ 88 | sorttmp.push_back(*sortit); 89 | sortit++; 90 | } 91 | sort(sorttmp.begin(),sorttmp.end(),Comp); 92 | 93 | rep2(j, 0, topk){ 94 | flow_t flowname = sorttmp[j].first; 95 | timestamp_t max_interval = sketch->query(flowname); 96 | timestamp_t gt_max_interval = sketch_flow_max_interval[flowname]; 97 | are += (ABS(gt_max_interval-max_interval))/(gt_max_interval); 98 | if(gt_max_interval>GTMAX) GTMAX = gt_max_interval; 99 | } 100 | 101 | are /= (topk); 102 | if(sketch) delete sketch; 103 | if(delay_hash) delete delay_hash; 104 | return are; 105 | } 106 | 107 | void ave(ofstream & stlog){ 108 | double arecnt = 0; 109 | //how many times to average 110 | int avetimes = 5; 111 | rep2(i, 0, (unsigned)avetimes){ 112 | arecnt += calcu(stlog); 113 | } 114 | arecnt /= (double) avetimes; 115 | stlog << Buck_Num_PerRow*Row_Num*8*2/1024 << ',' << arecnt << endl; 116 | return; 117 | } 118 | 119 | int main(){ 120 | ofstream stlog("./row3_top1000_maxinterval_memory.csv", std::ios::out | std::ios::trunc); 121 | double basic_buck_num = 8192; 122 | Row_Num = 3; 123 | stlog << "memory(KB), ARE" << endl; 124 | topkthres = 1000; 125 | 126 | while(basic_buck_num <= 65536*4){ 127 | Buck_Num_PerRow = (int)((double)basic_buck_num*3/(double)Row_Num); 128 | ave(stlog); 129 | basic_buck_num *= 2; 130 | } 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/max_inter-arrival/max_interval_vs_topk.cpp: -------------------------------------------------------------------------------- 1 | #include"Interval_old.h" 2 | #include"Interval.h" 3 | #include"packet.h" 4 | 5 | using namespace std; 6 | 7 | const int N = 1000000; 8 | int topkthres = 1000; 9 | map> GT; 10 | map flowmap; 11 | 12 | bool Cmp_By_Value(const pair & lhs, const pair & rhs){ 13 | return lhs.second > rhs.second; 14 | } 15 | 16 | int print_uint128(__uint128_t n) { 17 | if (n == 0) return printf("0"); 18 | 19 | char str[40] = {0}; // log10(1 << 128) + '\0' 20 | char *s = str + sizeof(str) - 1; // start at the end 21 | while (n != 0) { 22 | if (s == str) return -1; // never happens 23 | 24 | *--s = "0123456789"[n % 10]; // save last digit 25 | n /= 10; // drop it 26 | } 27 | return printf("%s", s); 28 | } 29 | 30 | double calcu(ofstream &stlog){ 31 | srand(time(0)); 32 | MinMaxSketch* sketch; 33 | sketch = new MinMaxSketch(0); 34 | 35 | ifstream fin(datapath, std::ios::binary); 36 | timestamp_t k1 = 0; 37 | flow_t k2_128 = 0; 38 | BOBHash32 *delay_hash; delay_hash = new BOBHash32(ABS(rand()%10)); 39 | cout << 1 << endl; 40 | double GTMAX = 0; 41 | fin.read((char*)&k2_128, 13); 42 | fin.read((char*)&k1, sizeof(timestamp_t)); 43 | if(flowmap.find(k2_128) == flowmap.end()){ 44 | flowmap.insert(make_pair(k2_128, 1)); 45 | } 46 | else{ 47 | flowmap[k2_128] += 1; 48 | } 49 | 50 | map sketch_flow_last_timestamp; 51 | map sketch_flow_max_interval; 52 | 53 | rep2(i, 1, N){ 54 | if(i %(N/10) == 0) std::cout << "Loading... "<< i/(N/100) << '%' << endl; 55 | k2_128 = 0, k1 = 0; 56 | fin.read((char*)&k2_128, 13); 57 | fin.read((char*)&k1, 8); 58 | 59 | if(flowmap.find(k2_128) == flowmap.end()){ 60 | flowmap.insert(make_pair(k2_128, 1)); 61 | } 62 | else{ 63 | flowmap[k2_128] += 1; 64 | } 65 | sketch->insert(k2_128, k1); 66 | 67 | if(sketch_flow_last_timestamp.find(k2_128)==sketch_flow_last_timestamp.end()){ 68 | sketch_flow_last_timestamp.insert(make_pair(k2_128, k1)); 69 | } 70 | if(sketch_flow_max_interval.find(k2_128)==sketch_flow_max_interval.end()){ 71 | sketch_flow_max_interval.insert(make_pair(k2_128, 0)); 72 | } 73 | double gt_interval = ABS(k1 - sketch_flow_last_timestamp[k2_128]); 74 | sketch_flow_max_interval[k2_128] = max(sketch_flow_max_interval[k2_128], gt_interval); 75 | sketch_flow_last_timestamp[k2_128] = k1; 76 | } 77 | double are = 0; 78 | double are_old = 0; 79 | double cnt = 0.0; 80 | double correct_cnt = 0.0; 81 | double wrong_cnt = 0.0; 82 | 83 | int topk = topkthres; 84 | int falsecnt = 0; 85 | vector> sorttmp; 86 | map::iterator sortit = flowmap.begin(); 87 | while(sortit != flowmap.end()){ 88 | sorttmp.push_back(*sortit); 89 | sortit++; 90 | } 91 | sort(sorttmp.begin(),sorttmp.end(),Comp); 92 | 93 | rep2(j, 0, topk){ 94 | flow_t flowname = sorttmp[j].first; 95 | timestamp_t max_interval = sketch->query(flowname); 96 | timestamp_t gt_max_interval = sketch_flow_max_interval[flowname]; 97 | are += (ABS(gt_max_interval-max_interval))/(gt_max_interval); 98 | if(gt_max_interval>GTMAX) GTMAX = gt_max_interval; 99 | } 100 | 101 | are /= (topk); 102 | if(sketch) delete sketch; 103 | if(delay_hash) delete delay_hash; 104 | return are; 105 | } 106 | 107 | void ave(ofstream & stlog){ 108 | double arecnt = 0; 109 | //how many times to average 110 | int avetimes = 5; 111 | rep2(i, 0, (unsigned)avetimes){ 112 | arecnt += calcu(stlog); 113 | } 114 | arecnt /= (double) avetimes; 115 | stlog << topkthres << ',' << arecnt << endl; 116 | return; 117 | } 118 | 119 | int main(){ 120 | ofstream stlog("./row3_basicbucknum262144_maxinterval_topk.csv", std::ios::out | std::ios::trunc); 121 | double basic_buck_num = 65536*2*2; 122 | Row_Num = 3; 123 | stlog << "top-k, ARE" << endl; 124 | topkthres = 10; 125 | while(topkthres <= 50000){ 126 | Buck_Num_PerRow = (int)((double)basic_buck_num*3/(double)Row_Num); 127 | ave(stlog); 128 | if(topkthres <= 100) topkthres += 10; 129 | else if(topkthres <= 1000) topkthres += 100; 130 | else if(topkthres <= 10000) topkthres += 1000; 131 | else topkthres += 10000; 132 | } 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/max_inter-arrival/packet.h: -------------------------------------------------------------------------------- 1 | #include"param.h" 2 | 3 | typedef vector > packet_in; 4 | typedef vector, packet_in>> packet_full; 5 | double get_delay(){ 6 | int tmp = rand() % 10000; 7 | return 0.1; 8 | return tmp*0.000001; 9 | } 10 | bool Comp_pair(const tuple & a, const tuple & b){ 11 | return get<1>(a) < get<1>(b); 12 | } 13 | bool Comp(const pair &a, const pair &b){ 14 | return a.second > b.second; 15 | } -------------------------------------------------------------------------------- /cpp/SuMax_Experiments/max_inter-arrival/param.h: -------------------------------------------------------------------------------- 1 | #ifndef Param 2 | #define Param 3 | #include 4 | #include"BOBHash32.h" 5 | 6 | #define fi first 7 | #define se second 8 | #define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 9 | #define rep2(i,a,b) for(int (i)=(a);(i)<(b);(i)++) 10 | #define END_FILE_NO 1 11 | #define START_FILE_NO 0 12 | #define KEY_LENGTH 8 13 | #define ITEM_LENGTH 16 14 | #define MAX(a,b) ((a)>(b)?(a):(b)) 15 | #define MIN(a,b) ((a)<(b)?(a):(b)) 16 | #define ABS(a) ((a)>0?(a):(-(a))) 17 | 18 | #define Lev_Num 8 19 | //#define Row_Num 3 20 | 21 | #define ChangeBuckNum 22 | #ifndef ChangeBuckNum 23 | #define Buck_Num_PerRow 100000 24 | #else 25 | int Buck_Num_PerRow = 65536; 26 | int Row_Num = 3; 27 | double collect_rate = 1.0; 28 | #endif 29 | 30 | #define small 31 | 32 | 33 | // Path of dataset 34 | #define datapath "/usr/share/dataset/CAIDA2018/dataset/130000.dat" 35 | 36 | typedef __uint128_t flow_t; 37 | typedef double_t timestamp_t; 38 | typedef map<__uint128_t, vector > gtmap; 39 | __uint128_t mistake = 0; 40 | unsigned delayLevThres[Lev_Num] = {10, 20, 30, 40, 50, 60, 70, 80}; 41 | unsigned Zeros[Lev_Num] = {0, 0, 0, 0, 0, 0, 0, 0}; 42 | #endif -------------------------------------------------------------------------------- /mininet/README.md: -------------------------------------------------------------------------------- 1 | ## File Descriptions 2 | 3 | - `client` contains the client's traffic generator and sketchlet aggregator. (end-host) 4 | - `switch` contains the switch's control scripts and P4 codes. 5 | 6 | ## Usage 7 | ### Basic Setups 8 | ##### Mininet Setups 9 | - Go to `./switch/p4src_*` folder 10 | - Activate tmux and create duplicate windows 11 | - With window A as the mininet console, type ` sudo p4run ` to evoke the Mininet. 12 | - After mininet_env established, we let window B enter `./switch/scripts` and we type `python routing-controller.py {f/i}` to set the tables in window B, where `f` represents the flowsize test, and `i` represents the interval test. 13 | - Now our Mininet has been fully established. And we are ready to perform the further tests. 14 | 15 | ##### Client Setups 16 | - Go to corresponding `./client/client_*` folder. 17 | - Type `make` to build traffic generator. 18 | - Type `sudo ./traffic` to run clients, they will automatically generate flows, send&receive packets and save the sketchlets. 19 | - Use tools in `/cpp/Simulation_Experiments` to analyze the collected log files in `./client/client_*/download_sketch` and `./switch/switch_log` 20 | 21 | ### More functions and tools 22 | - Sending&Receiving Packets. 23 | - In window C, type `mx h1` and `python simple_sender.py -h` to send packet from h1 and get helps. 24 | - In window D, type `mx h4` and `python simple_receiver.py {f/i}` to listen from an ethernet port. 25 | 26 | - Swaping sketch using `switch/script/monitor.py`. 27 | 28 | - Generating errors using `switch/script/error.py` and `link up`/`link down` instructions in CLI. 29 | 30 | - Generate switch logs. 31 | - enter `switch/script/`, type `mx sw-cpu` and `python log_generator.py {f/i}` to generator switch-collected log. 32 | 33 | - Setting core switch's priority. 34 | - Go to the directory where bmv2 has been installed. Go to `PATH\_TO\_BMV2/targets/simple\_switch/simple\_switch.h`. Look for the line `// #define SSWITCH_PRIORITY_QUEUEING_ON` and uncomment it. 35 | 36 | - Compile and install bmv2 again. 37 | 38 | - Copy `PATH\_TO\_P4C/p4include/v1model.p4` to another location. Add the following metadata fields into the `standard_metadata` struct. You will find a v1model.p4 in this directory. 39 | ``` 40 | @alias("queueing_metadata.qid") bit<5> qid; 41 | @alias("intrinsic_metadata.priority") bit<3> priority; 42 | ``` 43 | - Copy the v1model.p4 to the global path: cp v1model.p4 /usr/local/share/p4c/p4include/. Note that every time you update p4c, this file will be overwritten and the metadatas will be removed. 44 | 45 | - Start Mininet. 46 | - Input in CLI: `p4switch_reboot sw_name --p4src ecmp_priority.p4` 47 | - The rest steps in Basic Setups. 48 | 49 | ## Warnings for p4app.json Configuration 50 | 1. Change program item to the corresponding p4 file. 51 | 2. To use the logs, add `"cpu_port" : true` in every switch's configuration part, _e.g:_ `"s1": {"cpu_port" : true}` 52 | 3. Under different topology, we need change the `main` function of `switch/scripts/log_generator.py` and make sure the listening procedures' number is correpond to the real switch number. 53 | 54 | 55 | ## Other Hints 56 | Scripts in `\switch\scripts` contains the help information, use `-h` to get the detailed help. -------------------------------------------------------------------------------- /mininet/client/client_flowsize/Makefile: -------------------------------------------------------------------------------- 1 | all : sender receiver traffic 2 | 3 | 4 | traffic : traffic.cpp sender receiver 5 | g++ traffic.cpp -o traffic -O2 --std=c++11 -lpthread -g 6 | 7 | sender : sender.cpp sender.h host.h 8 | g++ sender.cpp -o sender -O2 --std=c++11 -g 9 | 10 | receiver : receiver.cpp receiver.h aggregator.h host.h 11 | g++ receiver.cpp -o receiver -O2 --std=c++11 -g 12 | 13 | clean : 14 | rm sender receiver 15 | -------------------------------------------------------------------------------- /mininet/client/client_flowsize/aggregator.h: -------------------------------------------------------------------------------- 1 | #ifndef __AGGREGATOR_H__ 2 | #define __AGGREGATOR_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "header.h" 18 | 19 | using namespace std; 20 | 21 | namespace Simulator { 22 | 23 | using namespace std::chrono; 24 | 25 | struct Sketch { 26 | int ar_num, bu_num; //array_num,bucket_num 27 | 28 | SFH_Header **sketch; 29 | 30 | int switch_id, sketch_fg, fgment_nu; //sketch_flag,fragment_num 31 | 32 | steady_clock::time_point time_beg; 33 | steady_clock::time_point time_end; 34 | 35 | Sketch(int sid, int anum, int bnum) { 36 | ar_num = anum; 37 | bu_num = bnum; 38 | 39 | sketch = new SFH_Header*[ar_num]; 40 | for (int i = 0; i < ar_num; i++) { 41 | sketch[i] = new SFH_Header[bu_num]; 42 | memset(sketch[i], 0xFF, bu_num * sizeof(SFH_Header)); 43 | } 44 | 45 | switch_id = sid; 46 | sketch_fg = 0; 47 | fgment_nu = 0; 48 | } 49 | 50 | void receive_fgment(int sfg, int fid, SFH_Header &sfh_header) { 51 | int aid = sfh_header.fgment_id / bu_num; 52 | int bid = sfh_header.fgment_id % bu_num; 53 | 54 | if (sfg != sketch_fg) { 55 | recv_next_sketch(sfg); 56 | } 57 | 58 | // printf("switch: %d, array: %d, bucket: %d.\n", switch_id, aid, bid); 59 | 60 | if (sketch[aid][bid].switch_id == 0xFFFF) { 61 | recv_next_fgment(sfh_header, aid, bid); 62 | } 63 | } 64 | 65 | void recv_next_sketch(int sfg) { 66 | printf("switch %d detect sketch %d.\n", switch_id, sfg); 67 | 68 | sketch_fg = sfg; 69 | fgment_nu = 0; 70 | for (int i = 0; i < ar_num; i++) { 71 | memset(sketch[i], 0xFF, bu_num * sizeof(SFH_Header)); 72 | } 73 | 74 | time_beg = steady_clock::now(); 75 | } 76 | 77 | void recv_next_fgment(SFH_Header &sfh_header, int aid, int bid) { 78 | sketch[aid][bid] = sfh_header; 79 | fgment_nu += 1; 80 | 81 | printf("switch %d detect fgment %d (%d / %d).\n", 82 | switch_id, sfh_header.fgment_id, fgment_nu, bu_num * ar_num); 83 | 84 | if (fgment_nu == bu_num * ar_num) { 85 | recv_full_sketch(); 86 | } 87 | } 88 | 89 | void recv_full_sketch() { 90 | time_end = steady_clock::now(); 91 | 92 | auto time_epoch = duration_cast (time_end - time_beg); 93 | printf("switch %d receive sketch %d using %ld ms.\n", 94 | switch_id, sketch_fg, time_epoch.count()); 95 | 96 | download_sketch(); 97 | } 98 | 99 | void visor_sketch() { 100 | for (int i = 0; i < ar_num; i++) { 101 | printf("sketch array %d.\n", i); 102 | for (int j = 0; j < 8; j++) { 103 | for (int k = 0; k < bu_num; k++) { 104 | printf("|%3u|", sketch[i][k].delay[j]); 105 | } 106 | printf("\n"); 107 | } 108 | } 109 | } 110 | 111 | void download_sketch(){ 112 | 113 | for (int i = 0; i < ar_num; i++) 114 | { 115 | ofstream out; 116 | string filename = "./download_sketch/switch" + to_string(switch_id) + "_array" + to_string(i) + ".txt"; 117 | out.open(filename, ios::out | ios::trunc); 118 | if (!out.is_open()) 119 | { 120 | return; 121 | } 122 | 123 | for (int j = 0; j < bu_num; j++) 124 | { 125 | for (int k = 0; k < 8; k++) 126 | { 127 | out << sketch[i][j].delay[k] <<'\t'; 128 | } 129 | 130 | out << '\n'; 131 | } 132 | out.close(); 133 | 134 | } 135 | 136 | } 137 | 138 | }; 139 | 140 | struct Aggregator { 141 | int sw_num, ar_num, bu_num; 142 | 143 | Sketch **sketch; 144 | 145 | Aggregator(int snum, int anum, int bnum) { 146 | sw_num = snum; 147 | ar_num = anum; 148 | bu_num = bnum; 149 | 150 | sketch = new Sketch*[sw_num]; 151 | for (int i = 0; i < sw_num; i++) { 152 | sketch[i] = new Sketch(i, anum, bnum); 153 | } 154 | } 155 | 156 | void display_header(COM_Header &com_header) { 157 | //printf("mih.switch_id : %u\n" , com_header.mih.switch_id); 158 | //printf("mih.tim_epoch : %lu\n", com_header.mih.tim_epoch); 159 | printf("sfh.switch_id : %u\n" , com_header.sfh.switch_id); 160 | printf("sfh.sketch_fg : %u\n" , com_header.flag_header.exists_fg & 0x1); 161 | printf("sfh.fgment_id : %u\n" , com_header.sfh.fgment_id); 162 | 163 | printf("sketch fragment :\n"); 164 | 165 | for (int i = 0; i < 8; i++) { 166 | printf("sfh.delay_%d : %u\n", i, com_header.sfh.delay[i]); 167 | } 168 | 169 | printf("\n"); 170 | } 171 | 172 | void receive_header(COM_Header &com_header) { 173 | int switch_id = com_header.sfh.switch_id; 174 | int sketch_fg = com_header.flag_header.exists_fg & 0x1; 175 | int fgment_id = com_header.sfh.fgment_id; 176 | 177 | sketch[switch_id]->receive_fgment(sketch_fg, fgment_id, com_header.sfh); 178 | } 179 | 180 | }; 181 | 182 | } 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /mininet/client/client_flowsize/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | host_num=8 4 | 5 | cat /dev/null > host.config 6 | 7 | for host in $(seq 1 $host_num) 8 | do 9 | echo h$host >> host.config 10 | ps au | grep mininet | grep -w h$host | awk '{print $2}' >> host.config 11 | mx h$host ifconfig | grep inet | grep -v 127.0.0.1 | awk '{print $2}' | tr -d "addr:" >> host.config 12 | done 13 | -------------------------------------------------------------------------------- /mininet/client/client_flowsize/header.h: -------------------------------------------------------------------------------- 1 | #ifndef __HEADER_H__ 2 | #define __HEADER_H__ 3 | 4 | #pragma pack(1) 5 | 6 | namespace Simulator { 7 | 8 | #define MAX_IP_LENGTH 128 9 | #define MAX_PATH_LENGTH 1024 10 | #define MAX_HOST_NUM 1024 11 | 12 | const int sw_num = 20; 13 | const int ar_num = 3; 14 | const int bu_num = 64; 15 | 16 | struct MIH_Header { 17 | uint16_t switch_id; 18 | uint64_t tim_epoch; 19 | uint64_t timestamp; 20 | }; 21 | 22 | struct SFH_Header { 23 | uint16_t switch_id; 24 | uint32_t fgment_id; 25 | uint32_t delay[8]; 26 | }; 27 | 28 | struct FLAG_Header 29 | { 30 | uint8_t exists_fg; 31 | }; 32 | 33 | struct LOAD_Header 34 | { 35 | uint8_t load[1400]; 36 | }; 37 | 38 | struct COM_Header { 39 | FLAG_Header flag_header; 40 | SFH_Header sfh; 41 | LOAD_Header load_header; 42 | 43 | }; 44 | 45 | struct SEND_Header 46 | { 47 | FLAG_Header flag_header; 48 | LOAD_Header load_header; 49 | }; 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /mininet/client/client_flowsize/host.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOST_H__ 2 | #define __HOST_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "header.h" 22 | 23 | namespace Simulator { 24 | 25 | struct Host { 26 | Host(std::string pid) { 27 | switch_namespace(pid); 28 | } 29 | 30 | void switch_namespace(std::string pid) { 31 | char path[MAX_PATH_LENGTH]; 32 | 33 | sprintf(path, "/proc/%s/ns/net", pid.c_str()); 34 | int status_net = attachToNS(path); 35 | // printf("attach net: %d.\n", status_net); 36 | 37 | sprintf(path, "/proc/%s/ns/pid", pid.c_str()); 38 | int status_pid = attachToNS(path); 39 | // printf("attach pid: %d.\n", status_pid); 40 | 41 | sprintf(path, "/proc/%s/ns/mnt", pid.c_str()); 42 | int status_mnt = attachToNS(path); 43 | // printf("attach mnt: %d.\n", status_mnt); 44 | 45 | // if (system("ifconfig | grep inet") != 0) { 46 | // exit(0); 47 | // } 48 | } 49 | 50 | int attachToNS(char *path) { 51 | int nsid = open(path, O_RDONLY); 52 | return setns(nsid, 0); 53 | } 54 | 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /mininet/client/client_flowsize/receiver.h: -------------------------------------------------------------------------------- 1 | #ifndef __RECEIVER_H__ 2 | #define __RECEIVER_H__ 3 | 4 | #include "header.h" 5 | #include "host.h" 6 | #include "aggregator.h" 7 | 8 | namespace Simulator { 9 | 10 | struct Receiver : Host { 11 | sockaddr_in addr_send, addr_recv; 12 | COM_Header com_header; 13 | 14 | int sock_fd, recv_port, addr_len, header_len; 15 | 16 | Aggregator *aggregator; 17 | 18 | Receiver(int port, Aggregator *agg, std::string pid) : 19 | Host(pid), aggregator(agg) { 20 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 21 | 22 | if (sock_fd < 0) { 23 | perror("socket."); 24 | exit(1); 25 | } 26 | 27 | recv_port = port; 28 | 29 | // printf("port: %d.\n", recv_port); 30 | 31 | addr_len = sizeof(addr_recv); 32 | header_len = sizeof(com_header); 33 | 34 | memset((char *)&addr_send, 0x00, addr_len); 35 | memset((char *)&addr_recv, 0x00, addr_len); 36 | memset((char *)&com_header, 0x00, header_len); 37 | 38 | addr_recv.sin_family = AF_INET; 39 | addr_recv.sin_addr.s_addr = htonl(INADDR_ANY); 40 | addr_recv.sin_port = htons(recv_port); 41 | 42 | if (bind(sock_fd, (sockaddr *)&addr_recv, addr_len) < 0) { 43 | perror("bind error."); 44 | exit(1); 45 | } 46 | } 47 | 48 | void receive(int maxp) { 49 | for (int recvp = 0; recvp < maxp || maxp < 0; recvp++) { 50 | int recv_num = recvfrom(sock_fd, (char *)&com_header, header_len, 51 | 0, (sockaddr *)&addr_send, (socklen_t *)&addr_len); 52 | 53 | // printf("receive: %d / %d bytes (PKT : %d, FG : %d)\n", recv_num, 54 | // header_len, recvp, com_header.mih.exists_fg); 55 | // printf("send ip: %s, send port: %d.\n", 56 | // inet_ntoa(addr_send.sin_addr), addr_send.sin_port); 57 | 58 | if (recv_num < 0) { 59 | perror("recvfrom error."); 60 | exit(1); 61 | } 62 | 63 | betoh_header(com_header); 64 | if (com_header.flag_header.exists_fg == 2 || com_header.flag_header.exists_fg == 3) { 65 | aggregator->receive_header(com_header); 66 | } 67 | } 68 | } 69 | 70 | void betoh_header(COM_Header &com_header) { 71 | 72 | com_header.sfh.switch_id = be16toh(com_header.sfh.switch_id); 73 | com_header.sfh.fgment_id = be32toh(com_header.sfh.fgment_id); 74 | 75 | for (int i = 0; i < 8; i++) { 76 | com_header.sfh.delay[i] = be32toh(com_header.sfh.delay[i]); 77 | } 78 | } 79 | 80 | ~Receiver() { 81 | close(sock_fd); 82 | } 83 | }; 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /mininet/client/client_flowsize/sender.h: -------------------------------------------------------------------------------- 1 | #ifndef __SENDER_H__ 2 | #define __SENDER_H__ 3 | 4 | #include "header.h" 5 | #include "host.h" 6 | 7 | namespace Simulator { 8 | 9 | struct Sender : Host { 10 | std::string recv_ip; 11 | 12 | sockaddr_in addr_recv; 13 | SEND_Header send_header; 14 | 15 | int recv_port, sock_fd, addr_len, header_len; 16 | 17 | Sender(std::string ip, int port, std::string pid) : Host(pid) { 18 | 19 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 20 | 21 | if (sock_fd < 0) { 22 | perror("socket error."); 23 | exit(1); 24 | } 25 | 26 | recv_ip = ip; 27 | recv_port = port; 28 | 29 | // printf("ip: %s, port: %d\n", recv_ip.c_str(), recv_port); 30 | 31 | addr_len = sizeof(addr_recv); 32 | header_len = sizeof(send_header); 33 | 34 | memset((char *)&addr_recv, 0x00, addr_len); 35 | memset((char *)&send_header.load_header, 0xFF, sizeof(send_header.load_header)); 36 | 37 | addr_recv.sin_family = AF_INET; 38 | addr_recv.sin_addr.s_addr = inet_addr(recv_ip.c_str()); 39 | addr_recv.sin_port = htons(recv_port); 40 | 41 | send_header.flag_header.exists_fg = 0; 42 | } 43 | 44 | void send(int maxp) { 45 | for (int sendp = 0; sendp < maxp || maxp < 0; sendp++) { 46 | int send_num = sendto(sock_fd, (char *)&send_header, header_len, 47 | 0, (sockaddr *)&addr_recv, addr_len); 48 | 49 | // printf("send: %d / %d bytes (PKT : %d)\n", send_num, header_len, sendp); 50 | // printf("recv ip: %s, recv port: %d\n", recv_ip.c_str(), recv_port); 51 | 52 | if (send_num < 0) { 53 | perror("sendto error."); 54 | exit(1); 55 | } 56 | 57 | // change to 0.1s 58 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 59 | } 60 | } 61 | 62 | ~Sender() { 63 | close(sock_fd); 64 | } 65 | }; 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /mininet/client/client_flowsize/traffic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "header.h" 24 | #include "sender.h" 25 | #include "receiver.h" 26 | #include "aggregator.h" 27 | 28 | using namespace std; 29 | 30 | string hname[MAX_HOST_NUM]; 31 | map host_pid, host_ip; 32 | 33 | std::mutex my_mutex; 34 | vector udp_port_array; 35 | float lambda = 0.001; // 0.00005; 36 | 37 | vector prob_array; 38 | vector flow_size_array; 39 | 40 | inline int bigrand() 41 | { 42 | return rand()%1000 + rand()%1000*1000 + rand()%1000*1000000; 43 | } 44 | 45 | void load_flowsize_distri(char file[]) 46 | { 47 | prob_array.clear(); 48 | flow_size_array.clear(); 49 | 50 | ifstream is(file, ios::in); 51 | string buf; 52 | 53 | int cnt = 0; 54 | while (getline(is, buf)) 55 | { 56 | int s, rd; 57 | float p; 58 | rd = sscanf(buf.c_str(), "%d 1 %f", &s, &p); 59 | if (rd < 2) 60 | break; 61 | prob_array.push_back(p); 62 | flow_size_array.push_back(s); 63 | cnt++; 64 | } 65 | 66 | printf("distribution loaded. (%d levels)\n", cnt); 67 | } 68 | 69 | int flow_size_generator(){ 70 | // float prob_array[9] = {0.0, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1.0}; 71 | // int flow_size_array[9] = {100, 1000, 3000, 4000, 10000, 400000, 3000000, 90000000, 900000000}; 72 | 73 | // only send 1 packet 74 | // return 1; 75 | 76 | int num_lv = prob_array.size(); 77 | 78 | float prob = bigrand() / (1e9-1); 79 | int index; 80 | 81 | if (prob == prob_array[0]){ 82 | return flow_size_array[0]; 83 | }else{ 84 | for (int i = 0; i < num_lv; ++i){ 85 | if (prob <= prob_array[i]){ 86 | index = i; 87 | break; 88 | } 89 | } 90 | 91 | int size = (int)(flow_size_array[index] - (prob_array[index] - prob)/(prob_array[index] - prob_array[index-1])*(flow_size_array[index] - flow_size_array[index-1])); 92 | return size / 1460; // 1460 bit per pkt 93 | } 94 | 95 | } 96 | 97 | int flow_interval_generator(double lambda){ 98 | double pV = 0.0; 99 | while(true) 100 | { 101 | pV = (double)rand()/(double)RAND_MAX; 102 | if (pV != 1) 103 | { 104 | break; 105 | } 106 | } 107 | pV = (-1.0/lambda)*log(1-pV); 108 | return (int)pV; 109 | } 110 | 111 | void Connector_S(string sname, string rname, int rport, int maxp) { 112 | Simulator::Sender sender(host_ip[rname], rport, host_pid[sname]); 113 | 114 | sender.send(maxp); 115 | } 116 | 117 | void Connector_R(string rname, int rport, int maxp, 118 | Simulator::Aggregator *agg) { 119 | Simulator::Receiver receiver(rport, agg, host_pid[rname]); 120 | 121 | receiver.receive(maxp); 122 | } 123 | 124 | void Connector_pair(std::thread **receiver, std::thread **sender, string sname, string rname, Simulator::Aggregator *agg, int ¤t_conn_num, int conn_num){ 125 | 126 | while (true) 127 | { 128 | my_mutex.lock(); 129 | 130 | if (current_conn_num >= conn_num) { 131 | my_mutex.unlock(); 132 | break; 133 | } 134 | 135 | int udp_port_index = rand() % udp_port_array.size(); 136 | int rport = udp_port_array[udp_port_index]; 137 | udp_port_array.erase(udp_port_array.begin() + udp_port_index, udp_port_array.begin() + udp_port_index + 1); 138 | 139 | receiver[current_conn_num] = new std::thread(Connector_R, rname, rport, -1, agg); 140 | 141 | int sendp = flow_size_generator(); 142 | int iterv = flow_interval_generator(lambda); 143 | sender[current_conn_num] = new std::thread(Connector_S, sname, rname, rport, sendp); 144 | 145 | std::cout << sname << " => " << rname << ":" << rport << "(" << sendp << ")" << std::endl; 146 | 147 | ofstream out; 148 | out.open("flow.txt", ios::out | ios::app); 149 | if (out.is_open()) 150 | { 151 | out << sname << " => " << rname << ":" << rport << "(" << sendp << ")" << '\n'; 152 | } 153 | out.close(); 154 | 155 | current_conn_num++; 156 | 157 | my_mutex.unlock(); 158 | 159 | std::this_thread::sleep_for(std::chrono::milliseconds(iterv)); 160 | } 161 | 162 | } 163 | 164 | int config_loader() { 165 | if (system("./config.sh") != 0) { 166 | exit(0); 167 | } 168 | 169 | ifstream loader("./host.config", std::ios::in); 170 | 171 | int host_num = 0; 172 | string name, pid, ip; 173 | 174 | while (loader >> hname[host_num] >> pid >> ip) { 175 | host_pid[hname[host_num]] = pid; 176 | host_ip[hname[host_num]] = ip; 177 | host_num += 1; 178 | } 179 | 180 | std::cout << "hosts:" << std:: endl; 181 | for (int i = 0; i < host_num; i++) { 182 | std::cout << hname[i] << " : (" << host_pid[hname[i]] << ", " << 183 | host_ip[hname[i]] << ")" << std::endl; 184 | } 185 | 186 | return host_num; 187 | } 188 | 189 | void traffic_generator(int host_num, int conn_num) { 190 | Simulator::Aggregator aggregator(Simulator::sw_num, Simulator::ar_num, 191 | Simulator::bu_num); 192 | 193 | std::thread **receiver = new std::thread*[conn_num]; 194 | std::thread **sender = new std::thread*[conn_num]; 195 | std::thread **pair = new std::thread*[host_num*(host_num - 1)]; 196 | 197 | int pair_index = 0; 198 | int current_conn_num = 0; 199 | 200 | ofstream out; 201 | out.open("flow.txt", ios::out | ios::trunc); 202 | out.close(); 203 | 204 | for (int i = 0; i < host_num; i++) { 205 | for (int j = 0; j < host_num; j++) { 206 | if (j != i) { 207 | string sname = hname[i]; 208 | string rname = hname[j]; 209 | 210 | pair[pair_index++] = new thread(Connector_pair, receiver, sender, sname, rname, 211 | &aggregator, std::ref(current_conn_num), conn_num); 212 | } 213 | } 214 | } 215 | 216 | for (int i = 0; i < host_num * (host_num - 1); i++) 217 | { 218 | pair[i] -> join(); 219 | } 220 | 221 | for (int i = 0; i < conn_num; i++) 222 | { 223 | receiver[i] -> join(); 224 | } 225 | 226 | for (int i = 0; i < conn_num; i++) 227 | { 228 | sender[i] -> join(); 229 | } 230 | } 231 | 232 | int main(int argc, char **argv) { 233 | if (argc != 2) { 234 | perror("args error."); 235 | exit(1); 236 | } 237 | 238 | // distribution file 239 | load_flowsize_distri("distri.txt"); 240 | 241 | int host_num = config_loader(); 242 | int conn_num = atoi(argv[1]); 243 | int count = 0; 244 | 245 | while (count < conn_num) 246 | { 247 | // fixed port 248 | int udp_port = rand() % 2000 + 20000; 249 | if (find(udp_port_array.begin(), udp_port_array.end(), udp_port) == udp_port_array.end()) 250 | { 251 | udp_port_array.push_back(udp_port); 252 | count++; 253 | } 254 | 255 | } 256 | 257 | traffic_generator(host_num, conn_num); 258 | 259 | return 0; 260 | } 261 | -------------------------------------------------------------------------------- /mininet/client/client_interval/Makefile: -------------------------------------------------------------------------------- 1 | all : sender receiver traffic 2 | 3 | 4 | traffic : traffic.cpp sender receiver 5 | g++ traffic.cpp -o traffic -O2 --std=c++11 -lpthread -g 6 | 7 | sender : sender.cpp sender.h host.h 8 | g++ sender.cpp -o sender -O2 --std=c++11 -g 9 | 10 | receiver : receiver.cpp receiver.h aggregator.h host.h 11 | g++ receiver.cpp -o receiver -O2 --std=c++11 -g 12 | 13 | clean : 14 | rm sender receiver 15 | -------------------------------------------------------------------------------- /mininet/client/client_interval/aggregator.h: -------------------------------------------------------------------------------- 1 | #ifndef __AGGREGATOR_H__ 2 | #define __AGGREGATOR_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "header.h" 18 | 19 | using namespace std; 20 | 21 | namespace Simulator { 22 | 23 | using namespace std::chrono; 24 | 25 | struct Sketch { 26 | int ar_num, bu_num; //array_num,bucket_num 27 | 28 | MIH_Header **sketch; 29 | 30 | int switch_id, sketch_fg, fgment_nu; //sketch_flag,fragment_num 31 | 32 | steady_clock::time_point time_beg; 33 | steady_clock::time_point time_end; 34 | 35 | Sketch(int sid, int anum, int bnum) { 36 | ar_num = anum; 37 | bu_num = bnum; 38 | 39 | sketch = new MIH_Header*[ar_num]; 40 | for (int i = 0; i < ar_num; i++) { 41 | sketch[i] = new MIH_Header[bu_num]; 42 | memset(sketch[i], 0xFF, bu_num * sizeof(MIH_Header)); 43 | } 44 | 45 | switch_id = sid; 46 | sketch_fg = 0; 47 | fgment_nu = 0; 48 | } 49 | 50 | void receive_fgment(int sfg, int fid, MIH_Header &mih_header) { 51 | int aid = mih_header.fgment_id / bu_num; 52 | int bid = mih_header.fgment_id % bu_num; 53 | 54 | if (sfg != sketch_fg) { 55 | recv_next_sketch(sfg); 56 | } 57 | 58 | // printf("switch: %d, array: %d, bucket: %d.\n", switch_id, aid, bid); 59 | 60 | if (sketch[aid][bid].switch_id == 0xFFFF) { 61 | recv_next_fgment(mih_header, aid, bid); 62 | } 63 | } 64 | 65 | void recv_next_sketch(int sfg) { 66 | printf("switch %d detect sketch %d.\n", switch_id, sfg); 67 | 68 | sketch_fg = sfg; 69 | fgment_nu = 0; 70 | for (int i = 0; i < ar_num; i++) { 71 | memset(sketch[i], 0xFF, bu_num * sizeof(MIH_Header)); 72 | } 73 | 74 | time_beg = steady_clock::now(); 75 | } 76 | 77 | void recv_next_fgment(MIH_Header &mih_header, int aid, int bid) { 78 | sketch[aid][bid] = mih_header; 79 | fgment_nu += 1; 80 | 81 | printf("switch %d detect fgment %d (%d / %d).\n", 82 | switch_id, mih_header.fgment_id, fgment_nu, bu_num * ar_num); 83 | 84 | if (fgment_nu == bu_num * ar_num) { 85 | recv_full_sketch(); 86 | } 87 | } 88 | 89 | void recv_full_sketch() { 90 | time_end = steady_clock::now(); 91 | 92 | auto time_epoch = duration_cast (time_end - time_beg); 93 | printf("switch %d receive sketch %d using %ld ms.\n", 94 | switch_id, sketch_fg, time_epoch.count()); 95 | 96 | download_sketch(); 97 | } 98 | /* 99 | void visor_sketch() { 100 | for (int i = 0; i < ar_num; i++) { 101 | printf("sketch array %d.\n", i); 102 | for (int j = 0; j < bu_num; j++) { 103 | printf("|%3u|", sketch[i][j].timestamp); 104 | printf("\n"); 105 | } 106 | } 107 | }*/ 108 | 109 | void download_sketch(){ 110 | ofstream out; 111 | string filename = "./download_sketch/switch" + to_string(switch_id) + ".txt"; 112 | out.open(filename, ios::out | ios::trunc); 113 | if (!out.is_open()) 114 | { 115 | return; 116 | } else 117 | { 118 | for (int i = 0; i < ar_num; i++) 119 | { 120 | for (int j = 0; j < bu_num; j++) 121 | { 122 | out << sketch[i][j].timestamp <<'\t'; 123 | } 124 | 125 | out << '\n'; 126 | } 127 | 128 | } 129 | 130 | out.close(); 131 | 132 | } 133 | 134 | }; 135 | 136 | struct Aggregator { 137 | int sw_num, ar_num, bu_num; 138 | 139 | Sketch **sketch; 140 | 141 | Aggregator(int snum, int anum, int bnum) { 142 | sw_num = snum; 143 | ar_num = anum; 144 | bu_num = bnum; 145 | 146 | sketch = new Sketch*[sw_num]; 147 | for (int i = 0; i < sw_num; i++) { 148 | sketch[i] = new Sketch(i, anum, bnum); 149 | } 150 | } 151 | 152 | void display_header(COM_Header &com_header) { 153 | 154 | printf("mih.switch_id : %u\n" , com_header.mih.switch_id); 155 | printf("mih.sketch_fg : %u\n" , com_header.flag_header.exists_fg & 0b100); 156 | printf("mih.fgment_id : %u\n" , com_header.mih.fgment_id); 157 | 158 | printf("sketch fragment :\n"); 159 | printf("mih.timestamp : %lu\n", com_header.mih.timestamp); 160 | 161 | printf("\n"); 162 | } 163 | 164 | void receive_header(COM_Header &com_header) { 165 | int switch_id = com_header.mih.switch_id; 166 | int sketch_fg = com_header.flag_header.exists_fg & 0b100; 167 | int fgment_id = com_header.mih.fgment_id; 168 | 169 | sketch[switch_id]->receive_fgment(sketch_fg, fgment_id, com_header.mih); 170 | } 171 | 172 | }; 173 | 174 | } 175 | 176 | #endif 177 | -------------------------------------------------------------------------------- /mininet/client/client_interval/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | host_num=8 4 | 5 | cat /dev/null > host.config 6 | 7 | for host in $(seq 1 $host_num) 8 | do 9 | echo h$host >> host.config 10 | ps au | grep mininet | grep h$host | awk '{print $2}' >> host.config 11 | mx h$host ifconfig | grep inet | grep -v 127.0.0.1 | awk '{print $2}' | tr -d "addr:" >> host.config 12 | done 13 | -------------------------------------------------------------------------------- /mininet/client/client_interval/header.h: -------------------------------------------------------------------------------- 1 | #ifndef __HEADER_H__ 2 | #define __HEADER_H__ 3 | 4 | #pragma pack(1) 5 | 6 | namespace Simulator { 7 | 8 | #define MAX_IP_LENGTH 128 9 | #define MAX_PATH_LENGTH 1024 10 | #define MAX_HOST_NUM 1024 11 | 12 | const int sw_num = 10; 13 | const int ar_num = 3; 14 | const int bu_num = 64; 15 | 16 | struct MIH_Header { 17 | uint16_t switch_id; 18 | uint32_t fgment_id; 19 | uint64_t timestamp; 20 | }; 21 | 22 | struct FLAG_Header 23 | { 24 | uint8_t exists_fg; 25 | }; 26 | 27 | struct LOAD_Header 28 | { 29 | uint8_t load[1400]; 30 | }; 31 | 32 | struct COM_Header { 33 | FLAG_Header flag_header; 34 | MIH_Header mih; 35 | LOAD_Header load_header; 36 | 37 | }; 38 | 39 | struct SEND_Header 40 | { 41 | FLAG_Header flag_header; 42 | LOAD_Header load_header; 43 | }; 44 | 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /mininet/client/client_interval/host.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOST_H__ 2 | #define __HOST_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "header.h" 22 | 23 | namespace Simulator { 24 | 25 | struct Host { 26 | Host(std::string pid) { 27 | switch_namespace(pid); 28 | } 29 | 30 | void switch_namespace(std::string pid) { 31 | char path[MAX_PATH_LENGTH]; 32 | 33 | sprintf(path, "/proc/%s/ns/net", pid.c_str()); 34 | int status_net = attachToNS(path); 35 | // printf("attach net: %d.\n", status_net); 36 | 37 | sprintf(path, "/proc/%s/ns/pid", pid.c_str()); 38 | int status_pid = attachToNS(path); 39 | // printf("attach pid: %d.\n", status_pid); 40 | 41 | sprintf(path, "/proc/%s/ns/mnt", pid.c_str()); 42 | int status_mnt = attachToNS(path); 43 | // printf("attach mnt: %d.\n", status_mnt); 44 | 45 | // if (system("ifconfig | grep inet") != 0) { 46 | // exit(0); 47 | // } 48 | } 49 | 50 | int attachToNS(char *path) { 51 | int nsid = open(path, O_RDONLY); 52 | return setns(nsid, 0); 53 | } 54 | 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /mininet/client/client_interval/receiver.h: -------------------------------------------------------------------------------- 1 | #ifndef __RECEIVER_H__ 2 | #define __RECEIVER_H__ 3 | 4 | #include "header.h" 5 | #include "host.h" 6 | #include "aggregator.h" 7 | 8 | namespace Simulator { 9 | 10 | struct Receiver : Host { 11 | sockaddr_in addr_send, addr_recv; 12 | COM_Header com_header; 13 | 14 | int sock_fd, recv_port, addr_len, header_len; 15 | 16 | Aggregator *aggregator; 17 | 18 | Receiver(int port, Aggregator *agg, std::string pid) : 19 | Host(pid), aggregator(agg) { 20 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 21 | 22 | if (sock_fd < 0) { 23 | perror("socket."); 24 | exit(1); 25 | } 26 | 27 | recv_port = port; 28 | 29 | // printf("port: %d.\n", recv_port); 30 | 31 | addr_len = sizeof(addr_recv); 32 | header_len = sizeof(com_header); 33 | 34 | memset((char *)&addr_send, 0x00, addr_len); 35 | memset((char *)&addr_recv, 0x00, addr_len); 36 | memset((char *)&com_header, 0x00, header_len); 37 | 38 | addr_recv.sin_family = AF_INET; 39 | addr_recv.sin_addr.s_addr = htonl(INADDR_ANY); 40 | addr_recv.sin_port = htons(recv_port); 41 | 42 | if (bind(sock_fd, (sockaddr *)&addr_recv, addr_len) < 0) { 43 | perror("bind error."); 44 | exit(1); 45 | } 46 | } 47 | 48 | void receive(int maxp) { 49 | for (int recvp = 0; recvp < maxp || maxp < 0; recvp++) { 50 | int recv_num = recvfrom(sock_fd, (char *)&com_header, header_len, 51 | 0, (sockaddr *)&addr_send, (socklen_t *)&addr_len); 52 | 53 | // printf("receive: %d / %d bytes (PKT : %d, FG : %d)\n", recv_num, 54 | // header_len, recvp, com_header.mih.exists_fg); 55 | // printf("send ip: %s, send port: %d.\n", 56 | // inet_ntoa(addr_send.sin_addr), addr_send.sin_port); 57 | 58 | if (recv_num < 0) { 59 | perror("recvfrom error."); 60 | exit(1); 61 | } 62 | 63 | betoh_header(com_header); 64 | if (com_header.flag_header.exists_fg == 12 || com_header.flag_header.exists_fg == 8) { 65 | aggregator->receive_header(com_header); 66 | } 67 | } 68 | } 69 | 70 | void betoh_header(COM_Header &com_header) { 71 | 72 | com_header.mih.switch_id = be16toh(com_header.mih.switch_id); 73 | com_header.mih.fgment_id = be32toh(com_header.mih.fgment_id); 74 | 75 | com_header.mih.timestamp = be32toh(com_header.mih.timestamp); 76 | 77 | } 78 | 79 | ~Receiver() { 80 | close(sock_fd); 81 | } 82 | }; 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /mininet/client/client_interval/sender.h: -------------------------------------------------------------------------------- 1 | #ifndef __SENDER_H__ 2 | #define __SENDER_H__ 3 | 4 | #include "header.h" 5 | #include "host.h" 6 | 7 | namespace Simulator { 8 | 9 | struct Sender : Host { 10 | std::string recv_ip; 11 | 12 | sockaddr_in addr_recv; 13 | SEND_Header send_header; 14 | 15 | int recv_port, sock_fd, addr_len, header_len; 16 | 17 | Sender(std::string ip, int port, std::string pid) : Host(pid) { 18 | 19 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 20 | 21 | if (sock_fd < 0) { 22 | perror("socket error."); 23 | exit(1); 24 | } 25 | 26 | recv_ip = ip; 27 | recv_port = port; 28 | 29 | // printf("ip: %s, port: %d\n", recv_ip.c_str(), recv_port); 30 | 31 | addr_len = sizeof(addr_recv); 32 | header_len = sizeof(send_header); 33 | 34 | memset((char *)&addr_recv, 0x00, addr_len); 35 | memset((char *)&send_header.load_header, 0xFF, sizeof(send_header.load_header)); 36 | 37 | addr_recv.sin_family = AF_INET; 38 | addr_recv.sin_addr.s_addr = inet_addr(recv_ip.c_str()); 39 | addr_recv.sin_port = htons(recv_port); 40 | 41 | send_header.flag_header.exists_fg = 0; 42 | } 43 | 44 | void send(int maxp) { 45 | for (int sendp = 0; sendp < maxp || maxp < 0; sendp++) { 46 | int send_num = sendto(sock_fd, (char *)&send_header, header_len, 47 | 0, (sockaddr *)&addr_recv, addr_len); 48 | 49 | // printf("send: %d / %d bytes (PKT : %d)\n", send_num, header_len, sendp); 50 | // printf("recv ip: %s, recv port: %d\n", recv_ip.c_str(), recv_port); 51 | 52 | if (send_num < 0) { 53 | perror("sendto error."); 54 | exit(1); 55 | } 56 | 57 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 58 | } 59 | } 60 | 61 | ~Sender() { 62 | close(sock_fd); 63 | } 64 | }; 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /mininet/client/client_interval/traffic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "header.h" 24 | #include "sender.h" 25 | #include "receiver.h" 26 | #include "aggregator.h" 27 | 28 | using namespace std; 29 | 30 | string hname[MAX_HOST_NUM]; 31 | map host_pid, host_ip; 32 | 33 | std::mutex my_mutex; 34 | vector udp_port_array; 35 | float lambda = 0.001; 36 | 37 | int flow_size_generator(){ 38 | float prob_array[9] = {0.0, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1.0}; 39 | int flow_size_array[9] = {100, 1000, 3000, 4000, 10000, 400000, 3000000, 90000000, 900000000}; 40 | 41 | float prob = (float)(rand() % 101) / 100; 42 | int index; 43 | 44 | if (prob == prob_array[0]){ 45 | return flow_size_array[0]; 46 | }else{ 47 | for (int i = 1; i < 9; ++i){ 48 | if (prob <= prob_array[i]){ 49 | index = i; 50 | break; 51 | } 52 | } 53 | 54 | return (int)(flow_size_array[index] - (prob_array[index] - prob)/(prob_array[index] - prob_array[index-1])*(flow_size_array[index] - flow_size_array[index-1])); 55 | } 56 | 57 | } 58 | 59 | int flow_interval_generator(double lambda){ 60 | double pV = 0.0; 61 | while(true) 62 | { 63 | pV = (double)rand()/(double)RAND_MAX; 64 | if (pV != 1) 65 | { 66 | break; 67 | } 68 | } 69 | pV = (-1.0/lambda)*log(1-pV); 70 | return (int)pV; 71 | } 72 | 73 | void Connector_S(string sname, string rname, int rport, int maxp) { 74 | Simulator::Sender sender(host_ip[rname], rport, host_pid[sname]); 75 | 76 | sender.send(maxp); 77 | } 78 | 79 | void Connector_R(string rname, int rport, int maxp, 80 | Simulator::Aggregator *agg) { 81 | Simulator::Receiver receiver(rport, agg, host_pid[rname]); 82 | 83 | receiver.receive(maxp); 84 | } 85 | 86 | void Connector_pair(std::thread **receiver, std::thread **sender, string sname, string rname, Simulator::Aggregator *agg, int ¤t_conn_num, int conn_num){ 87 | 88 | while (true) 89 | { 90 | my_mutex.lock(); 91 | 92 | if (current_conn_num >= conn_num) { 93 | my_mutex.unlock(); 94 | break; 95 | } 96 | 97 | int udp_port_index = rand() % udp_port_array.size(); 98 | int rport = udp_port_array[udp_port_index]; 99 | udp_port_array.erase(udp_port_array.begin() + udp_port_index, udp_port_array.begin() + udp_port_index + 1); 100 | 101 | receiver[current_conn_num] = new std::thread(Connector_R, rname, rport, -1, agg); 102 | 103 | int sendp = flow_size_generator(); 104 | int iterv = flow_interval_generator(lambda); 105 | sender[current_conn_num] = new std::thread(Connector_S, sname, rname, rport, sendp); 106 | 107 | std::cout << sname << " => " << rname << ":" << rport << "(" << sendp << ")" << std::endl; 108 | 109 | ofstream out; 110 | out.open("flow.txt", ios::out | ios::app); 111 | if (out.is_open()) 112 | { 113 | out << sname << " => " << rname << ":" << rport << "(" << sendp << ")" << '\n'; 114 | } 115 | out.close(); 116 | 117 | current_conn_num++; 118 | 119 | my_mutex.unlock(); 120 | 121 | std::this_thread::sleep_for(std::chrono::milliseconds(iterv)); 122 | } 123 | 124 | } 125 | 126 | int config_loader() { 127 | if (system("./config.sh") != 0) { 128 | exit(0); 129 | } 130 | 131 | ifstream loader("./host.config", std::ios::in); 132 | 133 | int host_num = 0; 134 | string name, pid, ip; 135 | 136 | while (loader >> hname[host_num] >> pid >> ip) { 137 | host_pid[hname[host_num]] = pid; 138 | host_ip[hname[host_num]] = ip; 139 | host_num += 1; 140 | } 141 | 142 | std::cout << "hosts:" << std:: endl; 143 | for (int i = 0; i < host_num; i++) { 144 | std::cout << hname[i] << " : (" << host_pid[hname[i]] << ", " << 145 | host_ip[hname[i]] << ")" << std::endl; 146 | } 147 | 148 | return host_num; 149 | } 150 | 151 | void traffic_generator(int host_num, int conn_num) { 152 | Simulator::Aggregator aggregator(Simulator::sw_num, Simulator::ar_num, 153 | Simulator::bu_num); 154 | 155 | std::thread **receiver = new std::thread*[conn_num]; 156 | std::thread **sender = new std::thread*[conn_num]; 157 | std::thread **pair = new std::thread*[host_num*(host_num - 1)]; 158 | 159 | int pair_index = 0; 160 | int current_conn_num = 0; 161 | 162 | ofstream out; 163 | out.open("flow.txt", ios::out | ios::trunc); 164 | out.close(); 165 | 166 | for (int i = 0; i < host_num; i++) { 167 | for (int j = 0; j < host_num; j++) { 168 | if (j != i) { 169 | string sname = hname[i]; 170 | string rname = hname[j]; 171 | 172 | pair[pair_index++] = new thread(Connector_pair, receiver, sender, sname, rname, 173 | &aggregator, std::ref(current_conn_num), conn_num); 174 | } 175 | } 176 | } 177 | 178 | for (int i = 0; i < host_num * (host_num - 1); i++) 179 | { 180 | pair[i] -> join(); 181 | } 182 | 183 | for (int i = 0; i < conn_num; i++) 184 | { 185 | receiver[i] -> join(); 186 | } 187 | 188 | for (int i = 0; i < conn_num; i++) 189 | { 190 | sender[i] -> join(); 191 | } 192 | } 193 | 194 | int main(int argc, char **argv) { 195 | if (argc != 2) { 196 | perror("args error."); 197 | exit(1); 198 | } 199 | 200 | int host_num = config_loader(); 201 | int conn_num = atoi(argv[1]); 202 | int count = 0; 203 | 204 | while (count < conn_num) 205 | { 206 | int udp_port = rand() % 2000 + 20000; 207 | if (find(udp_port_array.begin(), udp_port_array.end(), udp_port) == udp_port_array.end()) 208 | { 209 | udp_port_array.push_back(udp_port); 210 | count++; 211 | } 212 | 213 | } 214 | 215 | traffic_generator(host_num, conn_num); 216 | 217 | return 0; 218 | } 219 | -------------------------------------------------------------------------------- /mininet/client/client_simple/Makefile: -------------------------------------------------------------------------------- 1 | all : sender receiver traffic 2 | 3 | 4 | traffic : traffic.cpp sender.h receiver.h 5 | g++ traffic.cpp -o traffic -O2 --std=c++11 -lpthread -g 6 | -------------------------------------------------------------------------------- /mininet/client/client_simple/aggregator.h: -------------------------------------------------------------------------------- 1 | #ifndef __AGGREGATOR_H__ 2 | #define __AGGREGATOR_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "header.h" 18 | 19 | using namespace std; 20 | 21 | namespace Simulator { 22 | 23 | using namespace std::chrono; 24 | 25 | struct Sketch { 26 | int ar_num, bu_num; //array_num,bucket_num 27 | 28 | SFH_Header **sketch; 29 | 30 | int switch_id, sketch_fg, fgment_nu; //sketch_flag,fragment_num 31 | 32 | steady_clock::time_point time_beg; 33 | steady_clock::time_point time_end; 34 | 35 | Sketch(int sid, int anum, int bnum) { 36 | ar_num = anum; 37 | bu_num = bnum; 38 | 39 | sketch = new SFH_Header*[ar_num]; 40 | for (int i = 0; i < ar_num; i++) { 41 | sketch[i] = new SFH_Header[bu_num]; 42 | memset(sketch[i], 0xFF, bu_num * sizeof(SFH_Header)); 43 | } 44 | 45 | switch_id = sid; 46 | sketch_fg = 0; 47 | fgment_nu = 0; 48 | } 49 | 50 | void receive_fgment(int sfg, int fid, SFH_Header &sfh_header) { 51 | int aid = sfh_header.fgment_id / bu_num; 52 | int bid = sfh_header.fgment_id % bu_num; 53 | 54 | if (sfg != sketch_fg) { 55 | recv_next_sketch(sfg); 56 | } 57 | 58 | // printf("switch: %d, array: %d, bucket: %d.\n", switch_id, aid, bid); 59 | 60 | if (sketch[aid][bid].switch_id == 0xFFFF) { 61 | recv_next_fgment(sfh_header, aid, bid); 62 | } 63 | } 64 | 65 | void recv_next_sketch(int sfg) { 66 | printf("switch %d detect sketch %d.\n", switch_id, sfg); 67 | 68 | sketch_fg = sfg; 69 | fgment_nu = 0; 70 | for (int i = 0; i < ar_num; i++) { 71 | memset(sketch[i], 0xFF, bu_num * sizeof(SFH_Header)); 72 | } 73 | 74 | time_beg = steady_clock::now(); 75 | } 76 | 77 | void recv_next_fgment(SFH_Header &sfh_header, int aid, int bid) { 78 | sketch[aid][bid] = sfh_header; 79 | fgment_nu += 1; 80 | 81 | printf("switch %d detect fgment %d (%d / %d).\n", 82 | switch_id, sfh_header.fgment_id, fgment_nu, bu_num * ar_num); 83 | 84 | if (fgment_nu == bu_num * ar_num) { 85 | recv_full_sketch(); 86 | } 87 | } 88 | 89 | void recv_full_sketch() { 90 | time_end = steady_clock::now(); 91 | 92 | auto time_epoch = duration_cast (time_end - time_beg); 93 | printf("switch %d receive sketch %d using %ld ms.\n", 94 | switch_id, sketch_fg, time_epoch.count()); 95 | 96 | download_sketch(); 97 | } 98 | 99 | void visor_sketch() { 100 | for (int i = 0; i < ar_num; i++) { 101 | printf("sketch array %d.\n", i); 102 | for (int j = 0; j < 8; j++) { 103 | for (int k = 0; k < bu_num; k++) { 104 | printf("|%3u|", sketch[i][k].delay[j]); 105 | } 106 | printf("\n"); 107 | } 108 | } 109 | } 110 | 111 | void download_sketch(){ 112 | 113 | for (int i = 0; i < ar_num; i++) 114 | { 115 | ofstream out; 116 | string filename = "./download_sketch/switch" + to_string(switch_id) + "_array" + to_string(i) + ".txt"; 117 | out.open(filename, ios::out | ios::trunc); 118 | if (!out.is_open()) 119 | { 120 | return; 121 | } 122 | 123 | for (int j = 0; j < bu_num; j++) 124 | { 125 | for (int k = 0; k < 8; k++) 126 | { 127 | out << sketch[i][j].delay[k] <<'\t'; 128 | } 129 | 130 | out << '\n'; 131 | } 132 | out.close(); 133 | 134 | } 135 | 136 | } 137 | 138 | }; 139 | 140 | struct Aggregator { 141 | int sw_num, ar_num, bu_num; 142 | 143 | Sketch **sketch; 144 | 145 | Aggregator(int snum, int anum, int bnum) { 146 | sw_num = snum; 147 | ar_num = anum; 148 | bu_num = bnum; 149 | 150 | sketch = new Sketch*[sw_num]; 151 | for (int i = 0; i < sw_num; i++) { 152 | sketch[i] = new Sketch(i, anum, bnum); 153 | } 154 | } 155 | 156 | void display_header(COM_Header &com_header) { 157 | //printf("mih.switch_id : %u\n" , com_header.mih.switch_id); 158 | //printf("mih.tim_epoch : %lu\n", com_header.mih.tim_epoch); 159 | printf("sfh.switch_id : %u\n" , com_header.sfh.switch_id); 160 | printf("sfh.sketch_fg : %u\n" , com_header.flag_header.exists_fg & 0x1); 161 | printf("sfh.fgment_id : %u\n" , com_header.sfh.fgment_id); 162 | 163 | printf("sketch fragment :\n"); 164 | 165 | for (int i = 0; i < 8; i++) { 166 | printf("sfh.delay_%d : %u\n", i, com_header.sfh.delay[i]); 167 | } 168 | 169 | printf("\n"); 170 | } 171 | 172 | void receive_header(COM_Header &com_header) { 173 | int switch_id = com_header.sfh.switch_id; 174 | int sketch_fg = com_header.flag_header.exists_fg & 0x1; 175 | int fgment_id = com_header.sfh.fgment_id; 176 | 177 | sketch[switch_id]->receive_fgment(sketch_fg, fgment_id, com_header.sfh); 178 | } 179 | 180 | }; 181 | 182 | } 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /mininet/client/client_simple/config.sh: -------------------------------------------------------------------------------- 1 | !/bin/bash 2 | 3 | host_num=16 4 | 5 | cat /dev/null > host.config 6 | 7 | for host in $(seq 1 $host_num) 8 | do 9 | echo h$host >> host.config 10 | ps au | grep mininet | grep h$host$ | awk '{print $2}' >> host.config 11 | mx h$host ifconfig | grep inet | grep -v 127.0.0.1 | awk '{print $2}' | tr -d "addr:" >> host.config 12 | done 13 | -------------------------------------------------------------------------------- /mininet/client/client_simple/header.h: -------------------------------------------------------------------------------- 1 | #ifndef __HEADER_H__ 2 | #define __HEADER_H__ 3 | 4 | #pragma pack(1) 5 | 6 | namespace Simulator { 7 | 8 | #define MAX_IP_LENGTH 128 9 | #define MAX_PATH_LENGTH 1024 10 | #define MAX_HOST_NUM 1024 11 | 12 | const int sw_num = 10; 13 | const int ar_num = 3; 14 | const int bu_num = 64; 15 | 16 | struct MIH_Header { 17 | uint16_t switch_id; 18 | uint64_t tim_epoch; 19 | uint64_t timestamp; 20 | }; 21 | 22 | struct SFH_Header { 23 | uint16_t switch_id; 24 | //uint8_t sketch_fg; 25 | uint32_t fgment_id; 26 | uint32_t delay[8]; 27 | }; 28 | 29 | struct FLAG_Header 30 | { 31 | uint8_t exists_fg; 32 | }; 33 | 34 | struct LOAD_Header 35 | { 36 | uint16_t packet_id; 37 | uint8_t load[1400]; 38 | }; 39 | 40 | struct COM_Header { 41 | FLAG_Header flag_header; 42 | SFH_Header sfh; 43 | LOAD_Header load_header; 44 | 45 | }; 46 | 47 | struct SEND_Header 48 | { 49 | FLAG_Header flag_header; 50 | LOAD_Header load_header; 51 | }; 52 | 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /mininet/client/client_simple/host.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOST_H__ 2 | #define __HOST_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "header.h" 23 | 24 | namespace Simulator { 25 | 26 | struct Host { 27 | Host(std::string pid) { 28 | switch_namespace(pid); 29 | } 30 | 31 | void switch_namespace(std::string pid) { 32 | char path[MAX_PATH_LENGTH]; 33 | 34 | sprintf(path, "/proc/%s/ns/net", pid.c_str()); 35 | int status_net = attachToNS(path); 36 | // printf("attach net: %d.\n", status_net); 37 | 38 | sprintf(path, "/proc/%s/ns/pid", pid.c_str()); 39 | int status_pid = attachToNS(path); 40 | // printf("attach pid: %d.\n", status_pid); 41 | 42 | sprintf(path, "/proc/%s/ns/mnt", pid.c_str()); 43 | int status_mnt = attachToNS(path); 44 | // printf("attach mnt: %d.\n", status_mnt); 45 | 46 | // if (system("ifconfig | grep inet") != 0) { 47 | // exit(0); 48 | // } 49 | } 50 | 51 | int attachToNS(char *path) { 52 | int nsid = open(path, O_RDONLY); 53 | return setns(nsid, 0); 54 | } 55 | 56 | }; 57 | 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /mininet/client/client_simple/receiver.h: -------------------------------------------------------------------------------- 1 | #ifndef __RECEIVER_H__ 2 | #define __RECEIVER_H__ 3 | 4 | #include "header.h" 5 | #include "host.h" 6 | #include "aggregator.h" 7 | 8 | namespace Simulator { 9 | 10 | struct Receiver : Host { 11 | string recv_ip; 12 | 13 | sockaddr_in addr_send, addr_recv; 14 | COM_Header com_header; 15 | 16 | int sock_fd, recv_port, addr_len, header_len; 17 | 18 | Aggregator *aggregator; 19 | 20 | Receiver(string rip, int port, Aggregator *agg, std::string pid) : 21 | Host(pid), aggregator(agg) { 22 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 23 | 24 | if (sock_fd < 0) { 25 | perror("socket."); 26 | exit(1); 27 | } 28 | 29 | int nRecvBuf = 128 * 1024 * 1024; 30 | setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, (const char*) &nRecvBuf, sizeof(int)); 31 | 32 | recv_ip = rip; 33 | recv_port = port; 34 | 35 | // printf("port: %d.\n", recv_port); 36 | 37 | addr_len = sizeof(addr_recv); 38 | header_len = sizeof(com_header); 39 | 40 | memset((char *)&addr_send, 0x00, addr_len); 41 | memset((char *)&addr_recv, 0x00, addr_len); 42 | memset((char *)&com_header, 0x00, header_len); 43 | 44 | addr_recv.sin_family = AF_INET; 45 | addr_recv.sin_addr.s_addr = htonl(INADDR_ANY); 46 | addr_recv.sin_port = htons(recv_port); 47 | 48 | if (bind(sock_fd, (sockaddr *)&addr_recv, addr_len) < 0) { 49 | perror("bind error."); 50 | exit(1); 51 | } 52 | } 53 | 54 | void receive(int maxp) { 55 | for (int recvp = 0; recvp < maxp || maxp < 0; recvp++) { 56 | int recv_num = recvfrom(sock_fd, (char *)&com_header, header_len, 57 | 0, (sockaddr *)&addr_send, (socklen_t *)&addr_len); 58 | 59 | // printf("receive: %d / %d bytes (PKT : %d, FG : %d)\n", recv_num, 60 | // header_len, recvp, com_header.mih.exists_fg); 61 | // printf("send ip: %s, send port: %d.\n", 62 | // inet_ntoa(addr_send.sin_addr), addr_send.sin_port); 63 | 64 | if (com_header.flag_header.exists_fg) { 65 | printf("recv (%6d, %6d) : %s.\n", recvp, 66 | com_header.load_header.packet_id, recv_ip.c_str()); 67 | } 68 | else { 69 | printf("recv (%6d, %6d) : %s.\n", recvp, 70 | com_header.sfh.switch_id, recv_ip.c_str()); 71 | } 72 | 73 | if (recv_num < 0) { 74 | perror("recvfrom error."); 75 | exit(1); 76 | } 77 | 78 | betoh_header(com_header); 79 | if (aggregator != nullptr && 80 | (com_header.flag_header.exists_fg == 0x02 || 81 | com_header.flag_header.exists_fg == 0x03)) { 82 | aggregator->receive_header(com_header); 83 | } 84 | } 85 | } 86 | 87 | void betoh_header(COM_Header &com_header) { 88 | 89 | com_header.sfh.switch_id = be16toh(com_header.sfh.switch_id); 90 | com_header.sfh.fgment_id = be32toh(com_header.sfh.fgment_id); 91 | 92 | for (int i = 0; i < 8; i++) { 93 | com_header.sfh.delay[i] = be32toh(com_header.sfh.delay[i]); 94 | } 95 | } 96 | 97 | ~Receiver() { 98 | close(sock_fd); 99 | } 100 | }; 101 | } 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /mininet/client/client_simple/sender.h: -------------------------------------------------------------------------------- 1 | #ifndef __SENDER_H__ 2 | #define __SENDER_H__ 3 | 4 | #include "header.h" 5 | #include "host.h" 6 | 7 | namespace Simulator { 8 | 9 | struct Sender : Host { 10 | std::string send_ip, recv_ip; 11 | 12 | sockaddr_in addr_recv; 13 | SEND_Header send_header; 14 | 15 | int recv_port, sock_fd, addr_len, header_len; 16 | 17 | std::mutex *udp_mutex; 18 | 19 | Sender(std::string sip, std::string rip, int port, std::string pid) : Host(pid) { 20 | 21 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 22 | 23 | if (sock_fd < 0) { 24 | perror("socket error."); 25 | exit(1); 26 | } 27 | 28 | int nSendBuf = 128 * 1024 * 1024; 29 | setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, (const char*) &nSendBuf, sizeof(int)); 30 | 31 | send_ip = sip; 32 | recv_ip = rip; 33 | recv_port = port; 34 | 35 | // printf("ip: %s, port: %d\n", recv_ip.c_str(), recv_port); 36 | 37 | addr_len = sizeof(addr_recv); 38 | header_len = sizeof(send_header); 39 | 40 | memset((char *)&addr_recv, 0x00, addr_len); 41 | memset((char *)&send_header.load_header, 0xFF, sizeof(send_header.load_header)); 42 | 43 | addr_recv.sin_family = AF_INET; 44 | addr_recv.sin_addr.s_addr = inet_addr(recv_ip.c_str()); 45 | addr_recv.sin_port = htons(recv_port); 46 | 47 | send_header.flag_header.exists_fg = 0; 48 | } 49 | 50 | void send(int maxp) { 51 | for (int sendp = 0; sendp < maxp || maxp < 0; sendp++) { 52 | udp_mutex->lock(); 53 | 54 | send_header.load_header.packet_id += 1; 55 | 56 | int send_num = sendto(sock_fd, (char *)&send_header, header_len, 57 | 0, (sockaddr *)&addr_recv, addr_len); 58 | 59 | // printf("send: %d / %d bytes (PKT : %d)\n", send_num, header_len, sendp); 60 | // printf("recv ip: %s, recv port: %d\n", recv_ip.c_str(), recv_port); 61 | 62 | printf("send (%6d, %6d) : %s -> %s.\n", sendp, send_header.load_header.packet_id, 63 | send_ip.c_str(), recv_ip.c_str()); 64 | 65 | if (send_num < 0) { 66 | perror("sendto error."); 67 | exit(1); 68 | } 69 | 70 | std::this_thread::sleep_for(std::chrono::milliseconds(80)); 71 | 72 | udp_mutex->unlock(); 73 | } 74 | } 75 | 76 | void set_mutex(std::mutex *udp_mutex) { 77 | this->udp_mutex = udp_mutex; 78 | } 79 | 80 | ~Sender() { 81 | close(sock_fd); 82 | } 83 | }; 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /mininet/client/client_simple/traffic.config: -------------------------------------------------------------------------------- 1 | h1 h2 1000 2 | h1 h3 1000 3 | h1 h4 1000 4 | h1 h5 1000 5 | h1 h6 1000 6 | h1 h7 1000 7 | h1 h8 1000 8 | h1 h9 1000 9 | h1 h10 1000 10 | h1 h11 1000 11 | h1 h12 1000 12 | h1 h13 1000 13 | h1 h14 1000 14 | h1 h15 1000 15 | h1 h16 1000 16 | h2 h1 1000 17 | h2 h3 1000 18 | h2 h4 1000 19 | h2 h5 1000 20 | h2 h6 1000 21 | h2 h7 1000 22 | h2 h8 1000 23 | h2 h9 1000 24 | h2 h10 1000 25 | h2 h11 1000 26 | h2 h12 1000 27 | h2 h13 1000 28 | h2 h14 1000 29 | h2 h15 1000 30 | h2 h16 1000 31 | h3 h1 1000 32 | h3 h2 1000 33 | h3 h4 1000 34 | h3 h5 1000 35 | h3 h6 1000 36 | h3 h7 1000 37 | h3 h8 1000 38 | h3 h9 1000 39 | h3 h10 1000 40 | h3 h11 1000 41 | h3 h12 1000 42 | h3 h13 1000 43 | h3 h14 1000 44 | h3 h15 1000 45 | h3 h16 1000 46 | h4 h1 1000 47 | h4 h2 1000 48 | h4 h3 1000 49 | h4 h5 1000 50 | h4 h6 1000 51 | h4 h7 1000 52 | h4 h8 1000 53 | h4 h9 1000 54 | h4 h10 1000 55 | h4 h11 1000 56 | h4 h12 1000 57 | h4 h13 1000 58 | h4 h14 1000 59 | h4 h15 1000 60 | h4 h16 1000 61 | h5 h1 1000 62 | h5 h2 1000 63 | h5 h3 1000 64 | h5 h4 1000 65 | h5 h6 1000 66 | h5 h7 1000 67 | h5 h8 1000 68 | h5 h9 1000 69 | h5 h10 1000 70 | h5 h11 1000 71 | h5 h12 1000 72 | h5 h13 1000 73 | h5 h14 1000 74 | h5 h15 1000 75 | h5 h16 1000 76 | h6 h1 1000 77 | h6 h2 1000 78 | h6 h3 1000 79 | h6 h4 1000 80 | h6 h5 1000 81 | h6 h7 1000 82 | h6 h8 1000 83 | h6 h9 1000 84 | h6 h10 1000 85 | h6 h11 1000 86 | h6 h12 1000 87 | h6 h13 1000 88 | h6 h14 1000 89 | h6 h15 1000 90 | h6 h16 1000 91 | h7 h1 1000 92 | h7 h2 1000 93 | h7 h3 1000 94 | h7 h4 1000 95 | h7 h5 1000 96 | h7 h6 1000 97 | h7 h8 1000 98 | h7 h9 1000 99 | h7 h10 1000 100 | h7 h11 1000 101 | h7 h12 1000 102 | h7 h13 1000 103 | h7 h14 1000 104 | h7 h15 1000 105 | h7 h16 1000 106 | h8 h1 1000 107 | h8 h2 1000 108 | h8 h3 1000 109 | h8 h4 1000 110 | h8 h5 1000 111 | h8 h6 1000 112 | h8 h7 1000 113 | h8 h9 1000 114 | h8 h10 1000 115 | h8 h11 1000 116 | h8 h12 1000 117 | h8 h13 1000 118 | h8 h14 1000 119 | h8 h15 1000 120 | h8 h16 1000 121 | h9 h1 1000 122 | h9 h2 1000 123 | h9 h3 1000 124 | h9 h4 1000 125 | h9 h5 1000 126 | h9 h6 1000 127 | h9 h7 1000 128 | h9 h8 1000 129 | h9 h10 1000 130 | h9 h11 1000 131 | h9 h12 1000 132 | h9 h13 1000 133 | h9 h14 1000 134 | h9 h15 1000 135 | h9 h16 1000 136 | h10 h1 1000 137 | h10 h2 1000 138 | h10 h3 1000 139 | h10 h4 1000 140 | h10 h5 1000 141 | h10 h6 1000 142 | h10 h7 1000 143 | h10 h8 1000 144 | h10 h9 1000 145 | h10 h11 1000 146 | h10 h12 1000 147 | h10 h13 1000 148 | h10 h14 1000 149 | h10 h15 1000 150 | h10 h16 1000 151 | h11 h1 1000 152 | h11 h2 1000 153 | h11 h3 1000 154 | h11 h4 1000 155 | h11 h5 1000 156 | h11 h6 1000 157 | h11 h7 1000 158 | h11 h8 1000 159 | h11 h9 1000 160 | h11 h10 1000 161 | h11 h12 1000 162 | h11 h13 1000 163 | h11 h14 1000 164 | h11 h15 1000 165 | h11 h16 1000 166 | h12 h1 1000 167 | h12 h2 1000 168 | h12 h3 1000 169 | h12 h4 1000 170 | h12 h5 1000 171 | h12 h6 1000 172 | h12 h7 1000 173 | h12 h8 1000 174 | h12 h9 1000 175 | h12 h10 1000 176 | h12 h11 1000 177 | h12 h13 1000 178 | h12 h14 1000 179 | h12 h15 1000 180 | h12 h16 1000 181 | h13 h1 1000 182 | h13 h2 1000 183 | h13 h3 1000 184 | h13 h4 1000 185 | h13 h5 1000 186 | h13 h6 1000 187 | h13 h7 1000 188 | h13 h8 1000 189 | h13 h9 1000 190 | h13 h10 1000 191 | h13 h11 1000 192 | h13 h12 1000 193 | h13 h14 1000 194 | h13 h15 1000 195 | h13 h16 1000 196 | h14 h1 1000 197 | h14 h2 1000 198 | h14 h3 1000 199 | h14 h4 1000 200 | h14 h5 1000 201 | h14 h6 1000 202 | h14 h7 1000 203 | h14 h8 1000 204 | h14 h9 1000 205 | h14 h10 1000 206 | h14 h11 1000 207 | h14 h12 1000 208 | h14 h13 1000 209 | h14 h15 1000 210 | h14 h16 1000 211 | h15 h1 1000 212 | h15 h2 1000 213 | h15 h3 1000 214 | h15 h4 1000 215 | h15 h5 1000 216 | h15 h6 1000 217 | h15 h7 1000 218 | h15 h8 1000 219 | h15 h9 1000 220 | h15 h10 1000 221 | h15 h11 1000 222 | h15 h12 1000 223 | h15 h13 1000 224 | h15 h14 1000 225 | h15 h16 1000 226 | h16 h1 1000 227 | h16 h2 1000 228 | h16 h3 1000 229 | h16 h4 1000 230 | h16 h5 1000 231 | h16 h6 1000 232 | h16 h7 1000 233 | h16 h8 1000 234 | h16 h9 1000 235 | h16 h10 1000 236 | h16 h11 1000 237 | h16 h12 1000 238 | h16 h13 1000 239 | h16 h14 1000 240 | h16 h15 1000 241 | -------------------------------------------------------------------------------- /mininet/client/client_simple/traffic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "header.h" 24 | #include "sender.h" 25 | #include "receiver.h" 26 | #include "aggregator.h" 27 | 28 | using namespace std; 29 | 30 | map hostPID, hostIP; 31 | map hostThread; 32 | map hostMutex; 33 | 34 | vector connThread; 35 | 36 | void ThreadSend(string sname, string rname, int maxp) { 37 | Simulator::Sender sender(hostIP[sname], hostIP[rname], 50806, hostPID[sname]); 38 | 39 | sender.set_mutex(hostMutex[sname]); 40 | sender.send(maxp); 41 | } 42 | 43 | void ThreadRecv(string rname) { 44 | Simulator::Receiver receiver(hostIP[rname], 50806, nullptr, hostPID[rname]); 45 | 46 | receiver.receive(-1); 47 | } 48 | 49 | void EndhostLoader() { 50 | if (system("./config.sh") != 0) { 51 | exit(0); 52 | } 53 | 54 | ifstream loader("host.config", ios::in); 55 | 56 | string rname, pid, ip; 57 | 58 | while (loader >> rname >> pid >> ip) { 59 | hostPID[rname] = pid; 60 | hostIP[rname] = ip; 61 | hostThread[rname] = new thread(ThreadRecv, rname); 62 | hostMutex[rname] = new mutex; 63 | } 64 | } 65 | 66 | void TrafficLoader() { 67 | ifstream loader("traffic.config", ios::in); 68 | 69 | string sname, rname; 70 | int maxp; 71 | 72 | while (loader >> sname >> rname >> maxp) { 73 | thread *conn = new thread(ThreadSend, sname, rname, maxp); 74 | connThread.push_back(conn); 75 | 76 | cout << sname << " => " << rname << " : " << maxp << endl; 77 | } 78 | 79 | for (auto conn : connThread) { 80 | conn->join(); 81 | } 82 | } 83 | 84 | int main(int argc, char **argv) { 85 | EndhostLoader(); 86 | 87 | TrafficLoader(); 88 | 89 | std::this_thread::sleep_for(std::chrono::seconds(3600)); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /mininet/switch/README.md: -------------------------------------------------------------------------------- 1 | ## File Descriptions 2 | 3 | - `include` contains the related P4 codes. 4 | - `header.p4` defines the header used in P4. 5 | - `parser.p4` defines the parser and deparser used in P4. 6 | - `p4src_sum` contains the codes for the sum tasks simulation (flow size, flow size distribution, entropy, cardinality, and latency distribution). 7 | - `ecmp.p4`: P4 source codes. 8 | - `p4app.json`: P4 configuration codes. 9 | - `ecmp_priority.p4`: P4 configuration codes that set the packet priority. 10 | - `p4src_maximum` contains the codes for maximum tasks simulation (last arrival time, maximum inter-arrival time). Basically the same with `p4src_sum` but implements different function. 11 | - `ecmp.p4`: P4 source codes. 12 | - `p4app.json`: P4 configuration codes. 13 | - `ecmp_priority.p4`:P4 configuration codes that set the packet priority. 14 | - `p4src_simple`: ECMP logic implementation. 15 | - `ecmp.p4`: P4 source codes. 16 | - `header.p4` defines the header used in P4. 17 | - `parser.p4` defines the parser and deparser used in P4. 18 | - `routing_controller.py` automatically fills the route table. 19 | - `iface_moniter.sh` and `iface_moniter.py` are used to monitor per-switch per-port packets. 20 | - `scripts` contains python scripts. 21 | - `error.py`: generate loops and blackholes OR reset the router table. 22 | - `log_generator.py`: generate switch's log. 23 | - `monitor.py`: swap the switch's sketch. 24 | - `routing-controller.py`: basic configuration of router, register, and hash functions. 25 | - `simple_receiver.py`: a packet receiver for testing. 26 | - `simple_sender.py`: a packet sender for testing. 27 | - `visor.py`: print the sketches. 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /mininet/switch/include/headers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | *********************** H E A D E R S *********************************** 3 | *************************************************************************/ 4 | 5 | const bit<16> TYPE_IPV4 = 0x0800; 6 | const bit<8> TYPE_TCP = 6; 7 | const bit<8> TYPE_UDP = 17; 8 | const bit<8> TYPE_ICMP = 1; 9 | 10 | typedef bit<9> egressSpec_t; 11 | typedef bit<48> macAddr_t; 12 | typedef bit<32> ip4Addr_t; 13 | 14 | header ethernet_t { 15 | macAddr_t dstAddr; 16 | macAddr_t srcAddr; 17 | bit<16> etherType; 18 | } 19 | 20 | header ipv4_t { 21 | bit<4> version; 22 | bit<4> ihl; 23 | bit<6> dscp; 24 | bit<2> ecn; 25 | bit<16> totalLen; 26 | bit<16> identification; 27 | bit<3> flags; 28 | bit<13> fragOffset; 29 | bit<8> ttl; 30 | bit<8> protocol; 31 | bit<16> hdrChecksum; 32 | ip4Addr_t srcAddr; 33 | ip4Addr_t dstAddr; 34 | } 35 | 36 | header tcp_t{ 37 | bit<16> srcPort; 38 | bit<16> dstPort; 39 | bit<32> seqNo; 40 | bit<32> ackNo; 41 | bit<4> dataOffset; 42 | bit<1> MIH_fg; 43 | bit<1> SFH_fg; 44 | bit<1> SFH_sketch_number; 45 | bit<1> res; 46 | bit<1> cwr; 47 | bit<1> ece; 48 | bit<1> urg; 49 | bit<1> ack; 50 | bit<1> psh; 51 | bit<1> rst; 52 | bit<1> syn; 53 | bit<1> fin; 54 | bit<16> window; 55 | bit<16> checksum; 56 | bit<16> urgentPtr; 57 | } 58 | 59 | header udp_t { 60 | bit<16> srcPort; 61 | bit<16> dstPort; 62 | bit<16> length; 63 | bit<16> checksum; 64 | } 65 | 66 | // if using udp protocol ,we will use this one to judge whether exists MIH and SFH 67 | header FLAG_t{ 68 | bit<8> flag; //0b1000 for MIH;ob100 for MIH_sketch_number;0b010 for SFH; 0b001 for sfh_sketch_number 69 | } 70 | 71 | //part one of the bringing data 72 | header MIH_t{ 73 | //max interval header 74 | bit<16> mih_switch_id; 75 | bit<32> mih_fgment_id; 76 | bit<16> mih_padding; 77 | bit<48> mih_timestamp; 78 | } 79 | 80 | //sketch fragment header 81 | header SFH_t{ 82 | bit<16> sfh_switch_id; 83 | bit<32> sfh_fgment_id; 84 | 85 | //sketch fragments: a bucket which contains 10 bins 86 | bit<32> sfh_delay0; 87 | bit<32> sfh_delay1; 88 | bit<32> sfh_delay2; 89 | bit<32> sfh_delay3; 90 | bit<32> sfh_delay4; 91 | bit<32> sfh_delay5; 92 | bit<32> sfh_delay6; 93 | bit<32> sfh_delay7; 94 | //bit<32> sfh_delay8; 95 | //bit<32> sfh_delay9; 96 | } 97 | 98 | header cpu_t{ 99 | ip4Addr_t srcAddr; 100 | ip4Addr_t dstAddr; 101 | bit<8> protocol; 102 | bit<16> srcPort; 103 | bit<16> dstPort; 104 | bit<48> delay; 105 | bit<48> interval; 106 | bit<8> flags; 107 | } 108 | 109 | struct metadata { 110 | bit<16> ipv4_srcPort; 111 | bit<16> ipv4_dstPort; 112 | 113 | //for sketch register 114 | bit<32> array_index1; 115 | bit<32> array_index2; 116 | bit<32> array_index0; 117 | bit<32> array_index3; 118 | bit<32> array_index4; 119 | bit<32> array_index5; 120 | 121 | bit<32> array_value0; 122 | bit<32> array_value1; 123 | bit<32> array_value2; 124 | bit<32> array_value3; 125 | bit<32> array_value4; 126 | bit<32> array_value5; 127 | 128 | bit<32> SFH_index; 129 | bit<32> MIH_index; 130 | bit<32> SFH_random; 131 | 132 | //for timestamp register 133 | bit<32> timestamp_index0; 134 | bit<32> timestamp_index1; 135 | bit<32> timestamp_index2; 136 | 137 | bit<48> timestamp_value0; 138 | bit<48> timestamp_value1; 139 | bit<48> timestamp_value2; 140 | 141 | //for counter registers 142 | bit<32> counter_index0; 143 | bit<32> counter_index1; 144 | bit<32> counter_index2; 145 | bit<32> counter_index3; 146 | 147 | bit<1> counter_value0; 148 | bit<1> counter_value1; 149 | bit<1> counter_value2; 150 | 151 | bit<48> MIH_value0; 152 | bit<48> MIH_value1; 153 | bit<48> MIH_value2; 154 | 155 | //for max interval register 156 | 157 | bit<48> max_interval_value0; 158 | bit<48> max_interval_value1; 159 | bit<48> max_interval_value2; 160 | bit<16> switch_id; 161 | bit<48> switch_delay; 162 | bit<8> sketch_fg; 163 | bit<8> swap_control; 164 | 165 | bit<32> delay_lev; 166 | bit<48> previous_ingress_global_timestamp; 167 | bit<48> interval; 168 | 169 | bit<8> SFH_target_array; //the sketch selected 170 | bit<32> SFH_target_bucket; 171 | bit<8> MIH_target_array; //the sketch selected 172 | bit<32> MIH_target_bucket; //the bucket selected 173 | bit<32> random_number; 174 | bit<14> ecmp_hash; 175 | bit<14> ecmp_group_id; 176 | 177 | //tmp use 178 | bit<32> tmp00; 179 | bit<32> tmp01; 180 | bit<32> tmp02; 181 | bit<32> tmp03; 182 | bit<32> tmp04; 183 | bit<32> tmp05; 184 | bit<32> tmp06; 185 | bit<32> tmp07; 186 | bit<32> tmp08; 187 | bit<32> tmp09; 188 | 189 | bit<32> tmp10; 190 | bit<32> tmp11; 191 | bit<32> tmp12; 192 | bit<32> tmp13; 193 | bit<32> tmp14; 194 | bit<32> tmp15; 195 | bit<32> tmp16; 196 | bit<32> tmp17; 197 | bit<32> tmp18; 198 | bit<32> tmp19; 199 | 200 | bit<32> tmp20; 201 | bit<32> tmp21; 202 | bit<32> tmp22; 203 | bit<32> tmp23; 204 | bit<32> tmp24; 205 | bit<32> tmp25; 206 | bit<32> tmp26; 207 | bit<32> tmp27; 208 | bit<32> tmp28; 209 | bit<32> tmp29; 210 | } 211 | 212 | struct headers { 213 | ethernet_t ethernet; 214 | cpu_t CPU; 215 | ipv4_t ipv4; 216 | tcp_t tcp; 217 | udp_t udp; 218 | FLAG_t flag; 219 | MIH_t MIH; 220 | SFH_t SFH; 221 | } 222 | 223 | -------------------------------------------------------------------------------- /mininet/switch/include/parsers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | *********************** P A R S E R ******************************* 3 | *************************************************************************/ 4 | 5 | parser MyParser(packet_in packet, 6 | out headers hdr, 7 | inout metadata meta, 8 | inout standard_metadata_t standard_metadata) { 9 | 10 | state start { 11 | transition parse_ethernet; 12 | } 13 | 14 | state parse_ethernet { 15 | packet.extract(hdr.ethernet); 16 | transition select(hdr.ethernet.etherType){ 17 | TYPE_IPV4: parse_ipv4; 18 | default: accept; 19 | } 20 | } 21 | 22 | state parse_ipv4 { 23 | packet.extract(hdr.ipv4); 24 | transition select(hdr.ipv4.protocol) { 25 | TYPE_TCP : parse_tcp; 26 | TYPE_UDP : parse_udp; 27 | TYPE_ICMP: accept; 28 | default : accept; 29 | } 30 | } 31 | 32 | state parse_tcp { 33 | packet.extract(hdr.tcp); 34 | 35 | meta.ipv4_srcPort = hdr.tcp.srcPort; 36 | meta.ipv4_dstPort = hdr.tcp.dstPort; 37 | 38 | transition select(hdr.tcp.MIH_fg){ 39 | 0 : parse_SFH_of_TCP; 40 | 1 : parse_MIH; 41 | default : accept; 42 | } 43 | } 44 | 45 | state parse_SFH_of_TCP{ 46 | transition select(hdr.tcp.SFH_fg){ 47 | 0 : accept; 48 | 1 : parse_SFH; 49 | default : accept; 50 | } 51 | } 52 | 53 | state parse_udp { 54 | packet.extract(hdr.udp); 55 | 56 | meta.ipv4_srcPort = hdr.udp.srcPort; 57 | meta.ipv4_dstPort = hdr.udp.dstPort; 58 | 59 | transition parse_flag; 60 | } 61 | 62 | //udp only 63 | state parse_flag{ 64 | packet.extract(hdr.flag); 65 | transition select(hdr.flag.flag){ 66 | 12:parse_MIH; 67 | 8: parse_MIH; 68 | 3: parse_SFH; 69 | 2: parse_SFH; 70 | default : accept; 71 | } 72 | } 73 | 74 | state parse_MIH{ 75 | packet.extract(hdr.MIH); 76 | 77 | transition accept; 78 | 79 | } 80 | 81 | state parse_SFH { 82 | packet.extract(hdr.SFH); 83 | transition accept; 84 | } 85 | } 86 | 87 | /************************************************************************* 88 | *********************** D E P A R S E R ******************************* 89 | *************************************************************************/ 90 | 91 | control MyDeparser(packet_out packet, in headers hdr) { 92 | apply { 93 | 94 | //parsed headers have to be added again into the packet. 95 | packet.emit(hdr.ethernet); 96 | packet.emit(hdr.CPU); 97 | packet.emit(hdr.ipv4); 98 | packet.emit(hdr.tcp); 99 | packet.emit(hdr.udp); 100 | packet.emit(hdr.flag); 101 | packet.emit(hdr.MIH); 102 | packet.emit(hdr.SFH); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /mininet/switch/p4src_maximum/p4app.json: -------------------------------------------------------------------------------- 1 | { 2 | "program": "./ecmp.p4", 3 | "switch": "simple_switch", 4 | "compiler": "p4c", 5 | "options": "--target bmv2 --arch v1model --std p4-16", 6 | "switch_cli": "simple_switch_CLI", 7 | "cli": true, 8 | "pcap_dump": false, 9 | "enable_log": false, 10 | "topo_module": { 11 | "file_path": "", 12 | "module_name": "p4utils.mininetlib.apptopo", 13 | "object_name": "AppTopoStrategies" 14 | }, 15 | "controller_module": null, 16 | "topodb_module": { 17 | "file_path": "", 18 | "module_name": "p4utils.utils.topology", 19 | "object_name": "Topology" 20 | }, 21 | "mininet_module": { 22 | "file_path": "", 23 | "module_name": "p4utils.mininetlib.p4net", 24 | "object_name": "P4Mininet" 25 | }, 26 | "topology": { 27 | "assignment_strategy": "l3", 28 | "links": [ 29 | ["h1", "s7", {"bw" : 1}], 30 | ["h2", "s7", {"bw" : 1}], 31 | ["h3", "s8", {"bw" : 1}], 32 | ["h4", "s8", {"bw" : 1}], 33 | ["h5", "s9", {"bw" : 1}], 34 | ["h6", "s9", {"bw" : 1}], 35 | ["h7", "s10", {"bw" : 1}], 36 | ["h8", "s10", {"bw" : 1}], 37 | ["s1", "s3", {"bw" : 1}], 38 | ["s1", "s4", {"bw" : 1}], 39 | ["s1", "s5", {"bw" : 1}], 40 | ["s1", "s6", {"bw" : 1}], 41 | ["s2", "s3", {"bw" : 1}], 42 | ["s2", "s4", {"bw" : 1}], 43 | ["s2", "s5", {"bw" : 1}], 44 | ["s2", "s6", {"bw" : 1}], 45 | ["s3", "s7", {"bw" : 1}], 46 | ["s3", "s8", {"bw" : 1}], 47 | ["s4", "s7", {"bw" : 1}], 48 | ["s4", "s8", {"bw" : 1}], 49 | ["s5", "s9", {"bw" : 1}], 50 | ["s5", "s10", {"bw" : 1}], 51 | ["s6", "s9", {"bw" : 1}], 52 | ["s6", "s10", {"bw" : 1}]], 53 | "hosts": { 54 | "h1": { 55 | }, 56 | "h2": { 57 | }, 58 | "h3": { 59 | }, 60 | "h4": { 61 | }, 62 | "h5": { 63 | }, 64 | "h6": { 65 | }, 66 | "h7": { 67 | }, 68 | "h8": { 69 | } 70 | }, 71 | "switches": { 72 | "s1": {"cpu_port" : true 73 | }, 74 | "s2": {"cpu_port" : true 75 | }, 76 | "s3": {"cpu_port" : true 77 | }, 78 | "s4": {"cpu_port" : true 79 | }, 80 | "s5": {"cpu_port" : true 81 | }, 82 | "s6": {"cpu_port" : true 83 | }, 84 | "s7": {"cpu_port" : true 85 | }, 86 | "s8": {"cpu_port" : true 87 | }, 88 | "s9": {"cpu_port" : true 89 | }, 90 | "s10": {"cpu_port" : true 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /mininet/switch/p4src_simple/ecmp.p4: -------------------------------------------------------------------------------- 1 | 2 | /* -*- P4_16 -*- */ 3 | #include 4 | #include 5 | 6 | //My includes 7 | #include "./headers.p4" 8 | #include "./parsers.p4" 9 | 10 | 11 | 12 | 13 | /************************************************************************* 14 | ************ C H E C K S U M V E R I F I C A T I O N ************* 15 | *************************************************************************/ 16 | 17 | control MyVerifyChecksum(inout headers hdr, inout metadata meta) 18 | { 19 | apply {} 20 | } 21 | 22 | /************************************************************************* 23 | ************** I N G R E S S P R O C E S S I N G ******************* 24 | *************************************************************************/ 25 | 26 | control MyIngress(inout headers hdr, 27 | inout metadata meta, 28 | inout standard_metadata_t standard_metadata) 29 | { 30 | 31 | /******************* inherited code starts here ************************/ 32 | action drop(){ 33 | mark_to_drop(); 34 | } 35 | 36 | action ecmp_group(bit<14> ecmp_group_id, bit<16> num_nhops) 37 | { 38 | hash(meta.ecmp_hash, 39 | HashAlgorithm.crc16, 40 | (bit<1>)0, 41 | {hdr.ipv4.srcAddr, 42 | hdr.ipv4.dstAddr, 43 | meta.ipv4_srcPort, 44 | meta.ipv4_dstPort, 45 | hdr.ipv4.protocol 46 | }, 47 | num_nhops); 48 | meta.ecmp_group_id = ecmp_group_id; 49 | } 50 | 51 | action set_nhop(macAddr_t dstAddr, egressSpec_t port) 52 | { 53 | //set the src mac address as the previous dst, this is not correct right? 54 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 55 | //set the destination mac address that we got from the match in the table 56 | hdr.ethernet.dstAddr = dstAddr; 57 | //set the output port that we also get from the table 58 | standard_metadata.egress_spec = port; 59 | //decrease ttl by 1 60 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 61 | } 62 | 63 | table ecmp_group_to_nhop 64 | { 65 | key = { 66 | meta.ecmp_group_id : exact; 67 | meta.ecmp_hash : exact; 68 | } 69 | actions = { 70 | drop; 71 | set_nhop; 72 | } 73 | size = 1024; 74 | } 75 | 76 | table ipv4_lpm 77 | { 78 | key = { 79 | hdr.ipv4.dstAddr : lpm; 80 | } 81 | actions = { 82 | set_nhop; 83 | ecmp_group; 84 | drop; 85 | } 86 | size = 1024; 87 | default_action = drop; 88 | } 89 | 90 | /******************* inherited code ends here ************************/ 91 | 92 | 93 | 94 | /******** log code starts here*******/ 95 | 96 | 97 | /******** log code ends here*******/ 98 | 99 | apply 100 | { 101 | if (hdr.ipv4.isValid()&&hdr.ipv4.ttl > 1) { 102 | 103 | switch (ipv4_lpm.apply().action_run){ 104 | ecmp_group:{ 105 | ecmp_group_to_nhop.apply(); 106 | } 107 | } 108 | } 109 | else{ 110 | drop(); 111 | } 112 | 113 | } 114 | 115 | } 116 | 117 | /************************************************************************* 118 | **************** E G R E S S P R O C E S S I N G ******************* 119 | *************************************************************************/ 120 | 121 | control MyEgress(inout headers hdr, 122 | inout metadata meta, 123 | inout standard_metadata_t standard_metadata) 124 | { 125 | 126 | 127 | apply 128 | { 129 | if(hdr.ipv4.isValid()&&hdr.udp.isValid()&&standard_metadata.instance_type ==0&&hdr.ipv4.ttl > 1){ 130 | if(!hdr.flag.isValid()){ 131 | hdr.flag.setValid(); 132 | } 133 | hdr.flag.ingress_timestamp=standard_metadata.ingress_global_timestamp; 134 | hdr.flag.egress_timestamp=standard_metadata.egress_global_timestamp; 135 | 136 | 137 | } 138 | 139 | 140 | 141 | } 142 | } 143 | 144 | /************************************************************************* 145 | ************* C H E C K S U M C O M P U T A T I O N ************** 146 | *************************************************************************/ 147 | 148 | control MyComputeChecksum(inout headers hdr, inout metadata meta) 149 | { 150 | apply 151 | { 152 | update_checksum( 153 | hdr.ipv4.isValid(), 154 | {hdr.ipv4.version, 155 | hdr.ipv4.ihl, 156 | hdr.ipv4.dscp, 157 | hdr.ipv4.ecn, 158 | hdr.ipv4.totalLen, 159 | hdr.ipv4.identification, 160 | hdr.ipv4.flags, 161 | hdr.ipv4.fragOffset, 162 | hdr.ipv4.ttl, 163 | hdr.ipv4.protocol, 164 | hdr.ipv4.srcAddr, 165 | hdr.ipv4.dstAddr}, 166 | hdr.ipv4.hdrChecksum, 167 | HashAlgorithm.csum16); 168 | 169 | 170 | 171 | update_checksum_with_payload( 172 | hdr.flag.isValid(), 173 | {hdr.ipv4.srcAddr, 174 | hdr.ipv4.dstAddr, 175 | 8w0, 176 | hdr.ipv4.protocol, 177 | hdr.udp.length, 178 | hdr.udp.srcPort, 179 | hdr.udp.dstPort, 180 | hdr.udp.length, 181 | hdr.flag}, 182 | hdr.udp.checksum, 183 | HashAlgorithm.csum16); 184 | } 185 | } 186 | 187 | /************************************************************************* 188 | *********************** S W I T C H ******************************* 189 | *************************************************************************/ 190 | 191 | //switch architecture 192 | V1Switch( 193 | MyParser(), 194 | MyVerifyChecksum(), 195 | MyIngress(), 196 | MyEgress(), 197 | MyComputeChecksum(), 198 | MyDeparser()) main; 199 | -------------------------------------------------------------------------------- /mininet/switch/p4src_simple/headers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | *********************** H E A D E R S *********************************** 3 | *************************************************************************/ 4 | 5 | const bit<16> TYPE_IPV4 = 0x0800; 6 | const bit<8> TYPE_TCP = 6; 7 | const bit<8> TYPE_UDP = 17; 8 | const bit<8> TYPE_ICMP = 1; 9 | 10 | typedef bit<9> egressSpec_t; 11 | typedef bit<48> macAddr_t; 12 | typedef bit<32> ip4Addr_t; 13 | 14 | header ethernet_t { 15 | macAddr_t dstAddr; 16 | macAddr_t srcAddr; 17 | bit<16> etherType; 18 | } 19 | 20 | header ipv4_t { 21 | bit<4> version; 22 | bit<4> ihl; 23 | bit<6> dscp; 24 | bit<2> ecn; 25 | bit<16> totalLen; 26 | bit<16> identification; 27 | bit<3> flags; 28 | bit<13> fragOffset; 29 | bit<8> ttl; 30 | bit<8> protocol; 31 | bit<16> hdrChecksum; 32 | ip4Addr_t srcAddr; 33 | ip4Addr_t dstAddr; 34 | } 35 | 36 | header tcp_t{ 37 | bit<16> srcPort; 38 | bit<16> dstPort; 39 | bit<32> seqNo; 40 | bit<32> ackNo; 41 | bit<4> dataOffset; 42 | bit<1> MIH_fg; 43 | bit<1> SFH_fg; 44 | bit<1> SFH_sketch_number; 45 | bit<1> res; 46 | bit<1> cwr; 47 | bit<1> ece; 48 | bit<1> urg; 49 | bit<1> ack; 50 | bit<1> psh; 51 | bit<1> rst; 52 | bit<1> syn; 53 | bit<1> fin; 54 | bit<16> window; 55 | bit<16> checksum; 56 | bit<16> urgentPtr; 57 | } 58 | 59 | header udp_t { 60 | bit<16> srcPort; 61 | bit<16> dstPort; 62 | bit<16> length; 63 | bit<16> checksum; 64 | } 65 | 66 | // if using udp protocol ,we will use this one to judge whether exists MIH and SFH 67 | header FLAG_t{ 68 | bit<48> ingress_timestamp; 69 | bit<48> egress_timestamp; 70 | } 71 | 72 | //part one of the bringing data 73 | header MIH_t{ 74 | //max interval header 75 | bit<16> mih_switch_id; 76 | bit<32> mih_fgment_id; 77 | bit<16> mih_padding; 78 | bit<48> mih_timestamp; 79 | } 80 | 81 | //sketch fragment header 82 | header SFH_t{ 83 | bit<16> sfh_switch_id; 84 | bit<32> sfh_fgment_id; 85 | 86 | //sketch fragments: a bucket which contains 10 bins 87 | bit<32> sfh_delay0; 88 | bit<32> sfh_delay1; 89 | bit<32> sfh_delay2; 90 | bit<32> sfh_delay3; 91 | bit<32> sfh_delay4; 92 | bit<32> sfh_delay5; 93 | bit<32> sfh_delay6; 94 | bit<32> sfh_delay7; 95 | //bit<32> sfh_delay8; 96 | //bit<32> sfh_delay9; 97 | } 98 | 99 | header cpu_t{ 100 | ip4Addr_t srcAddr; 101 | ip4Addr_t dstAddr; 102 | bit<8> protocol; 103 | bit<16> srcPort; 104 | bit<16> dstPort; 105 | bit<48> delay; 106 | bit<48> interval; 107 | bit<8> flags; 108 | } 109 | 110 | struct metadata { 111 | bit<16> ipv4_srcPort; 112 | bit<16> ipv4_dstPort; 113 | 114 | //for sketch register 115 | bit<32> array_index1; 116 | bit<32> array_index2; 117 | bit<32> array_index0; 118 | bit<32> array_index3; 119 | bit<32> array_index4; 120 | bit<32> array_index5; 121 | 122 | bit<32> array_value0; 123 | bit<32> array_value1; 124 | bit<32> array_value2; 125 | bit<32> array_value3; 126 | bit<32> array_value4; 127 | bit<32> array_value5; 128 | 129 | bit<32> SFH_index; 130 | bit<32> MIH_index; 131 | bit<32> SFH_random; 132 | 133 | //for timestamp register 134 | bit<32> timestamp_index0; 135 | bit<32> timestamp_index1; 136 | bit<32> timestamp_index2; 137 | 138 | bit<48> timestamp_value0; 139 | bit<48> timestamp_value1; 140 | bit<48> timestamp_value2; 141 | 142 | //for counter registers 143 | bit<32> counter_index0; 144 | bit<32> counter_index1; 145 | bit<32> counter_index2; 146 | bit<32> counter_index3; 147 | 148 | bit<1> counter_value0; 149 | bit<1> counter_value1; 150 | bit<1> counter_value2; 151 | 152 | bit<48> MIH_value0; 153 | bit<48> MIH_value1; 154 | bit<48> MIH_value2; 155 | 156 | //for max interval register 157 | 158 | bit<48> max_interval_value0; 159 | bit<48> max_interval_value1; 160 | bit<48> max_interval_value2; 161 | bit<16> switch_id; 162 | bit<48> switch_delay; 163 | bit<8> sketch_fg; 164 | bit<8> swap_control; 165 | 166 | bit<32> delay_lev; 167 | bit<48> previous_ingress_global_timestamp; 168 | bit<48> interval; 169 | 170 | bit<8> SFH_target_array; //the sketch selected 171 | bit<32> SFH_target_bucket; 172 | bit<8> MIH_target_array; //the sketch selected 173 | bit<32> MIH_target_bucket; //the bucket selected 174 | bit<32> random_number; 175 | bit<14> ecmp_hash; 176 | bit<14> ecmp_group_id; 177 | 178 | //tmp use 179 | bit<32> tmp00; 180 | bit<32> tmp01; 181 | bit<32> tmp02; 182 | bit<32> tmp03; 183 | bit<32> tmp04; 184 | bit<32> tmp05; 185 | bit<32> tmp06; 186 | bit<32> tmp07; 187 | bit<32> tmp08; 188 | bit<32> tmp09; 189 | 190 | bit<32> tmp10; 191 | bit<32> tmp11; 192 | bit<32> tmp12; 193 | bit<32> tmp13; 194 | bit<32> tmp14; 195 | bit<32> tmp15; 196 | bit<32> tmp16; 197 | bit<32> tmp17; 198 | bit<32> tmp18; 199 | bit<32> tmp19; 200 | 201 | bit<32> tmp20; 202 | bit<32> tmp21; 203 | bit<32> tmp22; 204 | bit<32> tmp23; 205 | bit<32> tmp24; 206 | bit<32> tmp25; 207 | bit<32> tmp26; 208 | bit<32> tmp27; 209 | bit<32> tmp28; 210 | bit<32> tmp29; 211 | } 212 | 213 | struct headers { 214 | ethernet_t ethernet; 215 | // cpu_t CPU; 216 | ipv4_t ipv4; 217 | tcp_t tcp; 218 | udp_t udp; 219 | FLAG_t flag; 220 | 221 | // MIH_t MIH; 222 | // SFH_t SFH; 223 | } 224 | 225 | -------------------------------------------------------------------------------- /mininet/switch/p4src_simple/iface_moniter.py: -------------------------------------------------------------------------------- 1 | import nnpy 2 | import time 3 | import struct 4 | from p4utils.utils.topology import Topology 5 | from p4utils.utils.sswitch_API import SimpleSwitchAPI 6 | from scapy.all import * 7 | import sys 8 | import threading 9 | import argparse 10 | 11 | class FLAG(Packet): 12 | name = 'flag' 13 | fields_desc = [BitField('ingress_timestamp',0,48),BitField('egress_timestamp',0,48)] 14 | 15 | 16 | class packetReceiver(): 17 | 18 | def __init__(self, sw_name, iface_name, logf): 19 | self.sw_name = str(sw_name) 20 | self.iface_name = str(iface_name) 21 | self.topo = Topology(db="./topology.db") 22 | self.logf = logf 23 | 24 | self.thrift_port = self.topo.get_thrift_port(sw_name) 25 | self.counter = 1 26 | 27 | logf = open(self.logf, "w") 28 | logf.write(self.sw_name + "-" + self.iface_name + "\n") 29 | logf.close() 30 | 31 | def recv_msg_cpu(self, pkt): 32 | self.counter += 1 33 | ether = pkt.getlayer(Ether) 34 | ip = pkt.getlayer(IP) 35 | tcp=pkt.getlayer(TCP) 36 | udp=pkt.getlayer(UDP) 37 | icmp=pkt.getlayer(ICMP) 38 | if(ip!=None and udp!=None): 39 | self.gen_per_packet_log(ip,udp) 40 | else: 41 | pass 42 | def gen_per_packet_log(self,ip,udp): 43 | 44 | logs=open(self.logf,"a") 45 | 46 | 47 | logs.write('{"switch name":"'+self.sw_name+'",') 48 | logs.write('"packet number":"'+str(self.counter-1)+'","packet_info":{') 49 | logs.write('"srcAddr":"'+str(ip.src)+'",') 50 | logs.write('"dstAddr":"'+str(ip.dst)+'",') 51 | logs.write('"protocol":"'+str(ip.proto)+'",') 52 | logs.write('"srcPort":"'+str(udp.sport)+'",') 53 | logs.write('"dstPort":"'+str(udp.dport)) 54 | flag=FLAG(str(udp.payload)) 55 | if flag!=None: 56 | logs.write(',"ingress timestamp":"'+str(flag.ingress_timestamp)+'",') 57 | logs.write('"egress timestamp":"'+str(flag.egress_timestamp)) 58 | 59 | logs.write(" }}\n") 60 | logs.close() 61 | 62 | def run(self): 63 | sniff(iface=self.sw_name+"-"+self.iface_name, prn=self.recv_msg_cpu) 64 | 65 | 66 | if __name__ == "__main__": 67 | controller = packetReceiver(sys.argv[1], sys.argv[2], sys.argv[3]) 68 | controller.run() 69 | -------------------------------------------------------------------------------- /mininet/switch/p4src_simple/iface_moniter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo python iface_moniter.py s1 eth1 iface_log/s1_eth1.log & 4 | sudo python iface_moniter.py s1 eth2 iface_log/s1_eth2.log & 5 | # sudo python iface_moniter.py s1 eth3 iface_log/s1_eth3.log & 6 | # sudo python iface_moniter.py s1 eth4 iface_log/s1_eth4.log & 7 | 8 | sudo python iface_moniter.py s2 eth1 iface_log/s2_eth1.log & 9 | sudo python iface_moniter.py s2 eth2 iface_log/s2_eth2.log & 10 | # sudo python iface_moniter.py s2 eth3 iface_log/s2_eth3.log & 11 | # sudo python iface_moniter.py s2 eth4 iface_log/s2_eth4.log & 12 | 13 | sudo python iface_moniter.py s3 eth1 iface_log/s3_eth1.log & 14 | sudo python iface_moniter.py s3 eth2 iface_log/s3_eth2.log & 15 | # sudo python iface_moniter.py s3 eth3 iface_log/s3_eth3.log & 16 | # sudo python iface_moniter.py s3 eth4 iface_log/s3_eth4.log & 17 | 18 | sudo python iface_moniter.py s4 eth1 iface_log/s4_eth1.log & 19 | sudo python iface_moniter.py s4 eth2 iface_log/s4_eth2.log & 20 | # sudo python iface_moniter.py s4 eth3 iface_log/s4_eth3.log & 21 | # sudo python iface_moniter.py s4 eth4 iface_log/s4_eth4.log & 22 | 23 | sudo python iface_moniter.py s5 eth1 iface_log/s5_eth1.log & 24 | sudo python iface_moniter.py s5 eth2 iface_log/s5_eth2.log & 25 | # sudo python iface_moniter.py s5 eth3 iface_log/s5_eth3.log & 26 | # sudo python iface_moniter.py s5 eth4 iface_log/s5_eth4.log & 27 | 28 | sudo python iface_moniter.py s6 eth1 iface_log/s6_eth1.log & 29 | sudo python iface_moniter.py s6 eth2 iface_log/s6_eth2.log & 30 | # sudo python iface_moniter.py s6 eth3 iface_log/s6_eth3.log & 31 | # sudo python iface_moniter.py s6 eth4 iface_log/s6_eth4.log & 32 | 33 | sudo python iface_moniter.py s7 eth1 iface_log/s7_eth1.log & 34 | sudo python iface_moniter.py s7 eth2 iface_log/s7_eth2.log & 35 | # sudo python iface_moniter.py s7 eth3 iface_log/s7_eth3.log & 36 | # sudo python iface_moniter.py s7 eth4 iface_log/s7_eth4.log & 37 | 38 | sudo python iface_moniter.py s8 eth1 iface_log/s8_eth1.log & 39 | sudo python iface_moniter.py s8 eth2 iface_log/s8_eth2.log & 40 | # sudo python iface_moniter.py s8 eth3 iface_log/s8_eth3.log & 41 | # sudo python iface_moniter.py s8 eth4 iface_log/s8_eth4.log & 42 | 43 | sudo python iface_moniter.py s9 eth1 iface_log/s9_eth1.log & 44 | sudo python iface_moniter.py s9 eth2 iface_log/s9_eth2.log & 45 | # sudo python iface_moniter.py s9 eth3 iface_log/s9_eth3.log & 46 | # sudo python iface_moniter.py s9 eth4 iface_log/s9_eth4.log & 47 | 48 | sudo python iface_moniter.py s10 eth1 iface_log/s10_eth1.log & 49 | sudo python iface_moniter.py s10 eth2 iface_log/s10_eth2.log & 50 | # sudo python iface_moniter.py s10 eth3 iface_log/s10_eth3.log & 51 | # sudo python iface_moniter.py s10 eth4 iface_log/s10_eth4.log & 52 | 53 | # sudo python iface_moniter.py s11 eth1 iface_log/s11_eth1.log & 54 | # sudo python iface_moniter.py s11 eth2 iface_log/s11_eth2.log & 55 | # sudo python iface_moniter.py s11 eth3 iface_log/s11_eth3.log & 56 | # sudo python iface_moniter.py s11 eth4 iface_log/s11_eth4.log & 57 | 58 | # sudo python iface_moniter.py s12 eth1 iface_log/s12_eth1.log & 59 | # sudo python iface_moniter.py s12 eth2 iface_log/s12_eth2.log & 60 | # sudo python iface_moniter.py s12 eth3 iface_log/s12_eth3.log & 61 | # sudo python iface_moniter.py s12 eth4 iface_log/s12_eth4.log & 62 | 63 | # sudo python iface_moniter.py s13 eth1 iface_log/s13_eth1.log & 64 | # sudo python iface_moniter.py s13 eth2 iface_log/s13_eth2.log & 65 | # sudo python iface_moniter.py s13 eth3 iface_log/s13_eth3.log & 66 | # sudo python iface_moniter.py s13 eth4 iface_log/s13_eth4.log & 67 | 68 | # sudo python iface_moniter.py s14 eth1 iface_log/s14_eth1.log & 69 | # sudo python iface_moniter.py s14 eth2 iface_log/s14_eth2.log & 70 | # sudo python iface_moniter.py s14 eth3 iface_log/s14_eth3.log & 71 | # sudo python iface_moniter.py s14 eth4 iface_log/s14_eth4.log & 72 | 73 | # sudo python iface_moniter.py s15 eth1 iface_log/s15_eth1.log & 74 | # sudo python iface_moniter.py s15 eth2 iface_log/s15_eth2.log & 75 | # sudo python iface_moniter.py s15 eth3 iface_log/s15_eth3.log & 76 | # sudo python iface_moniter.py s15 eth4 iface_log/s15_eth4.log & 77 | 78 | # sudo python iface_moniter.py s16 eth1 iface_log/s16_eth1.log & 79 | # sudo python iface_moniter.py s16 eth2 iface_log/s16_eth2.log & 80 | # sudo python iface_moniter.py s16 eth3 iface_log/s16_eth3.log & 81 | # sudo python iface_moniter.py s16 eth4 iface_log/s16_eth4.log & 82 | 83 | # sudo python iface_moniter.py s17 eth1 iface_log/s17_eth1.log & 84 | # sudo python iface_moniter.py s17 eth2 iface_log/s17_eth2.log & 85 | # sudo python iface_moniter.py s17 eth3 iface_log/s17_eth3.log & 86 | # sudo python iface_moniter.py s17 eth4 iface_log/s17_eth4.log & 87 | 88 | # sudo python iface_moniter.py s18 eth1 iface_log/s18_eth1.log & 89 | # sudo python iface_moniter.py s18 eth2 iface_log/s18_eth2.log & 90 | # sudo python iface_moniter.py s18 eth3 iface_log/s18_eth3.log & 91 | # sudo python iface_moniter.py s18 eth4 iface_log/s18_eth4.log & 92 | 93 | # sudo python iface_moniter.py s19 eth1 iface_log/s19_eth1.log & 94 | # sudo python iface_moniter.py s19 eth2 iface_log/s19_eth2.log & 95 | # sudo python iface_moniter.py s19 eth3 iface_log/s19_eth3.log & 96 | # sudo python iface_moniter.py s19 eth4 iface_log/s19_eth4.log & 97 | 98 | # sudo python iface_moniter.py s20 eth1 iface_log/s20_eth1.log & 99 | # sudo python iface_moniter.py s20 eth2 iface_log/s20_eth2.log & 100 | # sudo python iface_moniter.py s20 eth3 iface_log/s20_eth3.log & 101 | # sudo python iface_moniter.py s20 eth4 iface_log/s20_eth4.log & 102 | -------------------------------------------------------------------------------- /mininet/switch/p4src_simple/parsers.p4: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | *********************** P A R S E R ******************************* 3 | *************************************************************************/ 4 | 5 | parser MyParser(packet_in packet, 6 | out headers hdr, 7 | inout metadata meta, 8 | inout standard_metadata_t standard_metadata) { 9 | 10 | state start { 11 | transition parse_ethernet; 12 | } 13 | 14 | state parse_ethernet { 15 | packet.extract(hdr.ethernet); 16 | transition select(hdr.ethernet.etherType){ 17 | TYPE_IPV4: parse_ipv4; 18 | default: accept; 19 | } 20 | } 21 | 22 | state parse_ipv4 { 23 | packet.extract(hdr.ipv4); 24 | transition select(hdr.ipv4.protocol) { 25 | TYPE_TCP : parse_tcp; 26 | TYPE_UDP : parse_udp; 27 | TYPE_ICMP: accept; 28 | default : accept; 29 | } 30 | } 31 | 32 | state parse_tcp { 33 | packet.extract(hdr.tcp); 34 | 35 | meta.ipv4_srcPort = hdr.tcp.srcPort; 36 | meta.ipv4_dstPort = hdr.tcp.dstPort; 37 | 38 | transition accept; 39 | } 40 | 41 | // state parse_SFH_of_TCP{ 42 | // transition select(hdr.tcp.SFH_fg){ 43 | // 0 : accept; 44 | // 1 : parse_SFH; 45 | // default : accept; 46 | // } 47 | // } 48 | 49 | state parse_udp { 50 | packet.extract(hdr.udp); 51 | 52 | meta.ipv4_srcPort = hdr.udp.srcPort; 53 | meta.ipv4_dstPort = hdr.udp.dstPort; 54 | 55 | transition parse_flag; 56 | } 57 | 58 | //udp only 59 | state parse_flag{ 60 | packet.extract(hdr.flag); 61 | transition accept; 62 | } 63 | 64 | // state parse_MIH{ 65 | // packet.extract(hdr.MIH); 66 | 67 | // transition accept; 68 | 69 | // } 70 | 71 | // state parse_SFH { 72 | // packet.extract(hdr.SFH); 73 | // transition accept; 74 | // } 75 | } 76 | 77 | /************************************************************************* 78 | *********************** D E P A R S E R ******************************* 79 | *************************************************************************/ 80 | 81 | control MyDeparser(packet_out packet, in headers hdr) { 82 | apply { 83 | //parsed headers have to be added again into the packet. 84 | packet.emit(hdr.ethernet); 85 | // packet.emit(hdr.CPU); 86 | packet.emit(hdr.ipv4); 87 | packet.emit(hdr.tcp); 88 | packet.emit(hdr.udp); 89 | packet.emit(hdr.flag); 90 | // packet.emit(hdr.MIH); 91 | // packet.emit(hdr.SFH); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /mininet/switch/scripts/monitor.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from p4utils.utils.topology import Topology 4 | from p4utils.utils.sswitch_API import * 5 | 6 | import threading 7 | import time 8 | import argparse 9 | 10 | BUCKET_NUM = 64 11 | BIN_NUM = 8 12 | ARRAY_NUM = 3 13 | 14 | UPDATE_INTERVAL = 600 15 | 16 | lock = threading.Lock() 17 | 18 | class Monitor(threading.Thread): 19 | 20 | def __init__(self, sw_name,program): 21 | threading.Thread.__init__(self) 22 | if program=="f": 23 | self.topo = Topology(db="../p4src_flowsize/topology.db") #set the topology 24 | elif program=="i": 25 | self.topo = Topology(db="../p4src_interval/topology.db") #set the topology 26 | 27 | self.program=program 28 | self.sw_name = sw_name 29 | self.thrift_port = self.topo.get_thrift_port(sw_name) 30 | self.controller = SimpleSwitchAPI(self.thrift_port) 31 | 32 | 33 | 34 | def sketch_swap(self): 35 | print ("start swapping sketch for switch "+self.sw_name) 36 | self.controller.register_write("swap_control",0,1) 37 | 38 | present_sketch=self.controller.register_read("sketch_fg",0) 39 | 40 | if present_sketch == 0 : 41 | if self.program=="f": 42 | self.controller.register_write("array3",[0,BUCKET_NUM * BIN_NUM],0) 43 | self.controller.register_write("array4",[0,BUCKET_NUM * BIN_NUM],0) 44 | self.controller.register_write("array5",[0,BUCKET_NUM * BIN_NUM],0) 45 | elif self.program=="i": 46 | self.controller.register_write("max_interval_array3",[0,BUCKET_NUM],0) 47 | self.controller.register_write("max_interval_array4",[0,BUCKET_NUM],0) 48 | self.controller.register_write("max_interval_array5",[0,BUCKET_NUM],0) 49 | 50 | 51 | else : 52 | if self.program=="f": 53 | self.controller.register_write("array0",[0,BUCKET_NUM * BIN_NUM],0) 54 | self.controller.register_write("array1",[0,BUCKET_NUM * BIN_NUM],0) 55 | self.controller.register_write("array2",[0,BUCKET_NUM * BIN_NUM],0) 56 | elif self.program=="i": 57 | self.controller.register_write("max_interval_array0",[0,BUCKET_NUM],0) 58 | self.controller.register_write("max_interval_array1",[0,BUCKET_NUM],0) 59 | self.controller.register_write("max_interval_array2",[0,BUCKET_NUM],0) 60 | 61 | 62 | self.controller.register_write("counter0", [0,BUCKET_NUM * ARRAY_NUM], 0); 63 | self.controller.register_write("counter1", [0,BUCKET_NUM * ARRAY_NUM], 0); 64 | self.controller.register_write("counter2", [0,BUCKET_NUM * ARRAY_NUM], 0); 65 | 66 | 67 | self.controller.register_write("swap_control",0,0) 68 | self.controller.register_write("sketch_fg",0,1-present_sketch) 69 | print ("end swapping sketch") 70 | print ("currently using sketch "+ str(1-present_sketch)+" to record") 71 | print ("currently using sketch "+ str(present_sketch)+" to bring\n") 72 | 73 | 74 | #lock.acquire() 75 | #self.visor() 76 | #lock.release() 77 | 78 | #time.sleep(UPDATE_INTERVAL - 2) 79 | 80 | def visor(self): 81 | sf = self.controller.register_read("sketch_fg", 0) 82 | print("switch id :{}".format(self.sw_name)) 83 | print("sketch flag: {}".format(sf)) 84 | 85 | if sf == 1: 86 | print("array0:") 87 | for j in range(0, 10): 88 | for i in range(0, 16): 89 | value = self.controller.register_read("array0", i * 10 + j) 90 | print("|{:^3}|".format(value), end = "") 91 | print() 92 | 93 | print("array1:") 94 | for j in range(0, 10): 95 | for i in range(0, 16): 96 | value = self.controller.register_read("array1", i * 10 + j) 97 | print("|{:^3}|".format(value), end = "") 98 | print() 99 | 100 | print("array2:") 101 | for j in range(0, 10): 102 | for i in range(0, 16): 103 | value = self.controller.register_read("array2", i * 10 + j) 104 | print("|{:^3}|".format(value), end = "") 105 | print() 106 | else: 107 | print("array3:") 108 | for j in range(0, 10): 109 | for i in range(0, 16): 110 | value = self.controller.register_read("array3", i * 10 + j) 111 | print("|{:^3}|".format(value), end = "") 112 | print() 113 | 114 | print("array4:") 115 | for j in range(0, 10): 116 | for i in range(0, 16): 117 | value = self.controller.register_read("array4", i * 10 + j) 118 | print("|{:^3}|".format(value), end = "") 119 | print() 120 | 121 | print("array5:") 122 | for j in range(0, 10): 123 | for i in range(0, 16): 124 | value = self.controller.register_read("array5", i * 10 + j) 125 | print("|{:^3}|".format(value), end = "") 126 | print() 127 | 128 | # for i in range(0, 16): 129 | # value = self.controller.register_read("timestamp_array0", i) 130 | # print("|{:^16}|".format(value), end = "") 131 | # value = self.controller.register_read("timestamp_array1", i) 132 | # print("|{:^16}|".format(value), end = "") 133 | # value = self.controller.register_read("timestamp_array2", i) 134 | # print("|{:^16}|".format(value), end = "") 135 | 136 | def monitor(self): 137 | while True: 138 | current_time = self.controller.sswitch_client.get_time_elapsed_us() \ 139 | % (UPDATE_INTERVAL * 1000 * 1000) 140 | if current_time < 1 * 1000 * 1000: 141 | print(self.controller.sswitch_client.get_time_elapsed_us()) 142 | self.sketch_swap() 143 | 144 | def run(self): 145 | # print("monitor switch {}".format(self.sw_name)) 146 | self.sketch_swap() 147 | 148 | if __name__ == "__main__": 149 | parser=argparse.ArgumentParser() 150 | parser.add_argument("p",help="the program to be run",choices=["f","i"]) 151 | args=parser.parse_args() 152 | ''' 153 | Monitor("s1",args.p).sketch_swap() 154 | Monitor("s2",args.p).sketch_swap() 155 | Monitor("s3",args.p).sketch_swap() 156 | Monitor("s4",args.p).sketch_swap() 157 | Monitor("s5",args.p).sketch_swap() 158 | Monitor("s6",args.p).sketch_swap() 159 | Monitor("s7",args.p).sketch_swap() 160 | Monitor("s8",args.p).sketch_swap() 161 | Monitor("s9",args.p).sketch_swap() 162 | Monitor("s10",args.p).sketch_swap() 163 | ''' 164 | num_switch = 20 165 | monitors = [] 166 | 167 | for i in range(num_switch): 168 | monitors.append(Monitor("s"+str(i+1),args.p)) 169 | 170 | for i in range(num_switch): 171 | monitors[i].start() 172 | 173 | for i in range(num_switch): 174 | monitors[i].join() 175 | -------------------------------------------------------------------------------- /mininet/switch/scripts/simple_receiver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import os 4 | from scapy.all import * 5 | 6 | counter=1; 7 | 8 | class SFH(Packet): 9 | name = 'SFH' 10 | fields_desc = [\ 11 | BitField('sfh_switch_id',0,16),\ 12 | #BitField('sfh_sketch_fg',0,8),\ 13 | BitField('sfh_fgment_id',0,32),\ 14 | BitField('sfh_delay0',0,32),\ 15 | BitField('sfh_delay1',0,32),\ 16 | BitField('sfh_delay2',0,32),\ 17 | BitField('sfh_delay3',0,32),\ 18 | BitField('sfh_delay4',0,32),\ 19 | BitField('sfh_delay5',0,32),\ 20 | BitField('sfh_delay6',0,32),\ 21 | #BitField('sfh_delay7',0,32),\ 22 | #BitField('sfh_delay8',0,32),\ 23 | BitField('sfh_delay7',0,32)] 24 | 25 | class MIH(Packet): 26 | name="MIH" 27 | #bitfiled(,,) 28 | fields_desc=[\ 29 | BitField("mih_switch_id",0,16),\ 30 | BitField("mih_fgment_id",0,32),\ 31 | 32 | BitField("mih_padding",0,16),\ 33 | BitField("mih_timestamp",0,48)] 34 | 35 | class FLAG(Packet): 36 | name="flag" 37 | fields_desc=[\ 38 | BitField("flag",0,8)] 39 | 40 | def get_if(): 41 | iface=None 42 | for i in get_if_list(): 43 | if "eth0" in i: 44 | iface=i 45 | break; 46 | if not iface: 47 | print "Cannot find eth0 interface" 48 | exit(1) 49 | return iface 50 | 51 | def isNotOutgoing(my_mac): 52 | my_mac = my_mac 53 | def _isNotOutgoing(pkt): 54 | return pkt[Ether].src != my_mac 55 | 56 | return _isNotOutgoing 57 | 58 | def handle_pkt(pkt): 59 | global counter 60 | print ("Packet "+str(counter)+" Received:") 61 | counter+=1 62 | 63 | 64 | ether = pkt.getlayer(Ether) 65 | ip = pkt.getlayer(IP) 66 | tcp=pkt.getlayer(TCP) 67 | udp=pkt.getlayer(UDP) 68 | icmp=pkt.getlayer(ICMP) 69 | if udp: 70 | flag=FLAG(str(udp.payload)) 71 | 72 | ''' 73 | print "###[ Ethernet ]###" 74 | print " src: {}".format(ether.src) 75 | print " dst: {}".format(ether.dst) 76 | print "###[ IP ]###" 77 | print " src: {}".format(ip.src) 78 | print " dst: {}".format(ip.dst) 79 | print " IP length:{}".format(ip.len) 80 | ''' 81 | if icmp: 82 | #print "ICMP packet" 83 | pass 84 | 85 | if udp: 86 | ''' 87 | print "###[ UDP ]###" 88 | print " sport: {}".format(udp.sport) 89 | print " dport: {}".format(udp.dport) 90 | print " length: {}".format(udp.len) 91 | print " chksum: {}".format(udp.chksum) 92 | print " udp payload length: {}".format(len(udp.payload)) 93 | ''' 94 | # packet_raw=raw(ip) 95 | # print len(packet_raw) 96 | # udp_raw=packet_raw[20:] 97 | # chksum = in4_chksum(socket.IPPROTO_UDP, pkt[IP], udp_raw) 98 | # print "scapy chksum:"+str(chksum) 99 | 100 | # print "###[ FLAG ]###" 101 | # print " flag: {}".format(flag.flag) 102 | # print " flag payload length: {}".format(len(flag.payload)) 103 | 104 | # if flag.flag&0b1000==0b1000: 105 | # mih=MIH(str(flag.payload)) 106 | # print "###[ MIH ]###" 107 | # print " mih_switch_id: {}".format(mih.mih_switch_id) 108 | # print " mih_timestamp: {}".format(mih.mih_timestamp) 109 | # print " mih_fgment_id: {}".format(mih.mih_fgment_id) 110 | # msg = mih.payload 111 | 112 | # elif flag.flag&0b010==0b010: 113 | # sfh=SFH(str(flag.payload)) 114 | # if (sfh.sfh_fgment_id==64 or sfh.sfh_fgment_id==63 or sfh.sfh_fgment_id==65 ) : 115 | # print "###[ SFH ]###" 116 | # print " sfh_switch_id: {}".format(sfh.sfh_switch_id) 117 | # #print " sfh_sketch_fg: {}".format(sfh.sfh_sketch_fg) 118 | # print " sfh_fgment_id: {}".format(sfh.sfh_fgment_id) 119 | # print " sfh_delay0: {}".format(sfh.sfh_delay0) 120 | # print " sfh_delay1: {}".format(sfh.sfh_delay1) 121 | # print " sfh_delay2: {}".format(sfh.sfh_delay2) 122 | # print " sfh_delay3: {}".format(sfh.sfh_delay3) 123 | # print " sfh_delay4: {}".format(sfh.sfh_delay4) 124 | # print " sfh_delay5: {}".format(sfh.sfh_delay5) 125 | # print " sfh_delay6: {}".format(sfh.sfh_delay6) 126 | # print " sfh_delay7: {}".format(sfh.sfh_delay7) 127 | # #print " sfh_delay8: {}".format(sfh.sfh_delay8) 128 | # #print " sfh_delay9: {}".format(sfh.sfh_delay9) 129 | # msg = sfh.payload 130 | # else: 131 | # msg=flag.payload 132 | #print "###[ MESSAGE ]###" 133 | # 134 | #print (type(str(msg))) 135 | #print (msg) 136 | #print "msg length: {}".format(len(msg)) 137 | 138 | #print 139 | 140 | def main(): 141 | ifaces = filter(lambda i: 'eth' in i, os.listdir('/sys/class/net/')) 142 | iface = ifaces[0] 143 | print "sniffing on %s" % iface 144 | sys.stdout.flush() 145 | my_filter = isNotOutgoing(get_if_hwaddr(get_if())) 146 | sniff(filter="ip", iface = iface, 147 | prn = lambda x: handle_pkt(x), lfilter=my_filter) 148 | 149 | if __name__ == '__main__': 150 | 151 | main() 152 | -------------------------------------------------------------------------------- /mininet/switch/scripts/simple_sender.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import socket 4 | import random 5 | import time 6 | import argparse 7 | from subprocess import Popen, PIPE 8 | import re 9 | from threading import Thread, Event 10 | from scapy.all import * 11 | from p4utils.utils.topology import Topology 12 | 13 | 14 | 15 | class MIH(Packet): 16 | name="MIH" 17 | #bitfiled(,,) 18 | fields_desc=[\ 19 | BitField("mih_switch_id",0,16),\ 20 | BitField("mih_timestamp",0,48),\ 21 | BitField("mih_padding",0,16),\ 22 | BitField("sfh_exists_fg",0,8)] 23 | 24 | class flag(Packet): 25 | name="flag" 26 | fields_desc=[\ 27 | BitField("mih_switch_id",0,8)] 28 | 29 | 30 | #always via eth0 31 | def get_if(): 32 | ifs=get_if_list() 33 | iface=None # "h1-eth0" 34 | for i in get_if_list(): 35 | if "eth0" in i: 36 | iface=i 37 | break; 38 | if not iface: 39 | print "Cannot find eth0 interface" 40 | exit(1) 41 | return iface 42 | 43 | 44 | def get_dst_mac(ip): 45 | try: 46 | pid = Popen(["arp", "-n", ip], stdout=PIPE) 47 | s = pid.communicate()[0] 48 | mac = re.search(r"(([a-f\d]{1,2}\:){5}[a-f\d]{1,2})", s).groups()[0] 49 | return mac 50 | except: 51 | return None 52 | 53 | 54 | def send_packet(interface,args,program): 55 | 56 | # a l2 implementation 57 | #dstAddr = socket.gethostbyname(args.d) 58 | #print(socket.getaddrinfo(sys.argv[1], None, 0, socket.SOCK_STREAM)) 59 | #ether_dst = get_dst_mac(dstAddr) 60 | #if not ether_dst: 61 | # print "Mac address for %s was not found in the ARP table" % dstAddr 62 | # exit(1) 63 | #pkt= Ether(src=get_if_hwaddr(interface),dst=ether_dst) 64 | #pkt=pkt/IP(dst=dstAddr) 65 | 66 | 67 | #warning! 68 | #if want to send TCP ,must change the parser of p4 69 | 70 | if program=="f": 71 | topo = Topology(db="../p4src_flowsize/topology.db") #set the topology 72 | elif program=="i": 73 | topo = Topology(db="../p4src_interval/topology.db") #set the topology 74 | dstAddr=topo.get_host_ip(args.d) 75 | pkt=IP(dst=dstAddr) 76 | if args.type=="tcp" : 77 | pkt=pkt/TCP() 78 | elif args.type=="udp": 79 | pkt=pkt/UDP() 80 | pkt=pkt/flag()/"load0load1load2load3" 81 | else: 82 | pkt=pkt/ICMP() 83 | while True: 84 | raw_input("Testing! Press the return key to send a packet using "+args.type.lower()) 85 | print "Sending on interface %s \n"%(interface) 86 | #sendp(pkt, iface=iface, verbose=False) 87 | for i in range(args.number): 88 | send(pkt) 89 | 90 | 91 | 92 | def main(): 93 | parser=argparse.ArgumentParser() 94 | parser.add_argument("d",help="the dst host name") 95 | parser.add_argument("p",help="the program to be run",choices=["f","i"]) 96 | 97 | parser.add_argument("-t","--type",help="the packet type to be sent",default="udp",choices=["udp","tcp","icmp"]) 98 | parser.add_argument("-n","--number",help="the packet number to be sent",type=int,default=1) 99 | args=parser.parse_args() 100 | 101 | interface=get_if() 102 | send_packet(interface,args,args.p) 103 | 104 | if __name__ == "__main__": 105 | main() 106 | -------------------------------------------------------------------------------- /mininet/switch/scripts/visor.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from p4utils.utils.topology import Topology 4 | from p4utils.utils.sswitch_API import * 5 | import socket, struct, pickle, os 6 | from scapy.all import Ether, sniff, Packet, BitField 7 | import time 8 | import sys 9 | 10 | class Monitor(object): 11 | 12 | def __init__(self, sw_name): 13 | 14 | self.topo = Topology(db="../p4src_flowsize/topology.db") 15 | self.sw_name = sw_name 16 | self.thrift_port = self.topo.get_thrift_port(sw_name) 17 | self.controller = SimpleSwitchAPI(self.thrift_port) 18 | 19 | def visor(self): 20 | sf = self.controller.register_read("sketch_fg", 0) 21 | print("sketch flag: {}".format(sf)) 22 | 23 | if sf == 0: 24 | print("array0:") 25 | for j in range(0, 8): 26 | for i in range(0, 64): 27 | value = self.controller.register_read("array0", i * 8 + j) 28 | print("|{:^3}|".format(value), end = "") 29 | print() 30 | print() 31 | 32 | print("array1:") 33 | for j in range(0, 8): 34 | for i in range(0, 64): 35 | value = self.controller.register_read("array1", i * 8 + j) 36 | print("|{:^3}|".format(value), end = "") 37 | print() 38 | print() 39 | 40 | print("array2:") 41 | for j in range(0, 8): 42 | for i in range(0, 64): 43 | value = self.controller.register_read("array2", i * 8 + j) 44 | print("|{:^3}|".format(value), end = "") 45 | print() 46 | print() 47 | else: 48 | print("array3:") 49 | for j in range(0, 8): 50 | for i in range(0, 64): 51 | value = self.controller.register_read("array3", i * 8 + j) 52 | print("|{:^3}|".format(value), end = "") 53 | print() 54 | print() 55 | 56 | print("array4:") 57 | for j in range(0, 8): 58 | for i in range(0, 64): 59 | value = self.controller.register_read("array4", i * 8 + j) 60 | print("|{:^3}|".format(value), end = "") 61 | print() 62 | print() 63 | 64 | print("array5:") 65 | for j in range(0, 8): 66 | for i in range(0, 64): 67 | value = self.controller.register_read("array5", i * 8 + j) 68 | print("|{:^3}|".format(value), end = "") 69 | print() 70 | print() 71 | 72 | # for i in range(0, 16): 73 | # value = self.controller.register_read("timestamp_array0", i) 74 | # print("|{:^16}|".format(value), end = "") 75 | # value = self.controller.register_read("timestamp_array1", i) 76 | # print("|{:^16}|".format(value), end = "") 77 | # value = self.controller.register_read("timestamp_array2", i) 78 | # print("|{:^16}|".format(value), end = "") 79 | # print() 80 | 81 | 82 | if __name__ == "__main__": 83 | Monitor(sys.argv[1]).visor() 84 | -------------------------------------------------------------------------------- /testbed/README.md: -------------------------------------------------------------------------------- 1 | ## File Description 2 | 3 | * ```Tofino_sum``` contains the codes for the sum tasks (including estimating flow size, flow size distribution, entropy, cardinality, and latency distribution). 4 | * ```Tofino_maximum``` contains the codes for the maximum tasks (recording last arrival time and maximum inter-arrival time). 5 | * ```analyzer``` contains the codes to perform the global analysis. 6 | 7 | -------------------------------------------------------------------------------- /testbed/Tofino_maximum/README.md: -------------------------------------------------------------------------------- 1 | ## P4 implementation 2 | The codes for packet-interval estimation. `timeSF.p4` is the data plane codes, `timeSF.py` is the control plane codes. 3 | 4 | ### Requirements 5 | - Please compile and run the codes on a Tofino ASIC. 6 | 7 | ### Usage 8 | - To run the control plane, you must complie the p4 program `timeSF.p4` with compiling option `--with-thrift` 9 | - Configure `ecmp.txt` as you need. 10 | 11 | -------------------------------------------------------------------------------- /testbed/Tofino_maximum/ggs.txt: -------------------------------------------------------------------------------- 1 | 0 1 2 | 2 1 3 | 1 5 4 | 3 5 5 | -------------------------------------------------------------------------------- /testbed/Tofino_maximum/includes/header_and_parser.p4: -------------------------------------------------------------------------------- 1 | 2 | header_type ethernet_t { 3 | fields { 4 | dmac : 48; 5 | smac : 48; 6 | ethertype : 16; 7 | } 8 | } 9 | header ethernet_t ethernet; 10 | header ethernet_t ethernet1; 11 | 12 | 13 | header_type vxlan_t 14 | { 15 | fields 16 | { 17 | vx1:32; 18 | vx2:32; 19 | } 20 | } 21 | header vxlan_t vxlan; 22 | 23 | 24 | 25 | header_type ipv4_t { 26 | fields { 27 | ver : 4; 28 | len : 4; 29 | diffserv : 6; 30 | ecn: 2; 31 | totalLen : 16; 32 | id : 16; 33 | flags : 3; 34 | offset : 13; 35 | ttl : 8; 36 | proto : 8; 37 | csum : 16; 38 | sip : 32; 39 | dip : 32; 40 | } 41 | } 42 | header ipv4_t ipv4; 43 | header ipv4_t ipv41; 44 | 45 | field_list ipv4_checksum_list { 46 | ipv4.ver; 47 | ipv4.len; 48 | ipv4.diffserv; 49 | ipv4.ecn; 50 | ipv4.totalLen; 51 | ipv4.id; 52 | ipv4.flags; 53 | ipv4.offset; 54 | ipv4.ttl; 55 | ipv4.proto; 56 | ipv4.sip; 57 | ipv4.dip; 58 | } 59 | 60 | field_list_calculation ipv4_checksum { 61 | input { 62 | ipv4_checksum_list; 63 | } 64 | algorithm : csum16; 65 | output_width : 16; 66 | } 67 | 68 | calculated_field ipv4.csum { 69 | update ipv4_checksum; 70 | } 71 | 72 | 73 | header_type tcp_t { 74 | fields { 75 | sPort : 16; 76 | dPort : 16; 77 | seqNo : 32; 78 | ackNo : 32; 79 | dataOffset : 4; 80 | res : 3; 81 | ecn : 3; 82 | ctrl : 6; 83 | window : 16; 84 | checksum : 16; 85 | urgentPtr : 16; 86 | } 87 | } 88 | header tcp_t tcp; 89 | 90 | header_type udp_t { 91 | fields { 92 | sPort : 16; 93 | dPort : 16; 94 | hdr_length : 16; 95 | checksum : 16; 96 | } 97 | } 98 | header udp_t udp; 99 | header udp_t udp1; 100 | header_type arp_t{ 101 | fields { 102 | hType: 16; 103 | pType: 16; 104 | hLen: 8; 105 | pLen: 8; 106 | oper: 16; 107 | hSrc: 48; 108 | pSrc: 32; 109 | hDst: 48; 110 | pDst: 32; 111 | } 112 | } 113 | header arp_t arp; 114 | 115 | header_type FS_h_t 116 | { 117 | fields { 118 | type:16; 119 | ID:16; 120 | binid:16; 121 | sketchid:16; 122 | 123 | 124 | 125 | } 126 | } 127 | header FS_h_t FS_h; 128 | header_type FS_s_t 129 | { 130 | fields { 131 | f1:32; 132 | f2:32; 133 | f3:32; 134 | f4:32; 135 | 136 | } 137 | } 138 | header FS_s_t FS_s; 139 | 140 | parser start { 141 | return parse_ethernet; 142 | } 143 | 144 | parser parse_ethernet1 { 145 | extract(ethernet1); 146 | return select(ethernet1.ethertype) { 147 | 0x0800 : parse_ipv41; 148 | 0x1000 : parse_FS_h; 149 | 0x0806 : parse_arp; 150 | default : ingress; 151 | } 152 | } 153 | parser parse_ipv41 { 154 | extract(ipv41); 155 | return select(ipv41.proto) { 156 | 6 : parse_tcp; 157 | 17: parse_udp1; 158 | default: ingress; 159 | } 160 | } 161 | parser parse_ipv4 { 162 | extract(ipv4); 163 | return select(latest.proto) { 164 | 6 : parse_tcp; 165 | 17: parse_udp; 166 | default: ingress; 167 | } 168 | } 169 | parser parse_udp1 { 170 | extract(udp1); 171 | return ingress; 172 | } 173 | 174 | parser parse_vxlan { 175 | extract(vxlan); 176 | return parse_ethernet1; 177 | } 178 | parser parse_ethernet { 179 | extract(ethernet); 180 | return select(latest.ethertype) { 181 | 0x0800 : parse_ipv4; 182 | 0x0806 : parse_arp; 183 | default : ingress; 184 | } 185 | } 186 | 187 | 188 | parser parse_FS_h { 189 | extract(FS_h); 190 | return parse_FS_s; 191 | } 192 | 193 | parser parse_FS_s { 194 | extract(FS_s); 195 | return select(FS_h.type) { 196 | 0x0800 : parse_ipv41; 197 | 0x0806 : parse_arp; 198 | default : ingress; 199 | } 200 | } 201 | 202 | parser parse_arp{ 203 | extract(arp); 204 | return ingress; 205 | } 206 | parser parse_tcp { 207 | extract(tcp); 208 | return ingress; 209 | } 210 | parser parse_udp { 211 | extract(udp); 212 | return select(latest.dPort) { 213 | 4789 : parse_vxlan; 214 | default: ingress; 215 | } 216 | 217 | } 218 | 219 | 220 | -------------------------------------------------------------------------------- /testbed/Tofino_maximum/timeSF.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | import os 3 | import datetime 4 | import time 5 | from thrift.transport import TSocket, TTransport 6 | from thrift.protocol import TBinaryProtocol, TMultiplexedProtocol 7 | 8 | p4_name = 'timeSF' 9 | 10 | import sys 11 | sys.path.append(os.environ["SDE_INSTALL"] + "/lib/python2.7/site-packages/tofinopd/" + p4_name) 12 | sys.path.append(os.environ["SDE_INSTALL"] + "/lib/python2.7/site-packages/tofino") 13 | sys.path.append(os.environ["SDE_INSTALL"] + "/lib/python2.7/site-packages") 14 | 15 | from res_pd_rpc.ttypes import * 16 | from tm_api_rpc.ttypes import * 17 | from p4_pd_rpc.ttypes import * 18 | from ptf.thriftutils import * 19 | 20 | from pal_rpc.ttypes import * 21 | iphash2port_conf = open("ecmp7.txt") 22 | iphash2port = [] 23 | for t in iphash2port_conf: 24 | d = t.split() 25 | iphash2port.append((d[0], int(d[1]),int(d[2]))) 26 | 27 | 28 | r_conf=open("ggs.txt") 29 | r=[] 30 | for t in r_conf: 31 | d = t.split() 32 | r.append((int(d[0]), int(d[1]))) 33 | 34 | 35 | def connect(): 36 | switchtime=118 37 | totaltime=120 38 | p4_client_module = importlib.import_module("p4_pd_rpc." + p4_name) 39 | transport = TSocket.TSocket("localhost", 9090) 40 | bprotocol = TBinaryProtocol.TBinaryProtocol(transport) 41 | 42 | p4_protocol = TMultiplexedProtocol.TMultiplexedProtocol(bprotocol, p4_name) 43 | client = p4_client_module.Client(p4_protocol) 44 | pal_protocol = TMultiplexedProtocol.TMultiplexedProtocol(bprotocol, "pal") 45 | pal_client_module = importlib.import_module(".".join(["pal_rpc", "pal"])) 46 | conn_mgr_client_module = importlib.import_module('.'.join(['conn_mgr_pd_rpc', 'conn_mgr'])) 47 | conn_mgr_protocol = TMultiplexedProtocol.TMultiplexedProtocol(bprotocol, 'conn_mgr') 48 | conn_mgr = conn_mgr_client_module.Client(conn_mgr_protocol) 49 | 50 | transport.open() 51 | 52 | pal = pal_client_module.Client(pal_protocol) 53 | dev_id = 0 54 | ports = [0, 4, 8, 12, 16, 20, 24, 28,32,36,40,44,48,52,56,60] 55 | pal.pal_port_del_all(dev_id) 56 | for port in ports: 57 | pal.pal_port_add(dev_id, port, pal_port_speed_t.BF_SPEED_40G, pal_fec_type_t.BF_FEC_TYP_NONE) 58 | pal.pal_port_enable_all(dev_id) 59 | sess_hdl = conn_mgr.client_init() 60 | dev_tgt = DevTarget_t(0, int(0xFFFF) - 0x10000) 61 | 62 | 63 | 64 | for kv in iphash2port: 65 | match_spec = timeSF_ECMP_t_match_spec_t(ipv4Addr_to_i32(kv[0]),kv[1]) 66 | action_spec = timeSF_ECMP_action_spec_t(kv[2]) 67 | try: 68 | client.ECMP_t_table_delete_by_match_spec(sess_hdl, dev_tgt, match_spec) 69 | except: 70 | pass 71 | client.ECMP_t_table_add_with_ECMP(sess_hdl, dev_tgt, match_spec, action_spec) 72 | 73 | 74 | 75 | pr=255 76 | match_spec = timeSF_take_t_match_spec_t(2) 77 | client.take_t_table_add_with_write2(sess_hdl, dev_tgt, match_spec) 78 | match_spec = timeSF_take_t_match_spec_t(1) 79 | client.take_t_table_add_with_write1(sess_hdl, dev_tgt, match_spec) 80 | 81 | for kv in r: 82 | match_spec = timeSF_getgoodsign_match_spec_t(kv[0]) 83 | action_spec = timeSF_ggs_action_spec_t(kv[1]) 84 | client.getgoodsign_table_add_with_ggs(sess_hdl, dev_tgt, match_spec,action_spec) 85 | 86 | 87 | 88 | match_spec1 = timeSF_rdmz_match_spec_t(0) 89 | match_spec2 = timeSF_rdmz_match_spec_t(1) 90 | match_spec3 = timeSF_rdmz_match_spec_t(2) 91 | match_spec4 = timeSF_rdmz_match_spec_t(3) 92 | client.rdmz_table_add_with_rm1(sess_hdl, dev_tgt, match_spec2) 93 | client.rdmz_table_add_with_rm1(sess_hdl, dev_tgt, match_spec4) 94 | client.rdmz_table_add_with_rm2(sess_hdl, dev_tgt, match_spec1) 95 | client.rdmz_table_add_with_rm2(sess_hdl, dev_tgt, match_spec3) 96 | 97 | match_spec1 = timeSF_restore_match_spec_t(0) 98 | match_spec2 = timeSF_restore_match_spec_t(1) 99 | match_spec3 = timeSF_restore_match_spec_t(2) 100 | match_spec4 = timeSF_restore_match_spec_t(3) 101 | client.restore_table_add_with_rs1(sess_hdl, dev_tgt, match_spec2) 102 | client.restore_table_add_with_rs1(sess_hdl, dev_tgt, match_spec4) 103 | client.restore_table_add_with_rs2(sess_hdl, dev_tgt, match_spec1) 104 | client.restore_table_add_with_rs2(sess_hdl, dev_tgt, match_spec3) 105 | 106 | 107 | 108 | print "Port add done." 109 | sign = 1 110 | match_spec = timeSF_sign_t_match_spec_t(0) 111 | action_spec = timeSF_signing_action_spec_t(sign) 112 | try: 113 | client.sign_t_table_delete_by_match_spec(sess_hdl, dev_tgt, match_spec) 114 | except: 115 | pass 116 | client.sign_t_table_add_with_signing(sess_hdl, dev_tgt, match_spec, action_spec) 117 | '''considersleep''' 118 | time1=datetime.datetime.now() 119 | x=0 120 | y=0 121 | z=0 122 | while True: 123 | time2=datetime.datetime.now() 124 | if (time2-time1).total_seconds()>=switchtime and x==0: 125 | print ((time2-time1).total_seconds()) 126 | sign1=(sign+2)%4 127 | x=1 128 | match_spec = timeSF_sign_t_match_spec_t(0) 129 | action_spec = timeSF_signing_action_spec_t(sign1) 130 | try: 131 | client.sign_t_table_delete_by_match_spec(sess_hdl, dev_tgt, match_spec) 132 | except: 133 | pass 134 | client.sign_t_table_add_with_signing(sess_hdl, dev_tgt, match_spec, action_spec) 135 | time.sleep(0.1) 136 | client.register_reset_all_rm_a(sess_hdl, dev_tgt) 137 | if sign1==3: 138 | client.register_reset_all_fs_a_1_1(sess_hdl, dev_tgt) 139 | client.register_reset_all_fs_b_1_1(sess_hdl, dev_tgt) 140 | client.register_reset_all_fs_c_1_1(sess_hdl, dev_tgt) 141 | client.register_reset_all_fs_d_1_1(sess_hdl, dev_tgt) 142 | print("clean sketch1") 143 | if sign1==0: 144 | client.register_reset_all_fs_a_2_1(sess_hdl, dev_tgt) 145 | client.register_reset_all_fs_b_2_1(sess_hdl, dev_tgt) 146 | client.register_reset_all_fs_c_2_1(sess_hdl, dev_tgt) 147 | client.register_reset_all_fs_d_2_1(sess_hdl, dev_tgt) 148 | print("clean sketch2") 149 | time6=datetime.datetime.now() 150 | print ((time6-time2).total_seconds()) 151 | if (time2-time1).total_seconds()>=totaltime: 152 | print ((time2-time1).total_seconds()) 153 | z=1 154 | time1=time2 155 | sign=3-sign 156 | x=0 157 | y=0 158 | match_spec = timeSF_sign_t_match_spec_t(0) 159 | action_spec = timeSF_signing_action_spec_t(sign) 160 | try: 161 | client.sign_t_table_delete_by_match_spec(sess_hdl, dev_tgt, match_spec) 162 | except: 163 | pass 164 | client.sign_t_table_add_with_signing(sess_hdl, dev_tgt, match_spec, action_spec) 165 | 166 | 167 | def main(): 168 | connect() 169 | 170 | if __name__ == "__main__": 171 | main() 172 | -------------------------------------------------------------------------------- /testbed/Tofino_sum/README.md: -------------------------------------------------------------------------------- 1 | ## P4 implementation 2 | The codes for flow size estimation. `flowSF.p4` is the data plane codes, `flowSF.py` is the control plane codes. 3 | 4 | ### Requirements 5 | - Please compile and run the codes on a Tofino ASIC. 6 | 7 | ### Usage 8 | - To run the control plane, you must complie the p4 program `flowSF.p4` with compiling option `--with-thrift` 9 | - Configure `ecmp.txt`, `range.txt` as you need. 10 | 11 | -------------------------------------------------------------------------------- /testbed/Tofino_sum/ggs.txt: -------------------------------------------------------------------------------- 1 | 0 0 1 2 | 0 1 1 3 | 0 2 1 4 | 0 3 1 5 | 0 4 2 6 | 0 5 2 7 | 0 6 2 8 | 0 7 2 9 | 1 0 5 10 | 1 1 5 11 | 1 2 5 12 | 1 3 5 13 | 1 4 6 14 | 1 5 6 15 | 1 6 6 16 | 1 7 6 17 | 2 0 1 18 | 2 1 1 19 | 2 2 1 20 | 2 3 1 21 | 2 4 2 22 | 2 5 2 23 | 2 6 2 24 | 2 7 2 25 | 3 0 5 26 | 3 1 5 27 | 3 2 5 28 | 3 3 5 29 | 3 4 6 30 | 3 5 6 31 | 3 6 6 32 | 3 7 6 33 | -------------------------------------------------------------------------------- /testbed/Tofino_sum/includes/header_and_parser.p4: -------------------------------------------------------------------------------- 1 | 2 | header_type ethernet_t { 3 | fields { 4 | dmac : 48; 5 | smac : 48; 6 | ethertype : 16; 7 | } 8 | } 9 | header ethernet_t ethernet; 10 | header ethernet_t ethernet1; 11 | 12 | 13 | header_type vxlan_t 14 | { 15 | fields 16 | { 17 | vx1:32; 18 | vx2:32; 19 | } 20 | } 21 | header vxlan_t vxlan; 22 | 23 | 24 | 25 | header_type ipv4_t { 26 | fields { 27 | ver : 4; 28 | len : 4; 29 | diffserv : 6; 30 | ecn: 2; 31 | totalLen : 16; 32 | id : 16; 33 | flags : 3; 34 | offset : 13; 35 | ttl : 8; 36 | proto : 8; 37 | csum : 16; 38 | sip : 32; 39 | dip : 32; 40 | } 41 | } 42 | header ipv4_t ipv4; 43 | header ipv4_t ipv41; 44 | 45 | field_list ipv4_checksum_list { 46 | ipv4.ver; 47 | ipv4.len; 48 | ipv4.diffserv; 49 | ipv4.ecn; 50 | ipv4.totalLen; 51 | ipv4.id; 52 | ipv4.flags; 53 | ipv4.offset; 54 | ipv4.ttl; 55 | ipv4.proto; 56 | ipv4.sip; 57 | ipv4.dip; 58 | } 59 | 60 | field_list_calculation ipv4_checksum { 61 | input { 62 | ipv4_checksum_list; 63 | } 64 | algorithm : csum16; 65 | output_width : 16; 66 | } 67 | 68 | calculated_field ipv4.csum { 69 | update ipv4_checksum; 70 | } 71 | 72 | 73 | header_type tcp_t { 74 | fields { 75 | sPort : 16; 76 | dPort : 16; 77 | seqNo : 32; 78 | ackNo : 32; 79 | dataOffset : 4; 80 | res : 3; 81 | ecn : 3; 82 | ctrl : 6; 83 | window : 16; 84 | checksum : 16; 85 | urgentPtr : 16; 86 | } 87 | } 88 | header tcp_t tcp; 89 | 90 | header_type udp_t { 91 | fields { 92 | sPort : 16; 93 | dPort : 16; 94 | hdr_length : 16; 95 | checksum : 16; 96 | } 97 | } 98 | header udp_t udp; 99 | header udp_t udp1; 100 | header_type arp_t{ 101 | fields { 102 | hType: 16; 103 | pType: 16; 104 | hLen: 8; 105 | pLen: 8; 106 | oper: 16; 107 | hSrc: 48; 108 | pSrc: 32; 109 | hDst: 48; 110 | pDst: 32; 111 | } 112 | } 113 | header arp_t arp; 114 | 115 | header_type FS_h_t 116 | { 117 | fields { 118 | type:16; 119 | ID:16; 120 | binid:16; 121 | sketchid:16; 122 | 123 | 124 | 125 | } 126 | } 127 | header FS_h_t FS_h; 128 | header_type FS_s_t 129 | { 130 | fields { 131 | f1:32; 132 | f2:32; 133 | f3:32; 134 | f4:32; 135 | } 136 | } 137 | header FS_s_t FS_s; 138 | 139 | parser start { 140 | return parse_ethernet; 141 | } 142 | 143 | parser parse_ethernet1 { 144 | extract(ethernet1); 145 | return select(ethernet1.ethertype) { 146 | 0x0800 : parse_ipv41; 147 | 0x1000 : parse_FS_h; 148 | 0x0806 : parse_arp; 149 | default : ingress; 150 | } 151 | } 152 | parser parse_ipv41 { 153 | extract(ipv41); 154 | return select(ipv41.proto) { 155 | 6 : parse_tcp; 156 | 17: parse_udp1; 157 | default: ingress; 158 | } 159 | } 160 | parser parse_ipv4 { 161 | extract(ipv4); 162 | return select(latest.proto) { 163 | 6 : parse_tcp; 164 | 17: parse_udp; 165 | default: ingress; 166 | } 167 | } 168 | parser parse_udp1 { 169 | extract(udp1); 170 | return ingress; 171 | } 172 | 173 | parser parse_vxlan { 174 | extract(vxlan); 175 | return parse_ethernet1; 176 | } 177 | parser parse_ethernet { 178 | extract(ethernet); 179 | return select(latest.ethertype) { 180 | 0x0800 : parse_ipv4; 181 | 0x0806 : parse_arp; 182 | default : ingress; 183 | } 184 | } 185 | 186 | 187 | parser parse_FS_h { 188 | extract(FS_h); 189 | return parse_FS_s; 190 | } 191 | 192 | parser parse_FS_s { 193 | extract(FS_s); 194 | return select(FS_h.type) { 195 | 0x0800 : parse_ipv41; 196 | 0x0806 : parse_arp; 197 | default : ingress; 198 | } 199 | } 200 | 201 | parser parse_arp{ 202 | extract(arp); 203 | return ingress; 204 | } 205 | parser parse_tcp { 206 | extract(tcp); 207 | return ingress; 208 | } 209 | parser parse_udp { 210 | extract(udp); 211 | return select(latest.dPort) { 212 | 4789 : parse_vxlan; 213 | default: ingress; 214 | } 215 | 216 | } 217 | 218 | 219 | -------------------------------------------------------------------------------- /testbed/analyzer/README.md: -------------------------------------------------------------------------------- 1 | ## File Description 2 | 3 | * ```analyzer_LG``` analyzes the packets received by each end-host after deploying *LightGuardian* on each switch. 4 | * ```analyzer_INT``` analyzes the packets received by each end-host after deploying *INT* on each swtich. 5 | 6 | ## Usage 7 | 8 | ### Generate and Configure packet information 9 | 10 | * Use ```tcpdump``` to capture packet information on each end-host. 11 | * Collect all ```pcap``` files and configure ```pcap.config``` as follows, where *inet_addr* is the hexadecimal IP address of the end-host. 12 | 13 | ``` 14 | inet_addr_1 pcap_file_1 15 | inet_addr_2 pcap_file_2 16 | ... 17 | inet_addr_N pcap_file_N 18 | ``` 19 | 20 | ### Analyze the ```pcap``` files 21 | 22 | * ```analyzer_INT``` provides the total bandwidth usage of the network, and the bandwidth usage of *INT*. 23 | * ```analyzer_LG``` provides the total bandwidth usage of the network, and the bandwidth usage of *LightGuardian*. It also provides how the reconstruction rate of each sketch changes over time. -------------------------------------------------------------------------------- /testbed/analyzer/analyzer_INT.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int MacAddressSize = 6; 7 | const int Ipv4HeaderSize = 20; 8 | const int IpAddressSize = 4; 9 | const int TcpHeaderSize = 20; 10 | const int VXLanHeaderSize = 50; 11 | 12 | struct GlobalHeader { 13 | uint32_t magic_number; 14 | uint16_t version_major; 15 | uint16_t version_minor; 16 | int32_t thiszone; 17 | uint32_t sigfigs; 18 | uint32_t snaplen; 19 | uint32_t network; 20 | }; 21 | 22 | struct PacketHeader { 23 | uint32_t ts_sec; 24 | uint32_t ts_usec; 25 | uint32_t incl_len; 26 | uint32_t orig_len; 27 | 28 | void logged(_IO_FILE* fd) { 29 | fprintf(fd, "timestamp: %d.%06d, incl length: %d, orig length: %d\n", 30 | ts_sec, ts_usec, incl_len, orig_len); 31 | } 32 | }; 33 | 34 | struct EthernetHeader { 35 | uint8_t srcMac[MacAddressSize]; 36 | uint8_t dstMac[MacAddressSize]; 37 | uint16_t type; 38 | 39 | void logged(_IO_FILE* fd) { 40 | fprintf(fd, "type: 0x%04x.\n", type); 41 | } 42 | 43 | void ntoh() { 44 | type = ntohs(type); 45 | } 46 | }; 47 | 48 | struct Ipv4Header { 49 | uint8_t ipv4Header1[Ipv4HeaderSize - IpAddressSize * 2]; 50 | uint32_t srcIP; 51 | uint32_t dstIP; 52 | 53 | void logged(_IO_FILE* fd) { 54 | uint8_t *srcIpBytes = (uint8_t *)&srcIP; 55 | uint8_t *dstIpBytes = (uint8_t *)&dstIP; 56 | fprintf(fd, "%p, %p, %p.\n", this, srcIpBytes, dstIpBytes); 57 | fprintf(fd, "src IP: %u.%u.%u.%u, dst IP: %u.%u.%u.%u, (0x%x, 0x%x)\n", 58 | srcIpBytes[0], srcIpBytes[1], srcIpBytes[2], srcIpBytes[3], 59 | dstIpBytes[0], dstIpBytes[1], dstIpBytes[2], dstIpBytes[3], 60 | srcIP, dstIP); 61 | } 62 | }; 63 | 64 | struct TcpHeader { 65 | uint8_t tcpHeader[TcpHeaderSize]; 66 | }; 67 | 68 | struct IntHeader { 69 | uint8_t TF; 70 | uint8_t count; 71 | uint16_t type; 72 | 73 | uint8_t sketchInt[100]; 74 | 75 | void logged(_IO_FILE* fd) { 76 | fprintf(fd, "type: 0x%04x, count: %d.\n", type, count); 77 | } 78 | 79 | void ntoh() { 80 | type = ntohs(type); 81 | } 82 | }; 83 | 84 | #pragma pack(2) 85 | struct PacketData { 86 | EthernetHeader ethernetHeader; 87 | IntHeader intHeader; 88 | Ipv4Header ipv4Header; 89 | TcpHeader tcpHeader; 90 | }; 91 | #pragma pack() 92 | 93 | struct EndHostInfo { 94 | uint32_t hostIP; 95 | string pcapFilename; 96 | }; 97 | 98 | void PcapFileParser(EndHostInfo &endHostInfo) { 99 | ifstream pcap(endHostInfo.pcapFilename.c_str(), ios::binary | ios::in); 100 | 101 | fprintf(stdout, "End Host: 0x%x, Pcap File: %s.\n", 102 | endHostInfo.hostIP, endHostInfo.pcapFilename.c_str()); 103 | 104 | GlobalHeader globalHeader; 105 | 106 | pcap.read((char *)&globalHeader, sizeof(GlobalHeader)); 107 | 108 | PacketHeader packetHeader; 109 | PacketData packetData; 110 | 111 | int packetCounter = 0, intCounter = 0; 112 | 113 | double totalRecvBytes = 0; 114 | double intRecvBytes = 0; 115 | 116 | double initTimestamp = 0.0; 117 | 118 | while (pcap.read((char *)&packetHeader, sizeof(PacketHeader))) { 119 | // packetHeader.logged(stdout); 120 | 121 | pcap.read((char *)&packetData, sizeof(PacketData)); 122 | 123 | packetData.ethernetHeader.ntoh(); 124 | // packetData.ethernetHeader.logged(stdout); 125 | packetData.intHeader.ntoh(); 126 | packetData.intHeader.logged(stdout); 127 | packetData.ipv4Header.logged(stdout); 128 | 129 | pcap.seekg(packetHeader.incl_len - sizeof(PacketData), ios::cur); 130 | 131 | // if (packetData.ethernetHeader.type != 0x1000) { 132 | // continue; 133 | // } 134 | // if (packetData.ipv4Header.dstIP != endHostInfo.hostIP) { 135 | // continue; 136 | // } 137 | 138 | packetCounter += 1; 139 | totalRecvBytes += packetHeader.orig_len + VXLanHeaderSize - sizeof(IntHeader); 140 | 141 | intRecvBytes += 4 + 20 * packetData.intHeader.count; 142 | totalRecvBytes += 4 + 20 * packetData.intHeader.count; 143 | 144 | if (packetCounter % 1000000 == 0) { 145 | fprintf(stdout, "read %dM packets.\n", packetCounter / 1000000); 146 | } 147 | if (packetCounter >= 20) { 148 | break; 149 | } 150 | } 151 | 152 | fprintf(stdout, "Total Packets: %d, Bandwidth Usage: %6fG.\n", 153 | packetCounter, totalRecvBytes / 1024.0 / 1024.0 / 1024.0); 154 | fprintf(stdout, "Total Ints: %d, Bandwidth Usage: %6fM.\n", 155 | intCounter, intRecvBytes / 1024.0 / 1024.0); 156 | } 157 | 158 | void PcapFileLoader() { 159 | ifstream pcapFile("pcap_config", ios::in); 160 | 161 | EndHostInfo endHostInfo; 162 | while (pcapFile >> hex >> endHostInfo.hostIP >> endHostInfo.pcapFilename) { 163 | PcapFileParser(endHostInfo); 164 | } 165 | } 166 | 167 | int main() { 168 | PcapFileLoader(); 169 | 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /utils/utils.py: -------------------------------------------------------------------------------- 1 | def Tuple2String(tup): 2 | string = '' 3 | for index in range(0, len(tup)): 4 | string += str(tup[index]) 5 | string += ',' 6 | return string 7 | 8 | 9 | def String2Tuple(string): 10 | Tuple = [] 11 | strlen = len(string) 12 | tmpstring = '' 13 | for index in range(0, strlen): 14 | if(string[index] == ','): 15 | if(tmpstring != ''): 16 | Tuple.append(int(tmpstring)) 17 | tmpstring = '' 18 | else: 19 | tmpstring += string[index] 20 | Tuple = tuple(Tuple) 21 | return Tuple 22 | --------------------------------------------------------------------------------