2013-08-29 15:21:13 +01:00
|
|
|
#
|
|
|
|
# CORE
|
|
|
|
# Copyright (c)2010-2013 the Boeing Company.
|
|
|
|
# See the LICENSE file included in this distribution.
|
|
|
|
#
|
|
|
|
# author: core-dev@pf.itd.nrl.navy.mil
|
|
|
|
#
|
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2013-08-29 15:21:13 +01:00
|
|
|
nodes.py: definition of CoreNode classes and other node classes that inherit
|
|
|
|
from the CoreNode, implementing specific node types.
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2013-08-29 15:21:13 +01:00
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
import socket
|
|
|
|
|
|
|
|
from core import constants
|
2013-08-29 15:21:13 +01:00
|
|
|
from core.api import coreapi
|
2017-04-25 16:45:34 +01:00
|
|
|
from core.bsd.netgraph import connectngnodes
|
2013-08-29 15:21:13 +01:00
|
|
|
from core.bsd.netgraph import ngloadkernelmodule
|
2017-04-25 16:45:34 +01:00
|
|
|
from core.bsd.vnet import NetgraphNet
|
|
|
|
from core.bsd.vnet import NetgraphPipeNet
|
|
|
|
from core.bsd.vnode import JailNode
|
|
|
|
from core.enumerations import LinkTlvs
|
|
|
|
from core.enumerations import LinkTypes
|
|
|
|
from core.enumerations import NodeTypes
|
|
|
|
from core.enumerations import RegisterTlvs
|
|
|
|
from core.misc import ipaddress
|
|
|
|
from core.misc import utils
|
|
|
|
|
|
|
|
utils.checkexec([constants.IFCONFIG_BIN])
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
class CoreNode(JailNode):
|
2017-04-25 16:45:34 +01:00
|
|
|
apitype = NodeTypes.DEFAULT.value
|
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
class PtpNet(NetgraphPipeNet):
|
|
|
|
def tonodemsg(self, flags):
|
2017-04-25 16:45:34 +01:00
|
|
|
""" Do not generate a Node Message for point-to-point links. They are
|
2013-08-29 15:21:13 +01:00
|
|
|
built using a link message instead.
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2013-08-29 15:21:13 +01:00
|
|
|
pass
|
|
|
|
|
|
|
|
def tolinkmsgs(self, flags):
|
2017-04-25 16:45:34 +01:00
|
|
|
""" Build CORE API TLVs for a point-to-point link. One Link message
|
2013-08-29 15:21:13 +01:00
|
|
|
describes this network.
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2013-08-29 15:21:13 +01:00
|
|
|
tlvdata = ""
|
|
|
|
if len(self._netif) != 2:
|
|
|
|
return tlvdata
|
|
|
|
(if1, if2) = self._netif.items()
|
|
|
|
if1 = if1[1]
|
|
|
|
if2 = if2[1]
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N1_NUMBER.value, if1.node.objid)
|
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N2_NUMBER.value, if2.node.objid)
|
|
|
|
delay = if1.getparam("delay")
|
|
|
|
bw = if1.getparam("bw")
|
|
|
|
loss = if1.getparam("loss")
|
|
|
|
duplicate = if1.getparam("duplicate")
|
|
|
|
jitter = if1.getparam("jitter")
|
2013-08-29 15:21:13 +01:00
|
|
|
if delay is not None:
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DELAY.value, delay)
|
2013-08-29 15:21:13 +01:00
|
|
|
if bw is not None:
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.BANDWIDTH.value, bw)
|
2013-08-29 15:21:13 +01:00
|
|
|
if loss is not None:
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.PER.value, str(loss))
|
2013-08-29 15:21:13 +01:00
|
|
|
if duplicate is not None:
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DUP.value, str(duplicate))
|
2013-08-29 15:21:13 +01:00
|
|
|
if jitter is not None:
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.JITTER.value, jitter)
|
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.TYPE.value, self.linktype)
|
2013-08-29 15:21:13 +01:00
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_NUMBER.value, if1.node.getifindex(if1))
|
2015-03-09 15:20:42 +00:00
|
|
|
if if1.hwaddr:
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_MAC.value, if1.hwaddr)
|
2013-08-29 15:21:13 +01:00
|
|
|
for addr in if1.addrlist:
|
2017-04-25 16:45:34 +01:00
|
|
|
(ip, sep, mask) = addr.partition("/")
|
2013-08-29 15:21:13 +01:00
|
|
|
mask = int(mask)
|
2017-04-25 16:45:34 +01:00
|
|
|
if ipaddress.is_ipv4_address(ip):
|
|
|
|
family = socket.AF_INET
|
|
|
|
tlvtypeip = LinkTlvs.INTERFACE1_IP4.value
|
|
|
|
tlvtypemask = LinkTlvs.INTERFACE1_IP4_MASK
|
2013-08-29 15:21:13 +01:00
|
|
|
else:
|
2017-04-25 16:45:34 +01:00
|
|
|
family = socket.AF_INET6
|
|
|
|
tlvtypeip = LinkTlvs.INTERFACE1_IP6.value
|
|
|
|
tlvtypemask = LinkTlvs.INTERFACE1_IP6_MASK.value
|
2013-08-29 15:21:13 +01:00
|
|
|
ipl = socket.inet_pton(family, ip)
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl))
|
2013-08-29 15:21:13 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
|
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_NUMBER.value, if2.node.getifindex(if2))
|
2015-03-09 15:20:42 +00:00
|
|
|
if if2.hwaddr:
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_MAC.value, if2.hwaddr)
|
2013-08-29 15:21:13 +01:00
|
|
|
for addr in if2.addrlist:
|
2017-04-25 16:45:34 +01:00
|
|
|
(ip, sep, mask) = addr.partition("/")
|
2013-08-29 15:21:13 +01:00
|
|
|
mask = int(mask)
|
2017-04-25 16:45:34 +01:00
|
|
|
if ipaddress.is_ipv4_address(ip):
|
|
|
|
family = socket.AF_INET
|
|
|
|
tlvtypeip = LinkTlvs.INTERFACE2_IP4.value
|
|
|
|
tlvtypemask = LinkTlvs.INTERFACE2_IP4_MASK
|
2013-08-29 15:21:13 +01:00
|
|
|
else:
|
2017-04-25 16:45:34 +01:00
|
|
|
family = socket.AF_INET6
|
|
|
|
tlvtypeip = LinkTlvs.INTERFACE2_IP6.value
|
|
|
|
tlvtypemask = LinkTlvs.INTERFACE2_IP6_MASK.value
|
2013-08-29 15:21:13 +01:00
|
|
|
ipl = socket.inet_pton(family, ip)
|
2017-04-25 16:45:34 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl))
|
2013-08-29 15:21:13 +01:00
|
|
|
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
|
|
|
|
|
|
|
|
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
|
2017-04-25 16:45:34 +01:00
|
|
|
return [msg, ]
|
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
class SwitchNode(NetgraphNet):
|
|
|
|
ngtype = "bridge"
|
|
|
|
nghooks = "link0 link0\nmsg .link0 setpersistent"
|
2017-04-25 16:45:34 +01:00
|
|
|
apitype = NodeTypes.SWITCH.value
|
2013-08-29 15:21:13 +01:00
|
|
|
policy = "ACCEPT"
|
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
class HubNode(NetgraphNet):
|
|
|
|
ngtype = "hub"
|
|
|
|
nghooks = "link0 link0\nmsg .link0 setpersistent"
|
2017-04-25 16:45:34 +01:00
|
|
|
apitype = NodeTypes.HUB.value
|
2013-08-29 15:21:13 +01:00
|
|
|
policy = "ACCEPT"
|
2017-04-25 16:45:34 +01:00
|
|
|
|
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
class WlanNode(NetgraphNet):
|
|
|
|
ngtype = "wlan"
|
|
|
|
nghooks = "anchor anchor"
|
2017-04-25 16:45:34 +01:00
|
|
|
apitype = NodeTypes.WIRELESS_LAN.value
|
|
|
|
linktype = LinkTypes.WIRELESS.value
|
2013-08-29 15:21:13 +01:00
|
|
|
policy = "DROP"
|
2017-04-25 16:45:34 +01:00
|
|
|
|
|
|
|
def __init__(self, session, objid=None, name=None, verbose=False,
|
|
|
|
start=True, policy=None):
|
2013-08-29 15:21:13 +01:00
|
|
|
NetgraphNet.__init__(self, session, objid, name, verbose, start, policy)
|
|
|
|
# wireless model such as basic range
|
|
|
|
self.model = None
|
|
|
|
# mobility model such as scripted
|
|
|
|
self.mobility = None
|
2017-04-25 16:45:34 +01:00
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
def attach(self, netif):
|
|
|
|
NetgraphNet.attach(self, netif)
|
|
|
|
if self.model:
|
|
|
|
netif.poshook = self.model._positioncallback
|
|
|
|
if netif.node is None:
|
|
|
|
return
|
2017-04-25 16:45:34 +01:00
|
|
|
x, y, z = netif.node.position.get()
|
2013-08-29 15:21:13 +01:00
|
|
|
netif.poshook(netif, x, y, z)
|
|
|
|
|
|
|
|
def setmodel(self, model, config):
|
2017-04-25 16:45:34 +01:00
|
|
|
""" Mobility and wireless model.
|
|
|
|
"""
|
|
|
|
if self.verbose:
|
2013-08-29 15:21:13 +01:00
|
|
|
self.info("adding model %s" % model._name)
|
2017-04-25 16:45:34 +01:00
|
|
|
if model._type == RegisterTlvs.WIRELESS.value:
|
2013-08-29 15:21:13 +01:00
|
|
|
self.model = model(session=self.session, objid=self.objid,
|
|
|
|
verbose=self.verbose, values=config)
|
|
|
|
if self.model._positioncallback:
|
|
|
|
for netif in self.netifs():
|
|
|
|
netif.poshook = self.model._positioncallback
|
|
|
|
if netif.node is not None:
|
2017-04-25 16:45:34 +01:00
|
|
|
(x, y, z) = netif.node.position.get()
|
2013-08-29 15:21:13 +01:00
|
|
|
netif.poshook(netif, x, y, z)
|
|
|
|
self.model.setlinkparams()
|
2017-04-25 16:45:34 +01:00
|
|
|
elif model._type == RegisterTlvs.MOBILITY.value:
|
2013-08-29 15:21:13 +01:00
|
|
|
self.mobility = model(session=self.session, objid=self.objid,
|
|
|
|
verbose=self.verbose, values=config)
|
|
|
|
|
|
|
|
|
|
|
|
class RJ45Node(NetgraphPipeNet):
|
2017-04-25 16:45:34 +01:00
|
|
|
apitype = NodeTypes.RJ45.value
|
2013-08-29 15:21:13 +01:00
|
|
|
policy = "ACCEPT"
|
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
def __init__(self, session, objid, name, verbose, start=True):
|
2013-08-29 15:21:13 +01:00
|
|
|
if start:
|
|
|
|
ngloadkernelmodule("ng_ether")
|
|
|
|
NetgraphPipeNet.__init__(self, session, objid, name, verbose, start)
|
|
|
|
if start:
|
|
|
|
self.setpromisc(True)
|
|
|
|
|
|
|
|
def shutdown(self):
|
|
|
|
self.setpromisc(False)
|
|
|
|
NetgraphPipeNet.shutdown(self)
|
|
|
|
|
|
|
|
def setpromisc(self, promisc):
|
|
|
|
p = "promisc"
|
|
|
|
if not promisc:
|
|
|
|
p = "-" + p
|
2017-04-25 16:45:34 +01:00
|
|
|
utils.check_call([constants.IFCONFIG_BIN, self.name, "up", p])
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
def attach(self, netif):
|
|
|
|
if len(self._netif) > 0:
|
|
|
|
raise ValueError, \
|
2017-04-25 16:45:34 +01:00
|
|
|
"RJ45 networks support at most 1 network interface"
|
2013-08-29 15:21:13 +01:00
|
|
|
NetgraphPipeNet.attach(self, netif)
|
|
|
|
connectngnodes(self.ngname, self.name, self.gethook(), "lower")
|
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
class TunnelNode(NetgraphNet):
|
|
|
|
ngtype = "pipe"
|
|
|
|
nghooks = "upper lower"
|
2017-04-25 16:45:34 +01:00
|
|
|
apitype = NodeTypes.TUNNEL.value
|
2013-08-29 15:21:13 +01:00
|
|
|
policy = "ACCEPT"
|