diff --git a/examples/tests/faces_test.py b/examples/demos_and_tests/faces_test.py similarity index 78% rename from examples/tests/faces_test.py rename to examples/demos_and_tests/faces_test.py index 0589441..c1b7a3f 100644 --- a/examples/tests/faces_test.py +++ b/examples/demos_and_tests/faces_test.py @@ -1,6 +1,6 @@ # -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */ # -# Copyright (C) 2015-2021, The University of Memphis, +# Copyright (C) 2015-2024, The University of Memphis, # Arizona Board of Regents, # Regents of the University of California. # @@ -73,8 +73,9 @@ def udp_run(): It can also be set manually as follows. The important bit to note here is the use of the Nfdc command """ - links = {"a":["b", "c"], "b":["c"]} + links = {"a": ["b", "c"], "b": ["c"]} nfdc_batches = dict() + info("Setting up routes and strategies...\n") for first in links: for second in links[first]: host1 = ndn.net[first] @@ -84,23 +85,24 @@ def udp_run(): Nfdc.createFace(host1, interface_ip) Nfdc.registerRoute(host1, PREFIX, interface_ip, cost=0) Nfdc.setStrategy(host1, PREFIX, Nfdc.STRATEGY_ASF) - sleep(1) - debug(ndn.net["a"].cmd("nfdc face list")) - debug(ndn.net["a"].cmd("nfdc fib list")) - debug(ndn.net["a"].cmd("nfdc strategy show /example")) + sleep(1) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) # Start ping server info("Starting pings...\n") - pingserver_log = open("{}/c/ndnpingserver.log".format(ndn.workDir), "w") - getPopen(ndn.net["c"], "ndnpingserver {}".format(PREFIX), stdout=pingserver_log,\ + pingserver_log = open(f"{ndn.workDir}/c/ndnpingserver.log", "w") + getPopen(ndn.net["c"], f"ndnpingserver {PREFIX}", stdout=pingserver_log,\ stderr=pingserver_log) # start ping client - ping1 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE) + ping1 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) ping1.wait() printOutput(ping1.stdout.read()) - links = {"a":["b", "c"], "b":["c"]} + info("Bringing down routes and strategies...\n") + links = {"a": ["b", "c"], "b": ["c"]} for first in links: for second in links[first]: host1 = ndn.net[first] @@ -111,11 +113,11 @@ def udp_run(): Nfdc.destroyFace(host1, interface_ip) Nfdc.unsetStrategy(host1, PREFIX) sleep(1) - debug(ndn.net["a"].cmd("nfdc face list")) - debug(ndn.net["a"].cmd("nfdc fib list")) - debug(ndn.net["a"].cmd("nfdc strategy show /example")) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) - ping2 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE) + ping2 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) ping2.wait() printOutput(ping2.stdout.read()) @@ -153,7 +155,8 @@ def eth_run(): It can also be set manually as follows. The important bit to note here is the use of the Nfdc command """ - links = {"a":["b", "c"], "b":["c"]} + info("Setting up routes and strategies...\n") + links = {"a": ["b", "c"], "b": ["c"]} nfdc_batches = dict() for first in links: for second in links[first]: @@ -165,22 +168,24 @@ def eth_run(): Nfdc.createFace(host1, interface_addr, protocol=Nfdc.PROTOCOL_ETHER, localInterface=sender_interface) Nfdc.registerRoute(host1, PREFIX, interface_addr, cost=0, protocol=Nfdc.PROTOCOL_ETHER) Nfdc.setStrategy(host1, PREFIX, Nfdc.STRATEGY_ASF) - sleep(1) - debug(ndn.net["a"].cmd("nfdc face list")) - debug(ndn.net["a"].cmd("nfdc fib list")) - debug(ndn.net["a"].cmd("nfdc strategy show /example")) + sleep(1) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) # Start ping server info("Starting pings...\n") - pingserver_log = open("{}/c/ndnpingserver.log".format(ndn.workDir), "w") - getPopen(ndn.net["c"], "ndnpingserver {}".format(PREFIX), stdout=pingserver_log,\ + pingserver_log = open(f"{ndn.workDir}/c/ndnpingserver.log", "w") + getPopen(ndn.net["c"], f"ndnpingserver {PREFIX}", stdout=pingserver_log,\ stderr=pingserver_log) # start ping client - ping1 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE) + ping1 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) ping1.wait() printOutput(ping1.stdout.read()) + info("Bringing down routes and strategies...\n") + links = {"a":["b", "c"], "b":["c"]} for first in links: for second in links[first]: @@ -192,11 +197,11 @@ def eth_run(): Nfdc.destroyFace(host1, interface_addr, protocol=Nfdc.PROTOCOL_ETHER) Nfdc.unsetStrategy(host1, PREFIX) sleep(1) - debug(ndn.net["a"].cmd("nfdc face list")) - debug(ndn.net["a"].cmd("nfdc fib list")) - debug(ndn.net["a"].cmd("nfdc strategy show /example")) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) - ping2 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE) + ping2 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) ping2.wait() printOutput(ping2.stdout.read()) @@ -234,6 +239,10 @@ def udp_nlsr_run(): Experiment.startPctPings(ndn.net, 60) sleep(70) + + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) ndn.stop() @@ -267,6 +276,10 @@ def eth_nlsr_run(): Experiment.startPctPings(ndn.net, 60) sleep(70) + + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) ndn.stop() @@ -311,18 +324,18 @@ def udp_static_run(): info('Route addition to NFD completed succesfully\n') - debug(ndn.net["a"].cmd("nfdc face list")) - debug(ndn.net["a"].cmd("nfdc fib list")) - debug(ndn.net["a"].cmd("nfdc strategy show /example")) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) # Start ping server info("Starting pings...\n") - pingserver_log = open("{}/c/ndnpingserver.log".format(ndn.workDir), "w") - getPopen(ndn.net["c"], "ndnpingserver {}".format(PREFIX), stdout=pingserver_log,\ + pingserver_log = open(f"{ndn.workDir}/c/ndnpingserver.log", "w") + getPopen(ndn.net["c"], f"ndnpingserver {PREFIX}", stdout=pingserver_log,\ stderr=pingserver_log) # start ping client - ping1 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE) + ping1 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) ping1.wait() printOutput(ping1.stdout.read()) @@ -369,28 +382,34 @@ def eth_static_run(): info('Route addition to NFD completed succesfully\n') - debug(ndn.net["a"].cmd("nfdc face list")) - debug(ndn.net["a"].cmd("nfdc fib list")) - debug(ndn.net["a"].cmd("nfdc strategy show /example")) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) # Start ping server info("Starting pings...\n") - pingserver_log = open("{}/c/ndnpingserver.log".format(ndn.workDir), "w") - getPopen(ndn.net["c"], "ndnpingserver {}".format(PREFIX), stdout=pingserver_log,\ + pingserver_log = open(f"{ndn.workDir}/c/ndnpingserver.log", "w") + getPopen(ndn.net["c"], f"ndnpingserver {PREFIX}", stdout=pingserver_log,\ stderr=pingserver_log) # start ping client - ping1 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE) + ping1 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) ping1.wait() printOutput(ping1.stdout.read()) ndn.stop() if __name__ == '__main__': - setLogLevel("debug") + setLogLevel("info") + info("\n\nUDP FACES\n") udp_run() + info("\n\nETHERNET FACES\n") eth_run() + info("\n\nNLSR WITH UDP FACES\n") udp_nlsr_run() + info("\n\nNLSR WITH ETHERNET FACES\n") eth_nlsr_run() + info("\n\nSTATIC ROUTING HELPER WITH UDP FACES\n") udp_static_run() + info("\n\nSTATIC ROUTING HELPER WITH ETHERNET FACES\n") eth_static_run() \ No newline at end of file diff --git a/examples/demos_and_tests/nfdc_batch_example.py b/examples/demos_and_tests/nfdc_batch_example.py new file mode 100644 index 0000000..ea002cb --- /dev/null +++ b/examples/demos_and_tests/nfdc_batch_example.py @@ -0,0 +1,131 @@ +# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */ +# +# Copyright (C) 2015-2024, The University of Memphis, +# Arizona Board of Regents, +# Regents of the University of California. +# +# This file is part of Mini-NDN. +# See AUTHORS.md for a complete list of Mini-NDN authors and contributors. +# +# Mini-NDN is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Mini-NDN is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Mini-NDN, e.g., in COPYING.md file. +# If not, see . + +from subprocess import PIPE +from time import sleep + +from mininet.log import setLogLevel, info, debug +from mininet.topo import Topo + +from minindn.minindn import Minindn +from minindn.apps.app_manager import AppManager +from minindn.util import MiniNDNCLI, getPopen +from minindn.apps.nfd import Nfd +from minindn.helpers.nfdc import Nfdc, NfdcBatch + +PREFIX = "/example" + +def printOutput(output): + _out = output.decode("utf-8").split("\n") + for _line in _out: + info(_line + "\n") + +def run(): + Minindn.cleanUp() + Minindn.verifyDependencies() + + # Topology can be created/modified using Mininet topo object + topo = Topo() + info("Setup\n") + # add hosts + a = topo.addHost('a') + b = topo.addHost('b') + c = topo.addHost('c') + + # add links + topo.addLink(a, b, delay='10ms', bw=10) # bw = bandwidth + topo.addLink(b, c, delay='10ms', bw=10) + topo.addLink(a, c, delay='10ms', bw=10) + + ndn = Minindn(topo=topo) + ndn.start() + + # configure and start nfd on each node + info("Configuring NFD\n") + AppManager(ndn, ndn.net.hosts, Nfd, logLevel="DEBUG") + + info("Setting up routes and strategies...\n") + links = {"a": ["b", "c"], "b": ["c"]} + nfdc_batches = dict() + for first in links: + nfdc_batches[first] = NfdcBatch() + batch = nfdc_batches[first] + for second in links[first]: + host1 = ndn.net[first] + host2 = ndn.net[second] + interface = host2.connectionsTo(host1)[0][0] + interface_ip = interface.IP() + # Nfdc.createFace(host1, interface_ip) + batch.createFace(interface_ip) + batch.registerRoute(PREFIX, interface_ip, cost=0) + batch.setStrategy(PREFIX, Nfdc.STRATEGY_ASF) + for node in nfdc_batches: + nfdc_batches[node].executeBatch(ndn.net[node]) + sleep(1) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) + + # Start ping server + info("Starting pings...\n") + pingserver_log = open(f"{ndn.workDir}/c/ndnpingserver.log", "w") + getPopen(ndn.net["c"], f"ndnpingserver {PREFIX}", stdout=pingserver_log, + stderr=pingserver_log) + + # start ping client + ping1 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) + ping1.wait() + printOutput(ping1.stdout.read()) + + info("Bringing down routes and strategies...\n") + links = {"a": ["b", "c"], "b": ["c"]} + nfdc_batches = dict() + for first in links: + nfdc_batches[first] = NfdcBatch() + batch = nfdc_batches[first] + for second in links[first]: + host1 = ndn.net[first] + host2 = ndn.net[second] + interface = host2.connectionsTo(host1)[0][0] + interface_ip = interface.IP() + batch.unregisterRoute(PREFIX, interface_ip) + batch.destroyFace(interface_ip) + batch.unsetStrategy(PREFIX) + for node in nfdc_batches: + nfdc_batches[node].executeBatch(ndn.net[node]) + sleep(1) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) + + ping2 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE) + ping2.wait() + printOutput(ping2.stdout.read()) + + info("\nExperiment Completed!\n") + # MiniNDNCLI(ndn.net) + ndn.stop() + +if __name__ == '__main__': + setLogLevel("info") + run() \ No newline at end of file diff --git a/examples/demos_and_tests/nfdc_example.py b/examples/demos_and_tests/nfdc_example.py new file mode 100644 index 0000000..baf1a45 --- /dev/null +++ b/examples/demos_and_tests/nfdc_example.py @@ -0,0 +1,119 @@ +# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */ +# +# Copyright (C) 2015-2024, The University of Memphis, +# Arizona Board of Regents, +# Regents of the University of California. +# +# This file is part of Mini-NDN. +# See AUTHORS.md for a complete list of Mini-NDN authors and contributors. +# +# Mini-NDN is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Mini-NDN is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Mini-NDN, e.g., in COPYING.md file. +# If not, see . + +from subprocess import PIPE +from time import sleep + +from mininet.log import setLogLevel, info, debug +from mininet.topo import Topo + +from minindn.minindn import Minindn +from minindn.apps.app_manager import AppManager +from minindn.util import MiniNDNCLI, getPopen +from minindn.apps.nfd import Nfd +from minindn.helpers.nfdc import Nfdc, NfdcBatch + +PREFIX = "/example" + +def printOutput(output): + _out = output.decode("utf-8").split("\n") + for _line in _out: + info(_line + "\n") + +def run(): + Minindn.cleanUp() + Minindn.verifyDependencies() + + # Topology can be created/modified using Mininet topo object + topo = Topo() + info("Setup\n") + # add hosts + a = topo.addHost('a') + b = topo.addHost('b') + c = topo.addHost('c') + + # add links + topo.addLink(a, b, delay='10ms', bw=10) # bw = bandwidth + topo.addLink(b, c, delay='10ms', bw=10) + topo.addLink(a, c, delay='10ms', bw=10) + + ndn = Minindn(topo=topo) + ndn.start() + + # configure and start nfd on each node + info("Configuring NFD\n") + AppManager(ndn, ndn.net.hosts, Nfd, logLevel="DEBUG") + + info("Setting up routes and strategies...\n") + links = {"a": ["b", "c"], "b": ["c"]} + for first in links: + for second in links[first]: + host1 = ndn.net[first] + host2 = ndn.net[second] + interface = host2.connectionsTo(host1)[0][0] + interface_ip = interface.IP() + # Nfdc.createFace(host1, interface_ip) + Nfdc.createFace(host1, interface_ip) + Nfdc.registerRoute(host1, PREFIX, interface_ip, cost=0) + Nfdc.setStrategy(host1, PREFIX, Nfdc.STRATEGY_ASF) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) + + # Start ping server + info("Starting pings...\n") + pingserver_log = open(f"{ndn.workDir}/c/ndnpingserver.log", "w") + getPopen(ndn.net["c"], f"ndnpingserver {PREFIX}", stdout=pingserver_log, + stderr=pingserver_log) + + # start ping client + ping1 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) + ping1.wait() + printOutput(ping1.stdout.read()) + + info("Bringing down routes and strategies...\n") + links = {"a": ["b", "c"], "b": ["c"]} + for first in links: + for second in links[first]: + host1 = ndn.net[first] + host2 = ndn.net[second] + interface = host2.connectionsTo(host1)[0][0] + interface_ip = interface.IP() + Nfdc.unregisterRoute(host1, PREFIX, interface_ip) + Nfdc.destroyFace(host1, interface_ip) + Nfdc.unsetStrategy(host1, PREFIX) + info(ndn.net["a"].cmd("nfdc face list")) + info(ndn.net["a"].cmd("nfdc fib list")) + info(ndn.net["a"].cmd("nfdc strategy show /example")) + + ping2 = getPopen(ndn.net["a"], f"ndnping {PREFIX} -c 5", stdout=PIPE, stderr=PIPE) + ping2.wait() + printOutput(ping2.stdout.read()) + + info("\nExperiment Completed!\n") + # MiniNDNCLI(ndn.net) + ndn.stop() + +if __name__ == '__main__': + setLogLevel("info") + run() \ No newline at end of file diff --git a/minindn/helpers/nfdc.py b/minindn/helpers/nfdc.py index 08aeccf..9aa38f4 100644 --- a/minindn/helpers/nfdc.py +++ b/minindn/helpers/nfdc.py @@ -23,126 +23,144 @@ from mininet.log import debug, warn from minindn.minindn import Minindn -from minindn.util import MACToEther +from minindn.util import MACToEther, getPopen -# If needed (e.g. to speed up the process), use a smaller (or larger value) +from subprocess import PIPE + +# If needed (e.g. to speed up the process), use a smaller (or larger value) # based on your machines resource (CPU, memory) SLEEP_TIME = 0.0015 -class Nfdc(object): +class _NfdcBase(object): STRATEGY_ASF = 'asf' STRATEGY_BEST_ROUTE = 'best-route' STRATEGY_MULTICAST = 'multicast' - STRATEGY_NCC = 'ncc' PROTOCOL_UDP = 'udp' PROTOCOL_TCP = 'tcp' PROTOCOL_ETHER = 'ether' +def _registerRoute(namePrefix, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP, origin=255, + cost=0, inheritFlag=True, captureFlag=False, expirationInMillis=None): + cmd = "" + if remoteNode.isdigit() and not protocol == "fd": + cmd = f'route add {namePrefix} {remoteNode} origin {origin} cost {cost}' + else: + if protocol == "ether": + remoteNode = MACToEther(remoteNode) + cmd = f'route add {namePrefix} {protocol}://{remoteNode} origin {origin} cost {cost}' + if not inheritFlag: + cmd += " no-inherit" + if captureFlag: + cmd += " capture" + if expirationInMillis: + cmd += f" expires {expirationInMillis}" + return cmd + +def _unregisterRoute(namePrefix, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP, origin=255): + cmd = "" + if remoteNode.isdigit() and not protocol == "fd": + cmd = f'route remove {namePrefix} {remoteNode} origin {origin}' + else: + if protocol == "ether": + remoteNode = MACToEther(remoteNode) + cmd = f'route remove {namePrefix} {protocol}://{remoteNode} origin {origin}' + return cmd + +def _createFace(remoteNodeAddress, protocol=_NfdcBase.PROTOCOL_UDP, isPermanent=False, localInterface=''): + '''Create face in node's NFD instance. Returns FaceID of created face or -1 if failed.''' + if protocol == "ether" and not localInterface: + warn("Cannot create ethernet face without local interface!") + return + elif protocol != "ether" and localInterface: + warn("Cannot create non-ethernet face with local interface specified!") + return + elif protocol == "ether" and localInterface: + remoteNodeAddress = MACToEther(remoteNodeAddress) + cmd = (f'face create {protocol}://{remoteNodeAddress} ' + f'{f"local dev://{localInterface} " if localInterface else ""}' + f'{"persistency permanent" if isPermanent else "persistency persistent"}') + return cmd + +def _destroyFace(remoteNode, protocol=_NfdcBase.PROTOCOL_UDP): + cmd = "" + if remoteNode.isdigit() and not protocol == "fd": + cmd = f'face destroy {remoteNode}' + else: + if protocol == "ether": + remoteNode = MACToEther(remoteNode) + cmd = f'face destroy {protocol}://{remoteNode}' + return cmd + +def _setStrategy(namePrefix, strategy): + cmd = f'strategy set {namePrefix} ndn:/localhost/nfd/strategy/{strategy}' + return cmd + +def _unsetStrategy(namePrefix): + cmd = f'strategy unset {namePrefix}' + return cmd + +class Nfdc(_NfdcBase): @staticmethod - def registerRoute(node, namePrefix, remoteNode, protocol=PROTOCOL_UDP, origin=255, + def registerRoute(node, namePrefix, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP, origin=255, cost=0, inheritFlag=True, captureFlag=False, expirationInMillis=None): - cmd = "" - if remoteNode.isdigit() and not protocol == "fd": - cmd = ('nfdc route add {} {} origin {} cost {} {}{}{}').format( - namePrefix, - remoteNode, - origin, - cost, - 'no-inherit ' if not inheritFlag else '', - 'capture ' if captureFlag else '', - 'expires {}'.format(expirationInMillis) if expirationInMillis else '' - ) - else: - if protocol == "ether": - remoteNode = MACToEther(remoteNode) - cmd = ('nfdc route add {} {}://{} origin {} cost {} {}{}{}').format( - namePrefix, - protocol, - remoteNode, - origin, - cost, - 'no-inherit ' if not inheritFlag else '', - 'capture ' if captureFlag else '', - 'expires {}'.format(expirationInMillis) if expirationInMillis else '' - ) + cmd = "nfdc " + _registerRoute(namePrefix, remoteNode, protocol, origin, cost, inheritFlag, captureFlag, expirationInMillis) debug(node.cmd(cmd)) Minindn.sleep(SLEEP_TIME) @staticmethod - def unregisterRoute(node, namePrefix, remoteNode, protocol=PROTOCOL_UDP, origin=255): - cmd = "" - if remoteNode.isdigit() and not protocol == "fd": - cmd = 'nfdc route remove {} {} origin {}'.format(namePrefix, remoteNode, origin) - else: - if protocol == "ether": - remoteNode = MACToEther(remoteNode) - cmd = 'nfdc route remove {} {}://{} origin {}'.format(namePrefix, protocol, remoteNode, origin) + def unregisterRoute(node, namePrefix, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP, origin=255): + cmd = "nfdc " + _unregisterRoute(namePrefix, remoteNode, protocol, origin) debug(node.cmd(cmd)) Minindn.sleep(SLEEP_TIME) @staticmethod - def createFace(node, remoteNodeAddress, protocol=PROTOCOL_UDP, isPermanent=False, localInterface='', allowExisting=True): + def createFace(node, remoteNodeAddress, protocol=_NfdcBase.PROTOCOL_UDP, isPermanent=False, localInterface='', allowExisting=True): '''Create face in node's NFD instance. Returns FaceID of created face or -1 if failed.''' - if protocol == "ether" and not localInterface: - warn("Cannot create ethernet face without local interface!") - return - elif protocol != "ether" and localInterface: - warn("Cannot create non-ethernet face with local interface specified!") - return - elif protocol == "ether" and localInterface: - remoteNodeAddress = MACToEther(remoteNodeAddress) - cmd = ('nfdc face create {}://{} {}{}'.format( - protocol, - remoteNodeAddress, - 'local dev://{} '.format(localInterface) if localInterface else '', - 'persistency permanent' if isPermanent else 'persistency persistent' - )) + cmd = "nfdc " + _createFace(remoteNodeAddress, protocol, isPermanent, localInterface) output = node.cmd(cmd) debug(output) Minindn.sleep(SLEEP_TIME) if "face-created" in output or (allowExisting and ("face-exists" in output or "face-updated" in output)): faceID = output.split(" ")[1][3:] if "face-exists" in output or "face-updated" in output: - debug("[{}] Existing face found: {}\n".format(node.name, faceID)) + debug(f'[{node.name}] Existing face found: {faceID}\n') return faceID - warn("[{}] Face register failed: {}\n".format(node.name, output)) + warn(f'[{node.name}] Face register failed: {output}\n') return -1 @staticmethod - def destroyFace(node, remoteNode, protocol=PROTOCOL_UDP): - if remoteNode.isdigit() and not protocol == "fd": - debug(node.cmd('nfdc face destroy {}'.format(remoteNode))) - else: - if protocol == "ether": - remoteNode = MACToEther(remoteNode) - debug(node.cmd('nfdc face destroy {}://{}'.format(protocol, remoteNode))) + def destroyFace(node, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP): + cmd = "nfdc " + _destroyFace(remoteNode, protocol) + debug(node.cmd(cmd)) Minindn.sleep(SLEEP_TIME) @staticmethod def setStrategy(node, namePrefix, strategy): - cmd = 'nfdc strategy set {} ndn:/localhost/nfd/strategy/{}'.format(namePrefix, strategy) + cmd = "nfdc " + _setStrategy(namePrefix, strategy) out = node.cmd(cmd) if out.find('error') != -1: - warn("[" + node.name + "] Error on strategy set out: " + out) + warn(f'[{node.name}] Error on strategy set out: {out}') + debug(out) Minindn.sleep(SLEEP_TIME) @staticmethod def unsetStrategy(node, namePrefix): - debug(node.cmd("nfdc strategy unset {}".format(namePrefix))) + cmd = "nfdc " + _unsetStrategy(namePrefix) + debug(node.cmd(cmd)) Minindn.sleep(SLEEP_TIME) @staticmethod - def getFaceId(node, remoteNodeAddress, localEndpoint=None, protocol=PROTOCOL_UDP, portNum="6363"): + def getFaceId(node, remoteNodeAddress, localEndpoint=None, protocol=_NfdcBase.PROTOCOL_UDP, portNum="6363"): '''Returns the faceId for a remote node based on FaceURI, or -1 if a face is not found''' - #Should this be cached or is the hit not worth it? + # Because this is an interactive helper method, we don't split this into _NfdcBase. local = "" if localEndpoint: - local = " local {}".format(localEndpoint) + local = f' local {localEndpoint}' if protocol == "ether": remoteNodeAddress = MACToEther(remoteNodeAddress) - output = node.cmd("nfdc face list remote {}://{}{}".format(protocol, remoteNodeAddress, local)) + output = node.cmd(f'nfdc face list remote {protocol}://{remoteNodeAddress}{local}') else: - output = node.cmd("nfdc face list remote {}://{}:{}{}".format(protocol, remoteNodeAddress, portNum, local)) + output = node.cmd(f'nfdc face list remote {protocol}://{remoteNodeAddress}:{portNum}{local}') debug(output) Minindn.sleep(SLEEP_TIME) # This is fragile but we don't have that many better options @@ -150,3 +168,43 @@ def getFaceId(node, remoteNodeAddress, localEndpoint=None, protocol=PROTOCOL_UDP return -1 faceId = output.split(" ")[0][7:] return faceId + +class NfdcBatch(_NfdcBase): + '''Helper for writing and passing an Nfdc batch file to Nfd''' + def __init__(self): + self.batch_commands = [] + + def executeBatch(self, node, batch_file_name = None): + '''Execute batch file on node given as argument. + Optional: batch_file_name is the name of the file that will be created in the node's home dir.''' + # The intended use of this method is to either use it for a universal configuration or to use an + # individual object for each node. + if batch_file_name == None: + batch_file_name = "nfdc_helper.batch" + batch_str = "\n".join(self.batch_commands) + file_path = f'{node.params["params"]["homeDir"]}/{batch_file_name}' + with open(file_path, "w") as f: + f.write(batch_str) + process = getPopen(node, f'nfdc --batch {file_path}') + # End user can poll if process has finished if desirable; this is also why we do not clean up the + # temporary files. + return process + + def registerRoute(self, namePrefix, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP, origin=255, + cost=0, inheritFlag=True, captureFlag=False, expirationInMillis=None): + self.batch_commands.append(_registerRoute(namePrefix, remoteNode, protocol, origin, cost, inheritFlag, captureFlag, expirationInMillis)) + + def unregisterRoute(self, namePrefix, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP, origin=255): + self.batch_commands.append(_unregisterRoute(namePrefix, remoteNode, protocol, origin)) + + def createFace(self, remoteNodeAddress, protocol=_NfdcBase.PROTOCOL_UDP, isPermanent=False, localInterface=''): + self.batch_commands.append(_createFace(remoteNodeAddress, protocol, isPermanent, localInterface)) + + def destroyFace(self, remoteNode, protocol=_NfdcBase.PROTOCOL_UDP): + self.batch_commands.append(_destroyFace(remoteNode, protocol)) + + def setStrategy(self, namePrefix, strategy): + self.batch_commands.append(_setStrategy(namePrefix, strategy)) + + def unsetStrategy(self, namePrefix): + self.batch_commands.append(_unsetStrategy(namePrefix)) \ No newline at end of file