diff --git a/daemon/core/services/OvsService.py b/daemon/core/services/OvsService.py new file mode 100755 index 00000000..3bb728f3 --- /dev/null +++ b/daemon/core/services/OvsService.py @@ -0,0 +1,113 @@ +# +# CORE +# Copyright (c)2010-2012 the Boeing Company. +# See the LICENSE file included in this distribution. +# +''' Sample user-defined service. +''' + +import os +import re + +from core.service import CoreService, addservice + +class OvsService(CoreService): + ''' This is a sample user-defined service. + ''' + # a unique name is required, without spaces + _name = "OvsService" + # you can create your own group here + _group = "SDN" + # list of other services this service depends on + _depends = () + # per-node directories + _dirs = ("/etc/openvswitch", "/var/run/openvswitch", "/var/log/openvswitch") + # generated files (without a full path this file goes in the node's dir, + # e.g. /tmp/pycore.12345/n1.conf/) + _configs = ('OvsService.sh', ) + # this controls the starting order vs other enabled services + _startindex = 50 + # list of startup commands, also may be generated during startup + _startup = ('sh OvsService.sh',) + # list of shutdown commands + _shutdown = ('killall ovs-vswitchd','killall ovsdb-server') + + @classmethod + def generateconfig(cls, node, filename, services): + ''' Return a string that will be written to filename, or sent to the + GUI for user customization. + ''' + # Check whether the node is running zebra + has_zebra = 0 + for s in services: + if s._name == "zebra": + has_zebra = 1 + + # Check whether the node is running an SDN controller + has_sdn_ctrlr = 0 + for s in services: + if s._name == "ryuService": + has_sdn_ctrlr = 1 + + cfg = "#!/bin/sh\n" + cfg += "# auto-generated by OvsService (OvsService.py)\n" + cfg += "/etc/init.d/openvswitch-switch start < /dev/null\n" + cfg += "ovs-vsctl add-br ovsbr0\n" + cfg += "ifconfig ovsbr0 up\n" + + for ifc in node.netifs(): + if hasattr(ifc, 'control') and ifc.control == True: + continue + ifnumstr = re.findall(r"\d+", ifc.name) + ifnum = ifnumstr[0] + + # create virtual interfaces + cfg += "ip link add rtr%s type veth peer name sw%s\n" % (ifnum, ifnum) + cfg += "ifconfig rtr%s up\n" % ifnum + cfg += "ifconfig sw%s up\n" % ifnum + + # remove ip address of eths because quagga/zebra will assign same IPs to rtr interfaces + # or assign them manually to rtr interfaces if zebra is not running + for ifcaddr in ifc.addrlist: + if ifcaddr.find(".") >= 0: + cfg += "ip addr del %s dev %s\n" % (ifcaddr, ifc.name) + if has_zebra == 0: + cfg += "ip addr add %s dev rtr%s\n" % (ifcaddr, ifnum) + elif ifcaddr.find(":") >= 0: + cfg += "ip -6 addr del %s dev %s\n" % (ifcaddr, ifc.name) + if has_zebra == 0: + cfg += "ip -6 addr add %s dev rtr%s\n" % (ifcaddr, ifnum) + else: + raise Value, "invalid address: %s", x + + # add interfaces to bridge + cfg += "ovs-vsctl add-port ovsbr0 eth%s\n" % ifnum + cfg += "ovs-vsctl add-port ovsbr0 sw%s\n" % ifnum + + #if has_sdn_ctrlr == 1: #TODO- even if the controller is not local, it finds it + # Add rule for default controller if there is one local + cfg += "ovs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\n" + #else: + # Delete flows otherwise + #cfg += "ovs-ofctl del-flows ovsbr0\n" + + # Setup default flows + portnum = 1 + for ifc in node.netifs(): + if hasattr(ifc, 'control') and ifc.control == True: + continue + cfg += "ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\n" % (portnum, portnum+1) + cfg += "ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\n" % (portnum+1, portnum) + portnum += 2 + + return cfg + + @staticmethod + def subnetentry(x): + # TODO - Maybe move default flow rules to here? + return + + +# this line is required to add the above class to the list of available services +addservice(OvsService) + diff --git a/daemon/core/services/ryuService.py b/daemon/core/services/ryuService.py new file mode 100755 index 00000000..3b3a21ce --- /dev/null +++ b/daemon/core/services/ryuService.py @@ -0,0 +1,66 @@ +# +# CORE +# Copyright (c)2010-2012 the Boeing Company. +# See the LICENSE file included in this distribution. +# +''' Ryu SDN controller user-defined service. +''' + +import os + +from core.service import CoreService, addservice +from core.misc.ipaddr import IPv4Prefix, IPv6Prefix + +class ryuService(CoreService): + ''' This is a ryu user-defined service. + ''' + # a unique name is required, without spaces + _name = "ryuService" + # you can create your own group here + _group = "SDN" + # list of other services this service depends on + _depends = () + # per-node directories + _dirs = () + # generated files (without a full path this file goes in the node's dir, + # e.g. /tmp/pycore.12345/n1.conf/) + _configs = ('ryuService.sh', ) + # this controls the starting order vs other enabled services + _startindex = 50 + # list of startup commands, also may be generated during startup + _startup = ('sh ryuService.sh',) + # list of shutdown commands + _shutdown = ('killall ryu-manager') + + @classmethod + def generateconfig(cls, node, filename, services): + ''' Return a string that will be written to filename, or sent to the + GUI for user customization. + ''' + app_path = "/usr/local/lib/python2.7/dist-packages/ryu/app" + cfg = "#!/bin/sh\n" + cfg += "# auto-generated by ryuService (ryuService.py)\n" + cfg += '/usr/local/bin/ryu-manager --observe-links %s/ofctl_rest.py %s/rest_topology.py' % (app_path, app_path) + + #for ifc in node.netifs(): + # cfg += 'echo "Node %s has interface %s"\n' % (node.name, ifc.name) + # # here we do something interesting + # cfg += "\n".join(map(cls.subnetentry, ifc.addrlist)) + # break + return cfg + + @staticmethod + def subnetentry(x): + ''' Generate a subnet declaration block given an IPv4 prefix string + for inclusion in the config file. + ''' + if x.find(":") >= 0: + # this is an IPv6 address + return "" + else: + net = IPv4Prefix(x) + return 'echo " network %s"' % (net) + +# this line is required to add the above class to the list of available services +addservice(ryuService) + diff --git a/gui/configs/sample11-sdn.imn b/gui/configs/sample11-sdn.imn new file mode 100644 index 00000000..a41dbc11 --- /dev/null +++ b/gui/configs/sample11-sdn.imn @@ -0,0 +1,291 @@ +node n1 { + type router + model host + network-config { + hostname ryu1 + ! + interface eth1 + ip address 10.0.5.10/24 + ipv6 address 2001:5::10/64 + ! + interface eth0 + ip address 10.0.4.10/24 + ipv6 address 2001:4::10/64 + ! + } + canvas c1 + iconcoords {203.0 65.0} + labelcoords {203.0 97.0} + interface-peer {eth0 n2} + interface-peer {eth1 n3} +} + +node n2 { + type router + model OVS + network-config { + hostname ovs1 + ! + interface eth2 + ip address 10.0.4.1/24 + ipv6 address 2001:4::1/64 + ! + interface eth1 + ip address 10.0.1.1/24 + ipv6 address 2001:1::1/64 + ! + interface eth0 + ip address 10.0.0.1/24 + ipv6 address 2001:0::1/64 + ! + } + canvas c1 + iconcoords {124.0 213.0} + labelcoords {124.0 245.0} + interface-peer {eth0 n6} + interface-peer {eth1 n4} + interface-peer {eth2 n1} +} + +node n3 { + type router + model OVS + network-config { + hostname ovs2 + ! + interface eth2 + ip address 10.0.5.1/24 + ipv6 address 2001:5::1/64 + ! + interface eth1 + ip address 10.0.3.1/24 + ipv6 address 2001:3::1/64 + ! + interface eth0 + ip address 10.0.2.1/24 + ipv6 address 2001:2::1/64 + ! + } + canvas c1 + iconcoords {299.0 220.0} + labelcoords {299.0 252.0} + interface-peer {eth0 n7} + interface-peer {eth1 n5} + interface-peer {eth2 n1} +} + +node n4 { + type router + model host + network-config { + hostname n4 + ! + interface eth0 + ip address 10.0.1.10/24 + ipv6 address 2001:1::10/64 + ! + } + canvas c1 + iconcoords {39.0 313.0} + labelcoords {39.0 345.0} + interface-peer {eth0 n2} +} + +node n5 { + type router + model host + network-config { + hostname n5 + ! + interface eth0 + ip address 10.0.3.10/24 + ipv6 address 2001:3::10/64 + ! + } + canvas c1 + iconcoords {286.0 327.0} + labelcoords {286.0 359.0} + interface-peer {eth0 n3} +} + +node n6 { + type router + model host + network-config { + hostname n6 + ! + interface eth0 + ip address 10.0.0.10/24 + ipv6 address 2001:0::10/64 + ! + } + canvas c1 + iconcoords {131.0 322.0} + labelcoords {131.0 354.0} + interface-peer {eth0 n2} +} + +node n7 { + type router + model host + network-config { + hostname n7 + ! + interface eth0 + ip address 10.0.2.10/24 + ipv6 address 2001:2::10/64 + ! + } + canvas c1 + iconcoords {373.0 328.0} + labelcoords {373.0 360.0} + interface-peer {eth0 n3} +} + +node n8 { + type router + model mdr + network-config { + hostname n8 + ! + interface eth0 + ip address 10.0.6.1/32 + ipv6 address 2001:6::1/128 + ! + } + canvas c1 + iconcoords {579.0 102.0} + labelcoords {579.0 134.0} + interface-peer {eth0 n11} +} + +node n9 { + type router + model mdr + network-config { + hostname n9 + ! + interface eth0 + ip address 10.0.6.2/32 + ipv6 address 2001:6::2/128 + ! + } + canvas c1 + iconcoords {493.0 212.0} + labelcoords {493.0 244.0} + interface-peer {eth0 n11} +} + +node n10 { + type router + model mdr + network-config { + hostname n10 + ! + interface eth0 + ip address 10.0.6.3/32 + ipv6 address 2001:6::3/128 + ! + } + canvas c1 + iconcoords {674.0 225.0} + labelcoords {674.0 257.0} + interface-peer {eth0 n11} +} + +node n11 { + type wlan + network-config { + hostname mobile-sdn + ! + interface wireless + ip address 10.0.6.0/32 + ipv6 address 2001:6::0/128 + ! + mobmodel + coreapi + basic_range + ! + } + custom-config { + custom-config-id basic_range + custom-command {3 3 9 9 9} + config { + range=275 + bandwidth=54000000 + jitter=0 + delay=20000 + error=0 + } + } + canvas c1 + iconcoords {683.0 127.0} + labelcoords {683.0 159.0} + interface-peer {e0 n8} + interface-peer {e1 n9} + interface-peer {e2 n10} +} + +link l1 { + nodes {n2 n6} + bandwidth 0 +} + +link l2 { + nodes {n2 n4} + bandwidth 0 +} + +link l3 { + nodes {n3 n7} + bandwidth 0 +} + +link l4 { + nodes {n3 n5} + bandwidth 0 +} + +link l5 { + nodes {n1 n2} + bandwidth 0 +} + +link l6 { + nodes {n1 n3} + bandwidth 0 +} + +link l7 { + nodes {n11 n8} +} + +link l8 { + nodes {n11 n9} +} + +link l9 { + nodes {n11 n10} +} + +canvas c1 { + name {Canvas1} +} + +option global { + interface_names no + ip_addresses yes + ipv6_addresses no + node_labels yes + link_labels yes + show_api no + background_images no + annotations yes + grid yes + traffic_start 0 + mac_address_start 80 +} + +option session { +} + diff --git a/gui/icons/normal/OVS.gif b/gui/icons/normal/OVS.gif new file mode 100755 index 00000000..38fcbb2e Binary files /dev/null and b/gui/icons/normal/OVS.gif differ diff --git a/gui/icons/svg/OVS.svg b/gui/icons/svg/OVS.svg new file mode 100755 index 00000000..4da0b111 --- /dev/null +++ b/gui/icons/svg/OVS.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/gui/icons/tiny/OVS.gif b/gui/icons/tiny/OVS.gif new file mode 100755 index 00000000..38fcbb2e Binary files /dev/null and b/gui/icons/tiny/OVS.gif differ