removed old examples, updated examples api to denote they are python script examples
This commit is contained in:
parent
319c10aa34
commit
41f7f46988
12 changed files with 1 additions and 1342 deletions
|
@ -19,7 +19,7 @@ scripting network emulation.
|
|||
* Documentation hosted on GitHub
|
||||
* <http://coreemu.github.io/core/>
|
||||
* Basic Script Examples
|
||||
* [Examples](daemon/examples/api)
|
||||
* [Examples](daemon/examples/python)
|
||||
* Custom Service Example
|
||||
* [sample.py](daemon/examples/myservices/sample.py)
|
||||
* Custom Emane Model Example
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
import logging
|
||||
import time
|
||||
|
||||
from core.location.event import EventLoop
|
||||
|
||||
|
||||
def main():
|
||||
loop = EventLoop()
|
||||
|
||||
def msg(arg):
|
||||
delta = time.time() - loop.start
|
||||
logging.debug("%s arg: %s", delta, arg)
|
||||
|
||||
def repeat(interval, count):
|
||||
count -= 1
|
||||
msg("repeat: interval: %s; remaining: %s" % (interval, count))
|
||||
if count > 0:
|
||||
loop.add_event(interval, repeat, interval, count)
|
||||
|
||||
def sleep(delay):
|
||||
msg("sleep %s" % delay)
|
||||
time.sleep(delay)
|
||||
msg("sleep done")
|
||||
|
||||
def stop(arg):
|
||||
msg(arg)
|
||||
loop.stop()
|
||||
|
||||
loop.add_event(0, msg, "start")
|
||||
loop.add_event(0, msg, "time zero")
|
||||
|
||||
for delay in 5, 4, 10, -1, 0, 9, 3, 7, 3.14:
|
||||
loop.add_event(delay, msg, "time %s" % delay)
|
||||
|
||||
loop.run()
|
||||
|
||||
loop.add_event(0, repeat, 1, 5)
|
||||
loop.add_event(12, sleep, 10)
|
||||
|
||||
loop.add_event(15.75, stop, "stop time: 15.75")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,212 +0,0 @@
|
|||
#!/usr/bin/python -i
|
||||
|
||||
# Copyright (c)2010-2013 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
|
||||
# A distributed example where CORE API messaging is used to create a session
|
||||
# on a daemon server. The daemon server defaults to 127.0.0.1:4038
|
||||
# to target a remote machine specify "-d <ip address>" parameter, it needs to be
|
||||
# running the daemon with listenaddr=0.0.0.0 in the core.conf file.
|
||||
# This script creates no nodes locally and therefore can be run as an
|
||||
# unprivileged user.
|
||||
|
||||
import datetime
|
||||
import optparse
|
||||
import sys
|
||||
from builtins import range
|
||||
|
||||
import core.nodes.base
|
||||
import core.nodes.network
|
||||
from core.api.tlv import coreapi, dataconversion
|
||||
from core.api.tlv.coreapi import CoreExecuteTlv
|
||||
from core.emulator.enumerations import (
|
||||
CORE_API_PORT,
|
||||
EventTlvs,
|
||||
EventTypes,
|
||||
ExecuteTlvs,
|
||||
LinkTlvs,
|
||||
LinkTypes,
|
||||
MessageFlags,
|
||||
MessageTypes,
|
||||
)
|
||||
from core.emulator.session import Session
|
||||
from core.nodes import ipaddress
|
||||
|
||||
# declare classes for use with Broker
|
||||
|
||||
# node list (count from 1)
|
||||
n = [None]
|
||||
exec_num = 1
|
||||
|
||||
|
||||
def cmd(node, exec_cmd):
|
||||
"""
|
||||
:param node: The node the command should be issued too
|
||||
:param exec_cmd: A string with the command to be run
|
||||
:return: Returns the result of the command
|
||||
"""
|
||||
global exec_num
|
||||
|
||||
# Set up the command api message
|
||||
tlvdata = CoreExecuteTlv.pack(ExecuteTlvs.NODE.value, node.id)
|
||||
tlvdata += CoreExecuteTlv.pack(ExecuteTlvs.NUMBER.value, exec_num)
|
||||
tlvdata += CoreExecuteTlv.pack(ExecuteTlvs.COMMAND.value, exec_cmd)
|
||||
msg = coreapi.CoreExecMessage.pack(
|
||||
MessageFlags.STRING.value | MessageFlags.TEXT.value, tlvdata
|
||||
)
|
||||
node.session.broker.handlerawmsg(msg)
|
||||
exec_num += 1
|
||||
|
||||
# Now wait for the response
|
||||
server = node.session.broker.servers["localhost"]
|
||||
server.sock.settimeout(50.0)
|
||||
|
||||
# receive messages until we get our execute response
|
||||
result = None
|
||||
while True:
|
||||
msghdr = server.sock.recv(coreapi.CoreMessage.header_len)
|
||||
msgtype, msgflags, msglen = coreapi.CoreMessage.unpack_header(msghdr)
|
||||
msgdata = server.sock.recv(msglen)
|
||||
|
||||
# If we get the right response return the results
|
||||
print("received response message: %s" % MessageTypes(msgtype))
|
||||
if msgtype == MessageTypes.EXECUTE.value:
|
||||
msg = coreapi.CoreExecMessage(msgflags, msghdr, msgdata)
|
||||
result = msg.get_tlv(ExecuteTlvs.RESULT.value)
|
||||
break
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
usagestr = "usage: %prog [-n] number of nodes [-d] daemon address"
|
||||
parser = optparse.OptionParser(usage=usagestr)
|
||||
parser.set_defaults(numnodes=5, daemon="127.0.0.1:" + str(CORE_API_PORT))
|
||||
|
||||
parser.add_option(
|
||||
"-n", "--numnodes", dest="numnodes", type=int, help="number of nodes"
|
||||
)
|
||||
parser.add_option(
|
||||
"-d",
|
||||
"--daemon-server",
|
||||
dest="daemon",
|
||||
type=str,
|
||||
help="daemon server IP address",
|
||||
)
|
||||
|
||||
def usage(msg=None, err=0):
|
||||
sys.stdout.write("\n")
|
||||
if msg:
|
||||
sys.stdout.write(msg + "\n\n")
|
||||
parser.print_help()
|
||||
sys.exit(err)
|
||||
|
||||
# parse command line options
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.numnodes < 1:
|
||||
usage("invalid number of nodes: %s" % options.numnodes)
|
||||
if not options.daemon:
|
||||
usage("daemon server IP address (-d) is a required argument")
|
||||
|
||||
for a in args:
|
||||
sys.stderr.write("ignoring command line argument: %s\n" % a)
|
||||
|
||||
start = datetime.datetime.now()
|
||||
|
||||
prefix = ipaddress.Ipv4Prefix("10.83.0.0/16")
|
||||
session = Session(1)
|
||||
server = globals().get("server")
|
||||
if server:
|
||||
server.addsession(session)
|
||||
|
||||
# distributed setup - connect to daemon server
|
||||
daemonport = options.daemon.split(":")
|
||||
daemonip = daemonport[0]
|
||||
|
||||
# Localhost is already set in the session but we change it to be the remote daemon
|
||||
# This stops the remote daemon trying to build a tunnel back which would fail
|
||||
daemon = "localhost"
|
||||
if len(daemonport) > 1:
|
||||
port = int(daemonport[1])
|
||||
else:
|
||||
port = CORE_API_PORT
|
||||
print("connecting to daemon at %s:%d" % (daemon, port))
|
||||
session.broker.addserver(daemon, daemonip, port)
|
||||
|
||||
# Set the local session id to match the port.
|
||||
# Not necessary but seems neater.
|
||||
session.broker.setupserver(daemon)
|
||||
|
||||
# We do not want the recvloop running as we will deal ourselves
|
||||
session.broker.dorecvloop = False
|
||||
|
||||
# Change to configuration state on both machines
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
tlvdata = coreapi.CoreEventTlv.pack(
|
||||
EventTlvs.TYPE.value, EventTypes.CONFIGURATION_STATE.value
|
||||
)
|
||||
session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata))
|
||||
|
||||
flags = MessageFlags.ADD.value
|
||||
switch = core.nodes.network.SwitchNode(session=session, name="switch", start=False)
|
||||
switch.setposition(x=80, y=50)
|
||||
switch.server = daemon
|
||||
switch_data = switch.data(flags)
|
||||
switch_message = dataconversion.convert_node(switch_data)
|
||||
session.broker.handlerawmsg(switch_message)
|
||||
|
||||
number_of_nodes = options.numnodes
|
||||
|
||||
print(
|
||||
"creating %d remote nodes with addresses from %s" % (options.numnodes, prefix)
|
||||
)
|
||||
|
||||
# create remote nodes via API
|
||||
for i in range(1, number_of_nodes + 1):
|
||||
node = core.nodes.base.CoreNode(
|
||||
session=session, _id=i, name="n%d" % i, start=False
|
||||
)
|
||||
node.setposition(x=150 * i, y=150)
|
||||
node.server = daemon
|
||||
node_data = node.data(flags)
|
||||
node_message = dataconversion.convert_node(node_data)
|
||||
session.broker.handlerawmsg(node_message)
|
||||
n.append(node)
|
||||
|
||||
# create remote links via API
|
||||
for i in range(1, number_of_nodes + 1):
|
||||
tlvdata = coreapi.CoreLinkTlv.pack(LinkTlvs.N1_NUMBER.value, switch.id)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N2_NUMBER.value, i)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.TYPE.value, LinkTypes.WIRED.value)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_NUMBER.value, 0)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(
|
||||
LinkTlvs.INTERFACE2_IP4.value, prefix.addr(i)
|
||||
)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(
|
||||
LinkTlvs.INTERFACE2_IP4_MASK.value, prefix.prefixlen
|
||||
)
|
||||
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
|
||||
session.broker.handlerawmsg(msg)
|
||||
|
||||
# We change the daemon to Instantiation state
|
||||
# We do not change the local session as it would try and build a tunnel and fail
|
||||
tlvdata = coreapi.CoreEventTlv.pack(
|
||||
EventTlvs.TYPE.value, EventTypes.INSTANTIATION_STATE.value
|
||||
)
|
||||
msg = coreapi.CoreEventMessage.pack(0, tlvdata)
|
||||
session.broker.handlerawmsg(msg)
|
||||
|
||||
# Get the ip or last node and ping it from the first
|
||||
print("Pinging from the first to the last node")
|
||||
pingip = cmd(n[-1], "ip -4 -o addr show dev eth0").split()[3].split("/")[0]
|
||||
print(cmd(n[1], "ping -c 5 " + pingip))
|
||||
print("elapsed time: %s" % (datetime.datetime.now() - start))
|
||||
print(
|
||||
"To stop this session, use the core-cleanup script on the remote daemon server."
|
||||
)
|
||||
input("press enter to exit")
|
||||
|
||||
|
||||
if __name__ == "__main__" or __name__ == "__builtin__":
|
||||
main()
|
|
@ -1,151 +0,0 @@
|
|||
#!/usr/bin/python -i
|
||||
|
||||
# Copyright (c)2010-2013 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
|
||||
# A distributed example where CORE API messaging is used to create a session
|
||||
# distributed across the local server and one slave server. The slave server
|
||||
# must be specified using the '-s <ip address>' parameter, and needs to be
|
||||
# running the daemon with listenaddr=0.0.0.0 in the core.conf file.
|
||||
#
|
||||
|
||||
import datetime
|
||||
import optparse
|
||||
import sys
|
||||
from builtins import range
|
||||
|
||||
import core.nodes.base
|
||||
import core.nodes.network
|
||||
from core import constants
|
||||
from core.api.tlv import coreapi, dataconversion
|
||||
from core.emulator.enumerations import (
|
||||
CORE_API_PORT,
|
||||
EventTlvs,
|
||||
EventTypes,
|
||||
LinkTlvs,
|
||||
LinkTypes,
|
||||
MessageFlags,
|
||||
)
|
||||
from core.emulator.session import Session
|
||||
from core.nodes import ipaddress
|
||||
|
||||
# node list (count from 1)
|
||||
n = [None]
|
||||
|
||||
|
||||
def main():
|
||||
usagestr = "usage: %prog [-h] [options] [args]"
|
||||
parser = optparse.OptionParser(usage=usagestr)
|
||||
parser.set_defaults(numnodes=5, slave=None)
|
||||
|
||||
parser.add_option(
|
||||
"-n", "--numnodes", dest="numnodes", type=int, help="number of nodes"
|
||||
)
|
||||
parser.add_option(
|
||||
"-s", "--slave-server", dest="slave", type=str, help="slave server IP address"
|
||||
)
|
||||
|
||||
def usage(msg=None, err=0):
|
||||
sys.stdout.write("\n")
|
||||
if msg:
|
||||
sys.stdout.write(msg + "\n\n")
|
||||
parser.print_help()
|
||||
sys.exit(err)
|
||||
|
||||
# parse command line options
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.numnodes < 1:
|
||||
usage("invalid number of nodes: %s" % options.numnodes)
|
||||
if not options.slave:
|
||||
usage("slave server IP address (-s) is a required argument")
|
||||
|
||||
for a in args:
|
||||
sys.stderr.write("ignoring command line argument: '%s'\n" % a)
|
||||
|
||||
start = datetime.datetime.now()
|
||||
|
||||
prefix = ipaddress.Ipv4Prefix("10.83.0.0/16")
|
||||
session = Session(1)
|
||||
server = globals().get("server")
|
||||
if server is not None:
|
||||
server.addsession(session)
|
||||
|
||||
# distributed setup - connect to slave server
|
||||
slaveport = options.slave.split(":")
|
||||
slave = slaveport[0]
|
||||
if len(slaveport) > 1:
|
||||
port = int(slaveport[1])
|
||||
else:
|
||||
port = CORE_API_PORT
|
||||
print("connecting to slave at %s:%d" % (slave, port))
|
||||
session.broker.addserver(slave, slave, port)
|
||||
session.broker.setupserver(slave)
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
tlvdata = coreapi.CoreEventTlv.pack(
|
||||
EventTlvs.TYPE.value, EventTypes.CONFIGURATION_STATE.value
|
||||
)
|
||||
session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata))
|
||||
|
||||
switch = session.create_node(cls=core.nodes.network.SwitchNode, name="switch")
|
||||
switch.setposition(x=80, y=50)
|
||||
num_local = options.numnodes / 2
|
||||
num_remote = options.numnodes / 2 + options.numnodes % 2
|
||||
print(
|
||||
"creating %d (%d local / %d remote) nodes with addresses from %s"
|
||||
% (options.numnodes, num_local, num_remote, prefix)
|
||||
)
|
||||
for i in range(1, num_local + 1):
|
||||
node = session.create_node(cls=core.nodes.base.CoreNode, name="n%d" % i, _id=i)
|
||||
node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
|
||||
node.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
|
||||
node.setposition(x=150 * i, y=150)
|
||||
n.append(node)
|
||||
|
||||
flags = MessageFlags.ADD.value
|
||||
session.broker.handlerawmsg(switch.tonodemsg(flags=flags))
|
||||
|
||||
# create remote nodes via API
|
||||
for i in range(num_local + 1, options.numnodes + 1):
|
||||
node = core.nodes.base.CoreNode(
|
||||
session=session, _id=i, name="n%d" % i, start=False
|
||||
)
|
||||
node.setposition(x=150 * i, y=150)
|
||||
node.server = slave
|
||||
n.append(node)
|
||||
node_data = node.data(flags)
|
||||
node_message = dataconversion.convert_node(node_data)
|
||||
session.broker.handlerawmsg(node_message)
|
||||
|
||||
# create remote links via API
|
||||
for i in range(num_local + 1, options.numnodes + 1):
|
||||
tlvdata = coreapi.CoreLinkTlv.pack(LinkTlvs.N1_NUMBER.value, switch.id)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N2_NUMBER.value, i)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.TYPE.value, LinkTypes.WIRED.value)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_NUMBER.value, 0)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(
|
||||
LinkTlvs.INTERFACE2_IP4.value, prefix.addr(i)
|
||||
)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(
|
||||
LinkTlvs.INTERFACE2_IP4_MASK.value, prefix.prefixlen
|
||||
)
|
||||
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
|
||||
session.broker.handlerawmsg(msg)
|
||||
|
||||
session.instantiate()
|
||||
tlvdata = coreapi.CoreEventTlv.pack(
|
||||
EventTlvs.TYPE.value, EventTypes.INSTANTIATION_STATE.value
|
||||
)
|
||||
msg = coreapi.CoreEventMessage.pack(0, tlvdata)
|
||||
session.broker.handlerawmsg(msg)
|
||||
|
||||
# start a shell on node 1
|
||||
n[1].client.term("bash")
|
||||
|
||||
print("elapsed time: %s" % (datetime.datetime.now() - start))
|
||||
print("To stop this session, use the 'core-cleanup' script on this server")
|
||||
print("and on the remote slave server.")
|
||||
|
||||
|
||||
if __name__ == "__main__" or __name__ == "__builtin__":
|
||||
main()
|
|
@ -1,247 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c)2010-2012 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
|
||||
"""
|
||||
howmanynodes.py - This is a CORE script that creates network namespace nodes
|
||||
having one virtual Ethernet interface connected to a bridge. It continues to
|
||||
add nodes until an exception occurs. The number of nodes per bridge can be
|
||||
specified.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import optparse
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
|
||||
import core.nodes.base
|
||||
import core.nodes.network
|
||||
from core import constants
|
||||
from core.emulator.session import Session
|
||||
from core.nodes import ipaddress
|
||||
|
||||
GBD = 1024.0 * 1024.0
|
||||
|
||||
|
||||
def linuxversion():
|
||||
""" Return a string having the Linux kernel version.
|
||||
"""
|
||||
f = open("/proc/version", "r")
|
||||
v = f.readline().split()
|
||||
version_str = " ".join(v[:3])
|
||||
f.close()
|
||||
return version_str
|
||||
|
||||
|
||||
MEMKEYS = ("total", "free", "buff", "cached", "stotal", "sfree")
|
||||
|
||||
|
||||
def memfree():
|
||||
""" Returns kilobytes memory [total, free, buff, cached, stotal, sfree].
|
||||
useful stats are:
|
||||
free memory = free + buff + cached
|
||||
swap used = stotal - sfree
|
||||
"""
|
||||
f = open("/proc/meminfo", "r")
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
kbs = {}
|
||||
for k in MEMKEYS:
|
||||
kbs[k] = 0
|
||||
for l in lines:
|
||||
if l[:9] == "MemTotal:":
|
||||
kbs["total"] = int(l.split()[1])
|
||||
elif l[:8] == "MemFree:":
|
||||
kbs["free"] = int(l.split()[1])
|
||||
elif l[:8] == "Buffers:":
|
||||
kbs["buff"] = int(l.split()[1])
|
||||
elif l[:8] == "Cached:":
|
||||
kbs["cache"] = int(l.split()[1])
|
||||
elif l[:10] == "SwapTotal:":
|
||||
kbs["stotal"] = int(l.split()[1])
|
||||
elif l[:9] == "SwapFree:":
|
||||
kbs["sfree"] = int(l.split()[1])
|
||||
break
|
||||
return kbs
|
||||
|
||||
|
||||
# node list (count from 1)
|
||||
nodelist = [None]
|
||||
switchlist = []
|
||||
|
||||
|
||||
def main():
|
||||
usagestr = "usage: %prog [-h] [options] [args]"
|
||||
parser = optparse.OptionParser(usage=usagestr)
|
||||
parser.set_defaults(
|
||||
waittime=0.2, numnodes=0, bridges=0, retries=0, logfile=None, services=None
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
"-w",
|
||||
"--waittime",
|
||||
dest="waittime",
|
||||
type=float,
|
||||
help="number of seconds to wait between node creation"
|
||||
" (default = %s)" % parser.defaults["waittime"],
|
||||
)
|
||||
parser.add_option(
|
||||
"-n",
|
||||
"--numnodes",
|
||||
dest="numnodes",
|
||||
type=int,
|
||||
help="number of nodes (default = unlimited)",
|
||||
)
|
||||
parser.add_option(
|
||||
"-b",
|
||||
"--bridges",
|
||||
dest="bridges",
|
||||
type=int,
|
||||
help="number of nodes per bridge; 0 = one bridge "
|
||||
"(def. = %s)" % parser.defaults["bridges"],
|
||||
)
|
||||
parser.add_option(
|
||||
"-r",
|
||||
"--retry",
|
||||
dest="retries",
|
||||
type=int,
|
||||
help="number of retries on error (default = %s)" % parser.defaults["retries"],
|
||||
)
|
||||
parser.add_option(
|
||||
"-l",
|
||||
"--log",
|
||||
dest="logfile",
|
||||
type=str,
|
||||
help="log memory usage to this file (default = %s)"
|
||||
% parser.defaults["logfile"],
|
||||
)
|
||||
parser.add_option(
|
||||
"-s",
|
||||
"--services",
|
||||
dest="services",
|
||||
type=str,
|
||||
help="pipe-delimited list of services added to each "
|
||||
"node (default = %s)\n(Example: zebra|OSPFv2|OSPFv3|"
|
||||
"IPForward)" % parser.defaults["services"],
|
||||
)
|
||||
|
||||
def usage(msg=None, err=0):
|
||||
sys.stdout.write("\n")
|
||||
if msg:
|
||||
sys.stdout.write(msg + "\n\n")
|
||||
parser.print_help()
|
||||
sys.exit(err)
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
for a in args:
|
||||
sys.stderr.write("ignoring command line argument: %s\n" % a)
|
||||
|
||||
start = datetime.datetime.now()
|
||||
prefix = ipaddress.Ipv4Prefix("10.83.0.0/16")
|
||||
|
||||
print("Testing how many network namespace nodes this machine can create.")
|
||||
print(" - %s" % linuxversion())
|
||||
mem = memfree()
|
||||
print(
|
||||
" - %.02f GB total memory (%.02f GB swap)"
|
||||
% (mem["total"] / GBD, mem["stotal"] / GBD)
|
||||
)
|
||||
print(" - using IPv4 network prefix %s" % prefix)
|
||||
print(" - using wait time of %s" % options.waittime)
|
||||
print(" - using %d nodes per bridge" % options.bridges)
|
||||
print(" - will retry %d times on failure" % options.retries)
|
||||
print(" - adding these services to each node: %s" % options.services)
|
||||
print(" ")
|
||||
|
||||
lfp = None
|
||||
if options.logfile is not None:
|
||||
# initialize a csv log file header
|
||||
lfp = open(options.logfile, "a")
|
||||
lfp.write("# log from howmanynodes.py %s\n" % time.ctime())
|
||||
lfp.write("# options = %s\n#\n" % options)
|
||||
lfp.write("# numnodes,%s\n" % ",".join(MEMKEYS))
|
||||
lfp.flush()
|
||||
|
||||
session = Session(1)
|
||||
switch = session.create_node(cls=core.nodes.network.SwitchNode)
|
||||
switchlist.append(switch)
|
||||
print("Added bridge %s (%d)." % (switch.brname, len(switchlist)))
|
||||
|
||||
i = 0
|
||||
retry_count = options.retries
|
||||
while True:
|
||||
i += 1
|
||||
# optionally add a bridge (options.bridges nodes per bridge)
|
||||
try:
|
||||
if 0 < options.bridges <= switch.numnetif():
|
||||
switch = session.create_node(cls=core.nodes.network.SwitchNode)
|
||||
switchlist.append(switch)
|
||||
print(
|
||||
"\nAdded bridge %s (%d) for node %d."
|
||||
% (switch.brname, len(switchlist), i)
|
||||
)
|
||||
except Exception as e:
|
||||
print(
|
||||
"At %d bridges (%d nodes) caught exception:\n%s\n"
|
||||
% (len(switchlist), i - 1, e)
|
||||
)
|
||||
break
|
||||
|
||||
# create a node
|
||||
try:
|
||||
n = session.create_node(cls=core.nodes.base.CoreNode, name="n%d" % i)
|
||||
n.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)])
|
||||
n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"])
|
||||
if options.services is not None:
|
||||
session.services.add_services(n, "", options.services.split("|"))
|
||||
session.services.boot_services(n)
|
||||
nodelist.append(n)
|
||||
if i % 25 == 0:
|
||||
print("\n%s nodes created " % i)
|
||||
mem = memfree()
|
||||
free = mem["free"] + mem["buff"] + mem["cached"]
|
||||
swap = mem["stotal"] - mem["sfree"]
|
||||
print("(%.02f/%.02f GB free/swap)" % (free / GBD, swap / GBD))
|
||||
if lfp:
|
||||
lfp.write("%d," % i)
|
||||
lfp.write("%s\n" % ",".join(str(mem[x]) for x in MEMKEYS))
|
||||
lfp.flush()
|
||||
else:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
time.sleep(options.waittime)
|
||||
except Exception as e:
|
||||
print("At %d nodes caught exception:\n" % i, e)
|
||||
if retry_count > 0:
|
||||
print("\nWill retry creating node %d." % i)
|
||||
shutil.rmtree(n.nodedir, ignore_errors=True)
|
||||
retry_count -= 1
|
||||
i -= 1
|
||||
time.sleep(options.waittime)
|
||||
continue
|
||||
else:
|
||||
print("Stopping at %d nodes!" % i)
|
||||
break
|
||||
|
||||
if i == options.numnodes:
|
||||
print("Stopping at %d nodes due to numnodes option." % i)
|
||||
break
|
||||
# node creation was successful at this point
|
||||
retry_count = options.retries
|
||||
|
||||
if lfp:
|
||||
lfp.flush()
|
||||
lfp.close()
|
||||
|
||||
print("elapsed time: %s" % (datetime.datetime.now() - start))
|
||||
print("Use the core-cleanup script to remove nodes and bridges.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,637 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c)2011-2014 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
|
||||
# create a random topology running OSPFv3 MDR, wait and then check
|
||||
# that all neighbor states are either full or two-way, and check the routes
|
||||
# in zebra vs those installed in the kernel.
|
||||
|
||||
import datetime
|
||||
import optparse
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
from builtins import range
|
||||
from string import Template
|
||||
|
||||
import core.nodes.base
|
||||
import core.nodes.network
|
||||
from core.constants import QUAGGA_STATE_DIR
|
||||
from core.emulator.session import Session
|
||||
from core.nodes import ipaddress
|
||||
from core.utils import check_cmd
|
||||
|
||||
quagga_sbin_search = ("/usr/local/sbin", "/usr/sbin", "/usr/lib/quagga")
|
||||
quagga_path = "zebra"
|
||||
|
||||
# sanity check that zebra is installed
|
||||
try:
|
||||
for p in quagga_sbin_search:
|
||||
if os.path.exists(os.path.join(p, "zebra")):
|
||||
quagga_path = p
|
||||
break
|
||||
check_cmd([os.path.join(quagga_path, "zebra"), "-u", "root", "-g", "root", "-v"])
|
||||
except OSError:
|
||||
sys.stderr.write("ERROR: running zebra failed\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class ManetNode(core.nodes.base.CoreNode):
|
||||
""" An Lxc namespace node configured for Quagga OSPFv3 MANET MDR
|
||||
"""
|
||||
|
||||
conftemp = Template(
|
||||
"""\
|
||||
interface eth0
|
||||
ip address $ipaddr
|
||||
ipv6 ospf6 instance-id 65
|
||||
ipv6 ospf6 hello-interval 2
|
||||
ipv6 ospf6 dead-interval 6
|
||||
ipv6 ospf6 retransmit-interval 5
|
||||
ipv6 ospf6 network manet-designated-router
|
||||
ipv6 ospf6 diffhellos
|
||||
ipv6 ospf6 adjacencyconnectivity biconnected
|
||||
ipv6 ospf6 lsafullness mincostlsa
|
||||
!
|
||||
router ospf6
|
||||
router-id $routerid
|
||||
interface eth0 area 0.0.0.0
|
||||
!
|
||||
ip forwarding
|
||||
"""
|
||||
)
|
||||
|
||||
confdir = "/usr/local/etc/quagga"
|
||||
|
||||
def __init__(self, core, ipaddr, routerid=None, _id=None, name=None, nodedir=None):
|
||||
if routerid is None:
|
||||
routerid = ipaddr.split("/")[0]
|
||||
self.ipaddr = ipaddr
|
||||
self.routerid = routerid
|
||||
core.nodes.base.CoreBaseNode.__init__(self, core, _id, name, nodedir)
|
||||
self.privatedir(self.confdir)
|
||||
self.privatedir(QUAGGA_STATE_DIR)
|
||||
|
||||
def qconf(self):
|
||||
return self.conftemp.substitute(ipaddr=self.ipaddr, routerid=self.routerid)
|
||||
|
||||
def config(self):
|
||||
filename = os.path.join(self.confdir, "Quagga.conf")
|
||||
f = self.opennodefile(filename, "w")
|
||||
f.write(self.qconf())
|
||||
f.close()
|
||||
tmp = self.bootscript()
|
||||
if tmp:
|
||||
self.nodefile(self.bootsh, tmp, mode=0o755)
|
||||
|
||||
def boot(self):
|
||||
self.config()
|
||||
self.session.services.boot_services(self)
|
||||
|
||||
def bootscript(self):
|
||||
return """\
|
||||
#!/bin/sh -e
|
||||
|
||||
STATEDIR=%s
|
||||
|
||||
waitfile()
|
||||
{
|
||||
fname=$1
|
||||
|
||||
i=0
|
||||
until [ -e $fname ]; do
|
||||
i=$(($i + 1))
|
||||
if [ $i -eq 10 ]; then
|
||||
echo "file not found: $fname" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
|
||||
mkdir -p $STATEDIR
|
||||
|
||||
%s/zebra -d -u root -g root
|
||||
waitfile $STATEDIR/zebra.vty
|
||||
|
||||
%s/ospf6d -d -u root -g root
|
||||
waitfile $STATEDIR/ospf6d.vty
|
||||
|
||||
vtysh -b
|
||||
""" % (
|
||||
QUAGGA_STATE_DIR,
|
||||
quagga_path,
|
||||
quagga_path,
|
||||
)
|
||||
|
||||
|
||||
class Route(object):
|
||||
""" Helper class for organzing routing table entries. """
|
||||
|
||||
def __init__(self, prefix=None, gw=None, metric=None):
|
||||
try:
|
||||
self.prefix = ipaddress.Ipv4Prefix(prefix)
|
||||
except Exception as e:
|
||||
raise ValueError(
|
||||
"Invalid prefix given to Route object: %s\n%s" % (prefix, e)
|
||||
)
|
||||
self.gw = gw
|
||||
self.metric = metric
|
||||
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
return (
|
||||
self.prefix == other.prefix
|
||||
and self.gw == other.gw
|
||||
and self.metric == other.metric
|
||||
)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return "(%s,%s,%s)" % (self.prefix, self.gw, self.metric)
|
||||
|
||||
@staticmethod
|
||||
def key(r):
|
||||
if not r.prefix:
|
||||
return 0
|
||||
return r.prefix.prefix
|
||||
|
||||
|
||||
class ManetExperiment(object):
|
||||
""" A class for building an MDR network and checking and logging its state.
|
||||
"""
|
||||
|
||||
def __init__(self, options, start):
|
||||
""" Initialize with options and start time. """
|
||||
self.session = None
|
||||
# node list
|
||||
self.nodes = []
|
||||
# WLAN network
|
||||
self.net = None
|
||||
self.verbose = options.verbose
|
||||
# dict from OptionParser
|
||||
self.options = options
|
||||
self.start = start
|
||||
self.logbegin()
|
||||
|
||||
def info(self, msg):
|
||||
""" Utility method for writing output to stdout. """
|
||||
print(msg)
|
||||
sys.stdout.flush()
|
||||
self.log(msg)
|
||||
|
||||
def warn(self, msg):
|
||||
""" Utility method for writing output to stderr. """
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.flush()
|
||||
self.log(msg)
|
||||
|
||||
def logbegin(self):
|
||||
""" Start logging. """
|
||||
self.logfp = None
|
||||
if not self.options.logfile:
|
||||
return
|
||||
self.logfp = open(self.options.logfile, "w")
|
||||
self.log("ospfmanetmdrtest begin: %s\n" % self.start.ctime())
|
||||
|
||||
def logend(self):
|
||||
""" End logging. """
|
||||
if not self.logfp:
|
||||
return
|
||||
end = datetime.datetime.now()
|
||||
self.log("ospfmanetmdrtest end: %s (%s)\n" % (end.ctime(), end - self.start))
|
||||
self.logfp.flush()
|
||||
self.logfp.close()
|
||||
self.logfp = None
|
||||
|
||||
def log(self, msg):
|
||||
""" Write to the log file, if any. """
|
||||
if not self.logfp:
|
||||
return
|
||||
self.logfp.write(msg)
|
||||
|
||||
def logdata(self, nbrs, mdrs, lsdbs, krs, zrs):
|
||||
""" Dump experiment parameters and data to the log file. """
|
||||
self.log("ospfmantetmdrtest data:")
|
||||
self.log("----- parameters -----")
|
||||
self.log("%s" % self.options)
|
||||
self.log("----- neighbors -----")
|
||||
for rtrid in sorted(nbrs.keys()):
|
||||
self.log("%s: %s" % (rtrid, nbrs[rtrid]))
|
||||
self.log("----- mdr levels -----")
|
||||
self.log(mdrs)
|
||||
self.log("----- link state databases -----")
|
||||
for rtrid in sorted(lsdbs.keys()):
|
||||
self.log("%s lsdb:" % rtrid)
|
||||
for line in lsdbs[rtrid].split("\n"):
|
||||
self.log(line)
|
||||
self.log("----- kernel routes -----")
|
||||
for rtrid in sorted(krs.keys()):
|
||||
msg = rtrid + ": "
|
||||
for rt in krs[rtrid]:
|
||||
msg += "%s" % rt
|
||||
self.log(msg)
|
||||
self.log("----- zebra routes -----")
|
||||
for rtrid in sorted(zrs.keys()):
|
||||
msg = rtrid + ": "
|
||||
for rt in zrs[rtrid]:
|
||||
msg += "%s" % rt
|
||||
self.log(msg)
|
||||
|
||||
def topology(self, numnodes, linkprob, verbose=False):
|
||||
""" Build a topology consisting of the given number of ManetNodes
|
||||
connected to a WLAN and probabilty of links and set
|
||||
the session, WLAN, and node list objects.
|
||||
"""
|
||||
# IP subnet
|
||||
prefix = ipaddress.Ipv4Prefix("10.14.0.0/16")
|
||||
self.session = Session(1)
|
||||
# emulated network
|
||||
self.net = self.session.create_node(cls=core.nodes.network.WlanNode)
|
||||
for i in range(1, numnodes + 1):
|
||||
addr = "%s/%s" % (prefix.addr(i), 32)
|
||||
tmp = self.session.create_node(
|
||||
cls=ManetNode, ipaddr=addr, _id="%d" % i, name="n%d" % i
|
||||
)
|
||||
tmp.newnetif(self.net, [addr])
|
||||
self.nodes.append(tmp)
|
||||
# connect nodes with probability linkprob
|
||||
for i in range(numnodes):
|
||||
for j in range(i + 1, numnodes):
|
||||
r = random.random()
|
||||
if r < linkprob:
|
||||
if self.verbose:
|
||||
self.info("linking (%d,%d)" % (i, j))
|
||||
self.net.link(self.nodes[i].netif(0), self.nodes[j].netif(0))
|
||||
# force one link to avoid partitions (should check if this is needed)
|
||||
j = i
|
||||
while j == i:
|
||||
j = random.randint(0, numnodes - 1)
|
||||
if self.verbose:
|
||||
self.info("linking (%d,%d)" % (i, j))
|
||||
self.net.link(self.nodes[i].netif(0), self.nodes[j].netif(0))
|
||||
self.nodes[i].boot()
|
||||
# run the boot.sh script on all nodes to start Quagga
|
||||
for i in range(numnodes):
|
||||
self.nodes[i].cmd(["./%s" % self.nodes[i].bootsh])
|
||||
|
||||
def compareroutes(self, node, kr, zr):
|
||||
""" Compare two lists of Route objects.
|
||||
"""
|
||||
kr.sort(key=Route.key)
|
||||
zr.sort(key=Route.key)
|
||||
if kr != zr:
|
||||
self.warn("kernel and zebra routes differ")
|
||||
if self.verbose:
|
||||
msg = "kernel: "
|
||||
for r in kr:
|
||||
msg += "%s " % r
|
||||
msg += "\nzebra: "
|
||||
for r in zr:
|
||||
msg += "%s " % r
|
||||
self.warn(msg)
|
||||
else:
|
||||
self.info(" kernel and zebra routes match")
|
||||
|
||||
def comparemdrlevels(self, nbrs, mdrs):
|
||||
""" Check that all routers form a connected dominating set, i.e. all
|
||||
routers are either MDR, BMDR, or adjacent to one.
|
||||
"""
|
||||
msg = "All routers form a CDS"
|
||||
for n in self.nodes:
|
||||
if mdrs[n.routerid] != "OTHER":
|
||||
continue
|
||||
connected = False
|
||||
for nbr in nbrs[n.routerid]:
|
||||
if mdrs[nbr] == "MDR" or mdrs[nbr] == "BMDR":
|
||||
connected = True
|
||||
break
|
||||
if not connected:
|
||||
msg = "All routers do not form a CDS"
|
||||
self.warn(
|
||||
"XXX %s: not in CDS; neighbors: %s" % (n.routerid, nbrs[n.routerid])
|
||||
)
|
||||
if self.verbose:
|
||||
self.info(msg)
|
||||
|
||||
def comparelsdbs(self, lsdbs):
|
||||
""" Check LSDBs for consistency.
|
||||
"""
|
||||
msg = "LSDBs of all routers are consistent"
|
||||
prev = self.nodes[0]
|
||||
for n in self.nodes:
|
||||
db = lsdbs[n.routerid]
|
||||
if lsdbs[prev.routerid] != db:
|
||||
msg = "LSDBs of all routers are not consistent"
|
||||
self.warn(
|
||||
"XXX LSDBs inconsistent for %s and %s" % (n.routerid, prev.routerid)
|
||||
)
|
||||
i = 0
|
||||
for entry in lsdbs[n.routerid].split("\n"):
|
||||
preventries = lsdbs[prev.routerid].split("\n")
|
||||
try:
|
||||
preventry = preventries[i]
|
||||
except IndexError:
|
||||
preventry = None
|
||||
if entry != preventry:
|
||||
self.warn("%s: %s" % (n.routerid, entry))
|
||||
self.warn("%s: %s" % (prev.routerid, preventry))
|
||||
i += 1
|
||||
prev = n
|
||||
if self.verbose:
|
||||
self.info(msg)
|
||||
|
||||
def checknodes(self):
|
||||
""" Check the neighbor state and routing tables of all nodes. """
|
||||
nbrs = {}
|
||||
mdrs = {}
|
||||
lsdbs = {}
|
||||
krs = {}
|
||||
zrs = {}
|
||||
v = self.verbose
|
||||
for n in self.nodes:
|
||||
self.info("checking %s" % n.name)
|
||||
nbrs[n.routerid] = Ospf6NeighState(n, verbose=v).run()
|
||||
krs[n.routerid] = KernelRoutes(n, verbose=v).run()
|
||||
zrs[n.routerid] = ZebraRoutes(n, verbose=v).run()
|
||||
self.compareroutes(n, krs[n.routerid], zrs[n.routerid])
|
||||
mdrs[n.routerid] = Ospf6MdrLevel(n, verbose=v).run()
|
||||
lsdbs[n.routerid] = Ospf6Database(n, verbose=v).run()
|
||||
self.comparemdrlevels(nbrs, mdrs)
|
||||
self.comparelsdbs(lsdbs)
|
||||
self.logdata(nbrs, mdrs, lsdbs, krs, zrs)
|
||||
|
||||
|
||||
class Cmd:
|
||||
""" Helper class for running a command on a node and parsing the result. """
|
||||
|
||||
args = ""
|
||||
|
||||
def __init__(self, node, verbose=False):
|
||||
""" Initialize with a CoreNode (LxcNode) """
|
||||
self.id = None
|
||||
self.stdin = None
|
||||
self.out = None
|
||||
self.node = node
|
||||
self.verbose = verbose
|
||||
|
||||
def info(self, msg):
|
||||
""" Utility method for writing output to stdout."""
|
||||
print(msg)
|
||||
sys.stdout.flush()
|
||||
|
||||
def warn(self, msg):
|
||||
""" Utility method for writing output to stderr. """
|
||||
sys.stderr.write("XXX %s:" % self.node.routerid, msg)
|
||||
sys.stderr.flush()
|
||||
|
||||
def run(self):
|
||||
""" This is the primary method used for running this command. """
|
||||
self.open()
|
||||
r = self.parse()
|
||||
self.cleanup()
|
||||
return r
|
||||
|
||||
def open(self):
|
||||
""" Exceute call to node.popen(). """
|
||||
self.id, self.stdin, self.out, self.err = self.node.client.popen(self.args)
|
||||
|
||||
def parse(self):
|
||||
""" This method is overloaded by child classes and should return some
|
||||
result.
|
||||
"""
|
||||
return None
|
||||
|
||||
def cleanup(self):
|
||||
""" Close the Popen channels."""
|
||||
self.stdin.close()
|
||||
self.out.close()
|
||||
self.err.close()
|
||||
tmp = self.id.wait()
|
||||
if tmp:
|
||||
self.warn("nonzero exit status:", tmp)
|
||||
|
||||
|
||||
class VtyshCmd(Cmd):
|
||||
""" Runs a vtysh command. """
|
||||
|
||||
def open(self):
|
||||
args = ("vtysh", "-c", self.args)
|
||||
self.id, self.stdin, self.out, self.err = self.node.client.popen(args)
|
||||
|
||||
|
||||
class Ospf6NeighState(VtyshCmd):
|
||||
""" Check a node for OSPFv3 neighbors in the full/two-way states. """
|
||||
|
||||
args = "show ipv6 ospf6 neighbor"
|
||||
|
||||
def parse(self):
|
||||
# skip first line
|
||||
self.out.readline()
|
||||
nbrlist = []
|
||||
for line in self.out:
|
||||
field = line.split()
|
||||
nbr = field[0]
|
||||
state = field[3].split("/")[0]
|
||||
if not state.lower() in ("full", "twoway"):
|
||||
self.warn("neighbor %s state: %s" % (nbr, state))
|
||||
nbrlist.append(nbr)
|
||||
|
||||
if len(nbrlist) == 0:
|
||||
self.warn("no neighbors")
|
||||
if self.verbose:
|
||||
self.info(" %s has %d neighbors" % (self.node.routerid, len(nbrlist)))
|
||||
return nbrlist
|
||||
|
||||
|
||||
class Ospf6MdrLevel(VtyshCmd):
|
||||
""" Retrieve the OSPFv3 MDR level for a node. """
|
||||
|
||||
args = "show ipv6 ospf6 mdrlevel"
|
||||
|
||||
def parse(self):
|
||||
line = self.out.readline()
|
||||
# TODO: handle multiple interfaces
|
||||
field = line.split()
|
||||
mdrlevel = field[4]
|
||||
if mdrlevel not in ("MDR", "BMDR", "OTHER"):
|
||||
self.warn("mdrlevel: %s" % mdrlevel)
|
||||
if self.verbose:
|
||||
self.info(" %s is %s" % (self.node.routerid, mdrlevel))
|
||||
return mdrlevel
|
||||
|
||||
|
||||
class Ospf6Database(VtyshCmd):
|
||||
""" Retrieve the OSPFv3 LSDB summary for a node. """
|
||||
|
||||
args = "show ipv6 ospf6 database"
|
||||
|
||||
def parse(self):
|
||||
db = ""
|
||||
for line in self.out:
|
||||
field = line.split()
|
||||
if len(field) < 8:
|
||||
continue
|
||||
# filter out Age and Duration columns
|
||||
filtered = field[:3] + field[4:7]
|
||||
db += " ".join(filtered) + "\n"
|
||||
return db
|
||||
|
||||
|
||||
class ZebraRoutes(VtyshCmd):
|
||||
""" Return a list of Route objects for a node based on its zebra
|
||||
routing table.
|
||||
"""
|
||||
|
||||
args = "show ip route"
|
||||
|
||||
def parse(self):
|
||||
for i in range(0, 3):
|
||||
# skip first three lines
|
||||
self.out.readline()
|
||||
r = []
|
||||
prefix = None
|
||||
for line in self.out:
|
||||
field = line.split()
|
||||
if len(field) < 1:
|
||||
continue
|
||||
# only use OSPFv3 selected FIB routes
|
||||
elif field[0][:2] == "o>":
|
||||
prefix = field[1]
|
||||
metric = field[2].split("/")[1][:-1]
|
||||
if field[0][2:] != "*":
|
||||
continue
|
||||
if field[3] == "via":
|
||||
gw = field[4][:-1]
|
||||
else:
|
||||
gw = field[6][:-1]
|
||||
r.append(Route(prefix, gw, metric))
|
||||
prefix = None
|
||||
elif prefix and field[0] == "*":
|
||||
# already have prefix and metric from previous line
|
||||
gw = field[2][:-1]
|
||||
r.append(Route(prefix, gw, metric))
|
||||
prefix = None
|
||||
|
||||
if len(r) == 0:
|
||||
self.warn("no zebra routes")
|
||||
if self.verbose:
|
||||
self.info(" %s has %d zebra routes" % (self.node.routerid, len(r)))
|
||||
return r
|
||||
|
||||
|
||||
class KernelRoutes(Cmd):
|
||||
""" Return a list of Route objects for a node based on its kernel
|
||||
routing table.
|
||||
"""
|
||||
|
||||
args = ("/sbin/ip", "route", "show")
|
||||
|
||||
def parse(self):
|
||||
r = []
|
||||
prefix = None
|
||||
for line in self.out:
|
||||
field = line.split()
|
||||
if field[0] == "nexthop":
|
||||
if not prefix:
|
||||
# this saves only the first nexthop entry if multiple exist
|
||||
continue
|
||||
else:
|
||||
prefix = field[0]
|
||||
metric = field[-1]
|
||||
tmp = prefix.split("/")
|
||||
if len(tmp) < 2:
|
||||
prefix += "/32"
|
||||
if field[1] == "proto":
|
||||
# nexthop entry is on the next line
|
||||
continue
|
||||
# nexthop IP or interface
|
||||
gw = field[2]
|
||||
r.append(Route(prefix, gw, metric))
|
||||
prefix = None
|
||||
|
||||
if len(r) == 0:
|
||||
self.warn("no kernel routes")
|
||||
if self.verbose:
|
||||
self.info(" %s has %d kernel routes" % (self.node.routerid, len(r)))
|
||||
return r
|
||||
|
||||
|
||||
def main():
|
||||
usagestr = "usage: %prog [-h] [options] [args]"
|
||||
parser = optparse.OptionParser(usage=usagestr)
|
||||
parser.set_defaults(numnodes=10, linkprob=0.35, delay=20, seed=None)
|
||||
|
||||
parser.add_option(
|
||||
"-n", "--numnodes", dest="numnodes", type=int, help="number of nodes"
|
||||
)
|
||||
parser.add_option(
|
||||
"-p", "--linkprob", dest="linkprob", type=float, help="link probabilty"
|
||||
)
|
||||
parser.add_option(
|
||||
"-d", "--delay", dest="delay", type=float, help="wait time before checking"
|
||||
)
|
||||
parser.add_option(
|
||||
"-s",
|
||||
"--seed",
|
||||
dest="seed",
|
||||
type=int,
|
||||
help="specify integer to use for random seed",
|
||||
)
|
||||
parser.add_option(
|
||||
"-v", "--verbose", dest="verbose", action="store_true", help="be more verbose"
|
||||
)
|
||||
parser.add_option(
|
||||
"-l",
|
||||
"--logfile",
|
||||
dest="logfile",
|
||||
type=str,
|
||||
help="log detailed output to the specified file",
|
||||
)
|
||||
|
||||
def usage(msg=None, err=0):
|
||||
sys.stdout.write("\n")
|
||||
if msg:
|
||||
sys.stdout.write(msg + "\n\n")
|
||||
parser.print_help()
|
||||
sys.exit(err)
|
||||
|
||||
# parse command line options
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.numnodes < 2:
|
||||
usage("invalid numnodes: %s" % options.numnodes)
|
||||
if options.linkprob <= 0.0 or options.linkprob > 1.0:
|
||||
usage("invalid linkprob: %s" % options.linkprob)
|
||||
if options.delay < 0.0:
|
||||
usage("invalid delay: %s" % options.delay)
|
||||
|
||||
for a in args:
|
||||
sys.stderr.write("ignoring command line argument: '%s'\n" % a)
|
||||
|
||||
if options.seed:
|
||||
random.seed(options.seed)
|
||||
|
||||
me = ManetExperiment(options=options, start=datetime.datetime.now())
|
||||
me.info(
|
||||
"creating topology: numnodes = %s; linkprob = %s"
|
||||
% (options.numnodes, options.linkprob)
|
||||
)
|
||||
me.topology(options.numnodes, options.linkprob)
|
||||
|
||||
me.info("waiting %s sec" % options.delay)
|
||||
time.sleep(options.delay)
|
||||
me.info("checking neighbor state and routes")
|
||||
me.checknodes()
|
||||
me.info("done")
|
||||
me.info("elapsed time: %s" % (datetime.datetime.now() - me.start))
|
||||
me.logend()
|
||||
|
||||
return me
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
me = main()
|
|
@ -1,50 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# (c)2010-2012 the Boeing Company
|
||||
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
# List and stop CORE sessions from the command line.
|
||||
#
|
||||
|
||||
import optparse
|
||||
import socket
|
||||
|
||||
from core.api.tlv import coreapi
|
||||
from core.emulator.enumerations import CORE_API_PORT, MessageFlags, SessionTlvs
|
||||
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser(usage="usage: %prog [-l] <sessionid>")
|
||||
parser.add_option(
|
||||
"-l", "--list", dest="list", action="store_true", help="list running sessions"
|
||||
)
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.list is True:
|
||||
num = "0"
|
||||
flags = MessageFlags.STRING.value
|
||||
else:
|
||||
num = args[0]
|
||||
flags = MessageFlags.DELETE.value
|
||||
tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, num)
|
||||
message = coreapi.CoreSessionMessage.pack(flags, tlvdata)
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect(("localhost", CORE_API_PORT))
|
||||
sock.send(message)
|
||||
|
||||
# receive and print a session list
|
||||
if options.list is True:
|
||||
hdr = sock.recv(coreapi.CoreMessage.header_len)
|
||||
msgtype, msgflags, msglen = coreapi.CoreMessage.unpack_header(hdr)
|
||||
data = ""
|
||||
if msglen:
|
||||
data = sock.recv(msglen)
|
||||
message = coreapi.CoreMessage(msgflags, hdr, data)
|
||||
sessions = message.get_tlv(coreapi.SessionTlvs.NUMBER.value)
|
||||
print("sessions: {}".format(sessions))
|
||||
|
||||
sock.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in a new issue