├── .travis.yml ├── KNet ├── __init__.py ├── app.py ├── cli │ ├── __init__.py │ ├── __init__.pyc │ ├── commands.py │ ├── commands.pyc │ └── formatter.pyc ├── lib │ ├── __init__.py │ ├── cleanup.sh │ ├── docker_cmds.py │ ├── host.py │ ├── link.py │ ├── logger.py │ ├── networks.py │ ├── ovs_cmds.py │ ├── qos.py │ ├── router.py │ ├── schema.py │ ├── server.py │ ├── switches.py │ ├── tc_cmds.py │ ├── topology.py │ └── utils.py ├── main.py └── test │ ├── __init__.py │ └── testutils.py ├── LICENSE ├── MANIFEST.in ├── README.md ├── docs ├── Makefile ├── cli.rst ├── conf.py ├── docker_commands.rst ├── example_topologies.rst ├── imgs │ ├── KNet_Actions.png │ ├── cli │ │ ├── cleanup_s.png │ │ ├── cli1_s.png │ │ ├── cli2_s.png │ │ ├── cli_deletetopo_s.png │ │ ├── cli_downlink_s.png │ │ ├── cli_gettopo_s.png │ │ ├── cli_help_s.png │ │ ├── cli_ping_s.png │ │ ├── cli_pingall_s.png │ │ └── cli_uplink_s.png │ ├── docker │ │ ├── docker_exit_s.png │ │ ├── docker_iperfs_s.png │ │ ├── docker_psa_s.png │ │ └── docker_shell_s.png │ ├── ovs │ │ ├── ovs_flows_s.png │ │ └── ovs_show_s.png │ ├── prerequisites.png │ ├── quick_start │ │ ├── CLI_CreateTopology_s.png │ │ ├── CLI_Delete_Topology_s.png │ │ ├── CLI_pingall_command_s.png │ │ ├── KNet_install_s.png │ │ ├── Knet_CLI_example_s.png │ │ ├── WebUI_emptypage_s.png │ │ ├── Webui_StarTopology_s.png │ │ ├── knet_cli_start_s.png │ │ ├── knet_install_output_s.png │ │ ├── knet_pip_install_s.png │ │ ├── knet_topology_creation_s.png │ │ ├── knet_ui_install_s.png │ │ ├── ovs_dumpflows_output_s.png │ │ ├── prereq_verification_s.png │ │ ├── prerequisites_s.png │ │ ├── ryu_controller_print_s.png │ │ ├── ryu_install_s.png │ │ ├── ryu_run_l3switch_s.png │ │ ├── startopology_dockerswitch_cmds_s.png │ │ ├── startwebui_s.png │ │ └── ubuntuversion_s.png │ ├── routing_img.png │ ├── topo0.png │ ├── topo1.png │ ├── topo2.png │ ├── topo3.png │ ├── topo4.png │ ├── topo5.png │ ├── topo6.png │ ├── topo7.png │ └── traffic │ │ ├── apache_install_s.png │ │ ├── apache_start_s.png │ │ ├── flow_tables_count_s.png │ │ ├── flow_tables_s.png │ │ ├── iperf_client_output_s.png │ │ ├── iperf_install1_s.png │ │ ├── iperf_install2_s.png │ │ ├── iperf_server_output_s.png │ │ ├── iperf_server_start_s.png │ │ ├── locust_install_s.png │ │ ├── locust_output_s.png │ │ ├── locust_run_s.png │ │ ├── ovs_flows_s.png │ │ ├── ryu_l4_s.png │ │ ├── ryu_s.png │ │ ├── topology_cli_s.png │ │ └── topology_ui_s.png ├── index.rst ├── overview.rst ├── ovs_commands.rst ├── quick_start.rst ├── topology_file.rst ├── traditional_networks.rst └── traffic_tests.rst ├── install.sh ├── setup.cfg └── setup.py /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | install: 5 | - pip install nose 6 | - pip install --process-dependency-links . 7 | script: 8 | - nosetests -------------------------------------------------------------------------------- /KNet/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/KNet/__init__.py -------------------------------------------------------------------------------- /KNet/app.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | 16 | from __future__ import unicode_literals 17 | import sys 18 | import abc 19 | import os 20 | from six import add_metaclass, text_type 21 | from smallcli.libs.shell import Shell 22 | 23 | # main CLI application 24 | 25 | 26 | def knetcli(): 27 | cpath = os.path.dirname(os.path.abspath(__file__)) + "/cli" 28 | print "directory ", cpath 29 | 30 | cprefix = "KNet.cli." 31 | hdr = ''' 32 | **************************************************************** 33 | * * 34 | * Knet Virtual Network Topology Builder - Interactive CLI * 35 | * * 36 | * * 37 | ***************************************************************** 38 | ''' 39 | cli = Shell(appname="KNet-cli", symbol="#", hdr=hdr, cmdpath=cpath, 40 | cmdprefix=cprefix) 41 | cli() 42 | print "exiting" 43 | 44 | # if __name__ == "__main__": 45 | # cli(sys.argv) 46 | -------------------------------------------------------------------------------- /KNet/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/KNet/cli/__init__.py -------------------------------------------------------------------------------- /KNet/cli/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/KNet/cli/__init__.pyc -------------------------------------------------------------------------------- /KNet/cli/commands.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | 16 | from smallcli.commands.base import Command 17 | from KNet.lib.topology import Topology 18 | import sys 19 | import yaml 20 | import traceback 21 | 22 | # Topology object 23 | t = Topology() 24 | 25 | 26 | class Exit(Command): 27 | description = "Exit" 28 | details = ''' 29 | Exit from the shell 30 | Args: None 31 | return: result 32 | Example: Exit 33 | ''' 34 | 35 | def __call__(self, args): 36 | sys.exit() 37 | 38 | 39 | class Version(Command): 40 | description = "Version" 41 | details = ''' 42 | Version of the KNet 43 | Args: None 44 | return: result 45 | Example: Version 46 | ''' 47 | 48 | def __call__(self, args): 49 | return t.version() 50 | 51 | 52 | class TcpTest(Command): 53 | description = "TcpTest" 54 | details = ''' 55 | Runs IPERF TCP test. 56 | Args: source destination Number-of-connections TestTime 57 | return: result 58 | Example: TcpTest a1 a2 1 60 59 | TcpTest a1 a2 10 300 60 | ''' 61 | 62 | def __validate(self, args): 63 | if args and len(args) > 2: 64 | return True 65 | else: 66 | return False 67 | 68 | def __call__(self, args): 69 | if not self.__validate(args): 70 | err = "Error : Input args \n ********* Help **********\n"+TcpTest.details 71 | return err 72 | try: 73 | result = t.tcptest(args[0], args[1], args[2], args[3]) 74 | except Exception as e: 75 | print e.__doc__ 76 | return e.message 77 | return result 78 | 79 | 80 | 81 | class TcpTest_Detach(Command): 82 | description = "TcpTest" 83 | details = ''' 84 | Runs IPERF TCP test in Detach Mode(Start the test and back to the shell). 85 | Args: source destination Number-of-connections TestTime 86 | return: result 87 | Example: TcpTest_Detach a1 a2 1 60 88 | TcpTest_Detach a1 a2 10 300 89 | ''' 90 | 91 | def __validate(self, args): 92 | if args and len(args) > 2: 93 | return True 94 | else: 95 | return False 96 | 97 | def __call__(self, args): 98 | if not self.__validate(args): 99 | err = "Error : Input args \n ********* Help **********\n"+TcpTest.details 100 | return err 101 | try: 102 | result = t.tcptest_detach(args[0], args[1], args[2], args[3]) 103 | except Exception as e: 104 | print e.__doc__ 105 | return e.message 106 | return result 107 | 108 | 109 | class Exec(Command): 110 | description = "Execute commands in the node" 111 | details = ''' 112 | Execute given command in the node. 113 | Args: nodename command to run 114 | return: result 115 | Example: Exec a1 ifconfig 116 | Exec a1 traceroute 10.1.1.2 117 | Exec a1 ping 10.1.1.3 -c 5 118 | ''' 119 | 120 | def __validate(self, args): 121 | if args and len(args) > 1: 122 | return True 123 | else: 124 | return False 125 | 126 | def __call__(self, args): 127 | if not self.__validate(args): 128 | err = "Error : Input args \n ********* Help **********\n"+Exec.details 129 | return err 130 | try: 131 | result = t.run(args) 132 | except Exception as e: 133 | print e.__doc__ 134 | return e.message 135 | return result 136 | 137 | 138 | class UdpTest(Command): 139 | description = "UdpTest" 140 | details = ''' 141 | Runs IPERF UDP test. 142 | Args: source destination Bandwitdh(Mbps) Number-of-connections testtime 143 | return: result 144 | Example: UdTest a1 a2 10 1 10 145 | UdpTest a1 a2 1 1 300 146 | ''' 147 | 148 | def __validate(self, args): 149 | if args and len(args) > 4: 150 | return True 151 | else: 152 | return False 153 | 154 | def __call__(self, args): 155 | if not self.__validate(args): 156 | err = "Error : Input args \n ********* Help **********\n"+UdpTest.details 157 | return err 158 | try: 159 | result = t.udptest(args[0], args[1], args[2], args[3], args[4]) 160 | except Exception as e: 161 | print e.__doc__ 162 | return e.message 163 | return result 164 | 165 | 166 | 167 | 168 | 169 | class UdpTest_Detach(Command): 170 | description = "UdpTest" 171 | details = ''' 172 | Runs IPERF UDP test in Detach Mode. 173 | Args: source destination Bandwitdh(Mbps) Number-of-connections testtime 174 | return: result 175 | Example: UdpTest_Detach a1 a2 10 1 10 176 | UdpTest_Detach a1 a2 1 1 300 177 | ''' 178 | 179 | def __validate(self, args): 180 | if args and len(args) > 4: 181 | return True 182 | else: 183 | return False 184 | 185 | def __call__(self, args): 186 | if not self.__validate(args): 187 | err = "Error : Input args \n ********* Help **********\n"+UdpTest.details 188 | return err 189 | try: 190 | result = t.udptest_detach(args[0], args[1], args[2], args[3], args[4]) 191 | except Exception as e: 192 | print e.__doc__ 193 | return e.message 194 | return result 195 | 196 | 197 | class Cleanup(Command): 198 | description = "Cleanup" 199 | details = ''' 200 | Cleanup the Test Environment, Removes the Nodes, Switches, DB stuff etc 201 | Args: None 202 | return: None 203 | Example: Cleanup 204 | ''' 205 | 206 | def __call__(self, args): 207 | return t.cleanup() 208 | 209 | 210 | class CreateTopology(Command): 211 | description = "Create Topology in SDN Test Bed" 212 | details = ''' 213 | Create a Test Topology in SDN Test bed 214 | Args: Topology filename in absolute path(yaml) 215 | Example: CreateTopology /home/ubuntu/topology1.yaml 216 | ''' 217 | 218 | def __validate(self, args): 219 | if args and len(args) == 1: 220 | return True 221 | else: 222 | return False 223 | 224 | def __call__(self, args): 225 | if not self.__validate(args): 226 | err = "Error : Topology File not given \n ********* Help **********\n"+CreateTopology.details 227 | return err 228 | 229 | try: 230 | with open(args[0]) as fp: 231 | tdata = yaml.load(fp) 232 | except Exception as e: 233 | print e.__doc__ 234 | return e.message 235 | 236 | try: 237 | result = t.create(tdata) 238 | except Exception as e: 239 | print e.__doc__ 240 | return e.message 241 | return result 242 | 243 | 244 | class DeleteTopology(Command): 245 | description = "Delete the Topology in SDN Test Bed" 246 | details = ''' 247 | Delete a Test Topology in SDN Test bed 248 | Args: None 249 | return: result 250 | Example: DeleteTopology 251 | ''' 252 | 253 | def __call__(self, args): 254 | try: 255 | result = t.delete() 256 | except Exception as e: 257 | print e.__doc__ 258 | return e.message 259 | return result 260 | 261 | 262 | class GetTopology(Command): 263 | description = "Get the Topology objects in Detail" 264 | details = ''' 265 | Get the Topology Objects(Nodes, Switchs, Links, QoS) 266 | Args: None 267 | return: result 268 | Example: GetTopology 269 | ''' 270 | 271 | def __call__(self, args): 272 | try: 273 | result = t.get() 274 | except Exception as e: 275 | print e.__doc__ 276 | return e.message 277 | return result 278 | 279 | 280 | class DeleteNode(Command): 281 | description = "Delete the Node in the Topology" 282 | details = ''' 283 | Delete a Node in the Topology 284 | Args: node name 285 | return: result 286 | Example: DeleteNode a1 287 | ''' 288 | 289 | def __call__(self, args): 290 | try: 291 | result = t.deleteNode(args[0]) 292 | except Exception as e: 293 | print e.__doc__ 294 | return e.message 295 | return result 296 | 297 | 298 | class DeleteSwitch(Command): 299 | description = "Delete the Switch in the Topology" 300 | details = ''' 301 | Delete a Switch in the Topology 302 | Args: switch name 303 | return: result 304 | Example: DeleteSwitch switch1 305 | ''' 306 | 307 | def __call__(self, args): 308 | try: 309 | result = t.deleteSwitch(args[0]) 310 | except Exception as e: 311 | print e.__doc__ 312 | return e.message 313 | return result 314 | 315 | 316 | class AdminDownLink(Command): 317 | description = "Admin down the Link" 318 | details = ''' 319 | Admin shut down the link 320 | Args: interface name 321 | return: result 322 | Example: AdminDownLink 6d025ab95ff04_l 323 | ''' 324 | 325 | def __call__(self, args): 326 | try: 327 | result = t.adminDownLink(args[0]) 328 | except Exception as e: 329 | print e.__doc__ 330 | return e.message 331 | return result 332 | 333 | 334 | class AdminUpLink(Command): 335 | description = "Admin up the Link" 336 | details = ''' 337 | Admin up the link 338 | Args: interface name 339 | return: result 340 | Example: AdminUpLink 6d025ab95ff04_l 341 | ''' 342 | 343 | def __call__(self, args): 344 | try: 345 | result = t.adminUpLink(args[0]) 346 | except Exception as e: 347 | print e.__doc__ 348 | return e.message 349 | return result 350 | 351 | 352 | class PingAll(Command): 353 | description = "Ping All nodes with each other" 354 | details = ''' 355 | Initiate the 20 Ping Packets between the nodes. 356 | Args: None 357 | return: result 358 | Example: PingAll 359 | ''' 360 | 361 | def __call__(self, args): 362 | try: 363 | result = t.pingAll() 364 | except Exception as e: 365 | print e.__doc__ 366 | return e.message 367 | return result 368 | 369 | 370 | class Ping(Command): 371 | description = "Ping the soruce node to destination node" 372 | details = ''' 373 | Initiate the 20 Ping Packets between the source node to destination node. 374 | Args: Source Destination 375 | return: result 376 | Example: Ping a1 a2 377 | ''' 378 | 379 | def __validate(self, args): 380 | if args and len(args) == 2: 381 | return True 382 | else: 383 | return False 384 | 385 | def __call__(self, args): 386 | if not self.__validate(args): 387 | err = "Error : Input args \n ********* Help **********\n"+Ping.details 388 | return err 389 | try: 390 | result = t.ping(args[0], args[1]) 391 | except Exception as e: 392 | print e.__doc__ 393 | return e.message 394 | return result 395 | -------------------------------------------------------------------------------- /KNet/cli/commands.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/KNet/cli/commands.pyc -------------------------------------------------------------------------------- /KNet/cli/formatter.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/KNet/cli/formatter.pyc -------------------------------------------------------------------------------- /KNet/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/KNet/lib/__init__.py -------------------------------------------------------------------------------- /KNet/lib/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | #cleaning the docker instances 18 | dockerfile=/tmp/dockers.txt 19 | sudo docker ps -a -q > "$dockerfile" 20 | echo "Cleaning docker instances...." 21 | while read -r line 22 | do 23 | echo "Stoping Docker instance - $line" 24 | sudo docker stop "$line" 25 | echo "Deleting Docker instance - $line" 26 | sudo docker rm "$line" 27 | done < "$dockerfile" 28 | #sudo docker stop $(sudo docker ps -a -q) 29 | #sudo docker rm $(sudo docker ps -a -q) 30 | 31 | 32 | 33 | #cleaning the bridges 34 | echo "Cleaning the Openvswitch bridges ...." 35 | brfile=/tmp/ovsbr.txt 36 | sudo ovs-vsctl show | grep Bridge | cut -d'"' -f2 > "$brfile" 37 | while read -r line 38 | do 39 | echo "Deleting the Openvswitch bridge $line" 40 | sudo ovs-vsctl del-br "$line" 41 | done < "$brfile" 42 | 43 | #cleaning the DB files 44 | echo "Cleaning the DB file ...." 45 | rm -rf /tmp/db.json 46 | 47 | #cleaning the log file 48 | #echo "Remove the log file..." 49 | #cp -rf /tmp/KNet.log /tmp/KNet.log.1 50 | #rm -rf /tmp/KNet.log 51 | 52 | #cleaning the tmp files 53 | rm -rf "$dockerfile" 54 | rm -rf "$brfile" 55 | echo "Cleaning finished....." 56 | 57 | -------------------------------------------------------------------------------- /KNet/lib/docker_cmds.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | import sys 16 | import KNet.lib.utils as utils 17 | import os 18 | from KNet.lib.logger import logger as log 19 | 20 | def create_container(name, img, net="none", cpu="0.1", mem="100m"): 21 | # sudo docker run -itd --name=node1 ubuntu:trusty 22 | n = "--name=" + name 23 | network = "--network=" + net 24 | hostname = "--hostname=" + name 25 | cpus = "--cpus=" + cpu 26 | memory = "--memory=" + mem 27 | cmd = ['sudo', 'docker', 'run', cpus, memory, '--cap-add=NET_ADMIN', '--privileged', 28 | '-itd', hostname, n, network, img] 29 | return utils.run_cmd(cmd) 30 | 31 | 32 | def stop_container(name): 33 | # sudo docker stop node1 34 | cmd = ['sudo', 'docker', 'stop', name] 35 | return utils.run_cmd(cmd) 36 | 37 | 38 | def delete_container(name): 39 | cmd = ['sudo', 'docker', 'rm', name] 40 | return utils.run_cmd(cmd) 41 | 42 | 43 | def run_ping_in_container(name, ip): 44 | # sudo docker exec -it a3 ping 10.20.20.2 -c 5 45 | cmd = ['sudo', 'docker', 'exec', '-t', name, 'ping', '-c', '2', ip] 46 | return utils.run_cmd(cmd) 47 | 48 | def add_static_route(name, subnet, via): 49 | # sudo docker exec -it a3 ip route add 10.20.20.0/24 via 10.10.10.1 50 | cmd = ['sudo', 'docker', 'exec', '-it', name, 'ip', 'route', 'add', 51 | subnet, 'via', via] 52 | return utils.run_cmd(cmd) 53 | 54 | 55 | 56 | def run_iperfs_in_container(name): 57 | # sudo docker exec -it a3 iperf -s & 58 | # note: background process doesnt work in utils.run_cmd 59 | cmd = "sudo docker exec -d " + name + " iperf -s &" 60 | log.debug(cmd) 61 | os.system(cmd) 62 | 63 | def run_iperf_udps_in_container(name): 64 | # sudo docker exec -it a3 iperf -s & 65 | # note: background process doesnt work in utils.run_cmd 66 | cmd = "sudo docker exec -d " + name + " iperf -u -s &" 67 | log.debug(cmd) 68 | os.system(cmd) 69 | 70 | def run_iperf_udpc_in_container(name, serverip, bandwidth, connections, t=30): 71 | # sudo docker exec -it a3 iperf -c 10.10.10.1 -P 5 72 | bandwidth = str(bandwidth) + "m" 73 | cmd = ['sudo', 'docker', 'exec', '-t', name, 'iperf', '-u', '-i', '10', '-c', 74 | serverip, '-b', bandwidth, '-P', connections, '-t', t] 75 | result = utils.run_cmd(cmd) 76 | print result 77 | return 78 | 79 | 80 | def run_iperf_udpc_detach_in_container(name, serverip, bandwidth, connections, t=30): 81 | # sudo docker exec -it a3 iperf -c 10.10.10.1 -P 5 82 | bandwidth = str(bandwidth) + "m" 83 | cmd = ['sudo', 'docker', 'exec', '-d', name, 'iperf', '-u', '-i', '10', '-c', 84 | serverip, '-b', bandwidth, '-P', connections, '-t', t] 85 | return utils.run_cmd(cmd) 86 | 87 | 88 | def run_iperfc_in_container(name, serverip, connections=1, t=30): 89 | # sudo docker exec -it a3 iperf -c 10.10.10.1 -P 5 90 | cmd = ['sudo', 'docker', 'exec', '-t', name, 'iperf', '-i', '10', '-c', 91 | serverip, '-P', connections, '-t', t] 92 | result = utils.run_cmd(cmd) 93 | print result 94 | return 95 | 96 | 97 | def run_iperfc_detach_in_container(name, serverip, connections=1, t=30): 98 | # sudo docker exec -it a3 iperf -c 10.10.10.1 -P 5 99 | cmd = ['sudo', 'docker', 'exec', '-d', name, 'iperf', '-i', '10', '-c', 100 | serverip, '-P', connections, '-t', t] 101 | return utils.run_cmd(cmd) 102 | 103 | 104 | def run_pkill_in_container(name, pname): 105 | # sudo docker exec -it a3 pkill -9 iperf 106 | cmd = ['sudo', 'docker', 'exec', '-t', name, 'pkill', '-9', pname] 107 | return utils.run_cmd(cmd) 108 | 109 | def run_cmd_in_container(args): 110 | cmd = ['sudo', 'docker', 'exec', '-t'] + args 111 | output = utils.run_cmd(cmd) 112 | print output 113 | return 114 | 115 | 116 | # Not used 117 | def verify_image_exits(img): 118 | img_name, img_version = img.split(':') 119 | # sudo docker images ubuntu:trusty 120 | cmd = ['sudo', 'docker', 'images', img] 121 | response = utils.run_cmd(cmd) 122 | # verify the img exists in the output 123 | if img_name in response and img_version in response: 124 | return {"result": "pass", "detail": response} 125 | else: 126 | return {"result": "fail", "detail": response} 127 | -------------------------------------------------------------------------------- /KNet/lib/host.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | from __future__ import unicode_literals 16 | import sys 17 | import abc 18 | from six import add_metaclass, text_type 19 | import KNet.lib.utils as utils 20 | import KNet.lib.docker_cmds as docker 21 | 22 | 23 | @add_metaclass(abc.ABCMeta) 24 | class Host(object): 25 | def __init__(self, data): 26 | self.id = utils.generate_id() 27 | self.name = data["name"] 28 | self.img = data["image"] 29 | self.status = "initialized" 30 | self.interfaces = data["interfaces"] 31 | self.mgmtif = False 32 | if "mgmt-if" in data: 33 | self.mgmtif = data["mgmt-if"] 34 | # DB Updation 35 | self.docid = utils.host_t.insert({'id': self.id, 'name': self.name, 36 | 'img': self.img, 37 | 'interfaces': self.interfaces, 38 | 'status': self.status}) 39 | # print self.docid 40 | 41 | def create(self): 42 | # sudo docker run -itd --name=node1 ubuntu:trusty 43 | #self.uuid = docker.create_container(self.name, self.img) 44 | 45 | if self.mgmtif is True: 46 | self.uuid = docker.create_container(self.name, self.img, 47 | net="bridge") 48 | else: 49 | self.uuid = docker.create_container(self.name, self.img) 50 | 51 | self.status = "created" 52 | # update the status in DB 53 | utils.host_t.update({'status': self.status}, doc_ids=[self.docid]) 54 | 55 | def delete(self): 56 | docker.stop_container(self.name) 57 | docker.delete_container(self.name) 58 | self.status = "deleted" 59 | # update the status in DB 60 | utils.host_t.remove(doc_ids=[self.docid]) 61 | 62 | def get(self): 63 | return utils.host_t.get(doc_id=self.docid) 64 | -------------------------------------------------------------------------------- /KNet/lib/link.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | from __future__ import unicode_literals 16 | import sys 17 | import abc 18 | from six import add_metaclass, text_type 19 | import KNet.lib.utils as utils 20 | import KNet.lib.ovs_cmds as ovs 21 | import KNet.lib.tc_cmds as tc 22 | from KNet.lib.logger import logger as log 23 | 24 | ''' 25 | @add_metaclass(abc.ABCMeta) 26 | class NodeLink(object): 27 | def __init__(self, data, qos=None): 28 | # self.network = network 29 | self.qos = qos 30 | self.switch = data["switches"][0] 31 | self.nodes = data["nodes"] 32 | self.links = [] 33 | 34 | def create(self): 35 | for node in self.nodes: 36 | # print node 37 | node_interface = "eth1" 38 | qos = None 39 | #mac = None 40 | #if "mac" in node: 41 | # mac = node["mac"] 42 | #ip = self.network.getip() 43 | n = utils.get_node_data(node["name"]) 44 | 45 | # create a link node to switch 46 | ovs.create_link(self.switch, node_interface, node["name"], 47 | n['ip'], n['mac']) 48 | # get the tap interface name 49 | tapif = ovs.get_port_name(node["name"], node_interface) 50 | # link - source node id 51 | # sourceid = utils.get_node_data(node["name"]) 52 | sourceid = n["id"] 53 | # link -target node id 54 | s = utils.get_switch_data(self.switch) 55 | targetid = s["id"] 56 | # apply the Qos to the interface 57 | if "qos" in node: 58 | qos = self.getqos(node["qos"]) 59 | tc.config_qos(tapif, qos) 60 | 61 | # store the link endpoints in array (for UI drawing) 62 | self.links.append({"source": sourceid, "target": targetid, 63 | "source-name": node["name"], 64 | "target-name": self.switch}) 65 | 66 | # update in DB 67 | self.docid = utils.link_t.insert({'id': utils.generate_id(), 68 | 'source': node["name"], 69 | 'target': self.switch, 70 | 'source-id': sourceid, 71 | 'target-id': targetid, 72 | 'if1': node_interface, 73 | 'if2': tapif, 74 | 'qos': qos, 75 | }) 76 | 77 | def getifname(self): 78 | for node in self.nodes: 79 | print ovs.get_port_name(node, "eth1") 80 | 81 | def getqos(self, qname): 82 | for q in self.qos: 83 | if q["name"] == qname: 84 | return q 85 | return None 86 | 87 | def delete(self): 88 | # what to write? 89 | pass 90 | ''' 91 | 92 | 93 | @add_metaclass(abc.ABCMeta) 94 | class HostLink(object): 95 | def __init__(self, data, qos=None): 96 | # self.network = network 97 | log.debug("HostLink Object init" + str(data)) 98 | self.qos = qos 99 | self.switch = data["switches"][0] 100 | self.hosts = data["hosts"] 101 | self.links = [] 102 | ''' 103 | def __getip(self, interfaces, ifname): 104 | for interface in interfaces: 105 | if interface["name"] == ifname: 106 | return interface["ip"], interface["mac"] 107 | return None 108 | ''' 109 | def __getip(self, interfaces, ifname): 110 | ip, mac = None, None 111 | for interface in interfaces: 112 | if interface["name"] == ifname: 113 | if "ip" in interface: 114 | ip = interface["ip"] 115 | if "mac" in interface: 116 | mac = interface["mac"] 117 | return ip, mac 118 | return None 119 | 120 | def create(self): 121 | for host in self.hosts: 122 | log.debug("Creating HostLink" + str(host)) 123 | r = utils.get_host_data(host['name']) 124 | ip, mac = self.__getip(r['interfaces'], host["interface"]) 125 | log.debug(ip) 126 | log.debug(mac) 127 | # create a link node to switch 128 | ovs.create_link(self.switch, host["interface"], host['name'], 129 | ip, mac) 130 | 131 | # get the tap interface name 132 | tapif = ovs.get_port_name(host["name"], host["interface"]) 133 | # apply the Qos to the interface 134 | if "qos" in host: 135 | qos = self.getqos(host["qos"]) 136 | tc.config_qos(tapif, qos) 137 | 138 | sourceid = r["id"] 139 | # link -target node id 140 | s = utils.get_switch_data(self.switch) 141 | targetid = s["id"] 142 | 143 | # get the tap interface name 144 | #tapif = ovs.get_port_name(host["name"], host["interface"]) 145 | 146 | # store the link endpoints in array (for UI drawing) 147 | self.links.append({"source": sourceid, "target": targetid, 148 | "source-name": host["name"], 149 | "target-name": self.switch}) 150 | 151 | # update in DB 152 | self.docid = utils.link_t.insert({'id': utils.generate_id(), 153 | 'source': host["name"], 154 | 'target': self.switch, 155 | 'source-id': sourceid, 156 | 'target-id': targetid, 157 | 'if1': host["interface"], 158 | 'if2': tapif, 159 | 'qos': None, 160 | }) 161 | 162 | def getifname(self): 163 | for router in self.routers: 164 | print ovs.get_port_name(router, "eth1") 165 | 166 | def getqos(self, qname): 167 | for q in self.qos: 168 | if q["name"] == qname: 169 | return q 170 | return None 171 | 172 | def delete(self): 173 | # what to write? 174 | pass 175 | 176 | 177 | 178 | 179 | @add_metaclass(abc.ABCMeta) 180 | class ServerLink(object): 181 | def __init__(self, data, qos=None): 182 | # self.network = network 183 | log.info("ServerLink Object init" + str(data)) 184 | self.qos = qos 185 | self.switch = data["switches"][0] 186 | self.servers = data["servers"] 187 | self.links = [] 188 | 189 | ''' 190 | def __getip(self, interfaces, ifname): 191 | for interface in interfaces: 192 | if interface["name"] == ifname: 193 | return interface["ip"], interface["mac"] 194 | return None 195 | ''' 196 | 197 | def __getip(self, interfaces, ifname): 198 | ip, mac = None, None 199 | for interface in interfaces: 200 | if interface["name"] == ifname: 201 | if "ip" in interface: 202 | ip = interface["ip"] 203 | if "mac" in interface: 204 | mac = interface["mac"] 205 | return ip, mac 206 | return None 207 | 208 | def create(self): 209 | for server in self.servers: 210 | log.info("Creating ServerLink" + str(server)) 211 | r = utils.get_server_data(server['name']) 212 | 213 | ip, mac = self.__getip(r['interfaces'], server["interface"]) 214 | log.debug(ip) 215 | log.debug(mac) 216 | # create a link node to switch 217 | ovs.create_link(self.switch, server["interface"], server['name'], 218 | ip, mac) 219 | # get the tap interface name 220 | tapif = ovs.get_port_name(server["name"], server["interface"]) 221 | # apply the Qos to the interface 222 | if "qos" in server: 223 | qos = self.getqos(server["qos"]) 224 | tc.config_qos(tapif, qos) 225 | 226 | sourceid = r["id"] 227 | # link -target node id 228 | s = utils.get_switch_data(self.switch) 229 | targetid = s["id"] 230 | 231 | # get the tap interface name 232 | tapif = ovs.get_port_name(server["name"], server["interface"]) 233 | 234 | # store the link endpoints in array (for UI drawing) 235 | self.links.append({"source": sourceid, "target": targetid, 236 | "source-name": server["name"], 237 | "target-name": self.switch}) 238 | 239 | # update in DB 240 | self.docid = utils.link_t.insert({'id': utils.generate_id(), 241 | 'source': server["name"], 242 | 'target': self.switch, 243 | 'source-id': sourceid, 244 | 'target-id': targetid, 245 | 'if1': server["interface"], 246 | 'if2': tapif, 247 | 'qos': None, 248 | }) 249 | 250 | def getifname(self): 251 | for server in self.servers: 252 | print ovs.get_port_name(server, "eth1") 253 | 254 | def getqos(self, qname): 255 | for q in self.qos: 256 | if q["name"] == qname: 257 | return q 258 | return None 259 | 260 | def delete(self): 261 | # what to write? 262 | pass 263 | 264 | 265 | @add_metaclass(abc.ABCMeta) 266 | class RouterLink(object): 267 | def __init__(self, data, qos=None): 268 | # self.network = network 269 | log.debug("RouterLink Object init" + str(data)) 270 | self.qos = qos 271 | self.switch = data["switches"][0] 272 | self.routers = data["routers"] 273 | self.links = [] 274 | 275 | ''' 276 | def __getip(self, interfaces, ifname): 277 | for interface in interfaces: 278 | if interface["name"] == ifname: 279 | return interface["ip"], interface["mac"] 280 | return None 281 | ''' 282 | 283 | def __getip(self, interfaces, ifname): 284 | ip, mac = None, None 285 | for interface in interfaces: 286 | if interface["name"] == ifname: 287 | if "ip" in interface: 288 | ip = interface["ip"] 289 | if "mac" in interface: 290 | mac = interface["mac"] 291 | return ip, mac 292 | return None 293 | 294 | 295 | def create(self): 296 | for router in self.routers: 297 | log.debug("Creating RouterLink" + str(router)) 298 | r = utils.get_router_data(router['name']) 299 | log.debug(r) 300 | # get IP from the router data r for the interface 301 | ip, mac = self.__getip(r['interfaces'], router["interface"]) 302 | log.debug(ip) 303 | log.debug(mac) 304 | # create a link node to switch 305 | ovs.create_link(self.switch, router["interface"], router['name'], 306 | ip, mac) 307 | 308 | # get the tap interface name 309 | tapif = ovs.get_port_name(router["name"], router["interface"]) 310 | # apply the Qos to the interface 311 | if "qos" in router: 312 | qos = self.getqos(router["qos"]) 313 | tc.config_qos(tapif, qos) 314 | 315 | sourceid = r["id"] 316 | # link -target node id 317 | s = utils.get_switch_data(self.switch) 318 | targetid = s["id"] 319 | 320 | # get the tap interface name 321 | tapif = ovs.get_port_name(router["name"], router["interface"]) 322 | 323 | # store the link endpoints in array (for UI drawing) 324 | self.links.append({"source": sourceid, "target": targetid, 325 | "source-name": router["name"], 326 | "target-name": self.switch}) 327 | 328 | # update in DB 329 | self.docid = utils.link_t.insert({'id': utils.generate_id(), 330 | 'source': router["name"], 331 | 'target': self.switch, 332 | 'source-id': sourceid, 333 | 'target-id': targetid, 334 | 'if1': router["interface"], 335 | 'if2': tapif, 336 | 'qos': None, 337 | }) 338 | 339 | def getifname(self): 340 | for router in self.routers: 341 | print ovs.get_port_name(router, "eth1") 342 | 343 | def getqos(self, qname): 344 | for q in self.qos: 345 | if q["name"] == qname: 346 | return q 347 | return None 348 | 349 | def delete(self): 350 | # what to write? 351 | pass 352 | 353 | 354 | 355 | 356 | @add_metaclass(abc.ABCMeta) 357 | class SwitchLink(object): 358 | # class variable 359 | patchif_index = 0 360 | 361 | def __init__(self, data): 362 | self.id = utils.generate_id() 363 | self.src_switch = data["switches"][0] 364 | self.dst_switch = data["switches"][1] 365 | self.links = [] 366 | 367 | def create(self): 368 | # add port 369 | # set port type as patch 370 | # set port peer mapping 371 | self.src_patchif = "patch"+str(SwitchLink.patchif_index) 372 | SwitchLink.patchif_index += 1 373 | self.dst_patchif = "patch"+str(SwitchLink.patchif_index) 374 | SwitchLink.patchif_index += 1 375 | ovs.addport(self.src_switch, self.src_patchif) 376 | ovs.addport(self.dst_switch, self.dst_patchif) 377 | 378 | ovs.config_port_as_patch(self.src_patchif) 379 | ovs.config_port_as_patch(self.dst_patchif) 380 | 381 | ovs.peer_patch_ports(self.src_patchif, self.dst_patchif) 382 | ovs.peer_patch_ports(self.dst_patchif, self.src_patchif) 383 | 384 | # link - source node id 385 | s = utils.get_switch_data(self.src_switch) 386 | sourceid = s["id"] 387 | # link -target node id 388 | t = utils.get_switch_data(self.dst_switch) 389 | targetid = t["id"] 390 | # store the link endpoints in array (for UI drawing) 391 | self.links.append({"source": sourceid, 392 | "target": targetid, 393 | "source-name": self.src_switch, 394 | "target-name": self.dst_switch 395 | }) 396 | 397 | # update in DB 398 | self.docid = utils.link_t.insert({'id': self.id, 399 | 'source': self.src_switch, 400 | 'target': self.dst_switch, 401 | 'source-id': sourceid, 402 | 'target-id': targetid, 403 | 'if1': self.src_patchif, 404 | 'if2': self.dst_patchif, 405 | 'qos': None, 406 | }) 407 | 408 | def delete(self): 409 | pass 410 | -------------------------------------------------------------------------------- /KNet/lib/logger.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | import logging 16 | 17 | 18 | def init_logging(fname="/tmp/KNet.log", loglevel=logging.DEBUG): 19 | hdlr = logging.FileHandler(fname) 20 | formatter = logging.Formatter('%(asctime)s %(levelname)s %(filename)s %(funcName)s %(message)s') 21 | hdlr.setFormatter(formatter) 22 | logger.addHandler(hdlr) 23 | logger.setLevel(logging.DEBUG) 24 | 25 | logger = logging.getLogger('KNet') 26 | init_logging() 27 | -------------------------------------------------------------------------------- /KNet/lib/networks.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | from __future__ import unicode_literals 16 | import sys 17 | import abc 18 | from six import add_metaclass, text_type 19 | import sys 20 | import ipaddress 21 | import KNet.lib.utils as utils 22 | 23 | 24 | @add_metaclass(abc.ABCMeta) 25 | class Network(object): 26 | 27 | def __init__(self, data): 28 | self.id = utils.generate_uuid() 29 | self.name = data["name"] 30 | self.subnet = data["subnet"] 31 | self.netmask = self.subnet.split('/')[1] 32 | # convert in to unicode - compatibility with ipaddress module 33 | self.subnet = unicode(self.subnet, "utf-8") 34 | self.ipaddresses = list(ipaddress.ip_network(self.subnet).hosts()) 35 | self.index = 0 36 | self.max = len(self.ipaddresses) 37 | 38 | def getip(self): 39 | self.index = self.index + 1 40 | ip = str(self.ipaddresses[self.index]) + "/" + self.netmask 41 | return ip 42 | -------------------------------------------------------------------------------- /KNet/lib/ovs_cmds.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | import sys 16 | import KNet.lib.utils as utils 17 | 18 | 19 | def check_controller_format(c): 20 | res = c.split(':') 21 | if not res[2].isdigit(): 22 | return False 23 | if not res[0] in ["udp", "tcp"]: 24 | return False 25 | return True 26 | 27 | 28 | def create_bridge(name): 29 | # sudo ovs-vsctl add-br ovs-br1 30 | cmd = ['sudo', 'ovs-vsctl', 'add-br', name] 31 | utils.run_cmd(cmd) 32 | # exception to be handled 33 | 34 | 35 | def create_userspace_bridge(name): 36 | # sudo ovs-vsctl add-br br1 -- set Bridge br1 datapath_type=netdev 37 | cmd = ['sudo', 'ovs-vsctl', 'add-br', name, "--", 38 | 'set', 'Bridge', name, 'datapath_type=netdev'] 39 | utils.run_cmd(cmd) 40 | # exception to be handled 41 | 42 | 43 | def set_controller(name, controller): 44 | # sudo ovs-vsctl set-controller ovs-br1 tcp:0.0.0.0:6633 45 | cmd = ['sudo', 'ovs-vsctl', 'set-controller', name, controller] 46 | utils.run_cmd(cmd) 47 | # exception to be handled 48 | 49 | def set_mgmt_ip(name, ips): 50 | #sudo ip addr add 192.168.1.1/24 dev sdn_rtr1 51 | #sudo ip link set sdn_rtr1 up 52 | for ip in ips: 53 | cmd = ['sudo', 'ip', 'addr','add',ip, 'dev', name] 54 | utils.run_cmd(cmd) 55 | cmd1 = ['sudo', 'ip', 'link','set', name, 'up'] 56 | utils.run_cmd(cmd1) 57 | # exception to be handled 58 | 59 | def disable_inband(name): 60 | #sudo ovs-vsctl set bridge br0 other-config:disable-in-band=true 61 | option = 'other-config:disable-in-band=true' 62 | cmd = ['sudo', 'ovs-vsctl', 'set', 'bridge', name, option] 63 | utils.run_cmd(cmd) 64 | # exception to be handl 65 | 66 | 67 | def dpid(id): 68 | # id is a number, which can be 0 to 16 digits 69 | # This function return 16digit string , prepends 0 in the id. 70 | temp = id 71 | Totalsize = 16 72 | 73 | # identify the number of digits 74 | digit = 1 75 | while (temp > 9): 76 | temp = temp / 10 77 | digit = digit+1 78 | 79 | prepend = '' 80 | prependbits = 16 - digit 81 | while (prependbits > 0): 82 | prepend += '0' 83 | prependbits -= 1 84 | 85 | r = prepend + str(id) 86 | return r 87 | 88 | 89 | def set_datapath_id(name, id): 90 | # sudo ovs-vsctl set bridge ovs-br1 other_config:datapath-id=#{dpid}" 91 | # convert id in to 16digit hex 92 | datapath = "other_config:datapath-id=" + str(dpid(id)) 93 | cmd = ['sudo', 'ovs-vsctl', 'set', 'bridge', name, datapath] 94 | utils.run_cmd(cmd) 95 | # exception to be handled 96 | 97 | 98 | def set_protocol_version(name, version): 99 | # sudo ovs-vsctl set bridge ovs-br1 protocols=OpenFlow13 100 | if str("1.3") == version: 101 | v = "OpenFlow13" 102 | elif str("1.2") == version: 103 | v = "OpenFlow12" 104 | else: 105 | v = "OpenFlow10" 106 | version = "protocols="+v 107 | cmd = ['sudo', 'ovs-vsctl', 'set', 'bridge', name, version] 108 | # version 1.4,1.5 support to be checked 109 | utils.run_cmd(cmd) 110 | 111 | 112 | def delete_bridge(name): 113 | # sudo ovs-vsctl del-br ovs-br1 114 | cmd = ['sudo', 'ovs-vsctl', 'del-br', name] 115 | utils.run_cmd(cmd) 116 | 117 | 118 | def addport(name, portname): 119 | # ovs-vsctl add-port br0 tap0 120 | cmd = ['sudo', 'ovs-vsctl', 'add-port', name, portname] 121 | utils.run_cmd(cmd) 122 | 123 | 124 | def config_port_as_patch(portname): 125 | # ovs-vsctl add-port br0 tap0 126 | cmd = ['sudo', 'ovs-vsctl', 'set', 'interface', portname, 'type=patch'] 127 | utils.run_cmd(cmd) 128 | 129 | 130 | def peer_patch_ports(portname, peerport): 131 | # ovs-vsctl add-port br0 tap0 132 | peer = "options:peer="+peerport 133 | cmd = ['sudo', 'ovs-vsctl', 'set', 'interface', portname, peer] 134 | utils.run_cmd(cmd) 135 | 136 | 137 | def create_link(swname, ifname, nodename, cidr, mac=None): 138 | # sudo ovs-docker add-port ovs-br1 eth1 node1 --ipaddress=192.168.1.1/24 139 | # --macaddress 00:00:00:00:00:01 140 | ipa = "--ipaddress=" + cidr 141 | cmd = ['sudo', 'ovs-docker', 'add-port', swname, ifname, nodename, ipa] 142 | if mac: 143 | maca = "--macaddress=" + mac 144 | cmd.append(maca) 145 | utils.run_cmd(cmd) 146 | 147 | 148 | def get_port_name(container, ifname): 149 | # ref: https://github.com/openvswitch/ovs/blob/master/utilities/ovs-docker 150 | # fn : get_port_for_container_interface () 151 | cn = "external_ids:container_id=" + str(container) 152 | ifname = "external_ids:container_iface=" + str(ifname) 153 | cmd = ['sudo', 'ovs-vsctl', '--data=bare', '--no-heading', 154 | '--columns=name', 'find', 'interface', cn, ifname] 155 | response = utils.run_cmd(cmd) 156 | return response.strip("\n") 157 | 158 | 159 | # admin down link 160 | def admindown_link(ifname): 161 | cmd = ['sudo', 'ifconfig', ifname, 'down'] 162 | utils.run_cmd(cmd) 163 | 164 | 165 | # admin up link 166 | def adminup_link(ifname): 167 | cmd = ['sudo', 'ifconfig', ifname, 'up'] 168 | utils.run_cmd(cmd) 169 | -------------------------------------------------------------------------------- /KNet/lib/qos.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | from __future__ import unicode_literals 16 | import abc 17 | from six import add_metaclass, text_type 18 | import sys 19 | import KNet.lib.utils as utils 20 | 21 | 22 | @add_metaclass(abc.ABCMeta) 23 | class Qos(object): 24 | 25 | def __init__(self, data, container): 26 | self.id = utils.generate_uuid() 27 | self.name = data["name"] 28 | self.bandwidth = data["bandwidth"] 29 | self.latency = data["latency"] 30 | self.jitter = data["jitter"] 31 | self.pktloss = data["pktloss"] 32 | 33 | def create(self): 34 | pass 35 | 36 | def delete(self): 37 | pass 38 | 39 | def get(self): 40 | pass 41 | -------------------------------------------------------------------------------- /KNet/lib/router.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | from __future__ import unicode_literals 16 | import sys 17 | import abc 18 | from six import add_metaclass, text_type 19 | import KNet.lib.utils as utils 20 | import KNet.lib.docker_cmds as docker 21 | 22 | 23 | @add_metaclass(abc.ABCMeta) 24 | class Router(object): 25 | def __init__(self, data): 26 | self.uuid = None 27 | self.id = utils.generate_id() 28 | self.name = data["name"] 29 | self.img = data["image"] 30 | self.external = False 31 | self.mgmtif = False 32 | if "external" in data: 33 | self.external = data["external"] 34 | if "mgmt-if" in data: 35 | self.mgmtif = data["mgmt-if"] 36 | self.status = "initialized" 37 | self.interfaces = data["interfaces"] 38 | 39 | # DB Updation 40 | self.docid = utils.router_t.insert({'id': self.id, 'name': self.name, 41 | 'img': self.img, 42 | 'external': self.external, 43 | 'interfaces': self.interfaces, 44 | 'status': self.status}) 45 | # print self.docid 46 | 47 | def create(self): 48 | # sudo docker run -itd --name=node1 ubuntu:trusty 49 | if self.external: 50 | self.uuid = docker.create_container(self.name, self.img, 51 | net="bridge") 52 | #iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 53 | natcmd = [self.name, "iptables", "-t", "nat", "-A", "POSTROUTING", 54 | "-o", "eth0", "-j", "MASQUERADE"] 55 | res = docker.run_cmd_in_container(natcmd) 56 | print res 57 | elif self.mgmtif is True: 58 | self.uuid = docker.create_container(self.name, self.img, 59 | net="bridge") 60 | else: 61 | self.uuid = docker.create_container(self.name, self.img) 62 | 63 | self.status = "created" 64 | # update the status in DB 65 | utils.router_t.update({'status': self.status}, doc_ids=[self.docid]) 66 | 67 | 68 | def delete(self): 69 | docker.stop_container(self.name) 70 | docker.delete_container(self.name) 71 | self.status = "deleted" 72 | # update the status in DB 73 | utils.router_t.remove(doc_ids=[self.docid]) 74 | 75 | def get(self): 76 | return utils.router_t.get(doc_id=self.docid) 77 | -------------------------------------------------------------------------------- /KNet/lib/schema.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | Topology_schema = { 16 | "type": "object", 17 | "properties": { 18 | "Topology": { 19 | "type": "object", 20 | "properties": { 21 | "name": {"type": "string"}, 22 | "controller": { 23 | "type": "object", 24 | "properties": { 25 | "url": {"type": "string"} 26 | }, 27 | }, 28 | "openflow": { 29 | "type": "object", 30 | "properties": { 31 | "version": {"type": "number"} 32 | } 33 | }, 34 | "hosts": { 35 | "type": "array", 36 | "properties": { 37 | "name": {"type": "string"}, 38 | "image": {"type": "string"} 39 | } 40 | }, # end of hosts 41 | "switches": { 42 | "type": "array", 43 | "properties": { 44 | "name": {"type": "string"}, 45 | "datapathid": {"type": "number"}, 46 | "openflow": { 47 | "type": "object", 48 | "properties": { 49 | "version": {"type": "number"} 50 | } 51 | } 52 | } 53 | }, # end of switches 54 | "links": { 55 | "type": "array", 56 | "properties": { 57 | "switches": {"type": "array"}, 58 | "nodes": {"type": "array"}, 59 | "network": {"type": "string"} 60 | } 61 | }, # end of links 62 | "networks": { 63 | "type": "array", 64 | "properties": { 65 | "name": {"type": "string"}, 66 | "type": {"type": "string"} 67 | } 68 | }, # end of networks 69 | "qos": { 70 | "type": "array", 71 | "properties": { 72 | "name": {"type": "string"}, 73 | "bandwidth": {"type": "string"}, 74 | "latency": {"type": "string"}, 75 | "jitter": {"type": "string"}, 76 | "pktloss": {"type": "string"}, 77 | } 78 | } # end of qos 79 | } # end of properties of Topology 80 | } # end of Topology 81 | } # end of properties of Topology_schema 82 | } # end of Topology_schema 83 | -------------------------------------------------------------------------------- /KNet/lib/server.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | from __future__ import unicode_literals 16 | import sys 17 | import abc 18 | from six import add_metaclass, text_type 19 | import KNet.lib.utils as utils 20 | import KNet.lib.docker_cmds as docker 21 | 22 | 23 | @add_metaclass(abc.ABCMeta) 24 | class Server(object): 25 | def __init__(self, data): 26 | self.id = utils.generate_id() 27 | self.name = data["name"] 28 | self.img = data["image"] 29 | self.status = "initialized" 30 | self.interfaces = data["interfaces"] 31 | self.mgmtif = False 32 | 33 | if "mgmt-if" in data: 34 | self.mgmtif = data["mgmt-if"] 35 | # DB Updation 36 | self.docid = utils.server_t.insert({'id': self.id, 'name': self.name, 37 | 'img': self.img, 38 | 'interfaces': self.interfaces, 39 | 'status': self.status}) 40 | # print self.docid 41 | 42 | def create(self): 43 | # sudo docker run -itd --name=node1 ubuntu:trusty 44 | 45 | if self.mgmtif is True: 46 | self.uuid = docker.create_container(self.name, self.img, 47 | net="bridge") 48 | else: 49 | self.uuid = docker.create_container(self.name, self.img) 50 | self.status = "created" 51 | # update the status in DB 52 | utils.server_t.update({'status': self.status}, doc_ids=[self.docid]) 53 | 54 | 55 | def delete(self): 56 | docker.stop_container(self.name) 57 | docker.delete_container(self.name) 58 | self.status = "deleted" 59 | # update the status in DB 60 | utils.server_t.remove(doc_ids=[self.docid]) 61 | 62 | def get(self): 63 | return utils.server_t.get(doc_id=self.docid) 64 | -------------------------------------------------------------------------------- /KNet/lib/switches.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | from __future__ import unicode_literals 16 | import abc 17 | from six import add_metaclass, text_type 18 | import sys 19 | import KNet.lib.utils as utils 20 | import KNet.lib.ovs_cmds as ovs 21 | 22 | 23 | @add_metaclass(abc.ABCMeta) 24 | class Switch(object): 25 | 26 | def __init__(self, data, controller): 27 | self.id = utils.generate_id() 28 | self.name = data["name"] 29 | if "openflow" in data: 30 | self.version = str(data["openflow"]["version"]) 31 | else: 32 | self.version = None 33 | if "mgmt_ips" in data: 34 | self.mgmt_ips = data["mgmt_ips"] 35 | else: 36 | self.mgmt_ips = None 37 | self.controller = controller 38 | self.status = "initialized" 39 | if "datapathid" in data: 40 | self.datapathid = int(data["datapathid"]) 41 | else: 42 | self.datapathid = int(self.id) 43 | # Insert the switch details in to DB 44 | self.docid = utils.switch_t.insert({'id': self.id, 'name': self.name, 45 | 'ofversion': self.version, 46 | 'controller': self.controller, 47 | 'datapathid': self.datapathid, 48 | 'status': self.status}) 49 | 50 | def create(self): 51 | ovs.create_bridge(self.name) 52 | #ovs.create_userspace_bridge(self.name) 53 | # controller format: 54 | if self.controller: 55 | if not ovs.check_controller_format(self.controller): 56 | return False 57 | ovs.set_controller(self.name, self.controller) 58 | ovs.set_protocol_version(self.name, str(self.version)) 59 | ovs.set_datapath_id(self.name, self.datapathid) 60 | 61 | if self.mgmt_ips: 62 | ovs.set_mgmt_ip(self.name, self.mgmt_ips) 63 | ovs.disable_inband(self.name) 64 | # Update theDB 65 | self.status = "created" 66 | utils.switch_t.update({'status': self.status}, doc_ids=[self.docid]) 67 | 68 | def delete(self): 69 | ovs.delete_bridge(self.name) 70 | # Update the DB 71 | self.status = "deleted" 72 | # utils.switch_t.update({'status': self.status}, doc_ids=[self.docid]) 73 | utils.switch_t.remove(doc_ids=[self.docid]) 74 | 75 | def get(self): 76 | return utils.switch_t.get(doc_id=self.docid) 77 | -------------------------------------------------------------------------------- /KNet/lib/tc_cmds.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | import sys 16 | import KNet.lib.utils as utils 17 | 18 | 19 | ''' 20 | tc qdisc add dev veth1 root handle 1:0 netem delay #{@config.latency} @config.jitter} loss #{@config.pktloss} 21 | bandwidth 22 | tc qdisc add dev veth1 parent 1:1 handle 10: tbf rate #{@config.bandwidth} buffer 1600 limit 3000 23 | ''' 24 | 25 | 26 | def config_qos(tapif, qos): 27 | cmd = ['sudo', 'tc', 'qdisc', 'add', 'dev', tapif, 28 | 'root', 'handle', '1:0', 'netem', 'delay', 29 | qos["latency"], qos["jitter"], 'loss', qos["pktloss"]] 30 | response = utils.run_cmd(cmd) 31 | cmd = ['sudo', 'tc', 'qdisc', 'add', 'dev', tapif, 'parent', '1:1', 32 | 'handle', '10:', 'tbf', 'rate', qos["bandwidth"], 'buffer', '1600', 33 | 'limit', '3000'] 34 | response = utils.run_cmd(cmd) 35 | -------------------------------------------------------------------------------- /KNet/lib/topology.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | 16 | from __future__ import unicode_literals 17 | import sys 18 | import abc 19 | import os 20 | from six import add_metaclass, text_type 21 | import json 22 | import jsonschema 23 | from jsonschema import validate 24 | from shutil import copyfile 25 | import time 26 | from KNet.lib.router import Router 27 | from KNet.lib.host import Host 28 | from KNet.lib.server import Server 29 | from KNet.lib.switches import Switch 30 | from KNet.lib.link import SwitchLink, RouterLink, HostLink, ServerLink 31 | from KNet.lib.networks import Network 32 | from KNet.lib.qos import Qos 33 | import KNet.lib.schema 34 | from KNet.lib.utils import Singleton 35 | import KNet.lib.utils as utils 36 | import KNet.lib.ovs_cmds as ovs 37 | from KNet.lib.logger import logger as log 38 | from KNet.lib.schema import Topology_schema as schema 39 | import KNet.lib.docker_cmds as docker 40 | 41 | UI_DATAFILE = "/tmp/data.js" 42 | VERSION = "1.0.18b" 43 | 44 | 45 | @add_metaclass(abc.ABCMeta) 46 | class Topology(Singleton, object): 47 | 48 | def __init__(self): 49 | self.initialize() 50 | 51 | def initialize(self): 52 | self.name = None 53 | self.status = None 54 | self.controller = None 55 | #self.nodeobjs = [] 56 | self.switchobjs = [] 57 | self.linkobjs = [] 58 | self.networkobjs = [] 59 | self.routerobjs = [] 60 | self.hostobjs = [] 61 | self.serverobjs = [] 62 | self.qos = None 63 | log.debug("Initializing Topology Object") 64 | 65 | def create(self, tdata): 66 | log.debug("Topology Create called with Data" + str(tdata)) 67 | if self.status: 68 | res = "Already Topology is running, we cannot create another one" 69 | log.warn(res) 70 | return res 71 | 72 | if not self.__validate(tdata): 73 | log.error("Topology data schmea validation check failed") 74 | return {"Error": "Invalid Topology Schema Check Data"} 75 | 76 | # setting the name 77 | self.name = tdata["Topology"]["name"] 78 | 79 | # setting the controller 80 | if "controller" in tdata["Topology"]: 81 | self.controller = tdata["Topology"]["controller"]["url"] 82 | 83 | ''' 84 | # check network object is present in the topology input 85 | if "networks" in tdata["Topology"]: 86 | log.debug("Topology Creating Networks") 87 | for net in tdata["Topology"]["networks"]: 88 | networkobj = Network(net) 89 | self.networkobjs.append(networkobj) 90 | ''' 91 | # qos - doesnt require objects. we need to just pass this 92 | # complete dict to Linkobj. 93 | log.debug("Topology Creating Qos") 94 | if "qos" in tdata["Topology"]: 95 | self.qos = tdata["Topology"]["qos"] 96 | 97 | # create hosts 98 | log.debug("Topology Creating Hosts") 99 | for h in tdata["Topology"]["hosts"]: 100 | hostobj = Host(data=h) 101 | hostobj.create() 102 | self.hostobjs.append(hostobj) 103 | 104 | # create servers 105 | if "servers" in tdata["Topology"]: 106 | log.debug("Topology Creating Servers") 107 | for s in tdata["Topology"]["servers"]: 108 | serverobj = Server(data=s) 109 | serverobj.create() 110 | self.serverobjs.append(serverobj) 111 | 112 | # Create switches 113 | log.debug("Topology Creating Switches") 114 | for s in tdata["Topology"]["switches"]: 115 | # Take details from global openflow json 116 | if "openflow" not in s: 117 | if "openflow" in tdata["Topology"]: 118 | s["openflow"] = tdata["Topology"]["openflow"] 119 | 120 | my_controller = None 121 | if "controller" in s: 122 | my_controller = s["controller"]["url"] 123 | else: 124 | my_controller = self.controller 125 | 126 | sobj = Switch(data=s, controller=my_controller) 127 | sobj.create() 128 | self.switchobjs.append(sobj) 129 | 130 | # create routers 131 | if "routers" in tdata["Topology"]: 132 | log.debug("Topology Creating Routers") 133 | for n in tdata["Topology"]["routers"]: 134 | routerobj = Router(data=n) 135 | routerobj.create() 136 | self.routerobjs.append(routerobj) 137 | 138 | # create links 139 | log.debug("Topology Creating Links") 140 | for l in tdata["Topology"]["links"]: 141 | # creating nodeLinks 142 | if "hosts" in l: 143 | lobj = HostLink(data=l, qos=self.qos) 144 | elif "servers" in l: 145 | lobj = ServerLink(data=l, qos=self.qos) 146 | elif "routers" in l: 147 | lobj = RouterLink(data=l, qos=self.qos) 148 | else: 149 | # creating Switch Links 150 | lobj = SwitchLink(data=l) 151 | lobj.create() 152 | self.linkobjs.append(lobj) 153 | 154 | log.debug("Wait for 2 seconds for bring Links") 155 | time.sleep(2) 156 | 157 | # Adding Static Routes in the hosts 158 | for n in tdata["Topology"]["hosts"]: 159 | if "static_routes" in n: 160 | for route in n["static_routes"]: 161 | docker.add_static_route(n["name"], route["subnet"], 162 | route["via"]) 163 | 164 | # Adding Static Routes in the servers 165 | if "servers" in tdata["Topology"]: 166 | for n in tdata["Topology"]["servers"]: 167 | if "static_routes" in n: 168 | for route in n["static_routes"]: 169 | docker.add_static_route(n["name"], route["subnet"], 170 | route["via"]) 171 | 172 | # Adding Static Routes in the routers 173 | if "routers" in tdata["Topology"]: 174 | for r in tdata["Topology"]["routers"]: 175 | if "static_routes" in r: 176 | for route in r["static_routes"]: 177 | docker.add_static_route(r["name"], route["subnet"], 178 | route["via"]) 179 | 180 | self.status = "Created" 181 | log.debug("Topology Creation Completed") 182 | 183 | # Todo - Store Network, Qos in DB?? 184 | 185 | # write the topology data for UI 186 | self.__write_ui_data() 187 | log.debug("Topology details updated in data.js for UI") 188 | 189 | # return the topology data(for CLI) 190 | res = utils.format_createtopo({"Name": self.name, 191 | "Status": self.status, 192 | "Controller": self.controller, 193 | "Hosts": self.__getHostNames(), 194 | "Switches": self.__getSwitchNames(), 195 | "Links": self.__getLinks()}) 196 | log.debug(res) 197 | return res 198 | 199 | def delete(self): 200 | if not self.status: 201 | log.warn("No Topology Exists for delete") 202 | return "No Topology Exists " 203 | 204 | log.debug("Deleting hosts") 205 | for h in self.hostobjs: 206 | h.delete() 207 | del self.hostobjs[:] 208 | 209 | log.debug("Deleting servers") 210 | for s in self.serverobjs: 211 | s.delete() 212 | del self.serverobjs[:] 213 | 214 | log.debug("Deleting switches") 215 | for s in self.switchobjs: 216 | s.delete() 217 | del self.switchobjs[:] 218 | 219 | log.debug("Deleting Routers") 220 | for r in self.routerobjs: 221 | r.delete() 222 | del self.routerobjs[:] 223 | 224 | log.debug("Deleting Links") 225 | del self.linkobjs[:] 226 | 227 | log.debug("Deleting Networks") 228 | del self.networkobjs[:] 229 | 230 | log.debug("Cleaning DB") 231 | utils.purge_db() 232 | # reinitializing the instance variable 233 | self.initialize() 234 | # resetting the id generator(start from 0) 235 | utils.reset_id() 236 | # removing the UI data file 237 | self.__delete_ui_data() 238 | res = "****--------- Topology Deleted---------****" 239 | log.debug(res) 240 | return res 241 | 242 | def get(self): 243 | if not self.status: 244 | log.warn("No Topology Exists") 245 | return "No Topology Exists " 246 | 247 | topo = utils.format_topo({"Name": self.name, 248 | "Status": self.status, 249 | "Controller": self.controller}) 250 | hosts = utils.format_nodes(self.__getHostDetails()) 251 | servers = utils.format_nodes(self.__getServerDetails()) 252 | switches = utils.format_switches(self.__getSwitchDetails()) 253 | routers = utils.format_nodes(self.__getRouterDetails()) 254 | links = utils.format_links(utils.link_t.all()) 255 | result = "Topology \n" + str(topo) + "\n" 256 | result += "Hosts \n" + str(hosts) + "\n" 257 | result += "Servers \n" + str(servers) + "\n" 258 | result += "Switches \n" + str(switches) + "\n" 259 | result += "Routers \n" + str(routers) + "\n" 260 | result += "Links \n" + str(links) + "\n" 261 | log.debug(result) 262 | return result 263 | 264 | def deleteNode(self, name): 265 | obj = self.__getNodebyName(name) 266 | if obj: 267 | obj.delete() 268 | return "Node deleted" 269 | else: 270 | return "Node not found" 271 | 272 | def deleteSwitch(self, name): 273 | obj = self.__getSwitchbyName(name) 274 | if obj: 275 | obj.delete() 276 | return "Switch deleted" 277 | else: 278 | return "Switch not found" 279 | 280 | # hack - short way - to be handled by node module 281 | def adminDownLink(self, ifname): 282 | ovs.admindown_link(ifname) 283 | 284 | def adminUpLink(self, ifname): 285 | ovs.adminup_link(ifname) 286 | 287 | def ping(self, src, dst): 288 | snode = self.__getNodebyName(src) 289 | dnode = self.__getNodebyName(dst) 290 | if snode is not None and dnode is not None: 291 | print "Ping from node " + snode.name + " to " + dnode.name 292 | print docker.run_ping_in_container(snode.name, 293 | dnode.interfaces[0]["ip"].split('/')[0]) 294 | print "---------------------------------------------------" 295 | else: 296 | print "Node not found" 297 | 298 | def pingAll(self): 299 | nodeobjs = self.hostobjs + self.serverobjs + self.routerobjs 300 | print nodeobjs 301 | for snode in nodeobjs: 302 | for dnode in nodeobjs: 303 | if snode.id != dnode.id: 304 | print "Ping from node " + snode.name + " to " + dnode.name 305 | print docker.run_ping_in_container(snode.name, 306 | dnode.interfaces[0]["ip"].split('/')[0]) 307 | print "---------------------------------------------------" 308 | 309 | def version(self): 310 | return VERSION 311 | 312 | def cleanup(self): 313 | cpath = os.path.dirname(os.path.abspath(__file__)) + "/cleanup.sh" 314 | cmd = ['sh', cpath] 315 | return utils.run_cmd(cmd) 316 | 317 | def tcptest(self, srcnode, destnode, connections, t): 318 | # Run tcp server in destnode 319 | docker.run_iperfs_in_container(destnode) 320 | 321 | # Run tcp client in srcnode 322 | serverip = self.__get_node_ip(destnode) 323 | docker.run_iperfc_in_container(srcnode, serverip, connections, t) 324 | 325 | # iperf client process automatically exits, so no need to kill 326 | # kill iperf server proecess in destnode 327 | docker.run_pkill_in_container(destnode, "iperf") 328 | 329 | 330 | def tcptest_detach(self, srcnode, destnode, connections, t): 331 | # Run tcp server in destnode 332 | docker.run_iperfs_in_container(destnode) 333 | 334 | # Run tcp client in srcnode 335 | serverip = self.__get_node_ip(destnode) 336 | docker.run_iperfc_detach_in_container(srcnode, serverip, connections, t) 337 | 338 | # iperf client process automatically exits, so no need to kill 339 | # kill iperf server proecess in destnode 340 | #docker.run_pkill_in_container(destnode, "iperf") 341 | 342 | 343 | def run(self, args): 344 | docker.run_cmd_in_container(args) 345 | 346 | def udptest(self, srcnode, destnode, bandwidth, connections, t): 347 | # Run tcp server in destnode 348 | docker.run_iperf_udps_in_container(destnode) 349 | 350 | # Run tcp client in srcnode 351 | serverip = self.__get_node_ip(destnode) 352 | docker.run_iperf_udpc_in_container(srcnode, serverip, bandwidth, connections, t) 353 | 354 | # iperf client process automatically exits, so no need to kill 355 | # kill iperf server proecess in destnode 356 | docker.run_pkill_in_container(destnode, "iperf") 357 | 358 | 359 | 360 | def udptest_detach(self, srcnode, destnode, bandwidth, connections, t): 361 | # Run tcp server in destnode 362 | docker.run_iperf_udps_in_container(destnode) 363 | 364 | # Run tcp client in srcnode 365 | serverip = self.__get_node_ip(destnode) 366 | docker.run_iperf_udpc_detach_in_container(srcnode, serverip, bandwidth, connections, t) 367 | 368 | # iperf client process automatically exits, so no need to kill 369 | # kill iperf server proecess in destnode 370 | #docker.run_pkill_in_container(destnode, "iperf") 371 | 372 | 373 | 374 | # private functions 375 | def __write_ui_data(self): 376 | topologyData = {} 377 | nodes = [] 378 | links = [] 379 | 380 | for host in self.hostobjs: 381 | nodes.append({"id": host.id, "name": host.name, "icon": "host"}) 382 | for server in self.serverobjs: 383 | nodes.append({"id": server.id, "name": server.name, "icon": "server"}) 384 | for switch in self.switchobjs: 385 | nodes.append({"id": switch.id, "name": switch.name, "icon": "switch"}) 386 | for router in self.routerobjs: 387 | nodes.append({"id": router.id, "name": router.name, "icon": "router"}) 388 | 389 | 390 | for linkobj in self.linkobjs: 391 | for link in linkobj.links: 392 | links.append(link) 393 | topologyData["nodes"] = nodes 394 | topologyData["links"] = links 395 | # print topologyData 396 | with open(UI_DATAFILE, 'w') as outfile: 397 | hdr = "var topologyData =" 398 | outfile.write(hdr) 399 | json.dump(topologyData, outfile) 400 | 401 | def __delete_ui_data(self): 402 | topologyData = {} 403 | nodes = [] 404 | links = [] 405 | topologyData["nodes"] = nodes 406 | topologyData["links"] = links 407 | with open(UI_DATAFILE, 'w') as outfile: 408 | hdr = "var topologyData =" 409 | outfile.write(hdr) 410 | json.dump(topologyData, outfile) 411 | 412 | def __validate(self, data): 413 | try: 414 | validate(data, schema) 415 | except jsonschema.ValidationError as e: 416 | log.error("json schema validation error %s", e.message) 417 | return False 418 | except jsonschema.SchemaError as e: 419 | log.error("json schema error %s", e.message) 420 | return False 421 | return True 422 | 423 | def __getnetwork(self, netname): 424 | for net in self.networkobjs: 425 | if net.name == netname: 426 | return net 427 | return None 428 | 429 | def __getqos(self, qosname): 430 | for qos in self.qosobjs: 431 | if qos.name == qosname: 432 | return qos 433 | return None 434 | 435 | def __getNodebyName(self, nodename): 436 | for host in self.hostobjs: 437 | if host.name == nodename: 438 | return host 439 | for server in self.serverobjs: 440 | if server.name == nodename: 441 | return server 442 | for router in self.routerobjs: 443 | if router.name == nodename: 444 | return router 445 | return None 446 | 447 | def __get_node_ip(self, nodename): 448 | node = self.__getNodebyName(nodename) 449 | return node.interfaces[0]["ip"].split('/')[0] 450 | 451 | def __getSwitchbyName(self, swname): 452 | for sw in self.switchobjs: 453 | if sw.name == swname: 454 | return sw 455 | return None 456 | 457 | # functions for collecting the Data for CLI dsplay 458 | 459 | def __getHostNames(self): 460 | return [host.name for host in self.hostobjs] 461 | 462 | def __getSwitchNames(self): 463 | return [sw.name for sw in self.switchobjs] 464 | 465 | def __getLinks(self): 466 | results = [] 467 | for linkobj in self.linkobjs: 468 | for link in linkobj.links: 469 | results.append(link["source-name"] + "->" + 470 | link["target-name"]) 471 | return results 472 | 473 | def __getHostDetails(self): 474 | result = [] 475 | for host in self.hostobjs: 476 | result.append({"name": host.name, 477 | "status": host.status, 478 | "id": host.id, 479 | "image": host.img, 480 | #"ip": host.ip, 481 | #"mac": host.mac 482 | }) 483 | return result 484 | 485 | 486 | def __getServerDetails(self): 487 | result = [] 488 | for s in self.serverobjs: 489 | result.append({"name": s.name, 490 | "status": s.status, 491 | "id": s.id, 492 | "image": s.img, 493 | #"ip": host.ip, 494 | #"mac": host.mac 495 | }) 496 | return result 497 | 498 | def __getSwitchDetails(self): 499 | result = [] 500 | for sw in self.switchobjs: 501 | result.append({"name": sw.name, 502 | "status": sw.status, 503 | "id": sw.id, 504 | "version": sw.version, 505 | "controller": sw.controller 506 | }) 507 | return result 508 | 509 | def __getRouterDetails(self): 510 | result = [] 511 | for router in self.routerobjs: 512 | result.append({"name": router.name, 513 | "status": router.status, 514 | "id": router.id, 515 | "image": router.img, 516 | }) 517 | return result 518 | 519 | 520 | def __getLinkDetails(self): 521 | result = [] 522 | # read from DB. link objects doesnt stores in switch perspective 523 | links = utils.link_t.all() 524 | for link in links: 525 | result.append({"name": sw.name, 526 | "status": sw.status, 527 | "id": sw.id, 528 | "version": sw.version, 529 | "controller": sw.controller 530 | }) 531 | return result 532 | -------------------------------------------------------------------------------- /KNet/lib/utils.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | 16 | import os 17 | import subprocess 18 | import sys 19 | import uuid 20 | import tinydb 21 | from tinydb import TinyDB, Query 22 | from beautifultable import BeautifulTable 23 | from KNet.lib.logger import logger as log 24 | 25 | 26 | # https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python 27 | class Singleton(object): 28 | _instance = None 29 | 30 | def __new__(class_, *args, **kwargs): 31 | if not isinstance(class_._instance, class_): 32 | class_._instance = object.__new__(class_, *args, **kwargs) 33 | return class_._instance 34 | 35 | 36 | # UUID Generation 37 | def generate_uuid(): 38 | return str(uuid.uuid4()) 39 | 40 | ''' 41 | ID Generation, Associated with nodes,switches. 42 | First ID should be 0. This ID is used in next-UI Topology Drawaing 43 | ''' 44 | id = -1 45 | def generate_id(): 46 | global id 47 | id = id + 1 48 | return id 49 | 50 | # id must be reset to -1,when deleting the topology. 51 | # every topology devices must get id from 0. 52 | def reset_id(): 53 | global id 54 | id = -1 55 | return 56 | 57 | # Executing Command 58 | def run_cmd(cmd): 59 | try: 60 | log.debug(str(cmd)) 61 | output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) 62 | log.debug(output) 63 | return output 64 | #return subprocess.check_output(cmd, stderr=subprocess.STDOUT) 65 | except subprocess.CalledProcessError as ex: 66 | if ex.returncode == 255: 67 | raise RuntimeWarning(ex.output.strip()) 68 | raise RuntimeError('cmd execution returned exit status %d:\n%s' 69 | % (ex.returncode, ex.output.strip())) 70 | 71 | # ---------------------------------------------------------------# 72 | # DB Interface 73 | db = TinyDB('/tmp/db.json') 74 | query = Query() 75 | topology_t = db.table('topology') 76 | host_t = db.table('host') 77 | server_t = db.table('server') 78 | node_t = db.table('node') 79 | router_t = db.table('router') 80 | switch_t = db.table('switch') 81 | link_t = db.table('link') 82 | network_t = db.table('network') 83 | qos_t = db.table('qos') 84 | 85 | def get_node_data(node_name): 86 | result = node_t.search(query.name == node_name) 87 | # print result 88 | return result[0] 89 | 90 | 91 | def get_router_data(router_name): 92 | result = router_t.search(query.name == router_name) 93 | # print result 94 | return result[0] 95 | 96 | 97 | def get_host_data(host_name): 98 | result = host_t.search(query.name == host_name) 99 | # print result 100 | return result[0] 101 | 102 | def get_server_data(server_name): 103 | result = server_t.search(query.name == server_name) 104 | # print result 105 | return result[0] 106 | 107 | def get_switch_data(switch_name): 108 | result = switch_t.search(query.name == switch_name) 109 | # print result 110 | return result[0] 111 | 112 | def purge_db(): 113 | topology_t.purge() 114 | node_t.purge() 115 | switch_t.purge() 116 | link_t.purge() 117 | network_t.purge() 118 | qos_t.purge() 119 | # --------------------------------------------------------------- # 120 | 121 | #Pretty Print Interface 122 | 123 | def format_createtopo(data): 124 | log.debug(str(data)) 125 | if not data: 126 | return "" 127 | table = BeautifulTable(max_width=120) 128 | header = [] 129 | row = [] 130 | for d in data: 131 | header.append(str(d)) 132 | row.append(data[d]) 133 | table.column_headers = header 134 | table.column_widths["Name"] = 10 135 | table.column_widths["Status"] = 10 136 | table.column_widths["Controller"] = 10 137 | table.column_widths["Hosts"] = 15 138 | table.column_widths["Switches"] = 15 139 | table.column_widths["Links"] = 20 140 | table.append_row(row) 141 | return table 142 | 143 | 144 | def format_topo(data): 145 | if not data: 146 | return "" 147 | table = BeautifulTable(max_width=80) 148 | header = [] 149 | row = [] 150 | for d in data: 151 | header.append(str(d)) 152 | row.append(data[d]) 153 | table.column_headers = header 154 | table.column_widths["Name"] = 20 155 | table.column_widths["Status"] = 20 156 | table.column_widths["Controller"] = 20 157 | table.append_row(row) 158 | return table 159 | 160 | def format_nodes(data): 161 | if not data: 162 | return "" 163 | table = BeautifulTable(max_width=120) 164 | header = [] 165 | row = [] 166 | # generate header 167 | for d in data[0]: 168 | header.append(str(d)) 169 | table.column_headers = header 170 | # generate rows 171 | for d in data: 172 | row = [] 173 | for key in d: 174 | row.append(d[key]) 175 | table.append_row(row) 176 | 177 | return table 178 | 179 | def format_switches(data): 180 | if not data: 181 | return "" 182 | table = BeautifulTable(max_width=120) 183 | header = [] 184 | row = [] 185 | # generate header 186 | for d in data[0]: 187 | header.append(str(d)) 188 | table.column_headers = header 189 | # generate rows 190 | for d in data: 191 | row = [] 192 | for key in d: 193 | row.append(d[key]) 194 | table.append_row(row) 195 | 196 | return table 197 | 198 | 199 | def format_links(data): 200 | # print data 201 | if not data: 202 | return "" 203 | table = BeautifulTable(max_width=120) 204 | header = [] 205 | row = [] 206 | # generate header 207 | for d in data[0]: 208 | header.append(str(d)) 209 | table.column_headers = header 210 | # generate rows 211 | for d in data: 212 | row = [] 213 | for key in d: 214 | row.append(d[key]) 215 | table.append_row(row) 216 | return table 217 | -------------------------------------------------------------------------------- /KNet/main.py: -------------------------------------------------------------------------------- 1 | '''Copyright 2018 KNet Solutions, India, http://knetsolutions.in 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ''' 15 | 16 | from __future__ import unicode_literals 17 | import sys 18 | import abc 19 | from six import add_metaclass, text_type 20 | import yaml 21 | import argparse 22 | from KNet.lib.topology import Topology 23 | 24 | # main application 25 | def main(argv): 26 | parser = argparse.ArgumentParser("KNet Test app") 27 | parser.add_argument("--input-file", required=True, help="Topology input file") 28 | args = parser.parse_args(argv[1:]) 29 | with open(args.input_file) as fp: 30 | tdata = yaml.load(fp) 31 | t = Topology() 32 | print t.create(tdata) 33 | print t.get() 34 | 35 | if __name__ == "__main__": 36 | main(sys.argv) 37 | -------------------------------------------------------------------------------- /KNet/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/KNet/test/__init__.py -------------------------------------------------------------------------------- /KNet/test/testutils.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import KNet.lib.utils as utils 3 | 4 | 5 | class TestUtils(unittest.TestCase): 6 | 7 | def test_generate_id(self): 8 | self.assertEqual(utils.generate_id(), 0) 9 | 10 | def test_generate_id_again(self): 11 | self.assertEqual(utils.generate_id(), 1) 12 | 13 | def test_reset_generate(self): 14 | utils.reset_id() 15 | self.assertEqual(utils.generate_id(), 0) 16 | 17 | if __name__ == '__main__': 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include KNet/lib/cleanup.sh -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/knetsolutions/KNet.svg?branch=master)](https://travis-ci.org/knetsolutions/KNet) 2 | [![Doc Status](https://readthedocs.org/projects/knet-topology-builder/badge/?version=latest)](http://knet-topology-builder.readthedocs.org/en/latest/) 3 | 4 | # KNet 5 | 6 | KNet is a Virtual Network Tobology builder. Some of the places, it can be used as, 7 | 8 | 1. SDN Test Lab. 9 | 2. Networking Lab 10 | 3. Security Test Environment 11 | 4. Test Environment for Containarized Applications 12 | 13 | 14 | KNet builds the Virtual Network Topology with Switches, Hosts, Routers, and Servers. KNet uses Dockers for building the Nodes, openvswitch for switches. 15 | 16 | KNet support QoS parameter configuration for the Links, such as bandwidth, latency, jitter and packetloss. 17 | 18 | KNet supports the CLI and Web Interface. 19 | 20 | ## Documents 21 | 22 | **1. Detailed Document is available in [readthedocs](http://knet-topology-builder.readthedocs.io)** 23 | 24 | 25 | **2. Youtube videos 26 | https://www.youtube.com/watch?v=SmWmbAsiimI&list=PLSO7MDepKLNCrHGrRcAyUWWUEFCOrjC4B** 27 | 28 | 29 | ## Support / Mailing List 30 | 31 | User can register in the below mailing list, and raise queries. 32 | 33 | www.freelists.org/list/knet 34 | 35 | 36 | ## Example Topologies 37 | 38 | ![Topology Diagram](docs/imgs/topo0.png?raw=true) 39 | 40 | ![Topology Diagram](docs/imgs/routing_img.png?raw=true) 41 | 42 | 43 | ## Getting Started 44 | 45 | Currently KNet is compatible with **Python 2.7** only. 46 | 47 | KNet is currently supported only in the below operating systems 48 | 49 | - Ubuntu 16.04 50 | - Ubuntu 18.04 51 | 52 | 53 | Note: It can be installed on any Linux OS ,if you customize the install script 54 | 55 | 56 | Minimum hardware configuration required is 4GB RAM, 2 Core processors. Higher configuration gives better result. 57 | 58 | 59 | ### Prerequisites 60 | 61 | The following script installs the prerequisites in Ubuntu 16.04 or 18.04 system . 62 | 63 | ``` 64 | curl https://raw.githubusercontent.com/knetsolutions/KNet/master/install.sh | bash 65 | ``` 66 | 67 | ### Installing 68 | 69 | Install Knet as below, 70 | 71 | ``` 72 | pip install knet 73 | 74 | ``` 75 | 76 | This installs the **knet-cli** executable script. Just run **knet-cli** command to get in to CLI. 77 | 78 | 79 | ### How to Run CLI 80 | 81 | Execute the below command to get in to KNet CLI 82 | ``` 83 | knet-cli 84 | ``` 85 | 86 | ### CLI Commands 87 | 88 | CLI supports the following commands 89 | 90 | ``` 91 | 92 | Available Commands 93 | **************************************************** 94 | Exit -------Exit 95 | Version -------Version 96 | TcpTest -------TcpTest 97 | TcpTest_Detach -------TcpTest 98 | Exec -------Execute commands in the node 99 | UdpTest -------UdpTest 100 | UdpTest_Detach -------UdpTest 101 | Cleanup -------Cleanup 102 | CreateTopology -------Create Topology in SDN Test Bed 103 | DeleteTopology -------Delete the Topology in SDN Test Bed 104 | GetTopology -------Get the Topology objects in Detail 105 | DeleteNode -------Delete the Node in the Topology 106 | DeleteSwitch -------Delete the Switch in the Topology 107 | AdminDownLink -------Admin down the Link 108 | AdminUpLink -------Admin up the Link 109 | PingAll -------Ping All nodes with each other 110 | Ping -------Ping the soruce node to destination node 111 | **************************************************** 112 | 113 | 114 | ``` 115 | 116 | To get the detailed help for a command 117 | 118 | 119 | ``` 120 | Help CreateTopology 121 | 122 | ``` 123 | 124 | 125 | 126 | 127 | ## Few Things to know about KNet. 128 | 129 | 130 | **Topology** 131 | 132 | Topology consists of Hosts, Servers, Routers, Switches, Links, QoS, . Hosts, Servers, Routers are build as Docker Containers. Switches are openvswitch switches. 133 | 134 | **Topology input file** 135 | 136 | User should write Topology in YAML file. This Topology file will be input to the KNet for Topology Creation. 137 | 138 | Example Topology files(linear,ring,mesh,parial mesh, tree) are available in https://github.com/knetsolutions/knet-example-topologies repository. 139 | 140 | 141 | **Hosts** 142 | 143 | Host is built as Docker Containers. Alpine Linux image is used as base Image. Iperf, tcpdump, ping, traceroute, curl tools are preinstalled. 144 | 145 | 146 | **Server** 147 | 148 | Server is built as Docker Containers. Alpine Linux image is used as base Image. Apache web server is preinstalled. 149 | 150 | 151 | 152 | **Router** 153 | 154 | Router is built as Docker Containers. Alpine Linux image is used as base Image. bird routing package is preinstalled. 155 | 156 | 157 | 158 | **Switch** 159 | 160 | Openvswitch is used for building switches. openvswitch kernel data module is used. 161 | 162 | 163 | 164 | ## UI - Web Interface 165 | 166 | KNet UI is optional component. 167 | It is used for Viewing the Topology. This Web Interface displayes Topology in Graphical representation and reflects the topology changes. 168 | 169 | KNet UI repo is available in https://github.com/knetsolutions/knet-ui 170 | 171 | **UI Installation** 172 | 173 | ``` 174 | git clone https://github.com/knetsolutions/knet-ui 175 | cd knet-ui 176 | python ui/webserver.py 177 | 178 | ``` 179 | UI can be accessible in http://localhost:5000/index.html 180 | 181 | 182 | 183 | ## Testing 184 | 185 | **Start the SDN Controller** 186 | 187 | ``` 188 | ryu-manager --verbose apps/simple_switch_13.py 189 | ``` 190 | 191 | **Start the Knet CLI** 192 | 193 | ``` 194 | knet-cli 195 | ``` 196 | 197 | **Create a Topology** 198 | Note : Topology example files available in https://github.com/knetsolutions/knet-example-topologies 199 | In the KNet cli prompt, use "CreateTopology" command to creates a topology. 200 | 201 | 202 | Example: 203 | ``` 204 | KNet-cli#CreateTopology /home/ubuntu/knet-example-topologies/1.0/topo0.yaml 205 | +---------+---------------+------------------------------------------+-------------+------------------+----------------+ 206 | | Status | Name | Links | Switches | Controller | Nodes | 207 | +---------+---------------+------------------------------------------+-------------+------------------+----------------+ 208 | | Created | Simple Star T | [u'a1->switch1', u'a2->switch1', u'a3->s | ['switch1'] | tcp:0.0.0.0:6633 | ['a1', 'a2', ' | 209 | | | opology 1 | witch1', u'a4->switch1'] | | | a3', 'a4'] | 210 | +---------+---------------+------------------------------------------+-------------+------------------+----------------+ 211 | KNet-cli# 212 | ``` 213 | 214 | 215 | **Start the KNet UI** 216 | 217 | 218 | ``` 219 | cd knet-ui 220 | python ui/webserver.py 221 | ``` 222 | 223 | Open the Browser with below URL to see the topology diagram 224 | 225 | ``` 226 | http://localhost:5000/index.html 227 | ``` 228 | 229 | Now you can check the Topology Diagram in the UI http://localhost:5000/index.html. 230 | ![Topology Diagram](docs/imgs/topo0.png?raw=true) 231 | 232 | Make sure, you delete the Topology "DeleteTopology" before you exit the shell. 233 | 234 | ``` 235 | KNet-cli#DeleteTopology 236 | ****--------- Topology Deleted---------**** 237 | KNet-cli#Exit 238 | (knet) ubuntu@ubuntu:~/KNet$ 239 | ``` 240 | 241 | 242 | ## Built With 243 | 244 | * [Dockers](https://www.docker.com/) - The Docker Containers 245 | * [Openvswitch](http://openvswitch.github.io/) - Open vSwitch is a production quality, multilayer virtual switch 246 | * [Next UI Toolkit](https://github.com/NeXt-UI/next-tutorials) - NeXt UI is a Javascript/CSS framework for rendering Network Topology 247 | 248 | ## Contributing 249 | 250 | Todo. 251 | 252 | ## Versioning 253 | 254 | For the versions available, see the [tags on this repository](https://github.com/knetsolutions/KNet/tags). 255 | 256 | ## Author 257 | 258 | S. Suresh Kumar (sureshkumarr.s@gmail.com) 259 | 260 | ## License 261 | 262 | This project is licensed under the Apache License - see the [LICENSE.md](LICENSE.md) file for details 263 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = KNet 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/cli.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | .. contents:: 17 | :depth: 1 18 | :local: 19 | 20 | Command Line Interface 21 | ======================= 22 | 23 | KNet CLI is a primary interface for the user to Create/delete/manipulate the Topology. Currently it supports the following commands. 24 | 25 | .. code-block:: bash 26 | 27 | Help 28 | Version 29 | Cleanup 30 | CreateTopology 31 | DeleteTopology 32 | GetTopology 33 | PingAll 34 | Ping 35 | TcpTest 36 | TcpTest_Detach 37 | Exec 38 | UdpTest 39 | UdpTest_Detach 40 | DeleteNode 41 | DeleteSwitch 42 | AdminDownLink 43 | AdminUpLink 44 | Exit 45 | 46 | Start the CLI 47 | -------------- 48 | .. code-block:: bash 49 | 50 | knet-cli 51 | 52 | 53 | .. figure:: imgs/quick_start/knet_cli_start_s.png 54 | :align: center 55 | 56 | 57 | 58 | Help commands 59 | ------------- 60 | Help Command, lists the available commands. 61 | 62 | Help gives the detailed help for a given command 63 | 64 | .. code-block:: bash 65 | 66 | Help 67 | Help 68 | 69 | Screeshot: 70 | 71 | .. figure:: imgs/cli/cli_help_s.png 72 | :align: center 73 | 74 | 75 | Version 76 | --------- 77 | Shows the version of KNet. 78 | 79 | 80 | 81 | CreateTopology 82 | --------------- 83 | 84 | CreateTopology command creates a Topology. The Topology input file is defined in YAML format. User can easily define any complex topology by writing the YAML file.(Refer: Topology_file section) 85 | 86 | There are few example topologies availale in https://github.com/knetsolutions/knet-example-topologies in the repository. 87 | 88 | 89 | 90 | .. code-block:: bash 91 | 92 | CreateTopology 93 | 94 | Note: Topology file needs to be specified in absolute path. Example; /home/ubuntu/mytopology.yaml 95 | 96 | .. figure:: imgs/cli/cli2_s.png 97 | :align: center 98 | 99 | 100 | Note: 101 | If the Topology file name or Path is not correct, you will see **"I/O operation failed"** Error. 102 | 103 | 104 | GetTopology 105 | --------------- 106 | 107 | GetTopology command gives the detailed information of the Topology, such as Node details(Name, IP, Mac, ID), Switch details(name, datapathid), Link Details(Interface name, Src, Destination). 108 | 109 | .. code-block:: bash 110 | 111 | GetTopology 112 | 113 | 114 | .. figure:: imgs/cli/cli_gettopo_s.png 115 | :align: center 116 | 117 | 118 | PingAll 119 | --------- 120 | 121 | PingAll command, generates 2 ping packets from each node to all other nodes. 122 | 123 | .. figure:: imgs/cli/cli_pingall_s.png 124 | :align: center 125 | 126 | 127 | Ping 128 | --------- 129 | 130 | Ping command, generates 2 ping packets from source node to destination node. 131 | 132 | 133 | .. code-block:: bash 134 | 135 | Ping 136 | 137 | 138 | Screenshot: 139 | 140 | .. figure:: imgs/cli/cli_ping_s.png 141 | :align: center 142 | 143 | 144 | Exec 145 | --------- 146 | Exec command, helps to execute the system command in the node. 147 | 148 | Syntax: 149 | 150 | .. code-block:: bash 151 | 152 | Exec < node> 153 | 154 | For example, you want to know the arp entries of the host 155 | 156 | .. code-block:: bash 157 | 158 | Exec a1 arp -a 159 | Exec a1 ifconfig 160 | Exec a1 ip route 161 | Exec a1 traceroute 10.1.1.2 162 | 163 | TcpTest 164 | ------- 165 | Helps to perform the Iperf TCP traffic test between two nodes 166 | 167 | Refer: Traffic Test session for mode details 168 | 169 | 170 | UdpTest 171 | --------- 172 | Helps to perform the Iperf UDP traffic test between two nodes 173 | 174 | Refer: Traffic Test session for mode details 175 | 176 | 177 | DeleteTopology 178 | -------------- 179 | 180 | DeleteTopology command deletes the entier topology(nodes, switches, links) 181 | 182 | .. code-block:: bash 183 | 184 | DeleteTopology 185 | 186 | Screenshot: 187 | 188 | .. figure:: imgs/cli/cli_deletetopo_s.png 189 | :align: center 190 | 191 | 192 | AdminDownLink 193 | -------------- 194 | 195 | AdminDownLink command downs the particular link. For example, if want to disconnect the link between node1 to node2, we can use this command. 196 | 197 | 1. Identify the Interface name for the link using GetTopology Command 198 | 2. Use AdminDownLink command with identified interface name to shutdown the link. 199 | 200 | .. code-block:: bash 201 | 202 | AdminDownLink 203 | 204 | 205 | In this below example, down the a4 interface. 206 | 207 | Screenshot: 208 | 209 | .. figure:: imgs/cli/cli_downlink_s.png 210 | :align: center 211 | 212 | 213 | 214 | AdminUpLink 215 | -------------- 216 | 217 | AdminUpLink command brings up the link back. 218 | 219 | .. code-block:: bash 220 | 221 | AdminDownLink 222 | 223 | 224 | In this below example, bring up the a4 interface. 225 | 226 | Screenshot: 227 | 228 | .. figure:: imgs/cli/cli_downlink_s.png 229 | :align: center 230 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # KNet documentation build configuration file, created by 5 | # sphinx-quickstart on Tue Jan 9 11:52:51 2018. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | # import os 21 | # import sys 22 | # sys.path.insert(0, os.path.abspath('.')) 23 | 24 | 25 | # -- General configuration ------------------------------------------------ 26 | 27 | # If your documentation needs a minimal Sphinx version, state it here. 28 | # 29 | # needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [] 35 | 36 | # Add any paths that contain templates here, relative to this directory. 37 | templates_path = ['_templates'] 38 | 39 | # The suffix(es) of source filenames. 40 | # You can specify multiple suffix as a list of string: 41 | # 42 | # source_suffix = ['.rst', '.md'] 43 | source_suffix = '.rst' 44 | 45 | # The master toctree document. 46 | master_doc = 'index' 47 | 48 | # General information about the project. 49 | project = 'KNet' 50 | copyright = '2018, KNet Solutions' 51 | author = 'KNet Solutions' 52 | 53 | # The version info for the project you're documenting, acts as replacement for 54 | # |version| and |release|, also used in various other places throughout the 55 | # built documents. 56 | # 57 | # The short X.Y version. 58 | version = '1.0' 59 | # The full version, including alpha/beta/rc tags. 60 | release = '1' 61 | 62 | # The language for content autogenerated by Sphinx. Refer to documentation 63 | # for a list of supported languages. 64 | # 65 | # This is also used if you do content translation via gettext catalogs. 66 | # Usually you set "language" from the command line for these cases. 67 | language = None 68 | 69 | # List of patterns, relative to source directory, that match files and 70 | # directories to ignore when looking for source files. 71 | # This patterns also effect to html_static_path and html_extra_path 72 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 73 | 74 | # The name of the Pygments (syntax highlighting) style to use. 75 | pygments_style = 'sphinx' 76 | 77 | # If true, `todo` and `todoList` produce output, else they produce nothing. 78 | todo_include_todos = False 79 | 80 | 81 | # -- Options for HTML output ---------------------------------------------- 82 | 83 | # The theme to use for HTML and HTML Help pages. See the documentation for 84 | # a list of builtin themes. 85 | # 86 | #html_theme = 'alabaster' 87 | html_theme = 'classic' 88 | 89 | # Theme options are theme-specific and customize the look and feel of a theme 90 | # further. For a list of options available for each theme, see the 91 | # documentation. 92 | # 93 | # html_theme_options = {} 94 | 95 | # Add any paths that contain custom static files (such as style sheets) here, 96 | # relative to this directory. They are copied after the builtin static files, 97 | # so a file named "default.css" will overwrite the builtin "default.css". 98 | html_static_path = ['_static'] 99 | 100 | # Custom sidebar templates, must be a dictionary that maps document names 101 | # to template names. 102 | # 103 | # This is required for the alabaster theme 104 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 105 | #html_sidebars = { 106 | # '**': [ 107 | # 'relations.html', # needs 'show_related': True theme option to display 108 | # 'searchbox.html', 109 | # ] 110 | #} 111 | 112 | html_sidebars = {'**': ['globaltoc.html'], 'using/windows': ['windowssidebar.html', 'searchbox.html'],} 113 | 114 | 115 | 116 | # -- Options for HTMLHelp output ------------------------------------------ 117 | 118 | # Output file base name for HTML help builder. 119 | htmlhelp_basename = 'KNetdoc' 120 | 121 | 122 | # -- Options for LaTeX output --------------------------------------------- 123 | 124 | latex_elements = { 125 | # The paper size ('letterpaper' or 'a4paper'). 126 | # 127 | # 'papersize': 'letterpaper', 128 | 129 | # The font size ('10pt', '11pt' or '12pt'). 130 | # 131 | # 'pointsize': '10pt', 132 | 133 | # Additional stuff for the LaTeX preamble. 134 | # 135 | # 'preamble': '', 136 | 137 | # Latex figure (float) alignment 138 | # 139 | # 'figure_align': 'htbp', 140 | } 141 | 142 | # Grouping the document tree into LaTeX files. List of tuples 143 | # (source start file, target name, title, 144 | # author, documentclass [howto, manual, or own class]). 145 | latex_documents = [ 146 | (master_doc, 'KNet.tex', 'KNet Documentation', 147 | 'KNet Solutions', 'manual'), 148 | ] 149 | 150 | 151 | # -- Options for manual page output --------------------------------------- 152 | 153 | # One entry per manual page. List of tuples 154 | # (source start file, name, description, authors, manual section). 155 | man_pages = [ 156 | (master_doc, 'knet', 'KNet Documentation', 157 | [author], 1) 158 | ] 159 | 160 | 161 | # -- Options for Texinfo output ------------------------------------------- 162 | 163 | # Grouping the document tree into Texinfo files. List of tuples 164 | # (source start file, target name, title, author, 165 | # dir menu entry, description, category) 166 | texinfo_documents = [ 167 | (master_doc, 'KNet', 'KNet Documentation', 168 | author, 'KNet', 'One line description of project.', 169 | 'Miscellaneous'), 170 | ] 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /docs/docker_commands.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | .. contents:: 17 | :depth: 1 18 | :local: 19 | 20 | Useful Docker Commands 21 | ======================= 22 | 23 | 24 | List the Nodes: 25 | ----------------- 26 | 27 | The following command lists all the nodes. You can identify the node with "name" names, its same as node name given in the topology file. 28 | 29 | 30 | .. code-block:: bash 31 | 32 | sudo docker ps -a 33 | 34 | Screenshot: 35 | 36 | .. figure:: imgs/docker/docker_psa_s.png 37 | :align: center 38 | 39 | 40 | .. _docker-install-package: 41 | 42 | How to Install the package(application) in the Node: 43 | ------------------------------------------------------ 44 | Each node is a Ubuntu Linux Container. So you can execute all the linux commands in the Container once you logged in. 45 | 46 | **To Login to the node:** 47 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 48 | 49 | .. code-block:: bash 50 | 51 | sudo docker exec -it bash 52 | Example: 53 | sudo docker exec -it a1 bash 54 | 55 | Screenshot: 56 | 57 | .. figure:: imgs/docker/docker_shell_s.png 58 | :align: center 59 | 60 | 61 | 62 | **To Install the package in the node,** 63 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 64 | 65 | First login to the node as mentioned above, 66 | 67 | .. code-block:: bash 68 | 69 | apt-get update 70 | apt-get install 71 | 72 | Example: 73 | apt-get install iperf3 74 | 75 | Screenshot: 76 | 77 | .. figure:: imgs/docker/docker_iperfs_s.png 78 | :align: center 79 | 80 | 81 | Exit from the node shell 82 | ------------------------- 83 | 84 | .. code-block:: bash 85 | 86 | exit 87 | 88 | Screenshot: 89 | 90 | .. figure:: imgs/docker/docker_exit_s.png 91 | :align: center 92 | 93 | 94 | -------------------------------------------------------------------------------- /docs/example_topologies.rst: -------------------------------------------------------------------------------- 1 | Example Topologies 2 | =================== 3 | 4 | `https://github.com/knetsolutions/knet-example-topologies` repository consists of SDN, and traditional topology ìnput files. 5 | 6 | SDN Folder consists of the below topology input files, 7 | 8 | 1. Simple Topology 9 | 2. Linear1 Topology 10 | 3. Linear2 Topology 11 | 4. Ring Topology 12 | 5. Partial Mesh Topology 13 | 6. Full Mesh Topology 14 | 7. Tree Topology 15 | 16 | Traditional Folder consists of 17 | 18 | 1. One Network with Hosts and Server 19 | 2. Two Networks with Hosts, Server, Router 20 | 3. WAN Topology with Two Routers, Hosts 21 | 22 | 23 | Star Topology 24 | ------------- 25 | 26 | Filename: `simple.yaml` 27 | 28 | .. figure:: imgs/topo0.png 29 | :align: center 30 | 31 | Simple Star Topology. 32 | 33 | This topology consists of 4 nodes, and a switch. All Nodes are connected to a same switch. 34 | 35 | RYU OpenFlow13 Switch application **simple_switch_13.py** can be used to test this topology. 36 | 37 | Linear Topology1 38 | ----------------- 39 | Filename: `linear1.yaml` 40 | 41 | .. figure:: imgs/topo1.png 42 | :align: center 43 | 44 | Simple Linear Topology. 45 | 46 | This topology consists of 4 nodes, and two switches. 2 Nodes are connected in each switch. Also these switches are interconnected. Also MAC address is explicitly mentioned. 47 | 48 | RYU OpenFlow13 Switch application **simple_switch_13.py** can be used to test this topology. 49 | 50 | Linear Topology2 51 | ----------------- 52 | 53 | Filename: `linear2.yaml` 54 | 55 | .. figure:: imgs/topo2.png 56 | :align: center 57 | 58 | Linear Topology with 4 Switches 59 | 60 | This topology consists of 4 nodes, and four switches. Each node is connected in each switch. Also these switches are connected linearly and no loop. 61 | 62 | RYU OpenFlow13 Switch application **simple_switch_13.py** can be used to test this topology. 63 | 64 | Ring Topology 65 | ----------------------- 66 | 67 | Filename: `ring.yaml` 68 | 69 | .. figure:: imgs/topo4.png 70 | :align: center 71 | 72 | Ring Topology. 73 | 74 | This topology consists of 4 nodes, and four switches. Each node is connected in each switch. Also these switches are connected linearly and forms the loop. 75 | 76 | This topology forms a loop, hence RYU STP application **simple_switch_stp_13.py** to be used to test this topology. 77 | 78 | 79 | 80 | Full Mesh Topology 81 | ----------------------- 82 | 83 | Filename: `fmesh.yaml` 84 | 85 | .. figure:: imgs/topo5.png 86 | :align: center 87 | 88 | Full Mesh Topology. 89 | 90 | This topology consists of 4 nodes, and four switches. Each node is connected in each switch. Also these switches are interconnected with each other to form a full mesh. 91 | 92 | This topology forms a loop, hence RYU STP application **simple_switch_stp_13.py** to be used to test this topology. 93 | 94 | Partial Mesh Topology 95 | ----------------------- 96 | 97 | Filename: `pmesh.yaml` 98 | 99 | .. figure:: imgs/topo6.png 100 | :align: center 101 | 102 | Partial Mesh Topology. 103 | 104 | This topology consists of 4 nodes, and four switches. Each node is connected in each switch. Also these switches are interconnected with some other to form a partial mesh. 105 | 106 | This topology forms a loop, hence RYU STP application **simple_switch_stp_13.py** to be used to test this topology. 107 | 108 | 109 | Tree Topology 110 | ----------------------- 111 | 112 | Filename: `tree.yaml` 113 | 114 | .. figure:: imgs/topo7.png 115 | :align: center 116 | 117 | Tree Topology. 118 | 119 | This topology consists of 8 nodes, and 7 switches. This topology forms a binary tree with depth 3. Root Switch is S1. Second level switches are S2 and S5. Third level switches are S3, S4, S6, S7. Nodes are connected to switches S3, S4, S6 and S7. 120 | 121 | RYU OpenFlow13 Switch application **simple_switch_13.py** can be used to test this topology. -------------------------------------------------------------------------------- /docs/imgs/KNet_Actions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/KNet_Actions.png -------------------------------------------------------------------------------- /docs/imgs/cli/cleanup_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cleanup_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli1_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli1_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli2_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli2_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli_deletetopo_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli_deletetopo_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli_downlink_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli_downlink_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli_gettopo_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli_gettopo_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli_help_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli_help_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli_ping_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli_ping_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli_pingall_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli_pingall_s.png -------------------------------------------------------------------------------- /docs/imgs/cli/cli_uplink_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/cli/cli_uplink_s.png -------------------------------------------------------------------------------- /docs/imgs/docker/docker_exit_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/docker/docker_exit_s.png -------------------------------------------------------------------------------- /docs/imgs/docker/docker_iperfs_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/docker/docker_iperfs_s.png -------------------------------------------------------------------------------- /docs/imgs/docker/docker_psa_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/docker/docker_psa_s.png -------------------------------------------------------------------------------- /docs/imgs/docker/docker_shell_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/docker/docker_shell_s.png -------------------------------------------------------------------------------- /docs/imgs/ovs/ovs_flows_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/ovs/ovs_flows_s.png -------------------------------------------------------------------------------- /docs/imgs/ovs/ovs_show_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/ovs/ovs_show_s.png -------------------------------------------------------------------------------- /docs/imgs/prerequisites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/prerequisites.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/CLI_CreateTopology_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/CLI_CreateTopology_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/CLI_Delete_Topology_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/CLI_Delete_Topology_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/CLI_pingall_command_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/CLI_pingall_command_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/KNet_install_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/KNet_install_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/Knet_CLI_example_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/Knet_CLI_example_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/WebUI_emptypage_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/WebUI_emptypage_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/Webui_StarTopology_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/Webui_StarTopology_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/knet_cli_start_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/knet_cli_start_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/knet_install_output_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/knet_install_output_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/knet_pip_install_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/knet_pip_install_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/knet_topology_creation_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/knet_topology_creation_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/knet_ui_install_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/knet_ui_install_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/ovs_dumpflows_output_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/ovs_dumpflows_output_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/prereq_verification_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/prereq_verification_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/prerequisites_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/prerequisites_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/ryu_controller_print_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/ryu_controller_print_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/ryu_install_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/ryu_install_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/ryu_run_l3switch_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/ryu_run_l3switch_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/startopology_dockerswitch_cmds_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/startopology_dockerswitch_cmds_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/startwebui_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/startwebui_s.png -------------------------------------------------------------------------------- /docs/imgs/quick_start/ubuntuversion_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/quick_start/ubuntuversion_s.png -------------------------------------------------------------------------------- /docs/imgs/routing_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/routing_img.png -------------------------------------------------------------------------------- /docs/imgs/topo0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo0.png -------------------------------------------------------------------------------- /docs/imgs/topo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo1.png -------------------------------------------------------------------------------- /docs/imgs/topo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo2.png -------------------------------------------------------------------------------- /docs/imgs/topo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo3.png -------------------------------------------------------------------------------- /docs/imgs/topo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo4.png -------------------------------------------------------------------------------- /docs/imgs/topo5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo5.png -------------------------------------------------------------------------------- /docs/imgs/topo6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo6.png -------------------------------------------------------------------------------- /docs/imgs/topo7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/topo7.png -------------------------------------------------------------------------------- /docs/imgs/traffic/apache_install_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/apache_install_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/apache_start_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/apache_start_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/flow_tables_count_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/flow_tables_count_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/flow_tables_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/flow_tables_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/iperf_client_output_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/iperf_client_output_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/iperf_install1_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/iperf_install1_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/iperf_install2_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/iperf_install2_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/iperf_server_output_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/iperf_server_output_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/iperf_server_start_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/iperf_server_start_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/locust_install_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/locust_install_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/locust_output_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/locust_output_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/locust_run_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/locust_run_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/ovs_flows_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/ovs_flows_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/ryu_l4_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/ryu_l4_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/ryu_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/ryu_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/topology_cli_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/topology_cli_s.png -------------------------------------------------------------------------------- /docs/imgs/traffic/topology_ui_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/KNet/49e0c5db394322022affdde23d5121aeb8120cf1/docs/imgs/traffic/topology_ui_s.png -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | ============== 17 | What is KNet 18 | ============== 19 | 20 | Software Defined Networking(SDN) opens the innovation in networking domain. University Students/Research fellows does plenty of innovative networking solutions with SDN. 21 | 22 | Building the Network Topology for their research activity is still nightmare. 23 | 24 | KNet is Virtual Network Topology Builder, it builds the Network Topology as a real network environment. It means the Nodes are built with Docker Containers. 25 | 26 | User can install any required packages (apache2,mysql,hacking tools.. etc) 27 | User have full control on the nodes to generate the real time original protocol traffic(no simulation). 28 | 29 | .. image:: ./imgs/KNet_Actions.png 30 | :align: center 31 | 32 | 33 | Welcome to KNet's documentation! 34 | ================================ 35 | 36 | .. toctree:: 37 | :maxdepth: 2 38 | :caption: Table of Contents: 39 | :numbered: 40 | 41 | overview 42 | quick_start 43 | cli 44 | example_topologies 45 | topology_file 46 | docker_commands 47 | ovs_commands 48 | traffic_tests 49 | traditional_networks 50 | -------------------------------------------------------------------------------- /docs/overview.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | .. contents:: 17 | :depth: 1 18 | :local: 19 | 20 | Overview 21 | ======== 22 | 23 | Software Defined Networking(SDN) opens the innovation in networking domain. University Students/Research fellows does plenty of innovative networking solutions with SDN. 24 | 25 | Building the Network Topology for their research activity is still nightmare. 26 | 27 | KNet is Virtual Network Topology Builder, it builds the Network Topology as a real network environment. It means the Nodes are built with Docker Containers. Currently it supports Hosts, Servers, Routers Nodes. 28 | 29 | KNet Virtual Network Topology Builder supports building the Traditional Networks as well as SDN Test bed. 30 | 31 | Host is built with basic required tools such as iperf, Traceroute, curl, Hping3. Server is built with apache2 webserver. Router is built with Quagga Router. 32 | 33 | User can install any required packages (mysql,hacking tools.. etc) in the nodes. 34 | User have full control on the nodes to generate the real time original protocol traffic(no simulation). 35 | 36 | 37 | 38 | Architecture 39 | ============ 40 | 41 | .. image:: ./imgs/KNet_Actions.png 42 | :align: center 43 | 44 | -------------------------------------------------------------------------------- /docs/ovs_commands.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | .. contents:: 17 | :depth: 1 18 | :local: 19 | 20 | Useful Openvswitch Commands 21 | ============================ 22 | 23 | 24 | List the Switches: 25 | ---------------------- 26 | 27 | The following command lists all the switches. You can identify the switch with "name" names, its same as switch name given in the topology file. 28 | 29 | 30 | .. code-block:: bash 31 | 32 | sudo ovs-vsctl show 33 | 34 | Screenshot: 35 | 36 | .. figure:: imgs/ovs/ovs_show_s.png 37 | :align: center 38 | 39 | 40 | List the Flows installed in the Switch 41 | ------------------------------------------------------ 42 | .. code-block:: bash 43 | 44 | sudo ovs-ofctl -O dump-flows 45 | 46 | Example : 47 | sudo ovs-ofctl -O OpenFlow13 dump-flows switch1 48 | 49 | Screenshot: 50 | 51 | .. figure:: imgs/ovs/ovs_flows_s.png 52 | :align: center -------------------------------------------------------------------------------- /docs/quick_start.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | .. contents:: 17 | :depth: 1 18 | :local: 19 | 20 | Quick Start 21 | ============ 22 | In this QuickStart section, we see few quick steps to install and execute the sample topology with RYU Controller. 23 | 24 | KNet is compatible with **Python 2.7** only. 25 | 26 | KNet is currently supported only in **Ubuntu 16.04** version. 27 | 28 | We have used Ubuntu 16.04 OS for the below demonstations. 29 | 30 | 31 | .. figure:: imgs/quick_start/ubuntuversion_s.png 32 | :align: center 33 | 34 | **The current released version is 1.0.11** 35 | 36 | Installation 37 | ------------- 38 | 1. Install the Prerequisties. Copy and Paste the below command in the Terminal 39 | 40 | .. code-block:: bash 41 | 42 | curl https://raw.githubusercontent.com/knetsolutions/KNet/master/install.sh | bash 43 | 44 | This command will install the Docker, openvswitch and required packages. 45 | 46 | 47 | 2. Once Prerequisties are installed. Execute the below commands to verify the docker and openvswitches are installed. 48 | 49 | .. code-block:: bash 50 | 51 | sudo docker images 52 | sudo ovs-vsctl show 53 | 54 | 55 | 3. Install the KNet Topology Builder with below commands, 56 | 57 | .. code-block:: bash 58 | 59 | pip install knet 60 | 61 | 62 | .. figure:: imgs/quick_start/knet_pip_install_s.png 63 | :align: center 64 | 65 | 66 | 4. Install the KNet WebUI & and Verify the WebUI in browser 67 | 68 | .. code-block:: bash 69 | 70 | git clone https://github.com/knetsolutions/knet-ui 71 | cd knet-ui 72 | python ui/webserver.py >/dev/null 2>&1 & 73 | 74 | 75 | .. figure:: imgs/quick_start/knet_ui_install_s.png 76 | :align: center 77 | 78 | Open FireFox/Chrome, with URL: ĥttp://ip:5000/index.html, and see the empty topology page. 79 | 80 | 81 | .. figure:: imgs/quick_start/WebUI_emptypage_s.png 82 | :align: center 83 | 84 | 85 | 5. Start the KNet CLI and verify the commands 86 | 87 | .. code-block:: bash 88 | 89 | knet-cli 90 | 91 | 92 | .. figure:: imgs/quick_start/knet_cli_start_s.png 93 | :align: center 94 | 95 | 96 | Create a sample Topology and Testing 97 | ------------------------------------- 98 | Now Let us Create the Sample Star Topology with RYU SDN Controller. 99 | 100 | Topology should be defined in simple YAML file(its just a text file representing the topology). 101 | 102 | Example topology files are available in https://github.com/knetsolutions/knet-example-topologies 103 | 104 | SDN example topologies are available inside SDN folder of the knet-example-topologies repo. 105 | 106 | Example SDN topologies are available for 107 | 1. Linear 108 | 2. Star 109 | 3. Tree 110 | 4. Mesh 111 | 5. Partial Mesh 112 | 113 | 114 | Setup the RYU SDN Controller 115 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 116 | 1. Install the RYU SDN Controller 117 | Open the another terminal and execute the below commands, 118 | 119 | .. code-block:: bash 120 | 121 | cd $HOME 122 | export LC_ALL="en_US.UTF-8" 123 | virtualenv ryu 124 | . ryu/bin/activate 125 | pip install ryu 126 | 127 | 128 | .. figure:: imgs/quick_start/ryu_install_s.png 129 | :align: center 130 | 131 | 2. Run the Ryu Simple L3 Switch application, 132 | 133 | .. code-block:: bash 134 | 135 | ryu-manager ryu/lib/python2.7/site-packages/ryu/app/simple_switch_13.py 136 | 137 | .. figure:: imgs/quick_start/ryu_run_l3switch_s.png 138 | :align: center 139 | 140 | CLI 141 | ^^^^^ 142 | 143 | 1. Create a Topology as below in the CLI 144 | 145 | .. code-block:: bash 146 | 147 | CreateTopology /home/suresh/knet-example-topologies/1.0/topo0.yaml 148 | 149 | .. figure:: imgs/quick_start/knet_topology_creation_s.png 150 | :align: center 151 | 152 | 2. Verify the topology digram in UI. 153 | 154 | ĥttp://ip:5000/index.html 155 | 156 | .. figure:: imgs/quick_start/Webui_StarTopology_s.png 157 | :align: center 158 | 159 | 160 | 3. Open the another terminal, and verify the switches and nodes. 161 | Run the below commands in the new terminal and see the created nodes and switches. 162 | 163 | .. code-block:: bash 164 | 165 | sudo docker ps -a 166 | sudo ovs-vsctl show 167 | 168 | .. figure:: imgs/quick_start/startopology_dockerswitch_cmds_s.png 169 | :align: center 170 | 171 | 4. Trigger the PingAll command from the KNet CLI and check the output 172 | Each node pings each other nodes. 173 | 174 | .. code-block:: bash 175 | 176 | PingAll 177 | 178 | .. figure:: imgs/quick_start/CLI_pingall_command_s.png 179 | :align: center 180 | 181 | 182 | 5. Verify the OVS flows with the below command, 183 | sudo ovs-ofctl -O OpenFlow13 dump-flows switch1 184 | 185 | .. figure:: imgs/quick_start/ovs_dumpflows_output_s.png 186 | :align: center 187 | 188 | 189 | Delete the Topology 190 | --------------------- 191 | 192 | 1. In the KNet CLI, Execute the below command 193 | 194 | .. code-block:: bash 195 | 196 | DeleteTopology 197 | 198 | .. figure:: imgs/quick_start/CLI_Delete_Topology_s.png 199 | :align: center 200 | 201 | 2. Exit from the CLI by "Exit" Command 202 | 203 | 204 | 205 | Cleanup 206 | ------------------- 207 | 208 | Cleanup command cleans up the Docker container, ovs switches, log files, db records etc. 209 | 210 | 1. In the KNet CLI, Execute the below command 211 | 212 | .. code-block:: bash 213 | 214 | Cleanup 215 | 216 | 217 | 2. Exit from the CLI by "Exit" Command 218 | 219 | 220 | -------------------------------------------------------------------------------- /docs/topology_file.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 KNet Solutions, India, http://knetsolutions.in 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | .. contents:: 17 | :depth: 1 18 | :local: 19 | 20 | Topology File explained 21 | ======================= 22 | 23 | Topology input file is defined in YAML(Yet another Markup Language). YAML is human readable data serialization language , commonly used as configuraton file for applications. 24 | 25 | 26 | Topology Object consists the following main sections, 27 | 28 | name 29 | ^^^^^ 30 | name defines the topology name. Data type is string 31 | 32 | Example: 33 | 34 | .. code-block:: bash 35 | 36 | name : Simple Star Topology 1 37 | 38 | version 39 | ^^^^^^^^ 40 | version defines the topology file schema version. The current version is 1.0. 41 | 42 | Example: 43 | 44 | .. code-block:: bash 45 | 46 | version: 1.0 47 | 48 | 49 | description 50 | ^^^^^^^^^^^^^^^^ 51 | **description** is for detailed description of the topology. Its a multiline string. 52 | 53 | Example: 54 | 55 | .. code-block:: bash 56 | 57 | description: | 58 | This topology consists of 4 nodes, and a switch. 59 | All Nodes are connected to a same switch. 60 | 61 | 62 | controller 63 | ^^^^^^^^^^^ 64 | **controller** is a object defined for SDN Controller. This object contains url property. **url** defines the SDN Controller URL. Data type is string. 65 | 66 | All the switches in the topology will be connected to this controller url. 67 | 68 | Example: 69 | 70 | .. code-block:: bash 71 | 72 | controller: 73 | url: tcp:0.0.0.0:6633 74 | 75 | 76 | openflow 77 | ^^^^^^^^^^^ 78 | **openflow** is a object defined for openflow protocol. This object contains **version** property. data type is number. 79 | 80 | This openflow version is applied for all the switches in the topology. 81 | 82 | Example: 83 | 84 | .. code-block:: bash 85 | 86 | openflow: 87 | version: 1.3 88 | 89 | 90 | network 91 | ^^^^^^^^^^^ 92 | **network** is a list for defining the network objects. Each network object containes **name** and **subnet** property. KNet will manages the IP assignment to the nodes in this network. The network name will be used by the nodes object. 93 | 94 | Example: 95 | 96 | .. code-block:: bash 97 | 98 | networks: 99 | - 100 | name: n1 101 | subnet: 10.1.1.0/24 102 | 103 | qos 104 | ^^^^^^^^ 105 | 106 | **qos** is a list for defining the qos object. Each qos object containes the **name, bandwidth, latency, jitter, pktloss** property. KNet use this qos object for applying qos in the link using linux traffic shaping tool. 107 | 108 | qos object will be consumed by link object. 109 | 110 | Example: 111 | 112 | .. code-block:: bash 113 | 114 | qos: 115 | - 116 | name: q1 117 | bandwidth: 100Mbps 118 | latency: 100ms 119 | jitter: 1ms 120 | pktloss: 0.5% 121 | 122 | 123 | nodes 124 | ^^^^^^^^^^^ 125 | nodes object consists of list of nodes. Each node is represented with the **name, image, network, ip, mac** properties. 126 | 127 | 1. **name** defines the node name. Its a mandatory parameter 128 | 129 | 2. **image** defines the docker image for the node. Recommended value is "ubuntu:trusty" image. thats is ubuntu 14.04 version. Dont change it until unless you know about this. Its a mandatory parmeter 130 | 131 | 3. **network** defines the network belongs to this node. if network is mentioned, IP will be automatically allocated from this network. 132 | 133 | 4. **ip** defines the static ip for this node. The given ip will be assigned to the node. Either network or ip should present. 134 | 135 | 5. **mac** defines the mac id for the interface. Its a optional parameter 136 | 137 | 138 | Example1: 139 | 140 | .. code-block:: bash 141 | 142 | nodes: 143 | - 144 | name: a1 145 | image: ubuntu:trusty 146 | network: n1 147 | 148 | 149 | Example2: 150 | 151 | 152 | .. code-block:: bash 153 | 154 | nodes: 155 | - 156 | name: a1 157 | image: ubuntu:trusty 158 | ip: 10.10.10.2/24 159 | mac: 00:00:00:00:00:01 160 | 161 | switches 162 | ^^^^^^^^^^^ 163 | 164 | switches object consists of list of switches. Each switch is represented with the **name** proerty. 165 | 166 | name defines the switch name. Its a mandatory parameter. 167 | 168 | Example1: 169 | 170 | .. code-block:: bash 171 | 172 | switches: 173 | - 174 | name: switch1 175 | 176 | links 177 | ^^^^^^^^^^^ 178 | links object consists of list of links. Each link is represented with the nodes and switches. 179 | 180 | There are two types of links. 181 | 182 | 1. Switch to Node Link: This means, Switch is connected with one or more nodes. 183 | 184 | 2. Switch to Switch Link: This means, switch to connected with another switch. 185 | 186 | **Switch to Node Link** 187 | 188 | .. code-block:: bash 189 | 190 | links: 191 | - 192 | switches: 193 | - switch1 194 | nodes: 195 | - name: a1 196 | - name: a2 197 | - name: a3 198 | - 199 | name: a4 200 | qos: q2 201 | 202 | In the above example, switch1 is connected with 4 nodes (a1, a2, a3, a4), and switch to a4 link will have qos configured. 203 | 204 | 205 | **Switch to Switch Link** 206 | 207 | .. code-block:: bash 208 | 209 | links: 210 | - 211 | switches: 212 | - switch2 213 | - switch3 214 | 215 | In the above example, switch2 is connected with switch3 216 | -------------------------------------------------------------------------------- /docs/traditional_networks.rst: -------------------------------------------------------------------------------- 1 | 2 | .. contents:: 3 | :depth: 1 4 | :local: 5 | 6 | Traditional Networks Topology 7 | ================================== 8 | 9 | KNet Supports building Traditional Network Topology with Routers, Firewall Nodes. 10 | 11 | Router node is built with "bird routing daemon" and "shorewall" firewall sofware. 12 | 13 | http://bird.network.cz/ 14 | 15 | http://shorewall.net/shorewall_quickstart_guide.htm 16 | 17 | Example traditional network topology examples are available in knet-example-topologies repository. 18 | 19 | 20 | Network Topology with Routers: 21 | ------------------------------------ 22 | 23 | Topology example (ex2 - Simple WAN Topology) consists of two routers . Router node is inbuilt with firewall. 24 | 25 | Provisioning the Router Node: 26 | **************************************************** 27 | 28 | 1. Login to Router Node shell 29 | 30 | 31 | .. code-block:: bash 32 | 33 | sudo docker exec -it R1 bash 34 | 35 | 2. Edit the bird configuration file (/etc/bird.conf). The default configuration consists of ospf configuration. 36 | 37 | .. code-block:: bash 38 | 39 | vi /etc/bird.conf 40 | 41 | Change the router id: 42 | 43 | .. code-block:: bash 44 | 45 | router id 1.1.1.1; 46 | 47 | Enable the ospf configuration in the required interfaces 48 | 49 | .. code-block:: bash 50 | 51 | protocol ospf MyOSPF { 52 | rfc1583compat yes; 53 | area 0.0.0.0 { 54 | stub no; 55 | interface "eth1" { 56 | hello 10; 57 | retransmit 6; 58 | cost 10; 59 | transmit delay 5; 60 | dead count 5; 61 | wait 50; 62 | type broadcast; 63 | }; 64 | 65 | interface "eth2" { 66 | hello 10; 67 | retransmit 6; 68 | cost 10; 69 | transmit delay 5; 70 | dead count 5; 71 | wait 50; 72 | type broadcast; 73 | }; 74 | 75 | }; 76 | } 77 | 78 | 79 | 3. Start the bird routing daemon 80 | 81 | .. code-block:: bash 82 | 83 | bird -c /etc/bird.conf -d & 84 | 85 | 86 | 4. Check the log files 87 | 88 | .. code-block:: bash 89 | 90 | cat /var/log/bird.log 91 | 92 | 93 | The detailed information of bird routing configuration is available in bird website. 94 | 95 | Repeat the same for all the Routers. 96 | 97 | 98 | Testing 99 | ************** 100 | 1. Check the Routing tables of Router Node. 101 | 102 | .. code-block:: bash 103 | 104 | ip route 105 | 106 | 2. Perform the Ping end to end ping from the hosts 107 | 108 | 109 | How to configure Firewall: 110 | ------------------------------------ 111 | 112 | 1. Login to the Router Node 113 | 114 | 2. Edit the shorewall configuration. 115 | 116 | 3. Start the shorewall. 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/traffic_tests.rst: -------------------------------------------------------------------------------- 1 | 2 | .. contents:: 3 | :depth: 1 4 | :local: 5 | 6 | Traffic Tests 7 | ================= 8 | 9 | KNet Supports UDP, TCP tests as simple Commands. KNet runs IPERF in the node to perform this test. 10 | 11 | 12 | TCP Test : 13 | ------------------------------------ 14 | TcpTest command performs the TCP test between two nodes for 10s 15 | 16 | 17 | .. code-block:: bash 18 | 19 | KNet-cli#help TcpTest 20 | ['TcpTest'] 21 | **************************************************** 22 | 23 | Runs IPERF TCP test. 24 | Args: source destination Number-of-connections 25 | return: result 26 | Example: TcpTest a1 a2 1 27 | TcpTest a1 a2 10 28 | 29 | **************************************************** 30 | 31 | 32 | UDP Test: 33 | ------------------------------------ 34 | 35 | UdpTest command performs the UDP test between two nodes for 10s 36 | 37 | 38 | .. code-block:: bash 39 | 40 | KNet-cli#help UdpTest 41 | ['UdpTest'] 42 | **************************************************** 43 | 44 | Runs IPERF UDP test. 45 | Args: source destination Bandwitdh(Mbps) Number-of-connections 46 | return: result 47 | Example: UdTest a1 a2 10 1 48 | UdpTest a1 a2 1 1 49 | 50 | **************************************************** 51 | 52 | 53 | References 54 | ^^^^^^^^^^^^^^^^^^^^ 55 | IPERF supports UDP Traffic tests as well , Below links can help you for udp tests. 56 | 57 | 1. https://iperf.fr/iperf-doc.php 58 | 59 | 2. https://openmaniak.com/iperf.php 60 | 61 | 62 | 63 | HTTP Tests Using Apache WebServer & Locust : 64 | --------------------------------------------- 65 | 66 | As all nodes are ubuntu nodes, we can just install Apache Webserver and Locust https://locust.io/ (HTTP Load Testing Tool) start using it. 67 | 68 | Objective is create the example topology0, and Install the Apache Web Server in a4 node. Install Locust in a1 node. Trigger the Locust to test the apache web server(a4). Locust will generate huge http connections to the Apache web server and load it. 69 | 70 | 71 | a1 node ip is 10.20.20.2 72 | a4 node ip is 10.20.20.5 73 | 74 | 75 | 76 | Create the Topology using KNet CLI. 77 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 78 | 79 | 80 | .. figure:: imgs/traffic/topology_cli_s.png 81 | :align: center 82 | 83 | 84 | 85 | View the Topology Web UI 86 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 87 | 88 | .. figure:: imgs/traffic/topology_ui_s.png 89 | :align: center 90 | 91 | 92 | Start the Ryu Controller L4Switch application, 93 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 94 | 95 | L4Switch(https://github.com/knetsolutions/knet/L4Switch.py) application creates flow based on srcip, dstip, protocol,srcport, dstport. 96 | 97 | 98 | 99 | .. figure:: imgs/traffic/ryu_l4_s.png 100 | :align: center 101 | 102 | 103 | Install the Apache WebServer on a4 node 104 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 105 | 106 | .. code-block:: bash 107 | 108 | sudo docker exec -it a4 bash 109 | sudo apt-get update 110 | sudo apt-get install apache2 111 | sudo service apache restart 112 | 113 | .. figure:: imgs/traffic/apache_install_s.png 114 | :align: center 115 | 116 | .. figure:: imgs/traffic/apache_start_s.png 117 | :align: center 118 | 119 | 120 | 121 | Install the Locust Tool on a1 node 122 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 123 | 124 | .. code-block:: bash 125 | 126 | sudo docker exec -it a1 bash 127 | sudo apt-get update 128 | sudo apt-get install python-dev python-pip 129 | sudo pip install locustio 130 | 131 | 132 | .. figure:: imgs/traffic/locust_install_s.png 133 | :align: center 134 | 135 | 136 | Run the Locust HTTP Load test 137 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 138 | In the a1 node, Create a locust input file (loadtest.py) 139 | 140 | .. code-block:: python 141 | 142 | from locust import HttpLocust, TaskSet 143 | def index(l): 144 | l.client.get("/index.html") 145 | 146 | class UserBehavior(TaskSet): 147 | tasks = {index: 2} 148 | 149 | class WebsiteUser(HttpLocust): 150 | task_set = UserBehavior 151 | min_wait = 0 152 | max_wait = 0 153 | 154 | Start the locust as below, 155 | 10.20.20.5 is a4 IP 156 | 157 | .. code-block:: bash 158 | 159 | locust -f loadtest.py --no-web --host http://10.20.20.5 160 | 161 | 162 | .. figure:: imgs/traffic/locust_run_s.png 163 | :align: center 164 | 165 | 166 | 167 | The output shows , how many connections per second requested and the response time, etc. 168 | 169 | .. figure:: imgs/traffic/locust_output_s.png 170 | :align: center 171 | 172 | 173 | Check the flow tables in ovs 174 | 175 | .. code-block:: bash 176 | 177 | sudo ovs-ofctl -O OpenFlow13 dump-flows switch1 178 | sudo ovs-ofctl -O OpenFlow13 dump-flows switch1 | wc 179 | 180 | .. figure:: imgs/traffic/flow_tables_s.png 181 | :align: center 182 | 183 | 184 | .. figure:: imgs/traffic/flow_tables_count_s.png 185 | :align: center 186 | 187 | 188 | I could able to simulate around 2000 Flows in 2 minutes. we can test flow setup rate using this test. 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | export LC_ALL="en_US.UTF-8" 5 | 6 | function check_ubuntu_version(){ 7 | 8 | if [[ -x $(command -v apt-get 2>/dev/null) ]]; then 9 | sudo apt-get install -y lsb-release 10 | os_RELEASE=$(lsb_release -r -s) 11 | os_CODENAME=$(lsb_release -c -s) 12 | os_VENDOR=$(lsb_release -i -s) 13 | if [[ $os_RELEASE =~ 16.04 ]]; then 14 | echo "*************************" 15 | echo "Your OS is UBUNTU 16.04. " 16 | echo "******* Installation starts ........" 17 | elif [[ $os_RELEASE =~ 18.04 ]]; then 18 | echo "*************************" 19 | echo "Your OS is UBUNTU 18.04. " 20 | echo "******* Installation starts ........" 21 | else 22 | echo "*************************" 23 | echo $os_VENDOR 24 | echo $os_CODENAME 25 | echo $os_RELEASE 26 | echo "Installation failed... Install supports only Ubuntu 16.04 version." 27 | exit 1 28 | fi 29 | else 30 | echo "Installation failed... Instal script supports only Ubuntu 16.04 version." 31 | exit 1 32 | fi 33 | } 34 | 35 | 36 | 37 | function u16_install_docker(){ 38 | # install Docker 39 | sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common 40 | 41 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 42 | sudo apt-key fingerprint 0EBFCD88 43 | sudo add-apt-repository \ 44 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 45 | $(lsb_release -cs) \ 46 | stable" 47 | sudo apt-get update 48 | sudo apt-get install -y docker-ce 49 | } 50 | 51 | 52 | function u16_install_ovs_docker(){ 53 | # Download the ovs-docker script 54 | wget https://raw.githubusercontent.com/openvswitch/ovs/master/utilities/ovs-docker 55 | chmod a+rwx ovs-docker 56 | sudo cp ovs-docker /usr/bin/. 57 | 58 | } 59 | 60 | 61 | function u16_install_deps() { 62 | 63 | sudo apt-get update 64 | sudo apt-get install -y openvswitch-switch python python-dev python-pip build-essential 65 | } 66 | 67 | 68 | function pull_imgs() { 69 | # Pull the Ubuntu dockeer images 70 | sudo docker pull knet/host 71 | sudo docker pull knet/web 72 | sudo docker pull knet/router 73 | } 74 | 75 | 76 | function verify_installation(){ 77 | echo "------------Verifying openvswitch tool------------- " 78 | sudo ovs-vsctl show 79 | echo "------------Verifying ovs-docker tool------------- " 80 | sudo ovs-docker -h 81 | echo "------------Verifying docker ------------- " 82 | sudo docker --version 83 | echo "------------Verifying docker images------------- " 84 | sudo docker images 85 | } 86 | 87 | function install_u1604(){ 88 | echo "*********** 1. Install OVS and other Dependencies ***************" 89 | u16_install_deps 90 | echo "*********** 2. Install Docker ***************" 91 | u16_install_docker 92 | echo "*********** 3. Install ovs_docker ***************" 93 | u16_install_ovs_docker 94 | echo "*********** 4. Download docker images ***************" 95 | pull_imgs 96 | echo "*********** Installation Completed ***************" 97 | 98 | } 99 | 100 | 101 | function install(){ 102 | echo "*********** 0. Checking your OS compatibility ****************" 103 | check_ubuntu_version 104 | install_u1604 105 | } 106 | 107 | 108 | install 109 | verify_installation -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from setuptools import find_packages 3 | 4 | install_requires = [ 5 | 'six==1.11.0', 6 | 'pyyaml==4.2b1', 7 | 'ipaddress==1.0.19', 8 | 'tinydb==3.7.0', 9 | 'beautifultable==0.3.0', 10 | 'logger==1.4', 11 | 'flask==1.1.0', 12 | 'jsonschema==2.6.0', 13 | 'smallcli==0.1', 14 | ] 15 | 16 | test_requires = [] 17 | 18 | setup( 19 | name='KNet', 20 | version='1.0.18b', 21 | description="Virtual Network Topology Builder", 22 | author="KNet Solutions", 23 | author_email="knetsolutions2@gmail.com", 24 | url="https://github.com/knetsolutions/KNet", 25 | packages=find_packages(exclude=['test']), 26 | include_package_data=True, 27 | install_requires=install_requires, 28 | license="Apache", 29 | keywords='sdn', 30 | python_requires='>=2.6, <3', 31 | entry_points={ 32 | 'console_scripts': ['knet-cli=KNet.app:knetcli'], 33 | }, 34 | classifiers=[ 35 | 'Development Status :: 4 - Beta', 36 | 'Intended Audience :: Developers', 37 | 'Topic :: Software Development :: User Interfaces', 38 | 'Programming Language :: Python :: 2.7' 39 | ] 40 | ) 41 | --------------------------------------------------------------------------------