├── .gitattributes ├── LICENSE ├── Makefile ├── README.md ├── commands_1_tree.txt ├── commands_3_trees.txt ├── demo_data ├── README.md └── UNSW_1000_packets.pcap ├── get_results.txt ├── scripts ├── ML.ipynb ├── README.md └── rftop4_v2.py ├── switchtree.1tree ├── switchtree.3trees ├── switchtree.p4 └── topology.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.1tree linguist-language=P4 2 | *.3trees linguist-language=P4 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kamal singh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BMV2_SWITCH_EXE = simple_switch 2 | TOPO = topology.json 3 | 4 | include ../../utils/Makefile 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwitchTree 2 | In-Network detection of attacks using Random Forests 3 | 4 | Please cite this paper if you use this code: 5 | 6 | `Jong-Hyouk Lee and Kamal Singh, "SwitchTree: In-network Computing and Traffic Analyses with Random Forests", Neural Computing and Applications (2020)` 7 | 8 | We perform in-network analysis of the network data by exploiting the power of programmable data planes. 9 | SwitchTree coded in P4 embeds Random Forest algorithm inside a programmable switch such that the 10 | Random Forest is configurable and re-configurable at runtime. We show how some flow level 11 | stateful features can be estimated, such as the round trip time and bitrate of each flow. 12 | Main references for this work are [IISY](https://github.com/cucl-srg/IIsy) and [pForest](https://arxiv.org/abs/1909.05680). 13 | 14 | # Quick Start Guide 15 | To run the code 16 | 1. Use or Create a BMV2 VM or machine. For example you may download the VM from here provided by P4 developer day: https://drive.google.com/uc?id=1lYF4NgFkYoRqtskdGTMxy3sXUV0jkMxo&export=download 17 | 18 | 2. Check if the examples are compiling and working in tutorials/exercises folder. 19 | 20 | 3. Copy the SwitchTree folder to tutorials/exercises/ folder 21 | 22 | 4. cd to SwitchTree folder 23 | 24 | 4. `make` 25 | 26 | 5. Open a new terminal and cd to tutorials/exercises/switchtree folder. Add rules (trained Decision Trees were translated to SwitchTree P4 rules using a script) to P4 switch by 27 | 28 | `simple_switch_CLI < commands_1_tree.txt` 29 | 30 | 6. Send the traffic using tcpreplay. A demo test file containing 1000 packets is provided in demo_data. It is extracted from UNSW database. 31 | 32 | `sudo tcpreplay -i s1-eth1 demo_data/UNSW_1000_packets.pcap` 33 | 34 | 7. To obtain results, you make check the counter values. The number of malware flows injected (tracked using other means for statistics) is provided by counter_malware_flows and 35 | the actually detected ones are provided by counter_true_detection_flows. 36 | 37 | `simple_switch_CLI < get_results.txt` 38 | 39 | 40 | 41 | To use SwitchTree with 3 trees: 42 | 43 | `cp switchtree.3trees switchtree.p4` 44 | 45 | `make clean` 46 | 47 | `make` 48 | 49 | `simple_switch_CLI < commands_3_trees.txt` 50 | 51 | Note you may need to exit and type make again to reinitialize and do a new test with new data. 52 | 53 | 8. In case you want to do performance evaluations and heavy tests: debugging and logging should be disabled otherwise several packets will be lost during real-time tests. This can be done by downloading the source of behavioral-model (https://github.com/p4lang/behavioral-model) to your home directory and recompiling it using the options that disable logging 54 | 55 | (TODO: I have put the commands below that I remember. Need to test and verify them.) 56 | 57 | `cd behavioral-model/` 58 | 59 | `sudo ./configure 'CXXFLAGS=-g -O3' 'CFLAGS=-g -O3' --disable-logging-macros --disable-elogger` 60 | 61 | `sudo make` 62 | 63 | `sudo make install` 64 | 65 | 9. If you want to train your own decison trees and random forests then please see the scripts folder. 66 | -------------------------------------------------------------------------------- /commands_1_tree.txt: -------------------------------------------------------------------------------- 1 | table_clear MyIngress.level4 2 | table_clear MyIngress.level5 3 | table_clear MyIngress.level6 4 | table_clear MyIngress.level7 5 | table_clear MyIngress.level8 6 | table_clear MyIngress.level9 7 | table_clear MyIngress.level10 8 | table_clear MyIngress.level11 9 | table_clear MyIngress.ipv4_exact 10 | table_add MyIngress.level1 MyIngress.CheckFeature 0 0 1 => 1 9 20000 11 | table_add MyIngress.level2 MyIngress.CheckFeature 1 9 1 => 2 4 0 12 | table_add MyIngress.level3 MyIngress.CheckFeature 2 4 1 => 3 1 1 13 | table_add MyIngress.level4 MyIngress.CheckFeature 3 1 1 => 4 10 61 14 | table_add MyIngress.level5 MyIngress.SetClass 4 10 1 => 5 0 15 | table_add MyIngress.level5 MyIngress.CheckFeature 4 10 0 => 6 8 1500 16 | table_add MyIngress.level6 MyIngress.CheckFeature 6 8 1 => 7 8 504 17 | table_add MyIngress.level7 MyIngress.SetClass 7 8 1 => 8 0 18 | table_add MyIngress.level7 MyIngress.CheckFeature 7 8 0 => 9 8 550 19 | table_add MyIngress.level8 MyIngress.SetClass 9 8 1 => 10 0 20 | table_add MyIngress.level8 MyIngress.SetClass 9 8 0 => 11 0 21 | table_add MyIngress.level6 MyIngress.SetClass 6 8 0 => 12 1 22 | table_add MyIngress.level4 MyIngress.CheckFeature 3 1 0 => 13 0 31 23 | table_add MyIngress.level5 MyIngress.CheckFeature 13 0 1 => 14 6 53 24 | table_add MyIngress.level6 MyIngress.SetClass 14 6 1 => 15 0 25 | table_add MyIngress.level6 MyIngress.CheckFeature 14 6 0 => 16 6 76 26 | table_add MyIngress.level7 MyIngress.SetClass 16 6 1 => 17 1 27 | table_add MyIngress.level7 MyIngress.SetClass 16 6 0 => 18 0 28 | table_add MyIngress.level5 MyIngress.CheckFeature 13 0 0 => 19 0 158 29 | table_add MyIngress.level6 MyIngress.SetClass 19 0 1 => 20 1 30 | table_add MyIngress.level6 MyIngress.CheckFeature 19 0 0 => 21 1 4 31 | table_add MyIngress.level7 MyIngress.CheckFeature 21 1 1 => 22 10 507 32 | table_add MyIngress.level8 MyIngress.CheckFeature 22 10 1 => 23 8 45 33 | table_add MyIngress.level9 MyIngress.CheckFeature 23 8 1 => 24 3 26188235 34 | table_add MyIngress.level10 MyIngress.SetClass 24 3 1 => 25 1 35 | table_add MyIngress.level10 MyIngress.CheckFeature 24 3 0 => 26 8 40 36 | table_add MyIngress.level11 MyIngress.SetClass 26 8 1 => 27 1 37 | table_add MyIngress.level11 MyIngress.SetClass 26 8 0 => 28 0 38 | table_add MyIngress.level9 MyIngress.CheckFeature 23 8 0 => 29 11 0 39 | table_add MyIngress.level10 MyIngress.CheckFeature 29 11 1 => 30 6 1612 40 | table_add MyIngress.level11 MyIngress.SetClass 30 6 1 => 31 1 41 | table_add MyIngress.level11 MyIngress.SetClass 30 6 0 => 32 1 42 | table_add MyIngress.level10 MyIngress.CheckFeature 29 11 0 => 33 11 0 43 | table_add MyIngress.level11 MyIngress.SetClass 33 11 1 => 34 1 44 | table_add MyIngress.level11 MyIngress.SetClass 33 11 0 => 35 1 45 | table_add MyIngress.level8 MyIngress.CheckFeature 22 10 0 => 36 8 41 46 | table_add MyIngress.level9 MyIngress.CheckFeature 36 8 1 => 37 3 25666666 47 | table_add MyIngress.level10 MyIngress.CheckFeature 37 3 1 => 38 3 16 48 | table_add MyIngress.level11 MyIngress.SetClass 38 3 1 => 39 0 49 | table_add MyIngress.level11 MyIngress.SetClass 38 3 0 => 40 1 50 | table_add MyIngress.level10 MyIngress.CheckFeature 37 3 0 => 41 11 0 51 | table_add MyIngress.level11 MyIngress.SetClass 41 11 1 => 42 1 52 | table_add MyIngress.level11 MyIngress.SetClass 41 11 0 => 43 0 53 | table_add MyIngress.level9 MyIngress.CheckFeature 36 8 0 => 44 3 993 54 | table_add MyIngress.level10 MyIngress.CheckFeature 44 3 1 => 45 6 290 55 | table_add MyIngress.level11 MyIngress.SetClass 45 6 1 => 46 0 56 | table_add MyIngress.level11 MyIngress.SetClass 45 6 0 => 47 1 57 | table_add MyIngress.level10 MyIngress.CheckFeature 44 3 0 => 48 11 9700000 58 | table_add MyIngress.level11 MyIngress.SetClass 48 11 1 => 49 1 59 | table_add MyIngress.level11 MyIngress.SetClass 48 11 0 => 50 0 60 | table_add MyIngress.level7 MyIngress.CheckFeature 21 1 0 => 51 10 575 61 | table_add MyIngress.level8 MyIngress.CheckFeature 51 10 1 => 52 10 517 62 | table_add MyIngress.level9 MyIngress.SetClass 52 10 1 => 53 1 63 | table_add MyIngress.level9 MyIngress.CheckFeature 52 10 0 => 54 6 91 64 | table_add MyIngress.level10 MyIngress.CheckFeature 54 6 1 => 55 3 53485714 65 | table_add MyIngress.level11 MyIngress.SetClass 55 3 1 => 56 1 66 | table_add MyIngress.level11 MyIngress.SetClass 55 3 0 => 57 0 67 | table_add MyIngress.level10 MyIngress.SetClass 54 6 0 => 58 0 68 | table_add MyIngress.level8 MyIngress.SetClass 51 10 0 => 59 0 69 | table_add MyIngress.level3 MyIngress.CheckFeature 2 4 0 => 60 2 46 70 | table_add MyIngress.level4 MyIngress.SetClass 60 2 1 => 61 0 71 | table_add MyIngress.level4 MyIngress.CheckFeature 60 2 0 => 62 10 161 72 | table_add MyIngress.level5 MyIngress.CheckFeature 62 10 1 => 63 1 0 73 | table_add MyIngress.level6 MyIngress.SetClass 63 1 1 => 64 0 74 | table_add MyIngress.level6 MyIngress.CheckFeature 63 1 0 => 65 8 88 75 | table_add MyIngress.level7 MyIngress.SetClass 65 8 1 => 66 1 76 | table_add MyIngress.level7 MyIngress.CheckFeature 65 8 0 => 67 11 940000 77 | table_add MyIngress.level8 MyIngress.SetClass 67 11 1 => 68 1 78 | table_add MyIngress.level8 MyIngress.CheckFeature 67 11 0 => 69 11 1040000 79 | table_add MyIngress.level9 MyIngress.SetClass 69 11 1 => 70 0 80 | table_add MyIngress.level9 MyIngress.SetClass 69 11 0 => 71 1 81 | table_add MyIngress.level5 MyIngress.CheckFeature 62 10 0 => 72 1 0 82 | table_add MyIngress.level6 MyIngress.SetClass 72 1 1 => 73 0 83 | table_add MyIngress.level6 MyIngress.CheckFeature 72 1 0 => 74 7 2490 84 | table_add MyIngress.level7 MyIngress.CheckFeature 74 7 1 => 75 3 7723 85 | table_add MyIngress.level8 MyIngress.CheckFeature 75 3 1 => 76 10 1931 86 | table_add MyIngress.level9 MyIngress.CheckFeature 76 10 1 => 77 6 548 87 | table_add MyIngress.level10 MyIngress.SetClass 77 6 1 => 78 0 88 | table_add MyIngress.level10 MyIngress.CheckFeature 77 6 0 => 79 3 5023 89 | table_add MyIngress.level11 MyIngress.SetClass 79 3 1 => 80 1 90 | table_add MyIngress.level11 MyIngress.SetClass 79 3 0 => 81 0 91 | table_add MyIngress.level9 MyIngress.SetClass 76 10 0 => 82 1 92 | table_add MyIngress.level8 MyIngress.SetClass 75 3 0 => 83 1 93 | table_add MyIngress.level7 MyIngress.CheckFeature 74 7 0 => 84 3 4740 94 | table_add MyIngress.level8 MyIngress.CheckFeature 84 3 1 => 85 4 9 95 | table_add MyIngress.level9 MyIngress.CheckFeature 85 4 1 => 86 6 494 96 | table_add MyIngress.level10 MyIngress.CheckFeature 86 6 1 => 87 8 62 97 | table_add MyIngress.level11 MyIngress.SetClass 87 8 1 => 88 0 98 | table_add MyIngress.level11 MyIngress.SetClass 87 8 0 => 89 1 99 | table_add MyIngress.level10 MyIngress.SetClass 86 6 0 => 90 1 100 | table_add MyIngress.level9 MyIngress.SetClass 85 4 0 => 91 1 101 | table_add MyIngress.level8 MyIngress.CheckFeature 84 3 0 => 92 5 45 102 | table_add MyIngress.level9 MyIngress.CheckFeature 92 5 1 => 93 11 200000 103 | table_add MyIngress.level10 MyIngress.CheckFeature 93 11 1 => 94 1 2 104 | table_add MyIngress.level11 MyIngress.SetClass 94 1 1 => 95 1 105 | table_add MyIngress.level11 MyIngress.SetClass 94 1 0 => 96 1 106 | table_add MyIngress.level10 MyIngress.SetClass 93 11 0 => 97 1 107 | table_add MyIngress.level9 MyIngress.SetClass 92 5 0 => 98 1 108 | table_add MyIngress.level2 MyIngress.CheckFeature 1 9 0 => 99 2 156 109 | table_add MyIngress.level3 MyIngress.SetClass 99 2 1 => 100 0 110 | table_add MyIngress.level3 MyIngress.CheckFeature 99 2 0 => 101 1 2 111 | table_add MyIngress.level4 MyIngress.CheckFeature 101 1 1 => 102 10 161 112 | table_add MyIngress.level5 MyIngress.CheckFeature 102 10 1 => 103 8 84 113 | table_add MyIngress.level6 MyIngress.CheckFeature 103 8 1 => 104 4 11 114 | table_add MyIngress.level7 MyIngress.CheckFeature 104 4 1 => 105 4 9 115 | table_add MyIngress.level8 MyIngress.CheckFeature 105 4 1 => 106 7 7827 116 | table_add MyIngress.level9 MyIngress.CheckFeature 106 7 1 => 107 0 158 117 | table_add MyIngress.level10 MyIngress.CheckFeature 107 0 1 => 108 8 78 118 | table_add MyIngress.level11 MyIngress.SetClass 108 8 1 => 109 1 119 | table_add MyIngress.level11 MyIngress.SetClass 108 8 0 => 110 0 120 | table_add MyIngress.level10 MyIngress.CheckFeature 107 0 0 => 111 10 123 121 | table_add MyIngress.level11 MyIngress.SetClass 111 10 1 => 112 1 122 | table_add MyIngress.level11 MyIngress.SetClass 111 10 0 => 113 1 123 | table_add MyIngress.level9 MyIngress.CheckFeature 106 7 0 => 114 11 460000 124 | table_add MyIngress.level10 MyIngress.CheckFeature 114 11 1 => 115 5 165 125 | table_add MyIngress.level11 MyIngress.SetClass 115 5 1 => 116 1 126 | table_add MyIngress.level11 MyIngress.SetClass 115 5 0 => 117 1 127 | table_add MyIngress.level10 MyIngress.CheckFeature 114 11 0 => 118 5 170 128 | table_add MyIngress.level11 MyIngress.SetClass 118 5 1 => 119 0 129 | table_add MyIngress.level11 MyIngress.SetClass 118 5 0 => 120 1 130 | table_add MyIngress.level8 MyIngress.CheckFeature 105 4 0 => 121 7 13243 131 | table_add MyIngress.level9 MyIngress.CheckFeature 121 7 1 => 122 6 801 132 | table_add MyIngress.level10 MyIngress.SetClass 122 6 1 => 123 1 133 | table_add MyIngress.level10 MyIngress.CheckFeature 122 6 0 => 124 7 1140 134 | table_add MyIngress.level11 MyIngress.SetClass 124 7 1 => 125 1 135 | table_add MyIngress.level11 MyIngress.SetClass 124 7 0 => 126 0 136 | table_add MyIngress.level9 MyIngress.CheckFeature 121 7 0 => 127 5 145 137 | table_add MyIngress.level10 MyIngress.CheckFeature 127 5 1 => 128 3 8829 138 | table_add MyIngress.level11 MyIngress.SetClass 128 3 1 => 129 0 139 | table_add MyIngress.level11 MyIngress.SetClass 128 3 0 => 130 1 140 | table_add MyIngress.level10 MyIngress.SetClass 127 5 0 => 131 1 141 | table_add MyIngress.level7 MyIngress.CheckFeature 104 4 0 => 132 7 5892 142 | table_add MyIngress.level8 MyIngress.CheckFeature 132 7 1 => 133 6 573 143 | table_add MyIngress.level9 MyIngress.SetClass 133 6 1 => 134 0 144 | table_add MyIngress.level9 MyIngress.CheckFeature 133 6 0 => 135 6 697 145 | table_add MyIngress.level10 MyIngress.CheckFeature 135 6 1 => 136 6 687 146 | table_add MyIngress.level11 MyIngress.SetClass 136 6 1 => 137 1 147 | table_add MyIngress.level11 MyIngress.SetClass 136 6 0 => 138 0 148 | table_add MyIngress.level10 MyIngress.CheckFeature 135 6 0 => 139 6 1635 149 | table_add MyIngress.level11 MyIngress.SetClass 139 6 1 => 140 1 150 | table_add MyIngress.level11 MyIngress.SetClass 139 6 0 => 141 1 151 | table_add MyIngress.level8 MyIngress.SetClass 132 7 0 => 142 1 152 | table_add MyIngress.level6 MyIngress.CheckFeature 103 8 0 => 143 3 363596 153 | table_add MyIngress.level7 MyIngress.CheckFeature 143 3 1 => 144 7 2828 154 | table_add MyIngress.level8 MyIngress.CheckFeature 144 7 1 => 145 11 550000 155 | table_add MyIngress.level9 MyIngress.CheckFeature 145 11 1 => 146 11 360000 156 | table_add MyIngress.level10 MyIngress.SetClass 146 11 1 => 147 1 157 | table_add MyIngress.level10 MyIngress.SetClass 146 11 0 => 148 0 158 | table_add MyIngress.level9 MyIngress.CheckFeature 145 11 0 => 149 5 44 159 | table_add MyIngress.level10 MyIngress.CheckFeature 149 5 1 => 150 8 1155 160 | table_add MyIngress.level11 MyIngress.SetClass 150 8 1 => 151 1 161 | table_add MyIngress.level11 MyIngress.SetClass 150 8 0 => 152 0 162 | table_add MyIngress.level10 MyIngress.SetClass 149 5 0 => 153 1 163 | table_add MyIngress.level8 MyIngress.CheckFeature 144 7 0 => 154 5 1149 164 | table_add MyIngress.level9 MyIngress.CheckFeature 154 5 1 => 155 10 127 165 | table_add MyIngress.level10 MyIngress.CheckFeature 155 10 1 => 156 5 137 166 | table_add MyIngress.level11 MyIngress.SetClass 156 5 1 => 157 1 167 | table_add MyIngress.level11 MyIngress.SetClass 156 5 0 => 158 1 168 | table_add MyIngress.level10 MyIngress.CheckFeature 155 10 0 => 159 5 50 169 | table_add MyIngress.level11 MyIngress.SetClass 159 5 1 => 160 1 170 | table_add MyIngress.level11 MyIngress.SetClass 159 5 0 => 161 1 171 | table_add MyIngress.level9 MyIngress.CheckFeature 154 5 0 => 162 4 53 172 | table_add MyIngress.level10 MyIngress.CheckFeature 162 4 1 => 163 9 170000 173 | table_add MyIngress.level11 MyIngress.SetClass 163 9 1 => 164 1 174 | table_add MyIngress.level11 MyIngress.SetClass 163 9 0 => 165 0 175 | table_add MyIngress.level10 MyIngress.SetClass 162 4 0 => 166 1 176 | table_add MyIngress.level7 MyIngress.CheckFeature 143 3 0 => 167 6 68194 177 | table_add MyIngress.level8 MyIngress.CheckFeature 167 6 1 => 168 7 6350 178 | table_add MyIngress.level9 MyIngress.CheckFeature 168 7 1 => 169 6 68188 179 | table_add MyIngress.level10 MyIngress.CheckFeature 169 6 1 => 170 9 120000 180 | table_add MyIngress.level11 MyIngress.SetClass 170 9 1 => 171 0 181 | table_add MyIngress.level11 MyIngress.SetClass 170 9 0 => 172 0 182 | table_add MyIngress.level10 MyIngress.CheckFeature 169 6 0 => 173 9 110000 183 | table_add MyIngress.level11 MyIngress.SetClass 173 9 1 => 174 0 184 | table_add MyIngress.level11 MyIngress.SetClass 173 9 0 => 175 1 185 | table_add MyIngress.level9 MyIngress.SetClass 168 7 0 => 176 1 186 | table_add MyIngress.level8 MyIngress.SetClass 167 6 0 => 177 1 187 | table_add MyIngress.level5 MyIngress.CheckFeature 102 10 0 => 178 9 100000 188 | table_add MyIngress.level6 MyIngress.CheckFeature 178 9 1 => 179 3 13232 189 | table_add MyIngress.level7 MyIngress.CheckFeature 179 3 1 => 180 7 8619 190 | table_add MyIngress.level8 MyIngress.CheckFeature 180 7 1 => 181 5 68 191 | table_add MyIngress.level9 MyIngress.CheckFeature 181 5 1 => 182 8 54 192 | table_add MyIngress.level10 MyIngress.CheckFeature 182 8 1 => 183 11 760000 193 | table_add MyIngress.level11 MyIngress.SetClass 183 11 1 => 184 0 194 | table_add MyIngress.level11 MyIngress.SetClass 183 11 0 => 185 1 195 | table_add MyIngress.level10 MyIngress.CheckFeature 182 8 0 => 186 7 4018 196 | table_add MyIngress.level11 MyIngress.SetClass 186 7 1 => 187 1 197 | table_add MyIngress.level11 MyIngress.SetClass 186 7 0 => 188 1 198 | table_add MyIngress.level9 MyIngress.CheckFeature 181 5 0 => 189 11 610000 199 | table_add MyIngress.level10 MyIngress.CheckFeature 189 11 1 => 190 11 600000 200 | table_add MyIngress.level11 MyIngress.SetClass 190 11 1 => 191 1 201 | table_add MyIngress.level11 MyIngress.SetClass 190 11 0 => 192 0 202 | table_add MyIngress.level10 MyIngress.SetClass 189 11 0 => 193 1 203 | table_add MyIngress.level8 MyIngress.CheckFeature 180 7 0 => 194 11 230000 204 | table_add MyIngress.level9 MyIngress.SetClass 194 11 1 => 195 0 205 | table_add MyIngress.level9 MyIngress.CheckFeature 194 11 0 => 196 4 9 206 | table_add MyIngress.level10 MyIngress.SetClass 196 4 1 => 197 1 207 | table_add MyIngress.level10 MyIngress.CheckFeature 196 4 0 => 198 7 10289 208 | table_add MyIngress.level11 MyIngress.SetClass 198 7 1 => 199 1 209 | table_add MyIngress.level11 MyIngress.SetClass 198 7 0 => 200 1 210 | table_add MyIngress.level7 MyIngress.CheckFeature 179 3 0 => 201 7 6912 211 | table_add MyIngress.level8 MyIngress.CheckFeature 201 7 1 => 202 6 3038 212 | table_add MyIngress.level9 MyIngress.CheckFeature 202 6 1 => 203 4 9 213 | table_add MyIngress.level10 MyIngress.CheckFeature 203 4 1 => 204 8 81 214 | table_add MyIngress.level11 MyIngress.SetClass 204 8 1 => 205 1 215 | table_add MyIngress.level11 MyIngress.SetClass 204 8 0 => 206 1 216 | table_add MyIngress.level10 MyIngress.SetClass 203 4 0 => 207 0 217 | table_add MyIngress.level9 MyIngress.CheckFeature 202 6 0 => 208 6 3520 218 | table_add MyIngress.level10 MyIngress.SetClass 208 6 1 => 209 0 219 | table_add MyIngress.level10 MyIngress.CheckFeature 208 6 0 => 210 9 80000 220 | table_add MyIngress.level11 MyIngress.SetClass 210 9 1 => 211 1 221 | table_add MyIngress.level11 MyIngress.SetClass 210 9 0 => 212 0 222 | table_add MyIngress.level8 MyIngress.CheckFeature 201 7 0 => 213 8 882 223 | table_add MyIngress.level9 MyIngress.CheckFeature 213 8 1 => 214 5 91 224 | table_add MyIngress.level10 MyIngress.SetClass 214 5 1 => 215 1 225 | table_add MyIngress.level10 MyIngress.CheckFeature 214 5 0 => 216 3 16531 226 | table_add MyIngress.level11 MyIngress.SetClass 216 3 1 => 217 1 227 | table_add MyIngress.level11 MyIngress.SetClass 216 3 0 => 218 1 228 | table_add MyIngress.level9 MyIngress.CheckFeature 213 8 0 => 219 8 889 229 | table_add MyIngress.level10 MyIngress.SetClass 219 8 1 => 220 0 230 | table_add MyIngress.level10 MyIngress.SetClass 219 8 0 => 221 1 231 | table_add MyIngress.level6 MyIngress.CheckFeature 178 9 0 => 222 10 281 232 | table_add MyIngress.level7 MyIngress.CheckFeature 222 10 1 => 223 3 5588 233 | table_add MyIngress.level8 MyIngress.CheckFeature 223 3 1 => 224 8 53 234 | table_add MyIngress.level9 MyIngress.CheckFeature 224 8 1 => 225 3 5583 235 | table_add MyIngress.level10 MyIngress.CheckFeature 225 3 1 => 226 11 1960000 236 | table_add MyIngress.level11 MyIngress.SetClass 226 11 1 => 227 0 237 | table_add MyIngress.level11 MyIngress.SetClass 226 11 0 => 228 1 238 | table_add MyIngress.level10 MyIngress.SetClass 225 3 0 => 229 1 239 | table_add MyIngress.level9 MyIngress.CheckFeature 224 8 0 => 230 7 82 240 | table_add MyIngress.level10 MyIngress.CheckFeature 230 7 1 => 231 3 164 241 | table_add MyIngress.level11 MyIngress.SetClass 231 3 1 => 232 1 242 | table_add MyIngress.level11 MyIngress.SetClass 231 3 0 => 233 0 243 | table_add MyIngress.level10 MyIngress.CheckFeature 230 7 0 => 234 6 780 244 | table_add MyIngress.level11 MyIngress.SetClass 234 6 1 => 235 1 245 | table_add MyIngress.level11 MyIngress.SetClass 234 6 0 => 236 1 246 | table_add MyIngress.level8 MyIngress.CheckFeature 223 3 0 => 237 4 25 247 | table_add MyIngress.level9 MyIngress.CheckFeature 237 4 1 => 238 7 4852 248 | table_add MyIngress.level10 MyIngress.CheckFeature 238 7 1 => 239 8 883 249 | table_add MyIngress.level11 MyIngress.SetClass 239 8 1 => 240 0 250 | table_add MyIngress.level11 MyIngress.SetClass 239 8 0 => 241 0 251 | table_add MyIngress.level10 MyIngress.CheckFeature 238 7 0 => 242 6 817 252 | table_add MyIngress.level11 MyIngress.SetClass 242 6 1 => 243 1 253 | table_add MyIngress.level11 MyIngress.SetClass 242 6 0 => 244 0 254 | table_add MyIngress.level9 MyIngress.SetClass 237 4 0 => 245 1 255 | table_add MyIngress.level7 MyIngress.CheckFeature 222 10 0 => 246 5 66 256 | table_add MyIngress.level8 MyIngress.CheckFeature 246 5 1 => 247 11 590000 257 | table_add MyIngress.level9 MyIngress.CheckFeature 247 11 1 => 248 7 9477 258 | table_add MyIngress.level10 MyIngress.CheckFeature 248 7 1 => 249 3 31010 259 | table_add MyIngress.level11 MyIngress.SetClass 249 3 1 => 250 1 260 | table_add MyIngress.level11 MyIngress.SetClass 249 3 0 => 251 1 261 | table_add MyIngress.level10 MyIngress.CheckFeature 248 7 0 => 252 7 9529 262 | table_add MyIngress.level11 MyIngress.SetClass 252 7 1 => 253 0 263 | table_add MyIngress.level11 MyIngress.SetClass 252 7 0 => 254 1 264 | table_add MyIngress.level9 MyIngress.CheckFeature 247 11 0 => 255 10 3385 265 | table_add MyIngress.level10 MyIngress.CheckFeature 255 10 1 => 256 7 4675 266 | table_add MyIngress.level11 MyIngress.SetClass 256 7 1 => 257 1 267 | table_add MyIngress.level11 MyIngress.SetClass 256 7 0 => 258 0 268 | table_add MyIngress.level10 MyIngress.CheckFeature 255 10 0 => 259 2 253 269 | table_add MyIngress.level11 MyIngress.SetClass 259 2 1 => 260 1 270 | table_add MyIngress.level11 MyIngress.SetClass 259 2 0 => 261 0 271 | table_add MyIngress.level8 MyIngress.CheckFeature 246 5 0 => 262 10 538 272 | table_add MyIngress.level9 MyIngress.CheckFeature 262 10 1 => 263 9 210000 273 | table_add MyIngress.level10 MyIngress.CheckFeature 263 9 1 => 264 5 95 274 | table_add MyIngress.level11 MyIngress.SetClass 264 5 1 => 265 1 275 | table_add MyIngress.level11 MyIngress.SetClass 264 5 0 => 266 1 276 | table_add MyIngress.level10 MyIngress.CheckFeature 263 9 0 => 267 3 12742 277 | table_add MyIngress.level11 MyIngress.SetClass 267 3 1 => 268 1 278 | table_add MyIngress.level11 MyIngress.SetClass 267 3 0 => 269 1 279 | table_add MyIngress.level9 MyIngress.CheckFeature 262 10 0 => 270 5 76 280 | table_add MyIngress.level10 MyIngress.CheckFeature 270 5 1 => 271 10 54148 281 | table_add MyIngress.level11 MyIngress.SetClass 271 10 1 => 272 1 282 | table_add MyIngress.level11 MyIngress.SetClass 271 10 0 => 273 1 283 | table_add MyIngress.level10 MyIngress.SetClass 270 5 0 => 274 1 284 | table_add MyIngress.level4 MyIngress.CheckFeature 101 1 0 => 275 7 3866 285 | table_add MyIngress.level5 MyIngress.CheckFeature 275 7 1 => 276 8 405 286 | table_add MyIngress.level6 MyIngress.CheckFeature 276 8 1 => 277 3 8371 287 | table_add MyIngress.level7 MyIngress.CheckFeature 277 3 1 => 278 7 548 288 | table_add MyIngress.level8 MyIngress.SetClass 278 7 1 => 279 0 289 | table_add MyIngress.level8 MyIngress.CheckFeature 278 7 0 => 280 3 3377 290 | table_add MyIngress.level9 MyIngress.SetClass 280 3 1 => 281 0 291 | table_add MyIngress.level9 MyIngress.CheckFeature 280 3 0 => 282 6 318 292 | table_add MyIngress.level10 MyIngress.SetClass 282 6 1 => 283 0 293 | table_add MyIngress.level10 MyIngress.SetClass 282 6 0 => 284 1 294 | table_add MyIngress.level7 MyIngress.SetClass 277 3 0 => 285 0 295 | table_add MyIngress.level6 MyIngress.SetClass 276 8 0 => 286 1 296 | table_add MyIngress.level5 MyIngress.SetClass 275 7 0 => 287 1 297 | table_add MyIngress.direction MyIngress.SetDirection 149.171.126.0/24 => 298 | table_add MyIngress.malware MyIngress.SetMalware 175.45.176.0/24 => 299 | table_add MyIngress.malware_inverse MyIngress.SetMalware 175.45.176.0/24 => 300 | table_add MyIngress.ipv4_exact MyIngress.ipv4_forward 0 => 00:00:00:00:02:02 2 301 | table_add MyIngress.ipv4_exact MyIngress.ipv4_forward 1 => 00:00:00:00:02:03 3 302 | table_dump MyIngress.level1 303 | table_dump MyIngress.level2 304 | table_dump MyIngress.level3 305 | table_dump MyIngress.ipv4_exact 306 | -------------------------------------------------------------------------------- /commands_3_trees.txt: -------------------------------------------------------------------------------- 1 | table_clear MyIngress.level4 2 | table_clear MyIngress.level5 3 | table_clear MyIngress.level6 4 | table_clear MyIngress.level7 5 | table_clear MyIngress.level8 6 | table_clear MyIngress.level9 7 | table_clear MyIngress.level10 8 | table_clear MyIngress.level11 9 | table_clear MyIngress.ipv4_exact 10 | table_add MyIngress.level1 MyIngress.CheckFeature 0 0 1 => 1 9 20000 11 | table_add MyIngress.level2 MyIngress.CheckFeature 1 9 1 => 2 4 0 12 | table_add MyIngress.level3 MyIngress.CheckFeature 2 4 1 => 3 1 1 13 | table_add MyIngress.level4 MyIngress.CheckFeature 3 1 1 => 4 10 61 14 | table_add MyIngress.level5 MyIngress.SetClass 4 10 1 => 5 0 15 | table_add MyIngress.level5 MyIngress.CheckFeature 4 10 0 => 6 8 1500 16 | table_add MyIngress.level6 MyIngress.CheckFeature 6 8 1 => 7 8 504 17 | table_add MyIngress.level7 MyIngress.SetClass 7 8 1 => 8 0 18 | table_add MyIngress.level7 MyIngress.CheckFeature 7 8 0 => 9 8 550 19 | table_add MyIngress.level8 MyIngress.SetClass 9 8 1 => 10 0 20 | table_add MyIngress.level8 MyIngress.SetClass 9 8 0 => 11 0 21 | table_add MyIngress.level6 MyIngress.SetClass 6 8 0 => 12 1 22 | table_add MyIngress.level4 MyIngress.CheckFeature 3 1 0 => 13 0 31 23 | table_add MyIngress.level5 MyIngress.CheckFeature 13 0 1 => 14 6 53 24 | table_add MyIngress.level6 MyIngress.SetClass 14 6 1 => 15 0 25 | table_add MyIngress.level6 MyIngress.CheckFeature 14 6 0 => 16 6 76 26 | table_add MyIngress.level7 MyIngress.SetClass 16 6 1 => 17 1 27 | table_add MyIngress.level7 MyIngress.SetClass 16 6 0 => 18 0 28 | table_add MyIngress.level5 MyIngress.CheckFeature 13 0 0 => 19 0 158 29 | table_add MyIngress.level6 MyIngress.SetClass 19 0 1 => 20 1 30 | table_add MyIngress.level6 MyIngress.CheckFeature 19 0 0 => 21 1 4 31 | table_add MyIngress.level7 MyIngress.CheckFeature 21 1 1 => 22 10 507 32 | table_add MyIngress.level8 MyIngress.CheckFeature 22 10 1 => 23 8 45 33 | table_add MyIngress.level9 MyIngress.CheckFeature 23 8 1 => 24 3 26188235 34 | table_add MyIngress.level10 MyIngress.SetClass 24 3 1 => 25 1 35 | table_add MyIngress.level10 MyIngress.CheckFeature 24 3 0 => 26 8 40 36 | table_add MyIngress.level11 MyIngress.SetClass 26 8 1 => 27 1 37 | table_add MyIngress.level11 MyIngress.SetClass 26 8 0 => 28 0 38 | table_add MyIngress.level9 MyIngress.CheckFeature 23 8 0 => 29 11 0 39 | table_add MyIngress.level10 MyIngress.CheckFeature 29 11 1 => 30 6 1612 40 | table_add MyIngress.level11 MyIngress.SetClass 30 6 1 => 31 1 41 | table_add MyIngress.level11 MyIngress.SetClass 30 6 0 => 32 1 42 | table_add MyIngress.level10 MyIngress.CheckFeature 29 11 0 => 33 11 0 43 | table_add MyIngress.level11 MyIngress.SetClass 33 11 1 => 34 1 44 | table_add MyIngress.level11 MyIngress.SetClass 33 11 0 => 35 1 45 | table_add MyIngress.level8 MyIngress.CheckFeature 22 10 0 => 36 8 41 46 | table_add MyIngress.level9 MyIngress.CheckFeature 36 8 1 => 37 3 25666666 47 | table_add MyIngress.level10 MyIngress.CheckFeature 37 3 1 => 38 3 16 48 | table_add MyIngress.level11 MyIngress.SetClass 38 3 1 => 39 0 49 | table_add MyIngress.level11 MyIngress.SetClass 38 3 0 => 40 1 50 | table_add MyIngress.level10 MyIngress.CheckFeature 37 3 0 => 41 11 0 51 | table_add MyIngress.level11 MyIngress.SetClass 41 11 1 => 42 1 52 | table_add MyIngress.level11 MyIngress.SetClass 41 11 0 => 43 0 53 | table_add MyIngress.level9 MyIngress.CheckFeature 36 8 0 => 44 3 993 54 | table_add MyIngress.level10 MyIngress.CheckFeature 44 3 1 => 45 6 290 55 | table_add MyIngress.level11 MyIngress.SetClass 45 6 1 => 46 0 56 | table_add MyIngress.level11 MyIngress.SetClass 45 6 0 => 47 1 57 | table_add MyIngress.level10 MyIngress.CheckFeature 44 3 0 => 48 11 9700000 58 | table_add MyIngress.level11 MyIngress.SetClass 48 11 1 => 49 1 59 | table_add MyIngress.level11 MyIngress.SetClass 48 11 0 => 50 0 60 | table_add MyIngress.level7 MyIngress.CheckFeature 21 1 0 => 51 10 575 61 | table_add MyIngress.level8 MyIngress.CheckFeature 51 10 1 => 52 10 517 62 | table_add MyIngress.level9 MyIngress.SetClass 52 10 1 => 53 1 63 | table_add MyIngress.level9 MyIngress.CheckFeature 52 10 0 => 54 6 91 64 | table_add MyIngress.level10 MyIngress.CheckFeature 54 6 1 => 55 3 53485714 65 | table_add MyIngress.level11 MyIngress.SetClass 55 3 1 => 56 1 66 | table_add MyIngress.level11 MyIngress.SetClass 55 3 0 => 57 0 67 | table_add MyIngress.level10 MyIngress.SetClass 54 6 0 => 58 0 68 | table_add MyIngress.level8 MyIngress.SetClass 51 10 0 => 59 0 69 | table_add MyIngress.level3 MyIngress.CheckFeature 2 4 0 => 60 2 46 70 | table_add MyIngress.level4 MyIngress.SetClass 60 2 1 => 61 0 71 | table_add MyIngress.level4 MyIngress.CheckFeature 60 2 0 => 62 10 161 72 | table_add MyIngress.level5 MyIngress.CheckFeature 62 10 1 => 63 1 0 73 | table_add MyIngress.level6 MyIngress.SetClass 63 1 1 => 64 0 74 | table_add MyIngress.level6 MyIngress.CheckFeature 63 1 0 => 65 8 88 75 | table_add MyIngress.level7 MyIngress.SetClass 65 8 1 => 66 1 76 | table_add MyIngress.level7 MyIngress.CheckFeature 65 8 0 => 67 11 940000 77 | table_add MyIngress.level8 MyIngress.SetClass 67 11 1 => 68 1 78 | table_add MyIngress.level8 MyIngress.CheckFeature 67 11 0 => 69 11 1040000 79 | table_add MyIngress.level9 MyIngress.SetClass 69 11 1 => 70 0 80 | table_add MyIngress.level9 MyIngress.SetClass 69 11 0 => 71 1 81 | table_add MyIngress.level5 MyIngress.CheckFeature 62 10 0 => 72 1 0 82 | table_add MyIngress.level6 MyIngress.SetClass 72 1 1 => 73 0 83 | table_add MyIngress.level6 MyIngress.CheckFeature 72 1 0 => 74 7 2490 84 | table_add MyIngress.level7 MyIngress.CheckFeature 74 7 1 => 75 3 7723 85 | table_add MyIngress.level8 MyIngress.CheckFeature 75 3 1 => 76 10 1931 86 | table_add MyIngress.level9 MyIngress.CheckFeature 76 10 1 => 77 6 548 87 | table_add MyIngress.level10 MyIngress.SetClass 77 6 1 => 78 0 88 | table_add MyIngress.level10 MyIngress.CheckFeature 77 6 0 => 79 3 5023 89 | table_add MyIngress.level11 MyIngress.SetClass 79 3 1 => 80 1 90 | table_add MyIngress.level11 MyIngress.SetClass 79 3 0 => 81 0 91 | table_add MyIngress.level9 MyIngress.SetClass 76 10 0 => 82 1 92 | table_add MyIngress.level8 MyIngress.SetClass 75 3 0 => 83 1 93 | table_add MyIngress.level7 MyIngress.CheckFeature 74 7 0 => 84 3 4740 94 | table_add MyIngress.level8 MyIngress.CheckFeature 84 3 1 => 85 4 9 95 | table_add MyIngress.level9 MyIngress.CheckFeature 85 4 1 => 86 6 494 96 | table_add MyIngress.level10 MyIngress.CheckFeature 86 6 1 => 87 8 62 97 | table_add MyIngress.level11 MyIngress.SetClass 87 8 1 => 88 0 98 | table_add MyIngress.level11 MyIngress.SetClass 87 8 0 => 89 1 99 | table_add MyIngress.level10 MyIngress.SetClass 86 6 0 => 90 1 100 | table_add MyIngress.level9 MyIngress.SetClass 85 4 0 => 91 1 101 | table_add MyIngress.level8 MyIngress.CheckFeature 84 3 0 => 92 5 45 102 | table_add MyIngress.level9 MyIngress.CheckFeature 92 5 1 => 93 11 200000 103 | table_add MyIngress.level10 MyIngress.CheckFeature 93 11 1 => 94 1 2 104 | table_add MyIngress.level11 MyIngress.SetClass 94 1 1 => 95 1 105 | table_add MyIngress.level11 MyIngress.SetClass 94 1 0 => 96 1 106 | table_add MyIngress.level10 MyIngress.SetClass 93 11 0 => 97 1 107 | table_add MyIngress.level9 MyIngress.SetClass 92 5 0 => 98 1 108 | table_add MyIngress.level2 MyIngress.CheckFeature 1 9 0 => 99 2 156 109 | table_add MyIngress.level3 MyIngress.SetClass 99 2 1 => 100 0 110 | table_add MyIngress.level3 MyIngress.CheckFeature 99 2 0 => 101 1 2 111 | table_add MyIngress.level4 MyIngress.CheckFeature 101 1 1 => 102 10 161 112 | table_add MyIngress.level5 MyIngress.CheckFeature 102 10 1 => 103 8 84 113 | table_add MyIngress.level6 MyIngress.CheckFeature 103 8 1 => 104 4 11 114 | table_add MyIngress.level7 MyIngress.CheckFeature 104 4 1 => 105 4 9 115 | table_add MyIngress.level8 MyIngress.CheckFeature 105 4 1 => 106 7 7827 116 | table_add MyIngress.level9 MyIngress.CheckFeature 106 7 1 => 107 0 158 117 | table_add MyIngress.level10 MyIngress.CheckFeature 107 0 1 => 108 8 78 118 | table_add MyIngress.level11 MyIngress.SetClass 108 8 1 => 109 1 119 | table_add MyIngress.level11 MyIngress.SetClass 108 8 0 => 110 0 120 | table_add MyIngress.level10 MyIngress.CheckFeature 107 0 0 => 111 10 123 121 | table_add MyIngress.level11 MyIngress.SetClass 111 10 1 => 112 1 122 | table_add MyIngress.level11 MyIngress.SetClass 111 10 0 => 113 1 123 | table_add MyIngress.level9 MyIngress.CheckFeature 106 7 0 => 114 11 460000 124 | table_add MyIngress.level10 MyIngress.CheckFeature 114 11 1 => 115 5 165 125 | table_add MyIngress.level11 MyIngress.SetClass 115 5 1 => 116 1 126 | table_add MyIngress.level11 MyIngress.SetClass 115 5 0 => 117 1 127 | table_add MyIngress.level10 MyIngress.CheckFeature 114 11 0 => 118 5 170 128 | table_add MyIngress.level11 MyIngress.SetClass 118 5 1 => 119 0 129 | table_add MyIngress.level11 MyIngress.SetClass 118 5 0 => 120 1 130 | table_add MyIngress.level8 MyIngress.CheckFeature 105 4 0 => 121 7 13243 131 | table_add MyIngress.level9 MyIngress.CheckFeature 121 7 1 => 122 6 801 132 | table_add MyIngress.level10 MyIngress.SetClass 122 6 1 => 123 1 133 | table_add MyIngress.level10 MyIngress.CheckFeature 122 6 0 => 124 7 1140 134 | table_add MyIngress.level11 MyIngress.SetClass 124 7 1 => 125 1 135 | table_add MyIngress.level11 MyIngress.SetClass 124 7 0 => 126 0 136 | table_add MyIngress.level9 MyIngress.CheckFeature 121 7 0 => 127 5 145 137 | table_add MyIngress.level10 MyIngress.CheckFeature 127 5 1 => 128 3 8829 138 | table_add MyIngress.level11 MyIngress.SetClass 128 3 1 => 129 0 139 | table_add MyIngress.level11 MyIngress.SetClass 128 3 0 => 130 1 140 | table_add MyIngress.level10 MyIngress.SetClass 127 5 0 => 131 1 141 | table_add MyIngress.level7 MyIngress.CheckFeature 104 4 0 => 132 7 5892 142 | table_add MyIngress.level8 MyIngress.CheckFeature 132 7 1 => 133 6 573 143 | table_add MyIngress.level9 MyIngress.SetClass 133 6 1 => 134 0 144 | table_add MyIngress.level9 MyIngress.CheckFeature 133 6 0 => 135 6 697 145 | table_add MyIngress.level10 MyIngress.CheckFeature 135 6 1 => 136 6 687 146 | table_add MyIngress.level11 MyIngress.SetClass 136 6 1 => 137 1 147 | table_add MyIngress.level11 MyIngress.SetClass 136 6 0 => 138 0 148 | table_add MyIngress.level10 MyIngress.CheckFeature 135 6 0 => 139 6 1635 149 | table_add MyIngress.level11 MyIngress.SetClass 139 6 1 => 140 1 150 | table_add MyIngress.level11 MyIngress.SetClass 139 6 0 => 141 1 151 | table_add MyIngress.level8 MyIngress.SetClass 132 7 0 => 142 1 152 | table_add MyIngress.level6 MyIngress.CheckFeature 103 8 0 => 143 3 363596 153 | table_add MyIngress.level7 MyIngress.CheckFeature 143 3 1 => 144 7 2828 154 | table_add MyIngress.level8 MyIngress.CheckFeature 144 7 1 => 145 11 550000 155 | table_add MyIngress.level9 MyIngress.CheckFeature 145 11 1 => 146 11 360000 156 | table_add MyIngress.level10 MyIngress.SetClass 146 11 1 => 147 1 157 | table_add MyIngress.level10 MyIngress.SetClass 146 11 0 => 148 0 158 | table_add MyIngress.level9 MyIngress.CheckFeature 145 11 0 => 149 5 44 159 | table_add MyIngress.level10 MyIngress.CheckFeature 149 5 1 => 150 8 1155 160 | table_add MyIngress.level11 MyIngress.SetClass 150 8 1 => 151 1 161 | table_add MyIngress.level11 MyIngress.SetClass 150 8 0 => 152 0 162 | table_add MyIngress.level10 MyIngress.SetClass 149 5 0 => 153 1 163 | table_add MyIngress.level8 MyIngress.CheckFeature 144 7 0 => 154 5 1149 164 | table_add MyIngress.level9 MyIngress.CheckFeature 154 5 1 => 155 10 127 165 | table_add MyIngress.level10 MyIngress.CheckFeature 155 10 1 => 156 5 137 166 | table_add MyIngress.level11 MyIngress.SetClass 156 5 1 => 157 1 167 | table_add MyIngress.level11 MyIngress.SetClass 156 5 0 => 158 1 168 | table_add MyIngress.level10 MyIngress.CheckFeature 155 10 0 => 159 5 50 169 | table_add MyIngress.level11 MyIngress.SetClass 159 5 1 => 160 1 170 | table_add MyIngress.level11 MyIngress.SetClass 159 5 0 => 161 1 171 | table_add MyIngress.level9 MyIngress.CheckFeature 154 5 0 => 162 4 53 172 | table_add MyIngress.level10 MyIngress.CheckFeature 162 4 1 => 163 9 170000 173 | table_add MyIngress.level11 MyIngress.SetClass 163 9 1 => 164 1 174 | table_add MyIngress.level11 MyIngress.SetClass 163 9 0 => 165 0 175 | table_add MyIngress.level10 MyIngress.SetClass 162 4 0 => 166 1 176 | table_add MyIngress.level7 MyIngress.CheckFeature 143 3 0 => 167 6 68194 177 | table_add MyIngress.level8 MyIngress.CheckFeature 167 6 1 => 168 7 6350 178 | table_add MyIngress.level9 MyIngress.CheckFeature 168 7 1 => 169 6 68188 179 | table_add MyIngress.level10 MyIngress.CheckFeature 169 6 1 => 170 9 120000 180 | table_add MyIngress.level11 MyIngress.SetClass 170 9 1 => 171 0 181 | table_add MyIngress.level11 MyIngress.SetClass 170 9 0 => 172 0 182 | table_add MyIngress.level10 MyIngress.CheckFeature 169 6 0 => 173 9 110000 183 | table_add MyIngress.level11 MyIngress.SetClass 173 9 1 => 174 0 184 | table_add MyIngress.level11 MyIngress.SetClass 173 9 0 => 175 1 185 | table_add MyIngress.level9 MyIngress.SetClass 168 7 0 => 176 1 186 | table_add MyIngress.level8 MyIngress.SetClass 167 6 0 => 177 1 187 | table_add MyIngress.level5 MyIngress.CheckFeature 102 10 0 => 178 9 100000 188 | table_add MyIngress.level6 MyIngress.CheckFeature 178 9 1 => 179 3 13232 189 | table_add MyIngress.level7 MyIngress.CheckFeature 179 3 1 => 180 7 8619 190 | table_add MyIngress.level8 MyIngress.CheckFeature 180 7 1 => 181 5 68 191 | table_add MyIngress.level9 MyIngress.CheckFeature 181 5 1 => 182 8 54 192 | table_add MyIngress.level10 MyIngress.CheckFeature 182 8 1 => 183 11 760000 193 | table_add MyIngress.level11 MyIngress.SetClass 183 11 1 => 184 0 194 | table_add MyIngress.level11 MyIngress.SetClass 183 11 0 => 185 1 195 | table_add MyIngress.level10 MyIngress.CheckFeature 182 8 0 => 186 7 4018 196 | table_add MyIngress.level11 MyIngress.SetClass 186 7 1 => 187 1 197 | table_add MyIngress.level11 MyIngress.SetClass 186 7 0 => 188 1 198 | table_add MyIngress.level9 MyIngress.CheckFeature 181 5 0 => 189 11 610000 199 | table_add MyIngress.level10 MyIngress.CheckFeature 189 11 1 => 190 11 600000 200 | table_add MyIngress.level11 MyIngress.SetClass 190 11 1 => 191 1 201 | table_add MyIngress.level11 MyIngress.SetClass 190 11 0 => 192 0 202 | table_add MyIngress.level10 MyIngress.SetClass 189 11 0 => 193 1 203 | table_add MyIngress.level8 MyIngress.CheckFeature 180 7 0 => 194 11 230000 204 | table_add MyIngress.level9 MyIngress.SetClass 194 11 1 => 195 0 205 | table_add MyIngress.level9 MyIngress.CheckFeature 194 11 0 => 196 4 9 206 | table_add MyIngress.level10 MyIngress.SetClass 196 4 1 => 197 1 207 | table_add MyIngress.level10 MyIngress.CheckFeature 196 4 0 => 198 7 10289 208 | table_add MyIngress.level11 MyIngress.SetClass 198 7 1 => 199 1 209 | table_add MyIngress.level11 MyIngress.SetClass 198 7 0 => 200 1 210 | table_add MyIngress.level7 MyIngress.CheckFeature 179 3 0 => 201 7 6912 211 | table_add MyIngress.level8 MyIngress.CheckFeature 201 7 1 => 202 6 3038 212 | table_add MyIngress.level9 MyIngress.CheckFeature 202 6 1 => 203 4 9 213 | table_add MyIngress.level10 MyIngress.CheckFeature 203 4 1 => 204 8 81 214 | table_add MyIngress.level11 MyIngress.SetClass 204 8 1 => 205 1 215 | table_add MyIngress.level11 MyIngress.SetClass 204 8 0 => 206 1 216 | table_add MyIngress.level10 MyIngress.SetClass 203 4 0 => 207 0 217 | table_add MyIngress.level9 MyIngress.CheckFeature 202 6 0 => 208 6 3520 218 | table_add MyIngress.level10 MyIngress.SetClass 208 6 1 => 209 0 219 | table_add MyIngress.level10 MyIngress.CheckFeature 208 6 0 => 210 9 80000 220 | table_add MyIngress.level11 MyIngress.SetClass 210 9 1 => 211 1 221 | table_add MyIngress.level11 MyIngress.SetClass 210 9 0 => 212 0 222 | table_add MyIngress.level8 MyIngress.CheckFeature 201 7 0 => 213 8 882 223 | table_add MyIngress.level9 MyIngress.CheckFeature 213 8 1 => 214 5 91 224 | table_add MyIngress.level10 MyIngress.SetClass 214 5 1 => 215 1 225 | table_add MyIngress.level10 MyIngress.CheckFeature 214 5 0 => 216 3 16531 226 | table_add MyIngress.level11 MyIngress.SetClass 216 3 1 => 217 1 227 | table_add MyIngress.level11 MyIngress.SetClass 216 3 0 => 218 1 228 | table_add MyIngress.level9 MyIngress.CheckFeature 213 8 0 => 219 8 889 229 | table_add MyIngress.level10 MyIngress.SetClass 219 8 1 => 220 0 230 | table_add MyIngress.level10 MyIngress.SetClass 219 8 0 => 221 1 231 | table_add MyIngress.level6 MyIngress.CheckFeature 178 9 0 => 222 10 281 232 | table_add MyIngress.level7 MyIngress.CheckFeature 222 10 1 => 223 3 5588 233 | table_add MyIngress.level8 MyIngress.CheckFeature 223 3 1 => 224 8 53 234 | table_add MyIngress.level9 MyIngress.CheckFeature 224 8 1 => 225 3 5583 235 | table_add MyIngress.level10 MyIngress.CheckFeature 225 3 1 => 226 11 1960000 236 | table_add MyIngress.level11 MyIngress.SetClass 226 11 1 => 227 0 237 | table_add MyIngress.level11 MyIngress.SetClass 226 11 0 => 228 1 238 | table_add MyIngress.level10 MyIngress.SetClass 225 3 0 => 229 1 239 | table_add MyIngress.level9 MyIngress.CheckFeature 224 8 0 => 230 7 82 240 | table_add MyIngress.level10 MyIngress.CheckFeature 230 7 1 => 231 3 164 241 | table_add MyIngress.level11 MyIngress.SetClass 231 3 1 => 232 1 242 | table_add MyIngress.level11 MyIngress.SetClass 231 3 0 => 233 0 243 | table_add MyIngress.level10 MyIngress.CheckFeature 230 7 0 => 234 6 780 244 | table_add MyIngress.level11 MyIngress.SetClass 234 6 1 => 235 1 245 | table_add MyIngress.level11 MyIngress.SetClass 234 6 0 => 236 1 246 | table_add MyIngress.level8 MyIngress.CheckFeature 223 3 0 => 237 4 25 247 | table_add MyIngress.level9 MyIngress.CheckFeature 237 4 1 => 238 7 4852 248 | table_add MyIngress.level10 MyIngress.CheckFeature 238 7 1 => 239 8 883 249 | table_add MyIngress.level11 MyIngress.SetClass 239 8 1 => 240 0 250 | table_add MyIngress.level11 MyIngress.SetClass 239 8 0 => 241 0 251 | table_add MyIngress.level10 MyIngress.CheckFeature 238 7 0 => 242 6 817 252 | table_add MyIngress.level11 MyIngress.SetClass 242 6 1 => 243 1 253 | table_add MyIngress.level11 MyIngress.SetClass 242 6 0 => 244 0 254 | table_add MyIngress.level9 MyIngress.SetClass 237 4 0 => 245 1 255 | table_add MyIngress.level7 MyIngress.CheckFeature 222 10 0 => 246 5 66 256 | table_add MyIngress.level8 MyIngress.CheckFeature 246 5 1 => 247 11 590000 257 | table_add MyIngress.level9 MyIngress.CheckFeature 247 11 1 => 248 7 9477 258 | table_add MyIngress.level10 MyIngress.CheckFeature 248 7 1 => 249 3 31010 259 | table_add MyIngress.level11 MyIngress.SetClass 249 3 1 => 250 1 260 | table_add MyIngress.level11 MyIngress.SetClass 249 3 0 => 251 1 261 | table_add MyIngress.level10 MyIngress.CheckFeature 248 7 0 => 252 7 9529 262 | table_add MyIngress.level11 MyIngress.SetClass 252 7 1 => 253 0 263 | table_add MyIngress.level11 MyIngress.SetClass 252 7 0 => 254 1 264 | table_add MyIngress.level9 MyIngress.CheckFeature 247 11 0 => 255 10 3385 265 | table_add MyIngress.level10 MyIngress.CheckFeature 255 10 1 => 256 7 4675 266 | table_add MyIngress.level11 MyIngress.SetClass 256 7 1 => 257 1 267 | table_add MyIngress.level11 MyIngress.SetClass 256 7 0 => 258 0 268 | table_add MyIngress.level10 MyIngress.CheckFeature 255 10 0 => 259 2 253 269 | table_add MyIngress.level11 MyIngress.SetClass 259 2 1 => 260 1 270 | table_add MyIngress.level11 MyIngress.SetClass 259 2 0 => 261 0 271 | table_add MyIngress.level8 MyIngress.CheckFeature 246 5 0 => 262 10 538 272 | table_add MyIngress.level9 MyIngress.CheckFeature 262 10 1 => 263 9 210000 273 | table_add MyIngress.level10 MyIngress.CheckFeature 263 9 1 => 264 5 95 274 | table_add MyIngress.level11 MyIngress.SetClass 264 5 1 => 265 1 275 | table_add MyIngress.level11 MyIngress.SetClass 264 5 0 => 266 1 276 | table_add MyIngress.level10 MyIngress.CheckFeature 263 9 0 => 267 3 12742 277 | table_add MyIngress.level11 MyIngress.SetClass 267 3 1 => 268 1 278 | table_add MyIngress.level11 MyIngress.SetClass 267 3 0 => 269 1 279 | table_add MyIngress.level9 MyIngress.CheckFeature 262 10 0 => 270 5 76 280 | table_add MyIngress.level10 MyIngress.CheckFeature 270 5 1 => 271 10 54148 281 | table_add MyIngress.level11 MyIngress.SetClass 271 10 1 => 272 1 282 | table_add MyIngress.level11 MyIngress.SetClass 271 10 0 => 273 1 283 | table_add MyIngress.level10 MyIngress.SetClass 270 5 0 => 274 1 284 | table_add MyIngress.level4 MyIngress.CheckFeature 101 1 0 => 275 7 3866 285 | table_add MyIngress.level5 MyIngress.CheckFeature 275 7 1 => 276 8 405 286 | table_add MyIngress.level6 MyIngress.CheckFeature 276 8 1 => 277 3 8371 287 | table_add MyIngress.level7 MyIngress.CheckFeature 277 3 1 => 278 7 548 288 | table_add MyIngress.level8 MyIngress.SetClass 278 7 1 => 279 0 289 | table_add MyIngress.level8 MyIngress.CheckFeature 278 7 0 => 280 3 3377 290 | table_add MyIngress.level9 MyIngress.SetClass 280 3 1 => 281 0 291 | table_add MyIngress.level9 MyIngress.CheckFeature 280 3 0 => 282 6 318 292 | table_add MyIngress.level10 MyIngress.SetClass 282 6 1 => 283 0 293 | table_add MyIngress.level10 MyIngress.SetClass 282 6 0 => 284 1 294 | table_add MyIngress.level7 MyIngress.SetClass 277 3 0 => 285 0 295 | table_add MyIngress.level6 MyIngress.SetClass 276 8 0 => 286 1 296 | table_add MyIngress.level5 MyIngress.SetClass 275 7 0 => 287 1 297 | table_add MyIngress.level_2_1 MyIngress.CheckFeature 287 0 1 => 288 5 45 298 | table_add MyIngress.level_2_2 MyIngress.CheckFeature 288 5 1 => 289 0 253 299 | table_add MyIngress.level_2_3 MyIngress.CheckFeature 289 0 1 => 290 7 2680 300 | table_add MyIngress.level_2_4 MyIngress.CheckFeature 290 7 1 => 291 0 61 301 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 291 0 1 => 292 11 0 302 | table_add MyIngress.level_2_6 MyIngress.SetClass2 292 11 1 => 293 0 303 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 292 11 0 => 294 3 1 304 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 294 3 1 => 295 0 0 305 | table_add MyIngress.level_2_8 MyIngress.SetClass2 295 0 1 => 296 1 306 | table_add MyIngress.level_2_8 MyIngress.SetClass2 295 0 0 => 297 0 307 | table_add MyIngress.level_2_7 MyIngress.SetClass2 294 3 0 => 298 0 308 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 291 0 0 => 299 6 140 309 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 299 6 1 => 300 11 2500000 310 | table_add MyIngress.level_2_7 MyIngress.SetClass2 300 11 1 => 301 1 311 | table_add MyIngress.level_2_7 MyIngress.SetClass2 300 11 0 => 302 0 312 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 299 6 0 => 303 4 5 313 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 303 4 1 => 304 9 50000 314 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 304 9 1 => 305 8 466 315 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 305 8 1 => 306 1 1 316 | table_add MyIngress.level_2_10 MyIngress.SetClass2 306 1 1 => 307 0 317 | table_add MyIngress.level_2_10 MyIngress.SetClass2 306 1 0 => 308 1 318 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 305 8 0 => 309 1 1 319 | table_add MyIngress.level_2_10 MyIngress.SetClass2 309 1 1 => 310 0 320 | table_add MyIngress.level_2_10 MyIngress.SetClass2 309 1 0 => 311 1 321 | table_add MyIngress.level_2_8 MyIngress.SetClass2 304 9 0 => 312 0 322 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 303 4 0 => 313 6 541 323 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 313 6 1 => 314 11 860000 324 | table_add MyIngress.level_2_9 MyIngress.SetClass2 314 11 1 => 315 1 325 | table_add MyIngress.level_2_9 MyIngress.SetClass2 314 11 0 => 316 0 326 | table_add MyIngress.level_2_8 MyIngress.SetClass2 313 6 0 => 317 1 327 | table_add MyIngress.level_2_4 MyIngress.CheckFeature 290 7 0 => 318 1 0 328 | table_add MyIngress.level_2_5 MyIngress.SetClass2 318 1 1 => 319 0 329 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 318 1 0 => 320 8 168 330 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 320 8 1 => 321 4 4 331 | table_add MyIngress.level_2_7 MyIngress.SetClass2 321 4 1 => 322 0 332 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 321 4 0 => 323 9 120000 333 | table_add MyIngress.level_2_8 MyIngress.SetClass2 323 9 1 => 324 1 334 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 323 9 0 => 325 6 819 335 | table_add MyIngress.level_2_9 MyIngress.SetClass2 325 6 1 => 326 1 336 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 325 6 0 => 327 8 83 337 | table_add MyIngress.level_2_10 MyIngress.SetClass2 327 8 1 => 328 0 338 | table_add MyIngress.level_2_10 MyIngress.SetClass2 327 8 0 => 329 1 339 | table_add MyIngress.level_2_6 MyIngress.SetClass2 320 8 0 => 330 1 340 | table_add MyIngress.level_2_3 MyIngress.CheckFeature 289 0 0 => 331 10 170 341 | table_add MyIngress.level_2_4 MyIngress.CheckFeature 331 10 1 => 332 1 0 342 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 332 1 1 => 333 7 751 343 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 333 7 1 => 334 3 109551 344 | table_add MyIngress.level_2_7 MyIngress.SetClass2 334 3 1 => 335 1 345 | table_add MyIngress.level_2_7 MyIngress.SetClass2 334 3 0 => 336 0 346 | table_add MyIngress.level_2_6 MyIngress.SetClass2 333 7 0 => 337 0 347 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 332 1 0 => 338 8 1124 348 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 338 8 1 => 339 10 129 349 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 339 10 1 => 340 11 0 350 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 340 11 1 => 341 8 62 351 | table_add MyIngress.level_2_9 MyIngress.SetClass2 341 8 1 => 342 1 352 | table_add MyIngress.level_2_9 MyIngress.SetClass2 341 8 0 => 343 0 353 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 340 11 0 => 344 6 91 354 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 344 6 1 => 345 6 80 355 | table_add MyIngress.level_2_10 MyIngress.SetClass2 345 6 1 => 346 1 356 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 345 6 0 => 347 11 0 357 | table_add MyIngress.level_2_11 MyIngress.SetClass2 347 11 1 => 348 1 358 | table_add MyIngress.level_2_11 MyIngress.SetClass2 347 11 0 => 349 0 359 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 344 6 0 => 350 5 44 360 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 350 5 1 => 351 9 330000 361 | table_add MyIngress.level_2_11 MyIngress.SetClass2 351 9 1 => 352 1 362 | table_add MyIngress.level_2_11 MyIngress.SetClass2 351 9 0 => 353 1 363 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 350 5 0 => 354 6 507 364 | table_add MyIngress.level_2_11 MyIngress.SetClass2 354 6 1 => 355 0 365 | table_add MyIngress.level_2_11 MyIngress.SetClass2 354 6 0 => 356 1 366 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 339 10 0 => 357 1 1 367 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 357 1 1 => 358 6 786 368 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 358 6 1 => 359 5 44 369 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 359 5 1 => 360 3 3955 370 | table_add MyIngress.level_2_11 MyIngress.SetClass2 360 3 1 => 361 1 371 | table_add MyIngress.level_2_11 MyIngress.SetClass2 360 3 0 => 362 1 372 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 359 5 0 => 363 3 6700 373 | table_add MyIngress.level_2_11 MyIngress.SetClass2 363 3 1 => 364 0 374 | table_add MyIngress.level_2_11 MyIngress.SetClass2 363 3 0 => 365 1 375 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 358 6 0 => 366 11 360000 376 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 366 11 1 => 367 6 5260 377 | table_add MyIngress.level_2_11 MyIngress.SetClass2 367 6 1 => 368 1 378 | table_add MyIngress.level_2_11 MyIngress.SetClass2 367 6 0 => 369 1 379 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 366 11 0 => 370 3 28009 380 | table_add MyIngress.level_2_11 MyIngress.SetClass2 370 3 1 => 371 1 381 | table_add MyIngress.level_2_11 MyIngress.SetClass2 370 3 0 => 372 1 382 | table_add MyIngress.level_2_8 MyIngress.SetClass2 357 1 0 => 373 1 383 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 338 8 0 => 374 6 68192 384 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 374 6 1 => 375 3 845637 385 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 375 3 1 => 376 8 1136 386 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 376 8 1 => 377 7 4918 387 | table_add MyIngress.level_2_10 MyIngress.SetClass2 377 7 1 => 378 0 388 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 377 7 0 => 379 9 120000 389 | table_add MyIngress.level_2_11 MyIngress.SetClass2 379 9 1 => 380 0 390 | table_add MyIngress.level_2_11 MyIngress.SetClass2 379 9 0 => 381 0 391 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 376 8 0 => 382 11 1340000 392 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 382 11 1 => 383 7 4192 393 | table_add MyIngress.level_2_11 MyIngress.SetClass2 383 7 1 => 384 0 394 | table_add MyIngress.level_2_11 MyIngress.SetClass2 383 7 0 => 385 1 395 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 382 11 0 => 386 6 68110 396 | table_add MyIngress.level_2_11 MyIngress.SetClass2 386 6 1 => 387 0 397 | table_add MyIngress.level_2_11 MyIngress.SetClass2 386 6 0 => 388 1 398 | table_add MyIngress.level_2_8 MyIngress.SetClass2 375 3 0 => 389 1 399 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 374 6 0 => 390 6 68194 400 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 390 6 1 => 391 7 4000 401 | table_add MyIngress.level_2_9 MyIngress.SetClass2 391 7 1 => 392 1 402 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 391 7 0 => 393 7 4473 403 | table_add MyIngress.level_2_10 MyIngress.SetClass2 393 7 1 => 394 0 404 | table_add MyIngress.level_2_10 MyIngress.SetClass2 393 7 0 => 395 1 405 | table_add MyIngress.level_2_8 MyIngress.SetClass2 390 6 0 => 396 1 406 | table_add MyIngress.level_2_4 MyIngress.CheckFeature 331 10 0 => 397 8 45 407 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 397 8 1 => 398 10 2048 408 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 398 10 1 => 399 6 397 409 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 399 6 1 => 400 8 38 410 | table_add MyIngress.level_2_8 MyIngress.SetClass2 400 8 1 => 401 1 411 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 400 8 0 => 402 7 461 412 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 402 7 1 => 403 3 130000000 413 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 403 3 1 => 404 11 0 414 | table_add MyIngress.level_2_11 MyIngress.SetClass2 404 11 1 => 405 1 415 | table_add MyIngress.level_2_11 MyIngress.SetClass2 404 11 0 => 406 0 416 | table_add MyIngress.level_2_10 MyIngress.SetClass2 403 3 0 => 407 0 417 | table_add MyIngress.level_2_9 MyIngress.SetClass2 402 7 0 => 408 0 418 | table_add MyIngress.level_2_7 MyIngress.SetClass2 399 6 0 => 409 1 419 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 398 10 0 => 410 4 3 420 | table_add MyIngress.level_2_7 MyIngress.SetClass2 410 4 1 => 411 0 421 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 410 4 0 => 412 11 310000 422 | table_add MyIngress.level_2_8 MyIngress.SetClass2 412 11 1 => 413 1 423 | table_add MyIngress.level_2_8 MyIngress.SetClass2 412 11 0 => 414 0 424 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 397 8 0 => 415 3 10749 425 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 415 3 1 => 416 2 126 426 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 416 2 1 => 417 6 220 427 | table_add MyIngress.level_2_8 MyIngress.SetClass2 417 6 1 => 418 0 428 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 417 6 0 => 419 6 2129 429 | table_add MyIngress.level_2_9 MyIngress.SetClass2 419 6 1 => 420 1 430 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 419 6 0 => 421 6 2207 431 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 421 6 1 => 422 11 14210000 432 | table_add MyIngress.level_2_11 MyIngress.SetClass2 422 11 1 => 423 0 433 | table_add MyIngress.level_2_11 MyIngress.SetClass2 422 11 0 => 424 1 434 | table_add MyIngress.level_2_10 MyIngress.SetClass2 421 6 0 => 425 1 435 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 416 2 0 => 426 10 284 436 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 426 10 1 => 427 4 9 437 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 427 4 1 => 428 4 7 438 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 428 4 1 => 429 5 44 439 | table_add MyIngress.level_2_11 MyIngress.SetClass2 429 5 1 => 430 1 440 | table_add MyIngress.level_2_11 MyIngress.SetClass2 429 5 0 => 431 0 441 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 428 4 0 => 432 8 72 442 | table_add MyIngress.level_2_11 MyIngress.SetClass2 432 8 1 => 433 0 443 | table_add MyIngress.level_2_11 MyIngress.SetClass2 432 8 0 => 434 0 444 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 427 4 0 => 435 7 82 445 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 435 7 1 => 436 7 77 446 | table_add MyIngress.level_2_11 MyIngress.SetClass2 436 7 1 => 437 1 447 | table_add MyIngress.level_2_11 MyIngress.SetClass2 436 7 0 => 438 0 448 | table_add MyIngress.level_2_10 MyIngress.SetClass2 435 7 0 => 439 1 449 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 426 10 0 => 440 6 2317 450 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 440 6 1 => 441 3 5488 451 | table_add MyIngress.level_2_10 MyIngress.SetClass2 441 3 1 => 442 1 452 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 441 3 0 => 443 7 4702 453 | table_add MyIngress.level_2_11 MyIngress.SetClass2 443 7 1 => 444 1 454 | table_add MyIngress.level_2_11 MyIngress.SetClass2 443 7 0 => 445 0 455 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 440 6 0 => 446 7 666 456 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 446 7 1 => 447 9 180000 457 | table_add MyIngress.level_2_11 MyIngress.SetClass2 447 9 1 => 448 0 458 | table_add MyIngress.level_2_11 MyIngress.SetClass2 447 9 0 => 449 1 459 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 446 7 0 => 450 11 2560000 460 | table_add MyIngress.level_2_11 MyIngress.SetClass2 450 11 1 => 451 0 461 | table_add MyIngress.level_2_11 MyIngress.SetClass2 450 11 0 => 452 0 462 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 415 3 0 => 453 10 1767 463 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 453 10 1 => 454 7 5483 464 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 454 7 1 => 455 10 284 465 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 455 10 1 => 456 4 13 466 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 456 4 1 => 457 3 227992 467 | table_add MyIngress.level_2_11 MyIngress.SetClass2 457 3 1 => 458 0 468 | table_add MyIngress.level_2_11 MyIngress.SetClass2 457 3 0 => 459 0 469 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 456 4 0 => 460 4 19 470 | table_add MyIngress.level_2_11 MyIngress.SetClass2 460 4 1 => 461 0 471 | table_add MyIngress.level_2_11 MyIngress.SetClass2 460 4 0 => 462 0 472 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 455 10 0 => 463 10 517 473 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 463 10 1 => 464 6 2034 474 | table_add MyIngress.level_2_11 MyIngress.SetClass2 464 6 1 => 465 1 475 | table_add MyIngress.level_2_11 MyIngress.SetClass2 464 6 0 => 466 1 476 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 463 10 0 => 467 6 2523 477 | table_add MyIngress.level_2_11 MyIngress.SetClass2 467 6 1 => 468 0 478 | table_add MyIngress.level_2_11 MyIngress.SetClass2 467 6 0 => 469 1 479 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 454 7 0 => 470 3 920976 480 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 470 3 1 => 471 9 90000 481 | table_add MyIngress.level_2_10 MyIngress.SetClass2 471 9 1 => 472 1 482 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 471 9 0 => 473 6 538 483 | table_add MyIngress.level_2_11 MyIngress.SetClass2 473 6 1 => 474 1 484 | table_add MyIngress.level_2_11 MyIngress.SetClass2 473 6 0 => 475 1 485 | table_add MyIngress.level_2_9 MyIngress.SetClass2 470 3 0 => 476 0 486 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 453 10 0 => 477 5 21 487 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 477 5 1 => 478 11 0 488 | table_add MyIngress.level_2_9 MyIngress.SetClass2 478 11 1 => 479 0 489 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 478 11 0 => 480 6 2463 490 | table_add MyIngress.level_2_10 MyIngress.SetClass2 480 6 1 => 481 1 491 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 480 6 0 => 482 11 60000 492 | table_add MyIngress.level_2_11 MyIngress.SetClass2 482 11 1 => 483 1 493 | table_add MyIngress.level_2_11 MyIngress.SetClass2 482 11 0 => 484 0 494 | table_add MyIngress.level_2_8 MyIngress.SetClass2 477 5 0 => 485 1 495 | table_add MyIngress.level_2_2 MyIngress.CheckFeature 288 5 0 => 486 1 0 496 | table_add MyIngress.level_2_3 MyIngress.SetClass2 486 1 1 => 487 0 497 | table_add MyIngress.level_2_3 MyIngress.CheckFeature 486 1 0 => 488 4 14 498 | table_add MyIngress.level_2_4 MyIngress.CheckFeature 488 4 1 => 489 9 80000 499 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 489 9 1 => 490 6 102 500 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 490 6 1 => 491 1 4 501 | table_add MyIngress.level_2_7 MyIngress.SetClass2 491 1 1 => 492 1 502 | table_add MyIngress.level_2_7 MyIngress.SetClass2 491 1 0 => 493 0 503 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 490 6 0 => 494 11 560000 504 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 494 11 1 => 495 11 280000 505 | table_add MyIngress.level_2_8 MyIngress.SetClass2 495 11 1 => 496 1 506 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 495 11 0 => 497 7 9204 507 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 497 7 1 => 498 9 10000 508 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 498 9 1 => 499 7 7918 509 | table_add MyIngress.level_2_11 MyIngress.SetClass2 499 7 1 => 500 1 510 | table_add MyIngress.level_2_11 MyIngress.SetClass2 499 7 0 => 501 0 511 | table_add MyIngress.level_2_10 MyIngress.SetClass2 498 9 0 => 502 1 512 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 497 7 0 => 503 11 420000 513 | table_add MyIngress.level_2_10 MyIngress.SetClass2 503 11 1 => 504 1 514 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 503 11 0 => 505 9 70000 515 | table_add MyIngress.level_2_11 MyIngress.SetClass2 505 9 1 => 506 1 516 | table_add MyIngress.level_2_11 MyIngress.SetClass2 505 9 0 => 507 1 517 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 494 11 0 => 508 11 560000 518 | table_add MyIngress.level_2_8 MyIngress.SetClass2 508 11 1 => 509 0 519 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 508 11 0 => 510 2 156 520 | table_add MyIngress.level_2_9 MyIngress.SetClass2 510 2 1 => 511 1 521 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 510 2 0 => 512 10 312 522 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 512 10 1 => 513 7 8797 523 | table_add MyIngress.level_2_11 MyIngress.SetClass2 513 7 1 => 514 1 524 | table_add MyIngress.level_2_11 MyIngress.SetClass2 513 7 0 => 515 1 525 | table_add MyIngress.level_2_10 MyIngress.SetClass2 512 10 0 => 516 1 526 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 489 9 0 => 517 11 1880000 527 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 517 11 1 => 518 6 843 528 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 518 6 1 => 519 10 4153 529 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 519 10 1 => 520 6 805 530 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 520 6 1 => 521 6 697 531 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 521 6 1 => 522 9 260000 532 | table_add MyIngress.level_2_11 MyIngress.SetClass2 522 9 1 => 523 0 533 | table_add MyIngress.level_2_11 MyIngress.SetClass2 522 9 0 => 524 1 534 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 521 6 0 => 525 7 15980 535 | table_add MyIngress.level_2_11 MyIngress.SetClass2 525 7 1 => 526 1 536 | table_add MyIngress.level_2_11 MyIngress.SetClass2 525 7 0 => 527 1 537 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 520 6 0 => 528 5 171 538 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 528 5 1 => 529 0 158 539 | table_add MyIngress.level_2_11 MyIngress.SetClass2 529 0 1 => 530 0 540 | table_add MyIngress.level_2_11 MyIngress.SetClass2 529 0 0 => 531 1 541 | table_add MyIngress.level_2_10 MyIngress.SetClass2 528 5 0 => 532 1 542 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 519 10 0 => 533 5 59 543 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 533 5 1 => 534 5 50 544 | table_add MyIngress.level_2_10 MyIngress.SetClass2 534 5 1 => 535 1 545 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 534 5 0 => 536 10 6153 546 | table_add MyIngress.level_2_11 MyIngress.SetClass2 536 10 1 => 537 1 547 | table_add MyIngress.level_2_11 MyIngress.SetClass2 536 10 0 => 538 0 548 | table_add MyIngress.level_2_9 MyIngress.SetClass2 533 5 0 => 539 1 549 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 518 6 0 => 540 5 57 550 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 540 5 1 => 541 10 161 551 | table_add MyIngress.level_2_9 MyIngress.SetClass2 541 10 1 => 542 1 552 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 541 10 0 => 543 11 1190000 553 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 543 11 1 => 544 3 46699 554 | table_add MyIngress.level_2_11 MyIngress.SetClass2 544 3 1 => 545 0 555 | table_add MyIngress.level_2_11 MyIngress.SetClass2 544 3 0 => 546 1 556 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 543 11 0 => 547 4 13 557 | table_add MyIngress.level_2_11 MyIngress.SetClass2 547 4 1 => 548 1 558 | table_add MyIngress.level_2_11 MyIngress.SetClass2 547 4 0 => 549 0 559 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 540 5 0 => 550 10 444 560 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 550 10 1 => 551 3 6394 561 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 551 3 1 => 552 3 6060 562 | table_add MyIngress.level_2_11 MyIngress.SetClass2 552 3 1 => 553 1 563 | table_add MyIngress.level_2_11 MyIngress.SetClass2 552 3 0 => 554 0 564 | table_add MyIngress.level_2_10 MyIngress.SetClass2 551 3 0 => 555 1 565 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 550 10 0 => 556 3 10840 566 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 556 3 1 => 557 5 79 567 | table_add MyIngress.level_2_11 MyIngress.SetClass2 557 5 1 => 558 0 568 | table_add MyIngress.level_2_11 MyIngress.SetClass2 557 5 0 => 559 1 569 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 556 3 0 => 560 8 84 570 | table_add MyIngress.level_2_11 MyIngress.SetClass2 560 8 1 => 561 1 571 | table_add MyIngress.level_2_11 MyIngress.SetClass2 560 8 0 => 562 1 572 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 517 11 0 => 563 7 2343 573 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 563 7 1 => 564 6 1006 574 | table_add MyIngress.level_2_8 MyIngress.SetClass2 564 6 1 => 565 1 575 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 564 6 0 => 566 10 312 576 | table_add MyIngress.level_2_9 MyIngress.SetClass2 566 10 1 => 567 1 577 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 566 10 0 => 568 3 2214 578 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 568 3 1 => 569 9 230000 579 | table_add MyIngress.level_2_11 MyIngress.SetClass2 569 9 1 => 570 1 580 | table_add MyIngress.level_2_11 MyIngress.SetClass2 569 9 0 => 571 0 581 | table_add MyIngress.level_2_10 MyIngress.SetClass2 568 3 0 => 572 1 582 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 563 7 0 => 573 6 26091 583 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 573 6 1 => 574 5 82 584 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 574 5 1 => 575 6 936 585 | table_add MyIngress.level_2_10 MyIngress.SetClass2 575 6 1 => 576 1 586 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 575 6 0 => 577 6 996 587 | table_add MyIngress.level_2_11 MyIngress.SetClass2 577 6 1 => 578 0 588 | table_add MyIngress.level_2_11 MyIngress.SetClass2 577 6 0 => 579 1 589 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 574 5 0 => 580 9 250000 590 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 580 9 1 => 581 7 2422 591 | table_add MyIngress.level_2_11 MyIngress.SetClass2 581 7 1 => 582 0 592 | table_add MyIngress.level_2_11 MyIngress.SetClass2 581 7 0 => 583 1 593 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 580 9 0 => 584 8 122 594 | table_add MyIngress.level_2_11 MyIngress.SetClass2 584 8 1 => 585 0 595 | table_add MyIngress.level_2_11 MyIngress.SetClass2 584 8 0 => 586 1 596 | table_add MyIngress.level_2_8 MyIngress.SetClass2 573 6 0 => 587 0 597 | table_add MyIngress.level_2_4 MyIngress.CheckFeature 488 4 0 => 588 11 58370000 598 | table_add MyIngress.level_2_5 MyIngress.CheckFeature 588 11 1 => 589 10 161 599 | table_add MyIngress.level_2_6 MyIngress.SetClass2 589 10 1 => 590 1 600 | table_add MyIngress.level_2_6 MyIngress.CheckFeature 589 10 0 => 591 11 1120000 601 | table_add MyIngress.level_2_7 MyIngress.CheckFeature 591 11 1 => 592 6 25713 602 | table_add MyIngress.level_2_8 MyIngress.SetClass2 592 6 1 => 593 1 603 | table_add MyIngress.level_2_8 MyIngress.CheckFeature 592 6 0 => 594 3 215371 604 | table_add MyIngress.level_2_9 MyIngress.SetClass2 594 3 1 => 595 0 605 | table_add MyIngress.level_2_9 MyIngress.CheckFeature 594 3 0 => 596 10 281 606 | table_add MyIngress.level_2_10 MyIngress.CheckFeature 596 10 1 => 597 7 7063 607 | table_add MyIngress.level_2_11 MyIngress.SetClass2 597 7 1 => 598 0 608 | table_add MyIngress.level_2_11 MyIngress.SetClass2 597 7 0 => 599 1 609 | table_add MyIngress.level_2_10 MyIngress.SetClass2 596 10 0 => 600 1 610 | table_add MyIngress.level_2_7 MyIngress.SetClass2 591 11 0 => 601 1 611 | table_add MyIngress.level_2_5 MyIngress.SetClass2 588 11 0 => 602 0 612 | table_add MyIngress.level_3_1 MyIngress.CheckFeature 602 0 1 => 603 7 5328 613 | table_add MyIngress.level_3_2 MyIngress.CheckFeature 603 7 1 => 604 5 45 614 | table_add MyIngress.level_3_3 MyIngress.CheckFeature 604 5 1 => 605 3 204 615 | table_add MyIngress.level_3_4 MyIngress.CheckFeature 605 3 1 => 606 7 93 616 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 606 7 1 => 607 5 43 617 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 607 5 1 => 608 0 159 618 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 608 0 1 => 609 6 62 619 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 609 6 1 => 610 11 0 620 | table_add MyIngress.level_3_9 MyIngress.SetClass3 610 11 1 => 611 0 621 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 610 11 0 => 612 8 53 622 | table_add MyIngress.level_3_10 MyIngress.SetClass3 612 8 1 => 613 0 623 | table_add MyIngress.level_3_10 MyIngress.SetClass3 612 8 0 => 614 1 624 | table_add MyIngress.level_3_8 MyIngress.SetClass3 609 6 0 => 615 0 625 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 608 0 0 => 616 10 294 626 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 616 10 1 => 617 8 26 627 | table_add MyIngress.level_3_9 MyIngress.SetClass3 617 8 1 => 618 1 628 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 617 8 0 => 619 6 764 629 | table_add MyIngress.level_3_10 MyIngress.SetClass3 619 6 1 => 620 0 630 | table_add MyIngress.level_3_10 MyIngress.SetClass3 619 6 0 => 621 1 631 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 616 10 0 => 622 11 55640000 632 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 622 11 1 => 623 6 438 633 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 623 6 1 => 624 1 1 634 | table_add MyIngress.level_3_11 MyIngress.SetClass3 624 1 1 => 625 0 635 | table_add MyIngress.level_3_11 MyIngress.SetClass3 624 1 0 => 626 0 636 | table_add MyIngress.level_3_10 MyIngress.SetClass3 623 6 0 => 627 1 637 | table_add MyIngress.level_3_9 MyIngress.SetClass3 622 11 0 => 628 0 638 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 607 5 0 => 629 11 54540000 639 | table_add MyIngress.level_3_7 MyIngress.SetClass3 629 11 1 => 630 0 640 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 629 11 0 => 631 6 1274 641 | table_add MyIngress.level_3_8 MyIngress.SetClass3 631 6 1 => 632 1 642 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 631 6 0 => 633 4 13 643 | table_add MyIngress.level_3_9 MyIngress.SetClass3 633 4 1 => 634 1 644 | table_add MyIngress.level_3_9 MyIngress.SetClass3 633 4 0 => 635 0 645 | table_add MyIngress.level_3_5 MyIngress.SetClass3 606 7 0 => 636 1 646 | table_add MyIngress.level_3_4 MyIngress.CheckFeature 605 3 0 => 637 9 260000 647 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 637 9 1 => 638 9 140000 648 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 638 9 1 => 639 0 253 649 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 639 0 1 => 640 1 0 650 | table_add MyIngress.level_3_8 MyIngress.SetClass3 640 1 1 => 641 0 651 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 640 1 0 => 642 1 2 652 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 642 1 1 => 643 7 3131 653 | table_add MyIngress.level_3_10 MyIngress.SetClass3 643 7 1 => 644 1 654 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 643 7 0 => 645 9 120000 655 | table_add MyIngress.level_3_11 MyIngress.SetClass3 645 9 1 => 646 1 656 | table_add MyIngress.level_3_11 MyIngress.SetClass3 645 9 0 => 647 0 657 | table_add MyIngress.level_3_9 MyIngress.SetClass3 642 1 0 => 648 0 658 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 639 0 0 => 649 1 2 659 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 649 1 1 => 650 7 908 660 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 650 7 1 => 651 10 507 661 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 651 10 1 => 652 1 0 662 | table_add MyIngress.level_3_11 MyIngress.SetClass3 652 1 1 => 653 0 663 | table_add MyIngress.level_3_11 MyIngress.SetClass3 652 1 0 => 654 1 664 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 651 10 0 => 655 10 1767 665 | table_add MyIngress.level_3_11 MyIngress.SetClass3 655 10 1 => 656 0 666 | table_add MyIngress.level_3_11 MyIngress.SetClass3 655 10 0 => 657 1 667 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 650 7 0 => 658 6 535 668 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 658 6 1 => 659 4 5 669 | table_add MyIngress.level_3_11 MyIngress.SetClass3 659 4 1 => 660 0 670 | table_add MyIngress.level_3_11 MyIngress.SetClass3 659 4 0 => 661 0 671 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 658 6 0 => 662 10 157 672 | table_add MyIngress.level_3_11 MyIngress.SetClass3 662 10 1 => 663 1 673 | table_add MyIngress.level_3_11 MyIngress.SetClass3 662 10 0 => 664 1 674 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 649 1 0 => 665 10 589 675 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 665 10 1 => 666 6 128 676 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 666 6 1 => 667 10 388 677 | table_add MyIngress.level_3_11 MyIngress.SetClass3 667 10 1 => 668 0 678 | table_add MyIngress.level_3_11 MyIngress.SetClass3 667 10 0 => 669 1 679 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 666 6 0 => 670 9 90000 680 | table_add MyIngress.level_3_11 MyIngress.SetClass3 670 9 1 => 671 1 681 | table_add MyIngress.level_3_11 MyIngress.SetClass3 670 9 0 => 672 0 682 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 665 10 0 => 673 11 170000 683 | table_add MyIngress.level_3_10 MyIngress.SetClass3 673 11 1 => 674 0 684 | table_add MyIngress.level_3_10 MyIngress.SetClass3 673 11 0 => 675 1 685 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 638 9 0 => 676 4 4 686 | table_add MyIngress.level_3_7 MyIngress.SetClass3 676 4 1 => 677 0 687 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 676 4 0 => 678 3 4562 688 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 678 3 1 => 679 8 46 689 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 679 8 1 => 680 1 0 690 | table_add MyIngress.level_3_10 MyIngress.SetClass3 680 1 1 => 681 0 691 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 680 1 0 => 682 9 180000 692 | table_add MyIngress.level_3_11 MyIngress.SetClass3 682 9 1 => 683 1 693 | table_add MyIngress.level_3_11 MyIngress.SetClass3 682 9 0 => 684 0 694 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 679 8 0 => 685 10 123 695 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 685 10 1 => 686 6 507 696 | table_add MyIngress.level_3_11 MyIngress.SetClass3 686 6 1 => 687 0 697 | table_add MyIngress.level_3_11 MyIngress.SetClass3 686 6 0 => 688 1 698 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 685 10 0 => 689 3 223 699 | table_add MyIngress.level_3_11 MyIngress.SetClass3 689 3 1 => 690 0 700 | table_add MyIngress.level_3_11 MyIngress.SetClass3 689 3 0 => 691 1 701 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 678 3 0 => 692 4 25 702 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 692 4 1 => 693 7 2716 703 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 693 7 1 => 694 8 149 704 | table_add MyIngress.level_3_11 MyIngress.SetClass3 694 8 1 => 695 1 705 | table_add MyIngress.level_3_11 MyIngress.SetClass3 694 8 0 => 696 0 706 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 693 7 0 => 697 10 123 707 | table_add MyIngress.level_3_11 MyIngress.SetClass3 697 10 1 => 698 1 708 | table_add MyIngress.level_3_11 MyIngress.SetClass3 697 10 0 => 699 0 709 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 692 4 0 => 700 3 787170 710 | table_add MyIngress.level_3_10 MyIngress.SetClass3 700 3 1 => 701 1 711 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 700 3 0 => 702 9 190000 712 | table_add MyIngress.level_3_11 MyIngress.SetClass3 702 9 1 => 703 1 713 | table_add MyIngress.level_3_11 MyIngress.SetClass3 702 9 0 => 704 0 714 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 637 9 0 => 705 5 43 715 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 705 5 1 => 706 10 519 716 | table_add MyIngress.level_3_7 MyIngress.SetClass3 706 10 1 => 707 1 717 | table_add MyIngress.level_3_7 MyIngress.SetClass3 706 10 0 => 708 0 718 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 705 5 0 => 709 6 1359 719 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 709 6 1 => 710 3 3256 720 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 710 3 1 => 711 6 902 721 | table_add MyIngress.level_3_9 MyIngress.SetClass3 711 6 1 => 712 1 722 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 711 6 0 => 713 9 290000 723 | table_add MyIngress.level_3_10 MyIngress.SetClass3 713 9 1 => 714 1 724 | table_add MyIngress.level_3_10 MyIngress.SetClass3 713 9 0 => 715 0 725 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 710 3 0 => 716 10 157 726 | table_add MyIngress.level_3_9 MyIngress.SetClass3 716 10 1 => 717 1 727 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 716 10 0 => 718 3 6993 728 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 718 3 1 => 719 6 600 729 | table_add MyIngress.level_3_11 MyIngress.SetClass3 719 6 1 => 720 1 730 | table_add MyIngress.level_3_11 MyIngress.SetClass3 719 6 0 => 721 0 731 | table_add MyIngress.level_3_10 MyIngress.SetClass3 718 3 0 => 722 1 732 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 709 6 0 => 723 11 1070000 733 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 723 11 1 => 724 8 455 734 | table_add MyIngress.level_3_9 MyIngress.SetClass3 724 8 1 => 725 0 735 | table_add MyIngress.level_3_9 MyIngress.SetClass3 724 8 0 => 726 1 736 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 723 11 0 => 727 3 14481 737 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 727 3 1 => 728 11 3070000 738 | table_add MyIngress.level_3_10 MyIngress.SetClass3 728 11 1 => 729 0 739 | table_add MyIngress.level_3_10 MyIngress.SetClass3 728 11 0 => 730 1 740 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 727 3 0 => 731 10 312 741 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 731 10 1 => 732 10 129 742 | table_add MyIngress.level_3_11 MyIngress.SetClass3 732 10 1 => 733 1 743 | table_add MyIngress.level_3_11 MyIngress.SetClass3 732 10 0 => 734 0 744 | table_add MyIngress.level_3_10 MyIngress.SetClass3 731 10 0 => 735 1 745 | table_add MyIngress.level_3_3 MyIngress.CheckFeature 604 5 0 => 736 1 0 746 | table_add MyIngress.level_3_4 MyIngress.SetClass3 736 1 1 => 737 0 747 | table_add MyIngress.level_3_4 MyIngress.CheckFeature 736 1 0 => 738 5 56 748 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 738 5 1 => 739 7 3891 749 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 739 7 1 => 740 8 45 750 | table_add MyIngress.level_3_7 MyIngress.SetClass3 740 8 1 => 741 0 751 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 740 8 0 => 742 3 4345 752 | table_add MyIngress.level_3_8 MyIngress.SetClass3 742 3 1 => 743 1 753 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 742 3 0 => 744 8 55 754 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 744 8 1 => 745 7 3584 755 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 745 7 1 => 746 10 129 756 | table_add MyIngress.level_3_11 MyIngress.SetClass3 746 10 1 => 747 1 757 | table_add MyIngress.level_3_11 MyIngress.SetClass3 746 10 0 => 748 0 758 | table_add MyIngress.level_3_10 MyIngress.SetClass3 745 7 0 => 749 1 759 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 744 8 0 => 750 6 732 760 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 750 6 1 => 751 4 4 761 | table_add MyIngress.level_3_11 MyIngress.SetClass3 751 4 1 => 752 1 762 | table_add MyIngress.level_3_11 MyIngress.SetClass3 751 4 0 => 753 1 763 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 750 6 0 => 754 1 3 764 | table_add MyIngress.level_3_11 MyIngress.SetClass3 754 1 1 => 755 1 765 | table_add MyIngress.level_3_11 MyIngress.SetClass3 754 1 0 => 756 0 766 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 739 7 0 => 757 10 161 767 | table_add MyIngress.level_3_7 MyIngress.SetClass3 757 10 1 => 758 1 768 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 757 10 0 => 759 3 8942 769 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 759 3 1 => 760 6 726 770 | table_add MyIngress.level_3_9 MyIngress.SetClass3 760 6 1 => 761 1 771 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 760 6 0 => 762 5 50 772 | table_add MyIngress.level_3_10 MyIngress.SetClass3 762 5 1 => 763 1 773 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 762 5 0 => 764 3 6853 774 | table_add MyIngress.level_3_11 MyIngress.SetClass3 764 3 1 => 765 0 775 | table_add MyIngress.level_3_11 MyIngress.SetClass3 764 3 0 => 766 1 776 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 759 3 0 => 767 4 20 777 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 767 4 1 => 768 3 47141 778 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 768 3 1 => 769 10 3341 779 | table_add MyIngress.level_3_11 MyIngress.SetClass3 769 10 1 => 770 0 780 | table_add MyIngress.level_3_11 MyIngress.SetClass3 769 10 0 => 771 1 781 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 768 3 0 => 772 4 11 782 | table_add MyIngress.level_3_11 MyIngress.SetClass3 772 4 1 => 773 1 783 | table_add MyIngress.level_3_11 MyIngress.SetClass3 772 4 0 => 774 0 784 | table_add MyIngress.level_3_9 MyIngress.SetClass3 767 4 0 => 775 1 785 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 738 5 0 => 776 9 190000 786 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 776 9 1 => 777 0 158 787 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 777 0 1 => 778 11 2190000 788 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 778 11 1 => 779 8 80 789 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 779 8 1 => 780 3 1035 790 | table_add MyIngress.level_3_10 MyIngress.SetClass3 780 3 1 => 781 0 791 | table_add MyIngress.level_3_10 MyIngress.SetClass3 780 3 0 => 782 1 792 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 779 8 0 => 783 5 93 793 | table_add MyIngress.level_3_10 MyIngress.SetClass3 783 5 1 => 784 1 794 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 783 5 0 => 785 6 825 795 | table_add MyIngress.level_3_11 MyIngress.SetClass3 785 6 1 => 786 0 796 | table_add MyIngress.level_3_11 MyIngress.SetClass3 785 6 0 => 787 1 797 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 778 11 0 => 788 9 180000 798 | table_add MyIngress.level_3_9 MyIngress.SetClass3 788 9 1 => 789 1 799 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 788 9 0 => 790 3 1399 800 | table_add MyIngress.level_3_10 MyIngress.SetClass3 790 3 1 => 791 0 801 | table_add MyIngress.level_3_10 MyIngress.SetClass3 790 3 0 => 792 1 802 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 777 0 0 => 793 11 970000 803 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 793 11 1 => 794 5 76 804 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 794 5 1 => 795 10 2165 805 | table_add MyIngress.level_3_10 MyIngress.SetClass3 795 10 1 => 796 1 806 | table_add MyIngress.level_3_10 MyIngress.SetClass3 795 10 0 => 797 0 807 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 794 5 0 => 798 3 6360 808 | table_add MyIngress.level_3_10 MyIngress.SetClass3 798 3 1 => 799 1 809 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 798 3 0 => 800 5 90 810 | table_add MyIngress.level_3_11 MyIngress.SetClass3 800 5 1 => 801 1 811 | table_add MyIngress.level_3_11 MyIngress.SetClass3 800 5 0 => 802 0 812 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 793 11 0 => 803 9 150000 813 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 803 9 1 => 804 10 3273 814 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 804 10 1 => 805 6 574 815 | table_add MyIngress.level_3_11 MyIngress.SetClass3 805 6 1 => 806 0 816 | table_add MyIngress.level_3_11 MyIngress.SetClass3 805 6 0 => 807 1 817 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 804 10 0 => 808 6 955 818 | table_add MyIngress.level_3_11 MyIngress.SetClass3 808 6 1 => 809 0 819 | table_add MyIngress.level_3_11 MyIngress.SetClass3 808 6 0 => 810 1 820 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 803 9 0 => 811 3 170206 821 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 811 3 1 => 812 9 150000 822 | table_add MyIngress.level_3_11 MyIngress.SetClass3 812 9 1 => 813 0 823 | table_add MyIngress.level_3_11 MyIngress.SetClass3 812 9 0 => 814 1 824 | table_add MyIngress.level_3_10 MyIngress.SetClass3 811 3 0 => 815 0 825 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 776 9 0 => 816 6 698 826 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 816 6 1 => 817 6 599 827 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 817 6 1 => 818 9 210000 828 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 818 9 1 => 819 7 3297 829 | table_add MyIngress.level_3_10 MyIngress.SetClass3 819 7 1 => 820 1 830 | table_add MyIngress.level_3_10 MyIngress.SetClass3 819 7 0 => 821 0 831 | table_add MyIngress.level_3_9 MyIngress.SetClass3 818 9 0 => 822 1 832 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 817 6 0 => 823 10 1663 833 | table_add MyIngress.level_3_9 MyIngress.SetClass3 823 10 1 => 824 0 834 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 823 10 0 => 825 4 11 835 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 825 4 1 => 826 7 3826 836 | table_add MyIngress.level_3_11 MyIngress.SetClass3 826 7 1 => 827 0 837 | table_add MyIngress.level_3_11 MyIngress.SetClass3 826 7 0 => 828 0 838 | table_add MyIngress.level_3_10 MyIngress.SetClass3 825 4 0 => 829 1 839 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 816 6 0 => 830 11 55370000 840 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 830 11 1 => 831 11 2580000 841 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 831 11 1 => 832 11 1700000 842 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 832 11 1 => 833 8 86 843 | table_add MyIngress.level_3_11 MyIngress.SetClass3 833 8 1 => 834 1 844 | table_add MyIngress.level_3_11 MyIngress.SetClass3 833 8 0 => 835 1 845 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 832 11 0 => 836 10 52 846 | table_add MyIngress.level_3_11 MyIngress.SetClass3 836 10 1 => 837 1 847 | table_add MyIngress.level_3_11 MyIngress.SetClass3 836 10 0 => 838 0 848 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 831 11 0 => 839 7 2549 849 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 839 7 1 => 840 6 3461 850 | table_add MyIngress.level_3_11 MyIngress.SetClass3 840 6 1 => 841 1 851 | table_add MyIngress.level_3_11 MyIngress.SetClass3 840 6 0 => 842 0 852 | table_add MyIngress.level_3_10 MyIngress.SetClass3 839 7 0 => 843 1 853 | table_add MyIngress.level_3_8 MyIngress.SetClass3 830 11 0 => 844 0 854 | table_add MyIngress.level_3_2 MyIngress.CheckFeature 603 7 0 => 845 0 61 855 | table_add MyIngress.level_3_3 MyIngress.SetClass3 845 0 1 => 846 0 856 | table_add MyIngress.level_3_3 MyIngress.CheckFeature 845 0 0 => 847 7 22014 857 | table_add MyIngress.level_3_4 MyIngress.CheckFeature 847 7 1 => 848 5 114 858 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 848 5 1 => 849 4 16 859 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 849 4 1 => 850 4 9 860 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 850 4 1 => 851 9 20000 861 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 851 9 1 => 852 10 129 862 | table_add MyIngress.level_3_9 MyIngress.SetClass3 852 10 1 => 853 1 863 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 852 10 0 => 854 5 70 864 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 854 5 1 => 855 7 14028 865 | table_add MyIngress.level_3_11 MyIngress.SetClass3 855 7 1 => 856 0 866 | table_add MyIngress.level_3_11 MyIngress.SetClass3 855 7 0 => 857 1 867 | table_add MyIngress.level_3_10 MyIngress.SetClass3 854 5 0 => 858 1 868 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 851 9 0 => 859 2 156 869 | table_add MyIngress.level_3_9 MyIngress.SetClass3 859 2 1 => 860 0 870 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 859 2 0 => 861 3 13709 871 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 861 3 1 => 862 3 12794 872 | table_add MyIngress.level_3_11 MyIngress.SetClass3 862 3 1 => 863 1 873 | table_add MyIngress.level_3_11 MyIngress.SetClass3 862 3 0 => 864 0 874 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 861 3 0 => 865 7 6321 875 | table_add MyIngress.level_3_11 MyIngress.SetClass3 865 7 1 => 866 1 876 | table_add MyIngress.level_3_11 MyIngress.SetClass3 865 7 0 => 867 1 877 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 850 4 0 => 868 7 7512 878 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 868 7 1 => 869 10 161 879 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 869 10 1 => 870 3 596618 880 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 870 3 1 => 871 7 5908 881 | table_add MyIngress.level_3_11 MyIngress.SetClass3 871 7 1 => 872 1 882 | table_add MyIngress.level_3_11 MyIngress.SetClass3 871 7 0 => 873 1 883 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 870 3 0 => 874 4 13 884 | table_add MyIngress.level_3_11 MyIngress.SetClass3 874 4 1 => 875 1 885 | table_add MyIngress.level_3_11 MyIngress.SetClass3 874 4 0 => 876 1 886 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 869 10 0 => 877 10 312 887 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 877 10 1 => 878 7 6379 888 | table_add MyIngress.level_3_11 MyIngress.SetClass3 878 7 1 => 879 0 889 | table_add MyIngress.level_3_11 MyIngress.SetClass3 878 7 0 => 880 0 890 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 877 10 0 => 881 6 668 891 | table_add MyIngress.level_3_11 MyIngress.SetClass3 881 6 1 => 882 0 892 | table_add MyIngress.level_3_11 MyIngress.SetClass3 881 6 0 => 883 1 893 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 868 7 0 => 884 6 648 894 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 884 6 1 => 885 7 8118 895 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 885 7 1 => 886 9 70000 896 | table_add MyIngress.level_3_11 MyIngress.SetClass3 886 9 1 => 887 1 897 | table_add MyIngress.level_3_11 MyIngress.SetClass3 886 9 0 => 888 0 898 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 885 7 0 => 889 8 57 899 | table_add MyIngress.level_3_11 MyIngress.SetClass3 889 8 1 => 890 1 900 | table_add MyIngress.level_3_11 MyIngress.SetClass3 889 8 0 => 891 1 901 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 884 6 0 => 892 10 161 902 | table_add MyIngress.level_3_10 MyIngress.SetClass3 892 10 1 => 893 1 903 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 892 10 0 => 894 11 580000 904 | table_add MyIngress.level_3_11 MyIngress.SetClass3 894 11 1 => 895 1 905 | table_add MyIngress.level_3_11 MyIngress.SetClass3 894 11 0 => 896 1 906 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 849 4 0 => 897 7 5388 907 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 897 7 1 => 898 9 180000 908 | table_add MyIngress.level_3_8 MyIngress.SetClass3 898 9 1 => 899 0 909 | table_add MyIngress.level_3_8 MyIngress.SetClass3 898 9 0 => 900 1 910 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 897 7 0 => 901 8 1274 911 | table_add MyIngress.level_3_8 MyIngress.SetClass3 901 8 1 => 902 1 912 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 901 8 0 => 903 7 5784 913 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 903 7 1 => 904 9 110000 914 | table_add MyIngress.level_3_10 MyIngress.SetClass3 904 9 1 => 905 1 915 | table_add MyIngress.level_3_10 MyIngress.SetClass3 904 9 0 => 906 0 916 | table_add MyIngress.level_3_9 MyIngress.SetClass3 903 7 0 => 907 1 917 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 848 5 0 => 908 5 173 918 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 908 5 1 => 909 9 100000 919 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 909 9 1 => 910 3 6416 920 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 910 3 1 => 911 7 7000 921 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 911 7 1 => 912 10 66 922 | table_add MyIngress.level_3_10 MyIngress.SetClass3 912 10 1 => 913 1 923 | table_add MyIngress.level_3_10 MyIngress.SetClass3 912 10 0 => 914 0 924 | table_add MyIngress.level_3_9 MyIngress.SetClass3 911 7 0 => 915 1 925 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 910 3 0 => 916 7 11911 926 | table_add MyIngress.level_3_9 MyIngress.SetClass3 916 7 1 => 917 0 927 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 916 7 0 => 918 6 843 928 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 918 6 1 => 919 8 80 929 | table_add MyIngress.level_3_11 MyIngress.SetClass3 919 8 1 => 920 1 930 | table_add MyIngress.level_3_11 MyIngress.SetClass3 919 8 0 => 921 0 931 | table_add MyIngress.level_3_10 MyIngress.SetClass3 918 6 0 => 922 1 932 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 909 9 0 => 923 0 158 933 | table_add MyIngress.level_3_8 MyIngress.CheckFeature 923 0 1 => 924 10 95 934 | table_add MyIngress.level_3_9 MyIngress.CheckFeature 924 10 1 => 925 8 84 935 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 925 8 1 => 926 5 144 936 | table_add MyIngress.level_3_11 MyIngress.SetClass3 926 5 1 => 927 0 937 | table_add MyIngress.level_3_11 MyIngress.SetClass3 926 5 0 => 928 0 938 | table_add MyIngress.level_3_10 MyIngress.CheckFeature 925 8 0 => 929 11 510000 939 | table_add MyIngress.level_3_11 MyIngress.SetClass3 929 11 1 => 930 0 940 | table_add MyIngress.level_3_11 MyIngress.SetClass3 929 11 0 => 931 1 941 | table_add MyIngress.level_3_9 MyIngress.SetClass3 924 10 0 => 932 1 942 | table_add MyIngress.level_3_8 MyIngress.SetClass3 923 0 0 => 933 1 943 | table_add MyIngress.level_3_6 MyIngress.SetClass3 908 5 0 => 934 1 944 | table_add MyIngress.level_3_4 MyIngress.CheckFeature 847 7 0 => 935 9 10000 945 | table_add MyIngress.level_3_5 MyIngress.CheckFeature 935 9 1 => 936 11 0 946 | table_add MyIngress.level_3_6 MyIngress.SetClass3 936 11 1 => 937 0 947 | table_add MyIngress.level_3_6 MyIngress.CheckFeature 936 11 0 => 938 8 46 948 | table_add MyIngress.level_3_7 MyIngress.CheckFeature 938 8 1 => 939 4 3 949 | table_add MyIngress.level_3_8 MyIngress.SetClass3 939 4 1 => 940 1 950 | table_add MyIngress.level_3_8 MyIngress.SetClass3 939 4 0 => 941 0 951 | table_add MyIngress.level_3_7 MyIngress.SetClass3 938 8 0 => 942 1 952 | table_add MyIngress.level_3_5 MyIngress.SetClass3 935 9 0 => 943 1 953 | table_add MyIngress.direction MyIngress.SetDirection 149.171.126.0/24 => 954 | table_add MyIngress.malware MyIngress.SetMalware 175.45.176.0/24 => 955 | table_add MyIngress.malware_inverse MyIngress.SetMalware 175.45.176.0/24 => 956 | table_add MyIngress.ipv4_exact MyIngress.ipv4_forward 0 => 00:00:00:00:02:02 2 957 | table_add MyIngress.ipv4_exact MyIngress.ipv4_forward 1 => 00:00:00:00:02:03 3 958 | table_dump MyIngress.level1 959 | table_dump MyIngress.level2 960 | table_dump MyIngress.level3 961 | table_dump MyIngress.ipv4_exact 962 | -------------------------------------------------------------------------------- /demo_data/README.md: -------------------------------------------------------------------------------- 1 | This is demo data in pcap. The data file data_1_clean.csv used in the scripts for training can be found here: 2 | 3 | [Google drive link](https://drive.google.com/file/d/1XhOzRsCbNwXmH1-qnBBA7YZ3jlzSs2BK/view?usp=drive_link) 4 | -------------------------------------------------------------------------------- /demo_data/UNSW_1000_packets.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ksingh25/SwitchTree/fcb0e078a80fd26519bac17bd26f7275aef67e2d/demo_data/UNSW_1000_packets.pcap -------------------------------------------------------------------------------- /get_results.txt: -------------------------------------------------------------------------------- 1 | counter_read counter_pkts 0 2 | counter_read counter_hash_collisions 0 3 | counter_read counter_malware 0 4 | counter_read counter_timeout 0 5 | counter_read counter_flows 0 6 | counter_read counter_malware_flows 0 7 | counter_read counter_true_detection_flows 0 8 | counter_read counter_false_detection_flows 0 9 | counter_read counter_false_detection 0 10 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | Here are various scripts used for training decision tree and random forests. 2 | 3 | - ML.ipynb is jupyter notebook file used to train randomforests. 4 | 5 | It will also write the decision trees in .dot files 6 | 7 | - rftop4_v2.py is a python file. It will read the randomforest file saved using pickle tool (see at the end of the notebook) and convert it into P4 rules. The code may need to be adapted to different number of trees in the trained random forest. 8 | 9 | 10 | # How do we convert a decision tree to P4 rules? 11 | 12 | Please check the paper: https://hal.archives-ouvertes.fr/hal-02968593/document. 13 | 14 | For example section 4.1 describes node id, previous feature id etc. 15 | 16 | Let us consider an example decision tree found in ML.ipynb: 17 | 18 | TREE 0 19 | 20 | |--- feature_9 <= 0.02 21 | 22 | | |--- feature_4 <= 0.50 23 | 24 | | | |--- feature_1 <= 1.00 25 | 26 | ... 27 | 28 | ... 29 | 30 | |--- feature_9 > 0.02 31 | 32 | | |--- feature_2 <= 156.00 33 | 34 | 35 | Corresponding P4 rules look like the following. 36 | 37 | `table_add MyIngress.level1 MyIngress.CheckFeature 0 0 1 => 1 9 20000` 38 | 39 | `table_add MyIngress.level2 MyIngress.CheckFeature 1 9 1 => 2 4 0` 40 | 41 | `table_add MyIngress.level3 MyIngress.CheckFeature 2 4 1 => 3 1 1` 42 | 43 | It corresponds to one branch of the following tree. It is saying on node 1 if feature 9 was less than equal to 20000 (0.02 in the tree) then result = 1 (in P4 program meta.isTrue = 1) 44 | 45 | Next time in rule it will match the key 1 9 1 (node id , feature id, isTrue) 46 | 47 | Thus, it will match and will go to node 2 and check for feature 4 with 0 as threshold (it is binary so <= 0 is equivalent to <=0.50) 48 | 49 | In case it was more than 20000 then it will match another rule and will check feature 2: 50 | 51 | `table_add MyIngress.level2 MyIngress.CheckFeature 1 9 0 => 99 2 156` 52 | 53 | If you want to add your own new feature then you may just create a new feature id for your features. 54 | 55 | Think of adding rules for them and then add the check in the end of the checkfeature function. 56 | -------------------------------------------------------------------------------- /scripts/rftop4_v2.py: -------------------------------------------------------------------------------- 1 | from io import StringIO 2 | from numbers import Integral 3 | 4 | import numpy as np 5 | import pandas 6 | import pickle 7 | import sklearn 8 | from sklearn import tree 9 | from sklearn.tree import export_text 10 | 11 | from sklearn.tree import _tree 12 | 13 | from sklearn.tree import DecisionTreeClassifier 14 | 15 | filename = 'final_rf_model.sav' 16 | rf = pickle.load(open(filename, 'rb')) 17 | 18 | i_tree = 0 19 | 20 | global_id = 0 21 | 22 | def export_p4(decision_tree): 23 | tree_ = decision_tree.tree_ 24 | class_names = decision_tree.classes_ 25 | right_child_fmt = "{} {} <= {}\n" 26 | left_child_fmt = "{} {} > {}\n" 27 | truncation_fmt = "{} {}\n" 28 | feature_names_ = ["{}".format(i) for i in tree_.feature] 29 | export_text.report = "" 30 | max_depth=10 31 | spacing=3 32 | decimals=2 33 | show_weights=False 34 | 35 | if isinstance(decision_tree, DecisionTreeClassifier): 36 | value_fmt = "{}{} weights: {}\n" 37 | if not show_weights: 38 | value_fmt = "{}{}{}\n" 39 | else: 40 | value_fmt = "{}{} value: {}\n" 41 | 42 | def _add_leaf(value, class_name, indent, prevfeature, result, depth, previous_id): 43 | global global_id 44 | global i_tree 45 | current_id = global_id 46 | 47 | val = '' 48 | is_classification = isinstance(decision_tree, 49 | DecisionTreeClassifier) 50 | if show_weights or not is_classification: 51 | val = ["{1:.{0}f}, ".format(decimals, v) for v in value] 52 | val = '['+''.join(val)[:-2]+']' 53 | if is_classification: 54 | val += ' class: ' + str(class_name) 55 | export_text.report += value_fmt.format(indent, '', val) 56 | print("table_add MyIngress.level_", i_tree,"_", depth, " ", "MyIngress.SetClass",i_tree," ", previous_id," ",prevfeature," ", result," ", "=>"," ", current_id, " ", int(float(class_name)), sep="") 57 | 58 | def print_tree_recurse(node, depth, prevfeature, result, previous_id): 59 | indent = ("|" + (" " * spacing)) * depth 60 | indent = indent[:-spacing] + "-" * spacing 61 | global global_id 62 | global i_tree 63 | global_id = global_id + 1 64 | current_id = global_id 65 | 66 | value = None 67 | if tree_.n_outputs == 1: 68 | value = tree_.value[node][0] 69 | else: 70 | value = tree_.value[node].T[0] 71 | class_name = np.argmax(value) 72 | 73 | if (tree_.n_classes[0] != 1 and 74 | tree_.n_outputs == 1): 75 | class_name = class_names[class_name] 76 | 77 | if depth <= max_depth+1: 78 | info_fmt = "" 79 | info_fmt_left = info_fmt 80 | info_fmt_right = info_fmt 81 | 82 | if tree_.feature[node] != _tree.TREE_UNDEFINED: 83 | name = feature_names_[node] 84 | threshold = tree_.threshold[node] 85 | threshold = "{1:.{0}f}".format(decimals, threshold) 86 | export_text.report += right_child_fmt.format(indent, 87 | name, 88 | threshold) 89 | export_text.report += info_fmt_left 90 | if int(name) == 9 or int(name) == 11: 91 | #print("**********", name, threshold, float(threshold), 1000000.0*float(threshold)) 92 | print("table_add MyIngress.level_", i_tree,"_", depth, " MyIngress.CheckFeature ", previous_id, " ", prevfeature, " ", result, " ", "=>", " ", current_id, " ", name," ", int(1000000.0*float(threshold)), sep='') 93 | 94 | else: 95 | print("table_add MyIngress.level_", i_tree,"_", depth, " MyIngress.CheckFeature ", previous_id, " ", prevfeature, " ", result, " ", "=>", " ", current_id, " ", name," ", int(float(threshold)), sep='') 96 | 97 | print_tree_recurse(tree_.children_left[node], depth+1, name, 1, current_id) 98 | 99 | export_text.report += left_child_fmt.format(indent, 100 | name, 101 | threshold) 102 | export_text.report += info_fmt_right 103 | # print("level", depth, "checkfeature", prevfeature, result, "=>", name, threshold) 104 | 105 | 106 | print_tree_recurse(tree_.children_right[node], depth+1, name, 0, current_id) 107 | else: # leaf 108 | _add_leaf(value, class_name, indent, prevfeature, result, depth, previous_id) 109 | else: 110 | subtree_depth = _compute_depth(tree_, node) 111 | if subtree_depth == 1: 112 | _add_leaf(value, class_name, indent, prevfeature, result, depth, previous_id) 113 | else: 114 | trunc_report = 'truncated branch of depth %d' % subtree_depth 115 | export_text.report += truncation_fmt.format(indent, 116 | trunc_report) 117 | 118 | print_tree_recurse(0, 1, 0, 1, global_id) 119 | 120 | 121 | for tree_in_forest in rf.estimators_: 122 | #r = export_text(tree_in_forest) 123 | #print(r) 124 | global i_tree 125 | 126 | i_tree = i_tree + 1 127 | export_p4(tree_in_forest) 128 | -------------------------------------------------------------------------------- /switchtree.1tree: -------------------------------------------------------------------------------- 1 | /* -*- P4_16 -*- */ 2 | /******************************************************************************** 3 | * 4 | * Copyright (c) 2019 Kamal Singh 5 | * All rights reserved. 6 | * 7 | *********************************************************************************/ 8 | 9 | 10 | #include 11 | #include 12 | 13 | const bit<16> TYPE_IPV4 = 0x800; 14 | 15 | #define MAX_REGISTER_ENTRIES 8192 16 | #define BLOOM_FILTER_BIT_WIDTH 32 17 | #define PACKET_THRESHOLD 1000 18 | #define FLOW_TIMEOUT 15000000 //15 seconds 19 | #define CLASS_NOT_SET 10000// A big number 20 | 21 | #define STATE_INT 1 22 | #define STATE_FIN 2 23 | #define STATE_REQ 3 24 | #define STATE_CON 4 25 | #define STATE_ACC 5 26 | #define STATE_CLO 6 27 | #define STATE_EST 7 28 | 29 | /************************************************************************* 30 | *********************** H E A D E R S *********************************** 31 | *************************************************************************/ 32 | 33 | typedef bit<9> egressSpec_t; 34 | typedef bit<48> macAddr_t; 35 | typedef bit<32> ip4Addr_t; 36 | 37 | header ethernet_t { 38 | macAddr_t dstAddr; 39 | macAddr_t srcAddr; 40 | bit<16> etherType; 41 | } 42 | 43 | header ipv4_t { 44 | bit<4> version; 45 | bit<4> ihl; 46 | bit<8> diffserv; 47 | bit<16> totalLen; 48 | bit<16> identification; 49 | bit<3> flags; 50 | bit<13> fragOffset; 51 | bit<8> ttl; 52 | bit<8> protocol; 53 | bit<16> hdrChecksum; 54 | ip4Addr_t srcAddr; 55 | ip4Addr_t dstAddr; 56 | } 57 | 58 | header tcp_t{ 59 | bit<16> srcPort; 60 | bit<16> dstPort; 61 | bit<32> seqNo; 62 | bit<32> ackNo; 63 | bit<4> dataOffset; 64 | bit<4> res; 65 | bit<1> cwr; 66 | bit<1> ece; 67 | bit<1> urg; 68 | bit<1> ack; 69 | bit<1> psh; 70 | bit<1> rst; 71 | bit<1> syn; 72 | bit<1> fin; 73 | bit<16> window; 74 | bit<16> checksum; 75 | bit<16> urgentPtr; 76 | } 77 | 78 | header udp_t { 79 | bit<16> srcPort; 80 | bit<16> dstPort; 81 | bit<16> length_; 82 | bit<16> checksum; 83 | } 84 | 85 | 86 | struct metadata { 87 | bit<64> feature1; 88 | bit<64> feature2; 89 | bit<64> feature3; 90 | bit<64> feature4; 91 | bit<64> feature5; 92 | bit<64> feature6; 93 | bit<64> feature7; 94 | bit<64> feature8; 95 | bit<64> feature9; 96 | bit<64> feature10; 97 | bit<64> feature11; 98 | bit<64> feature12; 99 | bit<64> feature13; 100 | 101 | bit<16> prevFeature; 102 | bit<16> isTrue; 103 | 104 | bit<16> class; 105 | bit<16> node_id; 106 | 107 | bit<1> direction; 108 | bit<32> register_index; 109 | bit<32> register_index_2; 110 | bit<32> register_index_inverse; 111 | bit<32> register_index_inverse_2; 112 | 113 | //bloom filter indexes 114 | bit<1> register_cell_one; 115 | bit<1> register_cell_two; 116 | bit<32> register_position_one; 117 | bit<32> register_position_two; 118 | 119 | bit<8> sttl; 120 | bit<8> dttl; 121 | bit<32> srcip; 122 | bit<16> srcport; 123 | bit<16> dstport; 124 | bit<16> hdr_srcport; 125 | bit<16> hdr_dstport; 126 | 127 | bit<32> dpkts; 128 | bit<32> spkts; 129 | bit<32> sbytes; 130 | bit<32> dbytes; 131 | bit<16> ct_srv_dst; 132 | bit<48> tcprtt; 133 | bit<48> syn_time; 134 | bit<48> time_last_pkt; 135 | bit<48> time_first_pkt; 136 | 137 | bit<48> dur; 138 | bit<1> is_first; 139 | bit<1> is_empty; 140 | bit<1> is_hash_collision; 141 | bit<1> first_ack; 142 | 143 | bit<8> state; 144 | bit<8> ct_state_ttl; 145 | bit<1> malware; 146 | bit<1> marked_malware; 147 | 148 | } 149 | 150 | struct headers { 151 | ethernet_t ethernet; 152 | ipv4_t ipv4; 153 | tcp_t tcp; 154 | udp_t udp; 155 | } 156 | 157 | /************************************************************************* 158 | *********************** P A R S E R *********************************** 159 | *************************************************************************/ 160 | 161 | parser MyParser(packet_in packet, 162 | out headers hdr, 163 | inout metadata meta, 164 | inout standard_metadata_t standard_metadata) { 165 | 166 | state start { 167 | transition parse_ethernet; 168 | } 169 | 170 | state parse_ethernet { 171 | packet.extract(hdr.ethernet); 172 | transition select(hdr.ethernet.etherType) { 173 | TYPE_IPV4: parse_ipv4; 174 | default: accept; 175 | } 176 | } 177 | 178 | //TODO parse different types of packets ARP, ICMP etc. 179 | state parse_ipv4 { 180 | packet.extract(hdr.ipv4); 181 | transition select(hdr.ipv4.protocol) { 182 | 6: parse_tcp; 183 | 17: parse_udp; 184 | default: accept; 185 | } 186 | } 187 | state parse_tcp { 188 | packet.extract(hdr.tcp); 189 | transition accept; 190 | } 191 | 192 | state parse_udp { 193 | packet.extract(hdr.udp); 194 | transition accept; 195 | } 196 | 197 | } 198 | 199 | /************************************************************************* 200 | ************ C H E C K S U M V E R I F I C A T I O N ************* 201 | *************************************************************************/ 202 | 203 | control MyVerifyChecksum(inout headers hdr, inout metadata meta) { 204 | apply { } 205 | } 206 | 207 | 208 | /************************************************************************* 209 | ************** I N G R E S S P R O C E S S I N G ******************* 210 | *************************************************************************/ 211 | 212 | control MyIngress(inout headers hdr, 213 | inout metadata meta, 214 | inout standard_metadata_t standard_metadata) { 215 | 216 | 217 | register>(MAX_REGISTER_ENTRIES) bloom_filter; 218 | 219 | //bloomfilter: a query returns either "possibly in set" or "definitely not in set." 220 | //Many more flows are normal than abnormal flows. Thus better performance 221 | //will be by storing abnormal flows 222 | register>(MAX_REGISTER_ENTRIES) reg_blacklisted; 223 | 224 | //Here performance will not be good, but once the filter says definitely not allowed, we are sure. 225 | register>(MAX_REGISTER_ENTRIES) reg_allowed; 226 | register>(MAX_REGISTER_ENTRIES) reg_first_ack; 227 | register>(MAX_REGISTER_ENTRIES) reg_is_empty; 228 | 229 | register>(MAX_REGISTER_ENTRIES) reg_ttl; 230 | register>(MAX_REGISTER_ENTRIES) reg_dttl; 231 | 232 | //Dload will be obtained by reversing the src-dst tuple 233 | register>(MAX_REGISTER_ENTRIES) reg_spkts;//src dst pkt count 234 | 235 | register>(MAX_REGISTER_ENTRIES) reg_dpkts;//src dst pkt count 236 | 237 | //Reg not needed for state_INT 238 | register>(MAX_REGISTER_ENTRIES) reg_sbytes;//src dst byte count 239 | register>(MAX_REGISTER_ENTRIES) reg_dbytes;//src dst byte count 240 | 241 | //sum of TCP connection setup time : sum of synack and ackdat time 242 | 243 | register>(8) reg_ct_srv_dst;//Number of connections that contain the same service and srcip in last 100 connections 244 | //Note that only 8 possibilities: http, ftp, smtp, ssh, dns, ftp-data ,irc and (-) if not much used service 245 | //Register not needed for dsport 246 | //dttl, Dpkts, dmeansz, Dload will be obtained by reversing the src-dst tuple 247 | 248 | //Registers for identifying the flow more apart from hash we may use source port 249 | register>(MAX_REGISTER_ENTRIES) reg_srcip; 250 | register>(MAX_REGISTER_ENTRIES) reg_srcport; 251 | register>(MAX_REGISTER_ENTRIES) reg_dstport; 252 | 253 | register>(MAX_REGISTER_ENTRIES) reg_marked_malware; 254 | 255 | 256 | 257 | register>(MAX_REGISTER_ENTRIES) reg_time_last_pkt; 258 | register>(MAX_REGISTER_ENTRIES) reg_time_first_pkt; 259 | register>(MAX_REGISTER_ENTRIES) reg_syn_time; 260 | register>(MAX_REGISTER_ENTRIES) reg_tcprtt; 261 | 262 | //Store some statistics for the experiment 263 | counter(1, CounterType.packets) counter_hash_collisions; 264 | counter(1, CounterType.packets) counter_pkts; 265 | counter(1, CounterType.packets) counter_malware; 266 | counter(1, CounterType.packets) counter_true_detection; 267 | counter(1, CounterType.packets) counter_false_detection; 268 | counter(1, CounterType.packets) counter_flows; 269 | counter(1, CounterType.packets) counter_malware_flows; 270 | counter(1, CounterType.packets) counter_true_detection_flows; 271 | counter(1, CounterType.packets) counter_false_detection_flows; 272 | counter(1, CounterType.packets) counter_timeout; 273 | 274 | action init_register() { 275 | //intialise the registers to 0 276 | reg_time_last_pkt.write(meta.register_index, 0); 277 | reg_srcip.write(meta.register_index, 0); 278 | reg_srcport.write(meta.register_index, 0); 279 | reg_dstport.write(meta.register_index, 0); 280 | reg_ttl.write(meta.register_index, 0); 281 | reg_dttl.write(meta.register_index, 0); 282 | reg_spkts.write(meta.register_index, 0); 283 | reg_sbytes.write(meta.register_index, 0); 284 | reg_dpkts.write(meta.register_index, 0); 285 | reg_dbytes.write(meta.register_index, 0); 286 | reg_syn_time.write(meta.register_index, 0); 287 | reg_tcprtt.write(meta.register_index, 0); 288 | reg_marked_malware.write(meta.register_index, 0); 289 | } 290 | 291 | action get_register_index_tcp() { 292 | //Get register position 293 | hash(meta.register_index, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.srcAddr, 294 | hdr.ipv4.dstAddr, 295 | hdr.tcp.srcPort, 296 | hdr.tcp.dstPort, 297 | hdr.ipv4.protocol}, 298 | (bit<32>)MAX_REGISTER_ENTRIES); 299 | 300 | hash(meta.register_index_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.srcAddr, 301 | hdr.ipv4.dstAddr, 302 | hdr.tcp.srcPort, 303 | hdr.tcp.dstPort, 304 | hdr.ipv4.protocol}, 305 | (bit<32>)MAX_REGISTER_ENTRIES); 306 | } 307 | 308 | action get_register_index_udp() { 309 | hash(meta.register_index, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.srcAddr, 310 | hdr.ipv4.dstAddr, 311 | hdr.udp.srcPort, 312 | hdr.udp.dstPort, 313 | hdr.ipv4.protocol}, 314 | (bit<32>)MAX_REGISTER_ENTRIES); 315 | 316 | hash(meta.register_index_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.srcAddr, 317 | hdr.ipv4.dstAddr, 318 | hdr.udp.srcPort, 319 | hdr.udp.dstPort, 320 | hdr.ipv4.protocol}, 321 | (bit<32>)MAX_REGISTER_ENTRIES); 322 | } 323 | 324 | action get_register_index_inverse_tcp() { 325 | //Get register position for the same flow in another directon 326 | // just inverse the src and dst 327 | hash(meta.register_index_inverse, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.dstAddr, 328 | hdr.ipv4.srcAddr, 329 | hdr.tcp.dstPort, 330 | hdr.tcp.srcPort, 331 | hdr.ipv4.protocol}, 332 | (bit<32>)MAX_REGISTER_ENTRIES); 333 | 334 | hash(meta.register_index_inverse_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.dstAddr, 335 | hdr.ipv4.srcAddr, 336 | hdr.tcp.dstPort, 337 | hdr.tcp.srcPort, 338 | hdr.ipv4.protocol}, 339 | (bit<32>)MAX_REGISTER_ENTRIES); 340 | } 341 | 342 | action get_register_index_inverse_udp() { 343 | hash(meta.register_index_inverse, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.dstAddr, 344 | hdr.ipv4.srcAddr, 345 | hdr.udp.dstPort, 346 | hdr.udp.srcPort, 347 | hdr.ipv4.protocol}, 348 | (bit<32>)MAX_REGISTER_ENTRIES); 349 | 350 | hash(meta.register_index_inverse_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.dstAddr, 351 | hdr.ipv4.srcAddr, 352 | hdr.udp.dstPort, 353 | hdr.ipv4.protocol}, 354 | (bit<32>)MAX_REGISTER_ENTRIES); 355 | } 356 | 357 | action set_allowed(){ 358 | //set bloom filter fields 359 | bloom_filter.write(meta.register_position_one, 1); 360 | bloom_filter.write(meta.register_position_two, 1); 361 | } 362 | 363 | action check_if_allowed(){ 364 | //Read bloom filter cells to check if there are 1's 365 | bloom_filter.read(meta.register_cell_one, meta.register_position_one); 366 | bloom_filter.read(meta.register_cell_two, meta.register_position_two); 367 | } 368 | 369 | action drop() { 370 | mark_to_drop(standard_metadata); 371 | } 372 | 373 | //we plan to use the following features for the moment 374 | //sttl ct_state_ttl dttl Sload Dpkts dmeansz state_INT sbytes sload smeansz tcprtt dsport dur ct_srv_dst 375 | 376 | //1.* sttl there by default 377 | //2. ct_state_ttl **to be called after sttl and dttl calc 378 | 379 | action calc_state() { 380 | //When Sload or Dload is 0 the state can be INT 381 | //Thus need to calculate sload, dload before 382 | // XX TODO Argus log shows only last state! 383 | //XX TODO The following logic is only approx. correct! 384 | if ((meta.is_first == 1)||(meta.dttl == 0)) { 385 | if (hdr.ipv4.protocol == 6) //TCP 386 | meta.state = STATE_REQ; 387 | else meta.state = STATE_INT; 388 | } 389 | else { 390 | if (hdr.ipv4.protocol == 6) //TCP 391 | meta.state = STATE_EST; 392 | else meta.state = STATE_CON; 393 | } 394 | //TODO for STATE_FIN, which may not be useful as it would be last packet of transaction 395 | if (hdr.ipv4.protocol == 6 && hdr.tcp.fin == (bit<1>)1) { 396 | meta.state = STATE_FIN; 397 | } 398 | } 399 | 400 | action calc_ct_state_ttl(){ 401 | 402 | meta.ct_state_ttl = 0; 403 | if ((meta.sttl == 62 || meta.sttl == 63 || meta.sttl == 254 || meta.sttl == 255) 404 | && (meta.dttl == 252 || meta.dttl == 253) && meta.state == STATE_FIN) { 405 | meta.ct_state_ttl = 1; 406 | } 407 | else if ((meta.sttl == 0 || meta.sttl == 62 || meta.sttl == 254) 408 | && (meta.dttl == 0) && meta.state == STATE_INT) { 409 | meta.ct_state_ttl = 2; 410 | } 411 | else if((meta.sttl == 62 || meta.sttl == 254) 412 | && (meta.dttl == 60 || meta.dttl == 252 || meta.dttl == 253) 413 | && meta.state == STATE_CON){ 414 | meta.ct_state_ttl = 3; 415 | } 416 | else if((meta.sttl == 254) && (meta.dttl == 252) && meta.state == STATE_ACC){ 417 | meta.ct_state_ttl = 4; 418 | } 419 | else if((meta.sttl == 254) && (meta.dttl == 252) && meta.state == STATE_CLO){ 420 | meta.ct_state_ttl = 5; 421 | } 422 | else if((meta.sttl == 254) && (meta.dttl == 0) && meta.state == STATE_REQ){ 423 | meta.ct_state_ttl = 7; 424 | } 425 | else { 426 | meta.ct_state_ttl = 0; 427 | } 428 | } 429 | 430 | action read_ct_srv_dst() { 431 | //TODO XX The following is just for test 432 | //No. of connections that contain the same service (14) (ftp, http, ..) and destination address (3) (ipaddress) in 100 connections according to the last time (26). 433 | 434 | meta.ct_srv_dst = 10; 435 | } 436 | 437 | 438 | action init_features() { 439 | //they will be updated when needed 440 | //or easy but a bit slow: to read them now 441 | //feature order can be changed flexibly using registers configurable from control plane, etc. 442 | 443 | // In the traces bitrate = int(smeanz)*(totalpkts - 1)*8/dur 444 | //We will compare sbytes*(totalpkts - 1)*8 > th*dur*spkts; 445 | 446 | meta.feature1 = (bit<64>)meta.sttl;//sttl 447 | meta.feature2 = (bit<64>)meta.ct_state_ttl;//ct_state_ttl 448 | meta.feature3 = (bit<64>)meta.dttl;//dttl 449 | meta.feature4 = (bit<64>)(meta.sbytes*(meta.spkts - 1)*8) ;//needed for Sload 450 | meta.feature5 = (bit<64>)meta.dpkts;//dpkts 451 | meta.feature6 = (bit<64>)meta.dbytes;//Needed for dmeansz 452 | meta.feature7 = (bit<64>)meta.sbytes;//sbytes 453 | meta.feature8 = (bit<64>)(meta.dbytes*(meta.dpkts - 1)*8);//Needed for dload 454 | meta.feature9 = (bit<64>)meta.sbytes;//needed for smeansz 455 | meta.feature10 = (bit<64>)meta.tcprtt;//tcprtt 456 | meta.feature11 = (bit<64>)meta.dstport;//dstport 457 | meta.feature12 = (bit<64>)meta.dur;//dur 458 | 459 | meta.class = CLASS_NOT_SET; 460 | } 461 | 462 | action CheckFeature(bit<16> node_id, bit<16> f_inout, bit<64> threshold) { 463 | //XX For dur and tcprtt are in microseconds! Thus multiplied by 1000000 if in seconds! 464 | //XX For rate comparisons 'th' is multiplied by time delta as division is not allowed 465 | 466 | bit<64> feature = 0; 467 | bit<64> th = threshold; 468 | bit<16> f = f_inout + 1; 469 | 470 | if (f == 1) { 471 | 472 | feature = meta.feature1; 473 | } 474 | else if (f == 2) { 475 | feature = meta.feature2; 476 | } 477 | else if (f == 3) { 478 | feature = meta.feature3; 479 | } 480 | else if (f == 4) { 481 | feature = meta.feature4*1000000; 482 | th = th*(bit<64>)meta.dur*(bit<64>)meta.sbytes; 483 | } 484 | else if (f == 5) { 485 | feature = meta.feature5; 486 | } 487 | else if (f == 6) { 488 | feature = meta.feature6; 489 | th = th*(bit<64>)meta.dpkts; 490 | } 491 | else if (f == 7) { 492 | feature = meta.feature7; 493 | } 494 | else if (f == 8) { 495 | feature = meta.feature8*1000000; 496 | th = th*(bit<64>)meta.dur*(bit<64>)meta.sbytes; 497 | } 498 | else if (f == 9) { 499 | feature = meta.feature9; 500 | th = th*(bit<64>)meta.spkts; 501 | } 502 | else if (f == 10) { 503 | feature = meta.feature10; 504 | } 505 | else if (f == 11) { 506 | feature = meta.feature11; 507 | } 508 | else if (f == 12) { 509 | feature = meta.feature12; 510 | } 511 | 512 | if (feature <= th) meta.isTrue = 1; 513 | else meta.isTrue = 0; 514 | 515 | meta.prevFeature = f - 1; 516 | 517 | meta.node_id = node_id; 518 | } 519 | 520 | action SetClass(bit<16> node_id, bit<16> class) { 521 | meta.class = class; 522 | meta.node_id = node_id; //just for debugging otherwise not needed 523 | } 524 | 525 | action SetDirection() { 526 | //need just for this setting as tcpreplay is sending all the packets to same interface 527 | meta.direction = 1; 528 | } 529 | 530 | action SetMalware() { 531 | //need just for this setting as tcpreplay is sending all the packets to same interface 532 | meta.malware = 1; 533 | } 534 | 535 | 536 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 537 | standard_metadata.egress_spec = port; 538 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 539 | hdr.ethernet.dstAddr = dstAddr; 540 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 541 | } 542 | 543 | 544 | 545 | table direction{ 546 | key = { 547 | hdr.ipv4.dstAddr: lpm; 548 | } 549 | actions = { 550 | NoAction; 551 | SetDirection; 552 | } 553 | size = 10; 554 | default_action = NoAction(); 555 | } 556 | 557 | table malware{ //For debugging 558 | key = { 559 | hdr.ipv4.srcAddr: lpm; 560 | } 561 | actions = { 562 | NoAction; 563 | SetMalware; 564 | } 565 | size = 10; 566 | default_action = NoAction(); 567 | } 568 | 569 | table malware_inverse { //For debugging 570 | key = { 571 | hdr.ipv4.dstAddr: lpm; 572 | } 573 | actions = { 574 | NoAction; 575 | SetMalware; 576 | } 577 | size = 10; 578 | default_action = NoAction(); 579 | } 580 | 581 | 582 | table level1{ 583 | key = { 584 | meta.node_id: exact; 585 | meta.prevFeature: exact; 586 | meta.isTrue: exact; 587 | } 588 | actions = { 589 | NoAction; 590 | CheckFeature; 591 | SetClass; 592 | } 593 | size = 1024; 594 | } 595 | 596 | table level2{ 597 | key = { 598 | meta.node_id: exact; 599 | meta.prevFeature: exact; 600 | meta.isTrue: exact; 601 | } 602 | actions = { 603 | NoAction; 604 | CheckFeature; 605 | SetClass; 606 | } 607 | size = 1024; 608 | } 609 | 610 | table level3{ 611 | key = { 612 | meta.node_id: exact; 613 | meta.prevFeature: exact; 614 | meta.isTrue: exact; 615 | } 616 | actions = { 617 | NoAction; 618 | CheckFeature; 619 | SetClass; 620 | } 621 | size = 1024; 622 | } 623 | table level4{ 624 | key = { 625 | meta.node_id: exact; 626 | meta.prevFeature: exact; 627 | meta.isTrue: exact; 628 | } 629 | actions = { 630 | NoAction; 631 | CheckFeature; 632 | SetClass; 633 | } 634 | size = 1024; 635 | } 636 | 637 | table level5{ 638 | key = { 639 | meta.node_id: exact; 640 | meta.prevFeature: exact; 641 | meta.isTrue: exact; 642 | } 643 | actions = { 644 | NoAction; 645 | CheckFeature; 646 | SetClass; 647 | } 648 | size = 1024; 649 | } 650 | 651 | table level6{ 652 | key = { 653 | meta.node_id: exact; 654 | meta.prevFeature: exact; 655 | meta.isTrue: exact; 656 | } 657 | actions = { 658 | NoAction; 659 | CheckFeature; 660 | SetClass; 661 | } 662 | size = 1024; 663 | } 664 | 665 | table level7{ 666 | key = { 667 | meta.node_id: exact; 668 | meta.prevFeature: exact; 669 | meta.isTrue: exact; 670 | } 671 | actions = { 672 | NoAction; 673 | CheckFeature; 674 | SetClass; 675 | } 676 | size = 1024; 677 | } 678 | 679 | table level8{ 680 | key = { 681 | meta.node_id: exact; 682 | meta.prevFeature: exact; 683 | meta.isTrue: exact; 684 | } 685 | actions = { 686 | NoAction; 687 | CheckFeature; 688 | SetClass; 689 | } 690 | size = 1024; 691 | } 692 | 693 | table level9{ 694 | key = { 695 | meta.node_id: exact; 696 | meta.prevFeature: exact; 697 | meta.isTrue: exact; 698 | } 699 | actions = { 700 | NoAction; 701 | CheckFeature; 702 | SetClass; 703 | } 704 | size = 1024; 705 | } 706 | 707 | table level10{ 708 | key = { 709 | meta.node_id: exact; 710 | meta.prevFeature: exact; 711 | meta.isTrue: exact; 712 | } 713 | actions = { 714 | NoAction; 715 | CheckFeature; 716 | SetClass; 717 | } 718 | size = 1024; 719 | } 720 | 721 | table level11{ 722 | key = { 723 | meta.node_id: exact; 724 | meta.prevFeature: exact; 725 | meta.isTrue: exact; 726 | } 727 | actions = { 728 | NoAction; 729 | CheckFeature; 730 | SetClass; 731 | } 732 | size = 1024; 733 | } 734 | 735 | 736 | 737 | /* This will send the packet to a specifique port of the switch for output*/ 738 | table ipv4_exact { 739 | key = { 740 | meta.class: exact; 741 | } 742 | actions = { 743 | ipv4_forward; 744 | drop; 745 | NoAction; 746 | } 747 | size = 1024; 748 | default_action = drop(); 749 | } 750 | 751 | table debug{ 752 | key = { 753 | meta.feature1: exact; 754 | meta.feature2: exact; 755 | meta.feature3: exact; 756 | meta.feature4: exact; 757 | meta.feature5: exact; 758 | meta.feature6: exact; 759 | meta.feature7: exact; 760 | meta.feature8: exact; 761 | meta.feature9: exact; 762 | meta.feature10: exact; 763 | meta.feature11: exact; 764 | meta.feature12: exact; 765 | meta.state: exact; 766 | meta.spkts: exact; 767 | meta.is_first: exact; 768 | hdr.ipv4.dstAddr: exact; 769 | meta.hdr_srcport: exact; 770 | meta.hdr_dstport: exact; 771 | standard_metadata.ingress_global_timestamp: exact; 772 | meta.syn_time: exact; 773 | meta.register_index: exact; 774 | meta.register_index_inverse: exact; 775 | meta.direction: exact; 776 | meta.is_hash_collision: exact; 777 | meta.malware: exact; 778 | meta.marked_malware: exact; 779 | meta.class: exact; 780 | meta.sbytes: exact; 781 | } 782 | actions = { 783 | NoAction; 784 | } 785 | size = 1024; 786 | } 787 | 788 | 789 | //Invoke the tables using the apply method 790 | 791 | apply { 792 | 793 | /*check the direction of packets going. 794 | For UNSW data, the emulation configuration is as follows 795 | Outside: 796 | 59.166.0.0 normal 797 | 175.45.176.0 malware 798 | Inside: 799 | 149.171.126.0 800 | Thus, mostly track 59.166.0.0/175.45.176.0 ---> 149.171.126.0 packets 801 | */ 802 | 803 | //count all the packets 804 | direction.apply(); 805 | counter_pkts.count(0); 806 | 807 | if ( hdr.ipv4.isValid()) { 808 | //Calculate all features 809 | //TODO optimize : feature needs to be calculated only if needed 810 | 811 | if (hdr.ipv4.protocol == 6 || hdr.ipv4.protocol == 17) {//We treat only TCP or UDP packets 812 | 813 | if (meta.direction == 1) { 814 | 815 | if (hdr.ipv4.protocol == 6) { 816 | get_register_index_tcp(); 817 | meta.hdr_srcport = hdr.tcp.srcPort; 818 | meta.hdr_dstport = hdr.tcp.dstPort; 819 | } 820 | else { 821 | get_register_index_udp(); 822 | meta.hdr_srcport = hdr.udp.srcPort; 823 | meta.hdr_dstport = hdr.udp.dstPort; 824 | 825 | } 826 | 827 | //read_reg_to_check_collision srcip, srcport, dstport 828 | reg_srcip.read(meta.srcip, meta.register_index); 829 | reg_srcport.read(meta.srcport, meta.register_index); 830 | reg_dstport.read(meta.dstport, meta.register_index); 831 | reg_time_last_pkt.read(meta.time_last_pkt, (bit<32>)meta.register_index); 832 | 833 | if (meta.srcip == 0) {//It was an empty register 834 | meta.is_first = 1; 835 | } 836 | else if ((standard_metadata.ingress_global_timestamp - meta.time_last_pkt) > FLOW_TIMEOUT) { 837 | /*We havent heard from this flow it has been FLOW_TIMEOUT 838 | We will initialse the register space 839 | TODO check if init_register() is initialising all and only those needed. ; 840 | */ 841 | init_register(); 842 | counter_timeout.count(0); 843 | meta.is_first = 1; 844 | } 845 | else if (meta.srcip != hdr.ipv4.srcAddr || meta.srcport != meta.hdr_srcport 846 | || meta.dstport != meta.hdr_dstport) { 847 | //Hash collision! 848 | //TODO handle hash collisions in a better way! 849 | meta.is_hash_collision = 1; 850 | counter_hash_collisions.count(0); 851 | } 852 | 853 | if (meta.is_hash_collision == 0) { 854 | 855 | if (meta.is_first == 1) { 856 | meta.time_first_pkt = standard_metadata.ingress_global_timestamp; 857 | reg_time_first_pkt.write((bit<32>)meta.register_index, meta.time_first_pkt); 858 | reg_srcip.write((bit<32>)meta.register_index, hdr.ipv4.srcAddr); 859 | reg_srcport.write((bit<32>)meta.register_index, meta.hdr_srcport); 860 | reg_dstport.write((bit<32>)meta.register_index, meta.hdr_dstport); 861 | counter_flows.count(0); 862 | } 863 | 864 | reg_spkts.read(meta.spkts, (bit<32>)meta.register_index); 865 | meta.spkts = meta.spkts + 1; 866 | reg_spkts.write((bit<32>)meta.register_index, meta.spkts); 867 | 868 | meta.sttl = hdr.ipv4.ttl; 869 | reg_ttl.write((bit<32>)meta.register_index, meta.sttl); 870 | 871 | reg_dttl.read(meta.dttl, (bit<32>)meta.register_index); 872 | 873 | 874 | //read_sbytes also used for sload 875 | reg_sbytes.read(meta.sbytes, (bit<32>)meta.register_index); 876 | meta.sbytes = meta.sbytes + standard_metadata.packet_length - 14; 877 | reg_sbytes.write((bit<32>)meta.register_index, meta.sbytes); 878 | 879 | 880 | // tcprtt 881 | //SYN TIME 882 | if ((hdr.tcp.ack != (bit<1>)1)&&(hdr.tcp.syn == (bit<1>)1)) {//this is a SYN 883 | reg_syn_time.write((bit<32>)meta.register_index, 884 | standard_metadata.ingress_global_timestamp); 885 | } 886 | //ACK + SYN time 887 | else if ((hdr.tcp.ack == (bit<1>)1)&&(hdr.tcp.syn != (bit<1>)1)) {//this is an ACK 888 | 889 | reg_first_ack.read(meta.first_ack, (bit<32>)meta.register_index); 890 | if (meta.first_ack == 0) { 891 | //sum of synack(SYN to SYN_ACK time) and ackdat(SYN_ACK to ACK time) 892 | reg_syn_time.read(meta.syn_time, (bit<32>)meta.register_index); 893 | if (meta.syn_time > 0) {//There was a syn before 894 | meta.tcprtt = standard_metadata.ingress_global_timestamp - meta.syn_time; 895 | reg_tcprtt.write((bit<32>)meta.register_index, meta.tcprtt); 896 | //no longer a first ack 897 | reg_first_ack.write((bit<32>)meta.register_index, 1); 898 | } 899 | } 900 | } 901 | 902 | 903 | //read all reverse flow features 904 | reg_dbytes.read(meta.dbytes, (bit<32>)meta.register_index); 905 | reg_dpkts.read(meta.dpkts, (bit<32>)meta.register_index); 906 | 907 | }//hash collision check 908 | 909 | }//end of direction = 1 910 | 911 | else {//direction = 0 912 | 913 | //TODO some flows can be marked malware even after analysing return flow! 914 | 915 | if (hdr.ipv4.protocol == 6) { 916 | get_register_index_inverse_tcp(); 917 | meta.hdr_srcport = hdr.tcp.dstPort;//its inverse 918 | meta.hdr_dstport = hdr.tcp.srcPort; 919 | } 920 | else { 921 | //TODO what if it is neither TCP nor UDP? 922 | get_register_index_inverse_udp(); 923 | meta.hdr_srcport = hdr.udp.dstPort; 924 | meta.hdr_dstport = hdr.udp.srcPort; 925 | 926 | } 927 | 928 | meta.register_index = meta.register_index_inverse; 929 | 930 | //read_reg_to_check_collision srcip, srcport, dstport 931 | reg_srcip.read(meta.srcip, meta.register_index); 932 | reg_srcport.read(meta.srcport, meta.register_index); 933 | reg_dstport.read(meta.dstport, meta.register_index); 934 | reg_time_last_pkt.read(meta.time_last_pkt, (bit<32>)meta.register_index); 935 | 936 | if (meta.srcip == 0) {//It was an empty register 937 | meta.is_first = 1; 938 | } 939 | else if ((standard_metadata.ingress_global_timestamp - meta.time_last_pkt) > FLOW_TIMEOUT) { 940 | /*We havent heard from this flow it has been FLOW_TIMEOUT 941 | We will initialse the register space 942 | TODO check if init_register() is initialising all and only those needed. ; 943 | */ 944 | init_register(); 945 | counter_timeout.count(0); 946 | meta.is_first = 1; 947 | } 948 | else if (meta.srcip != hdr.ipv4.dstAddr || meta.srcport != meta.hdr_srcport 949 | || meta.dstport != meta.hdr_dstport) { 950 | //Hash collision! 951 | //TODO handle hash collisions in a better way! 952 | meta.is_hash_collision = 1; 953 | counter_hash_collisions.count(0); 954 | } 955 | 956 | if (meta.is_hash_collision == 0) { 957 | 958 | if (meta.is_first == 1) {//shouldn't happen! 959 | meta.time_first_pkt = standard_metadata.ingress_global_timestamp; 960 | reg_time_first_pkt.write((bit<32>)meta.register_index, meta.time_first_pkt); 961 | reg_srcip.write((bit<32>)meta.register_index, hdr.ipv4.dstAddr); 962 | reg_srcport.write((bit<32>)meta.register_index, meta.hdr_srcport); 963 | reg_dstport.write((bit<32>)meta.register_index, meta.hdr_dstport); 964 | 965 | } 966 | 967 | //dpkts and dload 968 | reg_dpkts.read(meta.dpkts, (bit<32>)meta.register_index); 969 | meta.dpkts = meta.dpkts + 1; 970 | reg_dpkts.write((bit<32>)meta.register_index, meta.dpkts); 971 | 972 | //dbytes 973 | reg_dbytes.read(meta.dbytes, (bit<32>)meta.register_index); 974 | meta.dbytes = meta.dbytes + standard_metadata.packet_length - 14; 975 | reg_dbytes.write((bit<32>)meta.register_index, meta.dbytes); 976 | 977 | reg_time_last_pkt.write((bit<32>)meta.register_index, 978 | standard_metadata.ingress_global_timestamp ); 979 | 980 | //Read other features from the sources to destination direction 981 | meta.dttl = hdr.ipv4.ttl; 982 | reg_dttl.write((bit<32>)meta.register_index, meta.dttl); 983 | reg_ttl.read(meta.sttl, (bit<32>)meta.register_index); 984 | reg_sbytes.read(meta.sbytes, (bit<32>)meta.register_index); 985 | reg_spkts.read(meta.spkts, (bit<32>)meta.register_index); 986 | 987 | }//hash collision check 988 | 989 | } // end of direction = 0 990 | 991 | //Read common features 992 | 993 | if (meta.is_hash_collision == 0) { 994 | //TODO on hash collision we are letting the flow pass 995 | //We can also do a false detection! 996 | 997 | reg_tcprtt.read(meta.tcprtt, (bit<32>)meta.register_index); 998 | reg_time_first_pkt.read(meta.time_first_pkt, (bit<32>)meta.register_index); 999 | meta.dur = standard_metadata.ingress_global_timestamp - meta.time_first_pkt; 1000 | 1001 | reg_time_last_pkt.write((bit<32>)meta.register_index, 1002 | standard_metadata.ingress_global_timestamp ); 1003 | 1004 | 1005 | calc_state(); 1006 | calc_ct_state_ttl(); 1007 | read_ct_srv_dst(); 1008 | 1009 | init_features(); 1010 | 1011 | 1012 | //start with parent node of decision tree 1013 | meta.prevFeature = 0; 1014 | meta.isTrue = 1; 1015 | 1016 | reg_marked_malware.read(meta.marked_malware, (bit<32>)meta.register_index); 1017 | 1018 | 1019 | if (meta.direction == 1) { 1020 | malware.apply();//For statistics 1021 | } 1022 | else { 1023 | malware_inverse.apply();//For statistics 1024 | } 1025 | 1026 | if (meta.marked_malware == 1) { 1027 | meta.class = 1;//No need to check again! 1028 | } 1029 | else { 1030 | level1.apply(); 1031 | 1032 | if (meta.class == CLASS_NOT_SET) { 1033 | level2.apply(); 1034 | if (meta.class == CLASS_NOT_SET) { 1035 | level3.apply(); 1036 | if (meta.class == CLASS_NOT_SET) { 1037 | level4.apply(); 1038 | if (meta.class == CLASS_NOT_SET) { 1039 | level5.apply(); 1040 | if (meta.class == CLASS_NOT_SET) { 1041 | level6.apply(); 1042 | if (meta.class == CLASS_NOT_SET) { 1043 | level7.apply(); 1044 | if (meta.class == CLASS_NOT_SET) { 1045 | level8.apply(); 1046 | if (meta.class == CLASS_NOT_SET) { 1047 | level9.apply(); 1048 | if (meta.class == CLASS_NOT_SET) { 1049 | level10.apply(); 1050 | if (meta.class == CLASS_NOT_SET) 1051 | level11.apply(); 1052 | }}}}}}}}} 1053 | } 1054 | 1055 | if (meta.malware == 1) {// meta.malware is calculated with priori knowledge for statistics 1056 | 1057 | counter_malware.count(0); 1058 | 1059 | if (meta.is_first == 1) { 1060 | counter_malware_flows.count(0); 1061 | } 1062 | 1063 | if(meta.class == 1) { 1064 | counter_true_detection.count(0); 1065 | 1066 | if (meta.marked_malware == 0) { 1067 | //We detect the flow as malware first time! 1068 | counter_true_detection_flows.count(0); 1069 | } 1070 | reg_marked_malware.write((bit<32>)meta.register_index,1); 1071 | } 1072 | } 1073 | else { 1074 | if(meta.class == 1) { 1075 | counter_false_detection.count(0); 1076 | 1077 | if (meta.marked_malware == 0) { 1078 | //We detect the flow as malware first time! even if false 1079 | counter_false_detection_flows.count(0); 1080 | } 1081 | reg_marked_malware.write((bit<32>)meta.register_index,1); 1082 | } 1083 | } 1084 | 1085 | }//hash collision check 1086 | 1087 | debug.apply(); 1088 | 1089 | 1090 | 1091 | }//End of if (hdr.ipv4.protocol == 6 || hdr.ipv4.protocol == 17) 1092 | 1093 | ipv4_exact.apply(); 1094 | 1095 | }//End of if hdr.ipv4.isValid() 1096 | 1097 | }//End of apply 1098 | } 1099 | 1100 | /************************************************************************* 1101 | **************** E G R E S S P R O C E S S I N G ******************* 1102 | *************************************************************************/ 1103 | 1104 | control MyEgress(inout headers hdr, 1105 | inout metadata meta, 1106 | inout standard_metadata_t standard_metadata) { 1107 | apply { } 1108 | } 1109 | 1110 | /************************************************************************* 1111 | ************* C H E C K S U M C O M P U T A T I O N ************** 1112 | *************************************************************************/ 1113 | 1114 | control MyComputeChecksum(inout headers hdr, inout metadata meta) { 1115 | apply { 1116 | update_checksum( 1117 | hdr.ipv4.isValid(), 1118 | { hdr.ipv4.version, 1119 | hdr.ipv4.ihl, 1120 | hdr.ipv4.diffserv, 1121 | hdr.ipv4.totalLen, 1122 | hdr.ipv4.identification, 1123 | hdr.ipv4.flags, 1124 | hdr.ipv4.fragOffset, 1125 | hdr.ipv4.ttl, 1126 | hdr.ipv4.protocol, 1127 | hdr.ipv4.srcAddr, 1128 | hdr.ipv4.dstAddr }, 1129 | hdr.ipv4.hdrChecksum, 1130 | HashAlgorithm.csum16); 1131 | } 1132 | } 1133 | 1134 | /************************************************************************* 1135 | 1136 | *********************** D E P A R S E R ******************************* 1137 | *************************************************************************/ 1138 | 1139 | control MyDeparser(packet_out packet, in headers hdr) { 1140 | apply { 1141 | packet.emit(hdr.ethernet); 1142 | packet.emit(hdr.ipv4); 1143 | packet.emit(hdr.tcp); 1144 | } 1145 | } 1146 | 1147 | /************************************************************************* 1148 | *********************** S W I T C H ******************************* 1149 | *************************************************************************/ 1150 | 1151 | V1Switch( 1152 | MyParser(), 1153 | MyVerifyChecksum(), 1154 | MyIngress(), 1155 | MyEgress(), 1156 | MyComputeChecksum(), 1157 | MyDeparser() 1158 | ) main; 1159 | -------------------------------------------------------------------------------- /switchtree.3trees: -------------------------------------------------------------------------------- 1 | /* -*- P4_16 -*- */ 2 | /******************************************************************************** 3 | * 4 | * Copyright (c) 2019 Kamal Singh 5 | * All rights reserved. 6 | * 7 | *********************************************************************************/ 8 | 9 | #include 10 | #include 11 | 12 | const bit<16> TYPE_IPV4 = 0x800; 13 | 14 | #define MAX_REGISTER_ENTRIES 8192 15 | #define BLOOM_FILTER_BIT_WIDTH 32 16 | #define PACKET_THRESHOLD 1000 17 | #define FLOW_TIMEOUT 15000000 //15 seconds 18 | #define CLASS_NOT_SET 10000// A big number 19 | 20 | #define STATE_INT 1 21 | #define STATE_FIN 2 22 | #define STATE_REQ 3 23 | #define STATE_CON 4 24 | #define STATE_ACC 5 25 | #define STATE_CLO 6 26 | #define STATE_EST 7 27 | 28 | /************************************************************************* 29 | *********************** H E A D E R S *********************************** 30 | *************************************************************************/ 31 | 32 | typedef bit<9> egressSpec_t; 33 | typedef bit<48> macAddr_t; 34 | typedef bit<32> ip4Addr_t; 35 | 36 | header ethernet_t { 37 | macAddr_t dstAddr; 38 | macAddr_t srcAddr; 39 | bit<16> etherType; 40 | } 41 | 42 | header ipv4_t { 43 | bit<4> version; 44 | bit<4> ihl; 45 | bit<8> diffserv; 46 | bit<16> totalLen; 47 | bit<16> identification; 48 | bit<3> flags; 49 | bit<13> fragOffset; 50 | bit<8> ttl; 51 | bit<8> protocol; 52 | bit<16> hdrChecksum; 53 | ip4Addr_t srcAddr; 54 | ip4Addr_t dstAddr; 55 | } 56 | 57 | header tcp_t{ 58 | bit<16> srcPort; 59 | bit<16> dstPort; 60 | bit<32> seqNo; 61 | bit<32> ackNo; 62 | bit<4> dataOffset; 63 | bit<4> res; 64 | bit<1> cwr; 65 | bit<1> ece; 66 | bit<1> urg; 67 | bit<1> ack; 68 | bit<1> psh; 69 | bit<1> rst; 70 | bit<1> syn; 71 | bit<1> fin; 72 | bit<16> window; 73 | bit<16> checksum; 74 | bit<16> urgentPtr; 75 | } 76 | 77 | header udp_t { 78 | bit<16> srcPort; 79 | bit<16> dstPort; 80 | bit<16> length_; 81 | bit<16> checksum; 82 | } 83 | 84 | 85 | struct metadata { 86 | bit<64> feature1; 87 | bit<64> feature2; 88 | bit<64> feature3; 89 | bit<64> feature4; 90 | bit<64> feature5; 91 | bit<64> feature6; 92 | bit<64> feature7; 93 | bit<64> feature8; 94 | bit<64> feature9; 95 | bit<64> feature10; 96 | bit<64> feature11; 97 | bit<64> feature12; 98 | bit<64> feature13; 99 | 100 | bit<16> prevFeature; 101 | bit<16> isTrue; 102 | 103 | bit<16> class; 104 | bit<16> class2; 105 | bit<16> class3; 106 | 107 | bit<16> node_id; 108 | 109 | bit<1> direction; 110 | bit<32> register_index; 111 | bit<32> register_index_2; 112 | bit<32> register_index_inverse; 113 | bit<32> register_index_inverse_2; 114 | 115 | //bloom filter indexes 116 | bit<1> register_cell_one; 117 | bit<1> register_cell_two; 118 | bit<32> register_position_one; 119 | bit<32> register_position_two; 120 | 121 | bit<8> sttl; 122 | bit<8> dttl; 123 | bit<32> srcip; 124 | bit<16> srcport; 125 | bit<16> dstport; 126 | bit<16> hdr_srcport; 127 | bit<16> hdr_dstport; 128 | 129 | bit<32> dpkts; 130 | bit<32> spkts; 131 | bit<32> sbytes; 132 | bit<32> dbytes; 133 | bit<16> ct_srv_dst; 134 | bit<48> tcprtt; 135 | bit<48> syn_time; 136 | bit<48> time_last_pkt; 137 | bit<48> time_first_pkt; 138 | 139 | bit<48> dur; 140 | bit<1> is_first; 141 | bit<1> is_empty; 142 | bit<1> is_hash_collision; 143 | bit<1> first_ack; 144 | 145 | bit<8> state; 146 | bit<8> ct_state_ttl; 147 | bit<1> malware; 148 | bit<1> marked_malware; 149 | 150 | } 151 | 152 | struct headers { 153 | ethernet_t ethernet; 154 | ipv4_t ipv4; 155 | tcp_t tcp; 156 | udp_t udp; 157 | } 158 | 159 | /************************************************************************* 160 | *********************** P A R S E R *********************************** 161 | *************************************************************************/ 162 | 163 | parser MyParser(packet_in packet, 164 | out headers hdr, 165 | inout metadata meta, 166 | inout standard_metadata_t standard_metadata) { 167 | 168 | state start { 169 | transition parse_ethernet; 170 | } 171 | 172 | state parse_ethernet { 173 | packet.extract(hdr.ethernet); 174 | transition select(hdr.ethernet.etherType) { 175 | TYPE_IPV4: parse_ipv4; 176 | default: accept; 177 | } 178 | } 179 | 180 | //TODO parse different types of packets ARP, ICMP etc. 181 | state parse_ipv4 { 182 | packet.extract(hdr.ipv4); 183 | transition select(hdr.ipv4.protocol) { 184 | 6: parse_tcp; 185 | 17: parse_udp; 186 | default: accept; 187 | } 188 | } 189 | state parse_tcp { 190 | packet.extract(hdr.tcp); 191 | transition accept; 192 | } 193 | 194 | state parse_udp { 195 | packet.extract(hdr.udp); 196 | transition accept; 197 | } 198 | 199 | } 200 | 201 | /************************************************************************* 202 | ************ C H E C K S U M V E R I F I C A T I O N ************* 203 | *************************************************************************/ 204 | 205 | control MyVerifyChecksum(inout headers hdr, inout metadata meta) { 206 | apply { } 207 | } 208 | 209 | 210 | /************************************************************************* 211 | ************** I N G R E S S P R O C E S S I N G ******************* 212 | *************************************************************************/ 213 | 214 | control MyIngress(inout headers hdr, 215 | inout metadata meta, 216 | inout standard_metadata_t standard_metadata) { 217 | 218 | 219 | register>(MAX_REGISTER_ENTRIES) bloom_filter; 220 | 221 | //bloomfilter: a query returns either "possibly in set" or "definitely not in set." 222 | //Many more flows are normal than abnormal flows. Thus better performance 223 | //will be by storing abnormal flows 224 | register>(MAX_REGISTER_ENTRIES) reg_blacklisted; 225 | 226 | //Here performance will not be good, but once the filter says definitely not allowed, we are sure. 227 | register>(MAX_REGISTER_ENTRIES) reg_allowed; 228 | register>(MAX_REGISTER_ENTRIES) reg_first_ack; 229 | register>(MAX_REGISTER_ENTRIES) reg_is_empty; 230 | 231 | register>(MAX_REGISTER_ENTRIES) reg_ttl; 232 | register>(MAX_REGISTER_ENTRIES) reg_dttl; 233 | 234 | //Dload will be obtained by reversing the src-dst tuple 235 | register>(MAX_REGISTER_ENTRIES) reg_spkts;//src dst pkt count 236 | 237 | register>(MAX_REGISTER_ENTRIES) reg_dpkts;//src dst pkt count 238 | 239 | //Reg not needed for state_INT 240 | register>(MAX_REGISTER_ENTRIES) reg_sbytes;//src dst byte count 241 | register>(MAX_REGISTER_ENTRIES) reg_dbytes;//src dst byte count 242 | 243 | //sum of TCP connection setup time : sum of synack and ackdat time 244 | 245 | register>(8) reg_ct_srv_dst;//Number of connections that contain the same service and srcip in last 100 connections 246 | //Note that only 8 possibilities: http, ftp, smtp, ssh, dns, ftp-data ,irc and (-) if not much used service 247 | //Register not needed for dsport 248 | //dttl, Dpkts, dmeansz, Dload will be obtained by reversing the src-dst tuple 249 | 250 | //Registers for identifying the flow more apart from hash we may use source port 251 | register>(MAX_REGISTER_ENTRIES) reg_srcip; 252 | register>(MAX_REGISTER_ENTRIES) reg_srcport; 253 | register>(MAX_REGISTER_ENTRIES) reg_dstport; 254 | 255 | register>(MAX_REGISTER_ENTRIES) reg_marked_malware; 256 | 257 | 258 | 259 | register>(MAX_REGISTER_ENTRIES) reg_time_last_pkt; 260 | register>(MAX_REGISTER_ENTRIES) reg_time_first_pkt; 261 | register>(MAX_REGISTER_ENTRIES) reg_syn_time; 262 | register>(MAX_REGISTER_ENTRIES) reg_tcprtt; 263 | 264 | //Store some statistics for the experiment 265 | counter(1, CounterType.packets) counter_hash_collisions; 266 | counter(1, CounterType.packets) counter_pkts; 267 | counter(1, CounterType.packets) counter_malware; 268 | counter(1, CounterType.packets) counter_true_detection; 269 | counter(1, CounterType.packets) counter_false_detection; 270 | counter(1, CounterType.packets) counter_flows; 271 | counter(1, CounterType.packets) counter_malware_flows; 272 | counter(1, CounterType.packets) counter_true_detection_flows; 273 | counter(1, CounterType.packets) counter_false_detection_flows; 274 | counter(1, CounterType.packets) counter_timeout; 275 | 276 | action init_register() { 277 | //intialise the registers to 0 278 | reg_time_last_pkt.write(meta.register_index, 0); 279 | reg_srcip.write(meta.register_index, 0); 280 | reg_srcport.write(meta.register_index, 0); 281 | reg_dstport.write(meta.register_index, 0); 282 | reg_ttl.write(meta.register_index, 0); 283 | reg_dttl.write(meta.register_index, 0); 284 | reg_spkts.write(meta.register_index, 0); 285 | reg_sbytes.write(meta.register_index, 0); 286 | reg_dpkts.write(meta.register_index, 0); 287 | reg_dbytes.write(meta.register_index, 0); 288 | reg_syn_time.write(meta.register_index, 0); 289 | reg_tcprtt.write(meta.register_index, 0); 290 | reg_marked_malware.write(meta.register_index, 0); 291 | } 292 | 293 | action get_register_index_tcp() { 294 | //Get register position 295 | hash(meta.register_index, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.srcAddr, 296 | hdr.ipv4.dstAddr, 297 | hdr.tcp.srcPort, 298 | hdr.tcp.dstPort, 299 | hdr.ipv4.protocol}, 300 | (bit<32>)MAX_REGISTER_ENTRIES); 301 | 302 | hash(meta.register_index_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.srcAddr, 303 | hdr.ipv4.dstAddr, 304 | hdr.tcp.srcPort, 305 | hdr.tcp.dstPort, 306 | hdr.ipv4.protocol}, 307 | (bit<32>)MAX_REGISTER_ENTRIES); 308 | } 309 | 310 | action get_register_index_udp() { 311 | hash(meta.register_index, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.srcAddr, 312 | hdr.ipv4.dstAddr, 313 | hdr.udp.srcPort, 314 | hdr.udp.dstPort, 315 | hdr.ipv4.protocol}, 316 | (bit<32>)MAX_REGISTER_ENTRIES); 317 | 318 | hash(meta.register_index_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.srcAddr, 319 | hdr.ipv4.dstAddr, 320 | hdr.udp.srcPort, 321 | hdr.udp.dstPort, 322 | hdr.ipv4.protocol}, 323 | (bit<32>)MAX_REGISTER_ENTRIES); 324 | } 325 | 326 | action get_register_index_inverse_tcp() { 327 | //Get register position for the same flow in another directon 328 | // just inverse the src and dst 329 | hash(meta.register_index_inverse, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.dstAddr, 330 | hdr.ipv4.srcAddr, 331 | hdr.tcp.dstPort, 332 | hdr.tcp.srcPort, 333 | hdr.ipv4.protocol}, 334 | (bit<32>)MAX_REGISTER_ENTRIES); 335 | 336 | hash(meta.register_index_inverse_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.dstAddr, 337 | hdr.ipv4.srcAddr, 338 | hdr.tcp.dstPort, 339 | hdr.tcp.srcPort, 340 | hdr.ipv4.protocol}, 341 | (bit<32>)MAX_REGISTER_ENTRIES); 342 | } 343 | 344 | action get_register_index_inverse_udp() { 345 | hash(meta.register_index_inverse, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.dstAddr, 346 | hdr.ipv4.srcAddr, 347 | hdr.udp.dstPort, 348 | hdr.udp.srcPort, 349 | hdr.ipv4.protocol}, 350 | (bit<32>)MAX_REGISTER_ENTRIES); 351 | 352 | hash(meta.register_index_inverse_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.dstAddr, 353 | hdr.ipv4.srcAddr, 354 | hdr.udp.dstPort, 355 | hdr.ipv4.protocol}, 356 | (bit<32>)MAX_REGISTER_ENTRIES); 357 | } 358 | 359 | action set_allowed(){ 360 | //set bloom filter fields 361 | bloom_filter.write(meta.register_position_one, 1); 362 | bloom_filter.write(meta.register_position_two, 1); 363 | } 364 | 365 | action check_if_allowed(){ 366 | //Read bloom filter cells to check if there are 1's 367 | bloom_filter.read(meta.register_cell_one, meta.register_position_one); 368 | bloom_filter.read(meta.register_cell_two, meta.register_position_two); 369 | } 370 | 371 | action drop() { 372 | mark_to_drop(standard_metadata); 373 | } 374 | 375 | //we plan to use the following features for the moment 376 | //sttl ct_state_ttl dttl Sload Dpkts dmeansz state_INT sbytes sload smeansz tcprtt dsport dur ct_srv_dst 377 | 378 | //1.* sttl there by default 379 | //2. ct_state_ttl **to be called after sttl and dttl calc 380 | 381 | action calc_state() { 382 | //When Sload or Dload is 0 the state can be INT 383 | //Thus need to calculate sload, dload before 384 | // XX TODO Argus log shows only last state! 385 | //XX TODO The following logic is only approx. correct! 386 | if ((meta.is_first == 1)||(meta.dttl == 0)) { 387 | if (hdr.ipv4.protocol == 6) //TCP 388 | meta.state = STATE_REQ; 389 | else meta.state = STATE_INT; 390 | } 391 | else { 392 | if (hdr.ipv4.protocol == 6) //TCP 393 | meta.state = STATE_EST; 394 | else meta.state = STATE_CON; 395 | } 396 | //TODO for STATE_FIN, which may not be useful as it would be last packet of transaction 397 | if (hdr.ipv4.protocol == 6 && hdr.tcp.fin == (bit<1>)1) { 398 | meta.state = STATE_FIN; 399 | } 400 | } 401 | 402 | action calc_ct_state_ttl(){ 403 | 404 | meta.ct_state_ttl = 0; 405 | if ((meta.sttl == 62 || meta.sttl == 63 || meta.sttl == 254 || meta.sttl == 255) 406 | && (meta.dttl == 252 || meta.dttl == 253) && meta.state == STATE_FIN) { 407 | meta.ct_state_ttl = 1; 408 | } 409 | else if ((meta.sttl == 0 || meta.sttl == 62 || meta.sttl == 254) 410 | && (meta.dttl == 0) && meta.state == STATE_INT) { 411 | meta.ct_state_ttl = 2; 412 | } 413 | else if((meta.sttl == 62 || meta.sttl == 254) 414 | && (meta.dttl == 60 || meta.dttl == 252 || meta.dttl == 253) 415 | && meta.state == STATE_CON){ 416 | meta.ct_state_ttl = 3; 417 | } 418 | else if((meta.sttl == 254) && (meta.dttl == 252) && meta.state == STATE_ACC){ 419 | meta.ct_state_ttl = 4; 420 | } 421 | else if((meta.sttl == 254) && (meta.dttl == 252) && meta.state == STATE_CLO){ 422 | meta.ct_state_ttl = 5; 423 | } 424 | else if((meta.sttl == 254) && (meta.dttl == 0) && meta.state == STATE_REQ){ 425 | meta.ct_state_ttl = 7; 426 | } 427 | else { 428 | meta.ct_state_ttl = 0; 429 | } 430 | } 431 | 432 | action read_ct_srv_dst() { 433 | //TODO XX The following is just for test 434 | //No. of connections that contain the same service (14) (ftp, http, ..) and destination address (3) (ipaddress) in 100 connections according to the last time (26). 435 | 436 | meta.ct_srv_dst = 10; 437 | } 438 | 439 | 440 | action init_features() { 441 | //they will be updated when needed 442 | //or easy but a bit slow: to read them now 443 | //feature order can be changed flexibly using registers configurable from control plane, etc. 444 | 445 | // In the traces bitrate = int(smeanz)*(totalpkts - 1)*8/dur 446 | //We will compare sbytes*(totalpkts - 1)*8 > th*dur*spkts; 447 | 448 | meta.feature1 = (bit<64>)meta.sttl;//sttl 449 | meta.feature2 = (bit<64>)meta.ct_state_ttl;//ct_state_ttl 450 | meta.feature3 = (bit<64>)meta.dttl;//dttl 451 | meta.feature4 = (bit<64>)(meta.sbytes*(meta.spkts - 1)*8) ;//needed for Sload 452 | meta.feature5 = (bit<64>)meta.dpkts;//dpkts 453 | meta.feature6 = (bit<64>)meta.dbytes;//Needed for dmeansz 454 | meta.feature7 = (bit<64>)meta.sbytes;//sbytes 455 | meta.feature8 = (bit<64>)(meta.dbytes*(meta.dpkts - 1)*8);//Needed for dload 456 | meta.feature9 = (bit<64>)meta.sbytes;//needed for smeansz 457 | meta.feature10 = (bit<64>)meta.tcprtt;//tcprtt 458 | meta.feature11 = (bit<64>)meta.dstport;//dstport 459 | meta.feature12 = (bit<64>)meta.dur;//dur 460 | 461 | meta.class = CLASS_NOT_SET; 462 | meta.class2 = CLASS_NOT_SET; 463 | meta.class3 = CLASS_NOT_SET; 464 | } 465 | 466 | action CheckFeature(bit<16> node_id, bit<16> f_inout, bit<64> threshold) { 467 | //XX For dur and tcprtt are in microseconds! Thus multiplied by 1000000 if in seconds! 468 | //XX For rate comparisons 'th' is multiplied by time delta as division is not allowed 469 | 470 | bit<64> feature = 0; 471 | bit<64> th = threshold; 472 | bit<16> f = f_inout + 1; 473 | 474 | if (f == 1) { 475 | 476 | feature = meta.feature1; 477 | } 478 | else if (f == 2) { 479 | feature = meta.feature2; 480 | } 481 | else if (f == 3) { 482 | feature = meta.feature3; 483 | } 484 | else if (f == 4) { 485 | feature = meta.feature4*1000000; 486 | th = th*(bit<64>)meta.dur*(bit<64>)meta.sbytes; 487 | } 488 | else if (f == 5) { 489 | feature = meta.feature5; 490 | } 491 | else if (f == 6) { 492 | feature = meta.feature6; 493 | th = th*(bit<64>)meta.dpkts; 494 | } 495 | else if (f == 7) { 496 | feature = meta.feature7; 497 | } 498 | else if (f == 8) { 499 | feature = meta.feature8*1000000; 500 | th = th*(bit<64>)meta.dur*(bit<64>)meta.sbytes; 501 | } 502 | else if (f == 9) { 503 | feature = meta.feature9; 504 | th = th*(bit<64>)meta.spkts; 505 | } 506 | else if (f == 10) { 507 | feature = meta.feature10; 508 | } 509 | else if (f == 11) { 510 | feature = meta.feature11; 511 | } 512 | else if (f == 12) { 513 | feature = meta.feature12; 514 | } 515 | 516 | if (feature <= th) meta.isTrue = 1; 517 | else meta.isTrue = 0; 518 | 519 | meta.prevFeature = f - 1; 520 | 521 | meta.node_id = node_id; 522 | } 523 | 524 | action SetClass(bit<16> node_id, bit<16> class) { 525 | meta.class = class; 526 | meta.node_id = node_id; //just for debugging otherwise not needed 527 | } 528 | action SetClass2(bit<16> node_id, bit<16> class) { 529 | meta.class2 = class; 530 | meta.node_id = node_id; //just for debugging otherwise not needed 531 | } 532 | action SetClass3(bit<16> node_id, bit<16> class) { 533 | meta.class3 = class; 534 | meta.node_id = node_id; //just for debugging otherwise not needed 535 | } 536 | 537 | action SetDirection() { 538 | //need just for this setting as tcpreplay is sending all the packets to same interface 539 | meta.direction = 1; 540 | } 541 | 542 | action SetMalware() { 543 | //need just for this setting as tcpreplay is sending all the packets to same interface 544 | meta.malware = 1; 545 | } 546 | 547 | 548 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 549 | standard_metadata.egress_spec = port; 550 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 551 | hdr.ethernet.dstAddr = dstAddr; 552 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 553 | } 554 | 555 | 556 | 557 | table direction{ 558 | key = { 559 | hdr.ipv4.dstAddr: lpm; 560 | } 561 | actions = { 562 | NoAction; 563 | SetDirection; 564 | } 565 | size = 10; 566 | default_action = NoAction(); 567 | } 568 | 569 | table malware{ //For debugging 570 | key = { 571 | hdr.ipv4.srcAddr: lpm; 572 | } 573 | actions = { 574 | NoAction; 575 | SetMalware; 576 | } 577 | size = 10; 578 | default_action = NoAction(); 579 | } 580 | 581 | table malware_inverse { //For debugging 582 | key = { 583 | hdr.ipv4.dstAddr: lpm; 584 | } 585 | actions = { 586 | NoAction; 587 | SetMalware; 588 | } 589 | size = 10; 590 | default_action = NoAction(); 591 | } 592 | 593 | //TODO convert lavel1 --> level_1_1 594 | //TODO micro TABLE(N) 595 | 596 | table level1{ 597 | key = { 598 | meta.node_id: exact; 599 | meta.prevFeature: exact; 600 | meta.isTrue: exact; 601 | } 602 | actions = { 603 | NoAction; 604 | CheckFeature; 605 | SetClass; 606 | } 607 | size = 1024; 608 | } 609 | 610 | table level2{ 611 | key = { 612 | meta.node_id: exact; 613 | meta.prevFeature: exact; 614 | meta.isTrue: exact; 615 | } 616 | actions = { 617 | NoAction; 618 | CheckFeature; 619 | SetClass; 620 | } 621 | size = 1024; 622 | } 623 | 624 | table level3{ 625 | key = { 626 | meta.node_id: exact; 627 | meta.prevFeature: exact; 628 | meta.isTrue: exact; 629 | } 630 | actions = { 631 | NoAction; 632 | CheckFeature; 633 | SetClass; 634 | } 635 | size = 1024; 636 | } 637 | table level4{ 638 | key = { 639 | meta.node_id: exact; 640 | meta.prevFeature: exact; 641 | meta.isTrue: exact; 642 | } 643 | actions = { 644 | NoAction; 645 | CheckFeature; 646 | SetClass; 647 | } 648 | size = 1024; 649 | } 650 | 651 | table level5{ 652 | key = { 653 | meta.node_id: exact; 654 | meta.prevFeature: exact; 655 | meta.isTrue: exact; 656 | } 657 | actions = { 658 | NoAction; 659 | CheckFeature; 660 | SetClass; 661 | } 662 | size = 1024; 663 | } 664 | 665 | table level6{ 666 | key = { 667 | meta.node_id: exact; 668 | meta.prevFeature: exact; 669 | meta.isTrue: exact; 670 | } 671 | actions = { 672 | NoAction; 673 | CheckFeature; 674 | SetClass; 675 | } 676 | size = 1024; 677 | } 678 | 679 | table level7{ 680 | key = { 681 | meta.node_id: exact; 682 | meta.prevFeature: exact; 683 | meta.isTrue: exact; 684 | } 685 | actions = { 686 | NoAction; 687 | CheckFeature; 688 | SetClass; 689 | } 690 | size = 1024; 691 | } 692 | 693 | table level8{ 694 | key = { 695 | meta.node_id: exact; 696 | meta.prevFeature: exact; 697 | meta.isTrue: exact; 698 | } 699 | actions = { 700 | NoAction; 701 | CheckFeature; 702 | SetClass; 703 | } 704 | size = 1024; 705 | } 706 | 707 | table level9{ 708 | key = { 709 | meta.node_id: exact; 710 | meta.prevFeature: exact; 711 | meta.isTrue: exact; 712 | } 713 | actions = { 714 | NoAction; 715 | CheckFeature; 716 | SetClass; 717 | } 718 | size = 1024; 719 | } 720 | 721 | table level10{ 722 | key = { 723 | meta.node_id: exact; 724 | meta.prevFeature: exact; 725 | meta.isTrue: exact; 726 | } 727 | actions = { 728 | NoAction; 729 | CheckFeature; 730 | SetClass; 731 | } 732 | size = 1024; 733 | } 734 | 735 | table level11{ 736 | key = { 737 | meta.node_id: exact; 738 | meta.prevFeature: exact; 739 | meta.isTrue: exact; 740 | } 741 | actions = { 742 | NoAction; 743 | CheckFeature; 744 | SetClass; 745 | } 746 | size = 1024; 747 | } 748 | 749 | table level_2_1 { 750 | key = { 751 | meta.node_id: exact; 752 | meta.prevFeature: exact; 753 | meta.isTrue: exact; 754 | } 755 | actions = { 756 | NoAction; 757 | CheckFeature; 758 | SetClass2; 759 | } 760 | size = 1024; 761 | } 762 | 763 | table level_2_2{ 764 | key = { 765 | meta.node_id: exact; 766 | meta.prevFeature: exact; 767 | meta.isTrue: exact; 768 | } 769 | actions = { 770 | NoAction; 771 | CheckFeature; 772 | SetClass2; 773 | } 774 | size = 1024; 775 | } 776 | 777 | table level_2_3{ 778 | key = { 779 | meta.node_id: exact; 780 | meta.prevFeature: exact; 781 | meta.isTrue: exact; 782 | } 783 | actions = { 784 | NoAction; 785 | CheckFeature; 786 | SetClass2; 787 | } 788 | size = 1024; 789 | } 790 | table level_2_4{ 791 | key = { 792 | meta.node_id: exact; 793 | meta.prevFeature: exact; 794 | meta.isTrue: exact; 795 | } 796 | actions = { 797 | NoAction; 798 | CheckFeature; 799 | SetClass2; 800 | } 801 | size = 1024; 802 | } 803 | 804 | table level_2_5{ 805 | key = { 806 | meta.node_id: exact; 807 | meta.prevFeature: exact; 808 | meta.isTrue: exact; 809 | } 810 | actions = { 811 | NoAction; 812 | CheckFeature; 813 | SetClass2; 814 | } 815 | size = 1024; 816 | } 817 | 818 | table level_2_6{ 819 | key = { 820 | meta.node_id: exact; 821 | meta.prevFeature: exact; 822 | meta.isTrue: exact; 823 | } 824 | actions = { 825 | NoAction; 826 | CheckFeature; 827 | SetClass2; 828 | } 829 | size = 1024; 830 | } 831 | 832 | table level_2_7{ 833 | key = { 834 | meta.node_id: exact; 835 | meta.prevFeature: exact; 836 | meta.isTrue: exact; 837 | } 838 | actions = { 839 | NoAction; 840 | CheckFeature; 841 | SetClass2; 842 | } 843 | size = 1024; 844 | } 845 | 846 | table level_2_8{ 847 | key = { 848 | meta.node_id: exact; 849 | meta.prevFeature: exact; 850 | meta.isTrue: exact; 851 | } 852 | actions = { 853 | NoAction; 854 | CheckFeature; 855 | SetClass2; 856 | } 857 | size = 1024; 858 | } 859 | 860 | table level_2_9{ 861 | key = { 862 | meta.node_id: exact; 863 | meta.prevFeature: exact; 864 | meta.isTrue: exact; 865 | } 866 | actions = { 867 | NoAction; 868 | CheckFeature; 869 | SetClass2; 870 | } 871 | size = 1024; 872 | } 873 | 874 | table level_2_10{ 875 | key = { 876 | meta.node_id: exact; 877 | meta.prevFeature: exact; 878 | meta.isTrue: exact; 879 | } 880 | actions = { 881 | NoAction; 882 | CheckFeature; 883 | SetClass2; 884 | } 885 | size = 1024; 886 | } 887 | 888 | table level_2_11{ 889 | key = { 890 | meta.node_id: exact; 891 | meta.prevFeature: exact; 892 | meta.isTrue: exact; 893 | } 894 | actions = { 895 | NoAction; 896 | CheckFeature; 897 | SetClass2; 898 | } 899 | size = 1024; 900 | } 901 | 902 | table level_3_1{ 903 | key = { 904 | meta.node_id: exact; 905 | meta.prevFeature: exact; 906 | meta.isTrue: exact; 907 | } 908 | actions = { 909 | NoAction; 910 | CheckFeature; 911 | SetClass3; 912 | } 913 | size = 1024; 914 | } 915 | 916 | table level_3_2{ 917 | key = { 918 | meta.node_id: exact; 919 | meta.prevFeature: exact; 920 | meta.isTrue: exact; 921 | } 922 | actions = { 923 | NoAction; 924 | CheckFeature; 925 | SetClass3; 926 | } 927 | size = 1024; 928 | } 929 | 930 | table level_3_3{ 931 | key = { 932 | meta.node_id: exact; 933 | meta.prevFeature: exact; 934 | meta.isTrue: exact; 935 | } 936 | actions = { 937 | NoAction; 938 | CheckFeature; 939 | SetClass3; 940 | } 941 | size = 1024; 942 | } 943 | table level_3_4{ 944 | key = { 945 | meta.node_id: exact; 946 | meta.prevFeature: exact; 947 | meta.isTrue: exact; 948 | } 949 | actions = { 950 | NoAction; 951 | CheckFeature; 952 | SetClass3; 953 | } 954 | size = 1024; 955 | } 956 | 957 | table level_3_5{ 958 | key = { 959 | meta.node_id: exact; 960 | meta.prevFeature: exact; 961 | meta.isTrue: exact; 962 | } 963 | actions = { 964 | NoAction; 965 | CheckFeature; 966 | SetClass3; 967 | } 968 | size = 1024; 969 | } 970 | 971 | table level_3_6{ 972 | key = { 973 | meta.node_id: exact; 974 | meta.prevFeature: exact; 975 | meta.isTrue: exact; 976 | } 977 | actions = { 978 | NoAction; 979 | CheckFeature; 980 | SetClass3; 981 | } 982 | size = 1024; 983 | } 984 | 985 | table level_3_7{ 986 | key = { 987 | meta.node_id: exact; 988 | meta.prevFeature: exact; 989 | meta.isTrue: exact; 990 | } 991 | actions = { 992 | NoAction; 993 | CheckFeature; 994 | SetClass3; 995 | } 996 | size = 1024; 997 | } 998 | 999 | table level_3_8{ 1000 | key = { 1001 | meta.node_id: exact; 1002 | meta.prevFeature: exact; 1003 | meta.isTrue: exact; 1004 | } 1005 | actions = { 1006 | NoAction; 1007 | CheckFeature; 1008 | SetClass3; 1009 | } 1010 | size = 1024; 1011 | } 1012 | 1013 | table level_3_9{ 1014 | key = { 1015 | meta.node_id: exact; 1016 | meta.prevFeature: exact; 1017 | meta.isTrue: exact; 1018 | } 1019 | actions = { 1020 | NoAction; 1021 | CheckFeature; 1022 | SetClass3; 1023 | } 1024 | size = 1024; 1025 | } 1026 | 1027 | table level_3_10{ 1028 | key = { 1029 | meta.node_id: exact; 1030 | meta.prevFeature: exact; 1031 | meta.isTrue: exact; 1032 | } 1033 | actions = { 1034 | NoAction; 1035 | CheckFeature; 1036 | SetClass3; 1037 | } 1038 | size = 1024; 1039 | } 1040 | 1041 | table level_3_11{ 1042 | key = { 1043 | meta.node_id: exact; 1044 | meta.prevFeature: exact; 1045 | meta.isTrue: exact; 1046 | } 1047 | actions = { 1048 | NoAction; 1049 | CheckFeature; 1050 | SetClass3; 1051 | } 1052 | size = 1024; 1053 | } 1054 | 1055 | 1056 | 1057 | 1058 | /* This will send the packet to a specifique port of the switch for output*/ 1059 | table ipv4_exact { 1060 | key = { 1061 | meta.class: exact; 1062 | } 1063 | actions = { 1064 | ipv4_forward; 1065 | drop; 1066 | NoAction; 1067 | } 1068 | size = 1024; 1069 | default_action = drop(); 1070 | } 1071 | 1072 | table debug{ 1073 | key = { 1074 | meta.feature1: exact; 1075 | meta.feature2: exact; 1076 | meta.feature3: exact; 1077 | meta.feature4: exact; 1078 | meta.feature5: exact; 1079 | meta.feature6: exact; 1080 | meta.feature7: exact; 1081 | meta.feature8: exact; 1082 | meta.feature9: exact; 1083 | meta.feature10: exact; 1084 | meta.feature11: exact; 1085 | meta.feature12: exact; 1086 | meta.state: exact; 1087 | meta.spkts: exact; 1088 | meta.is_first: exact; 1089 | hdr.ipv4.dstAddr: exact; 1090 | meta.hdr_srcport: exact; 1091 | meta.hdr_dstport: exact; 1092 | standard_metadata.ingress_global_timestamp: exact; 1093 | meta.syn_time: exact; 1094 | meta.register_index: exact; 1095 | meta.register_index_inverse: exact; 1096 | meta.direction: exact; 1097 | meta.is_hash_collision: exact; 1098 | meta.malware: exact; 1099 | meta.marked_malware: exact; 1100 | meta.class: exact; 1101 | meta.sbytes: exact; 1102 | } 1103 | actions = { 1104 | NoAction; 1105 | } 1106 | size = 1024; 1107 | } 1108 | 1109 | 1110 | //Invoke the tables using the apply method 1111 | 1112 | apply { 1113 | 1114 | /*check the direction of packets going. 1115 | For UNSW data, the emulation configuration is as follows 1116 | Outside: 1117 | 59.166.0.0 normal 1118 | 175.45.176.0 malware 1119 | Inside: 1120 | 149.171.126.0 1121 | Thus, mostly track 59.166.0.0/175.45.176.0 ---> 149.171.126.0 packets 1122 | */ 1123 | 1124 | //count all the packets 1125 | direction.apply(); 1126 | counter_pkts.count(0); 1127 | 1128 | if ( hdr.ipv4.isValid()) { 1129 | //Calculate all features 1130 | //TODO optimize : feature needs to be calculated only if needed 1131 | 1132 | if (hdr.ipv4.protocol == 6 || hdr.ipv4.protocol == 17) {//We treat only TCP or UDP packets 1133 | 1134 | if (meta.direction == 1) { 1135 | 1136 | if (hdr.ipv4.protocol == 6) { 1137 | get_register_index_tcp(); 1138 | meta.hdr_srcport = hdr.tcp.srcPort; 1139 | meta.hdr_dstport = hdr.tcp.dstPort; 1140 | } 1141 | else { 1142 | get_register_index_udp(); 1143 | meta.hdr_srcport = hdr.udp.srcPort; 1144 | meta.hdr_dstport = hdr.udp.dstPort; 1145 | 1146 | } 1147 | 1148 | //read_reg_to_check_collision srcip, srcport, dstport 1149 | reg_srcip.read(meta.srcip, meta.register_index); 1150 | reg_srcport.read(meta.srcport, meta.register_index); 1151 | reg_dstport.read(meta.dstport, meta.register_index); 1152 | reg_time_last_pkt.read(meta.time_last_pkt, (bit<32>)meta.register_index); 1153 | 1154 | if (meta.srcip == 0) {//It was an empty register 1155 | meta.is_first = 1; 1156 | } 1157 | else if ((standard_metadata.ingress_global_timestamp - meta.time_last_pkt) > FLOW_TIMEOUT) { 1158 | /*We havent heard from this flow it has been FLOW_TIMEOUT 1159 | We will initialse the register space 1160 | TODO check if init_register() is initialising all and only those needed. ; 1161 | */ 1162 | init_register(); 1163 | counter_timeout.count(0); 1164 | meta.is_first = 1; 1165 | } 1166 | else if (meta.srcip != hdr.ipv4.srcAddr || meta.srcport != meta.hdr_srcport 1167 | || meta.dstport != meta.hdr_dstport) { 1168 | //Hash collision! 1169 | //TODO handle hash collisions in a better way! 1170 | meta.is_hash_collision = 1; 1171 | counter_hash_collisions.count(0); 1172 | } 1173 | 1174 | if (meta.is_hash_collision == 0) { 1175 | 1176 | if (meta.is_first == 1) { 1177 | meta.time_first_pkt = standard_metadata.ingress_global_timestamp; 1178 | reg_time_first_pkt.write((bit<32>)meta.register_index, meta.time_first_pkt); 1179 | reg_srcip.write((bit<32>)meta.register_index, hdr.ipv4.srcAddr); 1180 | reg_srcport.write((bit<32>)meta.register_index, meta.hdr_srcport); 1181 | reg_dstport.write((bit<32>)meta.register_index, meta.hdr_dstport); 1182 | counter_flows.count(0); 1183 | } 1184 | 1185 | reg_spkts.read(meta.spkts, (bit<32>)meta.register_index); 1186 | meta.spkts = meta.spkts + 1; 1187 | reg_spkts.write((bit<32>)meta.register_index, meta.spkts); 1188 | 1189 | meta.sttl = hdr.ipv4.ttl; 1190 | reg_ttl.write((bit<32>)meta.register_index, meta.sttl); 1191 | 1192 | reg_dttl.read(meta.dttl, (bit<32>)meta.register_index); 1193 | 1194 | 1195 | //read_sbytes also used for sload 1196 | reg_sbytes.read(meta.sbytes, (bit<32>)meta.register_index); 1197 | meta.sbytes = meta.sbytes + standard_metadata.packet_length - 14; 1198 | reg_sbytes.write((bit<32>)meta.register_index, meta.sbytes); 1199 | 1200 | 1201 | // tcprtt 1202 | //SYN TIME 1203 | if ((hdr.tcp.ack != (bit<1>)1)&&(hdr.tcp.syn == (bit<1>)1)) {//this is a SYN 1204 | reg_syn_time.write((bit<32>)meta.register_index, 1205 | standard_metadata.ingress_global_timestamp); 1206 | } 1207 | //ACK + SYN time 1208 | else if ((hdr.tcp.ack == (bit<1>)1)&&(hdr.tcp.syn != (bit<1>)1)) {//this is an ACK 1209 | 1210 | reg_first_ack.read(meta.first_ack, (bit<32>)meta.register_index); 1211 | if (meta.first_ack == 0) { 1212 | //sum of synack(SYN to SYN_ACK time) and ackdat(SYN_ACK to ACK time) 1213 | reg_syn_time.read(meta.syn_time, (bit<32>)meta.register_index); 1214 | if (meta.syn_time > 0) {//There was a syn before 1215 | meta.tcprtt = standard_metadata.ingress_global_timestamp - meta.syn_time; 1216 | reg_tcprtt.write((bit<32>)meta.register_index, meta.tcprtt); 1217 | //no longer a first ack 1218 | reg_first_ack.write((bit<32>)meta.register_index, 1); 1219 | } 1220 | } 1221 | } 1222 | 1223 | 1224 | //read all reverse flow features 1225 | reg_dbytes.read(meta.dbytes, (bit<32>)meta.register_index); 1226 | reg_dpkts.read(meta.dpkts, (bit<32>)meta.register_index); 1227 | 1228 | }//hash collision check 1229 | 1230 | }//end of direction = 1 1231 | 1232 | else {//direction = 0 1233 | 1234 | //TODO some flows can be marked malware even after analysing return flow! 1235 | 1236 | if (hdr.ipv4.protocol == 6) { 1237 | get_register_index_inverse_tcp(); 1238 | meta.hdr_srcport = hdr.tcp.dstPort;//its inverse 1239 | meta.hdr_dstport = hdr.tcp.srcPort; 1240 | } 1241 | else { 1242 | //TODO what if it is neither TCP nor UDP? 1243 | get_register_index_inverse_udp(); 1244 | meta.hdr_srcport = hdr.udp.dstPort; 1245 | meta.hdr_dstport = hdr.udp.srcPort; 1246 | 1247 | } 1248 | 1249 | meta.register_index = meta.register_index_inverse; 1250 | 1251 | //read_reg_to_check_collision srcip, srcport, dstport 1252 | reg_srcip.read(meta.srcip, meta.register_index); 1253 | reg_srcport.read(meta.srcport, meta.register_index); 1254 | reg_dstport.read(meta.dstport, meta.register_index); 1255 | reg_time_last_pkt.read(meta.time_last_pkt, (bit<32>)meta.register_index); 1256 | 1257 | if (meta.srcip == 0) {//It was an empty register 1258 | meta.is_first = 1; 1259 | } 1260 | else if ((standard_metadata.ingress_global_timestamp - meta.time_last_pkt) > FLOW_TIMEOUT) { 1261 | /*We havent heard from this flow it has been FLOW_TIMEOUT 1262 | We will initialse the register space 1263 | TODO check if init_register() is initialising all and only those needed. ; 1264 | */ 1265 | init_register(); 1266 | counter_timeout.count(0); 1267 | meta.is_first = 1; 1268 | } 1269 | else if (meta.srcip != hdr.ipv4.dstAddr || meta.srcport != meta.hdr_srcport 1270 | || meta.dstport != meta.hdr_dstport) { 1271 | //Hash collision! 1272 | //TODO handle hash collisions in a better way! 1273 | meta.is_hash_collision = 1; 1274 | counter_hash_collisions.count(0); 1275 | } 1276 | 1277 | if (meta.is_hash_collision == 0) { 1278 | 1279 | if (meta.is_first == 1) {//shouldn't happen! 1280 | meta.time_first_pkt = standard_metadata.ingress_global_timestamp; 1281 | reg_time_first_pkt.write((bit<32>)meta.register_index, meta.time_first_pkt); 1282 | reg_srcip.write((bit<32>)meta.register_index, hdr.ipv4.dstAddr); 1283 | reg_srcport.write((bit<32>)meta.register_index, meta.hdr_srcport); 1284 | reg_dstport.write((bit<32>)meta.register_index, meta.hdr_dstport); 1285 | 1286 | } 1287 | 1288 | //dpkts and dload 1289 | reg_dpkts.read(meta.dpkts, (bit<32>)meta.register_index); 1290 | meta.dpkts = meta.dpkts + 1; 1291 | reg_dpkts.write((bit<32>)meta.register_index, meta.dpkts); 1292 | 1293 | //dbytes 1294 | reg_dbytes.read(meta.dbytes, (bit<32>)meta.register_index); 1295 | meta.dbytes = meta.dbytes + standard_metadata.packet_length - 14; 1296 | reg_dbytes.write((bit<32>)meta.register_index, meta.dbytes); 1297 | 1298 | reg_time_last_pkt.write((bit<32>)meta.register_index, 1299 | standard_metadata.ingress_global_timestamp ); 1300 | 1301 | //Read other features from the sources to destination direction 1302 | meta.dttl = hdr.ipv4.ttl; 1303 | reg_dttl.write((bit<32>)meta.register_index, meta.dttl); 1304 | reg_ttl.read(meta.sttl, (bit<32>)meta.register_index); 1305 | reg_sbytes.read(meta.sbytes, (bit<32>)meta.register_index); 1306 | reg_spkts.read(meta.spkts, (bit<32>)meta.register_index); 1307 | 1308 | }//hash collision check 1309 | 1310 | } // end of direction = 0 1311 | 1312 | //Read common features 1313 | 1314 | if (meta.is_hash_collision == 0) { 1315 | //TODO on hash collision we are letting the flow pass 1316 | //We can also do a false detection! 1317 | 1318 | reg_tcprtt.read(meta.tcprtt, (bit<32>)meta.register_index); 1319 | reg_time_first_pkt.read(meta.time_first_pkt, (bit<32>)meta.register_index); 1320 | meta.dur = standard_metadata.ingress_global_timestamp - meta.time_first_pkt; 1321 | 1322 | reg_time_last_pkt.write((bit<32>)meta.register_index, 1323 | standard_metadata.ingress_global_timestamp ); 1324 | 1325 | 1326 | calc_state(); 1327 | calc_ct_state_ttl(); 1328 | read_ct_srv_dst(); 1329 | 1330 | init_features(); 1331 | 1332 | 1333 | //start with parent node of decision tree 1334 | meta.prevFeature = 0; 1335 | meta.isTrue = 1; 1336 | 1337 | reg_marked_malware.read(meta.marked_malware, (bit<32>)meta.register_index); 1338 | 1339 | 1340 | if (meta.direction == 1) { 1341 | malware.apply();//For statistics 1342 | } 1343 | else { 1344 | malware_inverse.apply();//For statistics 1345 | } 1346 | 1347 | if (meta.marked_malware == 1) { 1348 | meta.class = 1;//No need to check again! 1349 | } 1350 | else { 1351 | 1352 | //decision tree 1 1353 | 1354 | level1.apply(); 1355 | 1356 | if (meta.class == CLASS_NOT_SET) { 1357 | level2.apply(); 1358 | if (meta.class == CLASS_NOT_SET) { 1359 | level3.apply(); 1360 | if (meta.class == CLASS_NOT_SET) { 1361 | level4.apply(); 1362 | if (meta.class == CLASS_NOT_SET) { 1363 | level5.apply(); 1364 | if (meta.class == CLASS_NOT_SET) { 1365 | level6.apply(); 1366 | if (meta.class == CLASS_NOT_SET) { 1367 | level7.apply(); 1368 | if (meta.class == CLASS_NOT_SET) { 1369 | level8.apply(); 1370 | if (meta.class == CLASS_NOT_SET) { 1371 | level9.apply(); 1372 | if (meta.class == CLASS_NOT_SET) { 1373 | level10.apply(); 1374 | if (meta.class == CLASS_NOT_SET) 1375 | level11.apply(); 1376 | }}}}}}}}} 1377 | 1378 | //decision tree 2 1379 | meta.node_id = 287; 1380 | meta.prevFeature = 0; 1381 | meta.isTrue = 1; 1382 | 1383 | level_2_1.apply(); 1384 | 1385 | if (meta.class2 == CLASS_NOT_SET) { 1386 | level_2_2.apply(); 1387 | if (meta.class2 == CLASS_NOT_SET) { 1388 | level_2_3.apply(); 1389 | if (meta.class2 == CLASS_NOT_SET) { 1390 | level_2_4.apply(); 1391 | if (meta.class2 == CLASS_NOT_SET) { 1392 | level_2_5.apply(); 1393 | if (meta.class2 == CLASS_NOT_SET) { 1394 | level_2_6.apply(); 1395 | if (meta.class2 == CLASS_NOT_SET) { 1396 | level_2_7.apply(); 1397 | if (meta.class2 == CLASS_NOT_SET) { 1398 | level_2_8.apply(); 1399 | if (meta.class2 == CLASS_NOT_SET) { 1400 | level_2_9.apply(); 1401 | if (meta.class2 == CLASS_NOT_SET) { 1402 | level_2_10.apply(); 1403 | if (meta.class2 == CLASS_NOT_SET) 1404 | level_2_11.apply(); 1405 | }}}}}}}}} 1406 | 1407 | //decision tree 3 1408 | meta.node_id = 602; 1409 | meta.prevFeature = 0; 1410 | meta.isTrue = 1; 1411 | 1412 | level_3_1.apply(); 1413 | 1414 | if (meta.class3 == CLASS_NOT_SET) { 1415 | level_3_2.apply(); 1416 | if (meta.class3 == CLASS_NOT_SET) { 1417 | level_3_3.apply(); 1418 | if (meta.class3 == CLASS_NOT_SET) { 1419 | level_3_4.apply(); 1420 | if (meta.class3 == CLASS_NOT_SET) { 1421 | level_3_5.apply(); 1422 | if (meta.class3 == CLASS_NOT_SET) { 1423 | level_3_6.apply(); 1424 | if (meta.class3 == CLASS_NOT_SET) { 1425 | level_3_7.apply(); 1426 | if (meta.class3 == CLASS_NOT_SET) { 1427 | level_3_8.apply(); 1428 | if (meta.class3 == CLASS_NOT_SET) { 1429 | level_3_9.apply(); 1430 | if (meta.class3 == CLASS_NOT_SET) { 1431 | level_3_10.apply(); 1432 | if (meta.class3 == CLASS_NOT_SET) 1433 | level_3_11.apply(); 1434 | }}}}}}}}} 1435 | 1436 | //voting from results of different trees 1437 | if (meta.class == CLASS_NOT_SET) meta.class = 0; //TODO to check why this can happen! 1438 | if (meta.class2 == CLASS_NOT_SET) meta.class2 = 0; 1439 | if (meta.class3 == CLASS_NOT_SET) meta.class3 = 0; 1440 | 1441 | meta.class = meta.class + meta.class2 + meta.class3; 1442 | 1443 | if (meta.class <= 1) meta.class = 0; 1444 | else meta.class = 1; 1445 | 1446 | }//end of check for malware marked 1447 | 1448 | if (meta.malware == 1) {// meta.malware is calculated with priori knowledge for statistics 1449 | 1450 | counter_malware.count(0); 1451 | 1452 | if (meta.is_first == 1) { 1453 | counter_malware_flows.count(0); 1454 | } 1455 | 1456 | if(meta.class == 1) { 1457 | counter_true_detection.count(0); 1458 | 1459 | if (meta.marked_malware == 0) { 1460 | //We detect the flow as malware first time! 1461 | counter_true_detection_flows.count(0); 1462 | } 1463 | reg_marked_malware.write((bit<32>)meta.register_index,1); 1464 | } 1465 | } 1466 | else { 1467 | if(meta.class == 1) { 1468 | counter_false_detection.count(0); 1469 | 1470 | if (meta.marked_malware == 0) { 1471 | //We detect the flow as malware first time! even if false 1472 | counter_false_detection_flows.count(0); 1473 | } 1474 | reg_marked_malware.write((bit<32>)meta.register_index,1); 1475 | } 1476 | } 1477 | 1478 | }//hash collision check 1479 | 1480 | debug.apply(); 1481 | 1482 | 1483 | 1484 | }//End of if (hdr.ipv4.protocol == 6 || hdr.ipv4.protocol == 17) 1485 | 1486 | ipv4_exact.apply(); 1487 | 1488 | }//End of if hdr.ipv4.isValid() 1489 | 1490 | }//End of apply 1491 | } 1492 | 1493 | /************************************************************************* 1494 | **************** E G R E S S P R O C E S S I N G ******************* 1495 | *************************************************************************/ 1496 | 1497 | control MyEgress(inout headers hdr, 1498 | inout metadata meta, 1499 | inout standard_metadata_t standard_metadata) { 1500 | apply { } 1501 | } 1502 | 1503 | /************************************************************************* 1504 | ************* C H E C K S U M C O M P U T A T I O N ************** 1505 | *************************************************************************/ 1506 | 1507 | control MyComputeChecksum(inout headers hdr, inout metadata meta) { 1508 | apply { 1509 | update_checksum( 1510 | hdr.ipv4.isValid(), 1511 | { hdr.ipv4.version, 1512 | hdr.ipv4.ihl, 1513 | hdr.ipv4.diffserv, 1514 | hdr.ipv4.totalLen, 1515 | hdr.ipv4.identification, 1516 | hdr.ipv4.flags, 1517 | hdr.ipv4.fragOffset, 1518 | hdr.ipv4.ttl, 1519 | hdr.ipv4.protocol, 1520 | hdr.ipv4.srcAddr, 1521 | hdr.ipv4.dstAddr }, 1522 | hdr.ipv4.hdrChecksum, 1523 | HashAlgorithm.csum16); 1524 | } 1525 | } 1526 | 1527 | /************************************************************************* 1528 | 1529 | *********************** D E P A R S E R ******************************* 1530 | *************************************************************************/ 1531 | 1532 | control MyDeparser(packet_out packet, in headers hdr) { 1533 | apply { 1534 | packet.emit(hdr.ethernet); 1535 | packet.emit(hdr.ipv4); 1536 | packet.emit(hdr.tcp); 1537 | } 1538 | } 1539 | 1540 | /************************************************************************* 1541 | *********************** S W I T C H ******************************* 1542 | *************************************************************************/ 1543 | 1544 | V1Switch( 1545 | MyParser(), 1546 | MyVerifyChecksum(), 1547 | MyIngress(), 1548 | MyEgress(), 1549 | MyComputeChecksum(), 1550 | MyDeparser() 1551 | ) main; 1552 | -------------------------------------------------------------------------------- /switchtree.p4: -------------------------------------------------------------------------------- 1 | /* -*- P4_16 -*- */ 2 | /******************************************************************************** 3 | * 4 | * Copyright (c) 2019 Kamal Singh 5 | * All rights reserved. 6 | * 7 | *********************************************************************************/ 8 | 9 | 10 | #include 11 | #include 12 | 13 | const bit<16> TYPE_IPV4 = 0x800; 14 | 15 | #define MAX_REGISTER_ENTRIES 8192 16 | #define BLOOM_FILTER_BIT_WIDTH 32 17 | #define PACKET_THRESHOLD 1000 18 | #define FLOW_TIMEOUT 15000000 //15 seconds 19 | #define CLASS_NOT_SET 10000// A big number 20 | 21 | #define STATE_INT 1 22 | #define STATE_FIN 2 23 | #define STATE_REQ 3 24 | #define STATE_CON 4 25 | #define STATE_ACC 5 26 | #define STATE_CLO 6 27 | #define STATE_EST 7 28 | 29 | /************************************************************************* 30 | *********************** H E A D E R S *********************************** 31 | *************************************************************************/ 32 | 33 | typedef bit<9> egressSpec_t; 34 | typedef bit<48> macAddr_t; 35 | typedef bit<32> ip4Addr_t; 36 | 37 | header ethernet_t { 38 | macAddr_t dstAddr; 39 | macAddr_t srcAddr; 40 | bit<16> etherType; 41 | } 42 | 43 | header ipv4_t { 44 | bit<4> version; 45 | bit<4> ihl; 46 | bit<8> diffserv; 47 | bit<16> totalLen; 48 | bit<16> identification; 49 | bit<3> flags; 50 | bit<13> fragOffset; 51 | bit<8> ttl; 52 | bit<8> protocol; 53 | bit<16> hdrChecksum; 54 | ip4Addr_t srcAddr; 55 | ip4Addr_t dstAddr; 56 | } 57 | 58 | header tcp_t{ 59 | bit<16> srcPort; 60 | bit<16> dstPort; 61 | bit<32> seqNo; 62 | bit<32> ackNo; 63 | bit<4> dataOffset; 64 | bit<4> res; 65 | bit<1> cwr; 66 | bit<1> ece; 67 | bit<1> urg; 68 | bit<1> ack; 69 | bit<1> psh; 70 | bit<1> rst; 71 | bit<1> syn; 72 | bit<1> fin; 73 | bit<16> window; 74 | bit<16> checksum; 75 | bit<16> urgentPtr; 76 | } 77 | 78 | header udp_t { 79 | bit<16> srcPort; 80 | bit<16> dstPort; 81 | bit<16> length_; 82 | bit<16> checksum; 83 | } 84 | 85 | 86 | struct metadata { 87 | bit<64> feature1; 88 | bit<64> feature2; 89 | bit<64> feature3; 90 | bit<64> feature4; 91 | bit<64> feature5; 92 | bit<64> feature6; 93 | bit<64> feature7; 94 | bit<64> feature8; 95 | bit<64> feature9; 96 | bit<64> feature10; 97 | bit<64> feature11; 98 | bit<64> feature12; 99 | bit<64> feature13; 100 | 101 | bit<16> prevFeature; 102 | bit<16> isTrue; 103 | 104 | bit<16> class; 105 | bit<16> node_id; 106 | 107 | bit<1> direction; 108 | bit<32> register_index; 109 | bit<32> register_index_2; 110 | bit<32> register_index_inverse; 111 | bit<32> register_index_inverse_2; 112 | 113 | //bloom filter indexes 114 | bit<1> register_cell_one; 115 | bit<1> register_cell_two; 116 | bit<32> register_position_one; 117 | bit<32> register_position_two; 118 | 119 | bit<8> sttl; 120 | bit<8> dttl; 121 | bit<32> srcip; 122 | bit<16> srcport; 123 | bit<16> dstport; 124 | bit<16> hdr_srcport; 125 | bit<16> hdr_dstport; 126 | 127 | bit<32> dpkts; 128 | bit<32> spkts; 129 | bit<32> sbytes; 130 | bit<32> dbytes; 131 | bit<16> ct_srv_dst; 132 | bit<48> tcprtt; 133 | bit<48> syn_time; 134 | bit<48> time_last_pkt; 135 | bit<48> time_first_pkt; 136 | 137 | bit<48> dur; 138 | bit<1> is_first; 139 | bit<1> is_empty; 140 | bit<1> is_hash_collision; 141 | bit<1> first_ack; 142 | 143 | bit<8> state; 144 | bit<8> ct_state_ttl; 145 | bit<1> malware; 146 | bit<1> marked_malware; 147 | 148 | } 149 | 150 | struct headers { 151 | ethernet_t ethernet; 152 | ipv4_t ipv4; 153 | tcp_t tcp; 154 | udp_t udp; 155 | } 156 | 157 | /************************************************************************* 158 | *********************** P A R S E R *********************************** 159 | *************************************************************************/ 160 | 161 | parser MyParser(packet_in packet, 162 | out headers hdr, 163 | inout metadata meta, 164 | inout standard_metadata_t standard_metadata) { 165 | 166 | state start { 167 | transition parse_ethernet; 168 | } 169 | 170 | state parse_ethernet { 171 | packet.extract(hdr.ethernet); 172 | transition select(hdr.ethernet.etherType) { 173 | TYPE_IPV4: parse_ipv4; 174 | default: accept; 175 | } 176 | } 177 | 178 | //TODO parse different types of packets ARP, ICMP etc. 179 | state parse_ipv4 { 180 | packet.extract(hdr.ipv4); 181 | transition select(hdr.ipv4.protocol) { 182 | 6: parse_tcp; 183 | 17: parse_udp; 184 | default: accept; 185 | } 186 | } 187 | state parse_tcp { 188 | packet.extract(hdr.tcp); 189 | transition accept; 190 | } 191 | 192 | state parse_udp { 193 | packet.extract(hdr.udp); 194 | transition accept; 195 | } 196 | 197 | } 198 | 199 | /************************************************************************* 200 | ************ C H E C K S U M V E R I F I C A T I O N ************* 201 | *************************************************************************/ 202 | 203 | control MyVerifyChecksum(inout headers hdr, inout metadata meta) { 204 | apply { } 205 | } 206 | 207 | 208 | /************************************************************************* 209 | ************** I N G R E S S P R O C E S S I N G ******************* 210 | *************************************************************************/ 211 | 212 | control MyIngress(inout headers hdr, 213 | inout metadata meta, 214 | inout standard_metadata_t standard_metadata) { 215 | 216 | 217 | register>(MAX_REGISTER_ENTRIES) bloom_filter; 218 | 219 | //bloomfilter: a query returns either "possibly in set" or "definitely not in set." 220 | //Many more flows are normal than abnormal flows. Thus better performance 221 | //will be by storing abnormal flows 222 | register>(MAX_REGISTER_ENTRIES) reg_blacklisted; 223 | 224 | //Here performance will not be good, but once the filter says definitely not allowed, we are sure. 225 | register>(MAX_REGISTER_ENTRIES) reg_allowed; 226 | register>(MAX_REGISTER_ENTRIES) reg_first_ack; 227 | register>(MAX_REGISTER_ENTRIES) reg_is_empty; 228 | 229 | register>(MAX_REGISTER_ENTRIES) reg_ttl; 230 | register>(MAX_REGISTER_ENTRIES) reg_dttl; 231 | 232 | //Dload will be obtained by reversing the src-dst tuple 233 | register>(MAX_REGISTER_ENTRIES) reg_spkts;//src dst pkt count 234 | 235 | register>(MAX_REGISTER_ENTRIES) reg_dpkts;//src dst pkt count 236 | 237 | //Reg not needed for state_INT 238 | register>(MAX_REGISTER_ENTRIES) reg_sbytes;//src dst byte count 239 | register>(MAX_REGISTER_ENTRIES) reg_dbytes;//src dst byte count 240 | 241 | //sum of TCP connection setup time : sum of synack and ackdat time 242 | 243 | register>(8) reg_ct_srv_dst;//Number of connections that contain the same service and srcip in last 100 connections 244 | //Note that only 8 possibilities: http, ftp, smtp, ssh, dns, ftp-data ,irc and (-) if not much used service 245 | //Register not needed for dsport 246 | //dttl, Dpkts, dmeansz, Dload will be obtained by reversing the src-dst tuple 247 | 248 | //Registers for identifying the flow more apart from hash we may use source port 249 | register>(MAX_REGISTER_ENTRIES) reg_srcip; 250 | register>(MAX_REGISTER_ENTRIES) reg_srcport; 251 | register>(MAX_REGISTER_ENTRIES) reg_dstport; 252 | 253 | register>(MAX_REGISTER_ENTRIES) reg_marked_malware; 254 | 255 | 256 | 257 | register>(MAX_REGISTER_ENTRIES) reg_time_last_pkt; 258 | register>(MAX_REGISTER_ENTRIES) reg_time_first_pkt; 259 | register>(MAX_REGISTER_ENTRIES) reg_syn_time; 260 | register>(MAX_REGISTER_ENTRIES) reg_tcprtt; 261 | 262 | //Store some statistics for the experiment 263 | counter(1, CounterType.packets) counter_hash_collisions; 264 | counter(1, CounterType.packets) counter_pkts; 265 | counter(1, CounterType.packets) counter_malware; 266 | counter(1, CounterType.packets) counter_true_detection; 267 | counter(1, CounterType.packets) counter_false_detection; 268 | counter(1, CounterType.packets) counter_flows; 269 | counter(1, CounterType.packets) counter_malware_flows; 270 | counter(1, CounterType.packets) counter_true_detection_flows; 271 | counter(1, CounterType.packets) counter_false_detection_flows; 272 | counter(1, CounterType.packets) counter_timeout; 273 | 274 | action init_register() { 275 | //intialise the registers to 0 276 | reg_time_last_pkt.write(meta.register_index, 0); 277 | reg_srcip.write(meta.register_index, 0); 278 | reg_srcport.write(meta.register_index, 0); 279 | reg_dstport.write(meta.register_index, 0); 280 | reg_ttl.write(meta.register_index, 0); 281 | reg_dttl.write(meta.register_index, 0); 282 | reg_spkts.write(meta.register_index, 0); 283 | reg_sbytes.write(meta.register_index, 0); 284 | reg_dpkts.write(meta.register_index, 0); 285 | reg_dbytes.write(meta.register_index, 0); 286 | reg_syn_time.write(meta.register_index, 0); 287 | reg_tcprtt.write(meta.register_index, 0); 288 | reg_marked_malware.write(meta.register_index, 0); 289 | } 290 | 291 | action get_register_index_tcp() { 292 | //Get register position 293 | hash(meta.register_index, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.srcAddr, 294 | hdr.ipv4.dstAddr, 295 | hdr.tcp.srcPort, 296 | hdr.tcp.dstPort, 297 | hdr.ipv4.protocol}, 298 | (bit<32>)MAX_REGISTER_ENTRIES); 299 | 300 | hash(meta.register_index_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.srcAddr, 301 | hdr.ipv4.dstAddr, 302 | hdr.tcp.srcPort, 303 | hdr.tcp.dstPort, 304 | hdr.ipv4.protocol}, 305 | (bit<32>)MAX_REGISTER_ENTRIES); 306 | } 307 | 308 | action get_register_index_udp() { 309 | hash(meta.register_index, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.srcAddr, 310 | hdr.ipv4.dstAddr, 311 | hdr.udp.srcPort, 312 | hdr.udp.dstPort, 313 | hdr.ipv4.protocol}, 314 | (bit<32>)MAX_REGISTER_ENTRIES); 315 | 316 | hash(meta.register_index_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.srcAddr, 317 | hdr.ipv4.dstAddr, 318 | hdr.udp.srcPort, 319 | hdr.udp.dstPort, 320 | hdr.ipv4.protocol}, 321 | (bit<32>)MAX_REGISTER_ENTRIES); 322 | } 323 | 324 | action get_register_index_inverse_tcp() { 325 | //Get register position for the same flow in another directon 326 | // just inverse the src and dst 327 | hash(meta.register_index_inverse, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.dstAddr, 328 | hdr.ipv4.srcAddr, 329 | hdr.tcp.dstPort, 330 | hdr.tcp.srcPort, 331 | hdr.ipv4.protocol}, 332 | (bit<32>)MAX_REGISTER_ENTRIES); 333 | 334 | hash(meta.register_index_inverse_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.dstAddr, 335 | hdr.ipv4.srcAddr, 336 | hdr.tcp.dstPort, 337 | hdr.tcp.srcPort, 338 | hdr.ipv4.protocol}, 339 | (bit<32>)MAX_REGISTER_ENTRIES); 340 | } 341 | 342 | action get_register_index_inverse_udp() { 343 | hash(meta.register_index_inverse, HashAlgorithm.crc16, (bit<16>)0, {hdr.ipv4.dstAddr, 344 | hdr.ipv4.srcAddr, 345 | hdr.udp.dstPort, 346 | hdr.udp.srcPort, 347 | hdr.ipv4.protocol}, 348 | (bit<32>)MAX_REGISTER_ENTRIES); 349 | 350 | hash(meta.register_index_inverse_2, HashAlgorithm.crc32, (bit<16>)0, {hdr.ipv4.dstAddr, 351 | hdr.ipv4.srcAddr, 352 | hdr.udp.dstPort, 353 | hdr.ipv4.protocol}, 354 | (bit<32>)MAX_REGISTER_ENTRIES); 355 | } 356 | 357 | action set_allowed(){ 358 | //set bloom filter fields 359 | bloom_filter.write(meta.register_position_one, 1); 360 | bloom_filter.write(meta.register_position_two, 1); 361 | } 362 | 363 | action check_if_allowed(){ 364 | //Read bloom filter cells to check if there are 1's 365 | bloom_filter.read(meta.register_cell_one, meta.register_position_one); 366 | bloom_filter.read(meta.register_cell_two, meta.register_position_two); 367 | } 368 | 369 | action drop() { 370 | mark_to_drop(standard_metadata); 371 | } 372 | 373 | //we plan to use the following features for the moment 374 | //sttl ct_state_ttl dttl Sload Dpkts dmeansz state_INT sbytes sload smeansz tcprtt dsport dur ct_srv_dst 375 | 376 | //1.* sttl there by default 377 | //2. ct_state_ttl **to be called after sttl and dttl calc 378 | 379 | action calc_state() { 380 | //When Sload or Dload is 0 the state can be INT 381 | //Thus need to calculate sload, dload before 382 | // XX TODO Argus log shows only last state! 383 | //XX TODO The following logic is only approx. correct! 384 | if ((meta.is_first == 1)||(meta.dttl == 0)) { 385 | if (hdr.ipv4.protocol == 6) //TCP 386 | meta.state = STATE_REQ; 387 | else meta.state = STATE_INT; 388 | } 389 | else { 390 | if (hdr.ipv4.protocol == 6) //TCP 391 | meta.state = STATE_EST; 392 | else meta.state = STATE_CON; 393 | } 394 | //TODO for STATE_FIN, which may not be useful as it would be last packet of transaction 395 | if (hdr.ipv4.protocol == 6 && hdr.tcp.fin == (bit<1>)1) { 396 | meta.state = STATE_FIN; 397 | } 398 | } 399 | 400 | action calc_ct_state_ttl(){ 401 | 402 | meta.ct_state_ttl = 0; 403 | if ((meta.sttl == 62 || meta.sttl == 63 || meta.sttl == 254 || meta.sttl == 255) 404 | && (meta.dttl == 252 || meta.dttl == 253) && meta.state == STATE_FIN) { 405 | meta.ct_state_ttl = 1; 406 | } 407 | else if ((meta.sttl == 0 || meta.sttl == 62 || meta.sttl == 254) 408 | && (meta.dttl == 0) && meta.state == STATE_INT) { 409 | meta.ct_state_ttl = 2; 410 | } 411 | else if((meta.sttl == 62 || meta.sttl == 254) 412 | && (meta.dttl == 60 || meta.dttl == 252 || meta.dttl == 253) 413 | && meta.state == STATE_CON){ 414 | meta.ct_state_ttl = 3; 415 | } 416 | else if((meta.sttl == 254) && (meta.dttl == 252) && meta.state == STATE_ACC){ 417 | meta.ct_state_ttl = 4; 418 | } 419 | else if((meta.sttl == 254) && (meta.dttl == 252) && meta.state == STATE_CLO){ 420 | meta.ct_state_ttl = 5; 421 | } 422 | else if((meta.sttl == 254) && (meta.dttl == 0) && meta.state == STATE_REQ){ 423 | meta.ct_state_ttl = 7; 424 | } 425 | else { 426 | meta.ct_state_ttl = 0; 427 | } 428 | } 429 | 430 | action read_ct_srv_dst() { 431 | //TODO XX The following is just for test 432 | //No. of connections that contain the same service (14) (ftp, http, ..) and destination address (3) (ipaddress) in 100 connections according to the last time (26). 433 | 434 | meta.ct_srv_dst = 10; 435 | } 436 | 437 | 438 | action init_features() { 439 | //they will be updated when needed 440 | //or easy but a bit slow: to read them now 441 | //feature order can be changed flexibly using registers configurable from control plane, etc. 442 | 443 | // In the traces bitrate = int(smeanz)*(totalpkts - 1)*8/dur 444 | //We will compare sbytes*(totalpkts - 1)*8 > th*dur*spkts; 445 | 446 | meta.feature1 = (bit<64>)meta.sttl;//sttl 447 | meta.feature2 = (bit<64>)meta.ct_state_ttl;//ct_state_ttl 448 | meta.feature3 = (bit<64>)meta.dttl;//dttl 449 | meta.feature4 = (bit<64>)(meta.sbytes*(meta.spkts - 1)*8) ;//needed for Sload 450 | meta.feature5 = (bit<64>)meta.dpkts;//dpkts 451 | meta.feature6 = (bit<64>)meta.dbytes;//Needed for dmeansz 452 | meta.feature7 = (bit<64>)meta.sbytes;//sbytes 453 | meta.feature8 = (bit<64>)(meta.dbytes*(meta.dpkts - 1)*8);//Needed for dload 454 | meta.feature9 = (bit<64>)meta.sbytes;//needed for smeansz 455 | meta.feature10 = (bit<64>)meta.tcprtt;//tcprtt 456 | meta.feature11 = (bit<64>)meta.dstport;//dstport 457 | meta.feature12 = (bit<64>)meta.dur;//dur 458 | 459 | meta.class = CLASS_NOT_SET; 460 | } 461 | 462 | action CheckFeature(bit<16> node_id, bit<16> f_inout, bit<64> threshold) { 463 | //XX For dur and tcprtt are in microseconds! Thus multiplied by 1000000 if in seconds! 464 | //XX For rate comparisons 'th' is multiplied by time delta as division is not allowed 465 | 466 | bit<64> feature = 0; 467 | bit<64> th = threshold; 468 | bit<16> f = f_inout + 1; 469 | 470 | if (f == 1) { 471 | 472 | feature = meta.feature1; 473 | } 474 | else if (f == 2) { 475 | feature = meta.feature2; 476 | } 477 | else if (f == 3) { 478 | feature = meta.feature3; 479 | } 480 | else if (f == 4) { 481 | feature = meta.feature4*1000000; 482 | th = th*(bit<64>)meta.dur*(bit<64>)meta.sbytes; 483 | } 484 | else if (f == 5) { 485 | feature = meta.feature5; 486 | } 487 | else if (f == 6) { 488 | feature = meta.feature6; 489 | th = th*(bit<64>)meta.dpkts; 490 | } 491 | else if (f == 7) { 492 | feature = meta.feature7; 493 | } 494 | else if (f == 8) { 495 | feature = meta.feature8*1000000; 496 | th = th*(bit<64>)meta.dur*(bit<64>)meta.sbytes; 497 | } 498 | else if (f == 9) { 499 | feature = meta.feature9; 500 | th = th*(bit<64>)meta.spkts; 501 | } 502 | else if (f == 10) { 503 | feature = meta.feature10; 504 | } 505 | else if (f == 11) { 506 | feature = meta.feature11; 507 | } 508 | else if (f == 12) { 509 | feature = meta.feature12; 510 | } 511 | 512 | if (feature <= th) meta.isTrue = 1; 513 | else meta.isTrue = 0; 514 | 515 | meta.prevFeature = f - 1; 516 | 517 | meta.node_id = node_id; 518 | } 519 | 520 | action SetClass(bit<16> node_id, bit<16> class) { 521 | meta.class = class; 522 | meta.node_id = node_id; //just for debugging otherwise not needed 523 | } 524 | 525 | action SetDirection() { 526 | //need just for this setting as tcpreplay is sending all the packets to same interface 527 | meta.direction = 1; 528 | } 529 | 530 | action SetMalware() { 531 | //need just for this setting as tcpreplay is sending all the packets to same interface 532 | meta.malware = 1; 533 | } 534 | 535 | 536 | action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { 537 | standard_metadata.egress_spec = port; 538 | hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 539 | hdr.ethernet.dstAddr = dstAddr; 540 | hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 541 | } 542 | 543 | 544 | 545 | table direction{ 546 | key = { 547 | hdr.ipv4.dstAddr: lpm; 548 | } 549 | actions = { 550 | NoAction; 551 | SetDirection; 552 | } 553 | size = 10; 554 | default_action = NoAction(); 555 | } 556 | 557 | table malware{ //For debugging 558 | key = { 559 | hdr.ipv4.srcAddr: lpm; 560 | } 561 | actions = { 562 | NoAction; 563 | SetMalware; 564 | } 565 | size = 10; 566 | default_action = NoAction(); 567 | } 568 | 569 | table malware_inverse { //For debugging 570 | key = { 571 | hdr.ipv4.dstAddr: lpm; 572 | } 573 | actions = { 574 | NoAction; 575 | SetMalware; 576 | } 577 | size = 10; 578 | default_action = NoAction(); 579 | } 580 | 581 | 582 | table level1{ 583 | key = { 584 | meta.node_id: exact; 585 | meta.prevFeature: exact; 586 | meta.isTrue: exact; 587 | } 588 | actions = { 589 | NoAction; 590 | CheckFeature; 591 | SetClass; 592 | } 593 | size = 1024; 594 | } 595 | 596 | table level2{ 597 | key = { 598 | meta.node_id: exact; 599 | meta.prevFeature: exact; 600 | meta.isTrue: exact; 601 | } 602 | actions = { 603 | NoAction; 604 | CheckFeature; 605 | SetClass; 606 | } 607 | size = 1024; 608 | } 609 | 610 | table level3{ 611 | key = { 612 | meta.node_id: exact; 613 | meta.prevFeature: exact; 614 | meta.isTrue: exact; 615 | } 616 | actions = { 617 | NoAction; 618 | CheckFeature; 619 | SetClass; 620 | } 621 | size = 1024; 622 | } 623 | table level4{ 624 | key = { 625 | meta.node_id: exact; 626 | meta.prevFeature: exact; 627 | meta.isTrue: exact; 628 | } 629 | actions = { 630 | NoAction; 631 | CheckFeature; 632 | SetClass; 633 | } 634 | size = 1024; 635 | } 636 | 637 | table level5{ 638 | key = { 639 | meta.node_id: exact; 640 | meta.prevFeature: exact; 641 | meta.isTrue: exact; 642 | } 643 | actions = { 644 | NoAction; 645 | CheckFeature; 646 | SetClass; 647 | } 648 | size = 1024; 649 | } 650 | 651 | table level6{ 652 | key = { 653 | meta.node_id: exact; 654 | meta.prevFeature: exact; 655 | meta.isTrue: exact; 656 | } 657 | actions = { 658 | NoAction; 659 | CheckFeature; 660 | SetClass; 661 | } 662 | size = 1024; 663 | } 664 | 665 | table level7{ 666 | key = { 667 | meta.node_id: exact; 668 | meta.prevFeature: exact; 669 | meta.isTrue: exact; 670 | } 671 | actions = { 672 | NoAction; 673 | CheckFeature; 674 | SetClass; 675 | } 676 | size = 1024; 677 | } 678 | 679 | table level8{ 680 | key = { 681 | meta.node_id: exact; 682 | meta.prevFeature: exact; 683 | meta.isTrue: exact; 684 | } 685 | actions = { 686 | NoAction; 687 | CheckFeature; 688 | SetClass; 689 | } 690 | size = 1024; 691 | } 692 | 693 | table level9{ 694 | key = { 695 | meta.node_id: exact; 696 | meta.prevFeature: exact; 697 | meta.isTrue: exact; 698 | } 699 | actions = { 700 | NoAction; 701 | CheckFeature; 702 | SetClass; 703 | } 704 | size = 1024; 705 | } 706 | 707 | table level10{ 708 | key = { 709 | meta.node_id: exact; 710 | meta.prevFeature: exact; 711 | meta.isTrue: exact; 712 | } 713 | actions = { 714 | NoAction; 715 | CheckFeature; 716 | SetClass; 717 | } 718 | size = 1024; 719 | } 720 | 721 | table level11{ 722 | key = { 723 | meta.node_id: exact; 724 | meta.prevFeature: exact; 725 | meta.isTrue: exact; 726 | } 727 | actions = { 728 | NoAction; 729 | CheckFeature; 730 | SetClass; 731 | } 732 | size = 1024; 733 | } 734 | 735 | 736 | 737 | /* This will send the packet to a specifique port of the switch for output*/ 738 | table ipv4_exact { 739 | key = { 740 | meta.class: exact; 741 | } 742 | actions = { 743 | ipv4_forward; 744 | drop; 745 | NoAction; 746 | } 747 | size = 1024; 748 | default_action = drop(); 749 | } 750 | 751 | table debug{ 752 | key = { 753 | meta.feature1: exact; 754 | meta.feature2: exact; 755 | meta.feature3: exact; 756 | meta.feature4: exact; 757 | meta.feature5: exact; 758 | meta.feature6: exact; 759 | meta.feature7: exact; 760 | meta.feature8: exact; 761 | meta.feature9: exact; 762 | meta.feature10: exact; 763 | meta.feature11: exact; 764 | meta.feature12: exact; 765 | meta.state: exact; 766 | meta.spkts: exact; 767 | meta.is_first: exact; 768 | hdr.ipv4.dstAddr: exact; 769 | meta.hdr_srcport: exact; 770 | meta.hdr_dstport: exact; 771 | standard_metadata.ingress_global_timestamp: exact; 772 | meta.syn_time: exact; 773 | meta.register_index: exact; 774 | meta.register_index_inverse: exact; 775 | meta.direction: exact; 776 | meta.is_hash_collision: exact; 777 | meta.malware: exact; 778 | meta.marked_malware: exact; 779 | meta.class: exact; 780 | meta.sbytes: exact; 781 | } 782 | actions = { 783 | NoAction; 784 | } 785 | size = 1024; 786 | } 787 | 788 | 789 | //Invoke the tables using the apply method 790 | 791 | apply { 792 | 793 | /*check the direction of packets going. 794 | For UNSW data, the emulation configuration is as follows 795 | Outside: 796 | 59.166.0.0 normal 797 | 175.45.176.0 malware 798 | Inside: 799 | 149.171.126.0 800 | Thus, mostly track 59.166.0.0/175.45.176.0 ---> 149.171.126.0 packets 801 | */ 802 | 803 | //count all the packets 804 | direction.apply(); 805 | counter_pkts.count(0); 806 | 807 | if ( hdr.ipv4.isValid()) { 808 | //Calculate all features 809 | //TODO optimize : feature needs to be calculated only if needed 810 | 811 | if (hdr.ipv4.protocol == 6 || hdr.ipv4.protocol == 17) {//We treat only TCP or UDP packets 812 | 813 | if (meta.direction == 1) { 814 | 815 | if (hdr.ipv4.protocol == 6) { 816 | get_register_index_tcp(); 817 | meta.hdr_srcport = hdr.tcp.srcPort; 818 | meta.hdr_dstport = hdr.tcp.dstPort; 819 | } 820 | else { 821 | get_register_index_udp(); 822 | meta.hdr_srcport = hdr.udp.srcPort; 823 | meta.hdr_dstport = hdr.udp.dstPort; 824 | 825 | } 826 | 827 | //read_reg_to_check_collision srcip, srcport, dstport 828 | reg_srcip.read(meta.srcip, meta.register_index); 829 | reg_srcport.read(meta.srcport, meta.register_index); 830 | reg_dstport.read(meta.dstport, meta.register_index); 831 | reg_time_last_pkt.read(meta.time_last_pkt, (bit<32>)meta.register_index); 832 | 833 | if (meta.srcip == 0) {//It was an empty register 834 | meta.is_first = 1; 835 | } 836 | else if ((standard_metadata.ingress_global_timestamp - meta.time_last_pkt) > FLOW_TIMEOUT) { 837 | /*We havent heard from this flow it has been FLOW_TIMEOUT 838 | We will initialse the register space 839 | TODO check if init_register() is initialising all and only those needed. ; 840 | */ 841 | init_register(); 842 | counter_timeout.count(0); 843 | meta.is_first = 1; 844 | } 845 | else if (meta.srcip != hdr.ipv4.srcAddr || meta.srcport != meta.hdr_srcport 846 | || meta.dstport != meta.hdr_dstport) { 847 | //Hash collision! 848 | //TODO handle hash collisions in a better way! 849 | meta.is_hash_collision = 1; 850 | counter_hash_collisions.count(0); 851 | } 852 | 853 | if (meta.is_hash_collision == 0) { 854 | 855 | if (meta.is_first == 1) { 856 | meta.time_first_pkt = standard_metadata.ingress_global_timestamp; 857 | reg_time_first_pkt.write((bit<32>)meta.register_index, meta.time_first_pkt); 858 | reg_srcip.write((bit<32>)meta.register_index, hdr.ipv4.srcAddr); 859 | reg_srcport.write((bit<32>)meta.register_index, meta.hdr_srcport); 860 | reg_dstport.write((bit<32>)meta.register_index, meta.hdr_dstport); 861 | counter_flows.count(0); 862 | } 863 | 864 | reg_spkts.read(meta.spkts, (bit<32>)meta.register_index); 865 | meta.spkts = meta.spkts + 1; 866 | reg_spkts.write((bit<32>)meta.register_index, meta.spkts); 867 | 868 | meta.sttl = hdr.ipv4.ttl; 869 | reg_ttl.write((bit<32>)meta.register_index, meta.sttl); 870 | 871 | reg_dttl.read(meta.dttl, (bit<32>)meta.register_index); 872 | 873 | 874 | //read_sbytes also used for sload 875 | reg_sbytes.read(meta.sbytes, (bit<32>)meta.register_index); 876 | meta.sbytes = meta.sbytes + standard_metadata.packet_length - 14; 877 | reg_sbytes.write((bit<32>)meta.register_index, meta.sbytes); 878 | 879 | 880 | // tcprtt 881 | //SYN TIME 882 | if ((hdr.tcp.ack != (bit<1>)1)&&(hdr.tcp.syn == (bit<1>)1)) {//this is a SYN 883 | reg_syn_time.write((bit<32>)meta.register_index, 884 | standard_metadata.ingress_global_timestamp); 885 | } 886 | //ACK + SYN time 887 | else if ((hdr.tcp.ack == (bit<1>)1)&&(hdr.tcp.syn != (bit<1>)1)) {//this is an ACK 888 | 889 | reg_first_ack.read(meta.first_ack, (bit<32>)meta.register_index); 890 | if (meta.first_ack == 0) { 891 | //sum of synack(SYN to SYN_ACK time) and ackdat(SYN_ACK to ACK time) 892 | reg_syn_time.read(meta.syn_time, (bit<32>)meta.register_index); 893 | if (meta.syn_time > 0) {//There was a syn before 894 | meta.tcprtt = standard_metadata.ingress_global_timestamp - meta.syn_time; 895 | reg_tcprtt.write((bit<32>)meta.register_index, meta.tcprtt); 896 | //no longer a first ack 897 | reg_first_ack.write((bit<32>)meta.register_index, 1); 898 | } 899 | } 900 | } 901 | 902 | 903 | //read all reverse flow features 904 | reg_dbytes.read(meta.dbytes, (bit<32>)meta.register_index); 905 | reg_dpkts.read(meta.dpkts, (bit<32>)meta.register_index); 906 | 907 | }//hash collision check 908 | 909 | }//end of direction = 1 910 | 911 | else {//direction = 0 912 | 913 | //TODO some flows can be marked malware even after analysing return flow! 914 | 915 | if (hdr.ipv4.protocol == 6) { 916 | get_register_index_inverse_tcp(); 917 | meta.hdr_srcport = hdr.tcp.dstPort;//its inverse 918 | meta.hdr_dstport = hdr.tcp.srcPort; 919 | } 920 | else { 921 | //TODO what if it is neither TCP nor UDP? 922 | get_register_index_inverse_udp(); 923 | meta.hdr_srcport = hdr.udp.dstPort; 924 | meta.hdr_dstport = hdr.udp.srcPort; 925 | 926 | } 927 | 928 | meta.register_index = meta.register_index_inverse; 929 | 930 | //read_reg_to_check_collision srcip, srcport, dstport 931 | reg_srcip.read(meta.srcip, meta.register_index); 932 | reg_srcport.read(meta.srcport, meta.register_index); 933 | reg_dstport.read(meta.dstport, meta.register_index); 934 | reg_time_last_pkt.read(meta.time_last_pkt, (bit<32>)meta.register_index); 935 | 936 | if (meta.srcip == 0) {//It was an empty register 937 | meta.is_first = 1; 938 | } 939 | else if ((standard_metadata.ingress_global_timestamp - meta.time_last_pkt) > FLOW_TIMEOUT) { 940 | /*We havent heard from this flow it has been FLOW_TIMEOUT 941 | We will initialse the register space 942 | TODO check if init_register() is initialising all and only those needed. ; 943 | */ 944 | init_register(); 945 | counter_timeout.count(0); 946 | meta.is_first = 1; 947 | } 948 | else if (meta.srcip != hdr.ipv4.dstAddr || meta.srcport != meta.hdr_srcport 949 | || meta.dstport != meta.hdr_dstport) { 950 | //Hash collision! 951 | //TODO handle hash collisions in a better way! 952 | meta.is_hash_collision = 1; 953 | counter_hash_collisions.count(0); 954 | } 955 | 956 | if (meta.is_hash_collision == 0) { 957 | 958 | if (meta.is_first == 1) {//shouldn't happen! 959 | meta.time_first_pkt = standard_metadata.ingress_global_timestamp; 960 | reg_time_first_pkt.write((bit<32>)meta.register_index, meta.time_first_pkt); 961 | reg_srcip.write((bit<32>)meta.register_index, hdr.ipv4.dstAddr); 962 | reg_srcport.write((bit<32>)meta.register_index, meta.hdr_srcport); 963 | reg_dstport.write((bit<32>)meta.register_index, meta.hdr_dstport); 964 | 965 | } 966 | 967 | //dpkts and dload 968 | reg_dpkts.read(meta.dpkts, (bit<32>)meta.register_index); 969 | meta.dpkts = meta.dpkts + 1; 970 | reg_dpkts.write((bit<32>)meta.register_index, meta.dpkts); 971 | 972 | //dbytes 973 | reg_dbytes.read(meta.dbytes, (bit<32>)meta.register_index); 974 | meta.dbytes = meta.dbytes + standard_metadata.packet_length - 14; 975 | reg_dbytes.write((bit<32>)meta.register_index, meta.dbytes); 976 | 977 | reg_time_last_pkt.write((bit<32>)meta.register_index, 978 | standard_metadata.ingress_global_timestamp ); 979 | 980 | //Read other features from the sources to destination direction 981 | meta.dttl = hdr.ipv4.ttl; 982 | reg_dttl.write((bit<32>)meta.register_index, meta.dttl); 983 | reg_ttl.read(meta.sttl, (bit<32>)meta.register_index); 984 | reg_sbytes.read(meta.sbytes, (bit<32>)meta.register_index); 985 | reg_spkts.read(meta.spkts, (bit<32>)meta.register_index); 986 | 987 | }//hash collision check 988 | 989 | } // end of direction = 0 990 | 991 | //Read common features 992 | 993 | if (meta.is_hash_collision == 0) { 994 | //TODO on hash collision we are letting the flow pass 995 | //We can also do a false detection! 996 | 997 | reg_tcprtt.read(meta.tcprtt, (bit<32>)meta.register_index); 998 | reg_time_first_pkt.read(meta.time_first_pkt, (bit<32>)meta.register_index); 999 | meta.dur = standard_metadata.ingress_global_timestamp - meta.time_first_pkt; 1000 | 1001 | reg_time_last_pkt.write((bit<32>)meta.register_index, 1002 | standard_metadata.ingress_global_timestamp ); 1003 | 1004 | 1005 | calc_state(); 1006 | calc_ct_state_ttl(); 1007 | read_ct_srv_dst(); 1008 | 1009 | init_features(); 1010 | 1011 | 1012 | //start with parent node of decision tree 1013 | meta.prevFeature = 0; 1014 | meta.isTrue = 1; 1015 | 1016 | reg_marked_malware.read(meta.marked_malware, (bit<32>)meta.register_index); 1017 | 1018 | 1019 | if (meta.direction == 1) { 1020 | malware.apply();//For statistics 1021 | } 1022 | else { 1023 | malware_inverse.apply();//For statistics 1024 | } 1025 | 1026 | if (meta.marked_malware == 1) { 1027 | meta.class = 1;//No need to check again! 1028 | } 1029 | else { 1030 | level1.apply(); 1031 | 1032 | if (meta.class == CLASS_NOT_SET) { 1033 | level2.apply(); 1034 | if (meta.class == CLASS_NOT_SET) { 1035 | level3.apply(); 1036 | if (meta.class == CLASS_NOT_SET) { 1037 | level4.apply(); 1038 | if (meta.class == CLASS_NOT_SET) { 1039 | level5.apply(); 1040 | if (meta.class == CLASS_NOT_SET) { 1041 | level6.apply(); 1042 | if (meta.class == CLASS_NOT_SET) { 1043 | level7.apply(); 1044 | if (meta.class == CLASS_NOT_SET) { 1045 | level8.apply(); 1046 | if (meta.class == CLASS_NOT_SET) { 1047 | level9.apply(); 1048 | if (meta.class == CLASS_NOT_SET) { 1049 | level10.apply(); 1050 | if (meta.class == CLASS_NOT_SET) 1051 | level11.apply(); 1052 | }}}}}}}}} 1053 | } 1054 | 1055 | if (meta.malware == 1) {// meta.malware is calculated with priori knowledge for statistics 1056 | 1057 | counter_malware.count(0); 1058 | 1059 | if (meta.is_first == 1) { 1060 | counter_malware_flows.count(0); 1061 | } 1062 | 1063 | if(meta.class == 1) { 1064 | counter_true_detection.count(0); 1065 | 1066 | if (meta.marked_malware == 0) { 1067 | //We detect the flow as malware first time! 1068 | counter_true_detection_flows.count(0); 1069 | } 1070 | reg_marked_malware.write((bit<32>)meta.register_index,1); 1071 | } 1072 | } 1073 | else { 1074 | if(meta.class == 1) { 1075 | counter_false_detection.count(0); 1076 | 1077 | if (meta.marked_malware == 0) { 1078 | //We detect the flow as malware first time! even if false 1079 | counter_false_detection_flows.count(0); 1080 | } 1081 | reg_marked_malware.write((bit<32>)meta.register_index,1); 1082 | } 1083 | } 1084 | 1085 | }//hash collision check 1086 | 1087 | debug.apply(); 1088 | 1089 | 1090 | 1091 | }//End of if (hdr.ipv4.protocol == 6 || hdr.ipv4.protocol == 17) 1092 | 1093 | ipv4_exact.apply(); 1094 | 1095 | }//End of if hdr.ipv4.isValid() 1096 | 1097 | }//End of apply 1098 | } 1099 | 1100 | /************************************************************************* 1101 | **************** E G R E S S P R O C E S S I N G ******************* 1102 | *************************************************************************/ 1103 | 1104 | control MyEgress(inout headers hdr, 1105 | inout metadata meta, 1106 | inout standard_metadata_t standard_metadata) { 1107 | apply { } 1108 | } 1109 | 1110 | /************************************************************************* 1111 | ************* C H E C K S U M C O M P U T A T I O N ************** 1112 | *************************************************************************/ 1113 | 1114 | control MyComputeChecksum(inout headers hdr, inout metadata meta) { 1115 | apply { 1116 | update_checksum( 1117 | hdr.ipv4.isValid(), 1118 | { hdr.ipv4.version, 1119 | hdr.ipv4.ihl, 1120 | hdr.ipv4.diffserv, 1121 | hdr.ipv4.totalLen, 1122 | hdr.ipv4.identification, 1123 | hdr.ipv4.flags, 1124 | hdr.ipv4.fragOffset, 1125 | hdr.ipv4.ttl, 1126 | hdr.ipv4.protocol, 1127 | hdr.ipv4.srcAddr, 1128 | hdr.ipv4.dstAddr }, 1129 | hdr.ipv4.hdrChecksum, 1130 | HashAlgorithm.csum16); 1131 | } 1132 | } 1133 | 1134 | /************************************************************************* 1135 | 1136 | *********************** D E P A R S E R ******************************* 1137 | *************************************************************************/ 1138 | 1139 | control MyDeparser(packet_out packet, in headers hdr) { 1140 | apply { 1141 | packet.emit(hdr.ethernet); 1142 | packet.emit(hdr.ipv4); 1143 | packet.emit(hdr.tcp); 1144 | } 1145 | } 1146 | 1147 | /************************************************************************* 1148 | *********************** S W I T C H ******************************* 1149 | *************************************************************************/ 1150 | 1151 | V1Switch( 1152 | MyParser(), 1153 | MyVerifyChecksum(), 1154 | MyIngress(), 1155 | MyEgress(), 1156 | MyComputeChecksum(), 1157 | MyDeparser() 1158 | ) main; 1159 | -------------------------------------------------------------------------------- /topology.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosts": [ 3 | "h1", 4 | "h2" 5 | ], 6 | "switches": { 7 | "s1": { } 8 | }, 9 | "links": [ 10 | ["h1", "s1"], ["s1", "h2"],["s1", "h3"],["s1", "h4"] 11 | 12 | ] 13 | } --------------------------------------------------------------------------------