daemon support for unidirectional link effects
also enable link effects between hub/switch and hub/switch connections (Boeing r1798)
This commit is contained in:
parent
f01ddd7c16
commit
6547b898c3
4 changed files with 147 additions and 48 deletions
|
@ -299,6 +299,33 @@ class PyCoreNet(PyCoreObj):
|
||||||
with self._linked_lock:
|
with self._linked_lock:
|
||||||
del self._linked[netif]
|
del self._linked[netif]
|
||||||
|
|
||||||
|
def netifparamstolink(self, netif):
|
||||||
|
''' Helper for tolinkmsgs() to build TLVs having link parameters
|
||||||
|
from interface parameters.
|
||||||
|
'''
|
||||||
|
tlvdata = ""
|
||||||
|
delay = netif.getparam('delay')
|
||||||
|
bw = netif.getparam('bw')
|
||||||
|
loss = netif.getparam('loss')
|
||||||
|
duplicate = netif.getparam('duplicate')
|
||||||
|
jitter = netif.getparam('jitter')
|
||||||
|
if delay is not None:
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DELAY,
|
||||||
|
delay)
|
||||||
|
if bw is not None:
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_BW, bw)
|
||||||
|
if loss is not None:
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_PER,
|
||||||
|
str(loss))
|
||||||
|
if duplicate is not None:
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DUP,
|
||||||
|
str(duplicate))
|
||||||
|
if jitter is not None:
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_JITTER,
|
||||||
|
jitter)
|
||||||
|
return tlvdata
|
||||||
|
|
||||||
|
|
||||||
def tolinkmsgs(self, flags):
|
def tolinkmsgs(self, flags):
|
||||||
''' Build CORE API Link Messages for this network. Each link message
|
''' Build CORE API Link Messages for this network. Each link message
|
||||||
describes a link between this network and a node.
|
describes a link between this network and a node.
|
||||||
|
@ -323,26 +350,7 @@ class PyCoreNet(PyCoreObj):
|
||||||
self.objid)
|
self.objid)
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER,
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER,
|
||||||
otherobj.objid)
|
otherobj.objid)
|
||||||
delay = netif.getparam('delay')
|
tlvdata += self.netifparamstolink(netif)
|
||||||
bw = netif.getparam('bw')
|
|
||||||
loss = netif.getparam('loss')
|
|
||||||
duplicate = netif.getparam('duplicate')
|
|
||||||
jitter = netif.getparam('jitter')
|
|
||||||
if delay is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DELAY,
|
|
||||||
delay)
|
|
||||||
if bw is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_BW,
|
|
||||||
bw)
|
|
||||||
if loss is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_PER,
|
|
||||||
str(loss))
|
|
||||||
if duplicate is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DUP,
|
|
||||||
str(duplicate))
|
|
||||||
if jitter is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_JITTER,
|
|
||||||
jitter)
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_TYPE,
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_TYPE,
|
||||||
self.linktype)
|
self.linktype)
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF2NUM,
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF2NUM,
|
||||||
|
@ -440,6 +448,17 @@ class PyCoreNetIf(object):
|
||||||
return False
|
return False
|
||||||
self._params[key] = value
|
self._params[key] = value
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def swapparams(self, name):
|
||||||
|
''' Swap out the _params dict for name. If name does not exist,
|
||||||
|
intialize it. This is for supporting separate upstream/downstream
|
||||||
|
parameters when two layer-2 nodes are linked together.
|
||||||
|
'''
|
||||||
|
tmp = self._params
|
||||||
|
if not hasattr(self, name):
|
||||||
|
setattr(self, name, {})
|
||||||
|
self._params = getattr(self, name)
|
||||||
|
setattr(self, name, tmp)
|
||||||
|
|
||||||
def setposition(self, x, y, z):
|
def setposition(self, x, y, z):
|
||||||
''' Dispatch to any position hook (self.poshook) handler.
|
''' Dispatch to any position hook (self.poshook) handler.
|
||||||
|
|
|
@ -96,27 +96,14 @@ class PtpNet(LxBrNet):
|
||||||
if1.node.objid)
|
if1.node.objid)
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER,
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER,
|
||||||
if2.node.objid)
|
if2.node.objid)
|
||||||
delay = if1.getparam('delay')
|
uni = False
|
||||||
bw = if1.getparam('bw')
|
if if1.getparams() != if2.getparams():
|
||||||
loss = if1.getparam('loss')
|
uni = True
|
||||||
duplicate = if1.getparam('duplicate')
|
tlvdata += self.netifparamstolink(if1)
|
||||||
jitter = if1.getparam('jitter')
|
|
||||||
if delay is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DELAY,
|
|
||||||
delay)
|
|
||||||
if bw is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_BW, bw)
|
|
||||||
if loss is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_PER,
|
|
||||||
str(loss))
|
|
||||||
if duplicate is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DUP,
|
|
||||||
str(duplicate))
|
|
||||||
if jitter is not None:
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_JITTER,
|
|
||||||
jitter)
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_TYPE,
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_TYPE,
|
||||||
self.linktype)
|
self.linktype)
|
||||||
|
if uni:
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_UNI, 1)
|
||||||
|
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF1NUM, \
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF1NUM, \
|
||||||
if1.node.getifindex(if1))
|
if1.node.getifindex(if1))
|
||||||
|
@ -154,7 +141,23 @@ class PtpNet(LxBrNet):
|
||||||
IPAddr(af=family, addr=ipl))
|
IPAddr(af=family, addr=ipl))
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
|
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
|
||||||
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
|
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
|
||||||
return [msg,]
|
if not uni:
|
||||||
|
return [msg,]
|
||||||
|
# build a 2nd link message for the upstream link parameters
|
||||||
|
# (swap if1 and if2)
|
||||||
|
tlvdata = ""
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N1NUMBER,
|
||||||
|
if2.node.objid)
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER,
|
||||||
|
if1.node.objid)
|
||||||
|
tlvdata += self.netifparamstolink(if2)
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_UNI, 1)
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF1NUM, \
|
||||||
|
if2.node.getifindex(if2))
|
||||||
|
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF2NUM, \
|
||||||
|
if1.node.getifindex(if1))
|
||||||
|
msg2 = coreapi.CoreLinkMessage.pack(0, tlvdata)
|
||||||
|
return [msg, msg2]
|
||||||
|
|
||||||
class SwitchNode(LxBrNet):
|
class SwitchNode(LxBrNet):
|
||||||
apitype = coreapi.CORE_NODE_SWITCH
|
apitype = coreapi.CORE_NODE_SWITCH
|
||||||
|
|
|
@ -328,11 +328,14 @@ class LxBrNet(PyCoreNet):
|
||||||
ebq.ebchange(self)
|
ebq.ebchange(self)
|
||||||
|
|
||||||
def linkconfig(self, netif, bw = None, delay = None,
|
def linkconfig(self, netif, bw = None, delay = None,
|
||||||
loss = None, duplicate = None, jitter = None, netif2 = None):
|
loss = None, duplicate = None, jitter = None, netif2 = None,
|
||||||
|
devname = None):
|
||||||
''' Configure link parameters by applying tc queuing disciplines on the
|
''' Configure link parameters by applying tc queuing disciplines on the
|
||||||
interface.
|
interface.
|
||||||
'''
|
'''
|
||||||
tc = [TC_BIN, "qdisc", "replace", "dev", netif.localname]
|
if devname is None:
|
||||||
|
devname = netif.localname
|
||||||
|
tc = [TC_BIN, "qdisc", "replace", "dev", devname]
|
||||||
parent = ["root"]
|
parent = ["root"]
|
||||||
changed = False
|
changed = False
|
||||||
if netif.setparam('bw', bw):
|
if netif.setparam('bw', bw):
|
||||||
|
@ -344,6 +347,9 @@ class LxBrNet(PyCoreNet):
|
||||||
"burst", str(burst), "limit", str(limit)]
|
"burst", str(burst), "limit", str(limit)]
|
||||||
if bw > 0:
|
if bw > 0:
|
||||||
if self.up:
|
if self.up:
|
||||||
|
if (self.verbose):
|
||||||
|
self.info("linkconfig: %s" % \
|
||||||
|
([tc + parent + ["handle", "1:"] + tbf],))
|
||||||
check_call(tc + parent + ["handle", "1:"] + tbf)
|
check_call(tc + parent + ["handle", "1:"] + tbf)
|
||||||
netif.setparam('has_tbf', True)
|
netif.setparam('has_tbf', True)
|
||||||
changed = True
|
changed = True
|
||||||
|
@ -382,16 +388,22 @@ class LxBrNet(PyCoreNet):
|
||||||
netem += ["loss", "%s%%" % min(loss, 100)]
|
netem += ["loss", "%s%%" % min(loss, 100)]
|
||||||
if duplicate is not None:
|
if duplicate is not None:
|
||||||
netem += ["duplicate", "%s%%" % min(duplicate, 100)]
|
netem += ["duplicate", "%s%%" % min(duplicate, 100)]
|
||||||
if delay <= 0 and loss <= 0 and duplicate <= 0:
|
if delay <= 0 and jitter <= 0 and loss <= 0 and duplicate <= 0:
|
||||||
# possibly remove netem if it exists and parent queue wasn't removed
|
# possibly remove netem if it exists and parent queue wasn't removed
|
||||||
if not netif.getparam('has_netem'):
|
if not netif.getparam('has_netem'):
|
||||||
return
|
return
|
||||||
tc[2] = "delete"
|
tc[2] = "delete"
|
||||||
if self.up:
|
if self.up:
|
||||||
|
if self.verbose:
|
||||||
|
self.info("linkconfig: %s" % \
|
||||||
|
([tc + parent + ["handle", "10:"]],))
|
||||||
check_call(tc + parent + ["handle", "10:"])
|
check_call(tc + parent + ["handle", "10:"])
|
||||||
netif.setparam('has_netem', False)
|
netif.setparam('has_netem', False)
|
||||||
elif len(netem) > 1:
|
elif len(netem) > 1:
|
||||||
if self.up:
|
if self.up:
|
||||||
|
if self.verbose:
|
||||||
|
self.info("linkconfig: %s" % \
|
||||||
|
([tc + parent + ["handle", "10:"] + netem],))
|
||||||
check_call(tc + parent + ["handle", "10:"] + netem)
|
check_call(tc + parent + ["handle", "10:"] + netem)
|
||||||
netif.setparam('has_netem', True)
|
netif.setparam('has_netem', True)
|
||||||
|
|
||||||
|
@ -416,6 +428,16 @@ class LxBrNet(PyCoreNet):
|
||||||
net._linked[netif] = {}
|
net._linked[netif] = {}
|
||||||
netif.net = self
|
netif.net = self
|
||||||
netif.othernet = net
|
netif.othernet = net
|
||||||
|
return netif
|
||||||
|
|
||||||
|
def getlinknetif(self, net):
|
||||||
|
''' Return the interface of that links this net with another net
|
||||||
|
(that were linked using linknet()).
|
||||||
|
'''
|
||||||
|
for netif in self.netifs():
|
||||||
|
if hasattr(netif, 'othernet') and netif.othernet == net:
|
||||||
|
return netif
|
||||||
|
return None
|
||||||
|
|
||||||
def addrconfig(self, addrlist):
|
def addrconfig(self, addrlist):
|
||||||
''' Set addresses on the bridge.
|
''' Set addresses on the bridge.
|
||||||
|
|
|
@ -510,6 +510,13 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
|
||||||
node2 = None
|
node2 = None
|
||||||
net = None
|
net = None
|
||||||
net2 = None
|
net2 = None
|
||||||
|
|
||||||
|
uni = msg.gettlv(coreapi.CORE_TLV_LINK_UNI)
|
||||||
|
if uni is not None and uni == 1:
|
||||||
|
unidirectional = True
|
||||||
|
else:
|
||||||
|
unidirectional = False
|
||||||
|
|
||||||
|
|
||||||
# one of the nodes may exist on a remote server
|
# one of the nodes may exist on a remote server
|
||||||
if nodenum1 is not None and nodenum2 is not None:
|
if nodenum1 is not None and nodenum2 is not None:
|
||||||
|
@ -657,7 +664,8 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
|
||||||
netaddrlist.append("%s/%s" % (ipv61, ipv6mask1))
|
netaddrlist.append("%s/%s" % (ipv61, ipv6mask1))
|
||||||
ifindex2 = node2.newnetif(net, addrlist = addrlist,
|
ifindex2 = node2.newnetif(net, addrlist = addrlist,
|
||||||
hwaddr = mac2, ifindex = ifindex2)
|
hwaddr = mac2, ifindex = ifindex2)
|
||||||
net.linkconfig(node2.netif(ifindex2, net), bw = bw,
|
if not unidirectional:
|
||||||
|
net.linkconfig(node2.netif(ifindex2, net), bw = bw,
|
||||||
delay = delay, loss = loss,
|
delay = delay, loss = loss,
|
||||||
duplicate = duplicate, jitter = jitter)
|
duplicate = duplicate, jitter = jitter)
|
||||||
if node2 is None and net2:
|
if node2 is None and net2:
|
||||||
|
@ -679,9 +687,19 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
|
||||||
if net and net2:
|
if net and net2:
|
||||||
# two layer-2 networks linked together
|
# two layer-2 networks linked together
|
||||||
if isinstance(net2, pycore.nodes.RJ45Node):
|
if isinstance(net2, pycore.nodes.RJ45Node):
|
||||||
net2.linknet(net) # RJ45 nodes have different linknet()
|
netif = net2.linknet(net) # RJ45 nodes have different linknet()
|
||||||
else:
|
else:
|
||||||
net.linknet(net2)
|
netif = net.linknet(net2)
|
||||||
|
net.linkconfig(netif, bw = bw, delay = delay, loss = loss,
|
||||||
|
duplicate = duplicate, jitter = jitter)
|
||||||
|
if not unidirectional:
|
||||||
|
netif.swapparams('_params_up')
|
||||||
|
net2.linkconfig(netif, bw = bw, delay = delay, loss = loss,
|
||||||
|
duplicate = duplicate, jitter = jitter,
|
||||||
|
devname = netif.name)
|
||||||
|
netif.swapparams('_params_up')
|
||||||
|
|
||||||
|
|
||||||
elif net is None and net2 is None and \
|
elif net is None and net2 is None and \
|
||||||
(node1 is None or node2 is None):
|
(node1 is None or node2 is None):
|
||||||
# apply address/parameters to PhysicalNodes
|
# apply address/parameters to PhysicalNodes
|
||||||
|
@ -742,8 +760,44 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
|
||||||
duplicate = msg.gettlv(coreapi.CORE_TLV_LINK_DUP)
|
duplicate = msg.gettlv(coreapi.CORE_TLV_LINK_DUP)
|
||||||
jitter = msg.gettlv(coreapi.CORE_TLV_LINK_JITTER)
|
jitter = msg.gettlv(coreapi.CORE_TLV_LINK_JITTER)
|
||||||
numnet = 0
|
numnet = 0
|
||||||
|
# TODO: clean up all this logic. Having the add flag or not
|
||||||
|
# should use the same code block.
|
||||||
if node1 is None and node2 is None:
|
if node1 is None and node2 is None:
|
||||||
raise ValueError, "modify link for unknown nodes"
|
if net and net2:
|
||||||
|
# modify link between nets
|
||||||
|
netif = net.getlinknetif(net2)
|
||||||
|
upstream = False
|
||||||
|
if netif is None:
|
||||||
|
upstream = True
|
||||||
|
netif = net2.getlinknetif(net)
|
||||||
|
if netif is None:
|
||||||
|
raise ValueError, "modify unknown link between nets"
|
||||||
|
if upstream:
|
||||||
|
netif.swapparams('_params_up')
|
||||||
|
net.linkconfig(netif, bw = bw, delay = delay,
|
||||||
|
loss = loss, duplicate = duplicate,
|
||||||
|
jitter = jitter, devname = netif.name)
|
||||||
|
netif.swapparams('_params_up')
|
||||||
|
else:
|
||||||
|
net.linkconfig(netif, bw = bw, delay = delay,
|
||||||
|
loss = loss, duplicate = duplicate,
|
||||||
|
jitter = jitter)
|
||||||
|
if not unidirectional:
|
||||||
|
if upstream:
|
||||||
|
net2.linkconfig(netif, bw = bw, delay = delay,
|
||||||
|
loss = loss,
|
||||||
|
duplicate = duplicate,
|
||||||
|
jitter = jitter)
|
||||||
|
else:
|
||||||
|
netif.swapparams('_params_up')
|
||||||
|
net2.linkconfig(netif, bw = bw, delay = delay,
|
||||||
|
loss = loss,
|
||||||
|
duplicate = duplicate,
|
||||||
|
jitter = jitter,
|
||||||
|
devname = netif.name)
|
||||||
|
netif.swapparams('_params_up')
|
||||||
|
else:
|
||||||
|
raise ValueError, "modify link for unknown nodes"
|
||||||
elif node1 is None:
|
elif node1 is None:
|
||||||
# node1 = layer 2node, node2 = layer3 node
|
# node1 = layer 2node, node2 = layer3 node
|
||||||
net.linkconfig(node2.netif(ifindex2, net), bw = bw,
|
net.linkconfig(node2.netif(ifindex2, net), bw = bw,
|
||||||
|
@ -763,7 +817,8 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
|
||||||
net.linkconfig(netif1, bw = bw, delay = delay,
|
net.linkconfig(netif1, bw = bw, delay = delay,
|
||||||
loss = loss, duplicate = duplicate,
|
loss = loss, duplicate = duplicate,
|
||||||
jitter = jitter, netif2 = netif2)
|
jitter = jitter, netif2 = netif2)
|
||||||
net.linkconfig(netif2, bw = bw, delay = delay,
|
if not unidirectional:
|
||||||
|
net.linkconfig(netif2, bw = bw, delay = delay,
|
||||||
loss = loss, duplicate = duplicate,
|
loss = loss, duplicate = duplicate,
|
||||||
jitter = jitter, netif2 = netif1)
|
jitter = jitter, netif2 = netif1)
|
||||||
numnet += 1
|
numnet += 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue