Compare commits

..

190 Commits

Author SHA1 Message Date
baihe@pku.edu.cn 964d7c6ed9 feat(qsccp): Add qsccp scenario 2023-12-22 14:01:24 +00:00
suraviregmi 9665f5c9c1 update ndnsec commands
Change-Id: Ib802fd40d53e0405b9707e76dec4f2a92f9affc5
2023-11-09 20:05:26 +00:00
awlane af975e5ed5 Update dummy keychain patch to avoid potential segfaults
Under certain circumstances, use of the dummy keychain patch can cause fairly
frequent segfaults when NFD creates UDP multicast faces. These appear to have
been due to issues with using using function-local static variables in a way that
was not thread safe. After some collaboration with Alex Afanasyev regarding finding
a cause, we landed on this fix which adjusts the offending code.

Co-Authored-By: Alex Afanasyev <aa@cs.fiu.edu>
Change-Id: Iadb812cb8a3d87b83421b7fa109dd539f0c7065f
2023-10-09 17:43:55 +00:00
Davide Pesavento 273e80f1fe ci: update all actions to the latest version
Change-Id: Ib799183ea5d613b784f275213b4b2f0f97b80cb8
2023-09-20 23:28:11 -04:00
Varun Patil aed282d565 app: allow using list for command
This allows spaces in arguments

Change-Id: Icb71157eba43488028ea4f207e8009d0201c87c7
2023-09-06 15:10:33 -07:00
awlane 92bc429fe1 Add boolean parameter to NDNRoutingHelper constructor to allow for creating permanent faces.
Refs #5264

Change-Id: I6da3e777261ec978c8cff7da4d10f9661371dacf
2023-07-27 02:29:07 +00:00
awlane cb8c911f41 Allow float value for bw parameter in topology for non-integer values in megabits.
Refs #5263

Change-Id: I1c58129a474b3ec7362419c3a76863079b648b57
2023-07-24 22:55:28 +00:00
awlane 2e7b584ab5 Update dummy keychain patch for v2 namespace change
Change-Id: I8559c33fa8b02d0144b3e23c6c2d4033059e02d4
2023-06-27 08:02:20 -05:00
tylerliu 86647794f8 performance improvements
Change-Id: Ic8aaa0728a43936cd4c6e1ed590e01ba8f0fbf5a
2023-03-14 17:38:26 -07:00
dhensley6691 edd777fdfc Add an argument returnConvergenceInfo to checkConvergence which returns detailed information when convergence fails.
Adds returnConvergenceInfo as an argument to checkConvergence which returns a dictionary of nodes detailing which prefixes were missing from each node. Argument defaults to false to ensure backwards compatibility with pre-existing experiment code.

Refs: #5236
Change-Id: Ia690d50b42f849deee755098248e91a428b8af19
2022-12-13 17:22:36 +00:00
Dylan Hensley dc05e3ce90 docs: Fix broken links in README.md
The links in README.md pointed to an outdated link for the contributor guide and to AUTHORS.md instead of AUTHORS.rst

Refs: #5235
Change-Id: I380127d607b52773cc2d4c3020c9ac9950fe6f44
2022-11-20 19:25:06 -08:00
Varun Patil 047b92cf30 docker: use source install and prune image
Using source over PPA seems appropriate since MiniNDN is
used primarily for experimentation.

Other fixes:
* Let MiniNDN install mininet.
* Switch to Ubuntu 22.04
* Fix incorrect pruning of layers

Change-Id: Id5e52756929fbe3a40597c738ca81989ffb2c075
Signed-off-by: Varun Patil <varunpatil@ucla.edu>
2022-10-31 09:21:31 -07:00
Varun Patil aad8dbea87 docker: add GitHub build and push workflow
Change-Id: Ic600e91129ad81f3a41d4cc9fd9b1d45d44351c3
Signed-off-by: Varun Patil <varunpatil@ucla.edu>
2022-10-14 17:12:29 -07:00
Junxiao Shi 1e720875d2 install: fix git error and support Ubuntu 22.04
refs #5204

Change-Id: Ic6e2ce789746a18cdb8b97e5a4e8175a89ad2e8d
2022-08-01 14:53:33 -07:00
Varun Patil 63a330d317 Add static routes to NFDs in parallel
This allows setting up static routing in large
topologies in a reasonable time. Some timer values
are also reduced, seems to work fine to me

Change-Id: I112cfd216615a100db6dc18182db40ba614d83e6
2022-07-28 14:29:12 -07:00
awlane d8e6b8e508 Create helper methods for specifying face creation via topology
and changes to enable users to run NLSR in Mini-NDN-Wifi.

Refs: #5232
Change-Id: Iac8bd170f34985aa2b7ee080033a6ceaf334bd0c
2022-07-20 14:50:26 -05:00
Varun Patil c69041f603 Allow existing faces in createFace
Change-Id: I48c09c34a81822c25cbab25bff979194829e067f
2022-06-27 20:18:48 -07:00
Varun Patil 97a347fb3a Fix and move Dockerfile to this repository
Change-Id: I07039719c82d3a727b108f7875f231cd6b79493d
2022-05-24 14:33:51 -07:00
awlane 3e95ee8bd7 Fix for dummy keychain patch for ndn-cxx 8e2a6
Change-Id: I94c4e94ba70bafba8f410b4aee748529d75826d6
2022-05-23 16:24:26 -05:00
awlane a169f5702e Allow specification of working directory via constructor argument and related cleanup
Change-Id: Ifc73371c920d1d4e47b1fa04e57de5aebd2a6b40
2022-04-22 12:54:33 -08:00
awlane c32a07be3e Fix broken checks for presence of dummy keychain due to type mismatch
Refs #5200

Change-Id: I848c979c414cb802fe09359efda96c7dd29aa73d
2022-04-19 11:55:11 -08:00
awlane 49e43c39cd Update ndn-cxx dummy keychain patch for API changes
Change-Id: Ib57923ebcf1b5b00513ed50907629acfd1b56f60
2022-03-22 17:03:28 -05:00
dulalsaurab 90faa588cc Prepare 0.6.0 release
Change-Id: I3475f8a5929e0d0672f89aa0a51c25c3880fb03f
2021-12-27 18:02:05 -08:00
Alex Lane 1d3c0a8ac5 Add Nfdc functionality to enable working with FaceID rather than FaceURI exclusively
refs: #5130

Change-Id: I1b7ca1846cafdde8e959663ba53d5bd50b455b39
2021-12-19 04:23:00 +00:00
dulalsaurab 2085544799 examples: adding some basic examples
* consumer/producer
 * ndnping
 * traffic generator
 * catchunks/putchunks

Change-Id: Ie4c37f08f29a945f2fb1ce0b4d36da1bfb3edd3b
2021-12-17 09:11:56 -08:00
dulalsaurab 8c8e633d26 container: pre-built Vagrant box and docker container
Change-Id: Id49a6426f52fd3e22a94fee4607b7e2a6d0a7454
2021-12-17 01:12:03 +00:00
Junxiao Shi 48ada89a8a install: rewrite install script
* set dependency versions: PPA, git repository & commit
* separate download and build+install steps
* don't reinstall package if it's already installed

refs #4630

Change-Id: I966fac5e1633cbabf78ce20cd151a35618efc345
2021-11-04 09:02:21 -06:00
dulalsaurab 578f2ec695 Examples: incorporate latest change of NDNPing Class
Change-Id: I01d59de621992a87c082074766dc18e9a7b549a2
2021-06-17 08:58:02 -07:00
Saurab Dulal b428660d54 Revert "simple topology files with no additional parameters"
This reverts commit eef6ee890e.

Reason for revert: Topologies (http://minindn.memphis.edu/experiment.html#configuration) with no
additional parameter (e.g. hyperbolic coordinates) can't be processed by the existing script.
processTopo assumes that additional parameters exist which is not always true.

Change-Id: I8532b399de2c6f8b2a11823711b7637758dab630
2021-06-16 23:58:20 +00:00
Philipp Moll f53ab47678 ndn_routing_helper: Show status of route calculation
Change-Id: Ib38cedfed57bc8fe1397526c3d05bac6c3d80c93
2021-06-08 12:23:04 +02:00
Alex Lane 407c5f0ef3 Allow for creation of net object without topology and mixed topology fixes
refs: #5160, #5162

Change-Id: I54c2be3a9b4ee152057a8c4f1b52c9abd7b1a2a1
2021-05-14 14:48:59 -05:00
dulalsaurab 0ed7772f3f Bug fix on ndnpingclient and experiment script
Mininet host object is passed as a prefix from experiment
to ndnpingclient, string replacement operation on the
prefix fails at the client which crashes the Mini-NDN

Change-Id: I36c1f9e2e455321d8c650fd9711088b7e5ef2b22
2021-05-13 20:16:42 +00:00
Chad Cothran eef6ee890e simple topology files with no additional parameters
Change-Id: Ie121994596424249b969bb3af94c81d768fb0fc4
2021-03-26 11:15:27 -08:00
Alexander Lane ea2d5d6802 Add wireless simulation to redesigned Mini-NDN using Mininet-wifi.
refs: #4858

Change-Id: If9f7dd069203309c998ab2ff570a6cc8ee362434
2020-10-08 15:01:18 -05:00
Alex Lane 5dbf99dd78 Hotfix for broken code artifact in install.sh
Change-Id: I3296bff4b8e095f334958d1734f15c42f03c7105
2020-10-01 17:10:48 -05:00
Saurab Dulal 576a419ef2 Prepare 0.5.0 release
Small fix to properly handle ndnsec identity check message and also update copyright years in several files.

Change-Id: I1fae8749f7d755f4af1ccca519c236480ff3f824
2020-09-16 16:35:36 +00:00
Alex Lane 587b78ff64 Add a script to generate up-to-date NDN testbed topologies for Mini-NDN
Change-Id: I9686c65fe2f38fbc980c5fb54d876ebb3d9e7ede
2020-09-14 16:05:48 -05:00
Italo Valcy ccd85b1cf1 Change workDir and resultDir to be class attribute
Change-Id: Ia52c273492195163afb3ad14f92bcf06eaee075a
2020-09-04 12:41:16 -07:00
Alex Lane 722dcd53bd patches: updates dummy keychain patch for v2 namespace changes and ndn-cxx changes
Change-Id: I43a1d4a092190a953945cf43ea5f57556a325a9c
2020-08-28 16:06:35 -05:00
phmoll 9efd73922b BUGFIX IP-Routing helper did not work for large topologies
The initial version of the IP routing helper had issues with larger
topologies, especially when multiple paths between nodes are possible.
This fix ensures, that the same route between two nodes are
installed in both directions. This leads to a 100% reachability of nodes
in larger scenarios.

Change-Id: I6165caf11e61dd948320139752c271d8cf063b2a
2020-08-26 08:24:15 -07:00
Laqin Fan cf8e7541ab Check NDN security in Minindn class before printing related info.
refs: #5125

Change-Id: I6f8c154dcce0dd1285f26a244945aff0041f5d11
2020-08-25 01:01:15 -05:00
Ashlesh Gawande 76dbe6633c nfd: uncomment transport in client.conf to allow connections on /run/<node>.sock
refs: #5039

Change-Id: Id14c60ca171f80277a248cb9452c3b4d3e39ebce
2020-04-15 21:30:37 -07:00
Ashlesh Gawande f48424a4a7 patches: update dummy keychain patch to compile against latest ndn-cxx
Change-Id: I1cf323b9550707df0e9662f527348965649c1d94
2020-04-04 17:07:28 -07:00
Giovanni Grieco bb31ed2fcd install.sh: quiet apt install for Vagrant
Vagrant VM provisioning doesn't have any mechanism for user interaction.
For this reason, it is necessary to tell APT that we are in a
non-interactive session and any install question should be answered
automatically by its preset.

For this reason, according to issue #42 and GitHub PR #43, I propose to
add "quiet" option to install.sh. This option tells Debian-based systems
to run APT in non-interactive mode. In case of important questions
during install, we can update the preset list specified in quiet_install
subroutine.

Flag functionality can always be extended in the future to support
unexpected cases where Vagrant provision hangs due to user interaction
request by some other program.

Change-Id: Iab3ce5f9b19cd6bfcf2fa180c433fb5d5d521914
2020-03-24 12:18:22 +01:00
phmoll 1f1de1f87b Add GEANT network as mini-ndn topology
Change-Id: Ieb7e96b473436ce62c2ece6f24801c7f5b9ff4dc
2020-03-18 06:36:29 +01:00
Saurab Dulal 082e4449bb routing-helper: fix route computation bug
Route computation for link-state had a bug, neighbor's list
contained the host itself and so the computation was erroneous,
and ultimately crashing.

Change-Id: I461476eef83b73b64ae943f6f08bf576e3719b94
2020-03-17 21:30:14 -05:00
Philipp Moll 55e2dd9087 Add MiniNDN utility application for PCAP logging
Change-Id: I4f8ee5b6b970c7b74e3697af4a08b72d2169dc2a
2020-03-05 21:47:42 -08:00
phmoll 52223f7144 ndn_routing_helper: fix overwriting of existing prefixes
Instead of overwriting the existing prefixes, the prefixes given
in `prefix` are now appended to the list of already existing
prefixes.

Change-Id: I300f72ab8b0d2688a3379f295499a6ffdcbb54a4
2020-03-05 21:37:49 -08:00
phmoll ad8d37e89d Move logfiles to resultDir after evaluation finished
Reimplement the behavior that copies log files to the
`resultDir`, which was most likely lost when restructuring
MiniNDN. Parts of the patch are reused from an old
MiniNDN revision.

Change-Id: I3045237950320d1eb7840af9828459e47f6d9884
2020-03-04 08:42:27 +01:00
dulalsaurab 5c79db0aec Check duplicate HR coordinates in topology file
refs: #4812
Change-Id: If6c88d24d74e8d5d0d5e815eef1270fafe7b51e6
2020-02-27 06:10:13 +00:00
Eric Newberry a95b681d95 docs: restructure and update AUTHORS.md
refs #5078

Change-Id: Ieae783cb94a482b2ec25be895f4ca3939cc190d3
2020-02-05 19:40:44 -08:00
Ashlesh Gawande 6c86e30f63 **breaking** mini-ndn: re-design
refs: #5062

Everything is now done through examples like Mininet.
bin/minindn no longer provided as a binary installed in the system
bin/minindnedit GUI: will no longer be maintained
Remove cluster edition, will be re-introduced later

Change-Id: Id4ef137cb2a04d1b0dd24d01941757363bbf7d26
2019-12-05 15:13:01 -06:00
Saurab Dulal 8ae870a591 ndn/apps: add global routing helper
Change-Id: Id2bfb035424e2214d3dad1d00da95a0715c716c9
2019-11-25 13:51:04 -06:00
Philipp Moll 61a2be8726 Add RoutingHelper to allow IP communication in experiments
Change-Id: I267e264b2583909a47229279076655a8080ace22
2019-09-20 20:15:55 +02:00
dulalsaurab 0dcdb32992 Check duplicate HR coordinates in topology file
refs: #4812

Change-Id: I8b416e7fe5d5af73957e74b030e52897b7c75a9d
2019-07-26 12:05:49 -05:00
dulalsaurab 658c78b15f nlsr: rename seq-dir to state-dir
refs: #4835

Change-Id: I4110119758f142693c34005ed838adf411374779
2019-02-06 11:20:20 -06:00
Ashlesh Gawande 6651a74f37 ndn/experiments: add tests for psync
refs: #4670

Change-Id: I4c4ac9960eb5411ced1db855e641471c7251a046
2019-01-18 16:12:39 -06:00
dulalsaurab 50778df223 fix route expiration time
Change-Id: I6de07202c58d828d3564e6be3efe545ef912840f
2018-12-20 15:10:03 -06:00
Ashlesh Gawande 2b7acee13a install.sh: install PSync
refs: #4789

Change-Id: I5ef76acec0fa8d1d48c9c473c061c0c03420d4be
2018-12-14 15:15:48 -06:00
Ashlesh Gawande 27b5e1bf84 Add startup experiments for NLSR and current testbed topology
refs: #4785

Change-Id: I957b8c229ed0696b2f3fca9445f9f27274b0e197
2018-12-10 13:27:36 -06:00
dulalsaurab 2b899536e9 ndn: bug fixes in nfdc and experiments
Change-Id: I8cb9b0a9e53e0319e3f18ab6a52867d406a31fd5
2018-11-08 12:43:44 -06:00
Alexander Lane 6f7a64fc75 Create a helper class to provide a wrapper around nfdc.
Refs #3491

Change-Id: I2cc7cbb480a6ca81ee32bbfee47ef060dd8c51f4
2018-08-20 13:09:12 -05:00
Alexander Lane d6c3cad602 Fix checks for running software to account for no-nlsr.
Refs: #4640

Change-Id: Ie4086856d1b9d4f50e99aae917718233156f8fb9
2018-06-19 17:03:14 -05:00
Alexander Lane 9944cf5129 Move the NDNPing wrapper method to a helper class.
Also updates GPL header for the current calendar year.

Refs: #3492

Change-Id: Ic4977c33edd0311b140e6db3688afbb182acec9e
2018-06-14 17:08:00 -05:00
Alexander Lane 052aabbc7b Check that NFD and NLSR are running in all hosts before running experiments.
Added functionality to prevent minindn from running w/o dependencies.

ref #4562

Change-Id: Ib7a8544c9a981335d05f710023fb55a7995e0864
2018-06-08 14:50:27 -05:00
Alexander Lane 517d34cf64 Parser fix to avoid infinite loop
Refs: #4627

Change-Id: I629bb76b3a1dbba4f44aac6ee258000a8d5ade7e
2018-06-08 14:06:40 -05:00
Ashlesh Gawande 670ff15691 Install bash completion for argcomplete
Update version to 0.4.0

refs: #4629, #4631

Change-Id: I2319a37fc1ba6587528c4ed2eadf727c3c0f6526
2018-06-08 12:27:54 -05:00
Alexander Lane 4fa88819c1 Allow use of NFD and NLSR PPA with Mini-NDN.
Refs: #3992

Change-Id: I329d0303bb4e03ec2296dfb7f7aa00cac3dadfbd
2018-06-06 11:57:31 -05:00
Alexander Lane 1bc9b47be9 Remove arbitrary arguments in favor of parsing arguments from experiment files.
refs: #4611

Change-Id: Ic668b58766fef8a1e537ccaacf82230b3fb50923
2018-05-24 13:26:35 -05:00
Ashlesh Gawande 212cb82889 Autocomplete command line arguments.
Use bashrc for sudo autocomplete (argcomplete issue num. 65 on GitHub).

refs: #4454

Change-Id: I4d46cba20d2f046878063e45615c9a8eab41ba5a
2018-05-23 13:01:39 -05:00
Alexander Lane e842cc204d Exit cleanly on Mininet errors.
Refs #4540

Change-Id: I7605c9740eca785e290e64e0d8a29339c92c7df2
2018-05-16 12:54:29 -05:00
Ashlesh Gawande 532302bbf2 nfd: add option to set CS size
Don't append NFD logs b/w runs
Re-factor NFD start from ndn_host.py to bin/minindn

refs: #4469, #4508

Change-Id: I43f594a3353bb92101a0281a4561999cd8406707
2018-03-29 12:31:03 -05:00
Saurab Dulal 5f8c796609 ndn: Fix name "cost" to "link-cost" in nlsr.conf file
Change-Id: I92dd8d143b359ac5c77b4be45d4f7fdc086cf69f
2018-03-09 12:57:20 -06:00
Saurab Dulal 092755eaae Change NFD log and conf file names to nfd.log, nfd.conf
refs: #4077

Change-Id: I1cc843376c24a784b7a37225df88d26568345d01
2018-01-23 08:46:46 -08:00
dmcoomes 73caa524d3 adjust to use ndn-cxx logging
refs: #4435

Change-Id: If8709c24f7bdc5503e9b0b7b46aca5c1a65a5c2a
2018-01-19 15:54:19 -06:00
Ashlesh Gawande ed557f5a29 docs: Prepare version 0.4.0 release notes
Change-Id: I7eecaa606c0ec835148cc3177d223a30b57eb70e
2018-01-10 17:34:35 -06:00
Jeff Thompson 55d2bf4503 install.sh: Added function commonClientLibraries
refs: #4141

Change-Id: Ia0c820506690bd28b4196b4d2335d02933d0bb29
2018-01-10 16:22:39 -06:00
Saurab Dulal 7b3655a52a Modified Vagrantfile to remove sudo from the installation process
Included -a option to encapsulate -emfrti to install all dependencies

Change-Id: Ief864f4c7c69a80cfc47fc1ef195a2842c11011d
refs: #4423, #4404
2018-01-04 14:54:15 -08:00
Nick Gordon 22642a39ca docs: mention the contributing guide
Change-Id: I5fa215dd471945d9d2d4da3c67de511d4784b522
refs: #4413
2017-12-23 14:19:12 -08:00
Saurab Dulal 7a6978eb52 Use the nlsr.conf file installed in the system
Use infoedit to edit nlsr.conf file

refs: #4386, #4038

Change-Id: I4ad1e1efe92b20f444f5f9346679574888a456ed
2017-12-20 18:50:35 +00:00
Ashlesh Gawande a80484e0bd Changes to adopt to latest ndn-cxx
refs: #4292, #4155

Change-Id: Ifb0d94e23cb3a4efc82246b45578b1d5fc04ac67
2017-12-07 14:36:53 -06:00
Saurab Dulal 5d9ba60f95 use infoedit to edit nfd config files
refs: #4038

Change-Id: I193f32f54c0b47f6e2c1803b0bc4cdda9056540a
2017-12-06 22:55:44 +00:00
dmcoomes 74da84ce4d check for coordinates before running hyperbolic routing
refs: #4252

Change-Id: I04a4278443f02eef29666800fb3cd22e53a5ca28
2017-11-29 14:43:47 -06:00
dmcoomes 80eeea157b change default working directory
refs: #4357

Change-Id: I76715ddb4408a7c8c556ea5c5dbdf573f6eb840e
2017-11-03 15:26:31 -07:00
dmcoomes 8fb3a545bb Provide a vagrant file
refs: 4307

Change-Id: I9cf1c8f75b65a4d16bb2f13eb95a819f3aedf80c
2017-11-03 15:09:10 -05:00
Ashlesh Gawande 501d4d6a3a Arbitrary arguments
refs: #4360

Change-Id: I1c746c3349a72d1e262b75d4a864f096a2dfc018
2017-11-03 13:17:12 -05:00
dmcoomes ad5de70d4b docs: update authors
refs: #4333

Change-Id: I1a541223da2eaacc9938b27f016f239c6b877729
2017-11-01 10:28:28 -05:00
dmcoomes a013686a11 Revise mininet installation instructions
refs: #4036

Change-Id: Id71cc450ea90abf26387b9a9d35cd40abceaa795
2017-10-26 12:38:01 -05:00
Ashlesh Gawande 2763f1978e Use SIGQUIT instead of SIGINT
refs: #3870

Change-Id: I915d9422d56a441b351bb9ab38a0c8377e1da34f
2017-10-26 12:20:46 -05:00
dmcoomes 2ef39c064e fix nlsr startup error
refs: #4309

Change-Id: I0eb7e97c183bbfdb86f0992533fa531698c04600
2017-10-20 14:09:02 -05:00
dmcoomes ecf9c5a1bc Provide option to disable NLSR
refs: #4309

Change-Id: I78774aa535f3e1c8dea51b05e070b0e8815ff938
2017-10-19 11:32:05 -05:00
dmcoomes 7adc7f7275 Provide option to run NLSR in dry-run mode
refs: #4326

Change-Id: Icd84ae1f59acadac478e8a3425e21fd02d86bdf8
2017-10-17 13:44:04 -05:00
dmcoomes 9850d65151 Update install.sh to use ldconfig for chronosync
refs: #4295

Change-Id: Id7dab8fc09063c6cf72ad96c31a9c4376c5c8788
2017-09-29 14:31:33 -05:00
Ashlesh Gawande 6a075c25ff Add experiment to test nlsrc
refs: #4216

Change-Id: I59d1c96bfa5cdedf308d8885cbb2c487994c4c5b
2017-08-09 15:48:27 -05:00
Ashlesh Gawande 02852a0161 Update install script to use fixed version of ChronoSync
Only install ping and dump from ndn-tools

refs: #4212

Change-Id: I6f4e2782c4a3b58fd4f60729c97ea031c0a375a1
2017-07-28 20:42:36 -05:00
Ashlesh Gawande ec084835ce Update install script for ChronoSync
Use specific commits of ndn-cxx and NFD

refs: #4125

Change-Id: Ie5a1a5f514337dcb6d0aced94169762ee518070f
2017-06-27 09:26:51 -07:00
Ashlesh Gawande 708fccabdc Create faces in NFD for each neighbor of NLSR
Add option to specify whether to use TCP or UDP face in nlsr.conf

refs: #4144, #4146

Change-Id: Ida40aef80bea0e5bcb7392e446aaefce0bea9b66
2017-06-26 13:43:12 -05:00
Ashlesh Gawande 59f8624201 Fix key does not exist error
refs: 4076

Change-Id: If3569c4620f04b9ef51fa912d865f27c77a42004
2017-05-05 15:22:38 -05:00
Ashlesh Gawande da475f06c4 docs: Prepare version 0.3.0 release notes
refs: #3985

Change-Id: I5172cfe96b104b6c0b8cdf769413b9223d79ed18
2017-03-03 09:49:05 -06:00
Ashlesh Gawande f6a610bd2e No need to store host names, make network name a constant
refs: #3958, #3972

Change-Id: I16e5b94174dd47913d7d93a22708fb41061a762c
2017-03-01 13:32:34 -08:00
Ashlesh Gawande 95789ccc5e update INSTALL.md, use mini-ndn name in CLI
refs: #3969, #3980

Change-Id: Idd84d70b5edfa8fb06cf5158ccca452764d77eb7
2017-03-01 11:25:30 -06:00
Ashlesh Gawande 5f47020f43 add new experiments for NLSR bot
refs: #3975

Change-Id: Iad1db7fca4c475d308d2f5c79cdd737967a986b2
2017-02-28 09:42:12 -06:00
Ashlesh Gawande 3bed483792 add missing cert installs and nlsr conf file update
refs: #3951, #3953

Change-Id: Id1264bed658324083618faa579640e50240fecdb
2017-02-09 14:52:59 -06:00
Ashlesh Gawande f5f304b9cd modification to use cluster version
Change-Id: Iaf169507577deba20d548348532a2e0b91a03249
refs: #3652
2017-01-12 15:39:07 -06:00
Ashlesh Gawande 044611d101 use argparse instead of optparse
refs: #3900

Change-Id: I6a883ef5d481aeac4d92e29249e9368d7b1dcf49
2016-12-23 12:30:01 -06:00
Ashlesh Gawande f932a18f7b use nfdc instead of nfd-status
refs: #3878

Change-Id: Ib3aad0fdb48e719031d03a3706d284d93ada5653
2016-12-19 23:45:38 -06:00
Ashlesh Gawande e144ceb8c2 set different site name for each router
Change-Id: Ic81d8d9908923dfafce777c091fc9b288ade7400
refs: #2719
2016-11-28 14:50:44 -06:00
Ashlesh Gawande 5518f71bfe Fix NLSR termination due to key does not exist error
refs: #3869

Change-Id: I12927eeef02f0311112fae02a1c885389947dde5
2016-11-28 13:06:44 -06:00
Ashlesh Gawande 0cccdb8a3a docs: Prepare version 0.2.0 release notes
Change-Id: Ie390e902d8389f8554b62a1dbbb8fdb73772263b
2016-08-18 10:10:51 -07:00
Ashlesh Gawande e626b63cd9 docs: update docs
refs: #3670

Change-Id: I4a90df1cf5b28d05fd81877bf4d51659e21b1119
2016-08-16 18:04:15 -05:00
Ashlesh Gawande 52e47e161d Do not update if minindn has already been installed before
refs: #3729

Change-Id: I4409de6f9ddc876aed20a34435c2186f6470fa20
2016-08-09 14:37:31 -07:00
Ashlesh Gawande 3807c1b64f exit gracefully on control-c and non-convergence
refs: #3672

Change-Id: I19df1a3318315b49816b3cf93c39bc95af52d0b3
2016-08-09 09:16:03 -07:00
Ashlesh Gawande c09c16da83 ndn_application: init processId and fix nfd not being killed
Change-Id: I3ec5d79f903130d0ce42fd1c2a18bd73065757e7
refs: #3671
2016-08-09 11:02:58 -05:00
Ashlesh Gawande b07ada8b5e set best-route strategy correctly
refs: #3696

Change-Id: Ia9285e7261167f511c7193b09f37023b68a39eeb
2016-08-05 14:31:35 -07:00
Vince Lehman 5d5a566f8b Add automatic NLSR security configuration
refs: #3050

Change-Id: I218f96a2cb11dd35de99c4a9eab056f0fed890aa
2016-07-26 14:58:30 -05:00
Yucheng Zhang 14aa596935 Use nfd.conf by default instead of nfd.conf.sample
Change-Id: I2b539d2082efa20be0aea62286426d2dde85be7f
refs: #3468
2016-07-19 09:55:43 -07:00
Vince Lehman bf600a4334 Add ProcessMonitor class
refs: #3641

Change-Id: I88bf88081038360170532d3c4bf11f1bc2650bda
2016-06-02 16:36:41 -05:00
Yucheng Zhang dd4c6b78e4 Launch NLSR with explicit configuration file
Change-Id: Icacb1b4f320a4aa7394f58611ba424924a4ae0c0
refs: #3039
2016-06-02 12:36:42 -08:00
Yucheng Zhang 008387d311 Update verification instructions
Change-Id: I4b078f9c1e934590bdaebc761c66bb6be7056cbf
refs: #3467
2016-04-05 17:19:56 -05:00
Vince Lehman 68b0815584 docs: Prepare version 0.1.1 release notes
Change-Id: Ie2d8546eedfac8e9e54d1fcc68122dcc3f90b1b9
2015-11-04 14:05:44 -06:00
Ashlesh Gawande 5fee776a3b Add MCN failure experiment
refs: #3272

Change-Id: I663680898bf4a0b9da21e0c408933cef6200564b
2015-11-04 11:25:32 -07:00
Ashlesh Gawande d9c9e52507 experiments: Allow pinging a percentage of nodes
refs: #3265

Change-Id: I80a37d4a8cf6ca5a25d03f1f98cdcf9394feb92f
2015-11-04 12:10:39 -06:00
Vince Lehman 0c5eb69d30 Remove debug statement from IP address assignment
Change-Id: Ie4fd78e9a60279e11913e806a0309554eb46fb0c
2015-11-03 09:37:41 -06:00
Ashlesh Gawande d829bfc385 Add results directory option
refs: #3266

Change-Id: I80b74969377753445925effb0b1c2010e0923b23
2015-10-27 08:52:56 -07:00
Vince Lehman d96eed31e8 Add failNode and recoverNode methods to Experiment class
refs: #3085

Change-Id: Ib99edc1c7a201f16c993aa0e0c4791c2eea15a35
2015-10-23 14:19:14 -07:00
Vince Lehman c64dcb8366 Remove "FIB Entries" from NDN host options
refs: #2912

Change-Id: I4474c7c0aad3b4c6066f096c78934f561a2bf070
2015-10-22 15:22:02 -07:00
Vince Lehman fbd47c9ef8 Add support for switches in GUI and configuration file
refs: #2583

Change-Id: I051dfe7c9e5fae292a7ca97f26f41dfc403241b8
2015-10-22 13:50:16 -05:00
Ashlesh Gawande 1b66369d43 Add working directory option
refs: #3266

Change-Id: Ifd953b242c99f75c68eb3c63ef5e51ef46195b8b
2015-10-22 11:55:30 -05:00
Vince Lehman 194be2465a Refactor program options into POD
refs: #3269

Change-Id: Ica3a302bdc74ac13aa214f589bf7dc68fcd5f262
2015-10-22 11:09:50 -05:00
Vince Lehman 498625bb71 Use nfd.conf.sample from currently installed NFD
refs: #3282

Change-Id: Idc3a70fc62b98c72970eab41d16eb587a16efe9a
2015-10-21 15:07:43 -07:00
Ashlesh Gawande 4e545d967b exit before starting up if exp name is invalid
refs: #3115

Change-Id: I901ac7b951bc21ba8069b5b9be2a1d067ba8e61b
2015-10-21 16:00:50 -05:00
Ashlesh Gawande 1cebdfc7fb experiments: Restart pings for CSU after recovery
refs: #3086

Change-Id: I54fe2a2d1b4b6cd4d09ff72b79fbb30de50d5a89
2015-10-15 10:53:52 -05:00
Ashlesh Gawande 37bffa9ceb docs: Connect Mini-NDN to external network
refs: #3052

Change-Id: I0bb060fc1095946b8f6302880aa78b817a9c07f7
2015-10-14 14:13:57 -07:00
Vince Lehman 4e7df5ad86 docs: Add mailing list to README
Change-Id: I3961b279b871d57f103aafb1921b266e5dd8aaf9
2015-07-21 11:55:49 -05:00
Vince Lehman e9f116d781 docs: Prepare version 0.1.0 release notes
Change-Id: If3a00751ed5aef36b76c2af653f0fe7b71fc7efd
2015-07-15 11:02:00 -07:00
Vince Lehman 673b013984 docs: Update AUTHORS.md
Change-Id: I69d40a72001a064e4e0cf3f248d58928ba91fdd1
2015-07-15 11:39:40 -05:00
Vince Lehman 608a1337ec Update README.md
Change-Id: I58d3a56ae8dd7bc9b24a2e219b04fabc04902868
2015-07-14 16:42:34 -07:00
Vince Lehman d1ee56a16a docs: Add GUI.md
Change-Id: Ic7ffb8dea4521af95cb87e578be3eb46af6e8f6e
2015-07-14 16:41:43 -07:00
Vince Lehman d367dbb032 docs: Add GETTING-STARTED.md
Change-Id: I43d9b3d017d9c7f62d658f93bef97a62e43aeed0
2015-07-14 16:41:22 -07:00
Vince Lehman ce7f4e9236 docs: Add EXPERIMENTS.md
refs: #2916

Change-Id: I096269b0befb086add38d1d9e9cf1aad17e4d388
2015-07-14 16:40:01 -07:00
Ashlesh Gawande 3a1b6e54e4 docs: Add CONFIG.md
Change-Id: I02272d8a6bf6f4a4eceefc9c2b8b36003e3e78c2
2015-07-14 16:39:14 -07:00
Vince Lehman b8b1806546 Add license and copyright notices
Change-Id: I47244d7e3015c7d8a4c57f4ee1cc9679bc320d43
2015-07-14 16:36:22 -07:00
Vince Lehman 1c0e097ccf Add AUTHORS.md
Change-Id: Id408542f4318c0d0b6b29725dbe61185b9194777
2015-07-14 16:04:14 -07:00
Ashlesh Gawande ab087daa66 Load topology from saved files
refs: #2911

Change-Id: Ic5b0c0713333579fd6e92c738784b3de1dda6a1d
2015-07-14 09:53:44 -05:00
Ashlesh Gawande 557cb8466a Add ability to specify multiple apps to run on each node
refs: #2933

Change-Id: Ic5d47bb3e9ab830f01b55be37848aa680174cf32
2015-07-14 09:31:10 -05:00
Ashlesh Gawande 792c6aa970 Add NdnApplication class to handle start and stop
refs: #2909

Change-Id: Ibe5760b155e0edf2227d2d7146f8b6552149a63b
2015-07-13 22:33:29 -05:00
Ashlesh Gawande 3a4afb19d5 Set NFD logging level from GUI
refs: #2913

Change-Id: I4255b0467ef8ee6c4a2803ed078256cac9fbfd9c
2015-07-13 20:28:47 -05:00
Vince Lehman 3b8bc652d4 Implement ExperimentManager
refs: #2852

Change-Id: I49b50989477914ae4b076d6d39ca661f50fc92aa
2015-07-10 16:08:18 -05:00
Ashlesh Gawande c3ed2b9960 Set NLSR logging level from GUI
refs: #2914

Change-Id: I8dca010011bbe6b94ac986ce14c6c735d8bacb17
2015-07-09 11:10:02 -05:00
Ashlesh Gawande 20f70762b6 Use default topology when no topology file is provided
Change-Id: Icbc434a82cc147c84680c77e2f089f20d50ad803
refs: #2915
2015-07-09 09:26:29 -05:00
Ashlesh Gawande 1a0129681a Remove unused files and folders
Change-Id: I5b1872651bcaff603816b83ab23464b4808cbd19
refs: #2908
2015-07-01 17:01:00 -05:00
ashu 2ad32e2a61 Using latest version of mininet
refs: #2851

Change-Id: Ica4936cb98245a0b1a22d8ceada4e7a0f6dbddc8
2015-06-16 16:02:05 -05:00
Vince Lehman cb20c547af experiment: Add multiple failure experiment
Change-Id: Ia7e856606ec483f0bb63840a0e40399058e5b6ac
2015-05-13 09:52:46 -05:00
ashu 8bf379eaf3 Update INSTALL readme
refs: #2784

Change-Id: I26b03c297da3df9d8515766d262cf3f984fbea21
2015-05-08 13:47:13 -07:00
Vince Lehman c264d44357 Update nlsr.conf for NLSR 0.2.0
Change-Id: Ic7f026858ad0ab55bd2e821ddb9c4839cbb77a00
2015-05-01 12:46:16 -07:00
ashu 7b6ba18c7e ndn: Add GUI
Change-Id: I7336bbb04121166d064b76cbad9f760c3dd16c2d
2015-05-01 13:37:45 -05:00
ashu 34c3ee0b6a ndn: Add NLSR experiments
Change-Id: I0b86b121a5c8bf6a6e6e8df5027fe49561a9283b
2015-04-16 17:24:58 -05:00
ashu 4c85880a01 Modify README
Change-Id: I18a2cdd6d9a19ae7b8cf299e11595b6182c4eaa6
2015-04-15 13:33:44 -07:00
ashu 01b62f7c46 Add ndn_utils and modify install script
refs: #2528

Change-Id: I7c26df7c91572f8e48b23ca3cddcec1b8f0216a5
2015-03-25 11:25:52 -05:00
ashu ef3490b052 ndn: Add NFD and NLSR class abstractions
refs: #2528

Change-Id: I3241af0e85f4eec4eb640aca274ff9ca4f812656
2015-03-09 14:31:23 -05:00
Caio 188d2f3940 All done! GUI + working version. Some few adjustments on the code to be done. 2015-01-22 23:35:08 -02:00
Caio 6bdcecfbfc Minor code change 2015-01-19 18:50:13 -02:00
Caio 24c0cbddbf GUI OK - ToDo: ImportTOPO 2015-01-19 18:45:53 -02:00
Caio ac585d8778 Merge pull request #11 from caio92/master
Enhancements made in MiniccnxEdit.
2014-12-01 16:41:38 -02:00
Caio Elias 2fa082da91 Small about/credits changes 2014-12-01 16:38:04 -02:00
Caio Elias e904f533e3 Updated MiniCCNxEdit, now it has the possibility to Save and Load topologies. TODO: change nodes and links parameters from the GUI 2014-12-01 16:19:22 -02:00
Caio Elias 47b243c59d First changes into new version of mnccnxedit GUI 2014-11-23 19:25:34 -02:00
Caio d8711c8d1d Merge pull request #9 from caio92/master
fixed config_parser.py
2014-10-01 00:59:36 -03:00
Caio Elias b5e55fa658 Fixed indentation in conf_parser.py 2014-09-19 14:27:54 -03:00
Caio Elias c6b56036cf Fixed small bug in conf_parser.py file that would return an error in case there was an empty line in [link] session or an empty-options host in [nodes] section of the .config file 2014-09-19 14:12:48 -03:00
Christian Esteve Rothenberg 21d9179ac0 Update README.md 2014-01-11 12:09:26 -02:00
carlosmscabral 7736b82f92 mem 2013-07-21 14:40:31 -03:00
carlosmscabral 652bad492c new gui 2013-07-18 13:23:29 -03:00
carlosmscabral 3d060fc824 3 2013-07-18 13:18:09 -03:00
carlosmscabral ceef99c108 adapt 2013-07-18 11:18:02 -03:00
carlosmscabral b9d85b724e adaptions 2013-07-15 15:24:33 -03:00
carlosmscabral b4430fb7b6 Removing debug print 2013-03-23 12:06:00 -03:00
carlosmscabral 6d3dd60010 Adding NDN testbed 2013-03-23 11:12:34 -03:00
carlosmscabral d7ccfd9f52 Right wiki Link 2013-02-25 18:18:25 -03:00
carlosmscabral e3c810e23f README 2013-02-25 18:15:40 -03:00
carlosmscabral f8ccd38513 INSTALL docs 2013-02-25 18:14:27 -03:00
carlosmscabral e121a7b55b New functions 2013-02-18 18:14:53 -03:00
carlosmscabral cd5073b5e5 install.sh correction 2013-02-04 12:38:20 -02:00
carlosmscabral 4cf72ea2ef Install/README changes 2013-02-04 12:33:50 -02:00
carlosmscabral 9ab2f8dd86 Changed Makefile and setup.py 2013-02-04 12:28:14 -02:00
carlosmscabral fc8a032ed2 - 2013-02-04 12:10:16 -02:00
carlosmscabral 29432250ec Included CPULimitedCCNHost parsing 2013-02-04 11:54:16 -02:00
carlosmscabral b2d76332dc 3 2013-02-01 19:13:23 -02:00
carlosmscabral f40ecd179c First commit 2013-02-01 18:15:58 -02:00
carlosmscabral 0fb51cc605 first commit 2013-01-12 18:02:46 -02:00
219 changed files with 8773 additions and 20949 deletions
+1
View File
@@ -0,0 +1 @@
Dockerfile
-1
View File
@@ -1 +0,0 @@
*.py diff=python
+44
View File
@@ -0,0 +1,44 @@
name: Publish Docker image
on:
push:
branches:
- master
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Login to ${{ env.REGISTRY }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
pull: true
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+18 -11
View File
@@ -1,14 +1,21 @@
mnexec
*.pyc
*~
*.1
*.xcodeproj
*.xcworkspace
\#*\#
mininet.egg-info
# Python
build
dist
doc/html
doc/latex
trunk
Mini_NDN.egg-info
*.pyc
# Docs
docs/html
docs/latex
docs/_build
# Misc
.DS_Store
dl
*.apconf
# Vagrant
.vagrant
venv/
.vscode
-301
View File
@@ -1,301 +0,0 @@
# lint Python modules using external checkers.
#
# This is the main checker controlling the other ones and the reports
# generation. It is itself both a raw checker and an astng checker in order
# to:
# * handle message activation / deactivation at the module level
# * handle some basic but necessary stats'data (number of classes, methods...)
#
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Profiled execution.
profile=no
# Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times.
ignore=CVS
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
[MESSAGES CONTROL]
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once).
disable=pointless-except, invalid-name, super-init-not-called, fixme, star-args,
too-many-instance-attributes, too-few-public-methods, too-many-arguments,
too-many-locals, too-many-public-methods, duplicate-code, bad-whitespace,
locally-disabled
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html
output-format=colorized
msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}'
# Include message's id in output
include-ids=yes
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells wether to display a full report or only the messages
reports=no
# Python expression which should return a note less than 10 (10 is the highes
# note). You have access to the variables errors warning, statement which
# respectivly contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation repor
# (R0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Add a comment according to your evaluation note. This is used by the global
# evaluation report (R0004).
comment=no
# Enable the report(s) with the given id(s).
#enable-report=
# Disable the report(s) with the given id(s).
#disable-report=
# checks for :
# * doc strings
# * modules / classes / functions / methods / arguments / variables name
# * number of arguments, local variables, branchs, returns and statements in
# functions, methods
# * required module attributes
# * dangerous default values as arguments
# * redefinition of function / method / class
# * uses of the global statemen
#
[BASIC]
# Required attributes for module, separated by a comma
required-attributes=
# Regular expression which should only match functions or classes name which do
# not require a docstring
no-docstring-rgx=__.*__
# Regular expression which should only match correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression which should only match correct module level names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression which should only match correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Regular expression which should only match correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct instance attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct list comprehension /
# generator expression variable names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,inpu
# try to find bugs in the code using type inference
#
[TYPECHECK]
# Tells wether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamicaly set).
ignored-classes=SQLObjec
# When zope mode is activated, add a predefined set of Zope acquired attributes
# to generated-members.
zope=no
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E0201 when accessed.
generated-members=REQUEST,acl_users,aq_paren
# checks for
# * unused variables / imports
# * undefined variables
# * redefinition of variable from builtins or from an outer scope
# * use of variable before assigmen
#
[VARIABLES]
# Tells wether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching names used for dummy variables (i.e. not used).
dummy-variables-rgx=_|dummy
# List of additional names supposed to be defined in builtins. Remember tha
# you should avoid to define new builtins when possible.
additional-builtins=
# checks for :
# * methods without self as first argumen
# * overridden methods signature
# * access only to existant members via self
# * attributes not defined in the __init__ method
# * supported interfaces implementation
# * unreachable code
#
[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp,build
# checks for sign of poor/misdesign:
# * number of methods, attributes, local variables...
# * size, complexity of functions, methods
#
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branchs=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# checks for
# * external modules dependencies
# * relative / wildcard imports
# * cyclic imports
# * uses of deprecated modules
#
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report R0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report R0402 mus
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report R0402 mus
# not be disabled)
int-import-graph=
# checks for :
# * unauthorized constructions
# * strict indentation
# * line length
# * use of <> instead of !=
#
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=80
# Maximum number of lines in a module
# XXX 1500 -> 4000 for miniedit.py
max-module-lines=4000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# checks for:
# * warning notes in the code like FIXME, XXX
# * PEP 263: source code with non ascii character but no encoding declaration
#
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
# checks for similarities and duplicated code. This computation may be
# memory / CPU intensive, so you should disable it if you experiments some
# problems.
#
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=4
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
+38
View File
@@ -0,0 +1,38 @@
Mini-NDN Authors
=================
The following lists maintainers, primary developers, and all much-appreciated contributors to Mini-NDN in alphabetic order.
The specific contributions of individual authors can be obtained from the git history of the [official Mini-NDN repository](https://github.com/named-data/mini-ndn).
If you would like to become a contributor to the official repository, please follow the recommendations in https://github.com/named-data/.github/blob/master/CONTRIBUTING.md.
* Alexander Afanasyev <https://users.cs.fiu.edu/~afanasyev>
* Muktadir R. Chowdhury <https://github.com/alvyC>
* Damian Coomes <https://github.com/dmcoomes>
* ***(Maintainer)*** Saurab Dulal <https://dulalsaurab.github.io>
* Laqin Fan <https://github.com/laqinfan>
* ***(Former Maintainer)*** Ashlesh Gawande <https://www.linkedin.com/in/agawande>
* Nicholas Gordon <https://github.com/gorgonical>
* Giovanni Grieco <https://github.com/GiovanniGrieco>
* ***(Maintainer)*** Alexander Lane <https://github.com/awlane>
* Vince Lehman <http://vslehman.com>
* Philipp Moll <https://github.com/phylib>
* Eric Newberry <https://ericnewberry.com>
* Junxiao Shi <https://cs.arizona.edu/~shijunxiao>
* Jeff Thompson <https://remap.ucla.edu/jeff-thompson>
* Yucheng Zhang <https://peterskycloud.wixsite.com/yzportfolio>
* Italo Valcy S Brito <https://github.com/italovalcy>
Technical Advisors
-------------------
* Lan Wang <http://www.cs.memphis.edu/~lanwang>
* Beichuan Zhang <http://cs.arizona.edu/~bzhang>
The Mini-CCNx team
-------------------
* Carlos Cabral <https://github.com/carlosmscabral>
* Caio de Moraes Elias <https://github.com/ocaio>
* Christian Esteve Rothenberg <http://www.dca.fee.unicamp.br/~chesteve>
-49
View File
@@ -1,49 +0,0 @@
Mininet Contributors
Mininet is an open source project and we gratefully acknowledge
the many contributions to the project! If you have contributed
code into the project and are not on this list, please let us know
or send a pull request.
Contributors include:
Mininet Core Team (and alumni)
Bob Lantz
Brandon Heller
Nikhil Handigol
Vimal Jeyakumar
Brian O'Connor
Cody Burkard
Additional Mininet Contributors
Tomasz Buchert
Gustavo Pantuza Coelho Pinto
Fernando Cappi
Ryan Cox
Shaun Crampton
David Erickson
Glen Gibb
Andrew Ferguson
Eder Leao Fernandes
Gregory Gee
Jon Hall
Vitaly Ivanov
Rich Lane
Rémy Léone
Zi Shen Lim
Murphy McCauley
José Pedro Oliveira
James Page
Angad Singh
Piyush Srivastava
Ed Swierk
Darshan Thaker
Andreas Wundsam
Isaku Yamahata
Baohua Yang
Thanks also to everyone who has submitted issues and pull
requests on github, and to our friendly mininet-discuss
mailing list!
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+37
View File
@@ -0,0 +1,37 @@
# Setup container with Ubuntu 22.04 image
FROM ubuntu:22.04
# Set the working directory to /
WORKDIR /
# expose ports for openvswitch-switch
EXPOSE 6633 6653 6640
# Update container image
RUN apt-get update -y && \
apt-get install --no-install-recommends -y \
lsb-release sudo \
zip unzip wget git ca-certificates \
curl iproute2 iputils-ping net-tools \
python3 python3-pip \
tcpdump vim x11-xserver-utils xterm && \
update-ca-certificates && \
rm -rf /var/lib/apt/lists/* && \
alias python=python3
COPY . /mini-ndn
RUN cd mini-ndn && \
pip3 install -r requirements.txt && \
./install.sh -y --source && \
cd dl/mininet && make install && cd ../.. && \
cd dl/mininet-wifi && make install && cd ../.. && \
rm -rf dl && rm -rf /var/lib/apt/lists/* && cd /
COPY docker/ENTRYPOINT.sh /
RUN chmod +x ENTRYPOINT.sh
# Change the working directory to /mini-ndn
WORKDIR /mini-ndn
ENTRYPOINT ["/ENTRYPOINT.sh"]
-179
View File
@@ -1,179 +0,0 @@
Mininet Installation/Configuration Notes
----------------------------------------
Mininet 2.2.1d2
---
The supported installation methods for Mininet are 1) using a
pre-built VM image, and 2) native installation on Ubuntu. You can also
easily create your own Mininet VM image (4).
(Other distributions may be supported in the future - if you would
like to contribute an installation script, we would welcome it!)
1. Easiest "installation" - use our pre-built VM image!
The easiest way to get Mininet running is to start with one of our
pre-built virtual machine images from <http://mininet.org/>
Boot up the VM image, log in, and follow the instructions on the
Mininet web site.
One advantage of using the VM image is that it doesn't mess with
your native OS installation or damage it in any way.
Although a single Mininet instance can simulate multiple networks
with multiple controllers, only one Mininet instance may currently
be run at a time, and Mininet requires root access in the machine
it's running on. Therefore, if you have a multiuser system, you
may wish to consider running Mininet in a VM.
2. Next-easiest option: use our Ubuntu package!
To install Mininet itself (i.e. `mn` and the Python API) on Ubuntu
12.10+:
sudo apt-get install mininet
Note: if you are upgrading from an older version of Mininet, make
sure you remove the old OVS from `/usr/local`:
sudo rm /usr/local/bin/ovs*
sudo rm /usr/local/sbin/ovs*
3. Native installation from source
3.1. Native installation from source on Ubuntu 12.04+
If you're reading this, you've probably already done so, but the
command to download the Mininet source code is:
git clone git://github.com/mininet/mininet.git
Note that the above git command will check out the latest and greatest
Mininet (which we recommend!) If you want to run the last tagged/released
version of Mininet, you can look at the release tags using
cd mininet
git tag
and then
git checkout <release tag>
where <release tag> is the release you want to check out.
If you are running Ubuntu, Debian, or Fedora, you may be able to use
our handy `install.sh` script, which is in `mininet/util`.
*WARNING: USE AT YOUR OWN RISK!*
`install.sh` is a bit intrusive and may possibly damage your OS
and/or home directory, by creating/modifying several directories
such as `mininet`, `openflow`, `oftest`, `pox`, etc.. We recommend
trying it in a VM before trying it on a system you use from day to day.
Although we hope it won't do anything completely terrible, you may
want to look at the script before you run it, and you should make
sure your system and home directory are backed up just in case!
To install Mininet itself, the OpenFlow reference implementation, and
Open vSwitch, you may use:
mininet/util/install.sh -fnv
This should be reasonably quick, and the following command should
work after the installation:
sudo mn --test pingall
To install ALL of the software which we use for OpenFlow tutorials,
including POX, the OpenFlow WireShark dissector, the `oftest`
framework, and other potentially useful software, you may use:
mininet/util/install.sh -a
This takes about 4 minutes on our test system.
You can change the directory where the dependencies are installed using
the -s <directory> flag.
mininet/util/install.sh -s <directory> -a
3.2. Native installation from source on Fedora 18+.
As root execute the following operations:
* install git
yum install git
* create an user account (e.g. mininet) and add it to the wheel group
useradd [...] mininet
usermod -a -G wheel mininet
* change the SElinux setting to permissive. It can be done
temporarily with:
setenforce 0
then login with the new account (e.g. mininet) and do the following:
* clone the Mininet repository
git clone git://github.com/mininet/mininet.git
* install Mininet, the OpenFlow reference implementation, and
Open vSwitch
mininet/util/install.sh -fnv
* enable and start openvswitch
sudo systemctl enable openvswitch
sudo systemctl start openvswitch
* test the mininet installation
sudo mn --test pingall
4. Creating your own Mininet/OpenFlow tutorial VM
Creating your own Ubuntu Mininet VM for use with the OpenFlow tutorial
is easy! First, create a new Ubuntu VM. Next, run two commands in it:
wget https://raw.github.com/mininet/mininet/master/util/vm/install-mininet-vm.sh
time install-mininet-vm.sh
Finally, verify that Mininet is installed and working in the VM:
sudo mn --test pingall
5. Installation on other Linux distributions
Although we don't support other Linux distributions directly, it
should be possible to install and run Mininet with some degree of
manual effort.
In general, you must have:
* A Linux kernel compiled with network namespace support enabled
* An compatible software switch such as Open vSwitch or
the Linux bridge.
* Python, `bash`, `ping`, `iperf`, etc.
* Root privileges (required for network device access)
We encourage contribution of patches to the `install.sh` script to
support other Linux distributions.
Good luck!
Mininet Team
---
-33
View File
@@ -1,33 +0,0 @@
Mininet 2.2.1d2 License
Copyright (c) 2013-2015 Open Networking Laboratory
Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
The Leland Stanford Junior University
Original authors: Bob Lantz and Brandon Heller
We are making Mininet available for public use and benefit with the
expectation that others will use, modify and enhance the Software and
contribute those enhancements back to the community. However, since we
would like to make the Software available for broadest use, with as few
restrictions as possible permission is hereby granted, free of charge, to
any person obtaining a copy of this Software to deal in the Software
under the copyrights without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The name and trademarks of copyright holder(s) may NOT be used in
advertising or publicity pertaining to the Software or any derivatives
without specific, written prior permission.
-73
View File
@@ -1,73 +0,0 @@
MININET = mininet/*.py
TEST = mininet/test/*.py
EXAMPLES = mininet/examples/*.py
MN = bin/mn
BIN = $(MN)
PYSRC = $(MININET) $(TEST) $(EXAMPLES) $(BIN)
MNEXEC = mnexec
MANPAGES = mn.1 mnexec.1
P8IGN = E251,E201,E302,E202,E126,E127,E203,E226
BINDIR = /usr/bin
MANDIR = /usr/share/man/man1
DOCDIRS = doc/html doc/latex
PDF = doc/latex/refman.pdf
CFLAGS += -Wall -Wextra
all: codecheck test
clean:
rm -rf build dist *.egg-info *.pyc $(MNEXEC) $(MANPAGES) $(DOCDIRS)
codecheck: $(PYSRC)
-echo "Running code check"
util/versioncheck.py
pyflakes $(PYSRC)
pylint --rcfile=.pylint $(PYSRC)
# Exclude miniedit from pep8 checking for now
pep8 --repeat --ignore=$(P8IGN) `ls $(PYSRC) | grep -v miniedit.py`
errcheck: $(PYSRC)
-echo "Running check for errors only"
pyflakes $(PYSRC)
pylint -E --rcfile=.pylint $(PYSRC)
test: $(MININET) $(TEST)
-echo "Running tests"
mininet/test/test_nets.py
mininet/test/test_hifi.py
slowtest: $(MININET)
-echo "Running slower tests (walkthrough, examples)"
mininet/test/test_walkthrough.py -v
mininet/examples/test/runner.py -v
mnexec: mnexec.c $(MN) mininet/net.py
cc $(CFLAGS) $(LDFLAGS) -DVERSION=\"`PYTHONPATH=. $(MN) --version`\" $< -o $@
install: $(MNEXEC) $(MANPAGES)
install $(MNEXEC) $(BINDIR)
install $(MANPAGES) $(MANDIR)
python setup.py install
develop: $(MNEXEC) $(MANPAGES)
# Perhaps we should link these as well
install $(MNEXEC) $(BINDIR)
install $(MANPAGES) $(MANDIR)
python setup.py develop
man: $(MANPAGES)
mn.1: $(MN)
PYTHONPATH=. help2man -N -n "create a Mininet network." \
--no-discard-stderr $< -o $@
mnexec.1: mnexec
help2man -N -n "execution utility for Mininet." \
-h "-h" -v "-v" --no-discard-stderr ./$< -o $@
.PHONY: doc
doc: man
doxygen doc/doxygen.cfg
make -C doc/latex
+22 -122
View File
@@ -1,132 +1,32 @@
Mininet: Rapid Prototyping for Software Defined Networks
========================================================
Mini-NDN
========
*The best way to emulate almost any network on your laptop!*
If you are new to the NDN community of software generally, read the
[Contributor's Guide](https://github.com/named-data/.github/blob/master/CONTRIBUTING.md).
Mininet 2.2.1d2
### What is Mini-NDN?
### What is Mininet?
Mini-NDN is a lightweight networking emulation tool that enables testing, experimentation, and
research on the NDN platform based on [Mininet](https://github.com/mininet/mininet).
Mini-NDN uses the NDN libraries, NFD, NLSR, and tools released by the
[NDN project](http://named-data.net/codebase/platform/) to emulate an NDN network on a single system.
Mininet emulates a complete network of hosts, links, and switches
on a single machine. To create a sample two-host, one-switch network,
just run:
Mini-NDN is open and free software licensed under the GPL 3.0 license. Mini-NDN is free to all
users and developers. For more information about licensing details and limitations,
please refer to [COPYING.md](COPYING.md).
`sudo mn`
Mininet is useful for interactive development, testing, and demos,
especially those using OpenFlow and SDN. OpenFlow-based network
controllers prototyped in Mininet can usually be transferred to
hardware with minimal changes for full line-rate execution.
### How does it work?
Mininet creates virtual networks using process-based virtualization
and network namespaces - features that are available in recent Linux
kernels. In Mininet, hosts are emulated as `bash` processes running in
a network namespace, so any code that would normally run on a Linux
server (like a web server or client program) should run just fine
within a Mininet "Host". The Mininet "Host" will have its own private
network interface and can only see its own processes. Switches in
Mininet are software-based switches like Open vSwitch or the OpenFlow
reference switch. Links are virtual ethernet pairs, which live in the
Linux kernel and connect our emulated switches to emulated hosts
(processes).
### Features
Mininet includes:
* A command-line launcher (`mn`) to instantiate networks.
* A handy Python API for creating networks of varying sizes and
topologies.
* Examples (in the `examples/` directory) to help you get started.
* Full API documentation via Python `help()` docstrings, as well as
the ability to generate PDF/HTML documentation with `make doc`.
* Parametrized topologies (`Topo` subclasses) using the Mininet
object. For example, a tree network may be created with the
command:
`mn --topo tree,depth=2,fanout=3`
* A command-line interface (`CLI` class) which provides useful
diagnostic commands (like `iperf` and `ping`), as well as the
ability to run a command to a node. For example,
`mininet> h11 ifconfig -a`
tells host h11 to run the command `ifconfig -a`
* A "cleanup" command to get rid of junk (interfaces, processes, files
in /tmp, etc.) which might be left around by Mininet or Linux. Try
this if things stop working!
`mn -c`
### New features in this release
This is primarily a performance improvement and bug fix release.
- Batch startup has been implemented for Open vSwitch, improving
startup performance.
- OVS patch links have been implemented via OVSLink and --link ovs
Warning! These links have *serious limitations* compared to
virtual Ethernet pairs: they are not attached to real Linux
interfaces so you cannot use tcpdump or wireshark with them;
they also cannot be used in long chains - we don't recommend more
than 64 OVSLinks, for example --linear,64. However, they can offer
significantly better performance than veth pairs, for certain
configurations.
- Additional information for this release and previous releases
may be found in the release notes on docs.mininet.org
### Installation
See `INSTALL` for installation instructions and details.
The first release of Mini-NDN is developed by members of the NSF-sponsored NDN project team.
Mini-NDN is open to contribution from the public.
For more details, please refer to [AUTHORS.rst](AUTHORS.rst).
Bug reports and feedback are highly appreciated and can be made through our
[Redmine site](http://redmine.named-data.net/projects/mini-ndn) and the
[mini-ndn mailing list](http://www.lists.cs.ucla.edu/mailman/listinfo/mini-ndn).
### Documentation
In addition to the API documentation (`make doc`), much useful
information, including a Mininet walkthrough and an introduction
to the Python API, is available on the
[Mininet Web Site](http://mininet.org).
There is also a wiki which you are encouraged to read and to
contribute to, particularly the Frequently Asked Questions (FAQ.)
Please refer to http://minindn.memphis.edu/ or [docs/index.rst](docs/index.rst) for installation, usage, and other documentation.
The documentation can be built using:
### Support
Mininet is community-supported. We encourage you to join the
Mininet mailing list, `mininet-discuss` at:
<https://mailman.stanford.edu/mailman/listinfo/mininet-discuss>
### Join Us
Mininet is an open source project and is currently hosted
at <https://github.com/mininet>. You are encouraged to download
the code, examine it, modify it, and submit bug reports, bug fixes,
feature requests, new features and other issues and pull requests.
Thanks to everyone who has contributed code to the Mininet project
(see CONTRIBUTORS for more info!) It is because of everyone's
hard work that Mininet continues to grow and improve.
### Enjoy Mininet
Best wishes, and we look forward to seeing what you can do with
Mininet to change the networking world!
The Mininet Core Team:
* Bob Lantz
* Brian O'Connor
* Cody Burkard
Thanks again to all of the Mininet contributors, particularly Gregory
Gee for his work on MiniEdit.
./docs/build.sh
and is available under `docs/_build/html`.
-403
View File
@@ -1,403 +0,0 @@
#!/usr/bin/env python
"""
Mininet runner
author: Brandon Heller (brandonh@stanford.edu)
To see options:
sudo mn -h
Example to pull custom params (topo, switch, etc.) from a file:
sudo mn --custom ~/mininet/custom/custom_example.py
"""
from optparse import OptionParser
import os
import sys
import time
# Fix setuptools' evil madness, and open up (more?) security holes
if 'PYTHONPATH' in os.environ:
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
from mininet.clean import cleanup
from mininet.cli import CLI
from mininet.log import lg, LEVELS, info, debug, warn, error
from mininet.net import Mininet, MininetWithControlNet, VERSION
from mininet.node import ( Host, CPULimitedHost, Controller, OVSController,
Ryu, NOX, RemoteController, findController,
DefaultController,
UserSwitch, OVSSwitch, OVSBridge,
IVSSwitch )
from mininet.nodelib import LinuxBridge
from mininet.link import Link, TCLink, OVSLink
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
from mininet.topolib import TreeTopo, TorusTopo
from mininet.util import customClass, specialClass, splitArgs
from mininet.util import buildTopo
from functools import partial
# Experimental! cluster edition prototype
from mininet.examples.cluster import ( MininetCluster, RemoteHost,
RemoteOVSSwitch, RemoteLink,
SwitchBinPlacer, RandomPlacer,
ClusterCleanup )
from mininet.examples.clustercli import ClusterCLI
PLACEMENT = { 'block': SwitchBinPlacer, 'random': RandomPlacer }
# built in topologies, created only when run
TOPODEF = 'minimal'
TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
'linear': LinearTopo,
'reversed': SingleSwitchReversedTopo,
'single': SingleSwitchTopo,
'tree': TreeTopo,
'torus': TorusTopo }
SWITCHDEF = 'default'
SWITCHES = { 'user': UserSwitch,
'ovs': OVSSwitch,
'ovsbr' : OVSBridge,
# Keep ovsk for compatibility with 2.0
'ovsk': OVSSwitch,
'ivs': IVSSwitch,
'lxbr': LinuxBridge,
'default': OVSSwitch }
HOSTDEF = 'proc'
HOSTS = { 'proc': Host,
'rt': specialClass( CPULimitedHost, defaults=dict( sched='rt' ) ),
'cfs': specialClass( CPULimitedHost, defaults=dict( sched='cfs' ) ) }
CONTROLLERDEF = 'default'
CONTROLLERS = { 'ref': Controller,
'ovsc': OVSController,
'nox': NOX,
'remote': RemoteController,
'ryu': Ryu,
'default': DefaultController, # Note: replaced below
'none': lambda name: None }
LINKDEF = 'default'
LINKS = { 'default': Link,
'tc': TCLink,
'ovs': OVSLink }
# optional tests to run
TESTS = [ 'cli', 'build', 'pingall', 'pingpair', 'iperf', 'all', 'iperfudp',
'none' ]
ALTSPELLING = { 'pingall': 'pingAll',
'pingpair': 'pingPair',
'iperfudp': 'iperfUdp',
'iperfUDP': 'iperfUdp' }
def addDictOption( opts, choicesDict, default, name, helpStr=None, **kwargs ):
"""Convenience function to add choices dicts to OptionParser.
opts: OptionParser instance
choicesDict: dictionary of valid choices, must include default
default: default choice key
name: long option name
helpStr: help string
kwargs: additional arguments to add_option"""
if not helpStr:
helpStr = ( '|'.join( sorted( choicesDict.keys() ) ) +
'[,param=value...]' )
params = dict( type='string', default=default, help=helpStr )
params.update( **kwargs )
opts.add_option( '--' + name, **params )
def version( *_args ):
"Print Mininet version and exit"
print "%s" % VERSION
exit()
class MininetRunner( object ):
"Build, setup, and run Mininet."
def __init__( self ):
"Init."
self.options = None
self.args = None # May be used someday for more CLI scripts
self.validate = None
self.parseArgs()
self.setup()
self.begin()
def custom( self, _option, _opt_str, value, _parser ):
"""Parse custom file and add params.
option: option e.g. --custom
opt_str: option string e.g. --custom
value: the value the follows the option
parser: option parser instance"""
files = []
if os.path.isfile( value ):
# Accept any single file (including those with commas)
files.append( value )
else:
# Accept a comma-separated list of filenames
files += value.split(',')
for fileName in files:
customs = {}
if os.path.isfile( fileName ):
execfile( fileName, customs, customs )
for name, val in customs.iteritems():
self.setCustom( name, val )
else:
raise Exception( 'could not find custom file: %s' % fileName )
def setCustom( self, name, value ):
"Set custom parameters for MininetRunner."
if name in ( 'topos', 'switches', 'hosts', 'controllers' ):
# Update dictionaries
param = name.upper()
globals()[ param ].update( value )
elif name == 'validate':
# Add custom validate function
self.validate = value
else:
# Add or modify global variable or class
globals()[ name ] = value
def setNat( self, _option, opt_str, value, parser ):
"Set NAT option(s)"
assert self # satisfy pylint
parser.values.nat = True
# first arg, first char != '-'
if parser.rargs and parser.rargs[ 0 ][ 0 ] != '-':
value = parser.rargs.pop( 0 )
_, args, kwargs = splitArgs( opt_str + ',' + value )
parser.values.nat_args = args
parser.values.nat_kwargs = kwargs
else:
parser.values.nat_args = []
parser.values.nat_kwargs = {}
def parseArgs( self ):
"""Parse command-line args and return options object.
returns: opts parse options dict"""
desc = ( "The %prog utility creates Mininet network from the\n"
"command line. It can create parametrized topologies,\n"
"invoke the Mininet CLI, and run tests." )
usage = ( '%prog [options]\n'
'(type %prog -h for details)' )
opts = OptionParser( description=desc, usage=usage )
addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' )
addDictOption( opts, HOSTS, HOSTDEF, 'host' )
addDictOption( opts, CONTROLLERS, [], 'controller', action='append' )
addDictOption( opts, LINKS, LINKDEF, 'link' )
addDictOption( opts, TOPOS, TOPODEF, 'topo' )
opts.add_option( '--clean', '-c', action='store_true',
default=False, help='clean and exit' )
opts.add_option( '--custom', action='callback',
callback=self.custom,
type='string',
help='read custom classes or params from .py file(s)'
)
opts.add_option( '--test', type='choice', choices=TESTS,
default=TESTS[ 0 ],
help='|'.join( TESTS ) )
opts.add_option( '--xterms', '-x', action='store_true',
default=False, help='spawn xterms for each node' )
opts.add_option( '--ipbase', '-i', type='string', default='10.0.0.0/8',
help='base IP address for hosts' )
opts.add_option( '--mac', action='store_true',
default=False, help='automatically set host MACs' )
opts.add_option( '--arp', action='store_true',
default=False, help='set all-pairs ARP entries' )
opts.add_option( '--verbosity', '-v', type='choice',
choices=LEVELS.keys(), default = 'info',
help = '|'.join( LEVELS.keys() ) )
opts.add_option( '--innamespace', action='store_true',
default=False, help='sw and ctrl in namespace?' )
opts.add_option( '--listenport', type='int', default=6634,
help='base port for passive switch listening' )
opts.add_option( '--nolistenport', action='store_true',
default=False, help="don't use passive listening " +
"port")
opts.add_option( '--pre', type='string', default=None,
help='CLI script to run before tests' )
opts.add_option( '--post', type='string', default=None,
help='CLI script to run after tests' )
opts.add_option( '--pin', action='store_true',
default=False, help="pin hosts to CPU cores "
"(requires --host cfs or --host rt)" )
opts.add_option( '--nat', action='callback', callback=self.setNat,
help="adds a NAT to the topology that"
" connects Mininet hosts to the physical network."
" Warning: This may route any traffic on the machine"
" that uses Mininet's"
" IP subnet into the Mininet network."
" If you need to change"
" Mininet's IP subnet, see the --ipbase option." )
opts.add_option( '--version', action='callback', callback=version,
help='prints the version and exits' )
opts.add_option( '--cluster', type='string', default=None,
metavar='server1,server2...',
help=( 'run on multiple servers (experimental!)' ) )
opts.add_option( '--placement', type='choice',
choices=PLACEMENT.keys(), default='block',
metavar='block|random',
help=( 'node placement for --cluster '
'(experimental!) ' ) )
self.options, self.args = opts.parse_args()
# We don't accept extra arguments after the options
if self.args:
opts.print_help()
exit()
def setup( self ):
"Setup and validate environment."
# set logging verbosity
if LEVELS[self.options.verbosity] > LEVELS['output']:
print ( '*** WARNING: selected verbosity level (%s) will hide CLI '
'output!\n'
'Please restart Mininet with -v [debug, info, output].'
% self.options.verbosity )
lg.setLogLevel( self.options.verbosity )
# Maybe we'll reorganize this someday...
# pylint: disable=too-many-branches,too-many-statements
def begin( self ):
"Create and run mininet."
if self.options.cluster:
servers = self.options.cluster.split( ',' )
for server in servers:
ClusterCleanup.add( server )
if self.options.clean:
cleanup()
exit()
start = time.time()
if not self.options.controller:
# Update default based on available controllers
CONTROLLERS[ 'default' ] = findController()
self.options.controller = [ 'default' ]
if not CONTROLLERS[ 'default' ]:
self.options.controller = [ 'none' ]
if self.options.switch == 'default':
info( '*** No default OpenFlow controller found '
'for default switch!\n' )
info( '*** Falling back to OVS Bridge\n' )
self.options.switch = 'ovsbr'
elif self.options.switch not in ( 'ovsbr', 'lxbr' ):
raise Exception( "Could not find a default controller "
"for switch %s" %
self.options.switch )
topo = buildTopo( TOPOS, self.options.topo )
switch = customClass( SWITCHES, self.options.switch )
host = customClass( HOSTS, self.options.host )
controller = [ customClass( CONTROLLERS, c )
for c in self.options.controller ]
link = customClass( LINKS, self.options.link )
if self.validate:
self.validate( self.options )
ipBase = self.options.ipbase
xterms = self.options.xterms
mac = self.options.mac
arp = self.options.arp
pin = self.options.pin
listenPort = None
if not self.options.nolistenport:
listenPort = self.options.listenport
# Handle inNamespace, cluster options
inNamespace = self.options.innamespace
cluster = self.options.cluster
if inNamespace and cluster:
print "Please specify --innamespace OR --cluster"
exit()
Net = MininetWithControlNet if inNamespace else Mininet
cli = ClusterCLI if cluster else CLI
if cluster:
warn( '*** WARNING: Experimental cluster mode!\n'
'*** Using RemoteHost, RemoteOVSSwitch, RemoteLink\n' )
host, switch, link = RemoteHost, RemoteOVSSwitch, RemoteLink
Net = partial( MininetCluster, servers=servers,
placement=PLACEMENT[ self.options.placement ] )
mn = Net( topo=topo,
switch=switch, host=host, controller=controller,
link=link,
ipBase=ipBase,
inNamespace=inNamespace,
xterms=xterms, autoSetMacs=mac,
autoStaticArp=arp, autoPinCpus=pin,
listenPort=listenPort )
if self.options.ensure_value( 'nat', False ):
nat = mn.addNAT( *self.options.nat_args,
**self.options.nat_kwargs )
nat.configDefault()
if self.options.pre:
cli( mn, script=self.options.pre )
test = self.options.test
test = ALTSPELLING.get( test, test )
mn.start()
if test == 'none':
pass
elif test == 'all':
mn.waitConnected()
mn.start()
mn.ping()
mn.iperf()
elif test == 'cli':
cli( mn )
elif test != 'build':
mn.waitConnected()
getattr( mn, test )()
if self.options.post:
cli( mn, script=self.options.post )
mn.stop()
elapsed = float( time.time() - start )
info( 'completed in %0.3f seconds\n' % elapsed )
if __name__ == "__main__":
try:
MininetRunner()
except KeyboardInterrupt:
info( "\n\nKeyboard Interrupt. Shutting down and cleaning up...\n\n")
cleanup()
except Exception:
# Print exception
type_, val_, trace_ = sys.exc_info()
errorMsg = ( "-"*80 + "\n" +
"Caught exception. Cleaning up...\n\n" +
"%s: %s\n" % ( type_.__name__, val_ ) +
"-"*80 + "\n" )
error( errorMsg )
# Print stack trace to debug log
import traceback
stackTrace = traceback.format_exc()
debug( stackTrace + "\n" )
cleanup()
-6
View File
@@ -1,6 +0,0 @@
This directory should hold configuration files for custom mininets.
See custom_example.py, which loads the default minimal topology. The advantage of defining a mininet in a separate file is that you then use the --custom option in mn to run the CLI or specific tests with it.
To start up a mininet with the provided custom topology, do:
sudo mn --custom custom_example.py --topo mytopo
-34
View File
@@ -1,34 +0,0 @@
"""Custom topology example
Two directly connected switches plus a host for each switch:
host --- switch --- switch --- host
Adding the 'topos' dict with a key/value pair to generate our newly defined
topology enables one to pass in '--topo=mytopo' from the command line.
"""
from mininet.topo import Topo
class MyTopo( Topo ):
"Simple topology example."
def __init__( self ):
"Create custom topo."
# Initialize topology
Topo.__init__( self )
# Add hosts and switches
leftHost = self.addHost( 'h1' )
rightHost = self.addHost( 'h2' )
leftSwitch = self.addSwitch( 's3' )
rightSwitch = self.addSwitch( 's4' )
# Add links
self.addLink( leftHost, leftSwitch )
self.addLink( leftSwitch, rightSwitch )
self.addLink( rightSwitch, rightHost )
topos = { 'mytopo': ( lambda: MyTopo() ) }
-33
View File
@@ -1,33 +0,0 @@
mininet (2.1.0-0ubuntu1) saucy; urgency=low
* Add 2.1.0 final packaging
-- Bob Lantz <rlantz@cs.stanford.edu> Wed, 18 Sep 2013 22:43:47 -0700
mininet (2.1.0~rc1-0ubuntu1) saucy; urgency=low
* New upstream release candidate:
- d/control: Drop dependency on python-networkx, add iperf, socat
and cgroup-bin to Depends.
-- James Page <james.page@ubuntu.com> Wed, 28 Aug 2013 10:10:20 +0100
mininet (2.0.0-0ubuntu1) raring; urgency=low
* New upstream release.
-- James Page <james.page@ubuntu.com> Wed, 19 Dec 2012 15:48:01 +0000
mininet (2.0.0~rc1-0ubuntu1) quantal; urgency=low
* New upstream release.
* Update copyright to match upstream release
* Fix this message
-- Bob Lantz <rlantz@cs.stanford.edu> Sun, 18 Nov 2012 00:15:09 -0800
mininet (2.0.0~d4-0ubuntu1) quantal; urgency=low
* Initial release.
-- Bob Lantz <rlantz@cs.stanford.edu> Tue, 07 Aug 2012 14:11:27 -0700
-1
View File
@@ -1 +0,0 @@
9
-31
View File
@@ -1,31 +0,0 @@
Source: mininet
Section: net
Priority: extra
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
XSBC-Original-Maintainer: Bob Lantz <rlantz@cs.stanford.edu>
Standards-Version: 3.9.3
Build-Depends:
debhelper (>= 9~),
help2man,
python-dev,
python-pkg-resources,
python-setuptools
Homepage: http://openflow.org/mininet
Package: mininet
Architecture: any
Depends:
openvswitch-switch,
telnet,
socat,
iperf,
cgroup-bin,
${misc:Depends},
${python:Depends},
${shlibs:Depends}
Recommends: openvswitch-controller
Description: Process-based network emulator
Mininet is a network emulator which uses lightweight
virtualization to create virtual networks for rapid
prototyping of Software-Defined Network (SDN) designs
using OpenFlow.
-37
View File
@@ -1,37 +0,0 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
Upstream-Name: mininet
Source: https://github.com/mininet/mininet
Files: *
Copyright: 2012-2013 Open Networking Laboratory,
2009-2012 Bob Lantz,
2009-2012 The Board of Trustees of the Leland Stanford Junior
University
License:
Original authors: Bob Lantz and Brandon Heller
.
We are making Mininet available for public use and benefit with the
expectation that others will use, modify and enhance the Software and
contribute those enhancements back to the community. However, since we
would like to make the Software available for broadest use, with as few
restrictions as possible permission is hereby granted, free of charge, to
any person obtaining a copy of this Software to deal in the Software
under the copyrights without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
.
The name and trademarks of copyright holder(s) may NOT be used in
advertising or publicity pertaining to the Software or any derivatives
without specific, written prior permission.
Vendored
-1
View File
@@ -1 +0,0 @@
README.md
-1
View File
@@ -1 +0,0 @@
examples/*
-1
View File
@@ -1 +0,0 @@
mnexec /usr/bin
-1
View File
@@ -1 +0,0 @@
*.1
-12
View File
@@ -1,12 +0,0 @@
#!/usr/bin/make -f
%:
dh $@ --buildsystem=python_distutils --with=python2
override_dh_auto_build:
make man
make mnexec
dh_auto_build
get-orig-source:
uscan --force-download --rename
-1
View File
@@ -1 +0,0 @@
3.0 (quilt)
-3
View File
@@ -1,3 +0,0 @@
version=3
opts=filenamemangle=s/(.*)\/archive/$1/,uversionmangle=s/([abdr].*)\.tar\.gz/~$1/ \
https://github.com/mininet/mininet/tags .*/archive\/(\d.*\.tar\.gz)
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# set python3 alias, but needs permanent fix in image directly
alias python=python3
service openvswitch-switch start
ovs-vsctl set-manager ptcp:6640
bash
service openvswitch-switch stop
+35
View File
@@ -0,0 +1,35 @@
[comments]: The original author of Mini-NDN docker is Md Ashiqur Rahman (marahman@email.arizona.edu)
## Running Mini-NDN inside Docker
You can use the nightly build from GitHub package registry
```bash
docker run -m 4g --cpus=4 -it --privileged \
-v /lib/modules:/lib/modules \
ghcr.io/named-data/mini-ndn:master bash
```
## Building your own image
The Dockerfile can be used directly to `build` an image from scratch.
* Build with `Dockerfile`:
* Clone the repository and type.
```bash
docker build -t minindn .
```
* You can then access the container through shell with,
```bash
docker run -m 4g --cpus=4 -it --privileged \
-v /lib/modules:/lib/modules \
minindn bin/bash
```
### Notes:
* Memory (-m), CPU (--cpus) are recommended by Mini-NDN.
* `--privileged` is mandatory for underlying [Mininet](http://mininet.org/) to utilize virtual switch
* Root directory on `run` is `/mini-ndn` containing the installation and examples.
* GUI may not work for now due to docker and xterm setup issues and is independent from Mini-NDN.
If you intend to run the GUI, pass `-e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix` to the `docker run` command.
+20
View File
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+1
View File
@@ -0,0 +1 @@
.. include:: ../AUTHORS.rst
Executable
+36
View File
@@ -0,0 +1,36 @@
#!/bin/bash
# -*- Mode:bash; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
set -eo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
PIP='python3 -m pip'
for PIPPKG in sphinx sphinx_rtd_theme; do
if ! $PIP show $PIPPKG >/dev/null; then
sudo $PIP install $PIPPKG
fi
done
make clean html
+61
View File
@@ -0,0 +1,61 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
from datetime import datetime
from minindn import __version__
# -- Project information -----------------------------------------------------
project = 'Mini-NDN'
copyright = '2015-{}, Mini-NDN. This research is partially supported by NSF.'.format(datetime.now().year)
author = 'Mini-NDN'
# The full version, including alpha/beta/rc tags
release = __version__
version = __version__
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Need to specify the line below if custom conf.py
# https://github.com/readthedocs/readthedocs.org/issues/2569
# https://stackoverflow.com/questions/56336234/build-fail-sphinx-error-contents-rst-not-found
master_doc = 'index'
+274
View File
@@ -0,0 +1,274 @@
Experiment
==========
Configuration
-------------
Mini-NDN uses a configuration file describing the topology and its parameters to setup a network.
The [nodes] section:
At the bare minimum, the node section describes the nodes present in the
topology.
::
[nodes]
a: key1=value1 key2=value2
b: key1=value1
Any key and value passed here is accessible in Mini-NDN as:
::
ndn = Minindn(...)
value = ndn.net.hosts[0].params['params'].get('key1', "defaultValue")
One can specify log levels for each node's NFD and NLSR using this key-value system:
::
[nodes]
a: nfd-log-level=DEBUG nlsr-log-level=DEBUG
b: nfd-log-level=INFO
To specify a log level for certain modules of NFD, the following line can be added to `nfd.py`:
::
node.cmd('infoedit -f {} -s log.Forwarder -v {}'.format(self.confFile, 'INFO'))
This will turn on FORWARDER logging to INFO for all nodes.
.. Todo: Add switch section
The [links] section:
The links section describes the links in the topology.
::
e.g.)
[links]
a:b delay=10ms
This would create a link between a and b. 'b:a' would also result in the
same. The following parameters can be configured for a node:
- delay : Delay parameter is a required parameter which defines the
delay of the link (1-1000ms)
- bw : Bandwidth of a link (<1-1000> Mbps)
- loss : Percentage of packet loss (<1-100>)
Example configuration file
::
[nodes]
a:
b:
[links]
a:b delay=10ms bw=100
See ``ndn_utils/topologies`` for more sample files
Sample
------
Sample experiment may written as follows:
.. code:: python
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.appmanager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.helpers.routing_helper import IPRoutingHelper
if __name__ == '__main__':
setLogLevel('info')
Minindn.cleanUp()
Minindn.verifyDependencies()
# Can pass a custom parser, custom topology, or any Mininet params here
ndn = Minindn()
ndn.start()
# IP reachability if needed
# IPRoutingHelper.calcAllRoutes(ndn.net)
# info("IP routes configured, start ping\n")
# ndn.net.pingAll()
# Start apps with AppManager which registers a clean up function with ndn
info('Starting NFD on nodes\n')
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
info('Starting NLSR on nodes\n')
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
# or can not start NLSRs with some delay in between:
# nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
# for host in ndn.net.hosts:
# nlsrs.startOnNode(host)
# time.sleep(30)
MiniNDNCLI(ndn.net)
# Calls the clean up functions registered via AppManager
ndn.stop()
Users may look at how the NFD and NLSR applications are written as a sub class of Application
in the ``minindn/apps`` folder. Or users may choose to directly run their application on nodes
such as ndnpingserver is run in ``minindn/helpers/experiment.py``.
**Note:** A certain log-level can be set-up for all the NFD or NLSR nodes at once by passing it as an argument during the startup.
``nfds = AppManager(self.ndn, self.ndn.net.hosts, Nfd, logLevel='DEBUG')`` (same for NLSR)
Execution
---------
To run Mini-NDN with the default topology,
``ndn_utils/topologies/default-topology.conf``, type:
::
sudo python examples/minindn.py
To run Mini-NDN with a topology file, provide the filename as the first
argument:
::
sudo python examples/minindn.py my-topology.conf
After Mini-NDN is installed, users can run examples from anywhere with python directly as follows:
::
sudo python /path/to/myexample.py
The user no longer needs to create an experiment in the old Mini-NDN way, then install it to the system before executing it via the minindn binary. The new examples can be separate from the Mini-NDN folder if the core is not being modified.
CLI Interface
_____________
During set up, the list of nodes in the network will be listed as they
are initialized:
::
*** Adding hosts:
a b c d
After set up, the command-line interface (CLI) will display a prompt.
::
mini-ndn>
To interact with a node, first type the node's name and then the command
to be executed:
::
mini-ndn> a echo "Hello, world!"
Hello, world!
To see the status of the forwarder on the node:
::
mini-ndn> a nfdc status report
To see the status of routing on the node:
::
mini-ndn> a nlsrc status
To exit Mini-NDN, type ``quit`` in the CLI or use ``ctrl + D``:
::
mini-ndn> quit
``Ctrl + C`` is used to quit an application run in the foreground of the command line.
For a more in depth explanation of the CLI, please see the `Mininet
Walkthrough <http://mininet.org/walkthrough/>`__.
To run NDN commands from the outside the command line user can also open a new terminal
and export the HOME folder of a node ``export HOME=/tmp/minindn/a && cd ~``
Working Directory Structure
---------------------------
Currently Mini-NDN uses /tmp/minindn as the working directory if not
specified otherwise by using the option --work-dir.
Each node is given a HOME directory under /tmp/minindn/<node-name> where
<node-name> is the name of the node specified in the [nodes] section of
the conf file.
NFD
___
- NFD conf file is stored at ``/tmp/minindn/<node-name>/nfd.conf``
- NFD log file is stored at ``/tmp/minindn/<node-name>/log/nfd.log``
- ``.ndn`` folder is stored at ``/tmp/minindn/<node-name>/.ndn``
NLSR
____
- NLSR conf file is stored at ``/tmp/minindn/<node-name>/nlsr.conf``
- NLSR log file is stored at ``/tmp/minindn/<node-name>/log/nlsr.log``
When security is enabled, NLSR security certificates are stored in:
``/tmp/minindn/<node-name>/security`` Note that no NLSR publishes the root
certificate, Mini-NDN installs root.cert in security folder for each
NLSR.
While a host's NLSR neighbors are by default populated by adjacent nodes in wired scenarios,
for those running NLSR on wifi stations it is required that you specify "neighbor" faces
manually. The framework for this is provided either via a dictionary object or through
additional sections in topology files, and may also be used for wired experiments.
See an example of a topo of this sort in ``mini-ndn/topologies/wifi/nlsr_wifi_example.conf``.
NLSR faces to be created can be manually specified from topology files in a ``[faces]``
section, with the format ``nodeA:nodeB [cost=X]``. You should then call the ``setupFaces()``
method of an initialized Mini-NDN object to get a dictionary based on this parse in the format
``faceA:[(faceB, cost), (faceC, cost),...]``, which can finally be passed to the NLSR
helper via the faceDict parameter. An example experiment using this methodology is located
at ``mini-ndn/examples/wifi/nlsr_wifi.py``. Note that the aforementioned dict can also be
created manually in the previously established format.
Routing Options
----------------
Link State Routing (NLSR)
_________________________
By default, Mini-NDN uses `NLSR <https://github.com/named-data/NLSR>`__ for route management i.e route computation, route installation and so on. Additionally, the command line utility ``nlsrc`` can be used to advertise and withdraw prefixes and route status.
NDN Routing Helper
____________________
Computes link-state or hyperbolic route/s from a given minindn topology and installs them in the FIB. The major benefit of the routing helper is to eliminate the overhead of NLSR when using larger topology. See ``examples/static_routing_experiment.py`` on how to use the helper class.
**IMPORTANT:** NLSR and NDN Routing Helper are mutually exclusive, meaning you can only use one at a time, not both.
**Note:** The current version of ``ndn_routing_helper`` is still in the experimental phase. It doesn't support node or link failure and runtime prefix advertisement/withdrawal. If you find any bug please report `here <https://redmine.named-data.net/projects/mini-ndn>`__ or contact the :doc:`authors <authors>`.
IP Routing Helper
____________________
The routing helper allows to run IP-based evaluations with Mini-NDN. It configures static IP routes to all nodes, which means that all nodes can reach all other nodes in the network
reachable, even when relaying is required. Please see ``examples/ip_rounting_experiment.py`` for a simple example.
+48
View File
@@ -0,0 +1,48 @@
FAQ
=========
* ``How does Mini-NDN work?``
Mini-NDN's principles of operation most heavily rely on the underlying Mininet code it relies on.
Mininet uses a combination of limited containerization via network namespaces (which give processes
isolated interfaces and routing tables) and emulated ethernet connections via veth connections.
In practical terms, Mini-NDN ensures that processes running on distinct nodes will run seperately
and without interfering with each other.
* ``How does Mini-NDN apply link loss/delay/etc.?``
Mini-NDN relies on Mininet's code, which in turn uses the Linux tc utility on a stations' virtualized
interfaces to apply configurations known as qdiscs to these links. Note that these will only be applied
on egress packets from a station where it's applied.
For more information on qdiscs and tc, view the information `here <http://wiki.linuxwall.info/doku.php/en%3aressources%3adossiers%3anetworking%3atraffic_control>`_.
* ``Why use Mini-NDN rather than a simulator such as ndnSIM?``
Mini-NDN is easier and faster to use because, rather than serving as a mathematical model of a network,
it is instead running real NDN code on a real Linux kernel. This also means it's quite useful for testing code changes, as it can more accurately test the interaction of software componenents.
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Criteria | Mini-NDN | ndnSIM |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Based On | Mininet | ns-3 |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Language | Python | C++ |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Library/Forwarder/Applications | Use system binaries (free to use any compatible versions) | Integrated (fixed release version) |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Application language | C++ (ndn-cxx), CCL (ndn-cpp, PyNDN, ndn-js, jNDN) | C++ (ndn-cxx) |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Simulation size | Medium - Large (cluster edition in development) | Large (can be parallelized using MPI) |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Simulation time | Real time | Quick (depending on size/memory) |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Porting real applications | Drop in | Changes required |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Interactivity | Can interact directly with NFD, NLSR or Apps | Can show stats while running |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Logs | May need to manually setup to collect | Available with tracer |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Post processing scripts | Not available, users need to write their own | Available to use to process the logs |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
| Other | Not yet supported (Wifi in development) | WiFi, LTE, etc available from ns-3 |
+--------------------------------+-----------------------------------------------------------+-----------------------------------------+
+10
View File
@@ -0,0 +1,10 @@
Past NDN Hackathon projects
===========================
- 1st NDN Hackathon: `NFD integration test <http://ndncomm.github.io/mini-ndn/>`_.
- 2st NDN Hackathon: `Mini-NDN metrics <https://github.com/2nd-ndn-hackathon/mini-ndn-metrics>`_.
- 3rd NDN Hackathon: `Mini-NDN cluster <https://github.com/3rd-ndn-hackathon/mini-NDN-cluster>`_.
- 4th NDN Hackathon: `Mini-NDN wifi <https://github.com/4th-ndn-hackathon/Mini-NDN-Wi-Fi>`_.
- 7th NDN Hackathon: `Mini-NDN documentation <https://github.com/7th-ndn-hackathon/mini-ndn-documentation>`_.
- 11th NDN Hackathon: `Mini-NDN improvements <https://11th-ndn-hackathon.named-data.net/hacks.html#8-mini-ndn-improvements>`_.
- 12th NDN Hackathon: `Mini-NDN improvements and Refactoring <https://12th-ndn-hackathon.named-data.net/hacks.html#7-mini-ndn-improvements>`_.
+128
View File
@@ -0,0 +1,128 @@
Howtos
======
Connect Mini-NDN nodes to an outside network
---------------------------------------------
Mini-NDN nodes can be connected to an outside network indirectly by
running NFD on the local machine:
::
(Mini-NDN node) ------ (NFD running on the host machine where Mini-NDN is running) ------- (External Network)
Add a node in root namespace
____________________________
For this simple example, we can use a single node topology with node 'a'
If we want node 'a' to connect to the host machine, we need to add a
"root" node which has a link with node "a."
Then the following code can be used:
.. code:: python
topo = Topo()
root = topo.addHost('root', inNamespace=False)
a = topo.addHost('a')
topo.addLink(root, a, delay='10ms')
ndn = Minindn(topo=topo)
...
Configuration
_____________
Run Mini-NDN with the above code and issue ifconfig on the local
machine to confirm the addition of the interface. You should be able to
locate "root-eth0":
::
root-eth0 Link encap:Ethernet HWaddr 3e:eb:77:d2:6f:1f
inet addr:1.0.0.9 Bcast:1.0.0.11 Mask:255.255.255.252
inet6 addr: fe80::3ceb:77ff:fed2:6f1f/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:34 errors:0 dropped:0 overruns:0 frame:0
TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2667 (2.6 KB) TX bytes:2797 (2.7 KB)
To make the IP address associated with this interface persistent, add
the following line to /etc/network/interfaces and reboot your machine:
::
iface root-eth0 inet manual
Check connection
________________
After rebooting, run Mini-NDN and issue the following command:
::
mini-ndn>net
a a-eth0:b-eth0 a-eth1:c-eth0 a-eth2:root-eth0
Node "a" is connected to "root-eth0". Now issue "ifconfig a-eth2" on
node "a":
::
mini-ndn>a ifconfig a-eth2
a-eth2 Link encap:Ethernet HWaddr fa:76:d4:86:d3:ba
inet addr:1.0.0.10 Bcast:1.0.0.11 Mask:255.255.255.252
As learned from the previous step, the IP address of root-eth0 is
1.0.0.9.
::
mini-ndn>a ping 1.0.0.9
PING 1.0.0.9 (1.0.0.9) 56(84) bytes of data.
64 bytes from 1.0.0.9: icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from 1.0.0.9: icmp_seq=2 ttl=64 time=0.123 ms
The host machine will also be able to ping node "a":
::
VirtualBox:~$ ping 1.0.0.10
PING 1.0.0.10 (1.0.0.10) 56(84) bytes of data.
64 bytes from 1.0.0.10: icmp_seq=1 ttl=64 time=0.086 ms
Run NFD on local machine and register route
___________________________________________
Start NFD on the local machine by using:
::
sudo nfd
The "nfd-start" script cannot be used, since the script allows only one
instance of NFD at a time. The NFD processes running on the Mini-NDN
nodes will prevent the "nfd-start" script from working.
Now, using "nfdc register", we can register a route from node "a" in
Mini-NDN to the NFD process on the host machine and from the host
machine to an external machine.
Also, if the local machine has a public IP, Mini-NDN nodes can be
reached via external machines.
Generate NDN testbed topology
___________________________________________
Run the following install.sh command
::
python3 util/testbed_topo_generator.py
This will place a "testbed.conf" file in the topologies subdirectory,
where it can be referenced as desired. To update the topology, simply
rerun this command.
+30
View File
@@ -0,0 +1,30 @@
.. Mini-NDN documentation master file, created by
sphinx-quickstart on Mon Sep 23 11:15:54 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Mini-NDN: A Mininet-based NDN emulator
======================================
.. toctree::
:maxdepth: 2
:caption: Contents
introduction
install
experiment
howtos
release-notes
faq
hackathon
videos
Helpful Links
-------------
* `NDN Website <http://named-data.net/>`_
* `NDN Contributor's Guide <https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md>`_
* `Mininet Documentation <http://mininet.org/>`_
* `Mini-NDN redmine <https://redmine.named-data.net/projects/mini-ndn>`_
* `Mailing list <http://www.lists.cs.ucla.edu/mailman/listinfo/mini-ndn>`_
* :doc:`Mini-NDN Team <authors>`
+184
View File
@@ -0,0 +1,184 @@
Install
=======
Prerequisites
-------------
Mini-NDN is tested on the following Linux distributions:
- Ubuntu 20.04 (recommended)
- Ubuntu 22.04
- Debian 11 (WiFi scenario does not work)
- Fedora 33 (WiFi scenario does not work)
You must have sudo privileges to install and run Mini-NDN.
Using Vagrantfile
-----------------
With Vagrant installed, simply do ``vagrant up`` which will bring up an Ubuntu 18.04 virtual machine
and install Mini-NDN and all its dependencies on it. Please make sure to tweak the CPU core count
(default 4 cores) and RAM (default 4GB) according to your needs before doing vagrant up. Mini-NDN
can be found in /home/vagrant/mini-ndn which is a symlink to /vagrant if Vagrantfile was used from within mini-ndn cloned on the host. Otherwise it is an actual clone of mini-ndn.
Using install.sh
----------------
Mini-NDN has the following dependencies:
- `NDN Forwarding Daemon (NFD) <https://named-data.net/doc/NFD/>`_
- `Named Data Link State Routing (NLSR) <https://named-data.net/doc/NLSR/>`_
- `NDN Essential Tools (ndn-tools) <https://github.com/named-data/ndn-tools>`_
- `NDN Traffic Generator <https://github.com/named-data/ndn-traffic-generator>`_
- `infoedit <https://github.com/NDN-Routing/infoedit>`_
- `Mininet <http://mininet.org/>`_
- `Mininet-WiFi <https://mininet-wifi.github.io/>`_ (optional)
To install Mini-NDN and its dependencies, clone this repository and run:
::
./install.sh
The script accepts various command line flags.
Some notable flags are:
- ``-y`` skips interactive confirmation before installation.
- ``--ppa`` prefers installing NDN software from `named-data PPA <https://launchpad.net/~named-data/+archive/ubuntu/ppa>`_.
This shortens installation time by downloading binary packages, but is only available on Ubuntu.
- ``--source`` prefers installing NDN software from source code.
IMPORTANT: For now, Mininet-WiFi only works with ``--source`` installation because the current NFD release (0.7.1) doesn't
incorporate `issue 5155 <https://redmine.named-data.net/issues/5155>`, a required patch for WiFi module to work properly.
With the next NFD release, Mininet-WiFi will work with both ``source`` and ``ppa``. Alternatively, you can
checkout (at your own risk) a third-party source "`Use NFD nightly with Mini-NDN <https://yoursunny.com/t/2021/NFD-nightly-minindn/>`", which provides
NFD-nightly version and contains all the necessary patches.
- ``--dummy-keychain`` patches ndn-cxx to use an in-memory dummy KeyChain, which reduces CPU overhead
and allows you to scale up Mini-NDN experiments. Large Mini-NDN experiments would run significantly
faster after applying this patch. However, your experiments cannot use any NDN security related
features (signatures, verifier, access control, etc).
- ``--no-wifi`` skips Mininet-WiFi dependency.
Currently Mininet-WiFi only works on Ubuntu, so that you must specify this option when installing on other distros.
You can see all command line flags by running:
::
./install.sh -h
The script uses ``setup.py develop`` to point the system install of Python packages to the codebase
directory. Therefore, you can modify ``mininet``, ``mininet-wifi``, and ``mini-ndn``, and the
changes will be reflected immediately.
If NDN software is installed from source code (not PPA), the code is downloaded to ``dl`` directory
under your ``mini-ndn`` clone. If you modify the source code, you need to manually recompile and
reinstall the software (``./waf && sudo ./waf install``).
Installing Dependencies
-----------------------
This section outlines how to install dependnecies manually.
If you used ``install.sh``, you do not need to perform these steps.
Mininet
_______
Mini-NDN is based on Mininet. To install Mininet:
::
git clone --depth 1 https://github.com/mininet/mininet.git
After Mininet source is on your system, run the following command to
install Mininet core dependencies and Open vSwitch:
::
./util/install.sh -nv
To check if Mininet is working correctly, run this test:
::
sudo mn --test pingall
This will print out a series of statements that show the test setup and
the results of the test. Look for ``Results:`` two-thirds of the way
down where it will indicate the percentage of dropped packets. Your
results should show "0% dropped (2/2 received)".
NOTE: Mini-NDN, while providing a high level of emulation of hosts,
requires programs to be installed onto your computer. It will not work
if they are not installed. If you do not want NDN software installed
onto your computer, you can use a virtual machine, which can be quite
simply set up with the provided Vagrantfile.
NDN dependencies
________________
Each node in Mini-NDN will run the official implementation of NDN
installed on your system. The following dependencies are needed:
Mini-NDN uses NFD, NLSR, and ndn-tools.
- To install NFD: https://named-data.net/doc/NFD/current/INSTALL.html
- To install NLSR: https://named-data.net/doc/NLSR/current/INSTALL.html
- To install ndn-tools: https://github.com/named-data/ndn-tools
.. warning::
Please do not try to install NDN software from both the source (GitHub) and PPA (apt).
It will not work in most cases! If you used ./install.sh -a in the past but now want
to use apt, please run ``sudo ./waf uninstall`` in all the NDN projects before proceeding
with apt. Similarly, remove from apt if switching to source.
Please see the :ref:`scaling-note <scaling-note>` to learn about disabling
security for better scalability.
Note that all three of these can be installed from the Named Data PPA.
Instructions for setting it up can be found in the NFD installation
instructions. Note that PPA and installs from source **cannot** be
mixed. You must completely remove PPA installs from the system if switching
to source and vice-versa.
For PPA installs, if you are using a custom nfd.conf file in an experiment, you should
place it in /usr/local/etc/ndn/ rather than /etc/ndn/. This is to avoid
a bug from the default configuration file for the PPA, which is
incompatible with Mini-NDN.
Infoedit
________
Infoedit is used to edit configuration files for NFD and NLSR.
To install infoedit:
::
git clone --depth 1 https://github.com/NDN-Routing/infoedit
cd infoedit
make
sudo make install
Verification
------------
You can execute the following example to bring up the Mini-NDN command line
with NFD and NLSR running on each node:
::
sudo python examples/mnndn.py
You can use these steps to run the sample pingall experiment:
1. Issue the command: ``sudo python examples/nlsr/pingall.py``
2. When the ``mini-ndn>`` CLI prompt appears, the experiment has
finished. On the Mini-NDN CLI, issue the command ``exit`` to exit the
experiment.
3. Issue the command:
``grep -c content /tmp/minindn/*/ping-data/*.txt``. Each file should
report a count of 50.
4. Issue the command:
``grep -c timeout /tmp/minindn/*/ping-data/*.txt``. Each file should
report a count of 0.
+40
View File
@@ -0,0 +1,40 @@
Introduction
=================
If you are new to the NDN community of software generally, read the
`Contributor's Guide <https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md>`_.
What is Mini-NDN?
-----------------
Mini-NDN is a lightweight networking emulation tool that enables testing, experimentation, and
research on the NDN platform. It was initially based on `Mini-CCNx <https://github.com/chesteve/mn-ccnx>`_ which was a fork of `Mininet <https://github.com/mininet/mininet>`_. Mini-NDN uses the NDN libraries, NFD, NLSR, and tools released by the `NDN project <http://named-data.net/codebase/platform/>`_ to emulate an NDN network on a single system.
The first release of Mini-NDN is developed by members of the NSF-sponsored NDN project team.
Mini-NDN is open to contribution from the public.
.. image:: minindnnet.svg
License
_______
Mini-NDN is open and free software licensed under the GPL 3.0 license. Mini-NDN is free to all
users and developers. For more information about licensing details and limitations,
please refer to COPYING.md.
Feedback/Mailing List
_____________________
Bug reports and feedback are highly appreciated and can be made through our
`Redmine site <http://redmine.named-data.net/projects/mini-ndn>`_ and the
`mini-ndn mailing list <http://www.lists.cs.ucla.edu/mailman/listinfo/mini-ndn>`_.
Video
_____
.. raw:: html
<div id="video-container" class="col-md-6 ">
<p>Mini-NDN (content maybe outdated)</p>
<iframe width="600" height="345" src="https://www.youtube.com/embed/UxHPqaUwefg" frameborder="0" allowfullscreen=""></iframe>
</div>
+126
View File
@@ -0,0 +1,126 @@
<svg width="692" height="380" xmlns="http://www.w3.org/2000/svg">
<metadata id="metadata7">image/svg+xml</metadata>
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="382" width="694" y="-1" x="-1"/>
</g>
<g>
<title>Layer 1</title>
<g stroke="null" id="g3790">
<rect stroke="#000000" fill="#ffffff" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" id="rect2985" width="680.84682" height="350.443392" x="4.962804" y="5.773119" rx="0.324652"/>
<path stroke="#000000" fill="none" stroke-miterlimit="4" d="m4,175.828501l681.727736,1.357954" id="path3770"/>
</g>
<rect stroke="#000000" fill="#e3dedb" stroke-width="0.99538" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" rx="2.988095" y="176.111777" x="5.140841" height="180.524655" width="680.312936" id="rect3813"/>
<rect stroke="#000000" fill="#ffffff" stroke-width="1.602133" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dasharray="4.80639973, 4.80639973" stroke-dashoffset="0" ry="8.582684" rx="7.476771" y="44.78072" x="55.492192" height="195.219243" width="148.366914" id="rect3764"/>
<rect stroke="#000000" fill="#ffffff" stroke-width="1.638042" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dasharray="4.9141253, 4.9141253" stroke-dashoffset="0" id="rect3772" width="155.115252" height="195.190135" x="270.220868" y="46.153231" rx="7.816845" ry="8.581405"/>
<rect stroke="#000000" fill="#ffffff" stroke-width="1.602133" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dasharray="4.80639973, 4.80639973" stroke-dashoffset="0" ry="8.582684" rx="7.476771" y="45.459696" x="489.86568" height="195.219243" width="148.366914" id="rect3774"/>
<text transform="matrix(1.0192718802397343,0,0,0.9115536073383187,-2.8313337784806336,-12.183034089773187) " font-size="16.005802px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3776" y="392.709737" x="551.171304" xml:space="preserve">
<tspan stroke="null" font-weight="normal" y="398.194877" x="552.152396" id="tspan3778">Kernel Space</tspan>
</text>
<text transform="matrix(1.0524848569125234,0,0,0.8827879284304422,-52.30106698198968,-77.5201889102731) " font-size="14.180006px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="601.466013" y="108.524983" id="text3782">
<tspan stroke="null" font-weight="normal" id="tspan3784" x="602.416145" y="114.188857">User Space</tspan>
</text>
<path stroke="#000000" fill="none" stroke-width="1px" id="path3796" d="m488.56554,176.773764c1.782236,0.480113 1.527628,0.360085 1.527628,0.360085"/>
<rect stroke="#000000" fill="#ffffff" stroke-width="0.649807" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" rx="0.838801" y="202.851471" x="84.255138" height="26.434283" width="94.537572" id="rect3815"/>
<rect stroke="#000000" fill="#ffffff" stroke-width="0.792138" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" id="rect3817" width="131.339764" height="28.275376" x="282.077514" y="201.912133" rx="1.165334"/>
<path stroke="#000000" fill="none" stroke-width="0.865499px" id="path3823" d="m347.74739,201.086282l0,28.351986"/>
<text transform="matrix(0.7776670647796514,0,0,1.19475416519067,-52.30106724263901,-77.52018902784596) " font-size="12.623897px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="434.634023" y="248.956571" id="text3835">
<tspan stroke="null" font-size="15.579311px" font-weight="bold" font-family="Monospace" x="435.91992" y="253.141532" id="tspan3837">n2-eth0</tspan>
</text>
<text transform="matrix(0.9031157255303414,0,0,1.0287949657006918,-2.8313337284492768,-13.069358400177762) " font-size="13.163442px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="110.835751" y="225.210496" id="text3863">
<tspan stroke="null" font-size="16.245171px" font-weight="bold" font-family="Monospace" x="111.943029" y="230.070551" id="tspan3865">n1-eth0</tspan>
</text>
<path stroke="#000000" fill="none" stroke-width="0.992521px" id="path3887" d="m131.263954,229.882774l0,67.221296l176.555867,-0.960307l1.337531,-65.300682"/>
<rect stroke="#000000" fill="#ffffff" stroke-width="0.676601" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4" stroke-dashoffset="0" id="rect3891" width="95.679394" height="28.317195" x="515.346399" y="202.85306" rx="0.848932"/>
<path stroke="#000000" fill="none" stroke-width="0.992521px" d="m383.833251,230.842992l0,67.221296l176.555867,-0.960307l1.337531,-65.300682" id="path3897"/>
<text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="164.136782" y="409.888383" id="text3907">
<tspan stroke="null" id="tspan3915" x="165.159464" y="415.15046">isolated point to point link</tspan>
</text>
<text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3919" y="409.573373" x="429.378262" xml:space="preserve">
<tspan stroke="null" y="414.83545" x="430.400944" id="tspan3921">isolated point to point link</tspan>
</text>
<text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3923" y="428.078233" x="194.615642" xml:space="preserve">
<tspan stroke="null" font-weight="bold" y="433.34031" x="195.638324" id="tspan3925">(eg: 1Mbps, 10ms)</tspan>
</text>
<text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3927" y="409.888383" x="164.136782" xml:space="preserve">
<tspan stroke="null" y="415.15046" x="165.159464" id="tspan3929">Isolated point to point link</tspan>
</text>
<text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="429.378262" y="409.573373" id="text3931">
<tspan stroke="null" id="tspan3933" x="430.400944" y="414.83545">Isolated point to point link</tspan>
</text>
<text transform="matrix(0.877827228897152,0,0,1.0584326041598764,-53.30106731891522,-78.4233265445007) " font-size="13.706223px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3935" y="282.545218" x="661.482605" xml:space="preserve">
<tspan stroke="null" font-size="16.915024px" font-weight="bold" font-family="Monospace" id="tspan3937" y="287.269185" x="662.621781">n3-eth0</tspan>
</text>
<text transform="matrix(0.7776670647796514,0,0,1.19475416519067,-52.30106724263901,-77.52018902784596) " font-size="12.623897px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3939" y="248.297391" x="520.751053" xml:space="preserve">
<tspan stroke="null" font-size="15.579311px" font-weight="bold" font-family="Monospace" id="tspan3941" y="252.482352" x="522.03695">n2-eth1</tspan>
</text>
<text transform="matrix(0.8745385143393076,0,0,1.0624128521471832,-2.8313338199928846,-14.069358364146652) " font-size="16.205975px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3943" y="80.648481" x="141.655977" xml:space="preserve">
<tspan stroke="null" font-size="20px" font-weight="bold" font-family="Monospace" id="tspan3945" y="85.354749" x="142.799437">n1</tspan>
</text>
<text transform="matrix(0.8745385143393076,0,0,1.0624128521471832,-2.8313338199928846,-14.069358364146652) " font-size="16.205975px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="385.430517" y="78.840861" id="text3955">
<tspan stroke="null" font-size="20px" font-weight="bold" font-family="Monospace" x="386.573977" y="83.547129" id="tspan3957">n2</tspan>
</text>
<text transform="matrix(0.8745385143393076,0,0,1.0624128521471832,-2.8313338199928846,-14.069358364146652) " font-size="16.205975px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3959" y="79.181231" x="632.310457" xml:space="preserve">
<tspan stroke="null" font-size="20px" font-weight="bold" font-family="Monospace" id="tspan3961" y="83.887499" x="633.453917">n3</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="125.371536" y="171.060971" id="text3967">
<tspan stroke="null" font-weight="normal" id="tspan3969" x="126.421253" y="176.187525">(NDN Container)</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3979" y="170.076461" x="352.011746" xml:space="preserve">
<tspan stroke="null" font-weight="normal" y="175.203015" x="353.061463" id="tspan3981">(NDN Container)</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="580.077396" y="169.091931" id="text3983">
<tspan stroke="null" font-weight="normal" id="tspan3985" x="581.127113" y="174.218485">(NDN Container)</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3987" y="193.704961" x="123.946116" xml:space="preserve">
<tspan stroke="null" font-weight="bold" y="198.831515" x="124.995833" id="tspan3989">NFD</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="140.791686" y="208.664491" id="text3991">
<tspan stroke="null" font-weight="normal" id="tspan3993" x="141.841403" y="213.791045">n1.sock</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="123.946116" y="225.286191" id="text3995">
<tspan stroke="null" font-weight="bold" id="tspan3997" x="124.995833" y="230.412745">NLSR</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text3999" y="240.245731" x="138.385176" xml:space="preserve">
<tspan stroke="null" font-weight="normal" y="245.372285" x="139.434893" id="tspan4001">%C1.Router/n1</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="352.011746" y="191.735901" id="text4003">
<tspan stroke="null" font-weight="bold" id="tspan4005" x="353.061463" y="196.862455">NFD</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4007" y="206.695431" x="366.450896" xml:space="preserve">
<tspan stroke="null" font-weight="normal" y="211.821985" x="367.500613" id="tspan4009">n2.sock</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4011" y="223.317141" x="352.011746" xml:space="preserve">
<tspan stroke="null" font-weight="bold" y="228.443695" x="353.061463" id="tspan4013">NLSR</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="366.450896" y="238.276671" id="text4015">
<tspan stroke="null" font-weight="normal" id="tspan4017" x="367.500613" y="243.403225">%C1.Router/n2</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4019" y="190.751371" x="582.928226" xml:space="preserve">
<tspan stroke="null" font-weight="bold" y="195.877925" x="583.977943" id="tspan4021">NFD</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="599.773686" y="205.710911" id="text4023">
<tspan stroke="null" font-weight="normal" id="tspan4025" x="600.823403" y="210.837465">n3.sock</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="582.928226" y="222.332611" id="text4027">
<tspan stroke="null" font-weight="bold" id="tspan4029" x="583.977943" y="227.459165">NLSR</tspan>
</text>
<text transform="matrix(0.9526376792163275,0,0,0.9753141035001042,-53.30106707952308,-77.42332645354041) " font-size="14.959435px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4031" y="237.292141" x="597.367186" xml:space="preserve">
<tspan stroke="null" font-weight="normal" y="242.418695" x="598.416903" id="tspan4033">%C1.Router/n3</tspan>
</text>
<text transform="matrix(0.9778213687833123,0,0,0.9501950205038839,-52.301066914088324,-76.5370021990862) " font-size="16.459864px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4035" y="102.475413" x="322.701992" xml:space="preserve">
<tspan stroke="null" y="107.73749" x="323.724674" id="tspan4037">Isolated NDN nodes</tspan>
</text>
<text transform="matrix(0.935021961689298,0,0,0.9936889310882339,-2.9798247609055646,-12.086171479984756) " font-size="11.279781px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="75.549398" y="206.131281" id="text4039">
<tspan stroke="null" id="tspan4041" x="76.618892" y="211.163037">Private network space</tspan>
</text>
<text transform="matrix(0.935021961689298,0,0,0.9936889310882339,-2.9798247609055646,-12.086171479984756) " font-size="11.279781px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" id="text4043" y="206.946991" x="308.474828" xml:space="preserve">
<tspan stroke="null" y="211.978747" x="309.544322" id="tspan4045">Private network space</tspan>
</text>
<text transform="matrix(0.935021961689298,0,0,0.9936889310882339,-2.9798247609055646,-12.086171479984756) " font-size="11.279781px" font-style="normal" font-weight="normal" fill="#000000" font-family="Sans" xml:space="preserve" x="540.174348" y="206.131281" id="text4047">
<tspan stroke="null" id="tspan4049" x="541.243842" y="211.163037">Private network space</tspan>
</text>
<text xml:space="preserve" text-anchor="start" font-family="Helvetica,Arial,sans-serif" font-size="15px" id="svg_1" y="377" x="203.5" stroke-width="null" stroke="null" fill="#333">Figure: Relationship between Minindn and Mininet</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

+286
View File
@@ -0,0 +1,286 @@
Release Notes
=============
Mini-NDN version 0.6.0 (Major changes since version 0.5.0)
----------------------------------------------------------
**Breaking Changes**:
- Rewrite install script (`issue: 4630 <https://redmine.named-data.net/issues/4630>`__)
- Set dependency versions: PPA, git repository & commit
- Separate download and build+install steps
- Don't reinstall package if it's already installed
- More details `here <https://github.com/named-data/mini-ndn/blob/master/docs/install.rst>`__
- `Note: <https://redmine.named-data.net/issues/5161>`__ We have dropped support for python 2, the latest Mini-NDN requires at least python 3.0
**New features**:
- Update Mini-NDN codebase with Mini-NDN-Wifi code (`issue: 4858 <https://redmine.named-data.net/issues/4858>`__)
- Provide pre-built Mini-NDN Vagrant box and Docker container
- Added several new examples:
- consumer/producer
- ndnping
- traffic generator
- catchunks/putchunks
- Allow for creation of net object without topology (`issue: 5162 <https://redmine.named-data.net/issues/5162>`__)
**Improvements and Bug Fixes**:
- Support running NDN applications on mixed topologies (`issue: 5160 <https://redmine.named-data.net/issues/5160>`__)
- Support route addition using face-id in `Nfdc` helper (`issue: 5130 <https://redmine.named-data.net/issues/5130>`__)
- Add wrapper for `ndnpingserver` and fix passing the Mininet host object as a prefix on ndnpingclient
- Show status of route calculation in `NdnRoutingHelper`
- Incorporate changes of `NDNPing` Class (wrapper of pingserver and pingclient) in the examples
- Support simple topology files with no additional parameters
Mini-NDN version 0.5.0 (Major changes since version 0.4.0)
----------------------------------------------------------
**Breaking Changes**:
- `Mini-NDN re-design <https://redmine.named-data.net/issues/5062>`__: simple and robust design with better quality, control, and more consistency with Mininet
**New features**:
- Add a script to generate up-to-date NDN testbed topologies for Mini-NDN
- Add Mini-NDN utility application for PCAP logging
- Add NDN routing helper to compute centralized LS and HR routes
- Add routing helper to allow IP communication in experiments
- Add startup experiments for NLSR and current testbed topology
- Move the NDNPing wrapper method to a helper class
- Create a helper class to provide a wrapper around ``nfdc``
**Improvements and Bug Fixes**:
- Change workDir and resultDir to be class attribute
- Quiet apt install for Vagrant
- Fix route computation bug in ``ndn_routing_helper``
- Fix overwriting of existing prefixes in ``ndn_routing_helper``
- Move log files to resultDir after evaluation finishes
- Check for duplicate HR coordinates in the topology file
- Check PSync integration and add a tests case for it
- Bug fixes in nfdc and experiments
- Added functionality to check Mini-NDN dependencies
- Parser fix to avoid an infinite loop
- Allow use of NFD and NLSR PPA with Mini-NDN
- Remove arbitrary arguments in favor of parsing arguments from experiment files
- Auto-complete command-line arguments
- Add option to set CS size
- Adjust to use ndn-cxx logging
Mini-NDN version 0.4.0 (changes since version 0.3.0)
----------------------------------------------------
Release date: January 10, 2018
**New features**:
- Use SIGQUIT to quit Mini-NDN, SIGINT to kill programs
- Use Infoedit to edit NFD and NLSR configuration files
- Use nlsr.conf installed in the system
- Provide a Vagrantfile to setup Mini-NDN and NDN
- Provide option to disable NLSR
- Provide an option to run NLSR in dry-run mode
- Add option to specify whether to use TCP or UDP face in nlsr.conf
- Add option to specify arbitrary arguments to use in experiments
- Include a single option to install Mini-NDN and all the dependencies
**Bug fixes**:
- Fix "key does not exist error" after NLSR starts
- Update install.sh to call ldconfig after installing ChronoSync
- Add hyperbolic coordinates to default topology
**Misc changes**:
- Add an experiment to test nlsrc
- Create faces in NFD for each neighbor in NLSR
- Update to latest ndn-cxx
- Use /tmp/minindn folder as default work dir instead of /tmp
Mini-NDN version 0.3.0 (changes since version 0.2.0)
----------------------------------------------------
Release date: March 3, 2017
**New features**:
- Mini-NDN cluster edition
- New experiments for making NLSR testing easier
**Bug fixes**:
- Set site name correctly
- Install missing certificates in NLSR security config
- Fix quitting of NLSR due to key not found error
**Misc changes**:
- Removed nlsr.conf file, generate it within the code
- Use argparse instead of deprecated optparse
- Update security config section for NLSR
- Change mininet prompt to mini-ndn
- Set network name at one place
- Update install.sh script to install openssl
- Update install.sh script to install cryptopp from package instead of
compiling from source
- Update install.sh to clean build folder every time to get rid of
removed files such as old experiments
- Fix old code - use net.hosts instead of storing hosts in a variable
- Use nfdc instead of deprecated nfd-status
Mini-NDN version 0.2.0 (changes since version 0.1.1)
----------------------------------------------------
Release date: August 18, 2016
**New features**:
- Automatic security configuration for NLSR
- Use /usr/local/etc/ndn/nfd.conf as default config file for NFD
- Class to monitor /proc/$PID/stat file for PID
- Mini-NDN exits gracefully on SIGINT and non-convergence
- Faster Mini-NDN install script - does not do apt-get update everytime
- NLSR is launched with explicit config file for easier process
identification
- Add and update more documentation
**Bug fixes**:
- NFD is killed correctly on exit
- Best route strategy is set correctly
Mini-NDN version 0.1.1 (changes since version 0.1.0)
----------------------------------------------------
Release date: November 4, 2015
**New features**:
- Use nfd.conf.sample from currently installed NFD
- Add working directory option to allow execution environment outside
of /tmp
- Add results directory option to store experiment results after
completion
- Add support for switches in GUI and configuration file
- Add failNode and recoverNode methods to Experiment class
- Add most connected node (MCN) failure experiment
- Add option to specify percentage of nodes pinged
**Code changes**:
- Refactor program options into container class
- Remove unused "FIB Entries" option from NDN host options
**Bug fixes**:
- Abort start up if experiment name is invalid
- Restart pings after recovery in failure experiment
Mini-NDN version 0.1.0 (initial release)
----------------------------------------
Release date: July 15, 2015
Mini-NDN is a lightweight networking emulation tool that enables
testing, experimentation, and research on the NDN platform. Based on
Mininet, Mini-NDN uses the NDN libraries, NFD, NLSR, and tools released
by the `NDN project <http://named-data.net/codebase/platform/>`__ to
emulate an NDN network on a single system.
**Included features**:
- Run a complete NDN network on a single system
- Automatic configuration of NLSR to provide a routable NDN network
- Supports user created NDN applications
- Create a topology using the included Mini-NDN Edit GUI application
- Allows individual configuration of NFD and NLSR parameters for each
node
- Provides an experiment management framework for easy creation of
custom networking experiments
- Uses a simple topology file format to define hosts, links, and
configuration values
- Configure network link parameters including bandwidth, delay, and
loss rate
- Includes a pre-configured topology file to replicate the NDN testbed
+18
View File
@@ -0,0 +1,18 @@
Video Tutorials
===============
Maybe outdated since version 0.5.0.
.. raw:: html
<div id="video-container" class="col-md-6 ">
<p>Mini-NDN Demo at ACM, 2017</p>
<iframe width="400" height="230" src="https://www.youtube.com/embed/xYRPHZe18o0" frameborder="0" allowfullscreen=""></iframe>
</div>
.. raw:: html
<div id="video-container" class="col-md-6 "">
<p>Mini-NDN Overview </p>
<iframe width="400" height="230" src="https://www.youtube.com/embed/Da7t8yBWzv0" frameborder="0" allowfullscreen="">
</div>
-179
View File
@@ -1,179 +0,0 @@
Mininet Examples
========================================================
These examples are intended to help you get started using
Mininet's Python API.
========================================================
#### baresshd.py:
This example uses Mininet's medium-level API to create an sshd
process running in a namespace. Doesn't use OpenFlow.
#### bind.py:
This example shows how you can create private directories for each
node in a Mininet topology.
#### cluster.py:
This example contains all of the code for experimental cluster
edition. Remote classes and MininetCluster can be imported from
here to create a topology with nodes on remote machines.
#### clusterSanity.py:
This example runs cluster edition locally as a sanity check to test
basic functionality.
#### clustercli.py:
This example contains a CLI for experimental cluster edition.
#### clusterdemo.py:
This example is a basic demo of cluster edition on 3 servers with
a tree topology of depth 3 and fanout 3.
#### consoles.py:
This example creates a grid of console windows, one for each node,
and allows interaction with and monitoring of each console, including
graphical monitoring.
#### controllers.py:
This example creates a network with multiple controllers, by
using a custom `Switch()` subclass.
#### controllers2.py:
This example creates a network with multiple controllers by
creating an empty network, adding nodes to it, and manually
starting the switches.
#### controlnet.py:
This examples shows how you can model the control network as well
as the data network, by actually creating two Mininet objects.
#### cpu.py:
This example tests iperf bandwidth for varying CPU limits.
#### emptynet.py:
This example demonstrates creating an empty network (i.e. with no
topology object) and adding nodes to it.
#### hwintf.py:
This example shows how to add an interface (for example a real
hardware interface) to a network after the network is created.
#### intfoptions.py:
This example reconfigures a TCIntf during runtime with different
traffic control commands to test bandwidth, loss, and delay.
#### limit.py:
This example shows how to use link and CPU limits.
#### linearbandwidth.py:
This example shows how to create a custom topology programatically
by subclassing Topo, and how to run a series of tests on it.
#### linuxrouter.py:
This example shows how to create and configure a router in Mininet
that uses Linux IP forwarding.
#### miniedit.py:
This example demonstrates creating a network via a graphical editor.
#### mobility.py:
This example demonstrates detaching an interface from one switch and
attaching it another as a basic way to move a host around a network.
#### multiLink.py:
This example demonstrates the creation of multiple links between
nodes using a custom Topology class.
#### multiping.py:
This example demonstrates one method for
monitoring output from multiple hosts, using `node.monitor()`.
#### multipoll.py:
This example demonstrates monitoring output files from multiple hosts.
#### multitest.py:
This example creates a network and runs multiple tests on it.
#### nat.py:
This example shows how to connect a Mininet network to the Internet
using NAT. It also answers the eternal question "why can't I ping
`google.com`?"
#### natnet.py:
This example demonstrates how to create a network using a NAT node
to connect hosts to the internet.
#### numberedports.py:
This example verifies the mininet ofport numbers match up to the ovs port numbers.
It also verifies that the port numbers match up to the interface numbers
#### popen.py:
This example monitors a number of hosts using `host.popen()` and
`pmonitor()`.
#### popenpoll.py:
This example demonstrates monitoring output from multiple hosts using
the `node.popen()` interface (which returns `Popen` objects) and `pmonitor()`.
#### scratchnet.py, scratchnetuser.py:
These two examples demonstrate how to create a network by using the lowest-
level Mininet functions. Generally the higher-level API is easier to use,
but scratchnet shows what is going on behind the scenes.
#### simpleperf.py:
A simple example of configuring network and CPU bandwidth limits.
#### sshd.py:
This example shows how to run an `sshd` process in each host, allowing
you to log in via `ssh`. This requires connecting the Mininet data network
to an interface in the root namespace (generaly the control network
already lives in the root namespace, so it does not need to be explicitly
connected.)
#### tree1024.py:
This example attempts to create a 1024-host network, and then runs the
CLI on it. It may run into scalability limits, depending on available
memory and `sysctl` configuration (see `INSTALL`.)
#### treeping64.py:
This example creates a 64-host tree network, and attempts to check full
connectivity using `ping`, for different switch/datapath types.
#### vlanhost.py:
An example of how to subclass Host to use a VLAN on its primary interface.
-4
View File
@@ -1,4 +0,0 @@
"""
Mininet Examples
See README for details
"""
-43
View File
@@ -1,43 +0,0 @@
#!/usr/bin/python
"This example doesn't use OpenFlow, but attempts to run sshd in a namespace."
import sys
from mininet.node import Host
from mininet.util import ensureRoot, waitListening
ensureRoot()
timeout = 5
print "*** Creating nodes"
h1 = Host( 'h1' )
root = Host( 'root', inNamespace=False )
print "*** Creating links"
h1.linkTo( root )
print h1
print "*** Configuring nodes"
h1.setIP( '10.0.0.1', 8 )
root.setIP( '10.0.0.2', 8 )
print "*** Creating banner file"
f = open( '/tmp/%s.banner' % h1.name, 'w' )
f.write( 'Welcome to %s at %s\n' % ( h1.name, h1.IP() ) )
f.close()
print "*** Running sshd"
cmd = '/usr/sbin/sshd -o UseDNS=no -u0 -o "Banner /tmp/%s.banner"' % h1.name
# add arguments from the command line
if len( sys.argv ) > 1:
cmd += ' ' + ' '.join( sys.argv[ 1: ] )
h1.cmd( cmd )
listening = waitListening( server=h1, port=22, timeout=timeout )
if listening:
print "*** You may now ssh into", h1.name, "at", h1.IP()
else:
print ( "*** Warning: after %s seconds, %s is not listening on port 22"
% ( timeout, h1.name ) )
-67
View File
@@ -1,67 +0,0 @@
#!/usr/bin/python
"""
bind.py: Bind mount example
This creates hosts with private directories that the user specifies.
These hosts may have persistent directories that will be available
across multiple mininet session, or temporary directories that will
only last for one mininet session. To specify a persistent
directory, add a tuple to a list of private directories:
[ ( 'directory to be mounted on', 'directory to be mounted' ) ]
String expansion may be used to create a directory template for
each host. To do this, add a %(name)s in place of the host name
when creating your list of directories:
[ ( '/var/run', '/tmp/%(name)s/var/run' ) ]
If no persistent directory is specified, the directories will default
to temporary private directories. To do this, simply create a list of
directories to be made private. A tmpfs will then be mounted on them.
You may use both temporary and persistent directories at the same
time. In the following privateDirs string, each host will have a
persistent directory in the root filesystem at
"/tmp/(hostname)/var/run" mounted on "/var/run". Each host will also
have a temporary private directory mounted on "/var/log".
[ ( '/var/run', '/tmp/%(name)s/var/run' ), '/var/log' ]
This example has both persistent directories mounted on '/var/log'
and '/var/run'. It also has a temporary private directory mounted
on '/var/mn'
"""
from mininet.net import Mininet
from mininet.node import Host
from mininet.cli import CLI
from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel, info
from functools import partial
# Sample usage
def testHostWithPrivateDirs():
"Test bind mounts"
topo = SingleSwitchTopo( 10 )
privateDirs = [ ( '/var/log', '/tmp/%(name)s/var/log' ),
( '/var/run', '/tmp/%(name)s/var/run' ),
'/var/mn' ]
host = partial( Host,
privateDirs=privateDirs )
net = Mininet( topo=topo, host=host )
net.start()
directories = [ directory[ 0 ] if isinstance( directory, tuple )
else directory for directory in privateDirs ]
info( 'Private Directories:', directories, '\n' )
CLI( net )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
testHostWithPrivateDirs()
info( 'Done.\n')
+95
View File
@@ -0,0 +1,95 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
"""
This example demonstrates the functionality of the ndncatchunks and ndnputchunks. There are
programs to transfer a file as Data segments in NDN.
https://github.com/named-data/ndn-tools/tree/master/tools/chunks.
"""
from time import sleep
import subprocess
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
def sendFile(node, prefix, file):
"""
Publish a file using ndnputchunks
:parma mininet.node.Host node: mininet node object
:param string prefix: prefix to publish the chunks of the file
:param string file: file to publish
"""
info ("File published:", file)
cmd = 'ndnputchunks {}/{} < {} > putchunks.log 2>&1 &'.format(prefix, "fname", file)
node.cmd(cmd)
# Sleep for appropriate time based on the file size
sleep(5)
def receiveFile(node, prefix, filename):
"""
Fetch a file using ndncatchunks
:parma mininet.node.Host node: mininet node object
:param string prefix: producer's prefix under which the file the published
:param string file: name given to the file that will be received
"""
info ("Fething file: ", filename)
cmd = 'ndncatchunks {}/{} > {} 2> catchunks.log &'.format(prefix, "fname", filename)
node.cmd(cmd)
if __name__ == '__main__':
setLogLevel('info')
# Create a test file to publish
testFile = "/tmp/test-chunks"
cmd = 'echo "demonstrate file transfer using catchunks and putchunks" > {}'.format(testFile)
subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).communicate()
Minindn.cleanUp()
Minindn.verifyDependencies()
ndn = Minindn()
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
sleep(70)
# Default topology is used in this experiment "/topologies/default-topology.conf"
# lets make node "a" as a producer node, and node "c" as a conumer node
producer = ndn.net['a']
producerPrefix = "/test-producer" # prefix under which the file will be published
consumer = ndn.net['c']
# Advertise the producer prefix to the network
producer.cmd('nlsrc advertise {}'.format(producerPrefix))
sleep (5) # sleep for routing convergence.
sendFile(producer, producerPrefix, testFile)
receiveFile(consumer, producerPrefix, "test-chunks")
MiniNDNCLI(ndn.net)
ndn.stop()
-914
View File
@@ -1,914 +0,0 @@
#!/usr/bin/python
"""
cluster.py: prototyping/experimentation for distributed Mininet,
aka Mininet: Cluster Edition
Author: Bob Lantz
Core classes:
RemoteNode: a Node() running on a remote server
RemoteOVSSwitch(): an OVSSwitch() running on a remote server
RemoteLink: a Link() on a remote server
Tunnel: a Link() between a local Node() and a RemoteNode()
These are largely interoperable with local objects.
- One Mininet to rule them all
It is important that the same topologies, APIs, and CLI can be used
with minimal or no modification in both local and distributed environments.
- Multiple placement models
Placement should be as easy as possible. We should provide basic placement
support and also allow for explicit placement.
Questions:
What is the basic communication mechanism?
To start with? Probably a single multiplexed ssh connection between each
pair of mininet servers that needs to communicate.
How are tunnels created?
We have several options including ssh, GRE, OF capsulator, socat, VDE, l2tp,
etc.. It's not clear what the best one is. For now, we use ssh tunnels since
they are encrypted and semi-automatically shared. We will probably want to
support GRE as well because it's very easy to set up with OVS.
How are tunnels destroyed?
They are destroyed when the links are deleted in Mininet.stop()
How does RemoteNode.popen() work?
It opens a shared ssh connection to the remote server and attaches to
the namespace using mnexec -a -g.
Is there any value to using Paramiko vs. raw ssh?
Maybe, but it doesn't seem to support L2 tunneling.
Should we preflight the entire network, including all server-to-server
connections?
Yes! We don't yet do this with remote server-to-server connections yet.
Should we multiplex the link ssh connections?
Yes, this is done automatically with ControlMaster=auto.
Note on ssh and DNS:
Please add UseDNS: no to your /etc/ssh/sshd_config!!!
Things to do:
- asynchronous/pipelined/parallel startup
- ssh debugging/profiling
- make connections into real objects
- support for other tunneling schemes
- tests and benchmarks
- hifi support (e.g. delay compensation)
"""
from mininet.node import Node, Host, OVSSwitch, Controller
from mininet.link import Link, Intf
from mininet.net import Mininet
from mininet.topo import LinearTopo
from mininet.topolib import TreeTopo
from mininet.util import quietRun, errRun
from mininet.examples.clustercli import CLI
from mininet.log import setLogLevel, debug, info, error
from mininet.clean import addCleanupCallback
from signal import signal, SIGINT, SIG_IGN
from subprocess import Popen, PIPE, STDOUT
import os
from random import randrange
import sys
import re
from itertools import groupby
from operator import attrgetter
from distutils.version import StrictVersion
def findUser():
"Try to return logged-in (usually non-root) user"
return (
# If we're running sudo
os.environ.get( 'SUDO_USER', False ) or
# Logged-in user (if we have a tty)
( quietRun( 'who am i' ).split() or [ False ] )[ 0 ] or
# Give up and return effective user
quietRun( 'whoami' ) )
class ClusterCleanup( object ):
"Cleanup callback"
inited = False
serveruser = {}
@classmethod
def add( cls, server, user='' ):
"Add an entry to server: user dict"
if not cls.inited:
addCleanupCallback( cls.cleanup )
if not user:
user = findUser()
cls.serveruser[ server ] = user
@classmethod
def cleanup( cls ):
"Clean up"
info( '*** Cleaning up cluster\n' )
for server, user in cls.serveruser.iteritems():
if server == 'localhost':
# Handled by mininet.clean.cleanup()
continue
else:
cmd = [ 'su', user, '-c',
'ssh %s@%s sudo mn -c' % ( user, server ) ]
info( cmd, '\n' )
info( quietRun( cmd ) )
# BL note: so little code is required for remote nodes,
# we will probably just want to update the main Node()
# class to enable it for remote access! However, there
# are a large number of potential failure conditions with
# remote nodes which we may want to detect and handle.
# Another interesting point is that we could put everything
# in a mix-in class and easily add cluster mode to 2.0.
class RemoteMixin( object ):
"A mix-in class to turn local nodes into remote nodes"
# ssh base command
# -q: don't print stupid diagnostic messages
# BatchMode yes: don't ask for password
# ForwardAgent yes: forward authentication credentials
sshbase = [ 'ssh', '-q',
'-o', 'BatchMode=yes',
'-o', 'ForwardAgent=yes', '-tt' ]
def __init__( self, name, server='localhost', user=None, serverIP=None,
controlPath=False, splitInit=False, **kwargs):
"""Instantiate a remote node
name: name of remote node
server: remote server (optional)
user: user on remote server (optional)
controlPath: specify shared ssh control path (optional)
splitInit: split initialization?
**kwargs: see Node()"""
# We connect to servers by IP address
self.server = server if server else 'localhost'
self.serverIP = ( serverIP if serverIP
else self.findServerIP( self.server ) )
self.user = user if user else findUser()
ClusterCleanup.add( server=server, user=user )
if controlPath is True:
# Set a default control path for shared SSH connections
controlPath = '/tmp/mn-%r@%h:%p'
self.controlPath = controlPath
self.splitInit = splitInit
if self.user and self.server != 'localhost':
self.dest = '%s@%s' % ( self.user, self.serverIP )
self.sshcmd = [ 'sudo', '-E', '-u', self.user ] + self.sshbase
if self.controlPath:
self.sshcmd += [ '-o', 'ControlPath=' + self.controlPath,
'-o', 'ControlMaster=auto',
'-o', 'ControlPersist=' + '1' ]
self.sshcmd += [ self.dest ]
self.isRemote = True
else:
self.dest = None
self.sshcmd = []
self.isRemote = False
# Satisfy pylint
self.shell, self.pid = None, None
super( RemoteMixin, self ).__init__( name, **kwargs )
# Determine IP address of local host
_ipMatchRegex = re.compile( r'\d+\.\d+\.\d+\.\d+' )
@classmethod
def findServerIP( cls, server ):
"Return our server's IP address"
# First, check for an IP address
ipmatch = cls._ipMatchRegex.findall( server )
if ipmatch:
return ipmatch[ 0 ]
# Otherwise, look up remote server
output = quietRun( 'getent ahostsv4 %s' % server )
ips = cls._ipMatchRegex.findall( output )
ip = ips[ 0 ] if ips else None
return ip
# Command support via shell process in namespace
def startShell( self, *args, **kwargs ):
"Start a shell process for running commands"
if self.isRemote:
kwargs.update( mnopts='-c' )
super( RemoteMixin, self ).startShell( *args, **kwargs )
# Optional split initialization
self.sendCmd( 'echo $$' )
if not self.splitInit:
self.finishInit()
def finishInit( self ):
"Wait for split initialization to complete"
self.pid = int( self.waitOutput() )
def rpopen( self, *cmd, **opts ):
"Return a Popen object on underlying server in root namespace"
params = { 'stdin': PIPE,
'stdout': PIPE,
'stderr': STDOUT,
'sudo': True }
params.update( opts )
return self._popen( *cmd, **params )
def rcmd( self, *cmd, **opts):
"""rcmd: run a command on underlying server
in root namespace
args: string or list of strings
returns: stdout and stderr"""
popen = self.rpopen( *cmd, **opts )
# print 'RCMD: POPEN:', popen
# These loops are tricky to get right.
# Once the process exits, we can read
# EOF twice if necessary.
result = ''
while True:
poll = popen.poll()
result += popen.stdout.read()
if poll is not None:
break
return result
@staticmethod
def _ignoreSignal():
"Detach from process group to ignore all signals"
os.setpgrp()
def _popen( self, cmd, sudo=True, tt=True, **params):
"""Spawn a process on a remote node
cmd: remote command to run (list)
**params: parameters to Popen()
returns: Popen() object"""
if type( cmd ) is str:
cmd = cmd.split()
if self.isRemote:
if sudo:
cmd = [ 'sudo', '-E' ] + cmd
if tt:
cmd = self.sshcmd + cmd
else:
# Hack: remove -tt
sshcmd = list( self.sshcmd )
sshcmd.remove( '-tt' )
cmd = sshcmd + cmd
else:
if self.user and not sudo:
# Drop privileges
cmd = [ 'sudo', '-E', '-u', self.user ] + cmd
params.update( preexec_fn=self._ignoreSignal )
debug( '_popen', cmd, '\n' )
popen = super( RemoteMixin, self )._popen( cmd, **params )
return popen
def popen( self, *args, **kwargs ):
"Override: disable -tt"
return super( RemoteMixin, self).popen( *args, tt=False, **kwargs )
def addIntf( self, *args, **kwargs ):
"Override: use RemoteLink.moveIntf"
kwargs.update( moveIntfFn=RemoteLink.moveIntf )
return super( RemoteMixin, self).addIntf( *args, **kwargs )
class RemoteNode( RemoteMixin, Node ):
"A node on a remote server"
pass
class RemoteHost( RemoteNode ):
"A RemoteHost is simply a RemoteNode"
pass
class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
"Remote instance of Open vSwitch"
OVSVersions = {}
def __init__( self, *args, **kwargs ):
# No batch startup yet
kwargs.update( batch=True )
super( RemoteOVSSwitch, self ).__init__( *args, **kwargs )
def isOldOVS( self ):
"Is remote switch using an old OVS version?"
cls = type( self )
if self.server not in cls.OVSVersions:
# pylint: disable=not-callable
vers = self.cmd( 'ovs-vsctl --version' )
# pylint: enable=not-callable
cls.OVSVersions[ self.server ] = re.findall(
r'\d+\.\d+', vers )[ 0 ]
return ( StrictVersion( cls.OVSVersions[ self.server ] ) <
StrictVersion( '1.10' ) )
@classmethod
def batchStartup( cls, switches, **_kwargs ):
"Start up switches in per-server batches"
key = attrgetter( 'server' )
for server, switchGroup in groupby( sorted( switches, key=key ), key ):
info( '(%s)' % server )
group = tuple( switchGroup )
switch = group[ 0 ]
OVSSwitch.batchStartup( group, run=switch.cmd )
return switches
@classmethod
def batchShutdown( cls, switches, **_kwargs ):
"Stop switches in per-server batches"
key = attrgetter( 'server' )
for server, switchGroup in groupby( sorted( switches, key=key ), key ):
info( '(%s)' % server )
group = tuple( switchGroup )
switch = group[ 0 ]
OVSSwitch.batchShutdown( group, run=switch.rcmd )
return switches
class RemoteLink( Link ):
"A RemoteLink is a link between nodes which may be on different servers"
def __init__( self, node1, node2, **kwargs ):
"""Initialize a RemoteLink
see Link() for parameters"""
# Create links on remote node
self.node1 = node1
self.node2 = node2
self.tunnel = None
kwargs.setdefault( 'params1', {} )
kwargs.setdefault( 'params2', {} )
self.cmd = None # satisfy pylint
Link.__init__( self, node1, node2, **kwargs )
def stop( self ):
"Stop this link"
if self.tunnel:
self.tunnel.terminate()
self.intf1.delete()
self.intf2.delete()
else:
Link.stop( self )
self.tunnel = None
def makeIntfPair( self, intfname1, intfname2, addr1=None, addr2=None,
node1=None, node2=None, deleteIntfs=True ):
"""Create pair of interfaces
intfname1: name of interface 1
intfname2: name of interface 2
(override this method [and possibly delete()]
to change link type)"""
node1 = self.node1 if node1 is None else node1
node2 = self.node2 if node2 is None else node2
server1 = getattr( node1, 'server', 'localhost' )
server2 = getattr( node2, 'server', 'localhost' )
if server1 == server2:
# Link within same server
return Link.makeIntfPair( intfname1, intfname2, addr1, addr2,
node1, node2, deleteIntfs=deleteIntfs )
# Otherwise, make a tunnel
self.tunnel = self.makeTunnel( node1, node2, intfname1, intfname2,
addr1, addr2 )
return self.tunnel
@staticmethod
def moveIntf( intf, node, printError=True ):
"""Move remote interface from root ns to node
intf: string, interface
dstNode: destination Node
srcNode: source Node or None (default) for root ns
printError: if true, print error"""
intf = str( intf )
cmd = 'ip link set %s netns %s' % ( intf, node.pid )
node.rcmd( cmd )
links = node.cmd( 'ip link show' )
if not ' %s:' % intf in links:
if printError:
error( '*** Error: RemoteLink.moveIntf: ' + intf +
' not successfully moved to ' + node.name + '\n' )
return False
return True
def makeTunnel( self, node1, node2, intfname1, intfname2,
addr1=None, addr2=None ):
"Make a tunnel across switches on different servers"
# We should never try to create a tunnel to ourselves!
assert node1.server != 'localhost' or node2.server != 'localhost'
# And we can't ssh into this server remotely as 'localhost',
# so try again swappping node1 and node2
if node2.server == 'localhost':
return self.makeTunnel( node2, node1, intfname2, intfname1,
addr2, addr1 )
# 1. Create tap interfaces
for node in node1, node2:
# For now we are hard-wiring tap9, which we will rename
cmd = 'ip tuntap add dev tap9 mode tap user ' + node.user
result = node.rcmd( cmd )
if result:
raise Exception( 'error creating tap9 on %s: %s' %
( node, result ) )
# 2. Create ssh tunnel between tap interfaces
# -n: close stdin
dest = '%s@%s' % ( node2.user, node2.serverIP )
cmd = [ 'ssh', '-n', '-o', 'Tunnel=Ethernet', '-w', '9:9',
dest, 'echo @' ]
self.cmd = cmd
tunnel = node1.rpopen( cmd, sudo=False )
# When we receive the character '@', it means that our
# tunnel should be set up
debug( 'Waiting for tunnel to come up...\n' )
ch = tunnel.stdout.read( 1 )
if ch != '@':
raise Exception( 'makeTunnel:\n',
'Tunnel setup failed for',
'%s:%s' % ( node1, node1.dest ), 'to',
'%s:%s\n' % ( node2, node2.dest ),
'command was:', cmd, '\n' )
# 3. Move interfaces if necessary
for node in node1, node2:
if not self.moveIntf( 'tap9', node ):
raise Exception( 'interface move failed on node %s' % node )
# 4. Rename tap interfaces to desired names
for node, intf, addr in ( ( node1, intfname1, addr1 ),
( node2, intfname2, addr2 ) ):
if not addr:
result = node.cmd( 'ip link set tap9 name', intf )
else:
result = node.cmd( 'ip link set tap9 name', intf,
'address', addr )
if result:
raise Exception( 'error renaming %s: %s' % ( intf, result ) )
return tunnel
def status( self ):
"Detailed representation of link"
if self.tunnel:
if self.tunnel.poll() is not None:
status = "Tunnel EXITED %s" % self.tunnel.returncode
else:
status = "Tunnel Running (%s: %s)" % (
self.tunnel.pid, self.cmd )
else:
status = "OK"
result = "%s %s" % ( Link.status( self ), status )
return result
# Some simple placement algorithms for MininetCluster
class Placer( object ):
"Node placement algorithm for MininetCluster"
def __init__( self, servers=None, nodes=None, hosts=None,
switches=None, controllers=None, links=None ):
"""Initialize placement object
servers: list of servers
nodes: list of all nodes
hosts: list of hosts
switches: list of switches
controllers: list of controllers
links: list of links
(all arguments are optional)
returns: server"""
self.servers = servers or []
self.nodes = nodes or []
self.hosts = hosts or []
self.switches = switches or []
self.controllers = controllers or []
self.links = links or []
def place( self, node ):
"Return server for a given node"
assert self, node # satisfy pylint
# Default placement: run locally
return 'localhost'
class RandomPlacer( Placer ):
"Random placement"
def place( self, nodename ):
"""Random placement function
nodename: node name"""
assert nodename # please pylint
# This may be slow with lots of servers
return self.servers[ randrange( 0, len( self.servers ) ) ]
class RoundRobinPlacer( Placer ):
"""Round-robin placement
Note this will usually result in cross-server links between
hosts and switches"""
def __init__( self, *args, **kwargs ):
Placer.__init__( self, *args, **kwargs )
self.next = 0
def place( self, nodename ):
"""Round-robin placement function
nodename: node name"""
assert nodename # please pylint
# This may be slow with lots of servers
server = self.servers[ self.next ]
self.next = ( self.next + 1 ) % len( self.servers )
return server
class SwitchBinPlacer( Placer ):
"""Place switches (and controllers) into evenly-sized bins,
and attempt to co-locate hosts and switches"""
def __init__( self, *args, **kwargs ):
Placer.__init__( self, *args, **kwargs )
# Easy lookup for servers and node sets
self.servdict = dict( enumerate( self.servers ) )
self.hset = frozenset( self.hosts )
self.sset = frozenset( self.switches )
self.cset = frozenset( self.controllers )
# Server and switch placement indices
self.placement = self.calculatePlacement()
@staticmethod
def bin( nodes, servers ):
"Distribute nodes evenly over servers"
# Calculate base bin size
nlen = len( nodes )
slen = len( servers )
# Basic bin size
quotient = int( nlen / slen )
binsizes = { server: quotient for server in servers }
# Distribute remainder
remainder = nlen % slen
for server in servers[ 0 : remainder ]:
binsizes[ server ] += 1
# Create binsize[ server ] tickets for each server
tickets = sum( [ binsizes[ server ] * [ server ]
for server in servers ], [] )
# And assign one ticket to each node
return { node: ticket for node, ticket in zip( nodes, tickets ) }
def calculatePlacement( self ):
"Pre-calculate node placement"
placement = {}
# Create host-switch connectivity map,
# associating host with last switch that it's
# connected to
switchFor = {}
for src, dst in self.links:
if src in self.hset and dst in self.sset:
switchFor[ src ] = dst
if dst in self.hset and src in self.sset:
switchFor[ dst ] = src
# Place switches
placement = self.bin( self.switches, self.servers )
# Place controllers and merge into placement dict
placement.update( self.bin( self.controllers, self.servers ) )
# Co-locate hosts with their switches
for h in self.hosts:
if h in placement:
# Host is already placed - leave it there
continue
if h in switchFor:
placement[ h ] = placement[ switchFor[ h ] ]
else:
raise Exception(
"SwitchBinPlacer: cannot place isolated host " + h )
return placement
def place( self, node ):
"""Simple placement algorithm:
place switches into evenly sized bins,
and place hosts near their switches"""
return self.placement[ node ]
class HostSwitchBinPlacer( Placer ):
"""Place switches *and hosts* into evenly-sized bins
Note that this will usually result in cross-server
links between hosts and switches"""
def __init__( self, *args, **kwargs ):
Placer.__init__( self, *args, **kwargs )
# Calculate bin sizes
scount = len( self.servers )
self.hbin = max( int( len( self.hosts ) / scount ), 1 )
self.sbin = max( int( len( self.switches ) / scount ), 1 )
self.cbin = max( int( len( self.controllers ) / scount ), 1 )
info( 'scount:', scount )
info( 'bins:', self.hbin, self.sbin, self.cbin, '\n' )
self.servdict = dict( enumerate( self.servers ) )
self.hset = frozenset( self.hosts )
self.sset = frozenset( self.switches )
self.cset = frozenset( self.controllers )
self.hind, self.sind, self.cind = 0, 0, 0
def place( self, nodename ):
"""Simple placement algorithm:
place nodes into evenly sized bins"""
# Place nodes into bins
if nodename in self.hset:
server = self.servdict[ self.hind / self.hbin ]
self.hind += 1
elif nodename in self.sset:
server = self.servdict[ self.sind / self.sbin ]
self.sind += 1
elif nodename in self.cset:
server = self.servdict[ self.cind / self.cbin ]
self.cind += 1
else:
info( 'warning: unknown node', nodename )
server = self.servdict[ 0 ]
return server
# The MininetCluster class is not strictly necessary.
# However, it has several purposes:
# 1. To set up ssh connection sharing/multiplexing
# 2. To pre-flight the system so that everything is more likely to work
# 3. To allow connection/connectivity monitoring
# 4. To support pluggable placement algorithms
class MininetCluster( Mininet ):
"Cluster-enhanced version of Mininet class"
# Default ssh command
# BatchMode yes: don't ask for password
# ForwardAgent yes: forward authentication credentials
sshcmd = [ 'ssh', '-o', 'BatchMode=yes', '-o', 'ForwardAgent=yes' ]
def __init__( self, *args, **kwargs ):
"""servers: a list of servers to use (note: include
localhost or None to use local system as well)
user: user name for server ssh
placement: Placer() subclass"""
params = { 'host': RemoteHost,
'switch': RemoteOVSSwitch,
'link': RemoteLink,
'precheck': True }
params.update( kwargs )
servers = params.pop( 'servers', [ 'localhost' ] )
servers = [ s if s else 'localhost' for s in servers ]
self.servers = servers
self.serverIP = params.pop( 'serverIP', {} )
if not self.serverIP:
self.serverIP = { server: RemoteMixin.findServerIP( server )
for server in self.servers }
self.user = params.pop( 'user', findUser() )
if params.pop( 'precheck' ):
self.precheck()
self.connections = {}
self.placement = params.pop( 'placement', SwitchBinPlacer )
# Make sure control directory exists
self.cdir = os.environ[ 'HOME' ] + '/.ssh/mn'
errRun( [ 'mkdir', '-p', self.cdir ] )
Mininet.__init__( self, *args, **params )
def popen( self, cmd ):
"Popen() for server connections"
assert self # please pylint
old = signal( SIGINT, SIG_IGN )
conn = Popen( cmd, stdin=PIPE, stdout=PIPE, close_fds=True )
signal( SIGINT, old )
return conn
def baddLink( self, *args, **kwargs ):
"break addlink for testing"
pass
def precheck( self ):
"""Pre-check to make sure connection works and that
we can call sudo without a password"""
result = 0
info( '*** Checking servers\n' )
for server in self.servers:
ip = self.serverIP[ server ]
if not server or server == 'localhost':
continue
info( server, '' )
dest = '%s@%s' % ( self.user, ip )
cmd = [ 'sudo', '-E', '-u', self.user ]
cmd += self.sshcmd + [ '-n', dest, 'sudo true' ]
debug( ' '.join( cmd ), '\n' )
_out, _err, code = errRun( cmd )
if code != 0:
error( '\nstartConnection: server connection check failed '
'to %s using command:\n%s\n'
% ( server, ' '.join( cmd ) ) )
result |= code
if result:
error( '*** Server precheck failed.\n'
'*** Make sure that the above ssh command works'
' correctly.\n'
'*** You may also need to run mn -c on all nodes, and/or\n'
'*** use sudo -E.\n' )
sys.exit( 1 )
info( '\n' )
def modifiedaddHost( self, *args, **kwargs ):
"Slightly modify addHost"
assert self # please pylint
kwargs[ 'splitInit' ] = True
return Mininet.addHost( *args, **kwargs )
def placeNodes( self ):
"""Place nodes on servers (if they don't have a server), and
start shell processes"""
if not self.servers or not self.topo:
# No shirt, no shoes, no service
return
nodes = self.topo.nodes()
placer = self.placement( servers=self.servers,
nodes=self.topo.nodes(),
hosts=self.topo.hosts(),
switches=self.topo.switches(),
links=self.topo.links() )
for node in nodes:
config = self.topo.nodeInfo( node )
# keep local server name consistent accross nodes
if 'server' in config.keys() and config[ 'server' ] is None:
config[ 'server' ] = 'localhost'
server = config.setdefault( 'server', placer.place( node ) )
if server:
config.setdefault( 'serverIP', self.serverIP[ server ] )
info( '%s:%s ' % ( node, server ) )
key = ( None, server )
_dest, cfile, _conn = self.connections.get(
key, ( None, None, None ) )
if cfile:
config.setdefault( 'controlPath', cfile )
def addController( self, *args, **kwargs ):
"Patch to update IP address to global IP address"
controller = Mininet.addController( self, *args, **kwargs )
# Update IP address for controller that may not be local
if ( isinstance( controller, Controller)
and controller.IP() == '127.0.0.1'
and ' eth0:' in controller.cmd( 'ip link show' ) ):
Intf( 'eth0', node=controller ).updateIP()
return controller
def buildFromTopo( self, *args, **kwargs ):
"Start network"
info( '*** Placing nodes\n' )
self.placeNodes()
info( '\n' )
Mininet.buildFromTopo( self, *args, **kwargs )
def testNsTunnels():
"Test tunnels between nodes in namespaces"
net = Mininet( host=RemoteHost, link=RemoteLink )
h1 = net.addHost( 'h1' )
h2 = net.addHost( 'h2', server='ubuntu2' )
net.addLink( h1, h2 )
net.start()
net.pingAll()
net.stop()
# Manual topology creation with net.add*()
#
# This shows how node options may be used to manage
# cluster placement using the net.add*() API
def testRemoteNet( remote='ubuntu2' ):
"Test remote Node classes"
print '*** Remote Node Test'
net = Mininet( host=RemoteHost, switch=RemoteOVSSwitch,
link=RemoteLink )
c0 = net.addController( 'c0' )
# Make sure controller knows its non-loopback address
Intf( 'eth0', node=c0 ).updateIP()
print "*** Creating local h1"
h1 = net.addHost( 'h1' )
print "*** Creating remote h2"
h2 = net.addHost( 'h2', server=remote )
print "*** Creating local s1"
s1 = net.addSwitch( 's1' )
print "*** Creating remote s2"
s2 = net.addSwitch( 's2', server=remote )
print "*** Adding links"
net.addLink( h1, s1 )
net.addLink( s1, s2 )
net.addLink( h2, s2 )
net.start()
print 'Mininet is running on', quietRun( 'hostname' ).strip()
for node in c0, h1, h2, s1, s2:
print 'Node', node, 'is running on', node.cmd( 'hostname' ).strip()
net.pingAll()
CLI( net )
net.stop()
# High-level/Topo API example
#
# This shows how existing Mininet topologies may be used in cluster
# mode by creating node placement functions and a controller which
# can be accessed remotely. This implements a very compatible version
# of cluster edition with a minimum of code!
remoteHosts = [ 'h2' ]
remoteSwitches = [ 's2' ]
remoteServer = 'ubuntu2'
def HostPlacer( name, *args, **params ):
"Custom Host() constructor which places hosts on servers"
if name in remoteHosts:
return RemoteHost( name, *args, server=remoteServer, **params )
else:
return Host( name, *args, **params )
def SwitchPlacer( name, *args, **params ):
"Custom Switch() constructor which places switches on servers"
if name in remoteSwitches:
return RemoteOVSSwitch( name, *args, server=remoteServer, **params )
else:
return RemoteOVSSwitch( name, *args, **params )
def ClusterController( *args, **kwargs):
"Custom Controller() constructor which updates its eth0 IP address"
controller = Controller( *args, **kwargs )
# Find out its IP address so that cluster switches can connect
Intf( 'eth0', node=controller ).updateIP()
return controller
def testRemoteTopo():
"Test remote Node classes using Mininet()/Topo() API"
topo = LinearTopo( 2 )
net = Mininet( topo=topo, host=HostPlacer, switch=SwitchPlacer,
link=RemoteLink, controller=ClusterController )
net.start()
net.pingAll()
net.stop()
# Need to test backwards placement, where each host is on
# a server other than its switch!! But seriously we could just
# do random switch placement rather than completely random
# host placement.
def testRemoteSwitches():
"Test with local hosts and remote switches"
servers = [ 'localhost', 'ubuntu2']
topo = TreeTopo( depth=4, fanout=2 )
net = MininetCluster( topo=topo, servers=servers,
placement=RoundRobinPlacer )
net.start()
net.pingAll()
net.stop()
#
# For testing and demo purposes it would be nice to draw the
# network graph and color it based on server.
# The MininetCluster() class integrates pluggable placement
# functions, for maximum ease of use. MininetCluster() also
# pre-flights and multiplexes server connections.
def testMininetCluster():
"Test MininetCluster()"
servers = [ 'localhost', 'ubuntu2' ]
topo = TreeTopo( depth=3, fanout=3 )
net = MininetCluster( topo=topo, servers=servers,
placement=SwitchBinPlacer )
net.start()
net.pingAll()
net.stop()
def signalTest():
"Make sure hosts are robust to signals"
h = RemoteHost( 'h0', server='ubuntu1' )
h.shell.send_signal( SIGINT )
h.shell.poll()
if h.shell.returncode is None:
print 'OK: ', h, 'has not exited'
else:
print 'FAILURE:', h, 'exited with code', h.shell.returncode
h.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
# testRemoteTopo()
# testRemoteNet()
# testMininetCluster()
# testRemoteSwitches()
signalTest()
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/env python
'''
A sanity check for cluster edition
'''
from mininet.examples.cluster import MininetCluster
from mininet.log import setLogLevel
from mininet.examples.clustercli import ClusterCLI as CLI
from mininet.topo import SingleSwitchTopo
def clusterSanity():
"Sanity check for cluster mode"
topo = SingleSwitchTopo()
net = MininetCluster( topo=topo )
net.start()
CLI( net )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
clusterSanity()
-100
View File
@@ -1,100 +0,0 @@
#!/usr/bin/python
"CLI for Mininet Cluster Edition prototype demo"
from mininet.cli import CLI
from mininet.log import output, error
# pylint: disable=global-statement
nx, graphviz_layout, plt = None, None, None # Will be imported on demand
class ClusterCLI( CLI ):
"CLI with additional commands for Cluster Edition demo"
@staticmethod
def colorsFor( seq ):
"Return a list of background colors for a sequence"
colors = [ 'red', 'lightgreen', 'cyan', 'yellow', 'orange',
'magenta', 'pink', 'grey', 'brown',
'white' ]
slen, clen = len( seq ), len( colors )
reps = max( 1, slen / clen )
colors = colors * reps
colors = colors[ 0 : slen ]
return colors
def do_plot( self, _line ):
"Plot topology colored by node placement"
# Import networkx if needed
global nx, plt
if not nx:
try:
# pylint: disable=import-error
import networkx
nx = networkx # satisfy pylint
from matplotlib import pyplot
plt = pyplot # satisfiy pylint
import pygraphviz
assert pygraphviz # silence pyflakes
# pylint: enable=import-error
except ImportError:
error( 'plot requires networkx, matplotlib and pygraphviz - '
'please install them and try again\n' )
return
# Make a networkx Graph
g = nx.Graph()
mn = self.mn
servers, hosts, switches = mn.servers, mn.hosts, mn.switches
nodes = hosts + switches
g.add_nodes_from( nodes )
links = [ ( link.intf1.node, link.intf2.node )
for link in self.mn.links ]
g.add_edges_from( links )
# Pick some shapes and colors
# shapes = hlen * [ 's' ] + slen * [ 'o' ]
color = dict( zip( servers, self.colorsFor( servers ) ) )
# Plot it!
pos = nx.graphviz_layout( g )
opts = { 'ax': None, 'font_weight': 'bold',
'width': 2, 'edge_color': 'darkblue' }
hcolors = [ color[ getattr( h, 'server', 'localhost' ) ]
for h in hosts ]
scolors = [ color[ getattr( s, 'server', 'localhost' ) ]
for s in switches ]
nx.draw_networkx( g, pos=pos, nodelist=hosts, node_size=800,
label='host', node_color=hcolors, node_shape='s',
**opts )
nx.draw_networkx( g, pos=pos, nodelist=switches, node_size=1000,
node_color=scolors, node_shape='o', **opts )
# Get rid of axes, add title, and show
fig = plt.gcf()
ax = plt.gca()
ax.get_xaxis().set_visible( False )
ax.get_yaxis().set_visible( False )
fig.canvas.set_window_title( 'Mininet')
plt.title( 'Node Placement', fontweight='bold' )
plt.show()
def do_status( self, _line ):
"Report on node shell status"
nodes = self.mn.hosts + self.mn.switches
for node in nodes:
node.shell.poll()
exited = [ node for node in nodes
if node.shell.returncode is not None ]
if exited:
for node in exited:
output( '%s has exited with code %d\n'
% ( node, node.shell.returncode ) )
else:
output( 'All nodes are still running.\n' )
def do_placement( self, _line ):
"Describe node placement"
mn = self.mn
nodes = mn.hosts + mn.switches + mn.controllers
for server in mn.servers:
names = [ n.name for n in nodes if hasattr( n, 'server' )
and n.server == server ]
output( '%s: %s\n' % ( server, ' '.join( names ) ) )
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/python
"clusterdemo.py: demo of Mininet Cluster Edition prototype"
from mininet.examples.cluster import MininetCluster, SwitchBinPlacer
from mininet.topolib import TreeTopo
from mininet.log import setLogLevel
from mininet.examples.clustercli import ClusterCLI as CLI
def demo():
"Simple Demo of Cluster Mode"
servers = [ 'localhost', 'ubuntu2', 'ubuntu3' ]
topo = TreeTopo( depth=3, fanout=3 )
net = MininetCluster( topo=topo, servers=servers,
placement=SwitchBinPlacer )
net.start()
CLI( net )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
demo()
-466
View File
@@ -1,466 +0,0 @@
#!/usr/bin/python
"""
consoles.py: bring up a bunch of miniature consoles on a virtual network
This demo shows how to monitor a set of nodes by using
Node's monitor() and Tkinter's createfilehandler().
We monitor nodes in a couple of ways:
- First, each individual node is monitored, and its output is added
to its console window
- Second, each time a console window gets iperf output, it is parsed
and accumulated. Once we have output for all consoles, a bar is
added to the bandwidth graph.
The consoles also support limited interaction:
- Pressing "return" in a console will send a command to it
- Pressing the console's title button will open up an xterm
Bob Lantz, April 2010
"""
import re
from Tkinter import Frame, Button, Label, Text, Scrollbar, Canvas, Wm, READABLE
from mininet.log import setLogLevel
from mininet.topolib import TreeNet
from mininet.term import makeTerms, cleanUpScreens
from mininet.util import quietRun
class Console( Frame ):
"A simple console on a host."
def __init__( self, parent, net, node, height=10, width=32, title='Node' ):
Frame.__init__( self, parent )
self.net = net
self.node = node
self.prompt = node.name + '# '
self.height, self.width, self.title = height, width, title
# Initialize widget styles
self.buttonStyle = { 'font': 'Monaco 7' }
self.textStyle = {
'font': 'Monaco 7',
'bg': 'black',
'fg': 'green',
'width': self.width,
'height': self.height,
'relief': 'sunken',
'insertbackground': 'green',
'highlightcolor': 'green',
'selectforeground': 'black',
'selectbackground': 'green'
}
# Set up widgets
self.text = self.makeWidgets( )
self.bindEvents()
self.sendCmd( 'export TERM=dumb' )
self.outputHook = None
def makeWidgets( self ):
"Make a label, a text area, and a scroll bar."
def newTerm( net=self.net, node=self.node, title=self.title ):
"Pop up a new terminal window for a node."
net.terms += makeTerms( [ node ], title )
label = Button( self, text=self.node.name, command=newTerm,
**self.buttonStyle )
label.pack( side='top', fill='x' )
text = Text( self, wrap='word', **self.textStyle )
ybar = Scrollbar( self, orient='vertical', width=7,
command=text.yview )
text.configure( yscrollcommand=ybar.set )
text.pack( side='left', expand=True, fill='both' )
ybar.pack( side='right', fill='y' )
return text
def bindEvents( self ):
"Bind keyboard and file events."
# The text widget handles regular key presses, but we
# use special handlers for the following:
self.text.bind( '<Return>', self.handleReturn )
self.text.bind( '<Control-c>', self.handleInt )
self.text.bind( '<KeyPress>', self.handleKey )
# This is not well-documented, but it is the correct
# way to trigger a file event handler from Tk's
# event loop!
self.tk.createfilehandler( self.node.stdout, READABLE,
self.handleReadable )
# We're not a terminal (yet?), so we ignore the following
# control characters other than [\b\n\r]
ignoreChars = re.compile( r'[\x00-\x07\x09\x0b\x0c\x0e-\x1f]+' )
def append( self, text ):
"Append something to our text frame."
text = self.ignoreChars.sub( '', text )
self.text.insert( 'end', text )
self.text.mark_set( 'insert', 'end' )
self.text.see( 'insert' )
outputHook = lambda x, y: True # make pylint happier
if self.outputHook:
outputHook = self.outputHook
outputHook( self, text )
def handleKey( self, event ):
"If it's an interactive command, send it to the node."
char = event.char
if self.node.waiting:
self.node.write( char )
def handleReturn( self, event ):
"Handle a carriage return."
cmd = self.text.get( 'insert linestart', 'insert lineend' )
# Send it immediately, if "interactive" command
if self.node.waiting:
self.node.write( event.char )
return
# Otherwise send the whole line to the shell
pos = cmd.find( self.prompt )
if pos >= 0:
cmd = cmd[ pos + len( self.prompt ): ]
self.sendCmd( cmd )
# Callback ignores event
def handleInt( self, _event=None ):
"Handle control-c."
self.node.sendInt()
def sendCmd( self, cmd ):
"Send a command to our node."
if not self.node.waiting:
self.node.sendCmd( cmd )
def handleReadable( self, _fds, timeoutms=None ):
"Handle file readable event."
data = self.node.monitor( timeoutms )
self.append( data )
if not self.node.waiting:
# Print prompt
self.append( self.prompt )
def waiting( self ):
"Are we waiting for output?"
return self.node.waiting
def waitOutput( self ):
"Wait for any remaining output."
while self.node.waiting:
# A bit of a trade-off here...
self.handleReadable( self, timeoutms=1000)
self.update()
def clear( self ):
"Clear all of our text."
self.text.delete( '1.0', 'end' )
class Graph( Frame ):
"Graph that we can add bars to over time."
def __init__( self, parent=None, bg = 'white', gheight=200, gwidth=500,
barwidth=10, ymax=3.5,):
Frame.__init__( self, parent )
self.bg = bg
self.gheight = gheight
self.gwidth = gwidth
self.barwidth = barwidth
self.ymax = float( ymax )
self.xpos = 0
# Create everything
self.title, self.scale, self.graph = self.createWidgets()
self.updateScrollRegions()
self.yview( 'moveto', '1.0' )
def createScale( self ):
"Create a and return a new canvas with scale markers."
height = float( self.gheight )
width = 25
ymax = self.ymax
scale = Canvas( self, width=width, height=height,
background=self.bg )
opts = { 'fill': 'red' }
# Draw scale line
scale.create_line( width - 1, height, width - 1, 0, **opts )
# Draw ticks and numbers
for y in range( 0, int( ymax + 1 ) ):
ypos = height * (1 - float( y ) / ymax )
scale.create_line( width, ypos, width - 10, ypos, **opts )
scale.create_text( 10, ypos, text=str( y ), **opts )
return scale
def updateScrollRegions( self ):
"Update graph and scale scroll regions."
ofs = 20
height = self.gheight + ofs
self.graph.configure( scrollregion=( 0, -ofs,
self.xpos * self.barwidth, height ) )
self.scale.configure( scrollregion=( 0, -ofs, 0, height ) )
def yview( self, *args ):
"Scroll both scale and graph."
self.graph.yview( *args )
self.scale.yview( *args )
def createWidgets( self ):
"Create initial widget set."
# Objects
title = Label( self, text='Bandwidth (Gb/s)', bg=self.bg )
width = self.gwidth
height = self.gheight
scale = self.createScale()
graph = Canvas( self, width=width, height=height, background=self.bg)
xbar = Scrollbar( self, orient='horizontal', command=graph.xview )
ybar = Scrollbar( self, orient='vertical', command=self.yview )
graph.configure( xscrollcommand=xbar.set, yscrollcommand=ybar.set,
scrollregion=(0, 0, width, height ) )
scale.configure( yscrollcommand=ybar.set )
# Layout
title.grid( row=0, columnspan=3, sticky='new')
scale.grid( row=1, column=0, sticky='nsew' )
graph.grid( row=1, column=1, sticky='nsew' )
ybar.grid( row=1, column=2, sticky='ns' )
xbar.grid( row=2, column=0, columnspan=2, sticky='ew' )
self.rowconfigure( 1, weight=1 )
self.columnconfigure( 1, weight=1 )
return title, scale, graph
def addBar( self, yval ):
"Add a new bar to our graph."
percent = yval / self.ymax
c = self.graph
x0 = self.xpos * self.barwidth
x1 = x0 + self.barwidth
y0 = self.gheight
y1 = ( 1 - percent ) * self.gheight
c.create_rectangle( x0, y0, x1, y1, fill='green' )
self.xpos += 1
self.updateScrollRegions()
self.graph.xview( 'moveto', '1.0' )
def clear( self ):
"Clear graph contents."
self.graph.delete( 'all' )
self.xpos = 0
def test( self ):
"Add a bar for testing purposes."
ms = 1000
if self.xpos < 10:
self.addBar( self.xpos / 10 * self.ymax )
self.after( ms, self.test )
def setTitle( self, text ):
"Set graph title"
self.title.configure( text=text, font='Helvetica 9 bold' )
class ConsoleApp( Frame ):
"Simple Tk consoles for Mininet."
menuStyle = { 'font': 'Geneva 7 bold' }
def __init__( self, net, parent=None, width=4 ):
Frame.__init__( self, parent )
self.top = self.winfo_toplevel()
self.top.title( 'Mininet' )
self.net = net
self.menubar = self.createMenuBar()
cframe = self.cframe = Frame( self )
self.consoles = {} # consoles themselves
titles = {
'hosts': 'Host',
'switches': 'Switch',
'controllers': 'Controller'
}
for name in titles:
nodes = getattr( net, name )
frame, consoles = self.createConsoles(
cframe, nodes, width, titles[ name ] )
self.consoles[ name ] = Object( frame=frame, consoles=consoles )
self.selected = None
self.select( 'hosts' )
self.cframe.pack( expand=True, fill='both' )
cleanUpScreens()
# Close window gracefully
Wm.wm_protocol( self.top, name='WM_DELETE_WINDOW', func=self.quit )
# Initialize graph
graph = Graph( cframe )
self.consoles[ 'graph' ] = Object( frame=graph, consoles=[ graph ] )
self.graph = graph
self.graphVisible = False
self.updates = 0
self.hostCount = len( self.consoles[ 'hosts' ].consoles )
self.bw = 0
self.pack( expand=True, fill='both' )
def updateGraph( self, _console, output ):
"Update our graph."
m = re.search( r'(\d+.?\d*) ([KMG]?bits)/sec', output )
if not m:
return
val, units = float( m.group( 1 ) ), m.group( 2 )
#convert to Gbps
if units[0] == 'M':
val *= 10 ** -3
elif units[0] == 'K':
val *= 10 ** -6
elif units[0] == 'b':
val *= 10 ** -9
self.updates += 1
self.bw += val
if self.updates >= self.hostCount:
self.graph.addBar( self.bw )
self.bw = 0
self.updates = 0
def setOutputHook( self, fn=None, consoles=None ):
"Register fn as output hook [on specific consoles.]"
if consoles is None:
consoles = self.consoles[ 'hosts' ].consoles
for console in consoles:
console.outputHook = fn
def createConsoles( self, parent, nodes, width, title ):
"Create a grid of consoles in a frame."
f = Frame( parent )
# Create consoles
consoles = []
index = 0
for node in nodes:
console = Console( f, self.net, node, title=title )
consoles.append( console )
row = index / width
column = index % width
console.grid( row=row, column=column, sticky='nsew' )
index += 1
f.rowconfigure( row, weight=1 )
f.columnconfigure( column, weight=1 )
return f, consoles
def select( self, groupName ):
"Select a group of consoles to display."
if self.selected is not None:
self.selected.frame.pack_forget()
self.selected = self.consoles[ groupName ]
self.selected.frame.pack( expand=True, fill='both' )
def createMenuBar( self ):
"Create and return a menu (really button) bar."
f = Frame( self )
buttons = [
( 'Hosts', lambda: self.select( 'hosts' ) ),
( 'Switches', lambda: self.select( 'switches' ) ),
( 'Controllers', lambda: self.select( 'controllers' ) ),
( 'Graph', lambda: self.select( 'graph' ) ),
( 'Ping', self.ping ),
( 'Iperf', self.iperf ),
( 'Interrupt', self.stop ),
( 'Clear', self.clear ),
( 'Quit', self.quit )
]
for name, cmd in buttons:
b = Button( f, text=name, command=cmd, **self.menuStyle )
b.pack( side='left' )
f.pack( padx=4, pady=4, fill='x' )
return f
def clear( self ):
"Clear selection."
for console in self.selected.consoles:
console.clear()
def waiting( self, consoles=None ):
"Are any of our hosts waiting for output?"
if consoles is None:
consoles = self.consoles[ 'hosts' ].consoles
for console in consoles:
if console.waiting():
return True
return False
def ping( self ):
"Tell each host to ping the next one."
consoles = self.consoles[ 'hosts' ].consoles
if self.waiting( consoles ):
return
count = len( consoles )
i = 0
for console in consoles:
i = ( i + 1 ) % count
ip = consoles[ i ].node.IP()
console.sendCmd( 'ping ' + ip )
def iperf( self ):
"Tell each host to iperf to the next one."
consoles = self.consoles[ 'hosts' ].consoles
if self.waiting( consoles ):
return
count = len( consoles )
self.setOutputHook( self.updateGraph )
for console in consoles:
# Sometimes iperf -sD doesn't return,
# so we run it in the background instead
console.node.cmd( 'iperf -s &' )
i = 0
for console in consoles:
i = ( i + 1 ) % count
ip = consoles[ i ].node.IP()
console.sendCmd( 'iperf -t 99999 -i 1 -c ' + ip )
def stop( self, wait=True ):
"Interrupt all hosts."
consoles = self.consoles[ 'hosts' ].consoles
for console in consoles:
console.handleInt()
if wait:
for console in consoles:
console.waitOutput()
self.setOutputHook( None )
# Shut down any iperfs that might still be running
quietRun( 'killall -9 iperf' )
def quit( self ):
"Stop everything and quit."
self.stop( wait=False)
Frame.quit( self )
# Make it easier to construct and assign objects
def assign( obj, **kwargs ):
"Set a bunch of fields in an object."
obj.__dict__.update( kwargs )
class Object( object ):
"Generic object you can stuff junk into."
def __init__( self, **kwargs ):
assign( self, **kwargs )
if __name__ == '__main__':
setLogLevel( 'info' )
network = TreeNet( depth=2, fanout=4 )
network.start()
app = ConsoleApp( network, width=4 )
app.mainloop()
network.stop()
+70
View File
@@ -0,0 +1,70 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
from time import sleep
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
"""
This example demonstrates a basic consumer-producer using Mini-NDN. It uses ndnpeek and ndnpoke as
a consumer and a producer respectively. If you want to build your own consumer/producer program, you
can take help from here: https://github.com/named-data/ndn-cxx/tree/master/examples and
here: https://github.com/dulalsaurab/multicast-supression-ndn/tree/main/ndn-src/consumer-producer
"""
if __name__ == '__main__':
setLogLevel('info')
Minindn.cleanUp()
Minindn.verifyDependencies()
ndn = Minindn()
ndn.start()
info('Starting nfd and nlsr on nodes')
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
sleep(90)
# Default topology is used in this experiment "/topologies/default-topology.conf"
# lets make node "a" as a producer node, and node "c" as a consumer node
producer = ndn.net['a']
consumer = ndn.net['c']
# start producer
producerPrefix = "/example"
producer.cmd('nlsrc advertise {}'.format(producerPrefix))
sleep(5) # sleep for routing convergence
# Make sure that basic consumer/producer example are compiled and installed in the system
info('Starting consumer and producer application')
producer.cmd("echo 'HELLO WORLD' | ndnpoke {} &> producer.log &".format(producerPrefix))
consumer.cmd("ndnpeek -p {} &> consumer.log &".format(producerPrefix))
MiniNDNCLI(ndn.net)
ndn.stop()
-36
View File
@@ -1,36 +0,0 @@
#!/usr/bin/python
"""
Create a network where different switches are connected to
different controllers, by creating a custom Switch() subclass.
"""
from mininet.net import Mininet
from mininet.node import OVSSwitch, Controller, RemoteController
from mininet.topolib import TreeTopo
from mininet.log import setLogLevel
from mininet.cli import CLI
setLogLevel( 'info' )
# Two local and one "external" controller (which is actually c0)
# Ignore the warning message that the remote isn't (yet) running
c0 = Controller( 'c0', port=6633 )
c1 = Controller( 'c1', port=6634 )
c2 = RemoteController( 'c2', ip='127.0.0.1' )
cmap = { 's1': c0, 's2': c1, 's3': c2 }
class MultiSwitch( OVSSwitch ):
"Custom Switch() subclass that connects to different controllers"
def start( self, controllers ):
return OVSSwitch.start( self, [ cmap[ self.name ] ] )
topo = TreeTopo( depth=2, fanout=2 )
net = Mininet( topo=topo, switch=MultiSwitch, build=False )
for c in [ c0, c1 ]:
net.addController(c)
net.build()
net.start()
CLI( net )
net.stop()
-61
View File
@@ -1,61 +0,0 @@
#!/usr/bin/python
"""
This example creates a multi-controller network from semi-scratch by
using the net.add*() API and manually starting the switches and controllers.
This is the "mid-level" API, which is an alternative to the "high-level"
Topo() API which supports parametrized topology classes.
Note that one could also create a custom switch class and pass it into
the Mininet() constructor.
"""
from mininet.net import Mininet
from mininet.node import Controller, OVSSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel
def multiControllerNet():
"Create a network from semi-scratch with multiple controllers."
net = Mininet( controller=Controller, switch=OVSSwitch )
print "*** Creating (reference) controllers"
c1 = net.addController( 'c1', port=6633 )
c2 = net.addController( 'c2', port=6634 )
print "*** Creating switches"
s1 = net.addSwitch( 's1' )
s2 = net.addSwitch( 's2' )
print "*** Creating hosts"
hosts1 = [ net.addHost( 'h%d' % n ) for n in 3, 4 ]
hosts2 = [ net.addHost( 'h%d' % n ) for n in 5, 6 ]
print "*** Creating links"
for h in hosts1:
net.addLink( s1, h )
for h in hosts2:
net.addLink( s2, h )
net.addLink( s1, s2 )
print "*** Starting network"
net.build()
c1.start()
c2.start()
s1.start( [ c1 ] )
s2.start( [ c2 ] )
print "*** Testing network"
net.pingAll()
print "*** Running CLI"
CLI( net )
print "*** Stopping network"
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' ) # for CLI output
multiControllerNet()
-158
View File
@@ -1,158 +0,0 @@
#!/usr/bin/python
"""
controlnet.py: Mininet with a custom control network
We create two Mininet() networks, a control network
and a data network, running four DataControllers on the
control network to control the data network.
Since we're using UserSwitch on the data network,
it should correctly fail over to a backup controller.
We also use a Mininet Facade to talk to both the
control and data networks from a single CLI.
"""
from functools import partial
from mininet.net import Mininet
from mininet.node import Controller, UserSwitch
from mininet.cli import CLI
from mininet.topo import Topo
from mininet.topolib import TreeTopo
from mininet.log import setLogLevel, info
# Some minor hacks
class DataController( Controller ):
"""Data Network Controller.
patched to avoid checkListening error and to delete intfs"""
def checkListening( self ):
"Ignore spurious error"
pass
def stop( self, *args, **kwargs ):
"Make sure intfs are deleted"
kwargs.update( deleteIntfs=True )
super( DataController, self ).stop( *args, **kwargs )
class MininetFacade( object ):
"""Mininet object facade that allows a single CLI to
talk to one or more networks"""
def __init__( self, net, *args, **kwargs ):
"""Create MininetFacade object.
net: Primary Mininet object
args: unnamed networks passed as arguments
kwargs: named networks passed as arguments"""
self.net = net
self.nets = [ net ] + list( args ) + kwargs.values()
self.nameToNet = kwargs
self.nameToNet['net'] = net
def __getattr__( self, name ):
"returns attribute from Primary Mininet object"
return getattr( self.net, name )
def __getitem__( self, key ):
"returns primary/named networks or node from any net"
#search kwargs for net named key
if key in self.nameToNet:
return self.nameToNet[ key ]
#search each net for node named key
for net in self.nets:
if key in net:
return net[ key ]
def __iter__( self ):
"Iterate through all nodes in all Mininet objects"
for net in self.nets:
for node in net:
yield node
def __len__( self ):
"returns aggregate number of nodes in all nets"
count = 0
for net in self.nets:
count += len(net)
return count
def __contains__( self, key ):
"returns True if node is a member of any net"
return key in self.keys()
def keys( self ):
"returns a list of all node names in all networks"
return list( self )
def values( self ):
"returns a list of all nodes in all networks"
return [ self[ key ] for key in self ]
def items( self ):
"returns (key,value) tuple list for every node in all networks"
return zip( self.keys(), self.values() )
# A real control network!
class ControlNetwork( Topo ):
"Control Network Topology"
def __init__( self, n, dataController=DataController, **kwargs ):
"""n: number of data network controller nodes
dataController: class for data network controllers"""
Topo.__init__( self, **kwargs )
# Connect everything to a single switch
cs0 = self.addSwitch( 'cs0' )
# Add hosts which will serve as data network controllers
for i in range( 0, n ):
c = self.addHost( 'c%s' % i, cls=dataController,
inNamespace=True )
self.addLink( c, cs0 )
# Connect switch to root namespace so that data network
# switches will be able to talk to us
root = self.addHost( 'root', inNamespace=False )
self.addLink( root, cs0 )
# Make it Happen!!
def run():
"Create control and data networks, and invoke the CLI"
info( '* Creating Control Network\n' )
ctopo = ControlNetwork( n=4, dataController=DataController )
cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', controller=None )
info( '* Adding Control Network Controller\n')
cnet.addController( 'cc0', controller=Controller )
info( '* Starting Control Network\n')
cnet.start()
info( '* Creating Data Network\n' )
topo = TreeTopo( depth=2, fanout=2 )
# UserSwitch so we can easily test failover
sw = partial( UserSwitch, opts='--inactivity-probe=1 --max-backoff=1' )
net = Mininet( topo=topo, switch=sw, controller=None )
info( '* Adding Controllers to Data Network\n' )
for host in cnet.hosts:
if isinstance(host, Controller):
net.addController( host )
info( '* Starting Data Network\n')
net.start()
mn = MininetFacade( net, cnet=cnet )
CLI( mn )
info( '* Stopping Data Network\n' )
net.stop()
info( '* Stopping Control Network\n' )
cnet.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
run()
-73
View File
@@ -1,73 +0,0 @@
#!/usr/bin/python
"""
cpu.py: test iperf bandwidth for varying cpu limits
"""
from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.topolib import TreeTopo
from mininet.util import custom, waitListening
from mininet.log import setLogLevel, info
def bwtest( cpuLimits, period_us=100000, seconds=5 ):
"""Example/test of link and CPU bandwidth limits
cpu: cpu limit as fraction of overall CPU time"""
topo = TreeTopo( depth=1, fanout=2 )
results = {}
for sched in 'rt', 'cfs':
print '*** Testing with', sched, 'bandwidth limiting'
for cpu in cpuLimits:
host = custom( CPULimitedHost, sched=sched,
period_us=period_us,
cpu=cpu )
try:
net = Mininet( topo=topo, host=host )
# pylint: disable=bare-except
except:
info( '*** Skipping host %s\n' % sched )
break
net.start()
net.pingAll()
hosts = [ net.getNodeByName( h ) for h in topo.hosts() ]
client, server = hosts[ 0 ], hosts[ -1 ]
server.cmd( 'iperf -s -p 5001 &' )
waitListening( client, server, 5001 )
result = client.cmd( 'iperf -yc -t %s -c %s' % (
seconds, server.IP() ) ).split( ',' )
bps = float( result[ -1 ] )
server.cmdPrint( 'kill %iperf' )
net.stop()
updated = results.get( sched, [] )
updated += [ ( cpu, bps ) ]
results[ sched ] = updated
return results
def dump( results ):
"Dump results"
fmt = '%s\t%s\t%s'
print
print fmt % ( 'sched', 'cpu', 'client MB/s' )
print
for sched in sorted( results.keys() ):
entries = results[ sched ]
for cpu, bps in entries:
pct = '%.2f%%' % ( cpu * 100 )
mbps = bps / 1e6
print fmt % ( sched, pct, mbps )
if __name__ == '__main__':
setLogLevel( 'info' )
limits = [ .45, .4, .3, .2, .1 ]
out = bwtest( limits )
dump( out )
-44
View File
@@ -1,44 +0,0 @@
#!/usr/bin/python
"""
This example shows how to create an empty Mininet object
(without a topology object) and add nodes to it manually.
"""
from mininet.net import Mininet
from mininet.node import Controller
from mininet.cli import CLI
from mininet.log import setLogLevel, info
def emptyNet():
"Create an empty network and add nodes to it."
net = Mininet( controller=Controller )
info( '*** Adding controller\n' )
net.addController( 'c0' )
info( '*** Adding hosts\n' )
h1 = net.addHost( 'h1', ip='10.0.0.1' )
h2 = net.addHost( 'h2', ip='10.0.0.2' )
info( '*** Adding switch\n' )
s3 = net.addSwitch( 's3' )
info( '*** Creating links\n' )
net.addLink( h1, s3 )
net.addLink( h2, s3 )
info( '*** Starting network\n')
net.start()
info( '*** Running CLI\n' )
CLI( net )
info( '*** Stopping network' )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
emptyNet()
-52
View File
@@ -1,52 +0,0 @@
#!/usr/bin/python
"""
This example shows how to add an interface (for example a real
hardware interface) to a network after the network is created.
"""
import re
import sys
from mininet.cli import CLI
from mininet.log import setLogLevel, info, error
from mininet.net import Mininet
from mininet.link import Intf
from mininet.topolib import TreeTopo
from mininet.util import quietRun
def checkIntf( intf ):
"Make sure intf exists and is not configured."
if ( ' %s:' % intf ) not in quietRun( 'ip link show' ):
error( 'Error:', intf, 'does not exist!\n' )
exit( 1 )
ips = re.findall( r'\d+\.\d+\.\d+\.\d+', quietRun( 'ifconfig ' + intf ) )
if ips:
error( 'Error:', intf, 'has an IP address,'
'and is probably in use!\n' )
exit( 1 )
if __name__ == '__main__':
setLogLevel( 'info' )
# try to get hw intf from the command line; by default, use eth1
intfName = sys.argv[ 1 ] if len( sys.argv ) > 1 else 'eth1'
info( '*** Connecting to hw intf: %s' % intfName )
info( '*** Checking', intfName, '\n' )
checkIntf( intfName )
info( '*** Creating network\n' )
net = Mininet( topo=TreeTopo( depth=1, fanout=2 ) )
switch = net.switches[ 0 ]
info( '*** Adding hardware interface', intfName, 'to switch',
switch.name, '\n' )
_intf = Intf( intfName, node=switch )
info( '*** Note: you may need to reconfigure the interfaces for '
'the Mininet hosts:\n', net.hosts, '\n' )
net.start()
CLI( net )
net.stop()
-48
View File
@@ -1,48 +0,0 @@
#!/usr/bin/python
'''
example of using various TCIntf options.
reconfigures a single interface using intf.config()
to use different traffic control commands to test
bandwidth, loss, and delay
'''
from mininet.net import Mininet
from mininet.log import setLogLevel, info
from mininet.link import TCLink
def intfOptions():
"run various traffic control commands on a single interface"
net = Mininet( autoStaticArp=True )
net.addController( 'c0' )
h1 = net.addHost( 'h1' )
h2 = net.addHost( 'h2' )
s1 = net.addSwitch( 's1' )
link1 = net.addLink( h1, s1, cls=TCLink )
net.addLink( h2, s1 )
net.start()
# flush out latency from reactive forwarding delay
net.pingAll()
info( '\n*** Configuring one intf with bandwidth of 5 Mb\n' )
link1.intf1.config( bw=5 )
info( '\n*** Running iperf to test\n' )
net.iperf()
info( '\n*** Configuring one intf with loss of 50%\n' )
link1.intf1.config( loss=50 )
info( '\n' )
net.iperf( ( h1, h2 ), l4Type='UDP' )
info( '\n*** Configuring one intf with delay of 15ms\n' )
link1.intf1.config( delay='15ms' )
info( '\n*** Run a ping to confirm delay\n' )
net.pingPairFull()
info( '\n*** Done testing\n' )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
intfOptions()
+62
View File
@@ -0,0 +1,62 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2020, 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 <http://www.gnu.org/licenses/>.
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.helpers.ip_routing_helper import IPRoutingHelper
"""
This scenario demonstrates the functionality of the IPRoutingHelper. First, the routing helper
calculates and configures routes between all nodes and then calls the `pingAll` command to
demonstrate that all nodes are reachable.
Successful experiments end with: `*** Results: 0% dropped`
To demonstrate the IPRoutingHelper in more complex scenarios, consider starting the experiment with
the Geant-Topology (topologies/geant.conf).
"""
if __name__ == '__main__':
setLogLevel('info')
Minindn.cleanUp()
Minindn.verifyDependencies()
ndn = Minindn()
ndn.start()
info('Starting NFD on nodes\n')
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
info('Starting NLSR on nodes\n')
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
# Calculate all routes for IP routing
IPRoutingHelper.calcAllRoutes(ndn.net)
info("IP routes configured, start ping\n")
ndn.net.pingAll()
ndn.stop()
-60
View File
@@ -1,60 +0,0 @@
#!/usr/bin/python
"""
limit.py: example of using link and CPU limits
"""
from mininet.net import Mininet
from mininet.link import TCIntf
from mininet.node import CPULimitedHost
from mininet.topolib import TreeTopo
from mininet.util import custom, quietRun
from mininet.log import setLogLevel, info
def testLinkLimit( net, bw ):
"Run bandwidth limit test"
info( '*** Testing network %.2f Mbps bandwidth limit\n' % bw )
net.iperf()
def limit( bw=10, cpu=.1 ):
"""Example/test of link and CPU bandwidth limits
bw: interface bandwidth limit in Mbps
cpu: cpu limit as fraction of overall CPU time"""
intf = custom( TCIntf, bw=bw )
myTopo = TreeTopo( depth=1, fanout=2 )
for sched in 'rt', 'cfs':
info( '*** Testing with', sched, 'bandwidth limiting\n' )
if sched == 'rt':
release = quietRun( 'uname -r' ).strip('\r\n')
output = quietRun( 'grep CONFIG_RT_GROUP_SCHED /boot/config-%s'
% release )
if output == '# CONFIG_RT_GROUP_SCHED is not set\n':
info( '*** RT Scheduler is not enabled in your kernel. '
'Skipping this test\n' )
continue
host = custom( CPULimitedHost, sched=sched, cpu=cpu )
net = Mininet( topo=myTopo, intf=intf, host=host )
net.start()
testLinkLimit( net, bw=bw )
net.runCpuLimitTest( cpu=cpu )
net.stop()
def verySimpleLimit( bw=150 ):
"Absurdly simple limiting test"
intf = custom( TCIntf, bw=bw )
net = Mininet( intf=intf )
h1, h2 = net.addHost( 'h1' ), net.addHost( 'h2' )
net.addLink( h1, h2 )
net.start()
net.pingAll()
net.iperf()
h1.cmdPrint( 'tc -s qdisc ls dev', h1.defaultIntf() )
h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() )
h1.cmdPrint( 'tc -s qdisc ls dev', h1.defaultIntf() )
h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
limit()
-126
View File
@@ -1,126 +0,0 @@
#!/usr/bin/python
"""
Test bandwidth (using iperf) on linear networks of varying size,
using both kernel and user datapaths.
We construct a network of N hosts and N-1 switches, connected as follows:
h1 <-> s1 <-> s2 .. sN-1
| | |
h2 h3 hN
WARNING: by default, the reference controller only supports 16
switches, so this test WILL NOT WORK unless you have recompiled
your controller to support 100 switches (or more.)
In addition to testing the bandwidth across varying numbers
of switches, this example demonstrates:
- creating a custom topology, LinearTestTopo
- using the ping() and iperf() tests from Mininet()
- testing both the kernel and user switches
"""
from mininet.net import Mininet
from mininet.node import UserSwitch, OVSKernelSwitch, Controller
from mininet.topo import Topo
from mininet.log import lg
from mininet.util import irange, quietRun
from mininet.link import TCLink
from functools import partial
import sys
flush = sys.stdout.flush
class LinearTestTopo( Topo ):
"Topology for a string of N hosts and N-1 switches."
def __init__( self, N, **params ):
# Initialize topology
Topo.__init__( self, **params )
# Create switches and hosts
hosts = [ self.addHost( 'h%s' % h )
for h in irange( 1, N ) ]
switches = [ self.addSwitch( 's%s' % s )
for s in irange( 1, N - 1 ) ]
# Wire up switches
last = None
for switch in switches:
if last:
self.addLink( last, switch )
last = switch
# Wire up hosts
self.addLink( hosts[ 0 ], switches[ 0 ] )
for host, switch in zip( hosts[ 1: ], switches ):
self.addLink( host, switch )
def linearBandwidthTest( lengths ):
"Check bandwidth at various lengths along a switch chain."
results = {}
switchCount = max( lengths )
hostCount = switchCount + 1
switches = { 'reference user': UserSwitch,
'Open vSwitch kernel': OVSKernelSwitch }
# UserSwitch is horribly slow with recent kernels.
# We can reinstate it once its performance is fixed
del switches[ 'reference user' ]
topo = LinearTestTopo( hostCount )
# Select TCP Reno
output = quietRun( 'sysctl -w net.ipv4.tcp_congestion_control=reno' )
assert 'reno' in output
for datapath in switches.keys():
print "*** testing", datapath, "datapath"
Switch = switches[ datapath ]
results[ datapath ] = []
link = partial( TCLink, delay='1ms' )
net = Mininet( topo=topo, switch=Switch,
controller=Controller, waitConnected=True,
link=link )
net.start()
print "*** testing basic connectivity"
for n in lengths:
net.ping( [ net.hosts[ 0 ], net.hosts[ n ] ] )
print "*** testing bandwidth"
for n in lengths:
src, dst = net.hosts[ 0 ], net.hosts[ n ]
# Try to prime the pump to reduce PACKET_INs during test
# since the reference controller is reactive
src.cmd( 'telnet', dst.IP(), '5001' )
print "testing", src.name, "<->", dst.name,
bandwidth = net.iperf( [ src, dst ], seconds=10 )
print bandwidth
flush()
results[ datapath ] += [ ( n, bandwidth ) ]
net.stop()
for datapath in switches.keys():
print
print "*** Linear network results for", datapath, "datapath:"
print
result = results[ datapath ]
print "SwitchCount\tiperf Results"
for switchCount, bandwidth in result:
print switchCount, '\t\t',
print bandwidth[ 0 ], 'server, ', bandwidth[ 1 ], 'client'
print
print
if __name__ == '__main__':
lg.setLogLevel( 'info' )
sizes = [ 1, 10, 20, 40, 60, 80, 100 ]
print "*** Running linearBandwidthTest", sizes
linearBandwidthTest( sizes )
-89
View File
@@ -1,89 +0,0 @@
#!/usr/bin/python
"""
linuxrouter.py: Example network with Linux IP router
This example converts a Node into a router using IP forwarding
already built into Linux.
The example topology creates a router and three IP subnets:
- 192.168.1.0/24 (r0-eth1, IP: 192.168.1.1)
- 172.16.0.0/12 (r0-eth2, IP: 172.16.0.1)
- 10.0.0.0/8 (r0-eth3, IP: 10.0.0.1)
Each subnet consists of a single host connected to
a single switch:
r0-eth1 - s1-eth1 - h1-eth0 (IP: 192.168.1.100)
r0-eth2 - s2-eth1 - h2-eth0 (IP: 172.16.0.100)
r0-eth3 - s3-eth1 - h3-eth0 (IP: 10.0.0.100)
The example relies on default routing entries that are
automatically created for each router interface, as well
as 'defaultRoute' parameters for the host interfaces.
Additional routes may be added to the router or hosts by
executing 'ip route' or 'route' commands on the router or hosts.
"""
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import Node
from mininet.log import setLogLevel, info
from mininet.cli import CLI
class LinuxRouter( Node ):
"A Node with IP forwarding enabled."
def config( self, **params ):
super( LinuxRouter, self).config( **params )
# Enable forwarding on the router
self.cmd( 'sysctl net.ipv4.ip_forward=1' )
def terminate( self ):
self.cmd( 'sysctl net.ipv4.ip_forward=0' )
super( LinuxRouter, self ).terminate()
class NetworkTopo( Topo ):
"A LinuxRouter connecting three IP subnets"
def build( self, **_opts ):
defaultIP = '192.168.1.1/24' # IP address for r0-eth1
router = self.addNode( 'r0', cls=LinuxRouter, ip=defaultIP )
s1, s2, s3 = [ self.addSwitch( s ) for s in 's1', 's2', 's3' ]
self.addLink( s1, router, intfName2='r0-eth1',
params2={ 'ip' : defaultIP } ) # for clarity
self.addLink( s2, router, intfName2='r0-eth2',
params2={ 'ip' : '172.16.0.1/12' } )
self.addLink( s3, router, intfName2='r0-eth3',
params2={ 'ip' : '10.0.0.1/8' } )
h1 = self.addHost( 'h1', ip='192.168.1.100/24',
defaultRoute='via 192.168.1.1' )
h2 = self.addHost( 'h2', ip='172.16.0.100/12',
defaultRoute='via 172.16.0.1' )
h3 = self.addHost( 'h3', ip='10.0.0.100/8',
defaultRoute='via 10.0.0.1' )
for h, s in [ (h1, s1), (h2, s2), (h3, s3) ]:
self.addLink( h, s )
def run():
"Test linux router"
topo = NetworkTopo()
net = Mininet( topo=topo ) # controller is used by s1-s3
net.start()
info( '*** Routing Table on Router:\n' )
print net[ 'r0' ].cmd( 'route' )
CLI( net )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
run()
-3584
View File
File diff suppressed because it is too large Load Diff
+49
View File
@@ -0,0 +1,49 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2020, 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 <http://www.gnu.org/licenses/>.
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
if __name__ == '__main__':
setLogLevel('info')
Minindn.cleanUp()
Minindn.verifyDependencies()
ndn = Minindn()
ndn.start()
info('Starting NFD on nodes\n')
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
info('Starting NLSR on nodes\n')
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
MiniNDNCLI(ndn.net)
ndn.stop()
-134
View File
@@ -1,134 +0,0 @@
#!/usr/bin/python
"""
Simple example of Mobility with Mininet
(aka enough rope to hang yourself.)
We move a host from s1 to s2, s2 to s3, and then back to s1.
Gotchas:
The reference controller doesn't support mobility, so we need to
manually flush the switch flow tables!
Good luck!
to-do:
- think about wifi/hub behavior
- think about clearing last hop - why doesn't that work?
"""
from mininet.net import Mininet
from mininet.node import OVSSwitch
from mininet.topo import LinearTopo
from mininet.log import output, warn
from random import randint
class MobilitySwitch( OVSSwitch ):
"Switch that can reattach and rename interfaces"
def delIntf( self, intf ):
"Remove (and detach) an interface"
port = self.ports[ intf ]
del self.ports[ intf ]
del self.intfs[ port ]
del self.nameToIntf[ intf.name ]
def addIntf( self, intf, rename=False, **kwargs ):
"Add (and reparent) an interface"
OVSSwitch.addIntf( self, intf, **kwargs )
intf.node = self
if rename:
self.renameIntf( intf )
def attach( self, intf ):
"Attach an interface and set its port"
port = self.ports[ intf ]
if port:
if self.isOldOVS():
self.cmd( 'ovs-vsctl add-port', self, intf )
else:
self.cmd( 'ovs-vsctl add-port', self, intf,
'-- set Interface', intf,
'ofport_request=%s' % port )
self.validatePort( intf )
def validatePort( self, intf ):
"Validate intf's OF port number"
ofport = int( self.cmd( 'ovs-vsctl get Interface', intf,
'ofport' ) )
if ofport != self.ports[ intf ]:
warn( 'WARNING: ofport for', intf, 'is actually', ofport,
'\n' )
def renameIntf( self, intf, newname='' ):
"Rename an interface (to its canonical name)"
intf.ifconfig( 'down' )
if not newname:
newname = '%s-eth%d' % ( self.name, self.ports[ intf ] )
intf.cmd( 'ip link set', intf, 'name', newname )
del self.nameToIntf[ intf.name ]
intf.name = newname
self.nameToIntf[ intf.name ] = intf
intf.ifconfig( 'up' )
def moveIntf( self, intf, switch, port=None, rename=True ):
"Move one of our interfaces to another switch"
self.detach( intf )
self.delIntf( intf )
switch.addIntf( intf, port=port, rename=rename )
switch.attach( intf )
def printConnections( switches ):
"Compactly print connected nodes to each switch"
for sw in switches:
output( '%s: ' % sw )
for intf in sw.intfList():
link = intf.link
if link:
intf1, intf2 = link.intf1, link.intf2
remote = intf1 if intf1.node != sw else intf2
output( '%s(%s) ' % ( remote.node, sw.ports[ intf ] ) )
output( '\n' )
def moveHost( host, oldSwitch, newSwitch, newPort=None ):
"Move a host from old switch to new switch"
hintf, sintf = host.connectionsTo( oldSwitch )[ 0 ]
oldSwitch.moveIntf( sintf, newSwitch, port=newPort )
return hintf, sintf
def mobilityTest():
"A simple test of mobility"
print '* Simple mobility test'
net = Mininet( topo=LinearTopo( 3 ), switch=MobilitySwitch )
print '* Starting network:'
net.start()
printConnections( net.switches )
print '* Testing network'
net.pingAll()
print '* Identifying switch interface for h1'
h1, old = net.get( 'h1', 's1' )
for s in 2, 3, 1:
new = net[ 's%d' % s ]
port = randint( 10, 20 )
print '* Moving', h1, 'from', old, 'to', new, 'port', port
hintf, sintf = moveHost( h1, old, new, newPort=port )
print '*', hintf, 'is now connected to', sintf
print '* Clearing out old flows'
for sw in net.switches:
sw.dpctl( 'del-flows' )
print '* New network:'
printConnections( net.switches )
print '* Testing connectivity:'
net.pingAll()
old = new
net.stop()
if __name__ == '__main__':
mobilityTest()
-36
View File
@@ -1,36 +0,0 @@
#!/usr/bin/python
"""
This is a simple example that demonstrates multiple links
between nodes.
"""
from mininet.cli import CLI
from mininet.log import setLogLevel
from mininet.net import Mininet
from mininet.topo import Topo
def runMultiLink():
"Create and run multiple link network"
topo = simpleMultiLinkTopo( n=2 )
net = Mininet( topo=topo )
net.start()
CLI( net )
net.stop()
class simpleMultiLinkTopo( Topo ):
"Simple topology with multiple links"
def __init__( self, n, **kwargs ):
Topo.__init__( self, **kwargs )
h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' )
s1 = self.addSwitch( 's1' )
for _ in range( n ):
self.addLink( s1, h1 )
self.addLink( s1, h2 )
if __name__ == '__main__':
setLogLevel( 'info' )
runMultiLink()
-83
View File
@@ -1,83 +0,0 @@
#!/usr/bin/python
"""
multiping.py: monitor multiple sets of hosts using ping
This demonstrates how one may send a simple shell script to
multiple hosts and monitor their output interactively for a period=
of time.
"""
from mininet.net import Mininet
from mininet.node import Node
from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel
from select import poll, POLLIN
from time import time
def chunks( l, n ):
"Divide list l into chunks of size n - thanks Stackoverflow"
return [ l[ i: i + n ] for i in range( 0, len( l ), n ) ]
def startpings( host, targetips ):
"Tell host to repeatedly ping targets"
targetips = ' '.join( targetips )
# Simple ping loop
cmd = ( 'while true; do '
' for ip in %s; do ' % targetips +
' echo -n %s "->" $ip ' % host.IP() +
' `ping -c1 -w 1 $ip | grep packets` ;'
' sleep 1;'
' done; '
'done &' )
print ( '*** Host %s (%s) will be pinging ips: %s' %
( host.name, host.IP(), targetips ) )
host.cmd( cmd )
def multiping( netsize, chunksize, seconds):
"Ping subsets of size chunksize in net of size netsize"
# Create network and identify subnets
topo = SingleSwitchTopo( netsize )
net = Mininet( topo=topo )
net.start()
hosts = net.hosts
subnets = chunks( hosts, chunksize )
# Create polling object
fds = [ host.stdout.fileno() for host in hosts ]
poller = poll()
for fd in fds:
poller.register( fd, POLLIN )
# Start pings
for subnet in subnets:
ips = [ host.IP() for host in subnet ]
#adding bogus to generate packet loss
ips.append( '10.0.0.200' )
for host in subnet:
startpings( host, ips )
# Monitor output
endTime = time() + seconds
while time() < endTime:
readable = poller.poll(1000)
for fd, _mask in readable:
node = Node.outToNode[ fd ]
print '%s:' % node.name, node.monitor().strip()
# Stop pings
for host in hosts:
host.cmd( 'kill %while' )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
multiping( netsize=20, chunksize=4, seconds=10 )
-81
View File
@@ -1,81 +0,0 @@
#!/usr/bin/python
"""
Simple example of sending output to multiple files and
monitoring them
"""
from mininet.topo import SingleSwitchTopo
from mininet.net import Mininet
from mininet.log import setLogLevel
from time import time
from select import poll, POLLIN
from subprocess import Popen, PIPE
def monitorFiles( outfiles, seconds, timeoutms ):
"Monitor set of files and return [(host, line)...]"
devnull = open( '/dev/null', 'w' )
tails, fdToFile, fdToHost = {}, {}, {}
for h, outfile in outfiles.iteritems():
tail = Popen( [ 'tail', '-f', outfile ],
stdout=PIPE, stderr=devnull )
fd = tail.stdout.fileno()
tails[ h ] = tail
fdToFile[ fd ] = tail.stdout
fdToHost[ fd ] = h
# Prepare to poll output files
readable = poll()
for t in tails.values():
readable.register( t.stdout.fileno(), POLLIN )
# Run until a set number of seconds have elapsed
endTime = time() + seconds
while time() < endTime:
fdlist = readable.poll(timeoutms)
if fdlist:
for fd, _flags in fdlist:
f = fdToFile[ fd ]
host = fdToHost[ fd ]
# Wait for a line of output
line = f.readline().strip()
yield host, line
else:
# If we timed out, return nothing
yield None, ''
for t in tails.values():
t.terminate()
devnull.close() # Not really necessary
def monitorTest( N=3, seconds=3 ):
"Run pings and monitor multiple hosts"
topo = SingleSwitchTopo( N )
net = Mininet( topo )
net.start()
hosts = net.hosts
print "Starting test..."
server = hosts[ 0 ]
outfiles, errfiles = {}, {}
for h in hosts:
# Create and/or erase output files
outfiles[ h ] = '/tmp/%s.out' % h.name
errfiles[ h ] = '/tmp/%s.err' % h.name
h.cmd( 'echo >', outfiles[ h ] )
h.cmd( 'echo >', errfiles[ h ] )
# Start pings
h.cmdPrint('ping', server.IP(),
'>', outfiles[ h ],
'2>', errfiles[ h ],
'&' )
print "Monitoring output for", seconds, "seconds"
for h, line in monitorFiles( outfiles, seconds, timeoutms=500 ):
if h:
print '%s: %s' % ( h.name, line )
for h in hosts:
h.cmd('kill %ping')
net.stop()
if __name__ == '__main__':
setLogLevel('info')
monitorTest()
-35
View File
@@ -1,35 +0,0 @@
#!/usr/bin/python
"""
This example shows how to create a network and run multiple tests.
For a more complicated test example, see udpbwtest.py.
"""
from mininet.cli import CLI
from mininet.log import lg, info
from mininet.net import Mininet
from mininet.node import OVSKernelSwitch
from mininet.topolib import TreeTopo
def ifconfigTest( net ):
"Run ifconfig on all hosts in net."
hosts = net.hosts
for host in hosts:
info( host.cmd( 'ifconfig' ) )
if __name__ == '__main__':
lg.setLogLevel( 'info' )
info( "*** Initializing Mininet and kernel modules\n" )
OVSKernelSwitch.setup()
info( "*** Creating network\n" )
network = Mininet( TreeTopo( depth=2, fanout=2 ), switch=OVSKernelSwitch )
info( "*** Starting network\n" )
network.start()
info( "*** Running ping test\n" )
network.pingAll()
info( "*** Running ifconfig test\n" )
ifconfigTest( network )
info( "*** Starting CLI (type 'exit' to exit)\n" )
CLI( network )
info( "*** Stopping network\n" )
network.stop()
-112
View File
@@ -1,112 +0,0 @@
#!/usr/bin/python
"""
Example to create a Mininet topology and connect it to the internet via NAT
through eth0 on the host.
Glen Gibb, February 2011
(slight modifications by BL, 5/13)
"""
from mininet.cli import CLI
from mininet.log import lg
from mininet.node import Node
from mininet.topolib import TreeNet
#################################
def startNAT( root, inetIntf='eth0', subnet='10.0/8' ):
"""Start NAT/forwarding between Mininet and external network
root: node to access iptables from
inetIntf: interface for internet access
subnet: Mininet subnet (default 10.0/8)="""
# Identify the interface connecting to the mininet network
localIntf = root.defaultIntf()
# Flush any currently active rules
root.cmd( 'iptables -F' )
root.cmd( 'iptables -t nat -F' )
# Create default entries for unmatched traffic
root.cmd( 'iptables -P INPUT ACCEPT' )
root.cmd( 'iptables -P OUTPUT ACCEPT' )
root.cmd( 'iptables -P FORWARD DROP' )
# Configure NAT
root.cmd( 'iptables -I FORWARD -i', localIntf, '-d', subnet, '-j DROP' )
root.cmd( 'iptables -A FORWARD -i', localIntf, '-s', subnet, '-j ACCEPT' )
root.cmd( 'iptables -A FORWARD -i', inetIntf, '-d', subnet, '-j ACCEPT' )
root.cmd( 'iptables -t nat -A POSTROUTING -o ', inetIntf, '-j MASQUERADE' )
# Instruct the kernel to perform forwarding
root.cmd( 'sysctl net.ipv4.ip_forward=1' )
def stopNAT( root ):
"""Stop NAT/forwarding between Mininet and external network"""
# Flush any currently active rules
root.cmd( 'iptables -F' )
root.cmd( 'iptables -t nat -F' )
# Instruct the kernel to stop forwarding
root.cmd( 'sysctl net.ipv4.ip_forward=0' )
def fixNetworkManager( root, intf ):
"""Prevent network-manager from messing with our interface,
by specifying manual configuration in /etc/network/interfaces
root: a node in the root namespace (for running commands)
intf: interface name"""
cfile = '/etc/network/interfaces'
line = '\niface %s inet manual\n' % intf
config = open( cfile ).read()
if line not in config:
print '*** Adding', line.strip(), 'to', cfile
with open( cfile, 'a' ) as f:
f.write( line )
# Probably need to restart network-manager to be safe -
# hopefully this won't disconnect you
root.cmd( 'service network-manager restart' )
def connectToInternet( network, switch='s1', rootip='10.254', subnet='10.0/8'):
"""Connect the network to the internet
switch: switch to connect to root namespace
rootip: address for interface in root namespace
subnet: Mininet subnet"""
switch = network.get( switch )
prefixLen = subnet.split( '/' )[ 1 ]
# Create a node in root namespace
root = Node( 'root', inNamespace=False )
# Prevent network-manager from interfering with our interface
fixNetworkManager( root, 'root-eth0' )
# Create link between root NS and switch
link = network.addLink( root, switch )
link.intf1.setIP( rootip, prefixLen )
# Start network that now includes link to root namespace
network.start()
# Start NAT and establish forwarding
startNAT( root )
# Establish routes from end hosts
for host in network.hosts:
host.cmd( 'ip route flush root 0/0' )
host.cmd( 'route add -net', subnet, 'dev', host.defaultIntf() )
host.cmd( 'route add default gw', rootip )
return root
if __name__ == '__main__':
lg.setLogLevel( 'info')
net = TreeNet( depth=1, fanout=4 )
# Configure and start NATted connectivity
rootnode = connectToInternet( net )
print "*** Hosts are running and should have internet connectivity"
print "*** Type 'exit' or control-D to shut down network"
CLI( net )
# Shut down NAT
stopNAT( rootnode )
net.stop()
-69
View File
@@ -1,69 +0,0 @@
#!/usr/bin/python
"""
natnet.py: Example network with NATs
h0
|
s0
|
----------------
| |
nat1 nat2
| |
s1 s2
| |
h1 h2
"""
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.nodelib import NAT
from mininet.log import setLogLevel
from mininet.cli import CLI
from mininet.util import irange
class InternetTopo(Topo):
"Single switch connected to n hosts."
def __init__(self, n=2, **opts):
Topo.__init__(self, **opts)
# set up inet switch
inetSwitch = self.addSwitch('s0')
# add inet host
inetHost = self.addHost('h0')
self.addLink(inetSwitch, inetHost)
# add local nets
for i in irange(1, n):
inetIntf = 'nat%d-eth0' % i
localIntf = 'nat%d-eth1' % i
localIP = '192.168.%d.1' % i
localSubnet = '192.168.%d.0/24' % i
natParams = { 'ip' : '%s/24' % localIP }
# add NAT to topology
nat = self.addNode('nat%d' % i, cls=NAT, subnet=localSubnet,
inetIntf=inetIntf, localIntf=localIntf)
switch = self.addSwitch('s%d' % i)
# connect NAT to inet and local switches
self.addLink(nat, inetSwitch, intfName1=inetIntf)
self.addLink(nat, switch, intfName1=localIntf, params1=natParams)
# add host and connect to local switch
host = self.addHost('h%d' % i,
ip='192.168.%d.100/24' % i,
defaultRoute='via %s' % localIP)
self.addLink(host, switch)
def run():
"Create network and run the CLI"
topo = InternetTopo()
net = Mininet(topo=topo)
net.start()
CLI(net)
net.stop()
if __name__ == '__main__':
setLogLevel('info')
run()
+79
View File
@@ -0,0 +1,79 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2019, 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 <http://www.gnu.org/licenses/>.
import time
import sys
from mininet.log import setLogLevel, info
from mininet.topo import Topo
from minindn.minindn import Minindn
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from nlsr_common import getParser
if __name__ == '__main__':
setLogLevel('info')
topo = Topo()
h1 = topo.addHost('h1')
h2 = topo.addHost('h2')
topo.addLink(h1, h2, delay='10ms')
ndn = Minindn(parser=getParser(), topo=topo)
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, [], Nlsr)
host1 = ndn.net.hosts[0]
nlsrs.startOnNode(host1, security=args.security, faceType=args.faceType,
nFaces=args.faces, routingType=args.routingType)
expectedTotalCount = 500
for i in range(0, expectedTotalCount):
host1.cmd('nlsrc advertise /long/name/to/exceed/max/packet/size/host1/{}'.format(i))
time.sleep(60)
host2 = ndn.net.hosts[1]
nlsrs.startOnNode(host2, security=args.security, faceType=args.faceType,
nFaces=args.faces, routingType=args.routingType)
time.sleep(60)
advertiseCount = int(host2.cmd('nfdc fib | grep host1 | wc -l'))
info(advertiseCount)
if advertiseCount == expectedTotalCount:
info('\nSuccessfully advertised {} prefixes\n'.format(expectedTotalCount))
else:
info('\nAdvertising {} prefixes failed. Exiting...\n'.format(expectedTotalCount))
ndn.stop()
sys.exit(1)
ndn.stop()
+64
View File
@@ -0,0 +1,64 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2019, 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 <http://www.gnu.org/licenses/>.
import time
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.helpers.experiment import Experiment
from nlsr_common import getParser
if __name__ == '__main__':
setLogLevel('info')
ndn = Minindn(parser=getParser())
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, [], Nlsr)
i = 1
info('Starting NLSR on nodes\n')
for host in ndn.net.hosts:
nlsrs.startOnNode(host, security=args.security, sync=args.sync, faceType=args.faceType,
nFaces=args.faces, routingType=args.routingType)
# Wait 1/2 minute between starting NLSRs
# Wait 1 hour before starting last NLSR
if i == len(ndn.net.hosts) - 1:
info('Sleeping 1 hour before starting last NLSR\n')
time.sleep(3600)
else:
time.sleep(30)
i += 1
Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
ndn.stop()
+90
View File
@@ -0,0 +1,90 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
import time
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.helpers.experiment import Experiment
from minindn.helpers.nfdc import Nfdc
from minindn.helpers.ndnping import NDNPing
from nlsr_common import getParser
def mcnFailure(ndn, nfds, nlsrs, args):
Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
if args.nPings != 0:
Experiment.setupPing(ndn.net.hosts, Nfdc.STRATEGY_BEST_ROUTE)
pingedDict = Experiment.startPctPings(ndn.net, args.nPings, args.pctTraffic)
PING_COLLECTION_TIME_BEFORE_FAILURE = 60
PING_COLLECTION_TIME_AFTER_RECOVERY = 120
time.sleep(PING_COLLECTION_TIME_BEFORE_FAILURE)
mcn = max(ndn.net.hosts, key=lambda host: len(host.intfNames()))
info('Bringing down node {}\n'.format(mcn.name))
nlsrs[mcn.name].stop()
nfds[mcn.name].stop()
time.sleep(args.ctime)
info('Bringing up node {}\n'.format(mcn.name))
nfds[mcn.name].start()
nlsrs[mcn.name].start()
# Restart pings
if args.nPings != 0:
Experiment.setupPing([mcn], Nfdc.STRATEGY_BEST_ROUTE)
for nodeToPing in pingedDict[mcn]:
NDNPing.ping(mcn, nodeToPing, nPings=PING_COLLECTION_TIME_AFTER_RECOVERY)
time.sleep(PING_COLLECTION_TIME_AFTER_RECOVERY)
Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
if __name__ == '__main__':
setLogLevel('info')
ndn = Minindn(parser=getParser())
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
security=args.security, faceType=args.faceType,
nFaces=args.faces, routingType=args.routingType)
mcnFailure(ndn, nfds, nlsrs, args)
if args.isCliEnabled:
MiniNDNCLI(ndn.net)
ndn.stop()
+109
View File
@@ -0,0 +1,109 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
import time
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.helpers.experiment import Experiment
from minindn.helpers.nfdc import Nfdc
from minindn.helpers.ndnping import NDNPing
from nlsr_common import getParser
def multipleFailure(ndn, nfds, nlsrs, args):
Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
Experiment.setupPing(ndn.net.hosts, Nfdc.STRATEGY_BEST_ROUTE)
PING_COLLECTION_TIME_BEFORE_FAILURE = 60
FAILURE_INTERVAL = 60
RECOVERY_INTERVAL = 60
# Number of pings required to make it through the full experiment
nInitialPings = (PING_COLLECTION_TIME_BEFORE_FAILURE +
len(ndn.net.hosts) * (FAILURE_INTERVAL + RECOVERY_INTERVAL))
print('Scheduling with {} initial pings'.format(nInitialPings))
pingedDict = Experiment.startPctPings(ndn.net, nInitialPings, args.pctTraffic)
time.sleep(PING_COLLECTION_TIME_BEFORE_FAILURE)
nNodesRemainingToFail = len(ndn.net.hosts)
for host in ndn.net.hosts:
# Fail the node
info('Bringing down node {}\n'.format(host.name))
nlsrs[host.name].stop()
nfds[host.name].stop()
# Stay in failure state for FAILURE_INTERVAL seconds
time.sleep(FAILURE_INTERVAL)
# Bring the node back up
start_time = time.time()
info('Bringing up node {}\n'.format(host.name))
nfds[host.name].start()
nlsrs[host.name].start()
Experiment.setupPing([host], Nfdc.STRATEGY_BEST_ROUTE)
recovery_time = int(time.time() - start_time)
# Number of pings required to reach the end of the test
nNodesRemainingToFail -= 1
nPings = ((RECOVERY_INTERVAL - recovery_time) +
nNodesRemainingToFail * (FAILURE_INTERVAL + RECOVERY_INTERVAL))
info('Scheduling with {} remaining pings\n'.format(nPings))
# Restart pings
for nodeToPing in pingedDict[host]:
NDNPing.ping(host, nodeToPing, nPings=nPings)
time.sleep(RECOVERY_INTERVAL - recovery_time)
Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
if __name__ == '__main__':
setLogLevel('info')
ndn = Minindn(parser=getParser())
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
security=args.security, faceType=args.faceType,
nFaces=args.faces, routingType=args.routingType)
multipleFailure(ndn, nfds, nlsrs, args)
if args.isCliEnabled:
MiniNDNCLI(ndn.net)
ndn.stop()
+57
View File
@@ -0,0 +1,57 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2019, 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 <http://www.gnu.org/licenses/>.
import argparse
def getParser():
parser = argparse.ArgumentParser()
parser.add_argument('--ctime', type=int, default=60,
help='Specify convergence time for the topology (Default: 60 seconds)')
parser.add_argument('--faces', type=int, default=3,
help='Specify number of max faces per prefix for NLSR 0-60')
parser.add_argument('--routing', dest='routingType', default='link-state',
choices=['link-state', 'hr', 'dry'],
help='''Choose routing type, dry = link-state is used
but hr is calculated for comparision.''')
parser.add_argument('--sync', dest='sync', default='psync',
choices=['chronosync', 'psync'],
help='choose the sync protocol to be used by NLSR.')
parser.add_argument('--security', action='store_true', dest='security',
help='Enables NLSR security')
parser.add_argument('--face-type', dest='faceType', default='udp', choices=['udp', 'tcp'])
parser.add_argument('--no-cli', action='store_false', dest='isCliEnabled',
help='Run experiments and exit without showing the command line interface')
parser.add_argument('--pct-traffic', dest='pctTraffic', type=float, default=1.0,
help='Specify the percentage of nodes each node should ping')
parser.add_argument('--nPings', type=int, default=300,
help='Number of pings to perform between each node in the experiment')
return parser
+63
View File
@@ -0,0 +1,63 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2019, 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 <http://www.gnu.org/licenses/>.
import time
from mininet.log import setLogLevel
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.helpers.experiment import Experiment
from minindn.helpers.nfdc import Nfdc
from nlsr_common import getParser
if __name__ == '__main__':
setLogLevel('info')
ndn = Minindn(parser=getParser())
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
security=args.security, faceType=args.faceType,
nFaces=args.faces, routingType=args.routingType,
logLevel='ndn.*=TRACE:nlsr.*=TRACE')
Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=False)
if args.nPings != 0:
Experiment.setupPing(ndn.net.hosts, Nfdc.STRATEGY_BEST_ROUTE)
Experiment.startPctPings(ndn.net, args.nPings, args.pctTraffic)
time.sleep(args.nPings + 10)
if args.isCliEnabled:
MiniNDNCLI(ndn.net)
ndn.stop()
+85
View File
@@ -0,0 +1,85 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
import time
import sys
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.helpers.experiment import Experiment
from nlsr_common import getParser
if __name__ == '__main__':
setLogLevel('info')
ndn = Minindn(parser=getParser())
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr, sync=args.sync,
security=args.security, faceType=args.faceType,
nFaces=args.faces, routingType=args.routingType)
Experiment.checkConvergence(ndn, ndn.net.hosts, args.ctime, quit=True)
firstNode = ndn.net.hosts[0]
if args.security:
firstNode.cmd('ndnsec-set-default /ndn/{}-site/%C1.Operator/op'.format(firstNode.name))
info('Testing advertise\n')
firstNode.cmd('nlsrc advertise /testPrefix')
time.sleep(30)
for host in ndn.net.hosts:
if host.name != firstNode.name:
if (int(host.cmd('nfdc fib | grep testPrefix | wc -l')) != 1 or
int(host.cmd('nlsrc status | grep testPrefix | wc -l')) != 1):
info('Advertise test failed\n')
ndn.stop()
sys.exit(1)
info('Testing withdraw\n')
firstNode.cmd('nlsrc withdraw /testPrefix')
time.sleep(30)
for host in ndn.net.hosts:
if host.name != firstNode.name:
if (int(host.cmd('nfdc fib | grep testPrefix | wc -l')) != 0 or
int(host.cmd('nlsrc status | grep testPrefix | wc -l')) != 0):
info('Withdraw test failed\n')
ndn.stop()
sys.exit(1)
if args.isCliEnabled:
MiniNDNCLI(ndn.net)
ndn.stop()
-79
View File
@@ -1,79 +0,0 @@
#!/usr/bin/python
"""
Create a network with 5 hosts, numbered 1-4 and 9.
Validate that the port numbers match to the interface name,
and that the ovs ports match the mininet ports.
"""
from mininet.net import Mininet
from mininet.node import Controller
from mininet.log import setLogLevel, info, warn
def validatePort( switch, intf ):
"Validate intf's OF port number"
ofport = int( switch.cmd( 'ovs-vsctl get Interface', intf,
'ofport' ) )
if ofport != switch.ports[ intf ]:
warn( 'WARNING: ofport for', intf, 'is actually', ofport, '\n' )
return 0
else:
return 1
def testPortNumbering():
"""Test port numbering:
Create a network with 5 hosts (using Mininet's
mid-level API) and check that implicit and
explicit port numbering works as expected."""
net = Mininet( controller=Controller )
info( '*** Adding controller\n' )
net.addController( 'c0' )
info( '*** Adding hosts\n' )
h1 = net.addHost( 'h1', ip='10.0.0.1' )
h2 = net.addHost( 'h2', ip='10.0.0.2' )
h3 = net.addHost( 'h3', ip='10.0.0.3' )
h4 = net.addHost( 'h4', ip='10.0.0.4' )
h5 = net.addHost( 'h5', ip='10.0.0.5' )
info( '*** Adding switch\n' )
s1 = net.addSwitch( 's1' )
info( '*** Creating links\n' )
# host 1-4 connect to ports 1-4 on the switch
net.addLink( h1, s1 )
net.addLink( h2, s1 )
net.addLink( h3, s1 )
net.addLink( h4, s1 )
# specify a different port to connect host 5 to on the switch.
net.addLink( h5, s1, port1=1, port2= 9)
info( '*** Starting network\n' )
net.start()
# print the interfaces and their port numbers
info( '\n*** printing and validating the ports '
'running on each interface\n' )
for intfs in s1.intfList():
if not intfs.name == "lo":
info( intfs, ': ', s1.ports[intfs],
'\n' )
info( 'Validating that', intfs,
'is actually on port', s1.ports[intfs], '... ' )
if validatePort( s1, intfs ):
info( 'Validated.\n' )
print '\n'
# test the network with pingall
net.pingAll()
print '\n'
info( '*** Stopping network' )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
testPortNumbering()
+53
View File
@@ -0,0 +1,53 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2020, 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 <http://www.gnu.org/licenses/>.
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.apps.app_manager import AppManager
from minindn.util import MiniNDNCLI
from minindn.apps.nfd import Nfd
from minindn.apps.nlsr import Nlsr
from minindn.apps.tshark import Tshark
if __name__ == '__main__':
setLogLevel('info')
Minindn.cleanUp()
Minindn.verifyDependencies()
ndn = Minindn()
ndn.start()
info('Starting tshark logging on nodes\n')
tshark = AppManager(ndn, ndn.net.hosts, Tshark, logFolder="./log/", singleLogFile=False)
info('Starting NFD on nodes\n')
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
info('Starting NLSR on nodes\n')
nlsrs = AppManager(ndn, ndn.net.hosts, Nlsr)
MiniNDNCLI(ndn.net)
ndn.stop()
+121
View File
@@ -0,0 +1,121 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
from subprocess import PIPE
from mininet.log import setLogLevel, info
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
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=2.5) # bw = bandwidth
topo.addLink(b, c, delay='10ms', bw=2.5)
info(topo.links(withInfo=True))
ndn = Minindn(topo=topo)
ndn.start()
# configure and start nfd on each node
info("Configuring NFD111\n")
AppManager(ndn, ndn.net.hosts, Nfd, logLevel="DEBUG")
"""
There are multiple ways of setting up routes in Mini-NDN
refer: https://minindn.memphis.edu/experiment.html#routing-options
It can also be set manually as follows. The important bit to note here
is the use of the Nfdc command
"""
for link in topo.links(withInfo=True):
node1, node2, node_info = link
host1 = ndn.net[node1]
host2 = ndn.net[node2]
interface = host2.connectionsTo(host1)[0][0]
interface_ip = interface.IP()
bandwidth = interface.params.get("bw", 100) * 1000000
info(f"Setting up route from {node1} to {node2} with bandwidth {bandwidth}\n")
Nfdc.createFace(host1, interface_ip, bandwidth=bandwidth)
Nfdc.registerRoute(host1, PREFIX, interface_ip, cost=0)
# links = {"a":["b"], "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.registerRoute(host1, PREFIX, interface_ip, cost=0)
# 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,\
stderr=pingserver_log)
# start ping client
ping1 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE)
ping1.wait()
printOutput(ping1.stdout.read())
interface = ndn.net["b"].connectionsTo(ndn.net["a"])[0][0]
info("Failing link\n") # failing link by setting link loss to 100%
interface.config(delay="10ms", bw=10, loss=100)
info ("\n starting ping2 client \n")
ping2 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE)
ping2.wait()
printOutput(ping2.stdout.read())
interface.config(delay="10ms", bw=10, loss=0) # bringing back the link
info("\nExperiment Completed!\n")
MiniNDNCLI(ndn.net)
ndn.stop()
if __name__ == '__main__':
setLogLevel("info")
run()
-36
View File
@@ -1,36 +0,0 @@
#!/usr/bin/python
"""
This example monitors a number of hosts using host.popen() and
pmonitor()
"""
from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel
from mininet.util import custom, pmonitor
def monitorhosts( hosts=5, sched='cfs' ):
"Start a bunch of pings and monitor them using popen"
mytopo = SingleSwitchTopo( hosts )
cpu = .5 / hosts
myhost = custom( CPULimitedHost, cpu=cpu, sched=sched )
net = Mininet( topo=mytopo, host=myhost )
net.start()
# Start a bunch of pings
popens = {}
last = net.hosts[ -1 ]
for host in net.hosts:
popens[ host ] = host.popen( "ping -c5 %s" % last.IP() )
last = host
# Monitor them and print output
for host, line in pmonitor( popens ):
if host:
print "<%s>: %s" % ( host.name, line.strip() )
# Done
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
monitorhosts( hosts=5 )
-33
View File
@@ -1,33 +0,0 @@
#!/usr/bin/python
"Monitor multiple hosts using popen()/pmonitor()"
from mininet.net import Mininet
from mininet.topo import SingleSwitchTopo
from mininet.util import pmonitor
from time import time
from signal import SIGINT
def pmonitorTest( N=3, seconds=10 ):
"Run pings and monitor multiple hosts using pmonitor"
topo = SingleSwitchTopo( N )
net = Mininet( topo )
net.start()
hosts = net.hosts
print "Starting test..."
server = hosts[ 0 ]
popens = {}
for h in hosts:
popens[ h ] = h.popen('ping', server.IP() )
print "Monitoring output for", seconds, "seconds"
endTime = time() + seconds
for h, line in pmonitor( popens, timeoutms=500 ):
if h:
print '<%s>: %s' % ( h.name, line ),
if time() >= endTime:
for p in popens.values():
p.send_signal( SIGINT )
net.stop()
if __name__ == '__main__':
pmonitorTest()
+81
View File
@@ -0,0 +1,81 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2019, 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 <http://www.gnu.org/licenses/>.
import time
import sys
from mininet.log import setLogLevel, info
from minindn.minindn import Minindn
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.helpers.nfdc import Nfdc
def registerRouteToAllNeighbors(ndn, host, syncPrefix):
for node in ndn.net.hosts:
for neighbor in node.connectionsTo(host):
ip = node.IP(neighbor[0])
faceID = Nfdc.createFace(host, ip)
Nfdc.registerRoute(host, syncPrefix, faceID)
if __name__ == '__main__':
setLogLevel('info')
ndn = Minindn()
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
syncPrefix = "/sync"
numUserPrefixesPerNode = 2
maxUpdatesPerUserPrefixPerNode = 3
for host in ndn.net.hosts:
Nfdc.setStrategy(host, syncPrefix, Nfdc.STRATEGY_MULTICAST)
registerRouteToAllNeighbors(ndn, host, syncPrefix)
info('Starting psync-full-sync on all the nodes\n')
for host in ndn.net.hosts:
host.cmd('export NDN_LOG=examples.FullSyncApp=INFO')
host.cmd('psync-full-sync {} {} {} {} &> psync.logs &'
.format(syncPrefix, host.name, numUserPrefixesPerNode,
maxUpdatesPerUserPrefixPerNode))
info('Sleeping 5 minutes for convergence\n')
# Estimated time for 4 node default topology
time.sleep(300)
totalUpdates = int(host.cmd('grep -r Update {}/*/psync.logs | wc -l'
.format(ndn.workDir)))
expectedUpdates = (maxUpdatesPerUserPrefixPerNode *
len(ndn.net.hosts) * (len(ndn.net.hosts) - 1) * numUserPrefixesPerNode)
if totalUpdates == expectedUpdates:
info('PSync full sync has successfully converged.\n')
else:
info('PSync full sync convergence was not successful. Exiting...\n')
ndn.stop()
sys.exit(1)
+67
View File
@@ -0,0 +1,67 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2019, 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 <http://www.gnu.org/licenses/>.
import time
import sys
from mininet.log import setLogLevel, info
from mininet.topo import Topo
from minindn.minindn import Minindn
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
if __name__ == '__main__':
setLogLevel('info')
topo = Topo()
topo.addHost('h1')
ndn = Minindn(topo=topo)
args = ndn.args
ndn.start()
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
host1 = ndn.net.hosts[0]
host1.cmd('export NDN_LOG=examples.PartialSyncProducerApp=INFO')
host1.cmd('psync-producer /sync /{} 10 1 &> producer.log &'.format(host1.name))
time.sleep(1)
host1.cmd('export NDN_LOG=examples.PartialSyncConsumerApp=INFO:$NDN_LOG')
host1.cmd('psync-consumer /sync 5 &> consumer.log &')
info('Sleeping 90 seconds for convergence\n')
time.sleep(90)
consumerSubs = int(host1.cmd('cat consumer.log | grep -c Subscribing'))
consumerUpdates = int(host1.cmd('cat consumer.log | grep -c Update'))
producerPublish = int(host1.cmd('cat producer.log | grep -c Publish'))
if consumerSubs == 5 and consumerUpdates == 5 and producerPublish == 10:
info('PSync partial sync has successfully converged.\n')
else:
info('PSync partial sync convergence was not successful. Exiting...\n')
ndn.stop()
sys.exit(1)
+111
View File
@@ -0,0 +1,111 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2021, 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 <http://www.gnu.org/licenses/>.
from subprocess import PIPE
from mininet.log import setLogLevel, info
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
PREFIX = "/A"
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')
# add links
topo.addLink(a, b, delay='10ms', bw=10) # bw = bandwidth
info(topo.links(withInfo=True))
ndn = Minindn(topo=topo)
ndn.start()
# configure and start nfd on each node
info("Configuring NFD\n")
AppManager(ndn, ndn.net.hosts, Nfd, logLevel="INFO")
"""
There are multiple ways of setting up routes in Mini-NDN
refer: https://minindn.memphis.edu/experiment.html#routing-options
It can also be set manually as follows. The important bit to note here
is the use of the Nfdc command
"""
for link in topo.links(withInfo=True):
node1, node2, node_info = link
host1 = ndn.net[node1]
host2 = ndn.net[node2]
interface = host2.connectionsTo(host1)[0][0]
interface_ip = interface.IP()
bandwidth = interface.params.get("bw", 100) * 1000000
info(f"Setting up route from {node1} to {node2} with bandwidth {bandwidth}\n")
Nfdc.createFace(host1, interface_ip, bandwidth=bandwidth)
Nfdc.registerRoute(host1, PREFIX, interface_ip, cost=0)
# Start cc server
info("Starting cc...\n")
qsccp_server_log = open(f"{ndn.workDir}/qsccp-demo/qsccp-server.log", "w")
getPopen(ndn.net["b"], "cc-producer --prefix {}".format(PREFIX), stdout=qsccp_server_log,\
stderr=qsccp_server_log)
# start cc client
qsccp_client_log = open(f"{ndn.workDir}/qsccp-demo/qsccp-client.log", "w")
ping1 = getPopen(ndn.net["a"], "qsccp-client --prefix {} --timingStop 10000".format(PREFIX), stdout=qsccp_client_log, stderr=qsccp_client_log)
ping1.wait()
# printOutput(ping1.stdout.read())
# interface = ndn.net["b"].connectionsTo(ndn.net["a"])[0][0]
# info("Failing link\n") # failing link by setting link loss to 100%
# interface.config(delay="10ms", bw=10, loss=100)
# info ("\n starting ping2 client \n")
# ping2 = getPopen(ndn.net["a"], "ndnping {} -c 5".format(PREFIX), stdout=PIPE, stderr=PIPE)
# ping2.wait()
# printOutput(ping2.stdout.read())
# interface.config(delay="10ms", bw=10, loss=0) # bringing back the link
info("\nExperiment Completed!\n")
MiniNDNCLI(ndn.net)
ndn.stop()
if __name__ == '__main__':
setLogLevel("info")
run()
-68
View File
@@ -1,68 +0,0 @@
#!/usr/bin/python
"""
Build a simple network from scratch, using mininet primitives.
This is more complicated than using the higher-level classes,
but it exposes the configuration details and allows customization.
For most tasks, the higher-level API will be preferable.
"""
from mininet.net import Mininet
from mininet.node import Node
from mininet.link import Link
from mininet.log import setLogLevel, info
from mininet.util import quietRun
from time import sleep
def scratchNet( cname='controller', cargs='-v ptcp:' ):
"Create network from scratch using Open vSwitch."
info( "*** Creating nodes\n" )
controller = Node( 'c0', inNamespace=False )
switch = Node( 's0', inNamespace=False )
h0 = Node( 'h0' )
h1 = Node( 'h1' )
info( "*** Creating links\n" )
Link( h0, switch )
Link( h1, switch )
info( "*** Configuring hosts\n" )
h0.setIP( '192.168.123.1/24' )
h1.setIP( '192.168.123.2/24' )
info( str( h0 ) + '\n' )
info( str( h1 ) + '\n' )
info( "*** Starting network using Open vSwitch\n" )
controller.cmd( cname + ' ' + cargs + '&' )
switch.cmd( 'ovs-vsctl del-br dp0' )
switch.cmd( 'ovs-vsctl add-br dp0' )
for intf in switch.intfs.values():
print switch.cmd( 'ovs-vsctl add-port dp0 %s' % intf )
# Note: controller and switch are in root namespace, and we
# can connect via loopback interface
switch.cmd( 'ovs-vsctl set-controller dp0 tcp:127.0.0.1:6633' )
info( '*** Waiting for switch to connect to controller' )
while 'is_connected' not in quietRun( 'ovs-vsctl show' ):
sleep( 1 )
info( '.' )
info( '\n' )
info( "*** Running test\n" )
h0.cmdPrint( 'ping -c1 ' + h1.IP() )
info( "*** Stopping network\n" )
controller.cmd( 'kill %' + cname )
switch.cmd( 'ovs-vsctl del-br dp0' )
switch.deleteIntfs()
info( '\n' )
if __name__ == '__main__':
setLogLevel( 'info' )
info( '*** Scratch network demo (kernel datapath)\n' )
Mininet.init()
scratchNet()
-73
View File
@@ -1,73 +0,0 @@
#!/usr/bin/python
"""
Build a simple network from scratch, using mininet primitives.
This is more complicated than using the higher-level classes,
but it exposes the configuration details and allows customization.
For most tasks, the higher-level API will be preferable.
This version uses the user datapath and an explicit control network.
"""
from mininet.net import Mininet
from mininet.node import Node
from mininet.link import Link
from mininet.log import setLogLevel, info
def linkIntfs( node1, node2 ):
"Create link from node1 to node2 and return intfs"
link = Link( node1, node2 )
return link.intf1, link.intf2
def scratchNetUser( cname='controller', cargs='ptcp:' ):
"Create network from scratch using user switch."
# It's not strictly necessary for the controller and switches
# to be in separate namespaces. For performance, they probably
# should be in the root namespace. However, it's interesting to
# see how they could work even if they are in separate namespaces.
info( '*** Creating Network\n' )
controller = Node( 'c0' )
switch = Node( 's0')
h0 = Node( 'h0' )
h1 = Node( 'h1' )
cintf, sintf = linkIntfs( controller, switch )
h0intf, sintf1 = linkIntfs( h0, switch )
h1intf, sintf2 = linkIntfs( h1, switch )
info( '*** Configuring control network\n' )
controller.setIP( '10.0.123.1/24', intf=cintf )
switch.setIP( '10.0.123.2/24', intf=sintf)
info( '*** Configuring hosts\n' )
h0.setIP( '192.168.123.1/24', intf=h0intf )
h1.setIP( '192.168.123.2/24', intf=h1intf )
info( '*** Network state:\n' )
for node in controller, switch, h0, h1:
info( str( node ) + '\n' )
info( '*** Starting controller and user datapath\n' )
controller.cmd( cname + ' ' + cargs + '&' )
switch.cmd( 'ifconfig lo 127.0.0.1' )
intfs = [ str( i ) for i in sintf1, sintf2 ]
switch.cmd( 'ofdatapath -i ' + ','.join( intfs ) + ' ptcp: &' )
switch.cmd( 'ofprotocol tcp:' + controller.IP() + ' tcp:localhost &' )
info( '*** Running test\n' )
h0.cmdPrint( 'ping -c1 ' + h1.IP() )
info( '*** Stopping network\n' )
controller.cmd( 'kill %' + cname )
switch.cmd( 'kill %ofdatapath' )
switch.cmd( 'kill %ofprotocol' )
switch.deleteIntfs()
info( '\n' )
if __name__ == '__main__':
setLogLevel( 'info' )
info( '*** Scratch network demo (user datapath)\n' )
Mininet.init()
scratchNetUser()
-48
View File
@@ -1,48 +0,0 @@
#!/usr/bin/python
"""
Simple example of setting network and CPU parameters
NOTE: link params limit BW, add latency, and loss.
There is a high chance that pings WILL fail and that
iperf will hang indefinitely if the TCP handshake fails
to complete.
"""
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.link import TCLink
from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel
class SingleSwitchTopo(Topo):
"Single switch connected to n hosts."
def __init__(self, n=2, **opts):
Topo.__init__(self, **opts)
switch = self.addSwitch('s1')
for h in range(n):
# Each host gets 50%/n of system CPU
host = self.addHost('h%s' % (h + 1),
cpu=.5 / n)
# 10 Mbps, 5ms delay, 10% loss
self.addLink(host, switch,
bw=10, delay='5ms', loss=10, use_htb=True)
def perfTest():
"Create network and run simple performance test"
topo = SingleSwitchTopo( n=4 )
net = Mininet( topo=topo,
host=CPULimitedHost, link=TCLink,
autoStaticArp=True )
net.start()
print "Dumping host connections"
dumpNodeConnections(net.hosts)
print "Testing bandwidth between h1 and h4"
h1, h4 = net.getNodeByName('h1', 'h4')
net.iperf( ( h1, h4 ), l4Type='UDP' )
net.stop()
if __name__ == '__main__':
setLogLevel('info')
perfTest()
-85
View File
@@ -1,85 +0,0 @@
#!/usr/bin/python
"""
Create a network and start sshd(8) on each host.
While something like rshd(8) would be lighter and faster,
(and perfectly adequate on an in-machine network)
the advantage of running sshd is that scripts can work
unchanged on mininet and hardware.
In addition to providing ssh access to hosts, this example
demonstrates:
- creating a convenience function to construct networks
- connecting the host network to the root namespace
- running server processes (sshd in this case) on hosts
"""
import sys
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.log import lg
from mininet.node import Node
from mininet.topolib import TreeTopo
from mininet.util import waitListening
def TreeNet( depth=1, fanout=2, **kwargs ):
"Convenience function for creating tree networks."
topo = TreeTopo( depth, fanout )
return Mininet( topo, **kwargs )
def connectToRootNS( network, switch, ip, routes ):
"""Connect hosts to root namespace via switch. Starts network.
network: Mininet() network object
switch: switch to connect to root namespace
ip: IP address for root namespace node
routes: host networks to route to"""
# Create a node in root namespace and link to switch 0
root = Node( 'root', inNamespace=False )
intf = network.addLink( root, switch ).intf1
root.setIP( ip, intf=intf )
# Start network that now includes link to root namespace
network.start()
# Add routes from root ns to hosts
for route in routes:
root.cmd( 'route add -net ' + route + ' dev ' + str( intf ) )
def sshd( network, cmd='/usr/sbin/sshd', opts='-D',
ip='10.123.123.1/32', routes=None, switch=None ):
"""Start a network, connect it to root ns, and run sshd on all hosts.
ip: root-eth0 IP address in root namespace (10.123.123.1/32)
routes: Mininet host networks to route to (10.0/24)
switch: Mininet switch to connect to root namespace (s1)"""
if not switch:
switch = network[ 's1' ] # switch to use
if not routes:
routes = [ '10.0.0.0/24' ]
connectToRootNS( network, switch, ip, routes )
for host in network.hosts:
host.cmd( cmd + ' ' + opts + '&' )
print "*** Waiting for ssh daemons to start"
for server in network.hosts:
waitListening( server=server, port=22, timeout=5 )
print
print "*** Hosts are running sshd at the following addresses:"
print
for host in network.hosts:
print host.name, host.IP()
print
print "*** Type 'exit' or control-D to shut down network"
CLI( network )
for host in network.hosts:
host.cmd( 'kill %' + cmd )
network.stop()
if __name__ == '__main__':
lg.setLogLevel( 'info')
net = TreeNet( depth=1, fanout=4 )
# get sshd args from the command line or use default args
# useDNS=no -u0 to avoid reverse DNS lookup timeout
argvopts = ' '.join( sys.argv[ 1: ] ) if len( sys.argv ) > 1 else (
'-D -o UseDNS=no -u0' )
sshd( net, opts=argvopts )
+100
View File
@@ -0,0 +1,100 @@
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2020, 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 <http://www.gnu.org/licenses/>.
import argparse
import sys
from mininet.log import setLogLevel, info
from mininet.topo import Topo
from minindn.minindn import Minindn
from minindn.util import MiniNDNCLI
from minindn.apps.app_manager import AppManager
from minindn.apps.nfd import Nfd
from minindn.helpers.ndn_routing_helper import NdnRoutingHelper
if __name__ == '__main__':
setLogLevel('info')
Minindn.cleanUp()
Minindn.verifyDependencies()
parser = argparse.ArgumentParser()
parser.add_argument('--face-type', dest='faceType', default='udp', choices=['udp', 'tcp'])
parser.add_argument('--routing', dest='routingType', default='link-state',
choices=['link-state', 'hr', 'dry'],
help='''Choose routing type, dry = link-state is used
but hr is calculated for comparision.''')
'''
Experiment run with default topology, test cases won't work with other topologies
# With calculateNPossibleRoutes,
10 # routing = hr, N = All, from A, 3 routes needs to added to NFD.
a +++++++ b # a - b -- cost 10
+ + # a - c -- cost 10
10 + + 10 # a - d -- cost 20
+ + # Same goes for B being a source.
c d #
'''
topo = Topo()
a = topo.addHost('a')
b = topo.addHost('b')
c = topo.addHost('c')
d = topo.addHost('d')
topo.addLink(a, b, delay='10ms')
topo.addLink(a, c, delay='10ms')
topo.addLink(b, d, delay='10ms')
ndn = Minindn(parser=parser, topo=topo)
ndn.start()
info('Starting NFD on nodes\n')
nfds = AppManager(ndn, ndn.net.hosts, Nfd)
info('Adding static routes to NFD\n')
grh = NdnRoutingHelper(ndn.net, ndn.args.faceType, ndn.args.routingType)
# For all host, pass ndn.net.hosts or a list, [ndn.net['a'], ..] or [ndn.net.hosts[0],.]
grh.addOrigin([ndn.net['a']], ["/abc"])
grh.calculateNPossibleRoutes()
'''
prefix "/abc" is advertise from node A, it should be reachable from all other nodes.
'''
routesFromA = ndn.net['a'].cmd("nfdc route | grep -v '/localhost/nfd'")
if '/ndn/b-site/b' not in routesFromA or \
'/ndn/c-site/c' not in routesFromA or \
'/ndn/d-site/d' not in routesFromA:
info("Route addition failed\n")
routesToPrefix = ndn.net['b'].cmd("nfdc fib | grep '/abc'")
if '/abc' not in routesToPrefix:
info("Missing route to advertised prefix, Route addition failed\n")
ndn.net.stop()
sys.exit(1)
info('Route addition to NFD completed\n')
MiniNDNCLI(ndn.net)
ndn.stop()
-41
View File
@@ -1,41 +0,0 @@
#!/usr/bin/env python
"""
Run all mininet.examples tests
-v : verbose output
-quick : skip tests that take more than ~30 seconds
"""
import unittest
import os
import sys
from mininet.util import ensureRoot
from mininet.clean import cleanup
class MininetTestResult( unittest.TextTestResult ):
def addFailure( self, test, err ):
super( MininetTestResult, self ).addFailure( test, err )
cleanup()
def addError( self,test, err ):
super( MininetTestResult, self ).addError( test, err )
cleanup()
class MininetTestRunner( unittest.TextTestRunner ):
def _makeResult( self ):
return MininetTestResult( self.stream, self.descriptions, self.verbosity )
def runTests( testDir, verbosity=1 ):
"discover and run all tests in testDir"
# ensure root and cleanup before starting tests
ensureRoot()
cleanup()
# discover all tests in testDir
testSuite = unittest.defaultTestLoader.discover( testDir )
# run tests
MininetTestRunner( verbosity=verbosity ).run( testSuite )
if __name__ == '__main__':
# get the directory containing example tests
testDir = os.path.dirname( os.path.realpath( __file__ ) )
verbosity = 2 if '-v' in sys.argv else 1
runTests( testDir, verbosity )
-64
View File
@@ -1,64 +0,0 @@
#!/usr/bin/env python
"""
Tests for baresshd.py
"""
import unittest
import pexpect
from mininet.clean import cleanup, sh
class testBareSSHD( unittest.TestCase ):
opts = [ 'Welcome to h1', pexpect.EOF, pexpect.TIMEOUT ]
def connected( self ):
"Log into ssh server, check banner, then exit"
p = pexpect.spawn( 'ssh 10.0.0.1 -o StrictHostKeyChecking=no -i /tmp/ssh/test_rsa exit' )
while True:
index = p.expect( self.opts )
if index == 0:
return True
else:
return False
def setUp( self ):
# verify that sshd is not running
self.assertFalse( self.connected() )
# create public key pair for testing
sh( 'rm -rf /tmp/ssh' )
sh( 'mkdir /tmp/ssh' )
sh( "ssh-keygen -t rsa -P '' -f /tmp/ssh/test_rsa" )
sh( 'cat /tmp/ssh/test_rsa.pub >> /tmp/ssh/authorized_keys' )
# run example with custom sshd args
cmd = ( 'python -m mininet.examples.baresshd '
'-o AuthorizedKeysFile=/tmp/ssh/authorized_keys '
'-o StrictModes=no' )
p = pexpect.spawn( cmd )
runOpts = [ 'You may now ssh into h1 at 10.0.0.1',
'after 5 seconds, h1 is not listening on port 22',
pexpect.EOF, pexpect.TIMEOUT ]
while True:
index = p.expect( runOpts )
if index == 0:
break
else:
self.tearDown()
self.fail( 'sshd failed to start in host h1' )
def testSSH( self ):
"Simple test to verify that we can ssh into h1"
result = False
# try to connect up to 3 times; sshd can take a while to start
result = self.connected()
self.assertTrue( result )
def tearDown( self ):
# kill the ssh process
sh( "ps aux | grep 'ssh.*Banner' | awk '{ print $2 }' | xargs kill" )
cleanup()
# remove public key pair
sh( 'rm -rf /tmp/ssh' )
if __name__ == '__main__':
unittest.main()
-66
View File
@@ -1,66 +0,0 @@
#!/usr/bin/env python
"""
Tests for bind.py
"""
import unittest
import pexpect
class testBind( unittest.TestCase ):
prompt = 'mininet>'
def setUp( self ):
self.net = pexpect.spawn( 'python -m mininet.examples.bind' )
self.net.expect( "Private Directories: \[([\w\s,'/]+)\]" )
self.directories = []
# parse directories from mn output
for d in self.net.match.group(1).split(', '):
self.directories.append( d.strip("'") )
self.net.expect( self.prompt )
self.assertTrue( len( self.directories ) > 0 )
def testCreateFile( self ):
"Create a file, a.txt, in the first private directory and verify"
fileName = 'a.txt'
directory = self.directories[ 0 ]
path = directory + '/' + fileName
self.net.sendline( 'h1 touch %s; ls %s' % ( path, directory ) )
index = self.net.expect( [ fileName, self.prompt ] )
self.assertTrue( index == 0 )
self.net.expect( self.prompt )
self.net.sendline( 'h1 rm %s' % path )
self.net.expect( self.prompt )
def testIsolation( self ):
"Create a file in two hosts and verify that contents are different"
fileName = 'b.txt'
directory = self.directories[ 0 ]
path = directory + '/' + fileName
contents = { 'h1' : '1', 'h2' : '2' }
# Verify file doesn't exist, then write private copy of file
for host in contents:
value = contents[ host ]
self.net.sendline( '%s cat %s' % ( host, path ) )
self.net.expect( 'No such file' )
self.net.expect( self.prompt )
self.net.sendline( '%s echo %s > %s' % ( host, value, path ) )
self.net.expect( self.prompt )
# Verify file contents
for host in contents:
value = contents[ host ]
self.net.sendline( '%s cat %s' % ( host, path ) )
self.net.expect( value )
self.net.expect( self.prompt )
self.net.sendline( '%s rm %s' % ( host, path ) )
self.net.expect( self.prompt )
# TODO: need more tests
def tearDown( self ):
self.net.sendline( 'exit' )
self.net.wait()
if __name__ == '__main__':
unittest.main()
-27
View File
@@ -1,27 +0,0 @@
#!/usr/bin/env python
'''
A simple sanity check test for cluster edition
'''
import unittest
import pexpect
class clusterSanityCheck( unittest.TestCase ):
prompt = 'mininet>'
def testClusterPingAll( self ):
p = pexpect.spawn( 'python -m mininet.examples.clusterSanity' )
p.expect( self.prompt )
p.sendline( 'pingall' )
p.expect ( '(\d+)% dropped' )
percent = int( p.match.group( 1 ) ) if p.match else -1
self.assertEqual( percent, 0 )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
if __name__ == '__main__':
unittest.main()
-48
View File
@@ -1,48 +0,0 @@
#!/usr/bin/env python
"""
Tests for controllers.py and controllers2.py
"""
import unittest
import pexpect
class testControllers( unittest.TestCase ):
prompt = 'mininet>'
def connectedTest( self, name, cmap ):
"Verify that switches are connected to the controller specified by cmap"
p = pexpect.spawn( 'python -m %s' % name )
p.expect( self.prompt )
# but first a simple ping test
p.sendline( 'pingall' )
p.expect ( '(\d+)% dropped' )
percent = int( p.match.group( 1 ) ) if p.match else -1
self.assertEqual( percent, 0 )
p.expect( self.prompt )
# verify connected controller
for switch in cmap:
p.sendline( 'sh ovs-vsctl get-controller %s' % switch )
p.expect( 'tcp:([\d.:]+)')
actual = p.match.group(1)
expected = cmap[ switch ]
self.assertEqual( actual, expected )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
def testControllers( self ):
c0 = '127.0.0.1:6633'
c1 = '127.0.0.1:6634'
cmap = { 's1': c0, 's2': c1, 's3': c0 }
self.connectedTest( 'mininet.examples.controllers', cmap )
def testControllers2( self ):
c0 = '127.0.0.1:6633'
c1 = '127.0.0.1:6634'
cmap = { 's1': c0, 's2': c1 }
self.connectedTest( 'mininet.examples.controllers2', cmap )
if __name__ == '__main__':
unittest.main()

Some files were not shown because too many files have changed in this diff Show More