Merge branch 'cleanup' of git-ssh.web.boeing.com:Boeing-CORE/CORE into cleanup

This commit is contained in:
Blake J. Harnden 2017-06-16 14:31:23 -07:00
commit 5920a09aae
17 changed files with 758 additions and 66 deletions

View file

@ -13,5 +13,7 @@ Pieces can be imported individually, for example
from core.netns import vnode from core.netns import vnode
""" """
__all__ = []
# Automatically import all add-ons listed in addons.__all__ # Automatically import all add-ons listed in addons.__all__
from addons import * from addons import *

View file

@ -301,6 +301,12 @@ class LxBrNet(PyCoreNet):
snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % self.brname snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % self.brname
if os.path.exists(snoop): if os.path.exists(snoop):
open(snoop, "w").write('0') open(snoop, "w").write('0')
# turn on LLDP forwarding (disabled by default in linux)
lldpfile = "/sys/class/net/%s/bridge/group_fwd_mask" % self.brname
if os.path.exists(lldpfile):
open(lldpfile, "w").write('0x4000')
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
logger.exception("Error setting bridge parameters") logger.exception("Error setting bridge parameters")

View file

@ -4,3 +4,4 @@ Services
Services available to nodes can be put in this directory. Everything listed in Services available to nodes can be put in this directory. Everything listed in
__all__ is automatically loaded by the main core module. __all__ is automatically loaded by the main core module.
""" """
__all__ = ["quagga", "nrl", "xorp", "bird", "utility", "security", "ucarp", "dockersvc", "OvsService" , "ryuService" , 'startup' ]

View file

@ -89,7 +89,7 @@ class NrlNhdp(NrlService):
servicenames = map(lambda x: x._name, services) servicenames = map(lambda x: x._name, services)
if "SMF" in servicenames: if "SMF" in servicenames:
cmd += " -flooding ecds-etx sticky" cmd += " -flooding ecds"
cmd += " -smfClient %s_smf" % node.name cmd += " -smfClient %s_smf" % node.name
netifs = filter(lambda x: not getattr(x, 'control', False), \ netifs = filter(lambda x: not getattr(x, 'control', False), \
@ -603,7 +603,7 @@ class MgenActor(NrlService):
cfg = "#!/bin/sh\n" cfg = "#!/bin/sh\n"
cfg += "# auto-generated by nrl.py:MgenActor.generateconfig()\n" cfg += "# auto-generated by nrl.py:MgenActor.generateconfig()\n"
comments = "" comments = ""
cmd = "mgenBasicActor.py -n %s -a 0.0.0.0" % node.name cmd = "python /usr/local/bin/mgenBasicActor.py -n %s -a 0.0.0.0 -p 5555" % (node.name)
servicenames = map(lambda x: x._name, services) servicenames = map(lambda x: x._name, services)
netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs()) netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs())

View file

@ -3,6 +3,7 @@ quagga.py: defines routing services provided by Quagga.
""" """
import os import os
import re
from core import constants from core import constants
from core.enumerations import LinkTypes, NodeTypes from core.enumerations import LinkTypes, NodeTypes
@ -52,15 +53,28 @@ class Zebra(CoreService):
@classmethod @classmethod
def generateQuaggaConf(cls, node, services): def generateQuaggaConf(cls, node, services):
""" Returns configuration file text. Other services that depend on zebra
will have generatequaggaifcconfig() and generatequaggaconfig()
hooks that are invoked here.
""" """
Returns configuration file text. Other services that depend on zebra # Check whether the node is running OVS
will have generatequaggaifcconfig() and generatequaggaconfig() has_ovs = 0
hooks that are invoked here. for s in services:
""" if s._name == "OvsService":
has_ovs =1
# we could verify here that filename == Quagga.conf # we could verify here that filename == Quagga.conf
cfg = "" cfg = ""
for ifc in node.netifs(): for ifc in node.netifs():
cfg += "interface %s\n" % ifc.name if has_ovs == 0:
ifname = ifc.name
else:
ifnumstr = re.findall(r"\d+", ifc.name)
ifnum = ifnumstr[0]
ifname = "rtr%s" % ifnum
cfg += "interface %s\n" % ifname
#cfg += "interface %s\n" % ifc.name
# include control interfaces in addressing but not routing daemons # include control interfaces in addressing but not routing daemons
if hasattr(ifc, 'control') and ifc.control == True: if hasattr(ifc, 'control') and ifc.control == True:
cfg += " " cfg += " "
@ -100,7 +114,7 @@ class Zebra(CoreService):
for s in services: for s in services:
if cls._name not in s._depends: if cls._name not in s._depends:
continue continue
cfg += s.generatequaggaconfig(node) cfg += s.generatequaggaconfig(node, services)
return cfg return cfg
@staticmethod @staticmethod
@ -294,7 +308,7 @@ class QuaggaService(CoreService):
return "" return ""
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
return "" return ""
@ -339,7 +353,7 @@ class Ospfv2(QuaggaService):
return "" return ""
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
cfg = "router ospf\n" cfg = "router ospf\n"
rtrid = cls.routerid(node) rtrid = cls.routerid(node)
cfg += " router-id %s\n" % rtrid cfg += " router-id %s\n" % rtrid
@ -424,13 +438,26 @@ class Ospfv3(QuaggaService):
return "" return ""
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
# Check whether the node is running OVS
has_ovs = 0
for s in services:
if s._name == "OvsService":
has_ovs =1
cfg = "router ospf6\n" cfg = "router ospf6\n"
rtrid = cls.routerid(node) rtrid = cls.routerid(node)
cfg += " router-id %s\n" % rtrid cfg += " router-id %s\n" % rtrid
for ifc in node.netifs(): for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control is True: if hasattr(ifc, 'control') and ifc.control is True:
continue continue
if has_ovs == 0:
ifname = ifc.name
else:
ifnumstr = re.findall(r"\d+", ifc.name)
ifnum = ifnumstr[0]
ifname = "rtr%s" % ifnum
cfg += " interface %s area 0.0.0.0\n" % ifc.name cfg += " interface %s area 0.0.0.0\n" % ifc.name
cfg += "!\n" cfg += "!\n"
return cfg return cfg
@ -466,6 +493,7 @@ class Ospfv3mdr(Ospfv3):
@classmethod @classmethod
def generatequaggaifcconfig(cls, node, ifc): def generatequaggaifcconfig(cls, node, ifc):
cfg = cls.mtucheck(ifc) cfg = cls.mtucheck(ifc)
# Uncomment the following line to use Address Family Translation for IPv4
cfg += " ipv6 ospf6 instance-id 65\n" cfg += " ipv6 ospf6 instance-id 65\n"
if ifc.net is not None and nodeutils.is_node(ifc.net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)): if ifc.net is not None and nodeutils.is_node(ifc.net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)):
return cfg + """\ return cfg + """\
@ -480,7 +508,6 @@ class Ospfv3mdr(Ospfv3):
else: else:
return cfg return cfg
class Bgp(QuaggaService): class Bgp(QuaggaService):
""" """
The BGP service provides interdomain routing. The BGP service provides interdomain routing.
@ -496,7 +523,7 @@ class Bgp(QuaggaService):
_ipv6_routing = True _ipv6_routing = True
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
cfg = "!\n! BGP configuration\n!\n" cfg = "!\n! BGP configuration\n!\n"
cfg += "! You should configure the AS number below,\n" cfg += "! You should configure the AS number below,\n"
cfg += "! along with this router's peers.\n!\n" cfg += "! along with this router's peers.\n!\n"
@ -507,7 +534,6 @@ class Bgp(QuaggaService):
cfg += "! neighbor 1.2.3.4 remote-as 555\n!\n" cfg += "! neighbor 1.2.3.4 remote-as 555\n!\n"
return cfg return cfg
class Rip(QuaggaService): class Rip(QuaggaService):
""" """
The RIP service provides IPv4 routing for wired networks. The RIP service provides IPv4 routing for wired networks.
@ -519,7 +545,7 @@ class Rip(QuaggaService):
_ipv4_routing = True _ipv4_routing = True
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
cfg = """\ cfg = """\
router rip router rip
redistribute static redistribute static
@ -530,7 +556,6 @@ router rip
""" """
return cfg return cfg
class Ripng(QuaggaService): class Ripng(QuaggaService):
""" """
The RIP NG service provides IPv6 routing for wired networks. The RIP NG service provides IPv6 routing for wired networks.
@ -542,7 +567,7 @@ class Ripng(QuaggaService):
_ipv6_routing = True _ipv6_routing = True
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
cfg = """\ cfg = """\
router ripng router ripng
redistribute static redistribute static
@ -553,7 +578,6 @@ router ripng
""" """
return cfg return cfg
class Babel(QuaggaService): class Babel(QuaggaService):
""" """
The Babel service provides a loop-avoiding distance-vector routing The Babel service provides a loop-avoiding distance-vector routing
@ -566,11 +590,24 @@ class Babel(QuaggaService):
_ipv6_routing = True _ipv6_routing = True
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
# Check whether the node is running OVS
has_ovs = 0
for s in services:
if s._name == "OvsService":
has_ovs =1
cfg = "router babel\n" cfg = "router babel\n"
for ifc in node.netifs(): for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control is True: if hasattr(ifc, 'control') and ifc.control is True:
continue continue
if has_ovs == 0:
ifname = ifc.name
else:
ifnumstr = re.findall(r"\d+", ifc.name)
ifnum = ifnumstr[0]
ifname = "rtr%s" % ifnum
cfg += " network %s\n" % ifc.name cfg += " network %s\n" % ifc.name
cfg += " redistribute static\n redistribute connected\n" cfg += " redistribute static\n redistribute connected\n"
return cfg return cfg
@ -583,7 +620,6 @@ class Babel(QuaggaService):
else: else:
return " babel wired\n babel split-horizon\n" return " babel wired\n babel split-horizon\n"
class Xpimd(QuaggaService): class Xpimd(QuaggaService):
""" """
PIM multicast routing based on XORP. PIM multicast routing based on XORP.
@ -595,11 +631,26 @@ class Xpimd(QuaggaService):
_ipv4_routing = True _ipv4_routing = True
@classmethod @classmethod
def generatequaggaconfig(cls, node): def generatequaggaconfig(cls, node, services):
ifname = 'eth0' # Check whether the node is running OVS
has_ovs = 0
for s in services:
if s._name == "OvsService":
has_ovs =1
if has_ovs == 0:
ifname = 'eth0'
else:
ifname = 'rtr0'
for ifc in node.netifs(): for ifc in node.netifs():
if ifc.name != 'lo': if ifc.name != 'lo':
ifname = ifc.name if has_ovs == 0:
ifname = ifc.name
else:
ifnumstr = re.findall(r"\d+", ifc.name)
ifnum = ifnumstr[0]
ifname = "rtr%s" % ifnum
break break
cfg = 'router mfea\n!\n' cfg = 'router mfea\n!\n'
cfg += 'router igmp\n!\n' cfg += 'router igmp\n!\n'
@ -614,7 +665,6 @@ class Xpimd(QuaggaService):
def generatequaggaifcconfig(cls, node, ifc): def generatequaggaifcconfig(cls, node, ifc):
return ' ip mfea\n ip igmp\n ip pim\n' return ' ip mfea\n ip igmp\n ip pim\n'
class Vtysh(CoreService): class Vtysh(CoreService):
""" """
Simple service to run vtysh -b (boot) after all Quagga daemons have Simple service to run vtysh -b (boot) after all Quagga daemons have
@ -630,7 +680,6 @@ class Vtysh(CoreService):
def generateconfig(cls, node, filename, services): def generateconfig(cls, node, filename, services):
return "" return ""
def load_services(): def load_services():
ServiceManager.add(Zebra) ServiceManager.add(Zebra)
ServiceManager.add(Ospfv2) ServiceManager.add(Ospfv2)

126
daemon/core/services/sdn.py Normal file
View file

@ -0,0 +1,126 @@
"""
sdn.py defines services to start Open vSwitch and the Ryu SDN Controller.
"""
import os
import re
from core.service import CoreService
from core.service import ServiceManager
class SdnService(CoreService):
"""
Parent class for SDN services.
"""
_name = "SdnProcess"
_group = "SDN"
_depends = ()
_dirs = ()
_configs = ()
_startindex = 50
_startup = ()
_shutdown = ()
@classmethod
def generateconfig(cls, node, filename, services):
return ""
class OvsService(SdnService):
_name = "OvsService"
_group = "SDN"
_depends = ()
_dirs = ("/etc/openvswitch", "/var/run/openvswitch", "/var/log/openvswitch")
_configs = ('OvsService.sh', )
_startindex = 50
_startup = ('sh OvsService.sh',)
_shutdown = ('killall ovs-vswitchd','killall ovsdb-server')
@classmethod
def generateconfig(cls, node, filename, services):
# 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
# Add rule for default controller if there is one local (even if the controller is not local, it finds it)
cfg += "ovs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\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
class ryuService(SdnService):
_name = "ryuService"
_group = "SDN"
_depends = ()
_dirs = ()
_configs = ('ryuService.sh', )
_startindex = 50
_startup = ('sh ryuService.sh',)
_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)
return cfg
def load_services():
ServiceManager.add(OvsService)
ServiceManager.add(ryuService)

View file

@ -29,12 +29,12 @@ quagga_sbin_search = "/usr/local/sbin /usr/sbin /usr/lib/quagga"
# #
# #
# uncomment and edit to establish a distributed control backchannel # uncomment and edit to establish a distributed control backchannel
#controlnet = core1:172.16.1.0/24 core:172.16.2.0/24 core3:172.16.3.0/24 core4 :172.16.4.0/24 core5:172.16.5.0/24 #controlnet = core1:172.16.1.0/24 core2:172.16.2.0/24 core3:172.16.3.0/24 core4 :172.16.4.0/24 core5:172.16.5.0/24
# uncomment and edit to establish distributed auxiliary control channels. # uncomment and edit to establish distributed auxiliary control channels.
#controlnet1 = core1:172.17.1.0/24 core:172.17.2.0/24 core3:172.17.3.0/24 core4 :172.17.4.0/24 core5:172.17.5.0/24 #controlnet1 = core1:172.17.1.0/24 core2:172.17.2.0/24 core3:172.17.3.0/24 core4 :172.17.4.0/24 core5:172.17.5.0/24
#controlnet2 = core1:172.18.1.0/24 core:172.18.2.0/24 core3:172.18.3.0/24 core4 :172.18.4.0/24 core5:172.18.5.0/24 #controlnet2 = core1:172.18.1.0/24 core2:172.18.2.0/24 core3:172.18.3.0/24 core4 :172.18.4.0/24 core5:172.18.5.0/24
#controlnet3 = core1:172.19.1.0/24 core:172.19.2.0/24 core3:172.19.3.0/24 core4 :172.19.4.0/24 core5:172.19.5.0/24 #controlnet3 = core1:172.19.1.0/24 core2:172.19.2.0/24 core3:172.19.3.0/24 core4 :172.19.4.0/24 core5:172.19.5.0/24
# uncomment and edit to assign host interfaces to auxilary control channels # uncomment and edit to assign host interfaces to auxilary control channels
# for use in connecting with other servers in a distributed environments. # for use in connecting with other servers in a distributed environments.

View file

@ -8,8 +8,10 @@
import os import os
from core.service import CoreService, addservice from core.misc.ipaddress import Ipv4Prefix
from core.misc.ipaddr import IPv4Prefix, IPv6Prefix from core.misc.ipaddress import Ipv6Prefix
from core.service import CoreService
from core.service import ServiceManager
class MyService(CoreService): class MyService(CoreService):
''' This is a sample user-defined service. ''' This is a sample user-defined service.
@ -60,5 +62,5 @@ class MyService(CoreService):
return 'echo " network %s"' % (net) return 'echo " network %s"' % (net)
# this line is required to add the above class to the list of available services # this line is required to add the above class to the list of available services
addservice(MyService) ServiceManager.add(MyService)

View file

@ -2716,7 +2716,7 @@ proc sendNodeTypeInfo { sock reset } {
set typesinuse "" set typesinuse ""
foreach node $node_list { foreach node $node_list {
set type [nodeType $node] set type [nodeType $node]
if { $type != "router" } { continue } if { $type != "router" && $type != "OVS" } { continue }
set model [getNodeModel $node] set model [getNodeModel $node]
if { [lsearch $typesinuse $model] < 0 } { lappend typesinuse $model } if { [lsearch $typesinuse $model] < 0 } { lappend typesinuse $model }
} }
@ -2920,6 +2920,7 @@ proc getNodeTypeAPI { node } {
router { return 0x0 } router { return 0x0 }
netns { return 0x0 } netns { return 0x0 }
jail { return 0x0 } jail { return 0x0 }
OVS { return 0x0 }
physical { return 0x1 } physical { return 0x1 }
xen { return 0x2 } xen { return 0x2 }
tbd { return 0x3 } tbd { return 0x3 }

View file

@ -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 {
}

View file

@ -338,7 +338,7 @@ proc redrawAll {} {
proc drawNode { c node } { proc drawNode { c node } {
global showNodeLabels global showNodeLabels
global router pc host lanswitch rj45 hub pseudo global router pc host lanswitch rj45 hub pseudo OVS
global curcanvas zoom global curcanvas zoom
global wlan global wlan
if { $c == "" } { set c .c } ;# default canvas if { $c == "" } { set c .c } ;# default canvas
@ -353,7 +353,7 @@ proc drawNode { c node } {
set cimg "" set cimg ""
set imgzoom $zoom set imgzoom $zoom
if { $zoom == 0.75 || $zoom == 1.5 } { set imgzoom 1.0 } if { $zoom == 0.75 || $zoom == 1.5 } { set imgzoom 1.0 }
if { $type == "router" } { if { $type == "router" || $type == "OVS" } {
set model [getNodeModel $node] set model [getNodeModel $node]
set cimg [getNodeTypeImage $model normal] set cimg [getNodeTypeImage $model normal]
} }
@ -409,7 +409,8 @@ proc drawNode { c node } {
set ifc [ifcByPeer $pnode [getNodeMirror $node]] set ifc [ifcByPeer $pnode [getNodeMirror $node]]
if { $pcanvas != $curcanvas } { if { $pcanvas != $curcanvas } {
set label [$c create text $x $y -fill blue \ set label [$c create text $x $y -fill blue \
-text "[getNodeName $pnode]:$ifc @[getCanvasName $pcanvas]" \ -text "[getNodeName $pnode]:$ifc
@[getCanvasName $pcanvas]" \
-tags "nodelabel $node" -justify center] -tags "nodelabel $node" -justify center]
} else { } else {
set label [$c create text $x $y -fill blue \ set label [$c create text $x $y -fill blue \
@ -698,13 +699,16 @@ proc updateIfcLabel { lnode1 lnode2 } {
set labelstr "" set labelstr ""
} }
if { $showIfNames } { if { $showIfNames } {
set labelstr "$labelstr$ifc " set labelstr "$labelstr$ifc
"
} }
if { $showIfIPaddrs && $ifipv4addr != "" } { if { $showIfIPaddrs && $ifipv4addr != "" } {
set labelstr "$labelstr$ifipv4addr " set labelstr "$labelstr$ifipv4addr
"
} }
if { $showIfIPv6addrs && $ifipv6addr != "" } { if { $showIfIPv6addrs && $ifipv6addr != "" } {
set labelstr "$labelstr$ifipv6addr " set labelstr "$labelstr$ifipv6addr
"
} }
set labelstr \ set labelstr \
[string range $labelstr 0 [expr {[string length $labelstr] - 2}]] [string range $labelstr 0 [expr {[string length $labelstr] - 2}]]
@ -735,18 +739,23 @@ proc updateLinkLabel { link } {
set delstr [getLinkDelayString $link] set delstr [getLinkDelayString $link]
set berstr [getLinkBERString $link] set berstr [getLinkBERString $link]
set dupstr [getLinkDupString $link] set dupstr [getLinkDupString $link]
set labelstr " " set labelstr "
"
if { "$bwstr" != "" } { if { "$bwstr" != "" } {
set labelstr "$labelstr$bwstr " set labelstr "$labelstr$bwstr
"
} }
if { "$delstr" != "" } { if { "$delstr" != "" } {
set labelstr "$labelstr$delstr " set labelstr "$labelstr$delstr
"
} }
if { "$berstr" != "" } { if { "$berstr" != "" } {
set labelstr "$labelstr$berstr " set labelstr "$labelstr$berstr
"
} }
if { "$dupstr" != "" } { if { "$dupstr" != "" } {
set labelstr "$labelstr$dupstr " set labelstr "$labelstr$dupstr
"
} }
set labelstr \ set labelstr \
[string range $labelstr 0 [expr {[string length $labelstr] - 2}]] [string range $labelstr 0 [expr {[string length $labelstr] - 2}]]
@ -1530,7 +1539,7 @@ proc raiseAll {c} {
proc button1 { c x y button } { proc button1 { c x y button } {
global node_list plot_list curcanvas zoom global node_list plot_list curcanvas zoom
global activetool activetoolp newlink curobj changed def_router_model global activetool activetoolp newlink curobj changed def_router_model
global router pc host lanswitch rj45 hub global router pc host lanswitch rj45 hub OVS
global oval rectangle text global oval rectangle text
global lastX lastY global lastX lastY
global background selectbox global background selectbox
@ -1602,7 +1611,10 @@ proc button1 { c x y button } {
rectangle text} $activetool] < 0 } { rectangle text} $activetool] < 0 } {
if { $g_view_locked == 1 } { return } if { $g_view_locked == 1 } { return }
if { $activetoolp == "routers" } { if { $activetoolp == "routers" } {
set node [newNode router] if {$activetool != "OVS"} {
set node [newNode router]
} else {
set node [newNode OVS]}
setNodeModel $node $activetool setNodeModel $node $activetool
} else { } else {
set node [newNode $activetool] set node [newNode $activetool]
@ -2542,8 +2554,8 @@ proc popupConfigDialog { c } {
-side right -padx 4 -pady 4 -side right -padx 4 -pady 4
# end Boeing # end Boeing
pack $wi.ftop -side top pack $wi.ftop -side top
if { $type == "router" || $type == "OVS"} {
if { $type == "router" } {
ttk::frame $wi.model -borderwidth 4 ttk::frame $wi.model -borderwidth 4
ttk::label $wi.model.label -text "Type:" ttk::label $wi.model.label -text "Type:"
set runstate "disabled" set runstate "disabled"

BIN
gui/icons/normal/OVS.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

190
gui/icons/svg/OVS.svg Executable file
View file

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="146"
height="100"
id="svg3868"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="switch.svg">
<defs
id="defs3870">
<linearGradient
id="linearGradient5149">
<stop
id="stop5151"
offset="0"
style="stop-color:#5dacd1;stop-opacity:1;" />
<stop
id="stop5153"
offset="1"
style="stop-color:#1b4a78;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient4902">
<stop
style="stop-color:#484848;stop-opacity:1;"
offset="0"
id="stop4904" />
<stop
style="stop-color:#8f8f90;stop-opacity:0;"
offset="1"
id="stop4906" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3876" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12001"
id="linearGradient4908"
x1="5.8083773"
y1="68.180191"
x2="84.600281"
y2="68.180191"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.269166,0,0,1.2912385,-2.3717949,931.82545)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12001"
id="linearGradient5039"
x1="105"
y1="55"
x2="140"
y2="55"
gradientUnits="userSpaceOnUse" />
<inkscape:perspective
id="perspective5049"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12001"
id="linearGradient3844"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.471308,0,0,0.471308,9.3066001,-238.48173)"
x1="175.71875"
y1="737.01562"
x2="470.00089"
y2="737.01562" />
<linearGradient
id="linearGradient12001">
<stop
style="stop-color:#1b4a78;stop-opacity:1;"
offset="0"
id="stop12003" />
<stop
style="stop-color:#5dacd1;stop-opacity:1;"
offset="1"
id="stop12005" />
</linearGradient>
<inkscape:perspective
id="perspective5135"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5165"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="91.162404"
inkscape:cy="35.126778"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="809"
inkscape:window-height="852"
inkscape:window-x="605"
inkscape:window-y="185"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid4935"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata3873">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-952.36218)">
<rect
style="fill:url(#linearGradient4908);fill-opacity:1.0;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
id="rect4390"
width="100"
height="45"
x="5"
y="997.36218" />
<path
style="fill:url(#linearGradient5039);stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1.0"
d="m 105,45 35,-40 0,45 -35,40 0,-45 z"
id="path5031"
transform="translate(0,952.36218)"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#3a78a0;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="M 105,45 5,45 40,5 140,5 105,45 z"
id="path5079"
transform="translate(0,952.36218)" />
<path
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none"
d="m 63.720704,982.3378 12.656877,-3.10116 12.656905,-3.10105 -3.523923,3.28427 18.978167,0.15164 -6.571234,6.1243 -18.978156,-0.15164 -3.523925,3.28426 -5.843452,-3.24896 -5.851259,-3.24166 z"
id="path13511" />
<path
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none"
d="M 80.174263,970.7443 74.367199,967.43074 68.560125,964.11719 65,967.36218 46.024691,967.0001 l -6.638732,6.05106 18.975309,0.36208 -3.560123,3.24499 12.690524,-2.96052 12.682595,-2.95341 z"
id="path13513" />
<path
id="path5195"
d="M 65.174263,985.7443 59.367199,982.43074 53.560125,979.11719 50,982.36218 31.024691,982.0001 l -6.638732,6.05106 18.975309,0.36208 -3.560123,3.24499 12.690524,-2.96052 12.682595,-2.95341 z"
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
<path
id="path5209"
d="m 78.9675,967.75499 12.656877,-3.10116 12.656903,-3.10105 -3.52392,3.28427 18.97816,0.15164 -6.57123,6.1243 -18.978154,-0.15164 -3.523925,3.28426 -5.843452,-3.24896 -5.851259,-3.24166 z"
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
gui/icons/tiny/OVS.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

View file

@ -113,7 +113,7 @@ proc autoIPv4addr { node iface } {
set peer_node [logicalPeerByIfc $node $iface] set peer_node [logicalPeerByIfc $node $iface]
# find addresses of NETWORK layer peer nodes # find addresses of NETWORK layer peer nodes
if { [[typemodel $peer_node].layer] == "LINK" } { if { [[typemodel $peer_node].layer] == "LINK" || [nodeType $peer_node] == "OVS" } {
foreach l2node [listLANnodes $peer_node {}] { foreach l2node [listLANnodes $peer_node {}] {
foreach ifc [ifcList $l2node] { foreach ifc [ifcList $l2node] {
set peer [logicalPeerByIfc $l2node $ifc] set peer [logicalPeerByIfc $l2node $ifc]

View file

@ -752,13 +752,15 @@ proc newLink { lnode1 lnode2 } {
global defLinkColor defLinkWidth global defLinkColor defLinkWidth
global curcanvas global curcanvas
global systype global systype
if { ([nodeType $lnode1] == "lanswitch" ||[nodeType $lnode1] == "OVS") && \
if { [nodeType $lnode1] == "lanswitch" && \
[nodeType $lnode2] != "router" && \ [nodeType $lnode2] != "router" && \
[nodeType $lnode2] != "lanswitch" } { set regular no } ([nodeType $lnode2] != "lanswitch" || [nodeType $lnode2] != "OVS") } {
if { [nodeType $lnode2] == "lanswitch" && \ set regular no }
if { ([nodeType $lnode2] == "lanswitch" || [nodeType $lnode2] == "OVS") && \
[nodeType $lnode1] != "router" && \ [nodeType $lnode1] != "router" && \
[nodeType $lnode1] != "lanswitch" } { set regular no } ([nodeType $lnode1] != "lanswitch" || [nodeType $lnode1] != "OVS" )} {
#Khaled: puts "connecting '$lnode1' (type: '[nodeType $lnode1]') to '$lnode2' (type: '[nodeType $lnode2]') "
set regular no }
if { [nodeType $lnode1] == "hub" && \ if { [nodeType $lnode1] == "hub" && \
[nodeType $lnode2] == "hub" } { set regular no } [nodeType $lnode2] == "hub" } { set regular no }
# Boeing: added tunnel, ktunnel types to behave as rj45 # Boeing: added tunnel, ktunnel types to behave as rj45
@ -774,7 +776,7 @@ proc newLink { lnode1 lnode2 } {
set othernode $lnode1 set othernode $lnode1
} }
# only allowed to link with certain types # only allowed to link with certain types
if { [lsearch {router lanswitch hub pc host wlan} \ if { [lsearch {router lanswitch hub pc host wlan OVS} \
[nodeType $othernode]] < 0} { [nodeType $othernode]] < 0} {
return return
} }
@ -842,14 +844,19 @@ proc newLink { lnode1 lnode2 } {
} else { } else {
lappend $link "delay $delay" lappend $link "delay $delay"
} }
} }
if { [[typemodel $lnode2].layer] == "NETWORK" } { # Exclude OVS from network layer nodes IP address asignments
if { ([[typemodel $lnode2].layer] == "NETWORK") && ([nodeType $lnode2] != "OVS") } {
#Khaled: puts "Assigning '$lnode2' (type: '[nodeType $lnode2]') an automatic IP address"
if { $ipv4_addr2 == "" } { autoIPv4addr $lnode2 $ifname2 } if { $ipv4_addr2 == "" } { autoIPv4addr $lnode2 $ifname2 }
if { $ipv6_addr2 == "" } { autoIPv6addr $lnode2 $ifname2 } if { $ipv6_addr2 == "" } { autoIPv6addr $lnode2 $ifname2 }
} }
# tunnels also excluded from link settings # tunnels also excluded from link settings
} elseif { ([nodeType $lnode1] == "lanswitch" || \ # OVS and Lanswitch should go side by side
[nodeType $lnode2] == "lanswitch" || \ } elseif { (([nodeType $lnode1] == "lanswitch" || [nodeType $lnode1] == "OVS" )|| \
([nodeType $lnode2] == "lanswitch"|| [nodeType $lnode2] == "OVS") || \
[string first eth "$ifname1 $ifname2"] != -1) && \ [string first eth "$ifname1 $ifname2"] != -1) && \
[nodeType $lnode1] != "rj45" && [nodeType $lnode2] != "rj45" && \ [nodeType $lnode1] != "rj45" && [nodeType $lnode2] != "rj45" && \
[nodeType $lnode1] != "tunnel" && [nodeType $lnode2] != "tunnel" && \ [nodeType $lnode1] != "tunnel" && [nodeType $lnode2] != "tunnel" && \
@ -861,12 +868,13 @@ proc newLink { lnode1 lnode2 } {
} }
lappend link_list $link lappend link_list $link
# Exclude OVS from Network layer node configs
if { [nodeType $lnode2] != "pseudo" && if { [nodeType $lnode2] != "pseudo" &&
[nodeType $lnode1] != "wlan" && [nodeType $lnode1] != "wlan" &&
[[typemodel $lnode1].layer] == "NETWORK" } { ([[typemodel $lnode1].layer] == "NETWORK" && [nodeType $lnode1] != "OVS") } {
if { $ipv4_addr1 == "" && $do_auto_addressing } { if { $ipv4_addr1 == "" && $do_auto_addressing } {
autoIPv4addr $lnode1 $ifname1 autoIPv4addr $lnode1 $ifname1
} }
if { $ipv6_addr1 == "" && $do_auto_addressing } { if { $ipv6_addr1 == "" && $do_auto_addressing } {
autoIPv6addr $lnode1 $ifname1 autoIPv6addr $lnode1 $ifname1
@ -875,7 +883,8 @@ proc newLink { lnode1 lnode2 } {
# assume wlan is always lnode1 # assume wlan is always lnode1
if { [nodeType $lnode1] != "pseudo" && if { [nodeType $lnode1] != "pseudo" &&
[nodeType $lnode1] != "wlan" && [nodeType $lnode1] != "wlan" &&
[[typemodel $lnode2].layer] == "NETWORK" } { ([[typemodel $lnode2].layer] == "NETWORK" && [nodeType $lnode2] != "OVS") } {
if { $ipv4_addr2 == "" && $do_auto_addressing } { if { $ipv4_addr2 == "" && $do_auto_addressing } {
autoIPv4addr $lnode2 $ifname2 autoIPv4addr $lnode2 $ifname2
} }

View file

@ -28,10 +28,12 @@ array set g_node_types_default {
physical {built-in type for physical nodes}} physical {built-in type for physical nodes}}
6 {xen xen.gif xen.gif {zebra OSPFv2 OSPFv3 vtysh IPForward} \ 6 {xen xen.gif xen.gif {zebra OSPFv2 OSPFv3 vtysh IPForward} \
xen {built-in type for Xen PVM domU router}} xen {built-in type for Xen PVM domU router}}
7 {OVS lanswitch.gif lanswitch.gif {DefaultRoute SSH OvsService} OVS {} }
} }
# possible machine types for nodes # possible machine types for nodes
set MACHINE_TYPES "netns physical xen" set MACHINE_TYPES "netns physical xen OVS"
# array populated from nodes.conf file # array populated from nodes.conf file
array set g_node_types { } array set g_node_types { }
@ -189,7 +191,7 @@ proc getNodeTypeServices { type } {
# node type from the toolbar # node type from the toolbar
proc getNodeTypeMachineType { type } { proc getNodeTypeMachineType { type } {
global MACHINE_TYPES g_node_types global MACHINE_TYPES g_node_types
set default_machine_type [lindex $MACHINE_TYPES 0] set default_machine_type [lindex $MACHINE_TYPES 3]
set i [getNodeTypeIndex $type] set i [getNodeTypeIndex $type]
if { $i < 0 } { return $default_machine_type }; # failsafe if { $i < 0 } { return $default_machine_type }; # failsafe
return [lindex $g_node_types($i) 4] return [lindex $g_node_types($i) 4]
@ -213,7 +215,7 @@ proc getNodeTypeProfile { type } {
# node type from the toolbar # node type from the toolbar
proc getNodeTypeMachineType { type } { proc getNodeTypeMachineType { type } {
global MACHINE_TYPES g_node_types global MACHINE_TYPES g_node_types
set default_machine_type [lindex $MACHINE_TYPES 0] set default_machine_type [lindex $MACHINE_TYPES 3]
set i [getNodeTypeIndex $type] set i [getNodeTypeIndex $type]
if { $i < 0 } { return $default_machine_type }; # failsafe if { $i < 0 } { return $default_machine_type }; # failsafe
return [lindex $g_node_types($i) 4] return [lindex $g_node_types($i) 4]
@ -719,6 +721,7 @@ proc lanswitch.layer {} { return LINK }
proc hub.layer {} { return LINK } proc hub.layer {} { return LINK }
proc tunnel.layer {} { return LINK } proc tunnel.layer {} { return LINK }
proc wlan.layer {} { return LINK } proc wlan.layer {} { return LINK }
proc OVS.layer {} { return NETWORK }
proc router.layer {} { return NETWORK } proc router.layer {} { return NETWORK }
proc router.shellcmd { n } { return "vtysh" } proc router.shellcmd { n } { return "vtysh" }