Add OVS and Ryu Services to CORE for SDN support

This commit is contained in:
cspiker 2017-06-08 08:31:50 -07:00
parent b37d1d52fa
commit 46baca85d9
13 changed files with 146 additions and 63 deletions

View file

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

View file

@ -301,6 +301,12 @@ class LxBrNet(PyCoreNet):
snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % self.brname
if os.path.exists(snoop):
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:
logger.exception("Error setting bridge parameters")

0
daemon/core/services/OvsService.py Executable file → Normal file
View file

View file

@ -4,3 +4,4 @@ Services
Services available to nodes can be put in this directory. Everything listed in
__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)
if "SMF" in servicenames:
cmd += " -flooding ecds-etx sticky"
cmd += " -flooding ecds"
cmd += " -smfClient %s_smf" % node.name
netifs = filter(lambda x: not getattr(x, 'control', False), \
@ -603,7 +603,7 @@ class MgenActor(NrlService):
cfg = "#!/bin/sh\n"
cfg += "# auto-generated by nrl.py:MgenActor.generateconfig()\n"
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)
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 re
from core import constants
from core.enumerations import LinkTypes, NodeTypes
@ -52,15 +53,28 @@ class Zebra(CoreService):
@classmethod
def generateQuaggaConf(cls, node, services):
"""
Returns configuration file text. Other services that depend on zebra
""" Returns configuration file text. Other services that depend on zebra
will have generatequaggaifcconfig() and generatequaggaconfig()
hooks that are invoked here.
"""
# Check whether the node is running OVS
has_ovs = 0
for s in services:
if s._name == "OvsService":
has_ovs =1
# we could verify here that filename == Quagga.conf
cfg = ""
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
if hasattr(ifc, 'control') and ifc.control == True:
cfg += " "
@ -100,7 +114,7 @@ class Zebra(CoreService):
for s in services:
if cls._name not in s._depends:
continue
cfg += s.generatequaggaconfig(node)
cfg += s.generatequaggaconfig(node, services)
return cfg
@staticmethod
@ -294,7 +308,7 @@ class QuaggaService(CoreService):
return ""
@classmethod
def generatequaggaconfig(cls, node):
def generatequaggaconfig(cls, node, services):
return ""
@ -339,7 +353,7 @@ class Ospfv2(QuaggaService):
return ""
@classmethod
def generatequaggaconfig(cls, node):
def generatequaggaconfig(cls, node, services):
cfg = "router ospf\n"
rtrid = cls.routerid(node)
cfg += " router-id %s\n" % rtrid
@ -424,13 +438,26 @@ class Ospfv3(QuaggaService):
return ""
@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"
rtrid = cls.routerid(node)
cfg += " router-id %s\n" % rtrid
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control is True:
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 += "!\n"
return cfg
@ -466,6 +493,7 @@ class Ospfv3mdr(Ospfv3):
@classmethod
def generatequaggaifcconfig(cls, node, ifc):
cfg = cls.mtucheck(ifc)
# Uncomment the following line to use Address Family Translation for IPv4
cfg += " ipv6 ospf6 instance-id 65\n"
if ifc.net is not None and nodeutils.is_node(ifc.net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)):
return cfg + """\
@ -480,7 +508,6 @@ class Ospfv3mdr(Ospfv3):
else:
return cfg
class Bgp(QuaggaService):
"""
The BGP service provides interdomain routing.
@ -496,7 +523,7 @@ class Bgp(QuaggaService):
_ipv6_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generatequaggaconfig(cls, node, services):
cfg = "!\n! BGP configuration\n!\n"
cfg += "! You should configure the AS number below,\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"
return cfg
class Rip(QuaggaService):
"""
The RIP service provides IPv4 routing for wired networks.
@ -519,7 +545,7 @@ class Rip(QuaggaService):
_ipv4_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generatequaggaconfig(cls, node, services):
cfg = """\
router rip
redistribute static
@ -530,7 +556,6 @@ router rip
"""
return cfg
class Ripng(QuaggaService):
"""
The RIP NG service provides IPv6 routing for wired networks.
@ -542,7 +567,7 @@ class Ripng(QuaggaService):
_ipv6_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generatequaggaconfig(cls, node, services):
cfg = """\
router ripng
redistribute static
@ -553,7 +578,6 @@ router ripng
"""
return cfg
class Babel(QuaggaService):
"""
The Babel service provides a loop-avoiding distance-vector routing
@ -566,11 +590,24 @@ class Babel(QuaggaService):
_ipv6_routing = True
@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"
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control is True:
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 += " redistribute static\n redistribute connected\n"
return cfg
@ -583,7 +620,6 @@ class Babel(QuaggaService):
else:
return " babel wired\n babel split-horizon\n"
class Xpimd(QuaggaService):
"""
PIM multicast routing based on XORP.
@ -595,11 +631,26 @@ class Xpimd(QuaggaService):
_ipv4_routing = True
@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
if has_ovs == 0:
ifname = 'eth0'
else:
ifname = 'rtr0'
for ifc in node.netifs():
if ifc.name != 'lo':
if has_ovs == 0:
ifname = ifc.name
else:
ifnumstr = re.findall(r"\d+", ifc.name)
ifnum = ifnumstr[0]
ifname = "rtr%s" % ifnum
break
cfg = 'router mfea\n!\n'
cfg += 'router igmp\n!\n'
@ -614,7 +665,6 @@ class Xpimd(QuaggaService):
def generatequaggaifcconfig(cls, node, ifc):
return ' ip mfea\n ip igmp\n ip pim\n'
class Vtysh(CoreService):
"""
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):
return ""
def load_services():
ServiceManager.add(Zebra)
ServiceManager.add(Ospfv2)

0
daemon/core/services/ryuService.py Executable file → Normal file
View file

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
#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.
#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
#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
#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
#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 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 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
# for use in connecting with other servers in a distributed environments.

View file

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

View file

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

View file

@ -113,7 +113,7 @@ proc autoIPv4addr { node iface } {
set peer_node [logicalPeerByIfc $node $iface]
# 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 ifc [ifcList $l2node] {
set peer [logicalPeerByIfc $l2node $ifc]

View file

@ -752,13 +752,15 @@ proc newLink { lnode1 lnode2 } {
global defLinkColor defLinkWidth
global curcanvas
global systype
if { [nodeType $lnode1] == "lanswitch" && \
if { ([nodeType $lnode1] == "lanswitch" ||[nodeType $lnode1] == "OVS") && \
[nodeType $lnode2] != "router" && \
[nodeType $lnode2] != "lanswitch" } { set regular no }
if { [nodeType $lnode2] == "lanswitch" && \
([nodeType $lnode2] != "lanswitch" || [nodeType $lnode2] != "OVS") } {
set regular no }
if { ([nodeType $lnode2] == "lanswitch" || [nodeType $lnode2] == "OVS") && \
[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" && \
[nodeType $lnode2] == "hub" } { set regular no }
# Boeing: added tunnel, ktunnel types to behave as rj45
@ -774,7 +776,7 @@ proc newLink { lnode1 lnode2 } {
set othernode $lnode1
}
# 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} {
return
}
@ -843,13 +845,18 @@ proc newLink { lnode1 lnode2 } {
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 { $ipv6_addr2 == "" } { autoIPv6addr $lnode2 $ifname2 }
}
# tunnels also excluded from link settings
} elseif { ([nodeType $lnode1] == "lanswitch" || \
[nodeType $lnode2] == "lanswitch" || \
# OVS and Lanswitch should go side by side
} elseif { (([nodeType $lnode1] == "lanswitch" || [nodeType $lnode1] == "OVS" )|| \
([nodeType $lnode2] == "lanswitch"|| [nodeType $lnode2] == "OVS") || \
[string first eth "$ifname1 $ifname2"] != -1) && \
[nodeType $lnode1] != "rj45" && [nodeType $lnode2] != "rj45" && \
[nodeType $lnode1] != "tunnel" && [nodeType $lnode2] != "tunnel" && \
@ -861,10 +868,11 @@ proc newLink { lnode1 lnode2 } {
}
lappend link_list $link
# Exclude OVS from Network layer node configs
if { [nodeType $lnode2] != "pseudo" &&
[nodeType $lnode1] != "wlan" &&
[[typemodel $lnode1].layer] == "NETWORK" } {
([[typemodel $lnode1].layer] == "NETWORK" && [nodeType $lnode1] != "OVS") } {
if { $ipv4_addr1 == "" && $do_auto_addressing } {
autoIPv4addr $lnode1 $ifname1
}
@ -875,7 +883,8 @@ proc newLink { lnode1 lnode2 } {
# assume wlan is always lnode1
if { [nodeType $lnode1] != "pseudo" &&
[nodeType $lnode1] != "wlan" &&
[[typemodel $lnode2].layer] == "NETWORK" } {
([[typemodel $lnode2].layer] == "NETWORK" && [nodeType $lnode2] != "OVS") } {
if { $ipv4_addr2 == "" && $do_auto_addressing } {
autoIPv4addr $lnode2 $ifname2
}

View file

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