# # CORE # Copyright (c)2010-2013 the Boeing Company. # See the LICENSE file included in this distribution. # # author: core-dev@pf.itd.nrl.navy.mil # ''' nodes.py: definition of CoreNode classes and other node classes that inherit from the CoreNode, implementing specific node types. ''' from vnode import * from vnet import * from core.constants import * from core.misc.ipaddr import * from core.api import coreapi from core.bsd.netgraph import ngloadkernelmodule checkexec([IFCONFIG_BIN]) class CoreNode(JailNode): apitype = coreapi.CORE_NODE_DEF class PtpNet(NetgraphPipeNet): def tonodemsg(self, flags): ''' Do not generate a Node Message for point-to-point links. They are built using a link message instead. ''' pass def tolinkmsgs(self, flags): ''' Build CORE API TLVs for a point-to-point link. One Link message describes this network. ''' tlvdata = "" if len(self._netif) != 2: return tlvdata (if1, if2) = self._netif.items() if1 = if1[1] if2 = if2[1] tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N1NUMBER, if1.node.objid) tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER, if2.node.objid) delay = if1.getparam('delay') bw = if1.getparam('bw') loss = if1.getparam('loss') duplicate = if1.getparam('duplicate') 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, self.linktype) tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF1NUM, \ if1.node.getifindex(if1)) for addr in if1.addrlist: (ip, sep, mask) = addr.partition('/') mask = int(mask) if isIPv4Address(ip): family = AF_INET tlvtypeip = coreapi.CORE_TLV_LINK_IF1IP4 tlvtypemask = coreapi.CORE_TLV_LINK_IF1IP4MASK else: family = AF_INET6 tlvtypeip = coreapi.CORE_TLV_LINK_IF1IP6 tlvtypemask = coreapi.CORE_TLV_LINK_IF1IP6MASK ipl = socket.inet_pton(family, ip) tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, IPAddr(af=family, addr=ipl)) tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask) tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF2NUM, \ if2.node.getifindex(if2)) for addr in if2.addrlist: (ip, sep, mask) = addr.partition('/') mask = int(mask) if isIPv4Address(ip): family = AF_INET tlvtypeip = coreapi.CORE_TLV_LINK_IF2IP4 tlvtypemask = coreapi.CORE_TLV_LINK_IF2IP4MASK else: family = AF_INET6 tlvtypeip = coreapi.CORE_TLV_LINK_IF2IP6 tlvtypemask = coreapi.CORE_TLV_LINK_IF2IP6MASK ipl = socket.inet_pton(family, ip) tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, IPAddr(af=family, addr=ipl)) tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask) msg = coreapi.CoreLinkMessage.pack(flags, tlvdata) return [msg,] class SwitchNode(NetgraphNet): ngtype = "bridge" nghooks = "link0 link0\nmsg .link0 setpersistent" apitype = coreapi.CORE_NODE_SWITCH policy = "ACCEPT" class HubNode(NetgraphNet): ngtype = "hub" nghooks = "link0 link0\nmsg .link0 setpersistent" apitype = coreapi.CORE_NODE_HUB policy = "ACCEPT" class WlanNode(NetgraphNet): ngtype = "wlan" nghooks = "anchor anchor" apitype = coreapi.CORE_NODE_WLAN linktype = coreapi.CORE_LINK_WIRELESS policy = "DROP" def __init__(self, session, objid = None, name = None, verbose = False, start = True, policy = None): 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 def attach(self, netif): NetgraphNet.attach(self, netif) if self.model: netif.poshook = self.model._positioncallback if netif.node is None: return (x,y,z) = netif.node.position.get() netif.poshook(netif, x, y, z) def setmodel(self, model, config): ''' Mobility and wireless model. ''' if (self.verbose): self.info("adding model %s" % model._name) if model._type == coreapi.CORE_TLV_REG_WIRELESS: 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: (x,y,z) = netif.node.position.get() netif.poshook(netif, x, y, z) self.model.setlinkparams() elif model._type == coreapi.CORE_TLV_REG_MOBILITY: self.mobility = model(session=self.session, objid=self.objid, verbose=self.verbose, values=config) class RJ45Node(NetgraphPipeNet): apitype = coreapi.CORE_NODE_RJ45 policy = "ACCEPT" def __init__(self, session, objid, name, verbose, start = True): 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 check_call([IFCONFIG_BIN, self.name, "up", p]) def attach(self, netif): if len(self._netif) > 0: raise ValueError, \ "RJ45 networks support at most 1 network interface" NetgraphPipeNet.attach(self, netif) connectngnodes(self.ngname, self.name, self.gethook(), "lower") class TunnelNode(NetgraphNet): ngtype = "pipe" nghooks = "upper lower" apitype = coreapi.CORE_NODE_TUNNEL policy = "ACCEPT"