Compare commits
2773 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be9d919a58 | |||
| 937f78e7bc | |||
| d9a606c58d | |||
| d3942cd4d0 | |||
| 6badc137d9 | |||
| 312b8da3a3 | |||
| 26d46a960d | |||
| 2a323473e4 | |||
| 4904c44f15 | |||
| e4ec46dd52 | |||
| a947ff3967 | |||
| bbf1d7cce3 | |||
| dfb9b7360a | |||
| 554fcfda0d | |||
| 16d1d635a0 | |||
| 62d8743f1c | |||
| 5872949e0a | |||
| f173b434dd | |||
| 48fa3d344c | |||
| b9d448c83b | |||
| 6152ba1a89 | |||
| 08f2b87daa | |||
| 39c1412e3e | |||
| 41b7eadd33 | |||
| b851cc5b0b | |||
| 08961f4883 | |||
| c9ccce91ed | |||
| 76dd4d1db4 | |||
| 27e5640201 | |||
| fdc3e27c11 | |||
| 709f6a6d5b | |||
| 45793c3a02 | |||
| 137ff47a46 | |||
| ab01dd65a4 | |||
| 31870b3bc0 | |||
| 0c34dea05b | |||
| b135ced7aa | |||
| 16018e8d7e | |||
| 0ef25b59c4 | |||
| 20b1d65d07 | |||
| eaf4fb4a6d | |||
| f86b2de0af | |||
| 4182edbc93 | |||
| 6af434b9f9 | |||
| f79ac9e373 | |||
| c352b35d3f | |||
| b91e3b0e4c | |||
| 0d86d03be0 | |||
| 9a94ef7a2d | |||
| 791e9ae464 | |||
| c2a543f568 | |||
| b3390aaa3e | |||
| 3d0264e3a3 | |||
| 42fbffdbdb | |||
| f83b6c7ab1 | |||
| 2f1e4574c0 | |||
| de351e9388 | |||
| 20f5f62292 | |||
| 0008eeebce | |||
| ca7b76ef27 | |||
| a41edb2fa1 | |||
| ffd1766adc | |||
| f9e025ad81 | |||
| b62c394703 | |||
| 4ba092f3aa | |||
| 93126f3a55 | |||
| 5f94a4cf59 | |||
| 888a3bdad6 | |||
| 72dba0d456 | |||
| 72d054a867 | |||
| e9e87c3232 | |||
| ef99300eff | |||
| 49d5404bfc | |||
| c21d79a87b | |||
| 8dc2460416 | |||
| e6bd2a7a6a | |||
| ad374c8d87 | |||
| 935532822b | |||
| 45d6dcd5f4 | |||
| e4c1b22090 | |||
| 2a14b1c408 | |||
| 5b119aa40d | |||
| 25de2ff3c4 | |||
| 4c4ef85a93 | |||
| 67d54a7f8a | |||
| 0a476b4f04 | |||
| 2c57f536e3 | |||
| a1882f8e10 | |||
| 7c509777e5 | |||
| d5a75f0cec | |||
| 91c4ef481f | |||
| d034ec3e08 | |||
| dd4979ef89 | |||
| 84c9dd96db | |||
| 18011ba4eb | |||
| aa7b91f890 | |||
| 0e05b107fd | |||
| 05c3383610 | |||
| 43c64f656b | |||
| 2b4b265b60 | |||
| 0efe19fe76 | |||
| 1a990a1877 | |||
| 6547b9222c | |||
| a4a8086580 | |||
| 8d3dfb1df9 | |||
| 3226ce7f09 | |||
| 1b12b95ee9 | |||
| ffdff79112 | |||
| 4b7bfc9b77 | |||
| ccb704ffc7 | |||
| ce87f97994 | |||
| 8a7187fba3 | |||
| 3a8df9f3d6 | |||
| 31a31ffc07 | |||
| 63dccc1973 | |||
| 36e6b69aaf | |||
| dc624d46b3 | |||
| 1cecfe5548 | |||
| a54122b4e8 | |||
| 693099a950 | |||
| ae1fed72b1 | |||
| b5e22fdc37 | |||
| 47e58be578 | |||
| 833506428b | |||
| ca3c48f8e8 | |||
| b00892cae7 | |||
| 2e116e5f74 | |||
| 9eb007fd26 | |||
| 6be343530f | |||
| 9ee8930726 | |||
| a042d0bbef | |||
| 3ebec1046c | |||
| 4340da4ca6 | |||
| 6ec88588f1 | |||
| 32bc3d3664 | |||
| ee62b6d04e | |||
| fc73accacd | |||
| 9da8e1bb03 | |||
| 515183caae | |||
| 0f55fefaba | |||
| ddda864b77 | |||
| 5a16ff1df4 | |||
| 53841f6170 | |||
| 3c8bfe6ae6 | |||
| 2e699a4704 | |||
| 7089f682d6 | |||
| 371ed54dc9 | |||
| 0b6e955a24 | |||
| f5bb823415 | |||
| 83cd996471 | |||
| 418a3fae42 | |||
| 66229167d2 | |||
| 164e8c83bc | |||
| 2865203612 | |||
| f2a37c6ca4 | |||
| 6236cbf9a3 | |||
| 58ab30c53c | |||
| beaf8569c0 | |||
| 9679a25783 | |||
| aaccadb46a | |||
| 4c424da911 | |||
| 623d9898b7 | |||
| 1c05220bba | |||
| ccd72825dd | |||
| 29169d42b6 | |||
| 43ecf40b5a | |||
| 119cf2035b | |||
| 73aec9c9b1 | |||
| 04c8831510 | |||
| fbabf8129a | |||
| 08511f30c5 | |||
| daddd90d07 | |||
| bfe0533aa3 | |||
| f8a2add627 | |||
| af58cc3026 | |||
| c6f7bb2d3e | |||
| 075851985f | |||
| e4eeeb18f5 | |||
| b61d0ff5f2 | |||
| 288d193daa | |||
| 0996a38b84 | |||
| 18ee064a79 | |||
| 96c43a7e26 | |||
| 5c7b34db46 | |||
| d3623e2142 | |||
| 062a2dcc42 | |||
| 2d581766fd | |||
| d7a038431f | |||
| e17282f995 | |||
| 78829ba702 | |||
| 4a78ce68d1 | |||
| ad54b2ce62 | |||
| f79e7581b6 | |||
| aeffbb31d7 | |||
| b998a05cce | |||
| 3752943c22 | |||
| 9fd7fbb86c | |||
| 829a6dd8bb | |||
| 1f0dd55d8d | |||
| 28bf2500e9 | |||
| 63d6b14d45 | |||
| 815f3721b7 | |||
| 0dab5235c9 | |||
| eb9fa68703 | |||
| 7be1b92968 | |||
| d1ddd3c89b | |||
| 9b153c313b | |||
| ea6e067812 | |||
| 6a93edb24e | |||
| a6321aac60 | |||
| 450b10b597 | |||
| f91e2ff5a4 | |||
| 35170aed54 | |||
| 2c1b7db441 | |||
| a557f1c064 | |||
| f2b7b1795b | |||
| 3b711f9852 | |||
| a890500150 | |||
| 7468230ede | |||
| 6a3326e529 | |||
| 4ff40c4a07 | |||
| 254057bd80 | |||
| f5f32e0ea3 | |||
| 39ef17d6a4 | |||
| 505de0c685 | |||
| bb10734d66 | |||
| edb480ad29 | |||
| f4cff0e194 | |||
| 78a2df8963 | |||
| f8ec434cdb | |||
| 1649c1dc65 | |||
| 5c5ab1f1f0 | |||
| 53be11fe6f | |||
| 6fd8b6c572 | |||
| 61375f8ef5 | |||
| 8a32b1e369 | |||
| 22d1a6046d | |||
| db81db32a8 | |||
| c9d422bbb6 | |||
| bd1ef984cc | |||
| 6d53b47cae | |||
| 09f00c5b34 | |||
| fbe5e3949f | |||
| 43dbc0b4d1 | |||
| 5e9344d2d4 | |||
| 2b0056553c | |||
| 6cf0d2e645 | |||
| 822e13a7df | |||
| a62f9d7771 | |||
| 112b278854 | |||
| 14c60f7ad3 | |||
| e855838ed1 | |||
| 8a4b416428 | |||
| ca687b56f6 | |||
| 556d973168 | |||
| 42282f5512 | |||
| 0e65d73baa | |||
| f7691237f5 | |||
| ed0dcc982b | |||
| a390b13f86 | |||
| 5d91e8c2d2 | |||
| 0789c9b435 | |||
| 03b4114b20 | |||
| fda39900e3 | |||
| 9167a8b308 | |||
| 60c81de8b5 | |||
| 3211fbb0bf | |||
| 3327b9da92 | |||
| 72b496b9ef | |||
| 8bfd88b80b | |||
| c456128c6d | |||
| dd283f6ead | |||
| 271ea4bc75 | |||
| e7c2292d7b | |||
| c883517a1d | |||
| 696859e936 | |||
| 267a3ca69d | |||
| 27c1fab7fc | |||
| be27a1c03d | |||
| ba319c457d | |||
| 4a556dbf91 | |||
| 923b1180f9 | |||
| f6ba778fc9 | |||
| cff773b8d2 | |||
| 776a594c3c | |||
| a75e91cc03 | |||
| dc271270a8 | |||
| cc927f907f | |||
| 53fb65aea7 | |||
| 560a34ba97 | |||
| e0570ec0b0 | |||
| e110fea8ff | |||
| d4cd3c92fd | |||
| b807dfa090 | |||
| 5a16b2cad8 | |||
| 9ea56ac66a | |||
| 478e810ad5 | |||
| bf90dded3c | |||
| c22d5c5733 | |||
| bb5f9f1a50 | |||
| 3f1c2d2653 | |||
| f6dcb76287 | |||
| 6740fc4627 | |||
| edc7af8a02 | |||
| 80c8937a01 | |||
| 4400054ebe | |||
| 3a43bd4987 | |||
| c140066890 | |||
| c3f0505ddc | |||
| 8501ca807c | |||
| 75643a53ef | |||
| b6471a7749 | |||
| 0c393e38c4 | |||
| 05019b6214 | |||
| 737bc7cd00 | |||
| 31d26c1e84 | |||
| ec7c5d2dd6 | |||
| b34fbc477b | |||
| a8acd5c5f0 | |||
| 621f07f0d2 | |||
| 11468a4235 | |||
| 441b674f96 | |||
| 2c273b86cd | |||
| d4347bc1b5 | |||
| 5a8c75187d | |||
| 36049254af | |||
| 18dd6edda3 | |||
| c802635595 | |||
| 56b59c5905 | |||
| 6490c81cf8 | |||
| ec3d666f3b | |||
| 8dc44fbfaf | |||
| 5a8d264371 | |||
| 3faceb9149 | |||
| aad4e224e5 | |||
| 5bd019aba0 | |||
| 9fe0c49344 | |||
| bcc362cd11 | |||
| 34c057c351 | |||
| 9c1922aebe | |||
| 058f508927 | |||
| 24863d5368 | |||
| e103bc0ded | |||
| 766efc6d0e | |||
| e4fa093d5f | |||
| cb1e1d0023 | |||
| dc96b531b1 | |||
| a4a18943f7 | |||
| a87eed74c2 | |||
| 5a614715ea | |||
| 27d2380327 | |||
| d1d683ee21 | |||
| 812fc3be75 | |||
| ae4529b819 | |||
| 2c1c5afe91 | |||
| b41554c18f | |||
| 40349f92d8 | |||
| 6935a997e6 | |||
| 41f6573c8d | |||
| 2b44913a70 | |||
| 64f72686aa | |||
| d06c2b4fae | |||
| 889e333a35 | |||
| 379c3d5390 | |||
| 02273c7da7 | |||
| 2bb663d011 | |||
| 0dfe8fa5df | |||
| e173bb868d | |||
| c5ffe4c9dc | |||
| a053ff6896 | |||
| 537e375fe1 | |||
| 879b2cb91d | |||
| c0d60678d9 | |||
| 521c43eb23 | |||
| 627813fe6c | |||
| 16f7931992 | |||
| 76847a02ca | |||
| 935a7896e1 | |||
| 7f6f6ba6a7 | |||
| 8977a827b2 | |||
| 11608c6b16 | |||
| 6ac2042e55 | |||
| 4ff7264001 | |||
| 9bcf1cdac5 | |||
| f2769ba5a5 | |||
| db02706e4c | |||
| 78bfd610d9 | |||
| 20726f8201 | |||
| 4fc3138b1e | |||
| b6932288ae | |||
| 6397957980 | |||
| 8810ebfe02 | |||
| 7771ab6562 | |||
| 27615d70d1 | |||
| 1a443df051 | |||
| ff4dfc3009 | |||
| a349c602db | |||
| 62308cf1ce | |||
| 511e11e9be | |||
| 6de12cc9d2 | |||
| 9ad6948605 | |||
| 7e17f8d7e1 | |||
| 67c8f12b67 | |||
| e0346ac124 | |||
| 46cc3fab6d | |||
| 02dc54f597 | |||
| a7677d77de | |||
| e963c05aeb | |||
| cb475c1750 | |||
| 4202275d10 | |||
| e9c67a3ada | |||
| ba70c90271 | |||
| 8d084573dc | |||
| 9644e5ee88 | |||
| 74541b0d23 | |||
| fa2983e8a4 | |||
| a280c30a20 | |||
| a85420cd34 | |||
| 982fe8454b | |||
| b5cfd48e9a | |||
| b7f945f750 | |||
| 942f3404a3 | |||
| fd49891782 | |||
| 6191bda098 | |||
| ac7ef5158d | |||
| c61932afc5 | |||
| 473ea28f10 | |||
| 2158f87125 | |||
| b4aaac11c6 | |||
| 1d78ea62e8 | |||
| 37f1478f00 | |||
| 2fe2751c9e | |||
| 80e0d082b4 | |||
| 011e2bbb70 | |||
| 26fba17dc2 | |||
| 4e2a41ae85 | |||
| cb3bcff3a6 | |||
| 72f7ffdb6d | |||
| 050af31b95 | |||
| 89d089c506 | |||
| 3d0e59cd05 | |||
| 83dea96517 | |||
| e1d6ca18e1 | |||
| 7020d1611e | |||
| 0a3da46adc | |||
| ed271f5954 | |||
| a3628b44c1 | |||
| 23edc105e2 | |||
| 44afb107ba | |||
| 5fe039c6a6 | |||
| cabb264eef | |||
| ab8a395c49 | |||
| da1d232338 | |||
| 08eb0aef35 | |||
| d869416a92 | |||
| 77bf878ea8 | |||
| 4966231237 | |||
| 1724e3ceec | |||
| 58dd143df7 | |||
| a6979a7bb9 | |||
| 7b8b8e8de3 | |||
| 7f56378951 | |||
| b21f71e568 | |||
| 8872354a55 | |||
| 69dfbe8707 | |||
| 5117b61f63 | |||
| bb59c6a9fb | |||
| c6868e0961 | |||
| ff02feb0b7 | |||
| 991e83fe2c | |||
| 0a9ad0c47c | |||
| dafc9f88ae | |||
| 9b4661c799 | |||
| 69ddf50d98 | |||
| 386b5fe6eb | |||
| 25374b7325 | |||
| da3541e88d | |||
| 3bf71817cf | |||
| 8acd8baa33 | |||
| 7c1cda0ccb | |||
| a12b08bd3a | |||
| 341ef1908c | |||
| 18bfce3a97 | |||
| 35729f1717 | |||
| f44690e9af | |||
| 14690d8553 | |||
| 44d0c56680 | |||
| 3a19364b1b | |||
| 9ad409452b | |||
| 47775d87da | |||
| 41bbee50af | |||
| 80fec1898e | |||
| 0ccf783437 | |||
| 35d9ec1c8e | |||
| 4e5eab77e2 | |||
| 29f19e164e | |||
| e1c0003987 | |||
| 4404c371af | |||
| 83ac55585c | |||
| e9a8648ae9 | |||
| f17df2c2dc | |||
| 18c92e855d | |||
| 048ffbe7d3 | |||
| e5818f9865 | |||
| 09b0afe3d5 | |||
| 4f3921d1bf | |||
| 48a799a6ac | |||
| 08ce187c6b | |||
| d3fb648979 | |||
| 2759411565 | |||
| fa8f4bf528 | |||
| eeaea6f03b | |||
| 8125fab8c3 | |||
| 7fe3f102ff | |||
| 53b38a05ea | |||
| 8aada40095 | |||
| 621b84064a | |||
| 91cf6bfccd | |||
| c9785a0ef0 | |||
| 73ea5d6192 | |||
| 752658119f | |||
| 53b3d2bb1f | |||
| e22584cd79 | |||
| 05b6cf11a8 | |||
| 960bc0d1ba | |||
| 745520c03d | |||
| de80ab4910 | |||
| c995c98e85 | |||
| fc3824059b | |||
| ef44869539 | |||
| 4ef540a4e6 | |||
| 56299308b6 | |||
| f7aa0eb745 | |||
| 881590b6d7 | |||
| c78d5b071a | |||
| 6974ce4f24 | |||
| 627a2048f1 | |||
| 5cd592fe06 | |||
| 295c1cd3d5 | |||
| 931e5140e2 | |||
| 574ed67011 | |||
| 5b42ef5b02 | |||
| c6aa4c8fb4 | |||
| 6534020b54 | |||
| a3ed490b7f | |||
| 10bbdc4176 | |||
| 26f046edd5 | |||
| cabfd83031 | |||
| 1518a1dbd1 | |||
| e5b7c28375 | |||
| 2f666d9622 | |||
| 30525bef9a | |||
| e14aaceabe | |||
| c8f4d234ea | |||
| 8dc5510518 | |||
| 6b9fc231e1 | |||
| a0a7c6d88c | |||
| f6438556ef | |||
| 5d4ecfc62c | |||
| de502593ef | |||
| b5bfc150e3 | |||
| bcf92901ac | |||
| c7be59d0c1 | |||
| 218c66592a | |||
| 96e4874bdb | |||
| 0ef1e6b866 | |||
| 0bfc594407 | |||
| fd014845f7 | |||
| 660e414f36 | |||
| 1806cbede9 | |||
| 3aa9706150 | |||
| 939cee7ac3 | |||
| 0f79c7d754 | |||
| 6a96f3f3ea | |||
| ef0a14d093 | |||
| b66b302a6a | |||
| b685071f5a | |||
| 2ea43c9729 | |||
| eb89e875f7 | |||
| 7ecce753a6 | |||
| 8ab25173a1 | |||
| ac16151d22 | |||
| b68fa9919b | |||
| 516eb971a3 | |||
| 22a66ef917 | |||
| 9cf6137916 | |||
| 36995793fb | |||
| 0ddbe50a61 | |||
| 0d839a85c0 | |||
| be10286ae5 | |||
| 4163debdfb | |||
| c4b1bff412 | |||
| 848cb7cfb5 | |||
| 6df47b4d19 | |||
| c09319cab9 | |||
| 175518d248 | |||
| 14ccd72505 | |||
| fb452286e6 | |||
| aa3db11715 | |||
| 250eed3667 | |||
| 5a7be54e31 | |||
| 4227fc706d | |||
| 3e4aa96665 | |||
| b97dfc9450 | |||
| 3c32879211 | |||
| 5d2044ae93 | |||
| b5a8d46096 | |||
| 7a1c14372c | |||
| 9cac5c71ee | |||
| ef8ee7e7ef | |||
| ae62a57f4e | |||
| e3fe5ec788 | |||
| bd1c208097 | |||
| 56c82ac742 | |||
| 321b953877 | |||
| 603615d2d0 | |||
| a4c5f55812 | |||
| 517c5e5bfd | |||
| 514685e9a6 | |||
| 9b1a38aa42 | |||
| 9af9500a0c | |||
| eb4fb0cb5d | |||
| 415eb2496a | |||
| bb5e793580 | |||
| fcc2066d01 | |||
| ad625de65a | |||
| 6f26975964 | |||
| 9a8cbe189f | |||
| 782dd6d45b | |||
| 5ed6f37ad9 | |||
| fceeaca439 | |||
| f46a1041b8 | |||
| 90a26d4d51 | |||
| 90a367e2e1 | |||
| 5273535527 | |||
| c777a6802f | |||
| 267b3e487b | |||
| 4ca05b7aad | |||
| b1d7592e34 | |||
| b6d8a11148 | |||
| 8ca8824655 | |||
| 59df24f63f | |||
| 81b8f0f159 | |||
| e4a7b6e868 | |||
| 773b4d80a5 | |||
| b14aab2fe4 | |||
| a02c29d25b | |||
| ec5c7742d9 | |||
| 6916fd5c3b | |||
| 06e1a61fab | |||
| 93f5de21b1 | |||
| 8350d5d0af | |||
| 0fa7cbe6a3 | |||
| 45d5f42ca3 | |||
| f15c11d440 | |||
| 20d6fdf375 | |||
| c3d5b77c96 | |||
| 9b37416720 | |||
| 163c32fc28 | |||
| a786828ddf | |||
| 23bfe3fe09 | |||
| 732c7f1d0b | |||
| ce83863f87 | |||
| 713c893939 | |||
| 7951713874 | |||
| 42c7a8c6ab | |||
| 99f4928d7c | |||
| 356b89e672 | |||
| 7b79b4cdef | |||
| db4e999d61 | |||
| 346b857c6c | |||
| 936b124ff7 | |||
| ed22af820c | |||
| a5e8bdf451 | |||
| 8b2caa1a2a | |||
| c43e0ecb14 | |||
| 4c40782b30 | |||
| 5c83be026b | |||
| 0a3b46fdf5 | |||
| af58f11739 | |||
| 58d05259cb | |||
| 662bf63f87 | |||
| 947e86f4fa | |||
| a0f5714f8a | |||
| b7ab54776d | |||
| 4a1cb62fce | |||
| bf1aad6a7d | |||
| 93ee85a925 | |||
| 69a95852ba | |||
| 8e4605294a | |||
| 289cf2170e | |||
| 8f6d84e669 | |||
| 21466b9afe | |||
| de39c3b77a | |||
| 374362b25c | |||
| 7965ccd65c | |||
| 893a2d0859 | |||
| fea84ff0f2 | |||
| e06e3096cb | |||
| 0c586271e5 | |||
| 1d4187bd0f | |||
| fe07d43e5d | |||
| 9e40bb3bfd | |||
| 4704c9d427 | |||
| 49087105ad | |||
| dd0ae959fe | |||
| 8f8639aa7a | |||
| e5e35f6545 | |||
| 1ae525bf0e | |||
| fb2f498e54 | |||
| cf2466f185 | |||
| 5ea4a79c06 | |||
| ed32045dc6 | |||
| 1fe93d4e86 | |||
| e933b3091d | |||
| 0a8fd09acf | |||
| 200a9c69ff | |||
| bfc21a4e47 | |||
| 276147ac65 | |||
| 9094ef8b1b | |||
| b4ca4f9cf3 | |||
| a5c397f21b | |||
| d5221dcfe4 | |||
| 847f7587ff | |||
| 061f5a8426 | |||
| 6a2d2601fc | |||
| 0d49574056 | |||
| 10d2a5b770 | |||
| 9b0290012f | |||
| 9db1cd07e3 | |||
| 5b36ba86ad | |||
| f38dfb4e28 | |||
| 38d882d889 | |||
| 4e598bde94 | |||
| 702a31b06e | |||
| b5664b575d | |||
| 0ffaf38602 | |||
| 2eae2f926c | |||
| 96b47442ea | |||
| 93ae3cea51 | |||
| 6895e23eca | |||
| b744916fb8 | |||
| 0febad916b | |||
| 7b44a35460 | |||
| 5e08c5cb5b | |||
| c4238a2fb7 | |||
| 2aa6ff8d7d | |||
| 6d05a9e061 | |||
| f8ca997175 | |||
| 377f70de36 | |||
| 0dbeed4691 | |||
| ca3a3794bf | |||
| 1bcb523456 | |||
| 68a81eed0b | |||
| f9538ea708 | |||
| 03cc15ebdd | |||
| 37b0481304 | |||
| c1d4c1d4c5 | |||
| a7f4957c02 | |||
| e039942a02 | |||
| 1706273d74 | |||
| 23d972d9dd | |||
| 3b50a66d0b | |||
| 969a41048d | |||
| 5fc7981de6 | |||
| d041abd435 | |||
| 9a0f0f438f | |||
| baca67f7a3 | |||
| cb069a418f | |||
| ae4e6226cf | |||
| fda20b8236 | |||
| c5dc486e2c | |||
| 144e84154b | |||
| 5de083e234 | |||
| e4529f9217 | |||
| b511f31d39 | |||
| 4d6e41a185 | |||
| 73740bdbc6 | |||
| b30c9ee4b3 | |||
| 386b63ceb9 | |||
| ebbea8ae40 | |||
| ad7d70ae34 | |||
| c182f4d479 | |||
| 6353d911c0 | |||
| 8c4ce99b89 | |||
| 6c34a2f48e | |||
| f95a872d12 | |||
| 95c59da336 | |||
| 78a151d337 | |||
| cccdb1f6d6 | |||
| 4dce1b28b8 | |||
| 8bac0c2ba3 | |||
| c194579f5e | |||
| 2a3e635cd1 | |||
| 82c3fa3aaa | |||
| 2830225b2c | |||
| cf9ed2855f | |||
| b4edd36ec5 | |||
| 49d1a39d16 | |||
| 23a8d8bf1b | |||
| 1e70c7ac38 | |||
| bf0d4e7154 | |||
| e8fc6ec946 | |||
| be2b52ac8f | |||
| 7bb06e0661 | |||
| b56cad3cbc | |||
| 5bec43f720 | |||
| 25bb76ce20 | |||
| e94efb4a11 | |||
| de438d035b | |||
| 88c9b123ee | |||
| 2c234e63e7 | |||
| bd94258500 | |||
| ee5f2a5475 | |||
| 2806d0edbe | |||
| c51821715f | |||
| 85cbeccd3e | |||
| 147510bb00 | |||
| 450ca7325d | |||
| 3f5fa2d889 | |||
| 2e4860e39e | |||
| 392c7581eb | |||
| 81f0d2464c | |||
| 58a93485de | |||
| 23c4395731 | |||
| 0a20822e64 | |||
| cdc9002e41 | |||
| f8ae534480 | |||
| c6f3793178 | |||
| 96451fdb37 | |||
| feb47b3bb1 | |||
| 4f02439cb1 | |||
| b0e8f9ff56 | |||
| 74a7f5d065 | |||
| 8cc988f172 | |||
| a14e1de6cc | |||
| a30e3a7e94 | |||
| 450f9db5c6 | |||
| eca7dc5b27 | |||
| e51df22a48 | |||
| fa3b613148 | |||
| d4a6b3ab85 | |||
| c295b15d7e | |||
| cf48df0f49 | |||
| 16a94230d2 | |||
| d226ebb036 | |||
| 2c658704eb | |||
| ea1eacc952 | |||
| 161ff1c6b0 | |||
| eec4df655d | |||
| bd0ca7917a | |||
| 5af34cc0da | |||
| 69f491c008 | |||
| 1f848288d8 | |||
| 9cd8e34252 | |||
| 5137b37f86 | |||
| 16086b3349 | |||
| 153e0f6d48 | |||
| f44a019aed | |||
| f826fbc2d9 | |||
| f03f1c237b | |||
| b4c23f8ebf | |||
| dd8985b92d | |||
| bf9d59fe21 | |||
| 9fcd20505c | |||
| a142d30a9d | |||
| c3658bd810 | |||
| 6e7d9062cb | |||
| a6438d91b4 | |||
| d2d16360c1 | |||
| 3b277785c0 | |||
| c94bc0c5c8 | |||
| b1495e485e | |||
| 6d6ba0c668 | |||
| 0bc09d7d86 | |||
| 563f2e3594 | |||
| 6ba83d0891 | |||
| f21962defc | |||
| c3719a2eca | |||
| 3b58cf8c0e | |||
| b390f1ef73 | |||
| 02fd903228 | |||
| 52ca0dd3f6 | |||
| 6a874b283c | |||
| fd238f3e40 | |||
| 438036550f | |||
| a0e14bd523 | |||
| c8a76b7dd5 | |||
| c86c3ce16d | |||
| dd48772c9e | |||
| 53833582b7 | |||
| f262b76a41 | |||
| 441e17174d | |||
| defd58bc77 | |||
| 38f2897c29 | |||
| d9d019c5d4 | |||
| f23152d7a7 | |||
| d625837eb9 | |||
| cecd35e20b | |||
| 5ade799440 | |||
| 2786b195ee | |||
| ad6f51646d | |||
| 328190ca63 | |||
| 5b5649de74 | |||
| 78003d863a | |||
| 71c635dedc | |||
| 5f5518e05b | |||
| bd33305e5b | |||
| aa8bd8a8ba | |||
| 84cdad7f7d | |||
| 3c38ca5a1b | |||
| ffaf3e7d91 | |||
| a81a6fc0ec | |||
| 6c3559792c | |||
| 6292ead1f7 | |||
| 9a15ceadf6 | |||
| f61e9a9941 | |||
| 21a113f38f | |||
| 4f3bd6f9dd | |||
| d2c80f4d1a | |||
| 2949d86908 | |||
| 0fcbdbf0fe | |||
| 1dc22a9e8f | |||
| 5c769d2d24 | |||
| a2e63b7f0b | |||
| 44c33f1618 | |||
| 4730d7087f | |||
| 3b31a0234e | |||
| cac5b2ca97 | |||
| 3b08f13bf3 | |||
| e51bb180d4 | |||
| 4e97b6b47c | |||
| ed6ee71ded | |||
| 6c69295696 | |||
| fb72939392 | |||
| b61692f121 | |||
| 9ff2549315 | |||
| 3a4eb97315 | |||
| 4f58be6548 | |||
| 33bd62d32f | |||
| c547c88e89 | |||
| 2a4dcce444 | |||
| b41d008223 | |||
| a144ad9a1e | |||
| 93be0562cc | |||
| 64bb988613 | |||
| 3fcff1b1b3 | |||
| 6150ba4860 | |||
| 676307027c | |||
| 976f16c4d9 | |||
| b88e90fec3 | |||
| 2103459845 | |||
| 348eb1e187 | |||
| 1fb6ad5488 | |||
| 328aa2cc45 | |||
| 2deb2ea0f0 | |||
| bc1ab2d79b | |||
| f3e77eea3d | |||
| 6b0e717a19 | |||
| 906a9748b5 | |||
| 414c33ffc9 | |||
| 77f8c5cbf2 | |||
| 3f5d7030cb | |||
| c53c3afd46 | |||
| 33fd7f0c67 | |||
| 853f0a13e9 | |||
| 9569ad645b | |||
| 3a98117aa5 | |||
| 42092bc91e | |||
| 2d6f46dfa8 | |||
| f1f400bcee | |||
| a6e289c8ef | |||
| a83ec513a1 | |||
| f043a8789c | |||
| 30bbef4b14 | |||
| 26fb62c748 | |||
| 77c0e85775 | |||
| ac45276835 | |||
| cfa242a6a5 | |||
| 26599981a0 | |||
| 8fe2191d04 | |||
| 35b4c6c6b8 | |||
| e42ccef4a7 | |||
| 8449139061 | |||
| 16e7e60cab | |||
| c53988d01e | |||
| 1fea8b38fc | |||
| 7d6cd9ae7c | |||
| bd70c33606 | |||
| f2a0ca2b0e | |||
| 282543b759 | |||
| 15748575d8 | |||
| cc9655af45 | |||
| 465bf1c10a | |||
| eb1200a2cd | |||
| c1a71e53f9 | |||
| f5fe661c13 | |||
| f42e5c4814 | |||
| 135a4ab58c | |||
| b192207132 | |||
| 3464e84e90 | |||
| a0ee98cb4b | |||
| 01d7a64670 | |||
| cbafcb5aa6 | |||
| b604bf2d7a | |||
| 05efca8430 | |||
| 007f125e46 | |||
| 83dd618e5b | |||
| ffc992893f | |||
| b04e3d6cd6 | |||
| 5e19f9707b | |||
| 457d07a50f | |||
| 3262a4e103 | |||
| df27c80c72 | |||
| bc54e34375 | |||
| 49deb08b81 | |||
| b8fbe8341f | |||
| 07e46fb8aa | |||
| 0ee86b72fb | |||
| b54c43b966 | |||
| 1b82e5cba7 | |||
| 8a825ee775 | |||
| c91b667c13 | |||
| 32611749b2 | |||
| dd9e29c425 | |||
| 8debe6ef1d | |||
| bab56b0d88 | |||
| 0b43b4fdc2 | |||
| 210fb3539c | |||
| 026f3f2aef | |||
| 9b5d0a50f7 | |||
| d3df13225d | |||
| fb2ebab793 | |||
| 2f71efe6a7 | |||
| 7813d6fdd7 | |||
| 8ce92e1bc2 | |||
| 9316a5c23f | |||
| 64684b6b71 | |||
| f133bfaf9f | |||
| 3f174e0bd0 | |||
| 39a0e3b29c | |||
| ac8e86643e | |||
| 6a51ea96c0 | |||
| 94e2d9059a | |||
| 85c67ca048 | |||
| 99a5a8370f | |||
| 284ebcc23f | |||
| c156f29c86 | |||
| e075fcd4f3 | |||
| 49a8c459a8 | |||
| 1e45a4c9f5 | |||
| dd825831c7 | |||
| 1b17161758 | |||
| 908971e48b | |||
| ca76e83370 | |||
| 4774f44062 | |||
| f198acda79 | |||
| 86a564094c | |||
| f2c5dd8d71 | |||
| ed8ef96a61 | |||
| 87a1ae56d7 | |||
| 63331e705a | |||
| 6f447c2b6a | |||
| f415e99a36 | |||
| b699ad9ae1 | |||
| 632a762654 | |||
| a4a3bc72fc | |||
| b809739d8c | |||
| 7ad2a4c3f2 | |||
| 4c4332c88b | |||
| 6c0ef59a30 | |||
| 83714d4d03 | |||
| 7498ef647c | |||
| 321dfcf741 | |||
| bdc6fcf5dd | |||
| 50cd61e7c3 | |||
| 125796fec7 | |||
| d1d0e1c732 | |||
| 820fd1c13a | |||
| 577373aed9 | |||
| d1865a2c1e | |||
| 60efef0caf | |||
| 71c53d9f3d | |||
| 11a58a55c3 | |||
| fc099a35ab | |||
| f992fe0b8d | |||
| ac99f9e46c | |||
| 225df7593f | |||
| 5ecad32251 | |||
| cfd44fc50c | |||
| 20f47863bf | |||
| c6cfbd4e8c | |||
| 8422056873 | |||
| 80ba651375 | |||
| 18e5bf9c07 | |||
| 0394180213 | |||
| b52be989ed | |||
| b15597dbe7 | |||
| 6aa4ae880a | |||
| 01d2d77a76 | |||
| 640a49e1ce | |||
| c8cf6df4cd | |||
| 7f0a1a1caf | |||
| d9942c0c32 | |||
| 587d573a04 | |||
| 391adea516 | |||
| aad088e588 | |||
| ed31e39491 | |||
| 34345b47d0 | |||
| 873a2c8dda | |||
| 838bef63b3 | |||
| 6d97118181 | |||
| c1544ba7c4 | |||
| 008e02b03c | |||
| 2e68155c6d | |||
| a53e880346 | |||
| 79f4bb679e | |||
| 21baa41ccf | |||
| d20ccf186e | |||
| 3128aadfe0 | |||
| 03da97b0b8 | |||
| 2d39b3c2d0 | |||
| dada8dc1db | |||
| 5b47785ae4 | |||
| c18e92df67 | |||
| 8828ac5d30 | |||
| 83d717bcae | |||
| 21f9524b3e | |||
| c7078a3e10 | |||
| 1bbd9675b6 | |||
| 87db306da0 | |||
| c41da878f9 | |||
| 0a17e5ab7f | |||
| 2f356fd916 | |||
| 1bf52bda9e | |||
| 89117a326c | |||
| 51bc877b4e | |||
| f5772f0423 | |||
| 95596a53b0 | |||
| c114ad9aa7 | |||
| bb9c35ffea | |||
| 6b426b5f83 | |||
| 9e215a3493 | |||
| 3321873fc6 | |||
| fc57cac746 | |||
| dbdd00fef8 | |||
| 0986cb46d9 | |||
| e55384067b | |||
| c905f0658d | |||
| 99fca41f02 | |||
| eb666a62ac | |||
| 6e660e4c27 | |||
| 00bf89e1d2 | |||
| 48a98d8b1f | |||
| 1a8421bbfe | |||
| ecc4bab8f2 | |||
| b5a64f2fae | |||
| 7e11cfb891 | |||
| cdcfbd8ab2 | |||
| 9964005525 | |||
| 3dd8898aaf | |||
| d3acfdfa07 | |||
| cb0eeaeb32 | |||
| b114ba4ec6 | |||
| 688683fdaf | |||
| f0740d8235 | |||
| bf33ac89eb | |||
| baeee68d27 | |||
| 25d1f542d7 | |||
| 1b919575f2 | |||
| f7e49cfb04 | |||
| c3cbbcacd7 | |||
| d030b978ab | |||
| 1acb811437 | |||
| 1bf7be4d2a | |||
| 44096d2f95 | |||
| 136cb036b4 | |||
| a1bfcd1216 | |||
| 277173ae0f | |||
| 28e6e63c5d | |||
| a49623136a | |||
| 9041f3ed1f | |||
| bc759b5bb3 | |||
| 0d70b12c75 | |||
| b471e74ef8 | |||
| 745412ffb8 | |||
| 680c125dde | |||
| d072cdd527 | |||
| 570126f8ff | |||
| 5de828fa15 | |||
| 32f3411eca | |||
| 7509e66617 | |||
| 92d65a529f | |||
| 51590ad30f | |||
| 7af70745f3 | |||
| 936c25c98b | |||
| fcbfa307ef | |||
| 534b655291 | |||
| 5a0fa236cb | |||
| d17845d767 | |||
| ecd20983e8 | |||
| 66b200178f | |||
| 7dca6e0b04 | |||
| 60b6fb3d39 | |||
| 9d1a3eff16 | |||
| e560f2329d | |||
| d58602289d | |||
| 8845f347d3 | |||
| d6611f02ba | |||
| 3ed9dc6a94 | |||
| dbfc58c5ed | |||
| aedad2ccb0 | |||
| 1aa79965c7 | |||
| a7ec5d9b71 | |||
| 4afb2919fa | |||
| 52d6092ffd | |||
| 4bef99703a | |||
| 1afa21922f | |||
| d3cb3eccff | |||
| 937d727011 | |||
| ca7f175fb7 | |||
| 81f5e4c039 | |||
| 2f4ed00c93 | |||
| cb1b1daacd | |||
| 6862cc0ce9 | |||
| 6ff8bda568 | |||
| 8e78937160 | |||
| d7bfb88be9 | |||
| 46654ba28a | |||
| 34889dfb6a | |||
| e2a3b89175 | |||
| 6a51a05171 | |||
| 09bfa883ac | |||
| 6f0268171d | |||
| e0da616e37 | |||
| 224f0a0684 | |||
| f928f6c161 | |||
| 4e5203a3dd | |||
| 58363c9dab | |||
| 0e7024488d | |||
| 6310a6040b | |||
| ec31e714d6 | |||
| a80d3bcf38 | |||
| ad9b41e45e | |||
| 9d643387fb | |||
| c570beefbd | |||
| 6f97972582 | |||
| 736368f441 | |||
| 8975be38ae | |||
| 7aede726ca | |||
| 228150cd72 | |||
| 9f4f9e7b2f | |||
| 629de5c931 | |||
| 30af256bb6 | |||
| 7340c86c61 | |||
| 187c6692d8 | |||
| 0c5de08870 | |||
| 36a6d0c93c | |||
| 2d66b73e34 | |||
| 18517c1fe5 | |||
| 69dfc4fe32 | |||
| d7fe272673 | |||
| 40add040f9 | |||
| 766d7138ac | |||
| dc3fb38cbb | |||
| eb1e734628 | |||
| ba95d49a67 | |||
| a90aee32a0 | |||
| 8a9502ce01 | |||
| 8d46c4debc | |||
| fe2ab99c52 | |||
| a5467f201c | |||
| 976c3bbe98 | |||
| 551de62f42 | |||
| 860df74295 | |||
| eca4117497 | |||
| 434226dd01 | |||
| e770997d09 | |||
| 52d42bca30 | |||
| 3b5eba1c85 | |||
| 76af0aa6ed | |||
| 4a6e000a07 | |||
| cf2fbcb6e3 | |||
| 11c2f8c991 | |||
| 0d3182c278 | |||
| 1d2a21fa1f | |||
| c6763e76ee | |||
| 818c1ea9e9 | |||
| 0b4d0fcf67 | |||
| 384c4b998e | |||
| 449bd78db7 | |||
| 5d2227d3a6 | |||
| 0058449576 | |||
| 2059a57d96 | |||
| 8bb9ab629f | |||
| 73c536fa04 | |||
| 2d07bbdf2c | |||
| 83e7cf54f4 | |||
| 54725d30b1 | |||
| e688cc520b | |||
| ec5e79f86b | |||
| 87d56eb866 | |||
| 2922488eb9 | |||
| b8230bf5e6 | |||
| e66a3625b4 | |||
| 61ed256846 | |||
| 31bafccb6c | |||
| db709dc4dc | |||
| 9461d8ec13 | |||
| 834eb4c1b6 | |||
| 21ab738c72 | |||
| 620a465f84 | |||
| 0c760dc107 | |||
| ad7ea01ee8 | |||
| 1026821e33 | |||
| 302bdd366c | |||
| e5241d93e5 | |||
| 6804f40bc4 | |||
| a18fc4fd93 | |||
| 315dfd2041 | |||
| f5513abfc8 | |||
| 0296999ec8 | |||
| b2a44942a8 | |||
| 268e4d5ec9 | |||
| 4f562dbbfb | |||
| e9127c0427 | |||
| b2545f4d89 | |||
| 9c922e0c73 | |||
| d6721ea8ef | |||
| c8503d149e | |||
| cd045df1c3 | |||
| 20b226769f | |||
| 8460428f2e | |||
| d7f63afae7 | |||
| 6ad1a5b57f | |||
| a2388cc4b4 | |||
| f79ee4b582 | |||
| 03fd848f18 | |||
| 258a44de1a | |||
| 20a04408a6 | |||
| 662356311a | |||
| 806cba6352 | |||
| b42e00961b | |||
| fc0089c0f4 | |||
| 2c9b70a674 | |||
| 0bb0cb7b93 | |||
| 0e9a8e6c3d | |||
| c7d39c7975 | |||
| 86abaf4009 | |||
| 382c3d1787 | |||
| 2ac8e7e496 | |||
| 2425ad39ef | |||
| 6b5b86f343 | |||
| 230645ffa5 | |||
| 3861eada88 | |||
| a1691fda9b | |||
| ec7d64d30d | |||
| 8cda08d41c | |||
| 05fe040f88 | |||
| 756cc86a23 | |||
| 9e470dffc3 | |||
| 6e2080f092 | |||
| 24a0b73ce3 | |||
| 473c0eecb1 | |||
| 10baa77dbc | |||
| dec333d063 | |||
| 61d85c75d3 | |||
| 8dab22328c | |||
| ac0991a7cc | |||
| bc276b2bc1 | |||
| 1e6415ce45 | |||
| e4f6408939 | |||
| 497bb74d5a | |||
| dee939e78c | |||
| 79aa1535f3 | |||
| 9f2902e9d2 | |||
| ace6574179 | |||
| 8ac82843af | |||
| 3e4acb6921 | |||
| 3a41b51160 | |||
| c0ed9be287 | |||
| bb9a9fb06d | |||
| 1a0edab86e | |||
| 673ac3faa9 | |||
| 3833b9b585 | |||
| 6ba9224f32 | |||
| d138a49895 | |||
| 0e434f0212 | |||
| f807067337 | |||
| 5e5800363e | |||
| d643cf8c1d | |||
| 7a37ee7c30 | |||
| d42e7a6d0a | |||
| 115506476b | |||
| fab9df7825 | |||
| 0873562023 | |||
| ca890b509a | |||
| 59fc14c57c | |||
| 907ad64f96 | |||
| c96ad24a35 | |||
| 9a7694f32a | |||
| 73e9110b64 | |||
| 90439fc8c4 | |||
| 1a480445c9 | |||
| adf066acdd | |||
| a2d11d8100 | |||
| f77b8a9137 | |||
| ad0241047d | |||
| 6218b00486 | |||
| 4585f14b5f | |||
| c0af9c2bf1 | |||
| bf2adc6861 | |||
| 743a4eaf02 | |||
| 4df07ae61f | |||
| 6c1d1db4b4 | |||
| 11ac94d449 | |||
| a84a41bc75 | |||
| 5f61c348c2 | |||
| ffdc440926 | |||
| 3457fcb48b | |||
| f70700c330 | |||
| b28727ef8c | |||
| 3af33c8b75 | |||
| 9059dd7e3e | |||
| 2d0f686964 | |||
| cf896e8064 | |||
| 2422ec276d | |||
| c00aa2d807 | |||
| ab400de069 | |||
| 829a28c986 | |||
| 666850a6bc | |||
| 89ff51cc09 | |||
| c0ea316f44 | |||
| 7fae03e300 | |||
| 728d858f15 | |||
| 2029981f00 | |||
| 3e2e67d88d | |||
| 4fd5e3dc74 | |||
| 17a02b8fbb | |||
| 75a174bc7b | |||
| 086e01fcb8 | |||
| a219428887 | |||
| ca86b0acf9 | |||
| f20df8a492 | |||
| d742b306d7 | |||
| 119c647097 | |||
| 64c6fa6525 | |||
| 5a7965468d | |||
| 855ccbf300 | |||
| 855d52908b | |||
| 1440302ab3 | |||
| 9e055bd52f | |||
| d4a36c2e0f | |||
| ef9c8a4716 | |||
| cd21a5ed8a | |||
| 1d0c9511a5 | |||
| cd73b37673 | |||
| f970ede20b | |||
| 9308382295 | |||
| caf0a2c143 | |||
| 06cb649b55 | |||
| e216675ca1 | |||
| fec546e939 | |||
| e7fb2a2c7c | |||
| 1bc6f6eeda | |||
| afc46ac1d3 | |||
| 636e47d219 | |||
| 9c219d647d | |||
| 99da16b834 | |||
| d8e5697bfe | |||
| b504a88459 | |||
| 3745686f38 | |||
| fda2e2d34d | |||
| 2f4da0f0b0 | |||
| 327e60b275 | |||
| 2450bac944 | |||
| 46fe0fbc29 | |||
| 8f30f628a0 | |||
| 27ba7608db | |||
| d2cd341615 | |||
| 978e3e6e81 | |||
| 5099bebba5 | |||
| 6951f13ce4 | |||
| ea76a9f88e | |||
| 35ed9727d3 | |||
| b7ddc30244 | |||
| e525cd4465 | |||
| 3898752f67 | |||
| c0b11f6eab | |||
| b6d9bf7319 | |||
| 16e4a3c10e | |||
| 4b00999550 | |||
| c5797b916f | |||
| 7a6385b614 | |||
| 5391aa0fa2 | |||
| 06659f1dfc | |||
| eec001cad4 | |||
| d953614fe4 | |||
| 82070b999c | |||
| cbf46c9ec4 | |||
| 13347878df | |||
| 343d9fd63f | |||
| 4d1ab8f4ba | |||
| f7ff4d6cc7 | |||
| c1717498f4 | |||
| 74a57d9e12 | |||
| df3bfb2771 | |||
| 76dc77106f | |||
| 265df9d0f2 | |||
| e4352e3c5a | |||
| da44de59b9 | |||
| 8180ca7a9d | |||
| 71125e4833 | |||
| 5408c387ba | |||
| 8df3425a2e | |||
| eb4e4b6b05 | |||
| 166563d343 | |||
| f6dcef3b49 | |||
| 299015ae5d | |||
| dbc4beb71a | |||
| 7d23d0c5b0 | |||
| ac9d618188 | |||
| 87cd21f1f8 | |||
| a54dc98fad | |||
| 392b535cf0 | |||
| eecce3f414 | |||
| bea31d6487 | |||
| bd51ec2c87 | |||
| 75c461c8f9 | |||
| c8d4f578af | |||
| 4b242b57c8 | |||
| 6a5e3bf70d | |||
| 43bb81fd82 | |||
| 1f6d0347cc | |||
| 0826d6de53 | |||
| df5905ace6 | |||
| acadb46e6c | |||
| ccee2254e0 | |||
| e26b497ccc | |||
| 5e49ae47a9 | |||
| 1d79c8dc53 | |||
| 7bf7f4bbe5 | |||
| bba1cb3859 | |||
| 36b77224c5 | |||
| b310b6745d | |||
| 9ef345f02d | |||
| 8649c899db | |||
| ed9f98bda1 | |||
| 2e1dcf1479 | |||
| 90b02a4f6c | |||
| 16b634a7fc | |||
| 873176a3e6 | |||
| 6c30d76401 | |||
| 9bc6fe4e7a | |||
| 013a31afdb | |||
| 57b0050ae7 | |||
| 61a105af21 | |||
| 51a6c25e16 | |||
| 0e3ff45eb9 | |||
| 77e7c6f60f | |||
| d09deab2f1 | |||
| 3e77a6301d | |||
| 3e89ecfdf6 | |||
| 644fffd69f | |||
| a84dd0068c | |||
| eb05af8e74 | |||
| 7c6c5fe445 | |||
| 191c80211b | |||
| b13164b2c0 | |||
| 28456d5486 | |||
| eb99e12003 | |||
| 058529526c | |||
| 49cf104a12 | |||
| b639466adb | |||
| 1cf86b9641 | |||
| f894771e7d | |||
| 451a4762df | |||
| 92313a2d64 | |||
| 94743678a9 | |||
| 4a6e5ee331 | |||
| b284eab745 | |||
| 6969cf239a | |||
| 2b3b68605e | |||
| 738735b808 | |||
| c1034b9344 | |||
| 42e6c413b6 | |||
| 4e75362d4b | |||
| 9bbfa99b4c | |||
| 1f49f40faa | |||
| 69735ce1a5 | |||
| 8d1ac59134 | |||
| 3407a01845 | |||
| 485a114a2d | |||
| 4ae082bfc7 | |||
| cbd6277844 | |||
| 96f04b41cb | |||
| ba9338c522 | |||
| b39cf878a0 | |||
| 20bf1d71bb | |||
| 313a167729 | |||
| ca342d8de2 | |||
| 0c2dd78f3b | |||
| 3c81d0423e | |||
| 3fcc420e08 | |||
| 65c099c02a | |||
| c197a4a62c | |||
| 60fbe881c1 | |||
| e96365a4bc | |||
| 1e865deaaf | |||
| df98467eaf | |||
| 7265a5f3c0 | |||
| 0ac1983b66 | |||
| a0e8906575 | |||
| f13dc2777d | |||
| 0f588a8d97 | |||
| 6ce3443a34 | |||
| 1e448915d1 | |||
| a9124f0a4a | |||
| bd1adba17e | |||
| 39cb30a4be | |||
| 6ced31f8b5 | |||
| 74ceb06336 | |||
| ee35d8ada2 | |||
| 4e92674be7 | |||
| a39d25f6c1 | |||
| 0147e59899 | |||
| a08faa038f | |||
| 42189e5c52 | |||
| 6c05ba06ff | |||
| 1a75a82523 | |||
| 8b5b6d3636 | |||
| fd8b0ba57d | |||
| 187ae2fe0e | |||
| 4a6a601b5a | |||
| 5631c4d214 | |||
| 6be5ea55ce | |||
| b43e2f9190 | |||
| eb81a302b0 | |||
| 6b8f9a0d07 | |||
| 7d8b071049 | |||
| e143b5d142 | |||
| 929e23b74e | |||
| 07fb4b1e5b | |||
| f652969936 | |||
| 65c0b60e5f | |||
| 5b76e3e70f | |||
| 99d7c597b6 | |||
| 5e7e0d7b2a | |||
| e377cbad38 | |||
| 0824ceacd9 | |||
| 4ddb327597 | |||
| e068eb8bd1 | |||
| 0a9cb8d248 | |||
| bb1711de60 | |||
| 8c85cc598d | |||
| 5883e3db52 | |||
| 2894f50005 | |||
| 87a9c29cf7 | |||
| 471e30d85e | |||
| 3330ba77b1 | |||
| 62df1e933b | |||
| d23b3123ba | |||
| 2d73bd9927 | |||
| ca379f0814 | |||
| c5b3ed12a0 | |||
| 0e177e766a | |||
| 15234069fe | |||
| 45c531c463 | |||
| 01d0b1767c | |||
| 45f247393e | |||
| c8967b4b5e | |||
| cd40e70901 | |||
| ec3c5c7774 | |||
| 69c4f021c9 | |||
| a2fb5d5cbe | |||
| 0261a0b795 | |||
| 3b2ffd1a07 | |||
| e20b40ee61 | |||
| a882435757 | |||
| afbb95d987 | |||
| 74f9163b24 | |||
| cda26929bd | |||
| f9a6120685 | |||
| 979da57982 | |||
| 33e923540a | |||
| c384b746f7 | |||
| 4d9cf433ff | |||
| 380cdf687a | |||
| 722fb64245 | |||
| 67b0c98578 | |||
| 9f6f56f3ff | |||
| 91a6beb749 | |||
| a5cf22af80 | |||
| cc6d4c0c06 | |||
| 0b0a187967 | |||
| 966643a542 | |||
| 04569d27b7 | |||
| f55a3c0b3d | |||
| 579a173fbf | |||
| fa4bcd0cd4 | |||
| 8acd0300cd | |||
| 65f12f1df5 | |||
| 551fe6ebc5 | |||
| 95c06276cf | |||
| 403ece5588 | |||
| fce27dc4de | |||
| b41cef3631 | |||
| 3eeae90472 | |||
| e366a6eed4 | |||
| 90c8be1fa3 | |||
| 669ce539dd | |||
| ccef3f6d9f | |||
| c1b38a9203 | |||
| 3f159872c0 | |||
| 9a836af0d0 | |||
| 4e486b1f59 | |||
| 217edad33c | |||
| 89a326ebc5 | |||
| bce75ae3a8 | |||
| 9bf17256fb | |||
| 027cd21aa1 | |||
| 391b3eef11 | |||
| 4bf8491d01 | |||
| a62ac4df3a | |||
| 9a7206b971 | |||
| e23f26a8f3 | |||
| 490d38c9f1 | |||
| 02418f7498 | |||
| ca21c26638 | |||
| 00a9973ca8 | |||
| 2ee1d5fca6 | |||
| d8b046a69f | |||
| 08bcb4249d | |||
| 35f5503e26 | |||
| c0b90df335 | |||
| bea15392ec | |||
| 52de20c3b6 | |||
| 365e662472 | |||
| 89758558cf | |||
| 8d5ddc0ddf | |||
| 9d2617d9a0 | |||
| 6b17652197 | |||
| 6c2a73ebda | |||
| ad45701790 | |||
| ad3b6a04cc | |||
| caab4a3f41 | |||
| aecc283cb5 | |||
| 87c9e523c7 | |||
| 90451d9635 | |||
| e567af9b24 | |||
| dfae0be7d0 | |||
| d62a38e533 | |||
| bc8ee80491 | |||
| 915e34b32b | |||
| 5099a91a21 | |||
| 6f9ab0dea5 | |||
| f90c3d0350 | |||
| 66d375b3b3 | |||
| 233d71fec7 | |||
| 14f3f82555 | |||
| 22fec82616 | |||
| fcfdb18914 | |||
| 23d17d56e9 | |||
| 4d50d21f78 | |||
| 722285bd8f | |||
| 2bd8f97709 | |||
| b4aae47556 | |||
| 1d546dbd83 | |||
| 9fbb2607a1 | |||
| 442d4c9e35 | |||
| de7999c932 | |||
| 03cf88211e | |||
| ec4d9bbcb9 | |||
| 2df1260c87 | |||
| 6e762c1ae3 | |||
| 2db3a828d6 | |||
| c62cf3c82d | |||
| 5da9cd2205 | |||
| 883d92940f | |||
| f53e19589d | |||
| 8e6b694d6e | |||
| c298892833 | |||
| 971997fbc1 | |||
| 8b87d39c72 | |||
| 1124cf3a03 | |||
| 3691c3cc98 | |||
| 072734f7e8 | |||
| 0b34c336f7 | |||
| 6b64959309 | |||
| 704cab010d | |||
| 3153bfd916 | |||
| 493c34dfb9 | |||
| 346cdbfb18 | |||
| cb9fdc66e3 | |||
| 07aedd4bb2 | |||
| 8881f8bd91 | |||
| ee2b9fc885 | |||
| 250109b215 | |||
| aaa8a45658 | |||
| e683e1ab1c | |||
| 23a116b96e | |||
| 29014acd87 | |||
| c4ccb4a8ca | |||
| b392b2a867 | |||
| a7de7bcf31 | |||
| 371b1b01cb | |||
| 08062bc3c5 | |||
| bac11af00e | |||
| 69ccebd108 | |||
| 7f3f471f12 | |||
| 9f7eb9eecb | |||
| 86f50b36d6 | |||
| 0eca73234a | |||
| f346815b18 | |||
| 5e9325fad1 | |||
| d668f7749f | |||
| a34d15da01 | |||
| 7bc4564029 | |||
| f302d055e9 | |||
| 9cb258d920 | |||
| 4b8e9cf7d1 | |||
| 9b33c46995 | |||
| 6ae06014c5 | |||
| 32cd28829a | |||
| aceebd88bb | |||
| 7ad0b27460 | |||
| 635374075f | |||
| d3672ded33 | |||
| b5f68770a3 | |||
| 1bd35c2b55 | |||
| 1242430e2f | |||
| 771bf92f78 | |||
| 042f455113 | |||
| 57464209b8 | |||
| d6f35d7c5c | |||
| 1f73d0d258 | |||
| 7f9545754c | |||
| 1e22e6d203 | |||
| 496f1d91d0 | |||
| 5a38178db2 | |||
| 55b4291df0 | |||
| 5c419ea37f | |||
| 02ccad8fbc | |||
| 9a8e9dc34b | |||
| e6aae4aa5f | |||
| b8458246b8 | |||
| 287416006a | |||
| 1a1dda1796 | |||
| 3fd0b3ba42 | |||
| 77712a63ad | |||
| caf9c39afa | |||
| 0db07e14d6 | |||
| 988d512b77 | |||
| 06c632fa50 | |||
| f750bcefab | |||
| 4946bbcf97 | |||
| dcdca3338d | |||
| fbbd5dc9a6 | |||
| 913319d9e3 | |||
| 3919d03f97 | |||
| 5c19b67791 | |||
| a55fa0d833 | |||
| 8e1489d85b | |||
| 797d537cb8 | |||
| b6618577c7 | |||
| 0cb76eb275 | |||
| 93cea27ad8 | |||
| 263326ecbe | |||
| 61c85465b9 | |||
| 25c33df302 | |||
| 7d5a47afe9 | |||
| fc7802ea0f | |||
| b2ddd93191 | |||
| d9a9624c6c | |||
| aff09e3e34 | |||
| 6db993b589 | |||
| a454a51939 | |||
| 6a1e38d831 | |||
| cb6943010a | |||
| 6929464500 | |||
| 6e956f6cc3 | |||
| b080a339a6 | |||
| 5de2add9c3 | |||
| de77db64fc | |||
| 555885a3b0 | |||
| f6ec749e96 | |||
| a5b8f5af68 | |||
| fce7c3cc39 | |||
| 4050d495ed | |||
| 3378f0de19 | |||
| c05e7134ed | |||
| f8a6287322 | |||
| 6c6a9a073f | |||
| 9c309707a7 | |||
| 9c1e4a0e70 | |||
| 7298cd1110 | |||
| e672f9711f | |||
| 740ad8c1b2 | |||
| 62310f6b21 | |||
| 9c2de843b5 | |||
| a905bf35a7 | |||
| bd1932f12c | |||
| d272bd4e05 | |||
| 67e42e8600 | |||
| 078d8b607c | |||
| 7c001bf468 | |||
| 2eef3ac5fb | |||
| 63cc2150a0 | |||
| 2476dd4474 | |||
| b954d65b8f | |||
| 1b62aa5a79 | |||
| 48d1219f5c | |||
| 210e88b511 | |||
| 21960157ae | |||
| 73322272fe | |||
| 4d12a0bfdf | |||
| b632880fde | |||
| 707b722c36 | |||
| dd3ca3aa63 | |||
| a4c3028881 | |||
| b4b0d52ffb | |||
| 492afc0f9d | |||
| 38b3f73a85 | |||
| 2319629592 | |||
| 802ac99d0d | |||
| e91a1198a0 | |||
| b835a6b564 | |||
| 2687579986 | |||
| e05f635db5 | |||
| d3f1f2a341 | |||
| 4886a7c0fe | |||
| 93ad9161ec | |||
| 39633a0f09 | |||
| f8baaaf617 | |||
| 354e017a33 | |||
| 3d9d4ce7be | |||
| 530b65e51d | |||
| af6bed4995 | |||
| f7f981d549 | |||
| 1454050eef | |||
| 8c80e6c2f8 | |||
| b4237e51dc | |||
| 7af432c313 | |||
| 833462a84e | |||
| 222eea66fa | |||
| 072626d390 | |||
| e4dedb226f | |||
| acde0b6311 | |||
| 8cb57d43d6 | |||
| f597f96152 | |||
| 0f5b5f1f6c | |||
| ea0a9ae7ab | |||
| 98abf1d812 | |||
| f1b9327123 | |||
| 497b9deadc | |||
| 2e723a700d | |||
| 5b558714de | |||
| 2641f7fe88 | |||
| 80bf1491e1 | |||
| 22cf3afdfa | |||
| f2084098e2 | |||
| 00e998e5f9 | |||
| df7f115415 | |||
| 0467d48201 | |||
| 41074331ed | |||
| 034469197c | |||
| c80acdf88f | |||
| 7b9fbc36e1 | |||
| ecd4f30e41 | |||
| 8682d0293a | |||
| 28ddc5db69 | |||
| 9e23045867 | |||
| 08758e9129 | |||
| 14404dff66 | |||
| 7b0e63b123 | |||
| 3b52247058 | |||
| 4c5fe41f2b | |||
| b4ebd87229 | |||
| d5086e07a0 | |||
| b4698b7cca | |||
| 510083f0ea | |||
| e7f300bc7c | |||
| 45773a987d | |||
| 9f8910c258 | |||
| ef462dbb5e | |||
| d38da7ae3d | |||
| a9fe0f2d23 | |||
| 5e4dbc66dc | |||
| e85f337b2f | |||
| a7d36f9f9f | |||
| e6ef4109c8 | |||
| fc7b62e329 | |||
| 3cfda55a69 | |||
| 64a8418674 | |||
| c3e1f137e1 | |||
| 0b1819cdc8 | |||
| dcf642ffb0 | |||
| 21be3e3912 | |||
| d6cb167a0c | |||
| 1177dc94b8 | |||
| daa9c3c13c | |||
| 9d5184bae4 | |||
| c7906b2d61 | |||
| 0b1ddb45a2 | |||
| 3cec6af4a8 | |||
| 8474486b74 | |||
| 695119b3a5 | |||
| 863de62880 | |||
| c716994cab | |||
| db6a90d956 | |||
| 4d847a04a7 | |||
| a60ac679a0 | |||
| 8a5f927d8d | |||
| 073e685b0d | |||
| a7089873e9 | |||
| c2c7f7d71c | |||
| c2c923ba11 | |||
| e45d934cb6 | |||
| f35ff8f583 | |||
| 6b29b3c817 | |||
| 317f336c76 | |||
| ddd0dc6dff | |||
| 1da64ebbd6 | |||
| 48cf146a6f | |||
| ccd6240e23 | |||
| 41c4b6453a | |||
| fda49d72c1 | |||
| 230b3840ad | |||
| 31530c7311 | |||
| ad5f36f2ac | |||
| 718ec64593 | |||
| b078d91894 | |||
| 0e21d85be1 | |||
| 54af49fe40 | |||
| 2d950869f8 | |||
| d3ec8f8791 | |||
| 9033830375 | |||
| 35e5c48814 | |||
| b16efc8c0b | |||
| bdf28a79fc | |||
| bc634975d4 | |||
| 2f682ca9f8 | |||
| bb8c8e5fa8 | |||
| 014bc9ed79 | |||
| a89dbfad01 | |||
| b53716bd7f | |||
| 6e9b3d811b | |||
| 3fa85ade3a | |||
| 1bd05e4561 | |||
| a38a0d5b81 | |||
| efcf28b96b | |||
| 6b827886a0 | |||
| f6712c7cbd | |||
| 3e11da04df | |||
| 56d6ee9a1c | |||
| 897a518750 | |||
| c9b7590dd9 | |||
| 4d3d250d5e | |||
| 43d93b87bc | |||
| f0a90a46ed | |||
| d379c41d72 | |||
| 57688559b1 | |||
| fa26073882 | |||
| b37ca7868a | |||
| 767621d2cb | |||
| ab93e1f56d | |||
| f3523e8381 | |||
| 0eeaf31270 | |||
| 5703b95d0e | |||
| 7acaffa841 | |||
| ea7652677d | |||
| b239441ff9 | |||
| 8bea90280f | |||
| 4fef0935fb | |||
| 421e19ca4b | |||
| 3e00c2d842 | |||
| 3fe8f75d1b | |||
| 8e0837b6a1 | |||
| 347b7238dc | |||
| fdb89d13ef | |||
| f3060d8a33 | |||
| be743da973 | |||
| de8d7725be | |||
| 7033df8c0c | |||
| 2e6e200962 | |||
| b7a44adca0 | |||
| e831a050cd | |||
| 4e2af32bcf | |||
| 198b031d03 | |||
| 5ec60a6a2c | |||
| eadaabbe62 | |||
| b2d7640a1d | |||
| 39ba117abf | |||
| 7a3849ffdb | |||
| 9a367b2be7 | |||
| f671c11773 | |||
| bb7208b754 | |||
| 3ae6f849ac | |||
| e682be574b | |||
| ab084a9399 | |||
| 3f4edebda6 | |||
| a59e3bb3cd | |||
| e62ea4cdb4 | |||
| e3283739ce | |||
| 600aa2ec16 | |||
| 0921355a74 | |||
| 1ac757bd60 | |||
| 9c46074145 | |||
| 2ad239b6c9 | |||
| 9bc8eb952b | |||
| 83cbc1f450 | |||
| 5ef0970789 | |||
| 41920cc74f | |||
| bda63626d2 | |||
| d0d364d729 | |||
| e896c2576b | |||
| 8b417ebd25 | |||
| 6d93d700bb | |||
| 88b0af83b5 | |||
| 5e3d0126e3 | |||
| aef4192d6a | |||
| 30b8b3c61f | |||
| 7a1c6388c2 | |||
| a694ccb39e | |||
| a85bcfc0d7 | |||
| 5cc787f648 | |||
| a011792fb6 | |||
| 2bd88ed300 | |||
| bd234eafe3 | |||
| 0405be5bb0 | |||
| f8616ba0b5 | |||
| c40b0f6f63 | |||
| b10c76a3a6 | |||
| 683b301fb7 | |||
| 76223227ba | |||
| 04e59f26b9 | |||
| ba0f81e65c | |||
| 204352ca8b | |||
| 8b07f89d13 | |||
| 2f01154847 | |||
| 24458b4bf1 | |||
| 52049833fd | |||
| 3ec27d06ec | |||
| 2c813805e7 | |||
| 0583ab3bc8 | |||
| 510d234611 | |||
| 3006bcb3f7 | |||
| b9c2580f22 | |||
| 2684031ff2 | |||
| ae8f10ae47 | |||
| de2866fe38 | |||
| 2f2b10d22b | |||
| 2065013a04 | |||
| 57b3448019 | |||
| 65faee4e7b | |||
| e1c4bbed1d | |||
| 420fb5f6cc | |||
| c4ee764dd8 | |||
| 3e0167a9e9 | |||
| be74b3dca8 | |||
| ba94df76e1 | |||
| 6361dd3f6e | |||
| 9f44a9d6a4 | |||
| b6c0155487 | |||
| 42d93b9872 | |||
| 534ab7a030 | |||
| e0399adca9 | |||
| 33a0cc3759 | |||
| 9ff955496e | |||
| 9424ed9669 | |||
| 248122670f | |||
| 9dc9be484f | |||
| 3fc88faa51 | |||
| 8168ddcb40 | |||
| d57291777f | |||
| e47dd4f054 | |||
| 4e86f62a64 | |||
| 711276e62b | |||
| a2acacebe0 | |||
| 40e70fc6e9 | |||
| f4d5687704 | |||
| 3adfd850c7 | |||
| 42019fca7c | |||
| 0fc2f3d86d | |||
| b10355c846 | |||
| 05d649ef54 | |||
| 71d55ebf18 | |||
| dc80efa426 | |||
| 0068da44d4 | |||
| d757f69479 | |||
| 5629eae3ae | |||
| 496313f56b | |||
| 3640d302e1 | |||
| d07e17d85c | |||
| a87c498af8 | |||
| 75070e1bfa | |||
| 5487c20beb | |||
| bcedf25ebf | |||
| 7ce874f5d0 | |||
| bd0cbfb5b8 | |||
| 67fa3a8c82 | |||
| 3ce169b4e2 | |||
| 441a8868a0 | |||
| dfb744bdf1 | |||
| 849c347d2e | |||
| 9c3fa17ce2 | |||
| 37783c3446 | |||
| 2447ea37ca | |||
| 4d0e208a2e | |||
| 65f894b7ac | |||
| de608e90c1 | |||
| 3aa83b20ff | |||
| 1194823a73 | |||
| 60685f35d8 | |||
| 4d9b0f6157 | |||
| e2428486b1 | |||
| 5a7dd75687 | |||
| 42bc462559 | |||
| d0ff4c3306 | |||
| 2f5acd74d9 | |||
| 7979a01371 | |||
| 59633b8ba6 | |||
| 1eecfd24f6 | |||
| fdda9161fe | |||
| 4156e28d78 | |||
| 418275589c | |||
| 0b32b0109f | |||
| 0f246d7f69 | |||
| d30f4d66de | |||
| be946aab50 | |||
| 2aca908685 | |||
| 99ec33418a | |||
| c416887542 | |||
| dd0ff29f66 | |||
| 3e22f47624 | |||
| bda20507bd | |||
| 9111697a0b | |||
| 97ac1394fa | |||
| 6966d2633a | |||
| 58d341cea3 | |||
| f27587f391 | |||
| ce6536c1d8 | |||
| c0420dfa2a | |||
| 0c77aa5a69 | |||
| 96698c5783 | |||
| 038bc809cb | |||
| 71d559e1f2 | |||
| 184d929521 | |||
| 5e975db36e | |||
| 9a89cf1978 | |||
| 94c1f03300 | |||
| 872df4e54e | |||
| 5fdde955b3 | |||
| 826d8e0303 | |||
| 3f87b85886 | |||
| af6777397c | |||
| 2f29b73496 | |||
| 7bed39940e | |||
| 5625551898 | |||
| fd479088ec | |||
| c14499b211 | |||
| 57b5993f8d | |||
| 2f8fdae0db | |||
| e57869a38e | |||
| e4d291802b | |||
| 77eb4ec65a | |||
| d27798e797 | |||
| fca6b52fba | |||
| 04ebac2279 | |||
| fb968dccdf | |||
| 1271ada6e1 | |||
| 7a86a8a8e7 | |||
| e9ee638ae9 | |||
| 965e14c3f9 | |||
| a2ca638f47 | |||
| 0197e59eb1 | |||
| 418adb52a4 | |||
| 8894524474 | |||
| 8b7716b380 | |||
| 96a92d230e | |||
| 6ec6318d5f | |||
| bedbfd18d7 | |||
| a5e90a8dea | |||
| b22e98aa01 | |||
| 89ea0a9911 | |||
| 2756732458 | |||
| 3bb28c049f | |||
| ce57b5d156 | |||
| 23f4e85f87 | |||
| b937ec5a87 | |||
| 103a2527ce | |||
| 18e53720d1 | |||
| 35f80fc5c3 | |||
| 993dc85f8f | |||
| 99bd5418bc | |||
| 7c1e148ffa | |||
| ffa52a935a | |||
| 4b4b121366 | |||
| 2964b90925 | |||
| 50f2fc5a16 | |||
| d879c3c54a | |||
| 3012f74206 | |||
| 7fec46aecf | |||
| 91aa5250de | |||
| 75d762c0b9 | |||
| 67454b117b | |||
| 3b96881ba2 | |||
| 87c5cb5706 | |||
| f4911e544b | |||
| 10d053a838 | |||
| c4ab5ba8ff | |||
| 75bc2e9b0b | |||
| c2fda9ce09 | |||
| 8e2ee88b93 | |||
| d27fe9ac8e | |||
| 0d7b0e26ee | |||
| da531b4aef | |||
| 4772e79fee | |||
| 72622c0755 | |||
| 55f2084e86 | |||
| f34463d1cc | |||
| 76b31adc2f | |||
| 641ecb2736 | |||
| 3dbf735aeb | |||
| 33a493fe5d | |||
| 1ec3ab4a1f | |||
| 005d9c9877 | |||
| 102dcfd4bc | |||
| e89ad0a86b | |||
| b7ded4e595 | |||
| b61417101f | |||
| 6e2d898443 | |||
| 1ba5c01281 | |||
| c6f42b1cff | |||
| 2b3882fb1a | |||
| 12476595ad | |||
| 8435bfc4fe | |||
| 9cec524f88 | |||
| fb3786c137 | |||
| 40e654dd22 | |||
| d5087e2d90 | |||
| adf49bbc32 | |||
| 8361cbab71 | |||
| 49abdbd009 | |||
| 4b95d67bea | |||
| a6382422df | |||
| e77c211955 | |||
| 8a3e4b7b14 | |||
| a0901958a8 | |||
| 8e0ccbb45a | |||
| 1608934b89 | |||
| 02763bf7cb | |||
| e5b63ce34d | |||
| 4ed6463d22 | |||
| f348fc4fbc | |||
| 07489e7e9c | |||
| eb6eea0f72 | |||
| b0a30b32bb | |||
| 2caaf90037 | |||
| 929ea4dab0 | |||
| f5ce4791d2 | |||
| 5698e745c9 | |||
| 8c03ce9e0c | |||
| 113e6255ea | |||
| cbac246ffb | |||
| e829515b02 | |||
| 3e511d1457 | |||
| aabed928b1 | |||
| 6816e303ec | |||
| 1bbf7ce1a2 | |||
| 969ff1267e | |||
| 3634046dc7 | |||
| c3ff0ad584 | |||
| ebfe75384c | |||
| bd1dcf3f97 | |||
| d5e147d400 | |||
| 35dbade0a9 | |||
| dc62fabc0b | |||
| 47f2db1e23 | |||
| 967b3f34e9 | |||
| 09ed1c9575 | |||
| f71d6fd74f | |||
| b9c4fa85f1 | |||
| c32fa46161 | |||
| d0bd4ea161 | |||
| 7b6d5c4e97 | |||
| 0459737b00 | |||
| 372ecb8430 | |||
| 9a852e442e | |||
| 92757ef5c3 | |||
| 297692d88b | |||
| 4ead4618e6 | |||
| 96f1c67bfe | |||
| 9db1449b4b | |||
| 9421bfcfee | |||
| a5a1152e95 | |||
| 3a97fce182 | |||
| e8ab5afb41 | |||
| 1d0658dc85 | |||
| 01f37ccb65 | |||
| 4d5a66d6e5 | |||
| c4234041bc | |||
| 359a2f98a8 | |||
| 1225b1623e | |||
| 62aa29999b | |||
| a4f727f68d | |||
| a6c8a11881 | |||
| ce4bcba2e6 | |||
| a88ff1f2c4 | |||
| a986e81353 | |||
| b9899de6df | |||
| bebb4eb281 | |||
| 03ca60cd50 | |||
| 1c46ed54e5 | |||
| 34c6957f95 | |||
| 8a62c228b2 | |||
| 4c92dfe914 | |||
| 5f2b952521 | |||
| 3485d9829c | |||
| 00d6bb5c8a | |||
| 89fc9310db | |||
| 26e52f0da4 | |||
| 99c235760e | |||
| 0dfdcfbdc3 | |||
| 5f48c4e7f3 | |||
| 5e703c70f7 | |||
| e9ae18f809 | |||
| 396c76892c | |||
| c329d7dd4e | |||
| ca3871e4f6 | |||
| d1c6c9a348 | |||
| d5260811dc | |||
| ce155b4d35 | |||
| 65aca43f3f | |||
| 96418f577d | |||
| 2ee9064175 | |||
| 4042681e83 | |||
| cdf13df87d | |||
| 50037ae611 | |||
| e38244e7c0 | |||
| 4f0eae4a6d | |||
| 438e58cc1c | |||
| 4bfd1c4a2a | |||
| abfdb4befc | |||
| 5a1ffabd03 | |||
| 66bf48b6e6 | |||
| bf7acebc30 | |||
| 975c1dc46f | |||
| 8cf2162121 | |||
| 9980528f1e | |||
| 0e34f6cfb8 | |||
| 581b34b586 | |||
| 20581afe80 | |||
| 3861a96d5a | |||
| af44bde349 | |||
| 4736067ed2 | |||
| 2e686bcca7 | |||
| 8eef599aa6 | |||
| afb85320bf | |||
| 4b8dabddae | |||
| ab5c0a43bd | |||
| 65f215eee2 | |||
| e7abed2def | |||
| 66c3a25fe1 | |||
| d9f03cafbe | |||
| 639231388c | |||
| fe44d27cde | |||
| b71248e0f3 | |||
| 4db6e9a69a | |||
| a6d6859aab | |||
| 55f8e04570 | |||
| a1f206804c | |||
| 18c3f768a3 | |||
| 0e277a28d8 | |||
| 081e70c7f3 | |||
| 44007809fd | |||
| 827e1c879e | |||
| 1a7e6629fb | |||
| 4164903d0e | |||
| 5bedcf0a1c | |||
| f1db331e5d | |||
| 3df39a1f78 | |||
| 59459fc6ca | |||
| 83dcd91223 | |||
| ca530216ec | |||
| c2ac40ca00 | |||
| 14e59ca91a | |||
| 643522774e | |||
| cb3ec490a5 | |||
| 4358b2fd71 | |||
| 6c6a0073bf | |||
| f86cf8b9c3 | |||
| 0444eb1f80 | |||
| 45d2ebfc69 | |||
| acbfbc29b3 | |||
| 923f4aeb8f | |||
| 381103678d | |||
| 80247a993d | |||
| 29026f00db | |||
| 25c6350a88 | |||
| c0af811d13 | |||
| 01d21b3ea2 | |||
| df1cd3d5da | |||
| 1bab5a3625 | |||
| 911daba417 | |||
| 9b4e7f4cfc | |||
| 8c4e057c91 | |||
| cd0c502986 | |||
| 7436c51592 | |||
| 95863b81a3 | |||
| 49fbbec138 | |||
| cc2d1399ab | |||
| fcf02a427c | |||
| 73a66e5b1a | |||
| 8b48c39675 | |||
| 055f6d06ae | |||
| 23ab5ba436 | |||
| a655f02fcc | |||
| 92aa47e0bc | |||
| 8cdcda24e1 | |||
| a28dd7dbc3 | |||
| cd7fdcf026 | |||
| 81b081c67d | |||
| fb07f84709 | |||
| 0c0f992a5c | |||
| 64663cf3bd | |||
| e518ba5de5 | |||
| 2dc08498c4 | |||
| f3135499c2 | |||
| 5e093d105a | |||
| b09393e580 | |||
| 43c9310f2e | |||
| b862b62fb9 | |||
| e8d95c4e7e | |||
| 234aafe368 | |||
| 418ceadc2b | |||
| 12840fd46c | |||
| 8dd140d50d | |||
| 81da9b6187 | |||
| fdfcb95711 | |||
| 8d9a65d226 | |||
| 777438f7fc | |||
| d386be9d5d | |||
| 78f81de607 | |||
| b3b7a98b8e | |||
| b1bc31ae0e | |||
| 4c68aff164 | |||
| b3d1e90132 | |||
| 6e7e5822fb | |||
| 237de8786b | |||
| 6f9b937819 | |||
| 96535936a5 | |||
| f2c02fe3bb | |||
| 38ab245727 | |||
| 447de493d3 | |||
| f03a672ac0 | |||
| 6a4d33e3e6 | |||
| aa0d967512 | |||
| fd0a70f87e | |||
| 12ed9958e5 | |||
| 58f1af736e | |||
| 256582455b | |||
| b852e0492e | |||
| 37aa2a4bd2 | |||
| 6736b56964 | |||
| 41b12f96a5 | |||
| 12fa2d9178 | |||
| 7c4b2d67f6 | |||
| 487867d3aa | |||
| 29ba1c1c64 | |||
| 6c93b818af | |||
| 9d2216d84f | |||
| 093b8557ce | |||
| cf9674a713 | |||
| ddeb64e4dd | |||
| 109139b07f | |||
| ec9215fbc1 | |||
| 222f309be5 | |||
| 0ae24ebd1b | |||
| 94c5cf7457 | |||
| 1a70acc7c5 | |||
| 866c4cd4ec | |||
| bae023c075 | |||
| a6d24b73bd | |||
| 791a45c3da | |||
| b3375209c0 | |||
| 3c3bea853e | |||
| ee02cd1a23 | |||
| 4ac0069541 | |||
| 0d9f136298 | |||
| 1b0dbb2b34 | |||
| 01f945c459 | |||
| 58651f9ff6 | |||
| 7aacb7d136 | |||
| ca2416f431 | |||
| 19696ec37f | |||
| ec20424afb | |||
| a9ffc5d23b | |||
| 36b2223600 | |||
| 52d60ea049 | |||
| 88c5dfecb0 | |||
| 1f454dd36e | |||
| f1612bbc2c | |||
| a8bc213609 | |||
| d83bde7b0f | |||
| 293fb90057 | |||
| 05b444ae8a | |||
| b1574fba1a | |||
| 87112f46f7 | |||
| 26c628e81a | |||
| a37a156977 | |||
| bca528b89a | |||
| dc01b2136e | |||
| 5c5ad7b16a | |||
| 3834d248de | |||
| b3aee2deb2 | |||
| 5cb92847c4 | |||
| 666e00b097 | |||
| e22e6188cf | |||
| 6495c220a9 | |||
| e47155fe77 | |||
| 95280cac61 | |||
| 9be459e22f | |||
| 6c2e4c823c | |||
| 2d8ed8d400 | |||
| 24d19e29c0 | |||
| bc15f7157e | |||
| 720fae1bbe | |||
| d82a6d11f9 | |||
| 0e1388a2fd | |||
| 4bd2abebd2 | |||
| 349f970d82 | |||
| 01a20c0a82 | |||
| db94cb6941 | |||
| 2d66e7e804 | |||
| 60734cd2db | |||
| f5451f5bce | |||
| e322d7f1df | |||
| 96f4b45eab | |||
| 11d883f2a6 | |||
| 66bc2db9d1 | |||
| 96e58ed708 | |||
| ad8424e6d1 | |||
| 817876d6fe | |||
| 4d1c0647c8 | |||
| 5bd6229ac1 | |||
| b67d398976 | |||
| c12d5a1142 | |||
| 90a0cb3ad2 | |||
| 2eb20b5743 | |||
| a70e279787 | |||
| a82cf78743 | |||
| 80854a2c39 | |||
| bd73c92bb5 | |||
| de3b9c78f3 | |||
| ecfcfa977d | |||
| 4e32c8f56e | |||
| 5461e0a056 | |||
| b2a87732c9 | |||
| ea55c60fe3 | |||
| a6f05a05e0 | |||
| 8819fdde7a | |||
| 1808ad3c6d | |||
| 440479be65 | |||
| d35f6e80df | |||
| 0bd8f12c64 | |||
| 9e269500d2 | |||
| 658cc9cd23 | |||
| aa4cf039bf | |||
| 4b68e3f7fe | |||
| 6e437f5103 | |||
| ccd6f5b640 | |||
| c7db73ec6b | |||
| 4f05b2b2fc | |||
| b4810cc153 | |||
| 2f1189d766 | |||
| b1eccbe7bf | |||
| c2bd604574 | |||
| b15d1043d1 | |||
| e89d1692e5 | |||
| b0399a9f9c | |||
| 69ffe8defb | |||
| 0e11e9f7f4 | |||
| 20d0136449 | |||
| 3e3d180edb | |||
| 5b4433d50b | |||
| 0db7be7cb8 | |||
| 37434dca9c | |||
| 3ec8e09b8a | |||
| db843fd786 | |||
| 97f57a698b | |||
| 62a6143de1 | |||
| 5c9a4d2328 | |||
| 66780ca8aa | |||
| 4a90819ba6 | |||
| 08e8dbec66 | |||
| 77a1488dd2 | |||
| e5d10e4bf7 | |||
| 5528c400d0 | |||
| 43154a6a64 | |||
| 34160210b4 | |||
| b31f827d9b | |||
| 3dbf9f25e1 | |||
| a158a93198 | |||
| 2d41f0a3c1 | |||
| 9021652bd3 | |||
| 48899c0ba7 | |||
| e24a6a189a | |||
| b20e550e89 | |||
| ad230ae351 | |||
| 0ee24c204f | |||
| 43adf5863d | |||
| c5193f1e74 | |||
| 1893fea2ea | |||
| acf2d25cd5 | |||
| 3cc6ff972b | |||
| c82b51d8da | |||
| 3b476dbd6c | |||
| a6e2a3fc30 | |||
| 767fceb6f0 | |||
| 54e9226bdd | |||
| 0c235e8edd | |||
| 9bb706c627 | |||
| 6d4e502109 | |||
| 1eeab81136 | |||
| 5f7f31e7c9 | |||
| b7ad24cea9 | |||
| 6e03b80cd0 | |||
| d4814abf5f | |||
| cdee56670e | |||
| 63a732f71e | |||
| 8c580647fd | |||
| fb6b984be4 | |||
| 9eaf9191d8 | |||
| d4ddfc18f5 | |||
| 4206fd3bce | |||
| e8633acdca | |||
| 47c1f224dc | |||
| a49c5e804c | |||
| 399ba068e1 | |||
| f3febd91ac | |||
| 4873ff5f39 | |||
| 52646de997 | |||
| f311b5f77b | |||
| 4219858cc2 | |||
| 50e9149f90 | |||
| bb58b03aef | |||
| cd2fabe2f1 | |||
| e63689a66f | |||
| 6bc3146a79 | |||
| 327c365a41 | |||
| 75c78de2b3 | |||
| 7f228cc6f4 | |||
| 48dee43f04 | |||
| c0f7585f95 | |||
| 363c64c04f | |||
| 207976b5fe | |||
| 50728fecb3 | |||
| 859ea21294 | |||
| f3a623dbbc | |||
| dd8efc774c | |||
| a5d4a39e6d | |||
| f7017e22a0 | |||
| 504a77f44d | |||
| b1135d3e02 | |||
| 35ae37acb5 | |||
| b83e6d9dfc | |||
| 6aba69af41 | |||
| 967740726a | |||
| aeed4279d7 | |||
| 3af7a78855 | |||
| fbb179e7a6 | |||
| 90107197c7 |
@@ -1,7 +1,13 @@
|
||||
.*.orig$
|
||||
.*\.o$
|
||||
.*~$
|
||||
build-dir
|
||||
.*\.sconsign
|
||||
doc/html.*
|
||||
doc/latex.*
|
||||
\.rej$
|
||||
\.orig$
|
||||
\.o$
|
||||
~$
|
||||
^build-dir
|
||||
^build
|
||||
^doc/html
|
||||
^doc/latex
|
||||
^\.lock-wscript
|
||||
^\.waf
|
||||
^doc/introspected-doxygen\.h$
|
||||
.*\.py[co]$
|
||||
\.pcap$
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
56928998e05c9c11f5f3aefe79be8d2843e0db88 release ns-3.0.1
|
||||
7ac5a4b0969b255c4824c926c2b37ef450136ce9 release ns-3.0.2
|
||||
0dc81e76166c56aaae64da48b673b62155943aad packet-history-working
|
||||
38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3
|
||||
5701e60bf01a8ac1308945e69001e0cc07948faf release ns-3.0.4
|
||||
08046b6aef37932507696a2f2f427b42d693781e release ns-3.0.5
|
||||
267e2ebc28e4e4ae2f579e1cfc29902acade0c34 buffer-working-before-breaking
|
||||
606df29888e7573b825fc891a002f0757166b616 release ns-3.0.6
|
||||
36472385a1cc7c44d34fb7a5951b930010f4e8d2 release ns-3.0.7
|
||||
560a5091e0e6ded47d269e2f2dee780f13950a63 release ns-3.0.8
|
||||
4db981a0d9eb135e3e1c07765cff8d66f7a55cca release ns-3.0.9
|
||||
b5bf2588cde2f1273b1095cc5c83a0c272e55370 release ns-3.0.10
|
||||
ee5e1da76ecc52337f097cd90ebb50a3d49ec541 release-3.0.11
|
||||
b17f2928291eec5bf5b1c59a4a5fd583f704ac40 release ns-3.0.12
|
||||
@@ -1,5 +1,10 @@
|
||||
Raj Bhattarcharjea (raj.b@gatech.edu)
|
||||
Gustavo Carneiro (gjc@inescporto.pt, gjcarneiro@gmail.com)
|
||||
Craig Dowell (craigdo@ee.washington.edu)
|
||||
Tom Henderson (tomhend@u.washington.edu)
|
||||
Joe Kopena (tjkopena@cs.drexel.edu)
|
||||
Mathieu Lacage (mathieu.lacage@sophia.inria.fr)
|
||||
Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca)
|
||||
Federico Maguolo (maguolof@dei.unipd.it)
|
||||
George F. Riley (riley@ece.gatech.edu)
|
||||
Guillaume Vu-Brugier (gvubrugier@gmail.com)
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
If you want to build ns3, you need to install scons (see
|
||||
http://www.scons.org). scons takes care of building
|
||||
the whole source tree using your system compiler. scons
|
||||
0.91.1 and 0.91.96 have been tested and are known to
|
||||
work on linux FC5, Mac os X and MinGW.
|
||||
|
||||
To start a build, you can just type 'scons' which
|
||||
will generate a debug shared build by default, located
|
||||
in the directory 'build-dir/dbg-shared/bin' and
|
||||
'build-dir/dbg-shared/lib'.
|
||||
|
||||
All builds are built with debugging symbols. Debugging
|
||||
builds enable asserts while optimized builds disable them.
|
||||
On platforms which support it, rpath is used which means that
|
||||
the executable binaries generated link explicitely against
|
||||
the right libraries. This saves you the pain of having to
|
||||
setup environment variables to point to the right libraries.
|
||||
|
||||
1) Options
|
||||
----------
|
||||
|
||||
- verbose: if you have installed scons 0.91.96 or higher,
|
||||
the default build output is terse. To get a more verbose
|
||||
output, you need to set the 'verbose' variable to 'y'.
|
||||
Example: scons verbose=y
|
||||
- cflags: flags for the C compiler.
|
||||
Example: scons cflags="-O3 -ffast-math"
|
||||
- cxxflags: flags for the C++ compiler.
|
||||
Example: scons cxxflags="-O3 -ffast-math"
|
||||
- ldflags: flags for the linker:
|
||||
Example: scons ldflags="-L/foo -L/bar"
|
||||
- high-precision-as-double: set to 'y' to make sure that the
|
||||
high-precision arithmetics performed by the Time class on
|
||||
behalf of the user will use doubles. By default, the code
|
||||
uses 128 integers.
|
||||
Example: scons high-precision-as-double=y
|
||||
- inheritenv: set to 'y' if you want to make your compiler
|
||||
execute within the same environment (env vars) as your own
|
||||
shell. This is typically used to make colorgcc work.
|
||||
Example: scons inheritenv=y
|
||||
|
||||
2) Targets
|
||||
----------
|
||||
|
||||
- doc: build the doxygen documentation.
|
||||
Example: scons doc
|
||||
|
||||
- dbg-shared: a debug build using shared libraries.
|
||||
The files are built in 'build-dir/dbg-shared/'.
|
||||
Example: scons dbg-shared
|
||||
|
||||
- dbg-static: a debug build using static libraries
|
||||
The files are built in 'build-dir/dbg-static/'.
|
||||
Example: scons dbg-static
|
||||
|
||||
- opt-shared: an optimized build using shared libraries.
|
||||
The files are built in 'build-dir/opt-shared/'.
|
||||
Example: scons opt-shared
|
||||
|
||||
- opt-static: an optimized build using static libraries.
|
||||
The files are built in 'build-dir/opt-static/'.
|
||||
Example: scons opt-static
|
||||
|
||||
- dbg: an alias for dbg-shared
|
||||
Example: scons dbg
|
||||
|
||||
- opt: an alias for opt-shared
|
||||
Example: scons opt
|
||||
|
||||
- all: alias for dbg-shared, dbg-static, opt-shared
|
||||
and opt-static
|
||||
Example: scons all
|
||||
|
||||
- gcov: code coverage analysis. Build a debugging version of
|
||||
the code for code coverage analysis in 'build-dir/gcov'. Once
|
||||
the code has been built, you can run various applications to
|
||||
exercise the code paths. To generate an html report from
|
||||
the gcov data, use the lcov-report target
|
||||
|
||||
- lcov-report: generate html report of gcov data. The output
|
||||
is stored in 'build-dir/lcov-report/'.
|
||||
|
||||
- dist: generate a release tarball and zipfile from the
|
||||
source tree. The tarball and zipfile name are generated
|
||||
according to the version number stored in the SConstruct
|
||||
file.
|
||||
Example in SConstruct:
|
||||
ns3 = Ns3 ()
|
||||
ns3.name = 'foo'
|
||||
ns3.version = '0.0.10'
|
||||
Example command: scons dist
|
||||
Example output files:
|
||||
foo-0.0.10.tar.gz
|
||||
foo-0.0.10.zip
|
||||
|
||||
- distcheck: generate a release tarball and zipfile and
|
||||
attempt to run the 'all' target for the release tarball.
|
||||
Example: scons distcheck
|
||||
|
||||
3) How the build system works
|
||||
-----------------------------
|
||||
|
||||
The current build system defines what are called "ns3 modules": each module
|
||||
is a set of source files, normal header files and installable header
|
||||
files. Each module also depends on a set of other modules. We build
|
||||
modules automatically in the correct order. That is, we always start
|
||||
from the module which does not depend on any other module (core) and
|
||||
proceed with the other modules and make sure that when a module is
|
||||
built, all the modules it depends upon have already been built.
|
||||
|
||||
To build a module, we:
|
||||
1) generate the .o files
|
||||
2) link the .o files together
|
||||
3) install the installable headers in the common directory
|
||||
top_build_dir/include/ns3.
|
||||
|
||||
This means that if you want to use a header from your own module, you
|
||||
should just include it: #include "foo.h" but if you want to include a
|
||||
header from another module, you need to include it with #include
|
||||
"ns3/bar.h". This allows you to make sure that our "public" ns3 headers
|
||||
do not conflict with existing system-level headers. For instance,
|
||||
if you were to define a header called queue.h, you would include
|
||||
ns3/queue.h rather than queue.h, when including from a separate module,
|
||||
since many systems provide a queue.h system include file.
|
||||
|
||||
4) How to add files to a module ?
|
||||
---------------------------------
|
||||
|
||||
In the main SConstruct file, you can add source code
|
||||
to the add_sources method. For example, to add a foo.cc
|
||||
file to the core module, we coud do this:
|
||||
core.add_sources ('foo.cc')
|
||||
Of course, if this file implements public API, its
|
||||
header should be installable:
|
||||
core.add_inst_headers ('foo.h')
|
||||
|
||||
5) How to create a new module ?
|
||||
-------------------------------
|
||||
|
||||
# create a new module. First arg is the name of
|
||||
# the new module. Second arg is the directory in
|
||||
# which all source files for this module reside.
|
||||
my_module = build.Ns3Module ('my', 'src/my_dir')
|
||||
# add it to build system
|
||||
ns3.add (my_module)
|
||||
# specify module dependencies. Here, depends
|
||||
# on the 'ipv4' and 'core' modules
|
||||
my_module.add_deps (['core', 'ipv4'])
|
||||
# add source code to build located in
|
||||
# src/my_dir
|
||||
my_module.add_sources ([
|
||||
'my_a.cc',
|
||||
'my_b.cc',
|
||||
'my_c.cc'
|
||||
])
|
||||
my_module.add_sources ([
|
||||
'my_d.cc'
|
||||
])
|
||||
# add headers which are not public
|
||||
my_module.add_headers ([
|
||||
'my_a.h',
|
||||
'my_c.h'
|
||||
])
|
||||
# add headers which are public
|
||||
my_module.add_inst_headers ([
|
||||
'my_b.h'
|
||||
])
|
||||
my_module.add_inst_headers ([
|
||||
'my_d.h'
|
||||
])
|
||||
# if you need to link against an external library,
|
||||
# you must add 'external' dependencies. Here, the
|
||||
# pthread library
|
||||
my_module.add_external_dep ('pthread')
|
||||
# by default, a module is conceptually a library. If you
|
||||
# want to generate an executable from a module you need to:
|
||||
my_module.set_executable ()
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
ns-3.0.1 snapshot release, March 2007
|
||||
|
||||
1. Tested platforms:
|
||||
|
||||
- Windows XP 32-bit Cygwin
|
||||
|
||||
- Linux Fedora Core 5 x86
|
||||
|
||||
- OS X 10.4.7 or later with XCode 2.4 or later
|
||||
|
||||
2. Prerequisites:
|
||||
|
||||
- The SCons build system (http://www.scons.org) version 0.96.1 or later
|
||||
|
||||
- gcc (version 3.4 or later)
|
||||
|
||||
3. Installing into your current directory:
|
||||
|
||||
tar xvfz ns-3.0.1.tar.gz
|
||||
cd ns-3.0.1
|
||||
scons
|
||||
cd build-dir/dbg-shared/bin/
|
||||
./simple-p2p
|
||||
|
||||
The above steps will run a simple program whose source is found in
|
||||
ns-3.0.1/examples/simple-p2p.cc
|
||||
Some minimal trace output is found in simple-p2p.tr.
|
||||
|
||||
Note: OS X users may need to set the following env. variable from
|
||||
the bin/ directory above:
|
||||
setenv DYLD_LIBRARY_PATH `pwd`/../lib
|
||||
|
||||
4. For more information, read
|
||||
ns-3.0.1-documentation.pdf
|
||||
|
||||
@@ -1,32 +1,148 @@
|
||||
ns-3 uses the Mercurial software revision control system
|
||||
|
||||
Mercurial cheat sheet
|
||||
The Network Simulator, Version 3
|
||||
--------------------------------
|
||||
|
||||
clone this repository:
|
||||
----------------------
|
||||
hg clone http://code.nsnam.org/ns-3-dev
|
||||
Table of Contents:
|
||||
------------------
|
||||
|
||||
pull development tree changes to your local repository:
|
||||
------------------------------------------------------
|
||||
hg pull http://code.nsnam.org/ns-3-dev
|
||||
hg update (apply the changes) OR
|
||||
hg merge (if you've made local changes)
|
||||
1) An Open Source project
|
||||
2) An overview of the ns-3 project
|
||||
3) Building ns-3
|
||||
4) Running ns-3
|
||||
5) Getting access to the ns-3 documentation
|
||||
6) Working with the development version of ns-3
|
||||
|
||||
commit locally:
|
||||
--------------
|
||||
hg status
|
||||
hg add <new files, if any>
|
||||
hg ci -m "message"
|
||||
|
||||
push upwards (developers access only):
|
||||
--------------------------------------
|
||||
hg push ssh://code@code.nsnam.org//home/code/repos/ns-3-dev
|
||||
1) An Open Source project
|
||||
-------------------------
|
||||
|
||||
view the change log:
|
||||
--------------
|
||||
hg log <file>
|
||||
ns-3 is an Open Source project. We intend to make this
|
||||
project a successful collaborative project: we hope that
|
||||
the missing pieces of the models we have not yet implemented
|
||||
will be contributed by the community in an open collaboration
|
||||
process.
|
||||
|
||||
doing a scons make clean:
|
||||
------------------------
|
||||
scons -c
|
||||
Contributing to the ns-3 project is still a very informal
|
||||
process because that process depends heavily on the background
|
||||
of the people involved, the amount of time they can invest
|
||||
and the type of model they want to work on.
|
||||
|
||||
Despite this lack of a formal process, there are a number of
|
||||
steps which naturally stem from the open-source roots of the
|
||||
project. These steps are described in doc/contributing.txt
|
||||
|
||||
2) An overview of the ns-3 project
|
||||
----------------------------------
|
||||
|
||||
This package contains the latest version of ns-3 which aims
|
||||
at being a replacement for ns-2. Currently, ns-3 provides a
|
||||
number of simple network simulation models:
|
||||
- an ipv4 and tcp and udp stack
|
||||
- arp support at the bottom of the stack
|
||||
- static global and OLSR unicast routing
|
||||
- point-to-point, CSMA, and Wifi links
|
||||
- mobility
|
||||
- OnOff traffic generator
|
||||
|
||||
Our focus to date has been on getting an overall software
|
||||
framework in place. The framework is there to make adding
|
||||
new models as simple as possible:
|
||||
|
||||
- an extensive callback-based tracing system
|
||||
|
||||
- simple file trace serialization support is included
|
||||
to both text and pcap files.
|
||||
|
||||
- an attribute system for configuring parameters in the
|
||||
models
|
||||
|
||||
- adding new MAC-level models simply requires subclassing
|
||||
the pair of classes NetDevice and Channel.
|
||||
|
||||
- adding new traffic generation algorithms is also very
|
||||
simple through the Application and the Socket classes.
|
||||
|
||||
3) Building ns-3
|
||||
----------------
|
||||
|
||||
The code for the framework and the default models provided
|
||||
by ns-3 is built as a set of libraries. User simulations
|
||||
are expected to be written as simple programs that make
|
||||
use of these ns-3 libraries.
|
||||
|
||||
To build the set of default libraries and the example
|
||||
programs included in this package, you need to use the
|
||||
tool 'waf'. Detailed information on how to install
|
||||
and use waf is included in the file doc/build.txt
|
||||
|
||||
However, the real quick and dirty way to get started is to
|
||||
type the command "./waf" the the directory which contains
|
||||
this README file. The files built will be copied in the
|
||||
build/debug or build/optimized.
|
||||
|
||||
The current codebase is expected to build and run on the
|
||||
following set of platforms:
|
||||
- linux x86 gcc 4.2, 4.1, and, 3.4.6.
|
||||
- linux x86_64 gcc 4.1.3, 4.2.1, 3.4.6
|
||||
- MacOS X ppc and x86
|
||||
- cygwin gcc 3.4.4 (debug only)
|
||||
|
||||
The current codebase is expected to fail to build on
|
||||
the following platforms:
|
||||
- gcc 3.3 and earlier
|
||||
- optimized builds on gcc 3.4.4 and 3.4.5
|
||||
- optimized builds on linux x86 gcc 4.0
|
||||
|
||||
Other platforms may or may not work: we welcome
|
||||
patches to improve the portability of the code to these
|
||||
other platforms.
|
||||
|
||||
4) Running ns-3
|
||||
---------------
|
||||
|
||||
On recent Linux systems, once you have built ns-3, it
|
||||
should be easy to run the sample programs with the
|
||||
following command:
|
||||
|
||||
./waf --run simple-global-routing
|
||||
|
||||
That program should generate a simple-global-routing.tr text
|
||||
trace file and a set of simple-global-routing-xx-xx.pcap binary
|
||||
pcap trace files, which can be read by tcpdump -tt -r filename.pcap
|
||||
|
||||
5) Getting access to the ns-3 documentation
|
||||
-------------------------------------------
|
||||
|
||||
Once you have verified that your build of ns-3 works by running
|
||||
the simple-point-to-point example as outlined in 4) above, it is
|
||||
quite likely that you will want to get started on reading
|
||||
some ns-3 documentation.
|
||||
|
||||
All of that documentation should always be available from
|
||||
the ns-3 website: http:://www.nsnam.org/ but we
|
||||
include some of it in this release for ease of use.
|
||||
|
||||
This documentation includes:
|
||||
|
||||
- a tutorial
|
||||
|
||||
- a wiki for user-contributed tips: http://www.nsnam.org/wiki/
|
||||
|
||||
- an API documentation generated using doxygen: this is
|
||||
a reference manual, most likely not very well suited
|
||||
as introductory text:
|
||||
http://www.nsnam.org/doxygen/index.html
|
||||
|
||||
6) Working with the development version of ns-3
|
||||
-----------------------------------------------
|
||||
|
||||
If you want to download and use the development version
|
||||
of ns-3, you need to use the tool 'mercurial'. A quick and
|
||||
dirty cheat sheet is included in doc/mercurial.txt but
|
||||
reading through the mercurial tutorials included on the
|
||||
mercurial website is usually a good idea if you are not
|
||||
familiar with it.
|
||||
|
||||
If you have successfully installed mercurial, you can get
|
||||
a copy of the development version with the following command:
|
||||
"hg clone http://code.nsnam.org/ns-3-dev"
|
||||
|
||||
+118
-2
@@ -1,9 +1,125 @@
|
||||
|
||||
ns-3 RELEASE NOTES
|
||||
|
||||
This file contains ns-3 release notes (most recent releases first).
|
||||
This file contains ns-3 release notes (most recent releases first).
|
||||
|
||||
Release 0.1 (2007/03/31)
|
||||
Release 3.0.13 (2008/06/02)
|
||||
========================
|
||||
- point to point links generate ppp pcap traces
|
||||
- point to point links support asymmetrical data rates.
|
||||
- generate doxygen documentation for all attributes and trace sources
|
||||
- add ConfigStore and GtkConfigStore to contrib module
|
||||
- socket API now support tx and rx buffers: implemented for UDP and TCP
|
||||
- ARP cache now supports per-entry pending queues
|
||||
- lots of bugfixes and implementation and API cleanups
|
||||
|
||||
Release 3.0.12 (2008/04/07)
|
||||
========================
|
||||
- Add Attribute support to the TypeId metadata system and add
|
||||
attribute support to all in-tree models
|
||||
- Add a mid-level helper API to build simulation topologies
|
||||
and perform simple ascii and pcap link-level tracing.
|
||||
- Large amount of structural changes to accomodate the needs
|
||||
of the upcoming python bindings
|
||||
- new rate control algorithm (RRAA) and a jakes propagation model
|
||||
in the 802.11 model (Federico Maguolo).
|
||||
- regression test framework added
|
||||
- TCP delayed acknowledgements and multitasking server
|
||||
|
||||
Release 3.0.11 (2008/02/15)
|
||||
========================
|
||||
- Initial port of GTNetS TCP implementation (initial version
|
||||
that does not support multitasking or delayed acknowledgments yet,
|
||||
but supports a reliable stream service)
|
||||
- Changes to the ns-3 object model to create a TypeId-based
|
||||
metadata system
|
||||
- lots of bug fixes throughout the system
|
||||
- tutorial updates
|
||||
|
||||
Release 3.0.10 (2008/01/15)
|
||||
========================
|
||||
- Add tutorial document content;
|
||||
- Valgrind option for "waf" tool;
|
||||
- Doxygen organization changes.
|
||||
|
||||
Release 3.0.9 (2007/12/15)
|
||||
========================
|
||||
- A 802.11 model ported from Yans. This model supports:
|
||||
* a rather extensive PHY model
|
||||
* log-distance and friis propagation model
|
||||
* a simple set of rate control algorithms (ARF, Ideal,
|
||||
AARF, constant-rate)
|
||||
* adhoc and infrastructure mode (beacon+assoc)
|
||||
- Use smart pointer for Packet in the APIs
|
||||
- A new contrib directory with helper classes:
|
||||
EventGarbageCollector, Gnuplot
|
||||
- Tracing support for Applications
|
||||
- many bugs fixed
|
||||
|
||||
Release 3.0.8 (2007/11/15)
|
||||
========================
|
||||
- A simple error model
|
||||
- Source files for ns-3 tutorial
|
||||
|
||||
Release 3.0.7 (2007/10/15)
|
||||
========================
|
||||
- OLSR routing protocol
|
||||
- A timer class
|
||||
- Additional mobility models (random waypoint, random 2D walk)
|
||||
- A mobility visualization tool
|
||||
|
||||
Release 3.0.6 (2007/09/15)
|
||||
========================
|
||||
- Static multicast IPv4 routing
|
||||
- Logging overhaul (NS_LOG macros)
|
||||
- Refactoring of tracing subsystem
|
||||
- Tutorial document started
|
||||
|
||||
Release 3.0.5 (2007/08/15)
|
||||
========================
|
||||
|
||||
- Refactoring to support win32-based unix environments (Cygwin, mingw)
|
||||
- "Packet socket" for allowing applications to access NetDevices directly
|
||||
- Generalized, polymorphic Address class
|
||||
- Add CSMA NetDevice model (from Emmanuelle Laprise)
|
||||
- Modularize IPv4 routing support (from Gustavo Carneiro)
|
||||
- Add mobility framework and basic mobility models
|
||||
- Global unicast centralized routing
|
||||
|
||||
Release 3.0.4 (2007/07/15)
|
||||
========================
|
||||
|
||||
- Enable waf as the default build system.
|
||||
- Per-packet metadata: a system to track which headers and trailers
|
||||
are added to a packet
|
||||
- Simplifications to point-to-point devices and channel
|
||||
|
||||
Release 3.0.3 (2007/06/15)
|
||||
========================
|
||||
|
||||
- Enable Waf for release tarballs: users can now build ns-3
|
||||
with the "waf" tool. See doc/build-waf.txt.
|
||||
- Add support for variable time precision: it is now possible
|
||||
to run a simulation with an accuracy which is higher or lower
|
||||
than a nanosecond: seconds, milliseconds, microseconds,
|
||||
femtoseconds and picoseconds are supported.
|
||||
- Optimize and rework the COM framework, solidify the component
|
||||
manager
|
||||
- Many small API cleanups
|
||||
|
||||
Release 3.0.2 (2007/05/18)
|
||||
========================
|
||||
|
||||
- Implement a new memory management infrastructure based
|
||||
on reference counting and smart pointers (the latter being
|
||||
optional)
|
||||
|
||||
- Implement a COM-like framework with support for QueryInterface
|
||||
to provide object extensibility
|
||||
|
||||
- Add support for a BSD-style socket API for user applications
|
||||
|
||||
Release 3.0.1 (2007/03/31)
|
||||
========================
|
||||
|
||||
- First public release; not yet pre-alpha.
|
||||
|
||||
-386
@@ -1,386 +0,0 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
import os.path
|
||||
import build
|
||||
|
||||
ns3 = build.Ns3()
|
||||
ns3.build_dir = 'build-dir'
|
||||
ns3.version = '0.0.1'
|
||||
ns3.name = 'ns3'
|
||||
ns3.doxygen_config = os.path.join('doc', 'doxygen.conf')
|
||||
ns3.add_extra_dist(os.path.join('doc', 'main.txt'))
|
||||
|
||||
|
||||
#
|
||||
# The Core module
|
||||
#
|
||||
core = build.Ns3Module('core', 'src/core')
|
||||
ns3.add(core)
|
||||
core.add_sources([
|
||||
'reference-list-test.cc',
|
||||
'callback-test.cc',
|
||||
'debug.cc',
|
||||
'assert.cc',
|
||||
'ptr.cc',
|
||||
'object.cc',
|
||||
'test.cc',
|
||||
'random-variable.cc',
|
||||
'rng-stream.cc',
|
||||
'object-container.cc',
|
||||
])
|
||||
env = Environment()
|
||||
if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin':
|
||||
core.add_external_dep('pthread')
|
||||
core.add_sources([
|
||||
'unix-system-wall-clock-ms.cc',
|
||||
'unix-system-file.cc'
|
||||
])
|
||||
elif env['PLATFORM'] == 'win32':
|
||||
core.add_sources([
|
||||
'win32-system-wall-clock-ms.cc',
|
||||
'win32-system-file.cc'
|
||||
])
|
||||
core.add_inst_headers([
|
||||
'system-file.h',
|
||||
'system-wall-clock-ms.h',
|
||||
'reference-list.h',
|
||||
'callback.h',
|
||||
'ptr.h',
|
||||
'object.h',
|
||||
'debug.h',
|
||||
'assert.h',
|
||||
'fatal-error.h',
|
||||
'test.h',
|
||||
'random-variable.h',
|
||||
'rng-stream.h',
|
||||
'object-container.h'
|
||||
])
|
||||
|
||||
def config_core (env, config):
|
||||
retval = []
|
||||
# XXX This check is primitive but it should be
|
||||
# good enough for now.
|
||||
if config.CheckCHeader ('stdlib.h') == 1:
|
||||
retval.append ('#define HAVE_STDLIB_H 1')
|
||||
retval.append ('#define HAVE_GETENV 1')
|
||||
else:
|
||||
retval.append ('#undef HAVE_STDLIB_H')
|
||||
retval.append ('#undef HAVE_GETENV')
|
||||
return retval
|
||||
core.add_config (config_core)
|
||||
|
||||
#
|
||||
# The Simu module
|
||||
#
|
||||
simu = build.Ns3Module('simulator', 'src/simulator')
|
||||
ns3.add(simu)
|
||||
simu.add_dep('core')
|
||||
simu.add_external_dep('m')
|
||||
simu.add_sources([
|
||||
'high-precision.cc',
|
||||
'time.cc',
|
||||
'event-id.cc',
|
||||
'scheduler.cc',
|
||||
'scheduler-factory.cc',
|
||||
'scheduler-list.cc',
|
||||
'scheduler-heap.cc',
|
||||
'scheduler-map.cc',
|
||||
'event-impl.cc',
|
||||
'simulator.cc',
|
||||
])
|
||||
simu.add_headers([
|
||||
'scheduler-heap.h',
|
||||
'scheduler-map.h',
|
||||
'scheduler-list.h'
|
||||
])
|
||||
simu.add_inst_headers([
|
||||
'high-precision.h',
|
||||
'nstime.h',
|
||||
'event-id.h',
|
||||
'event-impl.h',
|
||||
'simulator.h',
|
||||
'scheduler.h',
|
||||
'scheduler-factory.h',
|
||||
])
|
||||
high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n')
|
||||
if high_precision_as_double == 'y':
|
||||
simu.add_inst_header ('high-precision-double.h')
|
||||
simu.add_source ('high-precision-double.cc')
|
||||
else:
|
||||
simu.add_inst_headers ([
|
||||
'high-precision-128.h',
|
||||
'cairo-wideint-private.h'
|
||||
])
|
||||
simu.add_sources ([
|
||||
'high-precision-128.cc',
|
||||
'cairo-wideint.c',
|
||||
])
|
||||
|
||||
def config_simulator (env, config):
|
||||
retval = []
|
||||
high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n')
|
||||
if high_precision_as_double == 'y':
|
||||
retval.append ('#define USE_HIGH_PRECISION_DOUBLE 1')
|
||||
else:
|
||||
retval.append ('#undef USE_HIGH_PRECISION_DOUBLE')
|
||||
if config.CheckCHeader ('stdint.h') == 1:
|
||||
retval.append ('#define HAVE_STDINT_H 1')
|
||||
elif config.CheckCHeader ('inttypes.h') == 1:
|
||||
retval.append ('#define HAVE_INTTYPES_H 1')
|
||||
elif config.CheckCHeader ('sys/inttypes.h') == 1:
|
||||
retval.append ('#define HAVE_SYS_INT_TYPES_H 1')
|
||||
return retval
|
||||
simu.add_config (config_simulator)
|
||||
|
||||
|
||||
#
|
||||
# The Common module
|
||||
#
|
||||
common = build.Ns3Module('common', 'src/common')
|
||||
common.add_deps(['core', 'simulator'])
|
||||
ns3.add(common)
|
||||
common.add_sources([
|
||||
'buffer.cc',
|
||||
'header.cc',
|
||||
'trailer.cc',
|
||||
'packet.cc',
|
||||
'tags.cc',
|
||||
'pcap-writer.cc',
|
||||
'variable-tracer-test.cc',
|
||||
'trace-context.cc',
|
||||
'trace-resolver.cc',
|
||||
'callback-trace-source.cc',
|
||||
'empty-trace-resolver.cc',
|
||||
'composite-trace-resolver.cc',
|
||||
'trace-root.cc',
|
||||
'data-rate.cc',
|
||||
])
|
||||
common.add_headers ([
|
||||
])
|
||||
common.add_inst_headers([
|
||||
'buffer.h',
|
||||
'header.h',
|
||||
'trailer.h',
|
||||
'tags.h',
|
||||
'packet.h',
|
||||
'uv-trace-source.h',
|
||||
'sv-trace-source.h',
|
||||
'fv-trace-source.h',
|
||||
'pcap-writer.h',
|
||||
'callback-trace-source.h',
|
||||
'trace-context.h',
|
||||
'trace-resolver.h',
|
||||
'empty-trace-resolver.h',
|
||||
'composite-trace-resolver.h',
|
||||
'array-trace-resolver.h',
|
||||
'trace-root.h',
|
||||
'terminal-trace-resolver.h',
|
||||
'smartvector.h',
|
||||
'smartset.h',
|
||||
'data-rate.h',
|
||||
])
|
||||
|
||||
node = build.Ns3Module ('node', 'src/node')
|
||||
ns3.add (node)
|
||||
node.add_deps (['core', 'common', 'simulator'])
|
||||
node.add_sources ([
|
||||
'node.cc',
|
||||
'l3-demux.cc',
|
||||
'l3-protocol.cc',
|
||||
'ipv4-l4-demux.cc',
|
||||
'ipv4-l4-protocol.cc',
|
||||
'ipv4-address.cc',
|
||||
'internet-node.cc',
|
||||
'net-device.cc',
|
||||
'mac-address.cc',
|
||||
'ipv4-header.cc',
|
||||
'udp-header.cc',
|
||||
'ipv4-checksum.cc',
|
||||
'ipv4-route.cc',
|
||||
'ipv4-interface.cc',
|
||||
'ipv4.cc',
|
||||
'ipv4-end-point.cc',
|
||||
'udp-end-point.cc',
|
||||
'datagram-socket.cc',
|
||||
'udp.cc',
|
||||
'capability.cc',
|
||||
'arp-header.cc',
|
||||
'application.cc',
|
||||
'application-list.cc',
|
||||
'onoff-application.cc',
|
||||
'arp-cache.cc',
|
||||
'arp-ipv4-interface.cc',
|
||||
'arp.cc',
|
||||
'ipv4-loopback-interface.cc',
|
||||
'llc-snap-header.cc',
|
||||
'header-utils.cc',
|
||||
'net-device-list.cc',
|
||||
'queue.cc',
|
||||
'drop-tail.cc',
|
||||
'channel.cc',
|
||||
'node-list.cc',
|
||||
'ascii-trace.cc',
|
||||
])
|
||||
node.add_headers ([
|
||||
'ipv4-header.h',
|
||||
'udp-header.h',
|
||||
'ipv4-checksum.h',
|
||||
'udp.h',
|
||||
'ipv4-l4-protocol.h',
|
||||
'application.h',
|
||||
'application-list.h',
|
||||
'onoff-application.h',
|
||||
'arp-header.h',
|
||||
'arp-cache-cache.h',
|
||||
'arp.h',
|
||||
'ipv4-loopback-interface.h',
|
||||
'l3-demux.h',
|
||||
'ipv4-l4-demux.h',
|
||||
'net-device-list.h',
|
||||
'header-utils.h',
|
||||
'protocol.h',
|
||||
'queue.h',
|
||||
])
|
||||
node.add_inst_headers ([
|
||||
'node.h',
|
||||
'internet-node.h',
|
||||
'datagram-socket.h',
|
||||
'ipv4-address.h',
|
||||
'net-device.h',
|
||||
'net-device-list.h',
|
||||
'arp-ipv4-interface.h',
|
||||
'ipv4-interface.h',
|
||||
'mac-address.h',
|
||||
'ipv4.h',
|
||||
'l3-protocol.h',
|
||||
'ipv4-route.h',
|
||||
'queue.h',
|
||||
'drop-tail.h',
|
||||
'llc-snap-header.h',
|
||||
'arp-header.h',
|
||||
'ipv4-header.h',
|
||||
'udp-header.h',
|
||||
'channel.h',
|
||||
'node-list.h',
|
||||
'capability.h',
|
||||
'application.h',
|
||||
'application-list.h',
|
||||
'onoff-application.h',
|
||||
'ascii-trace.h',
|
||||
])
|
||||
|
||||
p2p = build.Ns3Module ('p2p', 'src/devices/p2p')
|
||||
ns3.add (p2p)
|
||||
p2p.add_deps (['node'])
|
||||
p2p.add_sources ([
|
||||
'p2p-net-device.cc',
|
||||
'p2p-channel.cc',
|
||||
'p2p-topology.cc',
|
||||
'p2p-ipv4-interface.cc',
|
||||
])
|
||||
p2p.add_headers ([
|
||||
'propagator.h',
|
||||
])
|
||||
p2p.add_inst_headers ([
|
||||
'p2p-net-device.h',
|
||||
'p2p-channel.h',
|
||||
'p2p-topology.h',
|
||||
'p2p-ipv4-interface.h',
|
||||
])
|
||||
|
||||
|
||||
# utils
|
||||
run_tests = build.Ns3Module('run-tests', 'utils')
|
||||
ns3.add(run_tests)
|
||||
run_tests.set_executable()
|
||||
run_tests.add_deps(['core', 'simulator', 'common'])
|
||||
run_tests.add_source('run-tests.cc')
|
||||
|
||||
bench_packets = build.Ns3Module('bench-packets', 'utils')
|
||||
#ns3.add(bench_packets)
|
||||
bench_packets.set_executable()
|
||||
bench_packets.add_dep('core')
|
||||
bench_packets.add_source('bench-packets.cc')
|
||||
|
||||
bench_simu = build.Ns3Module('bench-simulator', 'utils')
|
||||
ns3.add(bench_simu)
|
||||
bench_simu.set_executable()
|
||||
bench_simu.add_dep('simulator')
|
||||
bench_simu.add_source('bench-simulator.cc')
|
||||
|
||||
replay_simu = build.Ns3Module('replay-simulation', 'utils')
|
||||
ns3.add(replay_simu)
|
||||
replay_simu.set_executable()
|
||||
replay_simu.add_dep('simulator')
|
||||
replay_simu.add_source('replay-simulation.cc')
|
||||
|
||||
|
||||
# samples
|
||||
sample_debug = build.Ns3Module('sample-debug', 'samples')
|
||||
sample_debug.set_executable()
|
||||
ns3.add(sample_debug)
|
||||
sample_debug.add_dep('core')
|
||||
sample_debug.add_source('main-debug.cc')
|
||||
sample_debug.add_source('main-debug-other.cc')
|
||||
|
||||
sample_callback = build.Ns3Module('sample-callback', 'samples')
|
||||
sample_callback.set_executable()
|
||||
ns3.add(sample_callback)
|
||||
sample_callback.add_dep('core')
|
||||
sample_callback.add_source('main-callback.cc')
|
||||
|
||||
sample_ptr = build.Ns3Module('sample-ptr', 'samples')
|
||||
sample_ptr.set_executable()
|
||||
ns3.add(sample_ptr)
|
||||
sample_ptr.add_dep('core')
|
||||
sample_ptr.add_source('main-ptr.cc')
|
||||
|
||||
sample_trace = build.Ns3Module('sample-trace', 'samples')
|
||||
#ns3.add(sample_trace)
|
||||
sample_trace.add_dep('common')
|
||||
sample_trace.set_executable()
|
||||
sample_trace.add_source('main-trace.cc')
|
||||
|
||||
sample_simu = build.Ns3Module('sample-simulator', 'samples')
|
||||
ns3.add(sample_simu)
|
||||
sample_simu.set_executable()
|
||||
sample_simu.add_dep('simulator')
|
||||
sample_simu.add_source('main-simulator.cc')
|
||||
|
||||
sample_packet = build.Ns3Module('sample-packet', 'samples')
|
||||
ns3.add(sample_packet)
|
||||
sample_packet.set_executable()
|
||||
sample_packet.add_dep('common')
|
||||
sample_packet.add_source('main-packet.cc')
|
||||
|
||||
sample_test = build.Ns3Module('sample-test', 'samples')
|
||||
sample_test.set_executable()
|
||||
ns3.add(sample_test)
|
||||
sample_test.add_dep('core')
|
||||
sample_test.add_source('main-test.cc')
|
||||
|
||||
sample_p2p_net_device_if = build.Ns3Module ('sample-p2p-net-device-if', 'samples')
|
||||
sample_p2p_net_device_if.set_executable ()
|
||||
ns3.add (sample_p2p_net_device_if)
|
||||
sample_p2p_net_device_if.add_deps (['common', 'node', 'p2p'])
|
||||
sample_p2p_net_device_if.add_source ('main-p2p-net-device-if.cc')
|
||||
|
||||
sample_simple = build.Ns3Module('sample-simple', 'samples')
|
||||
sample_simple.set_executable()
|
||||
ns3.add(sample_simple)
|
||||
sample_simple.add_deps(['core', 'simulator', 'node'])
|
||||
sample_simple.add_source('main-simple.cc')
|
||||
|
||||
sample_sp2p = build.Ns3Module('sample-simple-p2p', 'samples')
|
||||
sample_sp2p.set_executable()
|
||||
#n3.add(sample_sp2p)
|
||||
sample_sp2p.add_deps(['core', 'simulator', 'node', 'p2p'])
|
||||
sample_sp2p.add_source('main-simple-p2p.cc')
|
||||
|
||||
# examples
|
||||
example_simple_p2p = build.Ns3Module('simple-p2p', 'examples')
|
||||
example_simple_p2p.set_executable()
|
||||
ns3.add(example_simple_p2p)
|
||||
example_simple_p2p.add_deps(['core', 'simulator', 'node', 'p2p'])
|
||||
example_simple_p2p.add_source('simple-p2p.cc')
|
||||
|
||||
ns3.generate_dependencies()
|
||||
@@ -1,553 +0,0 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
# Copyright (c) 2006 INRIA
|
||||
# All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation;
|
||||
#
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
|
||||
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import shutil
|
||||
from SCons.Environment import Environment
|
||||
from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
import SCons
|
||||
|
||||
# hack stolen from wengo
|
||||
# to get an ARGUMENTS defined correctly
|
||||
try:
|
||||
ARGUMENTS = SCons.Script.ARGUMENTS
|
||||
COMMAND_LINE_TARGETS = SCons.Script.COMMAND_LINE_TARGETS
|
||||
except AttributeError:
|
||||
from SCons.Script.SConscript import Arguments
|
||||
from SCons.Script.SConscript import CommandLineTargets
|
||||
ARGUMENTS = Arguments
|
||||
COMMAND_LINE_TARGETS = CommandLineTargets
|
||||
|
||||
class Ns3Module:
|
||||
def __init__(self, name, dir):
|
||||
self.sources = []
|
||||
self.inst_headers = []
|
||||
self.headers = []
|
||||
self.extra_dist = []
|
||||
self.deps = []
|
||||
self.external_deps = []
|
||||
self.config = []
|
||||
self.name = name
|
||||
self.dir = dir
|
||||
self.executable = False
|
||||
self.library = True
|
||||
self.ldflags = []
|
||||
self.header_inst_dir = ''
|
||||
def set_library(self):
|
||||
self.library = True
|
||||
self.executable = False
|
||||
def set_executable(self):
|
||||
self.library = False
|
||||
self.executable = True
|
||||
def add_config(self, config_fn):
|
||||
self.config.append(config_fn)
|
||||
def add_extra_dist(self, dist):
|
||||
self.extra_dist.append(dist)
|
||||
def add_external_dep(self, dep):
|
||||
self.external_deps.append(dep)
|
||||
def add_dep(self, dep):
|
||||
self.deps.append(dep)
|
||||
def add_deps(self, deps):
|
||||
self.deps.extend(deps)
|
||||
def add_source(self, source):
|
||||
self.sources.append(source)
|
||||
def add_sources(self, sources):
|
||||
self.sources.extend(sources)
|
||||
def add_header(self, header):
|
||||
self.headers.append(header)
|
||||
def add_headers(self, headers):
|
||||
self.headers.extend(headers)
|
||||
def add_inst_header(self, header):
|
||||
self.inst_headers.append(header)
|
||||
def add_inst_headers(self, headers):
|
||||
self.inst_headers.extend(headers)
|
||||
def add_ldflags (self, ldflags):
|
||||
self.ldflags.extend (ldflags)
|
||||
def add_ldflag (self, ldflag):
|
||||
self.add_ldflags ([ldflag])
|
||||
def set_header_inst_dir (self, inst_dir):
|
||||
self.header_inst_dir = inst_dir
|
||||
|
||||
|
||||
def MyCopyAction(target, source, env):
|
||||
try:
|
||||
if len(target) == len(source):
|
||||
for i in range(len(target)):
|
||||
shutil.copy(source[i].path, target[i].path)
|
||||
return 0
|
||||
else:
|
||||
return 'invalid target/source match'
|
||||
except:
|
||||
print
|
||||
return 'exception'
|
||||
def MyCopyActionPrint(target, source, env):
|
||||
if len(target) == len(source):
|
||||
output = ''
|
||||
for i in range(len(target)):
|
||||
output = output + 'copy \'' + source[i].path + '\' to \'' + target[i].path + '\''
|
||||
if i < len(target) - 1:
|
||||
output = output + '\n'
|
||||
return output
|
||||
else:
|
||||
return 'error in copy'
|
||||
def GcxxEmitter(target, source, env):
|
||||
if os.path.exists(source[0].path):
|
||||
return [target, source]
|
||||
else:
|
||||
return [[], []]
|
||||
def MyRmTree(target, source, env):
|
||||
shutil.rmtree(env['RM_DIR'])
|
||||
return 0
|
||||
def MyRmTreePrint(target, source, env):
|
||||
return ''
|
||||
def print_cmd_line(s, target, src, env):
|
||||
print 'Building ' + (' and '.join([str(x) for x in target])) + '...'
|
||||
|
||||
class Ns3BuildVariant:
|
||||
def __init__(self):
|
||||
self.static = False
|
||||
self.gcxx_deps = False
|
||||
self.gcxx_root = ''
|
||||
self.build_root = ''
|
||||
self.env = None
|
||||
|
||||
class Ns3:
|
||||
def __init__(self):
|
||||
self.__modules = []
|
||||
self.extra_dist = []
|
||||
self.build_dir = 'build'
|
||||
self.version = '0.0.1'
|
||||
self.name = 'noname'
|
||||
self.doxygen_config = ''
|
||||
def add(self, module):
|
||||
self.__modules.append(module)
|
||||
def add_extra_dist(self, dist):
|
||||
self.extra_dist.append(dist)
|
||||
def __get_module(self, name):
|
||||
for module in self.__modules:
|
||||
if module.name == name:
|
||||
return module
|
||||
return None
|
||||
def get_mod_output(self, module, variant):
|
||||
if module.executable:
|
||||
suffix = variant.env.subst(variant.env['PROGSUFFIX'])
|
||||
filename = os.path.join(variant.build_root, 'bin',
|
||||
module.name + suffix)
|
||||
else:
|
||||
if variant.static:
|
||||
prefix = variant.env['LIBPREFIX']
|
||||
suffix = variant.env['LIBSUFFIX']
|
||||
else:
|
||||
prefix = variant.env['SHLIBPREFIX']
|
||||
suffix = variant.env['SHLIBSUFFIX']
|
||||
prefix = variant.env.subst(prefix)
|
||||
suffix = variant.env.subst(suffix)
|
||||
filename = os.path.join(variant.build_root, 'lib',
|
||||
prefix + module.name + suffix)
|
||||
return filename
|
||||
def get_obj_builders(self, variant, module):
|
||||
env = variant.env.Copy ()
|
||||
objects = []
|
||||
hash = {}
|
||||
self.get_internal_deps (module, hash)
|
||||
for dep in hash.values ():
|
||||
if dep.header_inst_dir != '':
|
||||
inc_dir = os.path.join(variant.build_root, 'include',
|
||||
self.name, dep.header_inst_dir)
|
||||
env.Append (CPPPATH = [inc_dir])
|
||||
|
||||
if len(module.config) > 0:
|
||||
src_config_file = os.path.join(self.build_dir, 'config', module.name + '-config.h')
|
||||
tgt_config_file = os.path.join(variant.build_root, 'include',
|
||||
self.name, module.name + '-config.h')
|
||||
|
||||
for source in module.sources:
|
||||
obj_file = os.path.splitext(source)[0] + '.o'
|
||||
tgt = os.path.join(variant.build_root, module.dir, obj_file)
|
||||
src = os.path.join(module.dir, source)
|
||||
if variant.static:
|
||||
obj_builder = env.StaticObject(target = tgt, source = src)
|
||||
else:
|
||||
obj_builder = env.SharedObject(target = tgt, source = src)
|
||||
if len(module.config) > 0:
|
||||
config_file = env.MyCopyBuilder(target = [tgt_config_file],
|
||||
source = [src_config_file])
|
||||
env.Depends(obj_builder, config_file)
|
||||
if variant.gcxx_deps:
|
||||
gcno_tgt = os.path.join(variant.build_root, module.dir,
|
||||
os.path.splitext(source)[0] + '.gcno')
|
||||
gcda_tgt = os.path.join(variant.build_root, module.dir,
|
||||
os.path.splitext(source)[0] + '.gcda')
|
||||
gcda_src = os.path.join(variant.gcxx_root, module.dir,
|
||||
os.path.splitext(source)[0] + '.gcda')
|
||||
gcno_src = os.path.join(variant.gcxx_root, module.dir,
|
||||
os.path.splitext(source)[0] + '.gcno')
|
||||
gcno_builder = env.CopyGcxxBuilder(target = gcno_tgt, source = gcno_src)
|
||||
gcda_builder = env.CopyGcxxBuilder(target = gcda_tgt, source = gcda_src)
|
||||
env.Depends(obj_builder, gcda_builder)
|
||||
env.Depends(obj_builder, gcno_builder)
|
||||
objects.append(obj_builder)
|
||||
return objects
|
||||
def get_internal_deps(self, module, hash):
|
||||
for dep_name in module.deps:
|
||||
dep = self.__get_module(dep_name)
|
||||
hash[dep_name] = dep
|
||||
self.get_internal_deps(dep, hash)
|
||||
def get_external_deps(self, module):
|
||||
hash = {}
|
||||
self.get_internal_deps(module, hash)
|
||||
ext_hash = {}
|
||||
for mod in hash.values():
|
||||
for ext_dep in mod.external_deps:
|
||||
ext_hash[ext_dep] = 1
|
||||
return ext_hash.keys()
|
||||
def get_sorted_deps(self, module):
|
||||
h = {}
|
||||
self.get_internal_deps(module, h)
|
||||
modules = []
|
||||
for dep in h.keys():
|
||||
deps_copy = []
|
||||
mod = h[dep]
|
||||
deps_copy.extend(mod.deps)
|
||||
modules.append([mod, deps_copy])
|
||||
sorted = []
|
||||
while len(modules) > 0:
|
||||
to_remove = []
|
||||
for item in modules:
|
||||
if len(item[1]) == 0:
|
||||
to_remove.append(item[0].name)
|
||||
for item in to_remove:
|
||||
for i in modules:
|
||||
if item in i[1]:
|
||||
i[1].remove(item)
|
||||
new_modules = []
|
||||
for mod in modules:
|
||||
found = False
|
||||
for i in to_remove:
|
||||
if i == mod[0].name:
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
new_modules.append(mod)
|
||||
modules = new_modules
|
||||
sorted.extend(to_remove)
|
||||
sorted.reverse()
|
||||
# append external deps
|
||||
ext_deps = self.get_external_deps(module)
|
||||
for dep in ext_deps:
|
||||
sorted.append(dep)
|
||||
return sorted
|
||||
|
||||
def gen_mod_dep(self, variant):
|
||||
build_root = variant.build_root
|
||||
cpp_path = os.path.join(variant.build_root, 'include')
|
||||
env = variant.env
|
||||
env.Append(CPPPATH = [cpp_path])
|
||||
header_dir = os.path.join(build_root, 'include', self.name)
|
||||
lib_path = os.path.join(build_root, 'lib')
|
||||
env.Append (LIBPATH = [lib_path])
|
||||
module_builders = []
|
||||
for module in self.__modules:
|
||||
my_env = env.Copy ();
|
||||
objects = self.get_obj_builders(variant, module)
|
||||
libs = self.get_sorted_deps(module)
|
||||
my_env.Append (LIBS = libs)
|
||||
my_env.Append (LINKFLAGS = module.ldflags)
|
||||
|
||||
filename = self.get_mod_output(module, variant)
|
||||
if module.executable:
|
||||
module_builder = my_env.Program(target=filename, source=objects)
|
||||
else:
|
||||
if variant.static:
|
||||
module_builder = my_env.StaticLibrary(target=filename, source=objects)
|
||||
else:
|
||||
module_builder = my_env.SharedLibrary(target=filename, source=objects)
|
||||
|
||||
for dep_name in module.deps:
|
||||
dep = self.__get_module(dep_name)
|
||||
my_env.Depends(module_builder, self.get_mod_output(dep, variant))
|
||||
|
||||
for header in module.inst_headers:
|
||||
if module.header_inst_dir != '':
|
||||
tgt = os.path.join(header_dir, module.header_inst_dir, header)
|
||||
else:
|
||||
tgt = os.path.join(header_dir, header)
|
||||
src = os.path.join(module.dir, header)
|
||||
#builder = env.Install(target = tgt, source = src)
|
||||
header_builder = my_env.MyCopyBuilder(target=tgt, source=src)
|
||||
my_env.Depends(module_builder, header_builder)
|
||||
|
||||
module_builders.append(module_builder)
|
||||
return module_builders
|
||||
def gen_mod_config(self, env):
|
||||
config_dir = os.path.join(self.build_dir, 'config')
|
||||
for module in self.__modules:
|
||||
if len(module.config) > 0:
|
||||
config_file = os.path.join(config_dir, module.name + '-config.h')
|
||||
config_file_guard = module.name + '_CONFIG_H'
|
||||
config_file_guard.upper()
|
||||
if not os.path.isfile(config_file):
|
||||
if not os.path.isdir(config_dir):
|
||||
os.makedirs(config_dir)
|
||||
outfile = open(config_file, 'w')
|
||||
outfile.write('#ifndef ' + config_file_guard + '\n')
|
||||
outfile.write('#define ' + config_file_guard + '\n')
|
||||
config = env.Configure()
|
||||
for fn in module.config:
|
||||
output = fn(env, config)
|
||||
for o in output:
|
||||
outfile.write(o)
|
||||
outfile.write('\n')
|
||||
outfile.write('#endif /*' + config_file_guard + '*/\n')
|
||||
config.Finish()
|
||||
def generate_dependencies(self):
|
||||
inheritenv = (ARGUMENTS.get('inheritenv', 'n') in 'yY1')
|
||||
if inheritenv:
|
||||
env = Environment(ENV=os.environ)
|
||||
else:
|
||||
env = Environment()
|
||||
self.gen_mod_config(env)
|
||||
cc = env['CC']
|
||||
cxx = env.subst(env['CXX'])
|
||||
if cc == '':
|
||||
print "Missing C compiler."
|
||||
env.Exit (1);
|
||||
if cxx == '':
|
||||
print "Missing C++ compiler."
|
||||
env.Exit (1);
|
||||
common_flags = ARGUMENTS.get('cflags', '').split(' ')
|
||||
cxxflags = ARGUMENTS.get('cxxflags', '').split(' ')
|
||||
ldflags = ARGUMENTS.get('ldflags', '').split(' ')
|
||||
if cc == 'cl' and cxx == 'cl':
|
||||
env = Environment(tools=['mingw'])
|
||||
cc = env['CC']
|
||||
cxx = env.subst(env['CXX'])
|
||||
if cc == 'gcc' and cxx == 'g++':
|
||||
common_flags.extend(['-g3', '-Wall', '-Werror'])
|
||||
debug_flags = []
|
||||
opti_flags = ['-O3']
|
||||
elif cc == 'cl' and cxx == 'cl':
|
||||
env = Environment(ENV=os.environ)
|
||||
debug_flags = ['-W1', '-GX', '-EHsc', '-D_DEBUG', '/MDd']
|
||||
opti_flags = ['-O2', '-EHsc', '-DNDEBUG', '/MD']
|
||||
env.Append(CCFLAGS = common_flags,
|
||||
CPPDEFINES = ['RUN_SELF_TESTS'],
|
||||
TARFLAGS = '-c -z',
|
||||
CPPFLAGS = cxxflags,
|
||||
LINKFLAGS = ldflags)
|
||||
if env['PLATFORM'] == 'posix':
|
||||
env.Append(LINKFLAGS = ' -z origin')
|
||||
env.Append(RPATH=env.Literal(os.path.join('\\$$ORIGIN', os.pardir, 'lib')))
|
||||
verbose = ARGUMENTS.get('verbose', 'n')
|
||||
if verbose == 'n':
|
||||
env['PRINT_CMD_LINE_FUNC'] = print_cmd_line
|
||||
header_builder = Builder(action = Action(MyCopyAction, strfunction=MyCopyActionPrint))
|
||||
env.Append(BUILDERS = {'MyCopyBuilder':header_builder})
|
||||
gcxx_builder = Builder(action = Action(MyCopyAction, strfunction=MyCopyActionPrint),
|
||||
emitter = GcxxEmitter)
|
||||
env.Append(BUILDERS = {'CopyGcxxBuilder':gcxx_builder})
|
||||
variant = Ns3BuildVariant()
|
||||
builders = []
|
||||
|
||||
|
||||
gcov_env = env.Copy()
|
||||
gcov_env.Append(CFLAGS = ['-fprofile-arcs', '-ftest-coverage'],
|
||||
CXXFLAGS = ['-fprofile-arcs', '-ftest-coverage'],
|
||||
LINKFLAGS = ['-fprofile-arcs'])
|
||||
# code coverage analysis
|
||||
variant.static = False
|
||||
variant.env = gcov_env
|
||||
variant.build_root = os.path.join(self.build_dir, 'gcov')
|
||||
builders = self.gen_mod_dep(variant)
|
||||
for builder in builders:
|
||||
gcov_env.Alias('gcov', builder)
|
||||
gcov_env.Alias('lcov-report')
|
||||
if 'lcov-report' in COMMAND_LINE_TARGETS:
|
||||
lcov_report_dir = os.path.join(self.build_dir, 'lcov-report')
|
||||
create_dir_command = "rm -rf " + lcov_report_dir
|
||||
create_dir_command += " && mkdir " + lcov_report_dir + ";"
|
||||
gcov_env.Execute(create_dir_command)
|
||||
info_file = os.path.join(lcov_report_dir, self.name + '.info')
|
||||
lcov_command = "utils/lcov/lcov -c -d . -o " + info_file
|
||||
lcov_command += " --source-dirs=" + os.getcwd()
|
||||
lcov_command += ":" + os.path.join(os.getcwd(),
|
||||
variant.build_root,
|
||||
'include')
|
||||
gcov_env.Execute(lcov_command)
|
||||
genhtml_command = "utils/lcov/genhtml -o " + lcov_report_dir
|
||||
genhtml_command += " " + info_file
|
||||
gcov_env.Execute(genhtml_command)
|
||||
|
||||
|
||||
|
||||
opt_env = env.Copy()
|
||||
opt_env.Append(CFLAGS=opti_flags,
|
||||
CXXFLAGS=opti_flags,
|
||||
CPPDEFINES=['NDEBUG'])
|
||||
# optimized static support
|
||||
variant.static = True
|
||||
variant.env = opt_env
|
||||
variant.build_root = os.path.join(self.build_dir, 'opt-static')
|
||||
builders = self.gen_mod_dep(variant)
|
||||
for builder in builders:
|
||||
opt_env.Alias('opt-static', builder)
|
||||
|
||||
|
||||
opt_env = env.Copy()
|
||||
opt_env.Append(CFLAGS = opti_flags,
|
||||
CXXFLAGS = opti_flags,
|
||||
CPPDEFINES = ['NDEBUG'])
|
||||
# optimized shared support
|
||||
variant.static = False
|
||||
variant.env = opt_env
|
||||
variant.build_root = os.path.join(self.build_dir, 'opt-shared')
|
||||
builders = self.gen_mod_dep(variant)
|
||||
for builder in builders:
|
||||
opt_env.Alias('opt-shared', builder)
|
||||
|
||||
|
||||
arc_env = env.Copy()
|
||||
arc_env.Append(CFLAGS=opti_flags,
|
||||
CXXFLAGS=opti_flags,
|
||||
CPPDEFINES=['NDEBUG'])
|
||||
arc_env.Append(CFLAGS=['-frandom-seed=0', '-fprofile-generate'],
|
||||
CXXFLAGS=['-frandom-seed=0', '-fprofile-generate'],
|
||||
LINKFLAGS=['-frandom-seed=0', '-fprofile-generate'])
|
||||
# arc profiling
|
||||
variant.static = False
|
||||
variant.env = arc_env
|
||||
variant.build_root = os.path.join(self.build_dir, 'opt-arc')
|
||||
builders = self.gen_mod_dep(variant)
|
||||
for builder in builders:
|
||||
arc_env.Alias('opt-arc', builder)
|
||||
|
||||
|
||||
arcrebuild_env = env.Copy()
|
||||
arcrebuild_env.Append(CFLAGS=opti_flags,
|
||||
CXXFLAGS=opti_flags,
|
||||
CPPDEFINES=['NDEBUG'])
|
||||
arcrebuild_env.Append(CFLAGS=['-frandom-seed=0', '-fprofile-use'],
|
||||
CXXFLAGS=['-frandom-seed=0', '-fprofile-use'],
|
||||
LINKFLAGS=['-frandom-seed=0', '-fprofile-use'])
|
||||
# arc rebuild
|
||||
variant.static = False
|
||||
variant.env = arcrebuild_env
|
||||
variant.gcxx_deps = True
|
||||
variant.gcxx_root = os.path.join(self.build_dir, 'opt-arc')
|
||||
variant.build_root = os.path.join(self.build_dir, 'opt-arc-rebuild')
|
||||
builders = self.gen_mod_dep(variant)
|
||||
for builder in builders:
|
||||
arcrebuild_env.Alias('opt-arc-rebuild', builder)
|
||||
variant.gcxx_deps = False
|
||||
|
||||
|
||||
|
||||
|
||||
dbg_env = env.Copy()
|
||||
dbg_env.Append(CFLAGS = debug_flags,
|
||||
CXXFLAGS = debug_flags,
|
||||
CPPDEFINES = ['NS3_DEBUG_ENABLE',
|
||||
'NS3_ASSERT_ENABLE'])
|
||||
# debug static support
|
||||
variant.static = True
|
||||
variant.env = dbg_env
|
||||
variant.build_root = os.path.join(self.build_dir, 'dbg-static')
|
||||
builders = self.gen_mod_dep(variant)
|
||||
for builder in builders:
|
||||
dbg_env.Alias('dbg-static', builder)
|
||||
|
||||
dbg_env = env.Copy()
|
||||
dbg_env.Append(CFLAGS=debug_flags,
|
||||
CXXFLAGS=debug_flags,
|
||||
CPPDEFINES = ['NS3_DEBUG_ENABLE',
|
||||
'NS3_ASSERT_ENABLE'])
|
||||
# debug shared support
|
||||
variant.static = False
|
||||
variant.env = dbg_env
|
||||
variant.build_root = os.path.join(self.build_dir, 'dbg-shared')
|
||||
builders = self.gen_mod_dep(variant)
|
||||
for builder in builders:
|
||||
dbg_env.Alias('dbg-shared', builder)
|
||||
|
||||
env.Alias('dbg', 'dbg-shared')
|
||||
env.Alias('opt', 'opt-shared')
|
||||
env.Default('dbg')
|
||||
env.Alias('all', ['dbg-shared', 'dbg-static', 'opt-shared', 'opt-static'])
|
||||
|
||||
|
||||
# dist support
|
||||
dist_env = env.Copy()
|
||||
if dist_env['PLATFORM'] == 'posix':
|
||||
dist_list = []
|
||||
for module in self.__modules:
|
||||
for f in module.sources:
|
||||
dist_list.append(os.path.join(module.dir, f))
|
||||
for f in module.headers:
|
||||
dist_list.append(os.path.join(module.dir, f))
|
||||
for f in module.inst_headers:
|
||||
dist_list.append(os.path.join(module.dir, f))
|
||||
for f in module.extra_dist:
|
||||
dist_list.append(os.path.join(module.dir, f))
|
||||
for f in self.extra_dist:
|
||||
dist_list.append(f)
|
||||
dist_list.append('SConstruct')
|
||||
dist_list.append('build.py')
|
||||
|
||||
targets = []
|
||||
basename = self.name + '-' + self.version
|
||||
for src in dist_list:
|
||||
tgt = os.path.join(basename, src)
|
||||
targets.append(dist_env.MyCopyBuilder(target=tgt, source=src))
|
||||
tar = basename + '.tar.gz'
|
||||
zip = basename + '.zip'
|
||||
tmp_tar = os.path.join(self.build_dir, tar)
|
||||
tmp_zip = os.path.join(self.build_dir, zip)
|
||||
dist_tgt = [tar, zip]
|
||||
dist_src = [tmp_tar, tmp_zip]
|
||||
dist_env.Tar(tmp_tar, targets)
|
||||
dist_env.Zip(tmp_zip, targets)
|
||||
dist_builder = dist_env.MyCopyBuilder(target=dist_tgt, source=dist_src)
|
||||
dist_env.Alias('dist', dist_builder)
|
||||
dist_env.Append(RM_DIR=basename)
|
||||
dist_env.AddPostAction(dist_builder, dist_env.Action(MyRmTree,
|
||||
strfunction=MyRmTreePrint))
|
||||
dist_builder = dist_env.MyCopyBuilder(target=dist_tgt, source=dist_src)
|
||||
dist_env.Alias('fastdist', dist_tgt)
|
||||
|
||||
# distcheck
|
||||
distcheck_list = []
|
||||
for src in dist_list:
|
||||
tgt = os.path.join(self.build_dir, basename, src)
|
||||
distcheck_list.append(tgt)
|
||||
untar = env.Command(distcheck_list, tar,
|
||||
['cd ' + self.build_dir + ' && tar -zxf ../' + tar])
|
||||
scons_dir = os.path.join(self.build_dir, basename)
|
||||
distcheck_builder = env.Command('x', distcheck_list,
|
||||
['cd ' + scons_dir + ' && scons'])
|
||||
env.AlwaysBuild(distcheck_builder)
|
||||
env.Alias('distcheck', distcheck_builder)
|
||||
if self.doxygen_config != '':
|
||||
doxy = env.Command('doc/html/*', self.doxygen_config,
|
||||
['doxygen ' + self.doxygen_config])
|
||||
env.AlwaysBuild(doxy)
|
||||
env.Alias('doc', doxy)
|
||||
@@ -0,0 +1,98 @@
|
||||
The Waf build system is used to build ns-3. Waf is a Python-based
|
||||
build system (http://www.freehackers.org/~tnagy/waf.html)
|
||||
|
||||
=== Installing Waf ===
|
||||
|
||||
The top-level ns-3 directory should contain a current waf script.
|
||||
|
||||
=== Building with Waf ===
|
||||
|
||||
To build ns-3 with waf type the commands from the top-level directory:
|
||||
1. ./waf configure [options]
|
||||
2. ./waf
|
||||
|
||||
To see valid configure options, type ./waf --help. The most important
|
||||
option is -d <debug level>. Valid debug levels (which are listed in
|
||||
waf --help) are: "debug" or "optimized". It is
|
||||
also possible to change the flags used for compilation with (e.g.):
|
||||
CXXFLAGS="-O3" ./waf configure.
|
||||
|
||||
[ Note: Unlike some other build tools, to change the build target,
|
||||
the option must be supplied during the configure stage rather than
|
||||
the build stage (i.e., "./waf -d optimized" will not work; instead, do
|
||||
"./waf -d optimized configure; ./waf" ]
|
||||
|
||||
The resulting binaries are placed in build/<debuglevel>/srcpath.
|
||||
|
||||
Other waf usages include:
|
||||
|
||||
1. ./waf check
|
||||
Runs the unit tests
|
||||
|
||||
2. ./waf --doxygen
|
||||
Run doxygen to generate documentation
|
||||
|
||||
3. ./waf --lcov-report
|
||||
Run code coverage analysis (assuming the project was configured
|
||||
with --enable-gcov)
|
||||
|
||||
4. ./waf --run "program [args]"
|
||||
Run a ns3 program, given its target name, with the given
|
||||
arguments. This takes care of automatically modifying the the
|
||||
path for finding the ns3 dynamic libraries in the environment
|
||||
before running the program. Note: the "program [args]" string is
|
||||
parsed using POSIX shell rules.
|
||||
|
||||
4.1 ./waf --run programname --command-template "... %s ..."
|
||||
|
||||
Same as --run, but uses a command template with %s replaced by the
|
||||
actual program (whose name is given by --run). This can be use to
|
||||
run ns-3 programs with helper tools. For example, to run unit
|
||||
tests with valgrind, use the command:
|
||||
|
||||
./waf --run run-tests --command-template "valgrind %s"
|
||||
|
||||
5. ./waf --shell
|
||||
Starts a nested system shell with modified environment to run ns3 programs.
|
||||
|
||||
6. ./waf distclean
|
||||
Cleans out the entire build/ directory
|
||||
|
||||
7. ./waf dist
|
||||
The command 'waf dist' can be used to create a distribution tarball.
|
||||
It includes all files in the source directory, except some particular
|
||||
extensions that are blacklisted, such as back files (ending in ~).
|
||||
|
||||
|
||||
=== Extending ns-3 ===
|
||||
|
||||
To add new modules:
|
||||
1. Create the module directory under src (or src/devices, or whatever);
|
||||
2. Add the source files to it;
|
||||
3. Add a 'wscript' describing it;
|
||||
4. Add the module subdirectory name to the all_modules list in src/wscript.
|
||||
|
||||
A module's wscript file is basically a regular Waf script. A ns-3
|
||||
module is created as a cpp/shlib object, like this:
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_obj('cpp', 'shlib')
|
||||
|
||||
## set module name; by convention it starts with ns3-
|
||||
obj.name = 'ns3-mymodule'
|
||||
obj.target = obj.name
|
||||
|
||||
## list dependencies to other modules
|
||||
obj.uselib_local = ['ns3-core']
|
||||
|
||||
## list source files (private or public header files excluded)
|
||||
obj.source = [
|
||||
'mymodule.cc',
|
||||
]
|
||||
|
||||
## list module public header files
|
||||
headers = bld.create_obj('ns3header')
|
||||
headers.source = [
|
||||
'mymodule-header.h',
|
||||
]
|
||||
|
||||
@@ -1,592 +0,0 @@
|
||||
\documentclass[11pt]{article}
|
||||
\usepackage{times}
|
||||
\setlength{\textwidth}{6.5in}
|
||||
\setlength{\textheight}{9in}
|
||||
\setlength{\oddsidemargin}{0.0in}
|
||||
\setlength{\evensidemargin}{0.0in}
|
||||
\setlength{\topmargin}{-0.5in}
|
||||
\def\nst{{\em ns--3}}
|
||||
\newcommand{\code}[1]{\texttt{#1}}
|
||||
|
||||
\begin{document}
|
||||
\begin{center}
|
||||
{\Large Coding Standard for ns--3}\\
|
||||
August 22, 2005
|
||||
|
||||
\end{center}
|
||||
\section{Introduction}
|
||||
|
||||
The purpose of the \nst\ project is to build software which will last
|
||||
many years: making sure that the code is readable and stays so is
|
||||
one of the most important items required to achieve this goal. This
|
||||
document thus outlines guidelines we plan to enforce on each component
|
||||
integrated in \nst to ensure uniformity of the codebase which is
|
||||
a first step towards readable code.
|
||||
|
||||
\section{Recommendations}
|
||||
|
||||
The following recommendations are not strict rules and some of them
|
||||
are conflicting but the point here is to outline the fact that we
|
||||
value more common-sense than strict adherence to the coding style
|
||||
defined in this document.
|
||||
|
||||
\subsection{naming}
|
||||
|
||||
Types, methods, functions and variable names should be self-descriptive.
|
||||
Avoid using acronyms, expand them, do not hesitate to use long names,
|
||||
Avoid shortcuts such as \code{sz} for \code{size}. Long names sometimes get in the
|
||||
way of being able to read the code:
|
||||
\begin{verbatim}
|
||||
for (int loopCount = 0; loopCount < max; loopCount++)
|
||||
{
|
||||
// code
|
||||
}
|
||||
\end{verbatim}
|
||||
loopCount should be renamed to something shorter such as
|
||||
\code{i}, \code{j}, \code{k}, \code{l}, \code{m}, and \code{n}
|
||||
which are widely used names which identify loop counters:
|
||||
\begin{verbatim}
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
// code
|
||||
}
|
||||
\end{verbatim}
|
||||
Similarly, \code{tmp} is a common way to denote temporary variables. On
|
||||
the other hand, \code{foo} is not an appropriate name: it says nothing
|
||||
about the purpose of the variable.
|
||||
|
||||
If you use predicates (that is, functions, variables or methods
|
||||
which return a single boolean value), prefix the
|
||||
name with \code{is} or \code{has}.
|
||||
|
||||
\subsection{Memory management}
|
||||
|
||||
As much as possible, try to pass around objects
|
||||
by value and allocate them on the stack. If you need to allocate
|
||||
objects on the heap with new, make sure that the corresponding
|
||||
call to delete happens where the new took place. i.e., avoid
|
||||
passing around pointer ownership.
|
||||
Avoid the use of reference counting and, more generaly, strive to
|
||||
keep the memory-management model simple.
|
||||
|
||||
\subsection{Templates}
|
||||
|
||||
For now, templates are defined only in the simulator
|
||||
core and are used everywhere else. Try to keep it that way by
|
||||
avoiding defining new templates in model-specific code.
|
||||
|
||||
|
||||
\section{Standards}
|
||||
\subsection{General}
|
||||
\begin{enumerate}
|
||||
\item There will be no {\em tab} characters in the code. Rather, repeated
|
||||
spaces are used to separate the characters as needed.
|
||||
\item No line of code will be longer than 80 characters in length, to
|
||||
prevent lines wrapping in the {\tt emacs} or {\tt vi} editors. For both
|
||||
of these linux text editing tools, the default is a window that is
|
||||
exactly 80 characters wide, so if none of the lines wrap when editing
|
||||
in {\tt emacs} or {\tt vi} this requirement is met.
|
||||
|
||||
\item Each C++ statement will be on a separate line. The only exception
|
||||
is when an {\tt if}, {\tt else}, {\tt for} or {\tt while}
|
||||
statement has a single
|
||||
statement sub--block these can be on the same line.
|
||||
|
||||
Examples:
|
||||
|
||||
\begin{tt}
|
||||
int i = 0; // Right\\
|
||||
i = 10; j = 20; // Wrong. Two statements same line\\
|
||||
Sub1(k); Sub2(k); // Wrong. Two statements same line\\
|
||||
if (done) break; // Right. If statement with single statement sub-block
|
||||
\end{tt}
|
||||
|
||||
\item Each variable declaration will be on a separate line.
|
||||
|
||||
Examples:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
int c, d; \=// Wrong. c and d defined on same line.\\
|
||||
int a = 0; \\
|
||||
int b = 0; \>// Right. a and b on different lines\\
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item Variables should be declared at the point in the code
|
||||
where they are needed, and should be assigned an initial value
|
||||
at the time of declaration.
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
int a = 0; \=// Right, a is assigned in initial value.\\
|
||||
int b; \> Wrong, b is not assigned an initial value.\\
|
||||
int c = 0; \\
|
||||
int d = Sub1(a, b);\\
|
||||
c = Sub2(d); \> // Wrong, c should be declared here, not above
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item Excepting when used in a {\tt switch} statement, the open
|
||||
and close curly braces (\{ and \}) are always on a separate line.
|
||||
|
||||
Examples:
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
for (int i = 0; i < MAX\_COUNT; ++i) \\
|
||||
\>\{ // Right. Open brace on separate line \\
|
||||
\>\>sum += i; \\
|
||||
\>\>prod *= i; \\
|
||||
\>\} // Right. Close brace on separate line
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
for (int i = 0; i < 10; ++i) \{ // Wrong. Open brace on same line\\
|
||||
\>sum += i; \\
|
||||
\>prod *= i; \} // Wrong. Close brace on same line
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item The C++ {\tt goto} statement is not to be used.
|
||||
\end{enumerate}
|
||||
\subsection{Commenting}
|
||||
In general, comments should be use liberally throughout the program to
|
||||
increase readability. Specifically:
|
||||
|
||||
\begin{enumerate}
|
||||
\item C++ style comments using the {\tt //} delimeter
|
||||
are to be used, rather than C style comments with the {\tt /*}
|
||||
and {\tt */} delimieters.
|
||||
|
||||
\item Variable declaration should have a short, one or two line comment
|
||||
describing the purpose of the variable, unless it is a
|
||||
local variable whose use is obvious from the context. The short
|
||||
comment should be on the same line as the variable declaration, unless it
|
||||
is too long, in which case it should be on the preceding lines.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
int averageGrade; // Computed average grade for this project \\
|
||||
// Note. The above comment likely qualifies as \\
|
||||
// obvious from context, and could be omitted.
|
||||
\\
|
||||
// Counts the total number of students completing the project, but\\
|
||||
// does not include those not turning in the project. \\
|
||||
int projectCount = 0;
|
||||
\end{tt}
|
||||
\item Every function should be preceded by a detailed comment block
|
||||
describing what the function does, what the formal parameters are, and
|
||||
what the return value is (if any).
|
||||
|
||||
\item Every class declaration should be preceded by a comment block
|
||||
describing what the class is to be used for.
|
||||
|
||||
\item Unless obvious from context, each {\tt if} statement should
|
||||
include a one--line comment on the open curly brace following describing
|
||||
the {\tt TRUE} condition and the {\tt FALSE} condition.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
if (iter == students.end()) \\
|
||||
\>\{ // Student not found, add him \\
|
||||
\>\>students.push\_back(thisStudent); \\
|
||||
\>\} \\
|
||||
else \\
|
||||
\>\{ // Student exists, modify existing data \\
|
||||
\>\>iter->grade += thisGrade; \\
|
||||
\>\}
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
\item Class and function comments should adhere to the Doxygen standard
|
||||
format, for automated extraction by the Doxygen tool. {\em Note from
|
||||
GFR. We need a bit more here, as Doxygen has several possible methods
|
||||
for commenting. I'll look them over and suggest an approach, for later
|
||||
discussion}
|
||||
|
||||
\end{enumerate}
|
||||
\subsection{Naming Conventions}
|
||||
\begin{enumerate}
|
||||
\item {\bf Variable Names}. All variables, including global variables,
|
||||
local variables, formal parameters,
|
||||
and member variables in classes will start with a
|
||||
lower case letter, and consist of only alphabetic characters and numeric
|
||||
digits. Capital letters are to be used when appropriate between words
|
||||
in a variable name for increased readability.
|
||||
Variable names should not contain the underscore character.
|
||||
|
||||
Examples:
|
||||
|
||||
{\tt int i;}\\
|
||||
{\tt int nextIndexValue;}\\
|
||||
{\tt int sum1;}\\
|
||||
{\tt int loopCount10;}
|
||||
|
||||
\item {\bf Class Member and Global Variables}. To be able to distinguish
|
||||
local variables from class member and global variables, prepend the
|
||||
\code{m\_} prefix to class member variables and the \code{g\_} prefix
|
||||
to global variables.
|
||||
|
||||
Examples:
|
||||
\begin{verbatim}
|
||||
class Foo {
|
||||
private:
|
||||
int m_myPrivateVar;
|
||||
};
|
||||
static int g_myGlobalVar;
|
||||
\end{verbatim}
|
||||
|
||||
\item {\bf Subroutine Names}. All subroutine names, including global
|
||||
routines and member functions in classes, will start with an upper case
|
||||
letter, and consist of only alphabetic characters and numeric digits
|
||||
(although digits should be rarely needed).
|
||||
As in variable names, upper case letters are to be used between words as needed
|
||||
to increase readability.
|
||||
|
||||
Examples:
|
||||
|
||||
{\tt int ComputeNextIterator()}\\
|
||||
{\tt int Calculate()}\\
|
||||
{\tt int TransmitPacket()}\\
|
||||
{\tt int Dummy()}
|
||||
|
||||
\item {\bf Defined Constants}. All defined constants will be all upper
|
||||
case letters or numeric digits, with the underscore character separating
|
||||
words.
|
||||
|
||||
Examples:
|
||||
|
||||
{\tt typedef enum \{ PACKET\_RX, PACKET\_FIRST\_BIT\_RX, PACKET\_TX\} }\\
|
||||
{\tt \#define NUMBER\_ELEMENTS 10}\\
|
||||
{\tt const int LOOP\_COUNT = 100}
|
||||
|
||||
\item {\bf Defined Types}. All user defined types will end start with
|
||||
an upper case letter, consist of upper and lower case letters only, and
|
||||
end in {\tt \_t}.
|
||||
|
||||
Examples:
|
||||
|
||||
{\tt typedef double Time\_t; // Simulation time}\\
|
||||
{\tt typedef unsigned long SimulatorUid\_t; // Unique ID for each event}\\
|
||||
{\tt typedef unsigned long Event\_t; // Idenifies events in handler}\\
|
||||
|
||||
\item {\bf Class Names}. Class names will start with an upper case letter,
|
||||
consist of only alphabetic characters, and include capital letters as
|
||||
needed to increase readability.
|
||||
|
||||
Examples:
|
||||
|
||||
{\tt class DropTailQueue \{}\\
|
||||
{\tt class Ferrari \{}\\
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
%\newpage % Adjust as needed
|
||||
\subsection{Statement Formatting}
|
||||
\begin{enumerate}
|
||||
\item {\bf Indention}. The basic indention level for all code
|
||||
is two character positions.
|
||||
\item {\bf Continuation statements}. Frequently a single statement
|
||||
is too long to fit within a single 80 column line. In this case, the
|
||||
statement is simply continued on the next one or more lines. Each
|
||||
continuation line must be indented at least one--half indention level,
|
||||
and more as necessary to increase readability.
|
||||
|
||||
Examples:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
longVariableName = \=(anotherLongName * shorterName) + (loopIndex2 * i) + \\
|
||||
\>(k * j); // Correct, indented for neatness
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
a\=a\=a\= \kill
|
||||
for (LongTypeName\_t longLoopIndexName = aLongExpression; \\
|
||||
\>longLoopIndexName < MAX\_VALUE; \\
|
||||
\>longLoopIndexName++) // Wrong, continuations not indented far enough
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
for (\=LongTypeName\_t longLoopIndexName = aLongExpression; \\
|
||||
\>longLoopIndexName < MAX\_VALUE; \\
|
||||
\>longLoopIndexName++) // Right, indented for readability
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item {\bf {\tt IF} Statements}.
|
||||
The open curly brace following an {\tt IF} statement must be on the
|
||||
following line, indented by one indention level.
|
||||
The subsequent lines must be
|
||||
indented by an additional one indention level.
|
||||
The {\tt ELSE} statement (if present)
|
||||
must be on a line by itself.
|
||||
|
||||
Examples:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
if (someCondition) \\
|
||||
\>\{ // Describe TRUE condition here\\
|
||||
\>\>i = k;\\
|
||||
\>\>k = i + 2;\\
|
||||
\>\} // Right, curly block indented one indent level, statements one indent more
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
if (someCondition) \\
|
||||
\>\{ // Describe TRUE condition here\\
|
||||
\>\>i = k;\\
|
||||
\>\>k = i + 2;\\
|
||||
\>\} \\
|
||||
else // Right, ELSE statement on separate line, same indent as IF \\
|
||||
\>\{ // Describe FALSE condition here\\
|
||||
\>\>i = k * 2; \\
|
||||
\>\>k = i + 4; \\
|
||||
\>\} // Right, closing curly brace lined up with open brace
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
if (someCondition) // Describe TRUE condition here\\
|
||||
\>i = k; // Right, single line block need not have curly braces \\
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
|
||||
\item {\bf {\tt FOR} Statements}.
|
||||
The open brace following a {\tt for} statement is indented
|
||||
one level from the {\tt for} statement itself. Each statement
|
||||
in the sub--block is indented one level from the curly brace.
|
||||
If the sub--block is a single statement, the curly braces can be
|
||||
omitted and the statement indented one level, or optionally appear
|
||||
on the same line as the {\tt for} statement.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
for (int i = 0; i < MAX\_COUNT; ++i) \\
|
||||
\>\{ // Curly brace indented one level \\
|
||||
\>\>sum += i; // Statements indented another one level \\
|
||||
\>\>prod *= i; \\
|
||||
\>\} // Close brace on same column as open brace \\
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item {\bf {\tt WHILE} Statements}.
|
||||
{\tt While} statements are formatted similarly to {\tt IF} statements,
|
||||
with curly braces indented one level on separate lines, and the
|
||||
inner statements indented another level. If the sub--block has only
|
||||
a single line, the curly braces can be omitted, and the statement may
|
||||
appear on the same line as the {\tt WHILE} statement.
|
||||
|
||||
Examples:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
while (someCondition) \\
|
||||
\>\{ // Right, open brace indented one level \\
|
||||
\>\>i = k; // Right, statements indented one level from open brace \\
|
||||
\>\>k = i + 2;\\
|
||||
\>\} // Right, close brace lines up with open brace
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item {\bf Infinite Loops}.
|
||||
Any loop intended to be infinite (of course with a {\tt break} statement
|
||||
somewhere) should be of the form:
|
||||
|
||||
\begin{tt}
|
||||
while(true) \\
|
||||
{ // Loop until sentinel found\\
|
||||
...code here \\
|
||||
}
|
||||
\end{tt}
|
||||
|
||||
\item {\bf {\tt SWITCH} Statements}.
|
||||
The open curly brace for a {\tt switch} statement will be on the same
|
||||
line as the {\tt switch} statement itself. Each {\tt case} statement
|
||||
following is indented two columns from the switch statement. Each
|
||||
statement in the {\tt case} block is indented two column from the
|
||||
{\tt case} statement. The closing curly brace is on a separate line
|
||||
by itself, indented two columns from the {\tt switch} statement.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\= \kill
|
||||
switch(someCondition) \{ Right, open brace on same line as switch\\
|
||||
\>case 0 : // Right, case indented two columns from switch\\
|
||||
\>\>i = k; // Right, statements indented two columns from case \\
|
||||
\>\>k = i + 2;\\
|
||||
\>\>break;\\
|
||||
\>case 1 : // Right, case indented two columns from switch\\
|
||||
\>\>i = k + 2; // Right, statements indented two columns from case \\
|
||||
\>\>k = i + 4;\\
|
||||
\>\>break;\\
|
||||
\>\} // Right, close brace lines up with case statements
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item {\bf Functions}. Since C and C++ do not allow nested functions,
|
||||
all functions start with no indentation at column 0. The open curly
|
||||
brace is on a line by itself immediately following the function header
|
||||
and formal parameters, also in column 0.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
aa\=aa\=aa\=aa\= \kill
|
||||
void Function1(int arg1, double arg2)\\
|
||||
\{ // Right, curly brace at column 0\\
|
||||
\>int local1 = 0; // Right, local variable at column 2\\
|
||||
\>int local2;\\
|
||||
\>\\
|
||||
\>local2 = local1 + arg1 + arg2; // Right, indented two columns\\
|
||||
\>int local3; // Right, variable at same level\\
|
||||
\>local3 = Function2(local2);\\
|
||||
\>if (someCondition)\\
|
||||
\>\>\{\\
|
||||
\>\>\>local3 = 0;\\
|
||||
\>\>\>local2 = local1;\\
|
||||
\>\>\>int local4 = local1 + 1; // Right, variable at same level\\
|
||||
\>\>\>Function3(local4);\\
|
||||
\>\>\}\\
|
||||
\} // Right, close brace at column 0
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\item {\bf Expressions}. Spaces should be used liberally in expressions
|
||||
to increase readability. One space before and after each operator,
|
||||
excepting the increment and decrement operators, leads to easy--to--read
|
||||
expressions. Continued expressions should be indented as far as needed
|
||||
for neatness and readability.
|
||||
|
||||
Examples:
|
||||
|
||||
\begin{tt}
|
||||
i = k * 2 + 3 / var1++; // Right, spacing separating terms \\
|
||||
\end{tt}
|
||||
|
||||
\begin{tt}
|
||||
i = k*2+2/var1++; // Wrong, crowded together and hard to read
|
||||
\end{tt}
|
||||
|
||||
\begin{tt}
|
||||
\begin{tabbing}
|
||||
someLongVariableName = \=anotherLongVariableName * shorterName + \\
|
||||
\>anotherName; // Right, indented to line up
|
||||
\end{tabbing}
|
||||
\end{tt}
|
||||
|
||||
\end{enumerate}
|
||||
\subsection{Header Files}
|
||||
\begin{enumerate}
|
||||
\item All header files will have a file name ending with {\tt .h}.
|
||||
\item All header files should have a one line comment describing
|
||||
the purpose of the header, and comments identifying the
|
||||
author and the (approximate) date the file was created.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
// ns3 Network Simulator - TCP Base Class Declaration \\
|
||||
// George F. Riley. riley@ece.gatech.edu. \\
|
||||
// Georgia Tech, Fall 2006
|
||||
\end{tt}
|
||||
|
||||
\item All header files should have an ``include guard'' to prevent accidental
|
||||
inclusion of the file multiple times in a single compilation unit. The include
|
||||
guard should be named after the file name. If the file name is \code{foo-bar.h}, then the
|
||||
include guard should be named \code{FOO\_BAR\_H}
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
\#ifndef FOO\_BAR\_H \\
|
||||
\#define FOO\_BAR\_H \\
|
||||
|
||||
// (Contents of foo-bar.h here
|
||||
|
||||
\#endif
|
||||
\end{tt}
|
||||
\item Header files should avoid including other files whenever possible.
|
||||
This can often be avoided with judicious use of the
|
||||
{\tt class ClassName;} forward declaration.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
// excerpt from application.h \\
|
||||
class L4Protocol; \\
|
||||
|
||||
class Application \{ \\
|
||||
.... \\
|
||||
AddL4Proto(const L4Protocol\&); \\
|
||||
.... \\
|
||||
L4Protocol* l4Proto; \\
|
||||
\};
|
||||
\end{tt}
|
||||
|
||||
In the above example, the use of the forward declaration for {\tt L4Protocol}
|
||||
obviates the need to include {\tt l4proto.h} in the application header
|
||||
file.
|
||||
|
||||
\end{enumerate}
|
||||
\subsection{Source Code Files}
|
||||
\begin{enumerate}
|
||||
\item All souce code files will have a file name ending with {\tt .cc}.
|
||||
\item All source code files should have a one line comment describing
|
||||
the purpose of the code, and comments identifying the
|
||||
author and the (approximate) date the file was created.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
// ns3 Network Simulator - TCP Base Class Implementation \\
|
||||
// George F. Riley. riley@ece.gatech.edu. \\
|
||||
// Georgia Tech, Fall 2006
|
||||
\end{tt}
|
||||
|
||||
\item All {\tt \#include} directives should be grouped with {\em system}
|
||||
files listed first (eg. {\tt \#include <iostream>}), followed by
|
||||
\nst\ defined files (eg. {\tt \#include "tcp.h"}). Within a group,
|
||||
the includes should be sorted in alphabetical order.
|
||||
|
||||
Example:
|
||||
|
||||
\begin{tt}
|
||||
\#include <iostream> \\
|
||||
\#include <list> \\
|
||||
\#include <vector> \\
|
||||
|
||||
\#include "application.h" \\
|
||||
\#include "dumbbell.h" \\
|
||||
\#include "simulator.h" \\
|
||||
\#include "tcp.h.h"
|
||||
|
||||
\end{tt}
|
||||
\end{enumerate}
|
||||
\end{document}
|
||||
@@ -0,0 +1,210 @@
|
||||
The Ns-3 Coding Style
|
||||
|
||||
/*
|
||||
* Note: This file is incomplete and will be converted to non-text (html,pdf)
|
||||
* formats at a future date
|
||||
*/
|
||||
|
||||
1) Code layout
|
||||
-----------
|
||||
|
||||
The code layout follows the GNU coding standard layout for C and extends
|
||||
it to C++. Do not use tabs for indentation. Indentation spacing is 2
|
||||
spaces as outlined below:
|
||||
|
||||
void
|
||||
Foo (void)
|
||||
{
|
||||
if (test)
|
||||
{
|
||||
// do stuff here
|
||||
}
|
||||
else
|
||||
{
|
||||
// do other stuff here
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// do loop
|
||||
}
|
||||
|
||||
while (test)
|
||||
{
|
||||
// do while
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// do stuff
|
||||
} while ();
|
||||
}
|
||||
|
||||
The following is not recommended:
|
||||
|
||||
if (test) statement
|
||||
|
||||
if (test)
|
||||
statement
|
||||
|
||||
for (...) statement
|
||||
|
||||
Each statement should be put on a separate line to increase readability.
|
||||
Short one-line comments can use the C++ comment style, that is, '//'
|
||||
but longer comments should use C-style comments:
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
2) Naming Patterns
|
||||
---------------
|
||||
|
||||
2.1) Name encoding
|
||||
-------------
|
||||
Function, Method, and Type names should follow the CamelCase convention:
|
||||
words are joined without spaces and are capitalized. For example,
|
||||
"my computer" is transformed into MyComputer. Do not use all capital
|
||||
letters such as MAC or, PHY, but choose instead Mac or Phy. Do not use
|
||||
all capital letters, even for acronyms such as EDCA: use Edca instead.
|
||||
The goal of the CamelCase convention is to ensure that the words which
|
||||
make up a name can be separated by the eye: the initial Caps fills
|
||||
that role.
|
||||
|
||||
Variable names should follow a slight variation on the base CamelCase
|
||||
convention: camelBack. For example, the variable "user name" would be
|
||||
named "userName". This variation on the basic naming pattern is used to
|
||||
allow a reader to distinguish a variable name from its type. For example,
|
||||
"UserName userName;" would be used to declare a variable named userName
|
||||
of type UserName.
|
||||
|
||||
Global variables should be prefixed with a "g_" and member variables
|
||||
(including static member variables) should be prefixed with a "m_". The
|
||||
goal of that prefix is to give a reader a sense of where a variable of
|
||||
a given name is declared to allow the reader to locate the variable
|
||||
declaration and infer the variable type from that declaration. For example
|
||||
you could declare in your class header my-class.h:
|
||||
|
||||
class MyClass
|
||||
{
|
||||
void MyMethod (int aVar);
|
||||
int m_aVar;
|
||||
static int m_anotherVar;
|
||||
};
|
||||
|
||||
and implement in your class file my-class.cc:
|
||||
|
||||
int MyClass::m_anotherVar = 10;
|
||||
static int g_aStaticVar = 100;
|
||||
int g_aGlobalVar = 1000;
|
||||
|
||||
void
|
||||
MyClass::MyMethod (int aVar)
|
||||
{
|
||||
m_aVar = aVar;
|
||||
}
|
||||
|
||||
2.2) Choosing names
|
||||
|
||||
Variable, function, method, and type names should be based on the
|
||||
english language. Furthermore, always try to choose descriptive
|
||||
names for them. Types are often english names such as: Packet,
|
||||
Buffer, Mac, or Phy. Functions and Methods are often named
|
||||
based on verbs and adjectives: GetX, DoDispose, ClearArray, etc.
|
||||
|
||||
A long descriptive name which requires a lot of typing is always
|
||||
better than a short name which is hard to decipher. Do not use
|
||||
abbreviations in names unless the abbreviation is really unambiguous
|
||||
and obvious to everyone. Do not use short inapropriate names such
|
||||
as foo, bar, or baz. The name of an item should always match its
|
||||
purpose. As such, names such as tmp to identify a temporary
|
||||
variable or such as 'i' to identify a loop index are ok.
|
||||
|
||||
3) File layout and code organization
|
||||
---------------------------------
|
||||
|
||||
A class named MyClass should be declared in a header named my-class.h
|
||||
and implemented in a source file named my-class.cc. The goal of this
|
||||
naming pattern is to allow a reader to quickly navigate through
|
||||
the ns-3 codebase to locate the source file relevant to a specific
|
||||
type.
|
||||
|
||||
Each my-class.h header should start with the following comments: the
|
||||
first line ensures that developers who use the emacs editor will be
|
||||
able to indent your code correctly. The following lines ensure that
|
||||
your code is licensed under the GPL, that the copyright holders
|
||||
are properly identified (typically, you or your employer), and
|
||||
that the actual author of the code is identified. The latter is
|
||||
purely informational and we use it to try to track the most
|
||||
appropriate person to review a patch or fix a bug.
|
||||
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) YEAR COPYRIGHTHOLDER
|
||||
*
|
||||
* 3-paragran GPL blurb
|
||||
*
|
||||
* Author: MyName <myemail@foo.com>
|
||||
*/
|
||||
|
||||
Below these C-style comments, always include the following which
|
||||
defines a set of header guards (MY_CLASS_H) used to avoid multiple
|
||||
header includes, which ensures that your code is included
|
||||
in the "ns3" namespace and which provides a set of doxygen comments
|
||||
for the public part of your class API. Detailed information
|
||||
on the set of tags available for doxygen documentation is described
|
||||
in the doxygen website: http://www.doxygen.org.
|
||||
|
||||
#ifndef MY_CLASS_H
|
||||
#define MY_CLASS_H
|
||||
|
||||
namespace n3 {
|
||||
|
||||
/**
|
||||
* \brief short one-line description of the purpose of your class
|
||||
*
|
||||
* A longer description of the purpose of your class after a blank
|
||||
* empty line.
|
||||
*/
|
||||
class MyClass
|
||||
{
|
||||
public:
|
||||
MyClass ();
|
||||
/**
|
||||
* \param firstParam a short description of the purpose of this parameter
|
||||
* \returns a short description of what is returned from this function.
|
||||
*
|
||||
* A detailed description of the purpose of the method.
|
||||
*/
|
||||
int DoFoo (int firstParam);
|
||||
private:
|
||||
void MyPrivateMethod (void);
|
||||
int m_myPrivateMemberVariable;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* MY_CLASS_H */
|
||||
|
||||
The my-class.cc file is structured similarly:
|
||||
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) YEAR COPYRIGHTHOLDER
|
||||
*
|
||||
* 3-paragran GPL blurb
|
||||
*
|
||||
* Author: MyName <myemail@foo.com>
|
||||
*/
|
||||
#include "my-class.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
MyClass::MyClass ()
|
||||
{}
|
||||
|
||||
...
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
Contributing to the ns-3 project
|
||||
--------------------------------
|
||||
|
||||
ns-3 is an open source project backed by an NSF CISE CRI grant.
|
||||
Although the NSF PIs have specific aims to fulfill, we want others to
|
||||
contribute, and we'd like to have a broad community of users and
|
||||
developers, with the goal of a self-sustaining project downstream.
|
||||
The project is currently in a bootstrapping phase, but we welcome
|
||||
ambitious developers who might want to help shape the early design.
|
||||
|
||||
Despite the lack of a formal contribution process to the ns-3
|
||||
project, there are a number of steps which we expect every
|
||||
potential contributor to follow. These naturally stem from
|
||||
the open-source roots of the project:
|
||||
|
||||
- first, you should subscribe to the ns-developers
|
||||
mailing-list (see http://www.nsnam.org/mailing_lists.html)
|
||||
|
||||
- then, you should send an email there stating your interest
|
||||
in working on a specific part of the models and trying
|
||||
to explain how you would like to implement it, what
|
||||
resources you have, etc.
|
||||
|
||||
- you should be prepared to work together with the other
|
||||
potential contributors who want to work on the same models.
|
||||
|
||||
- you should be prepared to go through code reviews with the
|
||||
ns-3 development team prior to integration. The goal of these
|
||||
code reviews is to:
|
||||
- ensure adherence to the coding style of the project
|
||||
(see doc/codingstyle.html)
|
||||
- ensure that the structure of your code has a certain
|
||||
coherence with regard to the rest of the ns-3 codebase
|
||||
- improve the quality of the code: we strongly believe in
|
||||
the old saying: "many eyes make all bugs shallow".
|
||||
- increase code reuse by trying to generalize certain
|
||||
useful pieces of your code to make them available to
|
||||
other models.
|
||||
|
||||
- you should be prepared to try to integrate as many tests
|
||||
in the codebase as possible: we understand that writing
|
||||
tests is not sexy and that not everyone is convinced that
|
||||
they improve the code-writing poductivity which is why
|
||||
we do not enforce strict rules about testing. However,
|
||||
we expect model authors to answer basic questions about
|
||||
how they plan to test and validate their models.
|
||||
|
||||
- you should be prepared to maintain your model once it is
|
||||
integrated: while we consider every bug filed against the
|
||||
simulator as being a bug we must deal with and while we
|
||||
will try to fix as many bugs as humanly possible, we
|
||||
also expect model authors to act as responsible maintainers
|
||||
and be reactive to bug reports concerning their models.
|
||||
|
||||
- The project has decided upon GNU GPLv2 as the licensing structure.
|
||||
All simulation software in the ns-3 repositories will be GNU GPLv2
|
||||
or GNU GPLv2-compatible (with non-GPLv2 licensing reserved for
|
||||
ports of pre-existing code under a different license, such as BSD).
|
||||
You do not have to assign your copyright to the ns-3 project but
|
||||
you must accept the terms of the GPLv2 and attest that your
|
||||
contributions can be licensed under those terms. See the
|
||||
following link:
|
||||
http://www.fsf.org/licensing/licenses/info/GPLv2.html
|
||||
+158
-65
@@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.4.4
|
||||
# Doxyfile 1.5.4
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project
|
||||
@@ -14,10 +14,18 @@
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# This tag specifies the encoding used for all characters in the config file that
|
||||
# follow. The default is UTF-8 which is also the encoding used for all text before
|
||||
# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
|
||||
# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
|
||||
# possible encodings.
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
|
||||
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
|
||||
# by quotes) that should identify the project.
|
||||
|
||||
PROJECT_NAME = "NS-3"
|
||||
PROJECT_NAME = "NS-3 "
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
|
||||
# This could be handy for archiving the generated documentation or
|
||||
@@ -45,24 +53,14 @@ CREATE_SUBDIRS = NO
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all constant output in the proper language.
|
||||
# The default language is English, other supported languages are:
|
||||
# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
|
||||
# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
|
||||
# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
|
||||
# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
|
||||
# Swedish, and Ukrainian.
|
||||
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
|
||||
# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
|
||||
# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
|
||||
# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
|
||||
# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# This tag can be used to specify the encoding used in the generated output.
|
||||
# The encoding is not always determined by the language that is chosen,
|
||||
# but also whether or not the output is meant for Windows or non-Windows users.
|
||||
# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
|
||||
# forces the Windows encoding (this is the default for the Windows binary),
|
||||
# whereas setting the tag to NO uses a Unix-style encoding (the default for
|
||||
# all platforms other than Windows).
|
||||
|
||||
USE_WINDOWS_ENCODING = NO
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
|
||||
# include brief member descriptions after the members that are listed in
|
||||
# the file and class documentation (similar to JavaDoc).
|
||||
@@ -135,11 +133,19 @@ SHORT_NAMES = NO
|
||||
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
|
||||
# will interpret the first line (until the first dot) of a JavaDoc-style
|
||||
# comment as the brief description. If set to NO, the JavaDoc
|
||||
# comments will behave just like the Qt-style comments (thus requiring an
|
||||
# explicit @brief command for a brief description.
|
||||
# comments will behave just like regular Qt-style comments
|
||||
# (thus requiring an explicit @brief command for a brief description.)
|
||||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
|
||||
# interpret the first line (until the first dot) of a Qt-style
|
||||
# comment as the brief description. If set to NO, the comments
|
||||
# will behave just like regular Qt-style comments (thus requiring
|
||||
# an explicit \brief command for a brief description.)
|
||||
|
||||
QT_AUTOBRIEF = NO
|
||||
|
||||
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
|
||||
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
|
||||
# comments) as a brief description. This used to be the default behaviour.
|
||||
@@ -161,13 +167,6 @@ DETAILS_AT_TOP = NO
|
||||
|
||||
INHERIT_DOCS = YES
|
||||
|
||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
||||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
|
||||
# a new page for each member. If set to NO, the documentation of a member will
|
||||
# be part of the file/class/namespace that contains it.
|
||||
@@ -195,13 +194,40 @@ ALIASES =
|
||||
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
|
||||
# only. Doxygen will then generate output that is more tailored for Java.
|
||||
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
|
||||
# sources only. Doxygen will then generate output that is more tailored for Java.
|
||||
# For instance, namespaces will be presented as packages, qualified scopes
|
||||
# will look different, etc.
|
||||
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
|
||||
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
|
||||
# include (a tag file for) the STL sources as input, then you should
|
||||
# set this tag to YES in order to let doxygen match functions declarations and
|
||||
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
|
||||
# func(std::string) {}). This also make the inheritance and collaboration
|
||||
# diagrams that involve STL classes more complete and accurate.
|
||||
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
|
||||
# If you use Microsoft's C++/CLI language, you should set this option to YES to
|
||||
# enable parsing support.
|
||||
|
||||
CPP_CLI_SUPPORT = NO
|
||||
|
||||
# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
|
||||
# Doxygen will parse them like normal C++ but will assume all classes use public
|
||||
# instead of private inheritance when no explicit protection keyword is present.
|
||||
|
||||
SIP_SUPPORT = NO
|
||||
|
||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
||||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
|
||||
# the same type (for instance a group of public functions) to be put as a
|
||||
# subgroup of that type (e.g. under the Public Functions section). Set it to
|
||||
@@ -210,6 +236,16 @@ OPTIMIZE_OUTPUT_JAVA = NO
|
||||
|
||||
SUBGROUPING = YES
|
||||
|
||||
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is
|
||||
# documented as struct with the name of the typedef. So
|
||||
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
|
||||
# with name TypeT. When disabled the typedef will appear as a member of a file,
|
||||
# namespace, or class. And the struct will be named TypeS. This can typically
|
||||
# be useful for C code where the coding convention is that all structs are
|
||||
# typedef'ed and only the typedef is referenced never the struct's name.
|
||||
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -244,6 +280,13 @@ EXTRACT_LOCAL_CLASSES = NO
|
||||
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
|
||||
# If this flag is set to YES, the members of anonymous namespaces will be extracted
|
||||
# and appear in the documentation as a namespace called 'anonymous_namespace{file}',
|
||||
# where file will be replaced with the base name of the file that contains the anonymous
|
||||
# namespace. By default anonymous namespace are hidden.
|
||||
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
|
||||
# undocumented members of documented classes, files or namespaces.
|
||||
# If set to NO (the default) these members will be included in the
|
||||
@@ -376,7 +419,7 @@ SHOW_USED_FILES = YES
|
||||
|
||||
# If the sources in your project are distributed over multiple directories
|
||||
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
|
||||
# in the documentation. The default is YES.
|
||||
# in the documentation. The default is NO.
|
||||
|
||||
SHOW_DIRECTORIES = NO
|
||||
|
||||
@@ -385,7 +428,7 @@ SHOW_DIRECTORIES = NO
|
||||
# version control system). Doxygen will invoke the program by executing (via
|
||||
# popen()) the command <command> <input-file>, where <command> is the value of
|
||||
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
|
||||
# provided by doxygen. Whatever the progam writes to standard output
|
||||
# provided by doxygen. Whatever the program writes to standard output
|
||||
# is used as the file version. See the manual for examples.
|
||||
|
||||
FILE_VERSION_FILTER =
|
||||
@@ -397,7 +440,7 @@ FILE_VERSION_FILTER =
|
||||
# The QUIET tag can be used to turn on/off the messages that are generated
|
||||
# by doxygen. Possible values are YES and NO. If left blank NO is used.
|
||||
|
||||
QUIET = NO
|
||||
QUIET = YES
|
||||
|
||||
# The WARNINGS tag can be used to turn on/off the warning messages that are
|
||||
# generated by doxygen. Possible values are YES and NO. If left blank
|
||||
@@ -433,7 +476,7 @@ WARN_NO_PARAMDOC = NO
|
||||
# $version, which will be replaced by the version of the file (if it could
|
||||
# be obtained via FILE_VERSION_FILTER)
|
||||
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_FORMAT = "$file:$line: $text "
|
||||
|
||||
# The WARN_LOGFILE tag can be used to specify a file to which warning
|
||||
# and error messages should be written. If left blank the output is written
|
||||
@@ -450,16 +493,28 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = src doc/main.txt
|
||||
INPUT = doc/modules \
|
||||
doc/main.h \
|
||||
doc/introspected-doxygen.h \
|
||||
doc/howtos/ \
|
||||
src
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files that
|
||||
# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
|
||||
# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
|
||||
# See http://www.gnu.org/software/libiconv for the list of possible encodings.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank the following patterns are tested:
|
||||
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
|
||||
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
|
||||
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
|
||||
|
||||
FILE_PATTERNS = *.h *.tcc
|
||||
FILE_PATTERNS = *.h \
|
||||
*.tcc
|
||||
|
||||
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
|
||||
# should be searched for input files as well. Possible values are YES and NO.
|
||||
@@ -471,10 +526,12 @@ RECURSIVE = YES
|
||||
# excluded from the INPUT source files. This way you can easily exclude a
|
||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||
|
||||
EXCLUDE = \
|
||||
src/simulator/high-precision.h \
|
||||
src/simulator/high-precision-128.h \
|
||||
src/simulator/high-precision-double.h
|
||||
EXCLUDE = src/routing/olsr/olsr-state.h \
|
||||
src/routing/olsr/repositories.h \
|
||||
src/routing/olsr/routing-table.h \
|
||||
src/simulator/high-precision.h \
|
||||
src/simulator/high-precision-128.h \
|
||||
src/simulator/high-precision-double.h
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
||||
# directories that are symbolic links (a Unix filesystem feature) are excluded
|
||||
@@ -490,6 +547,13 @@ EXCLUDE_SYMLINKS = NO
|
||||
|
||||
EXCLUDE_PATTERNS =
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the output.
|
||||
# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
|
||||
# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
|
||||
|
||||
EXCLUDE_SYMBOLS =
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
@@ -514,7 +578,7 @@ EXAMPLE_RECURSIVE = NO
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
IMAGE_PATH = doc
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
@@ -548,7 +612,9 @@ FILTER_SOURCE_FILES = NO
|
||||
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
|
||||
# be generated. Documented entities will be cross-referenced with these sources.
|
||||
# Note: To get rid of all source code in the generated output, make sure also
|
||||
# VERBATIM_HEADERS is set to NO.
|
||||
# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH
|
||||
# then you must also enable this option. If you don't then doxygen will produce
|
||||
# a warning and turn it on anyway
|
||||
|
||||
SOURCE_BROWSER = NO
|
||||
|
||||
@@ -575,6 +641,13 @@ REFERENCED_BY_RELATION = YES
|
||||
|
||||
REFERENCES_RELATION = YES
|
||||
|
||||
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
|
||||
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
|
||||
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
|
||||
# link to the source code. Otherwise they will link to the documentstion.
|
||||
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
|
||||
# If the USE_HTAGS tag is set to YES then the references to source code
|
||||
# will point to the HTML generated by the htags(1) tool instead of doxygen
|
||||
# built-in source browser. The htags tool is part of GNU's global source
|
||||
@@ -667,6 +740,14 @@ HTML_ALIGN_MEMBERS = YES
|
||||
|
||||
GENERATE_HTMLHELP = NO
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
# page has loaded. For this to work a browser that supports
|
||||
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
|
||||
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
|
||||
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
|
||||
# be used to specify the file name of the resulting .chm file. You
|
||||
# can add a path in front of the file if the result should not be
|
||||
@@ -965,13 +1046,13 @@ ENABLE_PREPROCESSING = YES
|
||||
# compilation will be performed. Macro expansion can be done in a controlled
|
||||
# way by setting EXPAND_ONLY_PREDEF to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
MACRO_EXPANSION = YES
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
|
||||
# then the macro expansion is limited to the macros specified with the
|
||||
# PREDEFINED and EXPAND_AS_PREDEFINED tags.
|
||||
# PREDEFINED and EXPAND_AS_DEFINED tags.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
|
||||
# in the INCLUDE_PATH (see below) will be search if a #include is found.
|
||||
@@ -999,14 +1080,18 @@ INCLUDE_FILE_PATTERNS =
|
||||
# undefined via #undef or recursively expanded use the := operator
|
||||
# instead of the = operator.
|
||||
|
||||
PREDEFINED = RUN_SELF_TESTS NS3_DEBUG_ENABLE
|
||||
PREDEFINED = RUN_SELF_TESTS \
|
||||
NS3_ASSERT_ENABLE \
|
||||
NS3_LOG_ENABLE
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
# The macro definition that is found in the sources will be used.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition.
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
EXPAND_AS_DEFINED = ATTRIBUTE_VALUE_DEFINE \
|
||||
ATTRIBUTE_VALUE_DEFINE_WITH_NAME \
|
||||
ATTRIBUTE_HELPER_HEADER_2
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
|
||||
# doxygen's preprocessor will remove all function-like macros that are alone
|
||||
@@ -1072,6 +1157,14 @@ PERL_PATH = /usr/bin/perl
|
||||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
|
||||
# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
|
||||
# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
|
||||
# be found in the default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# If set to YES, the inheritance and collaboration graphs will hide
|
||||
# inheritance and usage relations if the target is undocumented
|
||||
# or is not a class.
|
||||
@@ -1129,7 +1222,7 @@ INCLUDE_GRAPH = YES
|
||||
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
|
||||
# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
|
||||
# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
|
||||
# generate a call dependency graph for every global function or class method.
|
||||
# Note that enabling this option will significantly increase the time of a run.
|
||||
# So in most cases it will be better to enable call graphs for selected
|
||||
@@ -1137,6 +1230,14 @@ INCLUDED_BY_GRAPH = YES
|
||||
|
||||
CALL_GRAPH = NO
|
||||
|
||||
# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
|
||||
# generate a caller dependency graph for every global function or class method.
|
||||
# Note that enabling this option will significantly increase the time of a run.
|
||||
# So in most cases it will be better to enable caller graphs for selected
|
||||
# functions only using the \callergraph command.
|
||||
|
||||
CALLER_GRAPH = NO
|
||||
|
||||
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
|
||||
# will graphical hierarchy of all classes instead of a textual one.
|
||||
|
||||
@@ -1166,31 +1267,23 @@ DOT_PATH =
|
||||
|
||||
DOTFILE_DIRS =
|
||||
|
||||
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
|
||||
# nodes that will be shown in the graph. If the number of nodes in a graph
|
||||
# becomes larger than this value, doxygen will truncate the graph, which is
|
||||
# visualized by representing a node as a red box. Note that doxygen if the number
|
||||
# of direct children of the root node in a graph is already larger than
|
||||
# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
|
||||
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
|
||||
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
|
||||
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
|
||||
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
|
||||
# graphs generated by dot. A depth value of 3 means that only nodes reachable
|
||||
# from the root by following a path via at most 3 edges will be shown. Nodes
|
||||
# that lay further from the root node will be omitted. Note that setting this
|
||||
# option to 1 or 2 may greatly reduce the computation time needed for large
|
||||
# code bases. Also note that a graph may be further truncated if the graph's
|
||||
# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
|
||||
# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
|
||||
# the graph is not depth-constrained.
|
||||
# code bases. Also note that the size of a graph can be further restricted by
|
||||
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
|
||||
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*!
|
||||
\page callbacks Using ns-3 callbacks
|
||||
\anchor howtos-callbacks
|
||||
|
||||
\section null_callbacks Null Callbacks
|
||||
|
||||
<b>Question:</b> The API I am using calls for using a callback (in the
|
||||
function signature), but I do not
|
||||
want to provide one. Is there a way to provide a null callback?
|
||||
|
||||
<b>Answer:</b> Use the ns3::MakeNullCallback construct:
|
||||
\code
|
||||
template<typename R>
|
||||
Callback< R, T1, T2, T3, T4, T5, T6 > ns3::MakeNullCallback (void)
|
||||
\endcode
|
||||
|
||||
Example usage: The ns3::Socket class uses callbacks to indicate completion
|
||||
of events such as a successful TCP connect(). These callbacks are set
|
||||
in the following function:
|
||||
\code
|
||||
void Socket::SetConnectCallback (Callback<void, Ptr<Socket> > connectionSucceeded,
|
||||
Callback<void, Ptr<Socket> > connectionFailed,
|
||||
Callback<void, Ptr<Socket> > halfClose);
|
||||
|
||||
\endcode
|
||||
But suppose you do not care about registering a callback for the
|
||||
halfClose event (but you want to register one for the
|
||||
connectionSucceeded and connectionFailed cases). In that case, you
|
||||
can pass a null callback as the third argument. You just need to
|
||||
pass a callback with the matching signature, as follows:
|
||||
\code
|
||||
localSocket->SetConnectCallback (
|
||||
MakeCallback (&ConnectionSucceededCallback),
|
||||
MakeCallback (&ConnectionFailedCallback),
|
||||
MakeNullCallback<void, Ptr<Socket> > () );
|
||||
\endcode
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,17 @@
|
||||
/*!
|
||||
\page howtos ns-3 HOWTOs
|
||||
\anchor howtos-anchor
|
||||
|
||||
This is an organized set of frequently asked questions (FAQ) and HOWTOs
|
||||
for ns-3. This complements the following wiki pages:
|
||||
|
||||
- <a href="http://www.nsnam.org/wiki/index.php/User_FAQ">User FAQ</a>
|
||||
- <a href="http://www.nsnam.org/wiki/index.php/Developer_FAQ">Developer FAQ</a>
|
||||
|
||||
Please consider contributing tips to either the wiki (yourself) or
|
||||
by submitting a patch to this maintained documentation.
|
||||
|
||||
- \subpage callbacks
|
||||
|
||||
*/
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* \mainpage ns-3 Documentation
|
||||
*
|
||||
* \section intro-sec Introduction
|
||||
* <a href="http://www.nsnam.org/">ns-3</a> documentation is maintained using
|
||||
* <a href="http://www.doxygen.org">Doxygen</a>.
|
||||
* Doxygen is typically used for
|
||||
* API documentation, and organizes such documentation across different
|
||||
* modules. This project uses Doxygen both for building the manual around
|
||||
* the API documentation, and a separate GNU texinfo document is used for
|
||||
* the manual.
|
||||
*
|
||||
* The ns-3 project documentation is organized as follows:
|
||||
* - <b><a href="modules.html">modules</a></b>: The "Modules" tab (above)
|
||||
* organizes all of the public API and supporting manual text
|
||||
* along the source code directory structure. This forms the
|
||||
* "ns-3 manual", and it is available in HTML and PDF forms.
|
||||
* - \ref howtos-anchor "HOWTOs": A set of HOWTOs and FAQs is
|
||||
* maintained on another Doxygen "Related Page"
|
||||
* - <a href="http://www.nsnam.org/docs/tutorial/tutorial.html">tutorial</a>: The ns-3 tutorial is a separate document maintained in <a href="http://www.gnu.org/software/texinfo/"> GNU Texinfo</a>.
|
||||
* - The <b><a href="http://www.nsnam.org/wiki/index.php/Main_Page">ns-3 wiki</a></b>
|
||||
* contains additional user-contributed material. Some wiki-contributed
|
||||
* material may migrate to and overlap with the Doxygen information.
|
||||
*
|
||||
* \section install-sec Building the Documentation
|
||||
*
|
||||
* ns-3 requires Doxygen version 1.5.4 or greater to fully build all items,
|
||||
* although earlier versions of Doxygen will mostly work.
|
||||
*
|
||||
* Type "./waf check" followed by "./waf --doxygen" to build the documentation.
|
||||
* There is a program that runs during "./waf check" that builds pieces of
|
||||
* the documentation through introspection. The doc/ directory contains
|
||||
* configuration for Doxygen (doxygen.conf and main.txt). The Doxygen
|
||||
* build process puts html files into the doc/html/ directory, and latex
|
||||
* filex into the doc/latex/ directory.
|
||||
*
|
||||
* \section module-sec Module overview
|
||||
*
|
||||
* The ns-3 library is split across multiple modules:
|
||||
* - core: located in src/core and contains a number of facilities which
|
||||
* do not depend on any other module. Some of these facilities are
|
||||
* OS-dependent.
|
||||
* - simulator: located in src/simulator and contains event scheduling
|
||||
* facilities.
|
||||
* - common: located in src/common and contains facilities specific
|
||||
* to network simulations but shared by pretty much every model
|
||||
* of a network component.
|
||||
* - node: located in src/node. Defines the abstract interfaces which
|
||||
* must be implemented by every node and more specifically, by ipv4 nodes.
|
||||
* - devices: located in src/devices. Contains a set of MAC-level models
|
||||
*
|
||||
* More detail can be found in the <b><a href="modules.html">Modules</a></b>
|
||||
* tab.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \namespace ns3
|
||||
* \brief Every class exported by the ns3 library is enclosed in the
|
||||
* ns3 namespace.
|
||||
*/
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* \mainpage An Introduction to ns-3
|
||||
*
|
||||
* The ns-3 library is split across multiple modules:
|
||||
* - core: located in src/core and contains a number of facilities which
|
||||
* do not depend on any other module. Some of these facilities are
|
||||
* OS-dependent.
|
||||
* - simulator: located in src/simulator and contains event scheduling
|
||||
* facilities.
|
||||
* - common: located in src/common and contains facilities specific
|
||||
* to network simulations but shared by pretty much every model
|
||||
* of a network component.
|
||||
* - node: located in src/node. Contains an ipv4/udp model.
|
||||
* - devices: located in src/devices. Contains a set of MAC-level models
|
||||
*
|
||||
* The "core" module contains:
|
||||
* - a Functor class: ns3::Callback
|
||||
* - an os-independent interface to get write-only access to a file: ns3::SystemFile
|
||||
* - an os-independent interface to get access to the elapsed wall clock time: ns3::SystemWallClockMs
|
||||
* - a class to register regression tests with the test manager: ns3::Test and ns3::TestManager
|
||||
* - debugging facilities: \ref debugging, \ref assert, \ref error
|
||||
* - \ref randomvariable
|
||||
* - a class to handle automatic deletion of multiple sets of objects of different types:
|
||||
* ns3::ObjectContainer
|
||||
*
|
||||
* The "simulator" module contains:
|
||||
* - a time management class to hold a time and convert between various time units: ns3::Time
|
||||
* - a scheduler base class used to implement new simulation event schedulers:
|
||||
* ns3::Scheduler and ns3::SchedulerFactory
|
||||
* - a simulator class used to create, schedule and cancel events: ns3::Simulator
|
||||
*
|
||||
* The "common" module contains:
|
||||
* - a packet class to create and manipulate simulation packets: ns3::Packet, ns3::Header,
|
||||
* and ns3::Trailer
|
||||
* - a set of low-level trace facilities: \ref lowleveltracing
|
||||
*
|
||||
* The "node" module contains:
|
||||
* - a ns3::Node base class and an ns3::InternetNode implementation which model
|
||||
* network nodes.
|
||||
* - a set of models contained in InternetNode: ns3::Ipv4, ns3::Udp, ns3::L3Demux,
|
||||
* ns3::L3Protocol, ns3::Ipv4L4Demux, ns3::Ipv4L4Protocol, ns3::Ipv4Interface,
|
||||
* ns3::DatagramSocket
|
||||
* - models which abstract the MAC-layer from the IP layer protocols:
|
||||
* ns3::NetDevice and ns3::Channel.
|
||||
* - an Arp model if the underlying NetDevice object needs it: ns3::ArpIpv4Interface
|
||||
* - a set of traffic generation models: ns3::OnOffApplication
|
||||
*
|
||||
* The "devices" module contains:
|
||||
* - a PointToPoint MAC device: ns3::PointToPointNetDevice, ns3::PointToPointChannel,
|
||||
* and ns3::PointToPointTopology.
|
||||
*/
|
||||
/**
|
||||
* \namespace ns3
|
||||
* \brief Every class exported by the ns3 library is enclosed in the
|
||||
* ns3 namespace.
|
||||
*/
|
||||
/**
|
||||
* \defgroup constants Constants
|
||||
* \brief Constants you can change
|
||||
*/
|
||||
@@ -0,0 +1,45 @@
|
||||
Introduction
|
||||
------------
|
||||
|
||||
ns-3 uses the Mercurial software revision control system which
|
||||
is a replacement for tools liks cvs or subversion. Thus, to get
|
||||
access to the development versions of ns-3, you need to install
|
||||
mercurial first. See http://www.selenic.com/mercurial/wiki/
|
||||
|
||||
Mercurial cheat sheet
|
||||
---------------------
|
||||
|
||||
Look at our project history and source code:
|
||||
-------------------------------------------
|
||||
http://code.nsnam.org/ns-3-dev
|
||||
|
||||
clone this repository:
|
||||
---------------------
|
||||
hg clone http://code.nsnam.org/ns-3-dev
|
||||
|
||||
commit locally:
|
||||
--------------
|
||||
hg status
|
||||
hg add <new files, if any>
|
||||
hg ci -m "message"
|
||||
|
||||
pull development tree changes to your local repository:
|
||||
------------------------------------------------------
|
||||
hg ci -m "my local changes are recorded"
|
||||
hg pull http://code.nsnam.org/ns-3-dev
|
||||
hg update (apply the changes) OR
|
||||
hg merge (if you've made local changes)
|
||||
|
||||
view the change log:
|
||||
-------------------
|
||||
hg log <file>
|
||||
|
||||
push upwards (developers access only):
|
||||
--------------------------------------
|
||||
To the main repository:
|
||||
hg push ssh://code@code.nsnam.org/repos/ns-3-dev
|
||||
|
||||
To your private repository:
|
||||
hg push ssh://username@code.nsnam.org//home/username/repositories/username/repository
|
||||
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @anchor modules_anchor
|
||||
*
|
||||
* @defgroup simulator Simulator
|
||||
* The "simulator" module contains:
|
||||
* - a time management class to hold a time and convert between various time units: ns3::Time
|
||||
* - a scheduler base class used to implement new simulation event schedulers:
|
||||
* ns3::Scheduler and ns3::SchedulerFactory
|
||||
* - a simulator class used to create, schedule and cancel events: ns3::Simulator
|
||||
*
|
||||
* @defgroup core Core
|
||||
* \brief The "core" module contains:
|
||||
* - a Functor class: ns3::Callback
|
||||
* - an os-independent interface to get access to the elapsed wall clock time: ns3::SystemWallClockMs
|
||||
* - a class to register regression tests with the test manager: ns3::Test and ns3::TestManager
|
||||
* - debugging facilities: \ref logging, \ref assert
|
||||
* - \ref randomvariable
|
||||
* - a base class for objects which need to support per-instance "attributes" and
|
||||
* trace sources: ns3::ObjectBase
|
||||
* - a base class for objects which need to support reference counting
|
||||
* and dynamic object aggregation: ns3::Object
|
||||
* - a smart-pointer class ns3::Ptr designed to work together with ns3::Object
|
||||
* - a configuration class used to set and control all attributes and trace sources
|
||||
* in a simulation: ns3::Config.
|
||||
*
|
||||
* @defgroup common Common
|
||||
* The "common" module contains:
|
||||
* - a packet class to create and manipulate simulation packets:
|
||||
* ns3::Packet, ns3::Header, and ns3::Trailer. This packet class
|
||||
* also supports per-packet ns3::Tag which are globs of data
|
||||
* which can be attached to any packet.
|
||||
*
|
||||
* @defgroup node Node
|
||||
* The "node" module contains:
|
||||
* - a ns3::Node base class which should be subclassed by any new type of
|
||||
* network Node.
|
||||
* - models which abstract the MAC-layer from the IP layer protocols:
|
||||
* ns3::NetDevice and ns3::Channel.
|
||||
* - models which abstract the application-layer API: ns3::Application,
|
||||
* ns3::Socket, ns3::SocketFactory, and, ns3::Udp
|
||||
*
|
||||
*
|
||||
* @defgroup devices Devices
|
||||
*
|
||||
* @defgroup internetNode InternetNode
|
||||
*
|
||||
* The "internet-node" module contains a set of classes which implement the
|
||||
* APIs defined in the "node" module:
|
||||
* - an Ipv4/Udp stack with socket support
|
||||
* - an ARP module
|
||||
* - an InternetNode class which is a Node subclass.
|
||||
*
|
||||
* @defgroup helper Helpers
|
||||
*
|
||||
* @defgroup applications Applications
|
||||
*
|
||||
* @defgroup mobility Mobility
|
||||
*
|
||||
* @defgroup routing Routing
|
||||
*
|
||||
* @defgroup constants Constants
|
||||
* @brief Constants you can change
|
||||
*
|
||||
* @defgroup contrib Contrib
|
||||
*/
|
||||
+1658
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -0,0 +1,50 @@
|
||||
Steps in doing an ns-3 release
|
||||
|
||||
0. check out a clean ns-3-dev somewhere
|
||||
1. prepare the source files
|
||||
- revise and check in AUTHORS, if needed
|
||||
- revise and check in RELEASE_NOTES
|
||||
- update and check in VERSION to the latest release number
|
||||
- confirm that Doxygen builds cleanly and without warnings
|
||||
(./waf check; ./waf --doxygen), and check in any necessary changes
|
||||
2. ./waf configure; ./waf dist
|
||||
- this will create a ns-3.0.x.tar.bz2 tarball
|
||||
- this will also create a ns-3.0.x-ref-traces.tar.bz2 tarball
|
||||
3. test tarball on release platforms (waf check and maybe some other scripts)
|
||||
4. once you are happy with the tarball, tag ns-3-dev with "release ns-3.0.X"
|
||||
- hg tag "release ns-3.0.x"
|
||||
- hg push
|
||||
5. clone the tagged ns-3-dev and place it on the repository
|
||||
- ssh code.nsnam.org; sudo tcsh; su code;
|
||||
- cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x
|
||||
- cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately:
|
||||
"description = ns-3.0.x release
|
||||
name = ns-3.0.x"
|
||||
6. Run the regression tests on the new release and update the reference traces
|
||||
- ./waf --regression
|
||||
- ./waf --valgrind --regression (for valgrind version)
|
||||
- There should be no regression errors at this time
|
||||
- tag ns-3-dev-ref-traces with "release ns-3.0.X"
|
||||
hg tag "release ns-3.0.x"
|
||||
hg push
|
||||
- clone the ns-3-dev-ref-traces and place it on the repository as in step
|
||||
5 but use the name ns-3.0.x-ref-traces
|
||||
7. Create a reference traces tarball
|
||||
- again, run "./waf dist"
|
||||
8. upload "ns-3.0.x.tar.bz2" to the /var/www/html/releases/ directory on
|
||||
the www.nsnam.org server
|
||||
- give it 644 file permissions, and user/group = apache
|
||||
9. upload "ns-3.0.x-ref-traces.tar.bz2" to the /var/www/html/releases/
|
||||
directory on the www.nsnam.org server
|
||||
- give it 644 file permissions, and user/group = apache
|
||||
10. update web pages on www.nsnam.org (source is in the www/ module)
|
||||
- add link to news.html
|
||||
- update getting_started.html
|
||||
- update documents.html
|
||||
- update roadmap on wiki
|
||||
- build and update Doxygen directory on the server
|
||||
-- ssh www.nsnam.org; sudo tcsh; su nsnam;
|
||||
-- edit ~/bin/update-doxygen-release file and change RELEASE variable
|
||||
to the right version number
|
||||
-- run ~/bin/update-doxygen-release
|
||||
11. announce to ns-developers, with summary of release notes
|
||||
@@ -0,0 +1,49 @@
|
||||
TEXI2HTML = texi2html
|
||||
TEXI2PDF = texi2dvi --pdf
|
||||
EPSTOPDF = epstopdf
|
||||
TGIF = tgif
|
||||
DIA = dia
|
||||
CONVERT = convert
|
||||
CSS = --css-include=tutorial.css
|
||||
SPLIT = --split section
|
||||
|
||||
DIA_SOURCES = buffer.dia pp.dia dumbbell.dia star.dia sockets-overview.dia
|
||||
TGIF_SOURCES = packet.obj helpers.obj
|
||||
|
||||
DIA_EPS = ${DIA_SOURCES:.dia=.eps}
|
||||
DIA_PNG = ${DIA_SOURCES:.dia=.png}
|
||||
DIA_PDF = ${DIA_SOURCES:.dia=.pdf}
|
||||
|
||||
TGIF_EPS = ${TGIF_SOURCES:.obj=.eps}
|
||||
TGIF_PNG = ${TGIF_SOURCES:.obj=.png}
|
||||
TGIF_PDF = ${TGIF_SOURCES:.obj=.pdf}
|
||||
|
||||
all: images html split-html pdf
|
||||
|
||||
# Note: tgif requires a valid x display to convert from .obj to .png.
|
||||
# If running this makefile on a remote console, the X virtual frame
|
||||
# buffer may be needed (xorg-x11-server-Xvfb) to provide a "fake"
|
||||
# display
|
||||
images:
|
||||
cd figures/; $(DIA) -t png $(DIA_SOURCES)
|
||||
cd figures/; $(DIA) -t eps $(DIA_SOURCES)
|
||||
cd figures/; $(foreach FILE,$(DIA_EPS),$(EPSTOPDF) $(FILE);)
|
||||
cd figures/; $(TGIF) -print -png $(TGIF_SOURCES)
|
||||
cd figures/; $(TGIF) -print -eps $(TGIF_SOURCES)
|
||||
cd figures/; $(foreach FILE,$(TGIF_EPS),$(EPSTOPDF) $(FILE);)
|
||||
|
||||
html: images
|
||||
$(TEXI2HTML) ${CSS} tutorial.texi
|
||||
|
||||
split-html: images
|
||||
$(TEXI2HTML) ${CSS} ${SPLIT} tutorial.texi
|
||||
|
||||
pdf: images
|
||||
$(TEXI2PDF) tutorial.texi
|
||||
|
||||
figures-clean:
|
||||
cd figures/; rm -rf $(DIA_EPS); rm -rf $(DIA_PNG); rm -rf $(DIA_PDF)
|
||||
cd figures/; rm -rf $(TGIF_EPS); rm -rf $(TGIF_PNG); rm -rf $(TGIF_PDF)
|
||||
|
||||
clean: figures-clean
|
||||
rm -rf tutorial.aux tutorial.cp tutorial.cps tutorial.fn tutorial.ky tutorial.pg tutorial.tp tutorial.vr tutorial.toc tutorial.log tutorial.pdf tutorial.html tutorial/
|
||||
@@ -0,0 +1,535 @@
|
||||
@node ns-3 Attributes
|
||||
@chapter ns-3 Attributes
|
||||
@anchor{chap:Attributes}
|
||||
|
||||
In ns-3 simulations, there are two main aspects to configuration:
|
||||
@itemize @bullet
|
||||
@item the simulation topology and how objects are connected
|
||||
@item the values used by the models instantiated in the topology
|
||||
@end itemize
|
||||
|
||||
This chapter focuses on the second item above: how the many values
|
||||
in use in ns-3 are organized, documented, and modifiable by ns-3 users.
|
||||
The ns-3 attribute system is also the underpinning of how traces
|
||||
and statistics are gathered in the simulator.
|
||||
|
||||
Before delving into details of the attribute value system,
|
||||
it will help to review some basic properties of @code{class ns3::Object}.
|
||||
|
||||
@node Object Overview
|
||||
@section Object Overview
|
||||
|
||||
ns-3 is fundamentally a C++ object-based system. By this we mean that
|
||||
new C++ classes (types) can be declared, defined, and subclassed
|
||||
as usual.
|
||||
|
||||
Many ns-3 objects inherit from the @code{ns3::Object} base class. These
|
||||
objects have some additional properties that we exploit for
|
||||
organizing the system and improving the memory management
|
||||
of our objects:
|
||||
|
||||
@itemize @bullet
|
||||
@item a "metadata" system that links the class name to a lot of
|
||||
meta-information about the object, including the base class of the subclass,
|
||||
the set of accessible constructors in the subclass, and the set of
|
||||
"attributes" of the subclass
|
||||
@item a reference counting smart pointer implementation, for memory
|
||||
management.
|
||||
@end itemize
|
||||
|
||||
ns-3 objects that use the attribute system derive from either
|
||||
@code{ns3::Object} or @code{ns3::ObjectBase}. Most ns-3 objects
|
||||
we will discuss derive from @code{ns3::Object}, but a few that
|
||||
are outside the smart pointer memory management framework derive
|
||||
from @code{ns3::ObjectBase}.
|
||||
|
||||
Let's review a couple of properties of these objects.
|
||||
|
||||
@node Smart pointers
|
||||
@subsection Smart pointers
|
||||
|
||||
As introduced above in @ref{Smart Pointers 101}, ns-3 objects
|
||||
are memory managed by a
|
||||
@uref{http://en.wikipedia.org/wiki/Smart_pointer,,reference counting smart pointer implementation}, @code{class ns3::Ptr}.
|
||||
|
||||
Smart pointers are used extensively in the ns-3 APIs, to avoid passing
|
||||
references to heap-allocated objects that may cause memory leaks.
|
||||
For most basic usage (syntax), treat a smart pointer like a regular pointer:
|
||||
@verbatim
|
||||
Ptr<WifiNetDevice> nd = ...;
|
||||
nd->CallSomeFunction ();
|
||||
// etc.
|
||||
@end verbatim
|
||||
|
||||
@node CreateObject
|
||||
@subsection CreateObject
|
||||
|
||||
As we discussed above in @ref{Object Creation},
|
||||
at the lowest-level API, objects of type @code{ns3::Object} are
|
||||
not instantiated using @code{operator new} as usual but instead by
|
||||
a templated function called @code{CreateObject()}.
|
||||
|
||||
A typical way to create such an object is as follows:
|
||||
@verbatim
|
||||
Ptr<WifiNetDevice> nd = CreateObject<WifiNetDevice> ();
|
||||
@end verbatim
|
||||
|
||||
You can think of this as being functionally equivalent to:
|
||||
@verbatim
|
||||
WifiNetDevice* nd = new WifiNetDevice ();
|
||||
@end verbatim
|
||||
|
||||
Objects that derive from @code{ns3::Object} must be allocated
|
||||
on the heap using CreateObject(). Those deriving from
|
||||
@code{ns3::ObjectBase}, such as ns-3 helper functions and packet
|
||||
headers and trailers, can be allocated on the stack.
|
||||
|
||||
In some scripts, you may not see a lot of CreateObject() calls
|
||||
in the code;
|
||||
this is because there are some helper objects in effect that
|
||||
are doing the CreateObject()s for you.
|
||||
|
||||
@node TypeId
|
||||
@subsection TypeId
|
||||
|
||||
ns-3 classes that derive from class ns3::Object can include
|
||||
a metadata class called @code{TypeId} that records meta-information
|
||||
about the class, for use in the object aggregation and component
|
||||
manager systems:
|
||||
@itemize @bullet
|
||||
@item a unique string identifying the class
|
||||
@item the base class of the subclass, within the metadata system
|
||||
@item the set of accessible constructors in the subclass
|
||||
@end itemize
|
||||
|
||||
@node Object Summary
|
||||
@subsection Object Summary
|
||||
|
||||
Putting all of these concepts together, let's look at a specific
|
||||
example: @code{class ns3::Node}.
|
||||
|
||||
The public header file node.h has a declaration that includes
|
||||
a static GetTypeId function call:
|
||||
@verbatim
|
||||
class Node : public Object
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
...
|
||||
@end verbatim
|
||||
|
||||
This is defined in the node.cc file as follows:
|
||||
@verbatim
|
||||
TypeId
|
||||
Node::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Node")
|
||||
.SetParent<Object> ()
|
||||
return tid;
|
||||
}
|
||||
@end verbatim
|
||||
Finally, when users want to create Nodes, they call:
|
||||
@verbatim
|
||||
Ptr<Node> n = CreateObject<Node> n;
|
||||
@end verbatim
|
||||
|
||||
We next discuss how attributes (values associated with member variables
|
||||
or functions of the class) are plumbed into the above TypeId.
|
||||
|
||||
@node Attribute Overview
|
||||
@section Attribute Overview
|
||||
|
||||
The goal of the attribute system is to organize the access of
|
||||
internal member objects of a simulation. This goal arises because,
|
||||
typically in simulation, users will cut and paste/modify existing
|
||||
simulation scripts, or will use higher-level simulation constructs,
|
||||
but often will be interested in studying or tracing particular
|
||||
internal variables. For instance, use cases such as:
|
||||
@itemize @bullet
|
||||
@item "I want to trace the packets on the wireless interface only on
|
||||
the first access point"
|
||||
@item "I want to trace the value of the TCP congestion window (every
|
||||
time it changes) on a particular TCP socket"
|
||||
@item "I want a dump of all values that were used in my simulation."
|
||||
@end itemize
|
||||
|
||||
Similarly, users may want fine-grained access to internal
|
||||
variables in the simulation, or may want to broadly change the
|
||||
initial value used for a particular parameter in all subsequently
|
||||
created objects. Finally, users may wish to know what variables
|
||||
are settable and retrievable in a simulation configuration. This
|
||||
is not just for direct simulation interaction on the command line;
|
||||
consider also a (future) graphical user interface
|
||||
that would like to be able to provide a feature whereby a user
|
||||
might right-click on an node on the canvas and see a hierarchical,
|
||||
organized list of parameters that are settable on the node and its
|
||||
constituent member objects, and help text and default values for
|
||||
each parameter.
|
||||
|
||||
@node Functional overview
|
||||
@subsection Functional overview
|
||||
|
||||
We provide a way for users to access values deep in the system, without
|
||||
having to plumb accessors (pointers) through the system and walk
|
||||
pointer chains to get to them. Consider a class DropTailQueue that
|
||||
has a member variable that is an unsigned integer @code{m_maxPackets};
|
||||
this member variable controls the depth of the queue.
|
||||
|
||||
If we look at the declaration of DropTailQueue, we see the following:
|
||||
@verbatim
|
||||
class DropTailQueue : public Queue {
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
...
|
||||
|
||||
private:
|
||||
std::queue<Ptr<Packet> > m_packets;
|
||||
uint32_t m_maxPackets;
|
||||
};
|
||||
@end verbatim
|
||||
|
||||
Let's consider things that a user may want to do with the value of
|
||||
m_maxPackets:
|
||||
|
||||
@itemize @bullet
|
||||
@item Set a default value for the system, such that whenever a new
|
||||
DropTailQueue is created, this member is initialized to that default.
|
||||
@item Set or get the value on an already instantiated queue.
|
||||
@end itemize
|
||||
|
||||
The above things typically require providing Set() and Get() functions,
|
||||
and some type of global default value.
|
||||
|
||||
In the ns-3 attribute system, these value definitions and accessor
|
||||
functions are moved into the TypeId class; e.g.:
|
||||
@verbatim
|
||||
TypeId DropTailQueue::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::DropTailQueue")
|
||||
.SetParent<Queue> ()
|
||||
.AddConstructor<DropTailQueue> ()
|
||||
.AddAttribute ("MaxPackets", "The maximum number of packets accepted by this DropTailQueue.",
|
||||
Uinteger (100),
|
||||
MakeUintegerAccessor (&DropTailQueue::m_maxPackets),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
;
|
||||
|
||||
return tid;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
The AddAttribute() method is performing a number of things with this
|
||||
value:
|
||||
@itemize @bullet
|
||||
@item Binding the variable m_maxPackets to a string "MaxPackets"
|
||||
@item Providing a default value (100 packets)
|
||||
@item Providing some help text defining the value
|
||||
@item Providing a "checker" (not used in this example) that can be used to set
|
||||
bounds on the allowable range of values
|
||||
@end itemize
|
||||
|
||||
The key point is that now the value of this variable and its default
|
||||
value are accessible in the attribute namespace, which is based on
|
||||
strings such as "MaxPackets" and TypeId strings. In the next
|
||||
section, we will provide an example script that shows how users
|
||||
may manipulate these values.
|
||||
|
||||
@node Basic usage
|
||||
@subsection Basic usage
|
||||
|
||||
Let's look at how a user script might access these values.
|
||||
This is based on the script found at @code{samples/main-attribute-value.cc},
|
||||
with some details stripped out.
|
||||
@verbatim
|
||||
//
|
||||
// This is a basic example of how to use the attribute system to
|
||||
// set and get a value in the underlying system; namely, an unsigned
|
||||
// integer of the maximum number of packets in a queue
|
||||
//
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
|
||||
// By default, the MaxPackets attribute has a value of 100 packets
|
||||
// (this default can be observed in the function DropTailQueue::GetTypeId)
|
||||
//
|
||||
// Here, we set it to 80 packets. We could use one of two value types:
|
||||
// a string-based value or a Uinteger value
|
||||
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", String ("80"));
|
||||
// The below function call is redundant
|
||||
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", Uinteger(80));
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// SetDefaults() at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
@end verbatim
|
||||
|
||||
The main thing to notice in the above are the two calls to
|
||||
@code{Config::SetDefault}. This is how we set the default value
|
||||
for all subsequently instantiated DropTailQueues. We illustrate
|
||||
that two types of Value classes, a String and a Uinteger class,
|
||||
can be used to assign the value to the attribute named by
|
||||
"ns3::DropTailQueue::MaxPackets".
|
||||
|
||||
Now, we will create a few objects using the low-level API; here,
|
||||
our newly created queues will not have a m_maxPackets initialized to
|
||||
100 packets but to 80 packets, because of what we did above with
|
||||
default values.
|
||||
@verbatim
|
||||
Ptr<Node> n0 = CreateObject<Node> ();
|
||||
|
||||
Ptr<PointToPointNetDevice> net0 = CreateObject<PointToPointNetDevice> ();
|
||||
n0->AddDevice (net0);
|
||||
|
||||
Ptr<Queue> q = CreateObject<DropTailQueue> ();
|
||||
net0->AddQueue(q);
|
||||
@end verbatim
|
||||
|
||||
At this point, we have created a single node (Node 0) and a
|
||||
single PointToPointNetDevice (NetDevice 0) and added a
|
||||
DropTailQueue to it.
|
||||
|
||||
Now, we can manipulate the MaxPackets value of the already
|
||||
instantiated DropTailQueue. Here are various ways to do that.
|
||||
|
||||
@subsubsection Pointer-based access
|
||||
|
||||
We assume that a smart pointer (Ptr) to a relevant network device is
|
||||
in hand; here, it is the net0 pointer.
|
||||
|
||||
One way to change the value is to access a pointer to the
|
||||
underlying queue and modify its attribute.
|
||||
|
||||
First, we observe that we can get a pointer to the (base class)
|
||||
queue via the PointToPointNetDevice attributes, where it is called
|
||||
TxQueue
|
||||
@verbatim
|
||||
Ptr<Queue> txQueue = net0->GetAttribute ("TxQueue");
|
||||
@end verbatim
|
||||
|
||||
Using the GetObject function, we can perform a safe downcast
|
||||
to a DropTailQueue, where MaxPackets is a member
|
||||
@verbatim
|
||||
Ptr<DropTailQueue> dtq = txQueue->GetObject <DropTailQueue> ();
|
||||
NS_ASSERT (dtq);
|
||||
@end verbatim
|
||||
|
||||
Next, we can get the value of an attribute on this queue
|
||||
We have introduced wrapper "Value" classes for the underlying
|
||||
data types, similar to Java wrappers around these types, since
|
||||
the attribute system stores values and not disparate types.
|
||||
Here, the attribute value is assigned to a Uinteger, and
|
||||
the Get() method on this value produces the (unwrapped) uint32_t.
|
||||
@verbatim
|
||||
Uinteger limit = dtq->GetAttribute ("MaxPackets");
|
||||
NS_LOG_INFO ("1. dtq limit: " << limit.Get () << " packets");
|
||||
@end verbatim
|
||||
|
||||
Note that the above downcast is not really needed; we could have
|
||||
done the same using the Ptr<Queue> even though the attribute
|
||||
is a member of the subclass
|
||||
@verbatim
|
||||
limit = txQueue->GetAttribute ("MaxPackets");
|
||||
NS_LOG_INFO ("2. txQueue limit: " << limit.Get () << " packets");
|
||||
@end verbatim
|
||||
|
||||
Now, let's set it to another value (60 packets)
|
||||
@verbatim
|
||||
txQueue->SetAttribute("MaxPackets", Uinteger (60));
|
||||
limit = txQueue->GetAttribute ("MaxPackets");
|
||||
NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get () << " packets");
|
||||
@end verbatim
|
||||
|
||||
@subsubsection Namespace-based access
|
||||
|
||||
An alternative way to get at the attribute is to use the configuration
|
||||
namespace. Here, this attribute resides on a known path in this
|
||||
namespace; this approach is useful if one doesn't have access to
|
||||
the underlying pointers and would like to configure a specific
|
||||
attribute with a single statement.
|
||||
@verbatim
|
||||
Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets", Uinteger (25));
|
||||
limit = txQueue->GetAttribute ("MaxPackets");
|
||||
NS_LOG_INFO ("4. txQueue limit changed through namespace: " <<
|
||||
limit.Get () << " packets");
|
||||
@end verbatim
|
||||
|
||||
We could have also used wildcards to set this value for all nodes
|
||||
and all net devices (which in this simple example has the same
|
||||
effect as the previous Set())
|
||||
@verbatim
|
||||
Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets", Uinteger (15));
|
||||
limit = txQueue->GetAttribute ("MaxPackets");
|
||||
NS_LOG_INFO ("5. txQueue limit changed through wildcarded namespace: " <<
|
||||
limit.Get () << " packets");
|
||||
@end verbatim
|
||||
|
||||
@node Setting through constructors and helper classes
|
||||
@subsection Setting through constructors helper classes
|
||||
|
||||
Arbitrary combinations of attributes can be set and fetched from
|
||||
the helper and low-level APIs; either from the constructors themselves:
|
||||
@verbatim
|
||||
Ptr<Object> p = CreateObject<MyNewObject> ("n1", v1, "n2", v2, ...);
|
||||
@end verbatim
|
||||
or from the higher-level helper APIs, such as:
|
||||
@verbatim
|
||||
mobility.SetPositionAllocator ("GridPositionAllocator",
|
||||
"MinX", FpValue (-100.0),
|
||||
"MinY", FpValue (-100.0),
|
||||
"DeltaX", FpValue (5.0),
|
||||
"DeltaY", FpValue (20.0),
|
||||
"GridWidth", UintValue (20),
|
||||
"LayoutType", "RowFirst");
|
||||
@end verbatim
|
||||
|
||||
@node Value classes
|
||||
@subsection Value classes
|
||||
Readers will note the new Value classes. These can be thought of as
|
||||
an intermediate class that can be used to convert from raw types to the
|
||||
Values that are used by the system. Recall that this database is holding
|
||||
objects of many types with a single generic type. Conversions to this
|
||||
type can either be done using an intermediate class (IntValue, FpValue for
|
||||
"floating point") or via strings. Direct implicit conversion of types
|
||||
to Value is not really practical. So in the above, users have a choice
|
||||
of using strings or values:
|
||||
@verbatim
|
||||
p->Set ("cwnd", "100"); // string-based setter
|
||||
p->Set ("cwnd", IntValue(100)); // value-based setter
|
||||
@end verbatim
|
||||
|
||||
The system provides some macros that help users declare and define
|
||||
new Value subclasses for new types that they want to introduce into
|
||||
the attribute system.
|
||||
|
||||
@node Extending attributes
|
||||
@section Extending attributes
|
||||
|
||||
The ns-3 system will place a number of internal values under the
|
||||
attribute system, but undoubtedly users will want to extend this
|
||||
to pick up ones we have missed, or to add their own classes to this.
|
||||
|
||||
@subsection Adding an existing internal variable to the metadata system
|
||||
|
||||
// XXX revise me
|
||||
|
||||
Consider this variable in class TcpSocket:
|
||||
@verbatim
|
||||
uint32_t m_cWnd; // Congestion window
|
||||
@end verbatim
|
||||
|
||||
Suppose that someone working with Tcp wanted to get or set the
|
||||
value of that variable using the metadata system. If it were not
|
||||
already provided by ns-3, the user could declare the following addition
|
||||
in the metadata system (to the TypeId declaration for TcpSocket):
|
||||
@verbatim
|
||||
.AddParameter ("Congestion window",
|
||||
"Tcp congestion window (bytes)",
|
||||
MakeUIntParamSpec (&TcpSocket::m_cWnd, 1));
|
||||
|
||||
@end verbatim
|
||||
|
||||
Now, the user with a pointer to the TcpSocket can perform operations
|
||||
such as setting and getting the value, without having to add these
|
||||
functions explicitly. Furthermore, access controls can be applied, such
|
||||
as allowing the parameter to be read and not written, or bounds
|
||||
checking on the permissible values can be applied.
|
||||
|
||||
@subsection Adding a new TypeId
|
||||
|
||||
Here, we discuss the impact on a user who wants to add a new class to
|
||||
ns-3; what additional things must be done to hook it into this system.
|
||||
|
||||
We've already introduced what a TypeId definition looks like:
|
||||
@verbatim
|
||||
TypeId
|
||||
RandomWalk2dMobilityModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("RandomWalkMobilityModel")
|
||||
.SetParent<MobilityModel> ()
|
||||
.SetGroupName ("Mobility")
|
||||
.AddConstructor<RandomWalk2dMobilityModel> ()
|
||||
// followed by a number of Parameters
|
||||
.AddParameter ("bounds",
|
||||
"Bounds of the area to cruise.",
|
||||
MakeRectangleParamSpec (&RandomWalk2dMobilityModel::m_bounds, Rectangle (0.0, 0.0, 100.0, 100.0)))
|
||||
.AddParameter ("time",
|
||||
"Change current direction and speed after moving for this delay.",
|
||||
MakeTimeParamSpec (&RandomWalk2dMobilityModel::m_modeTime,
|
||||
Seconds (1.0)))
|
||||
|
||||
// etc (more parameters).
|
||||
@end verbatim
|
||||
|
||||
The declaration for this in the class declaration is one-line public
|
||||
member method:
|
||||
@verbatim
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
@end verbatim
|
||||
|
||||
@section Adding new class type to the Value system
|
||||
|
||||
From the perspective of the user who writes a new class in the system and
|
||||
wants to hook it in to the attribute system, there is mainly the matter
|
||||
of writing
|
||||
the conversions to/from strings and Values. Most of this can be
|
||||
copy/pasted with macro-ized code. For instance, consider class
|
||||
Rectangle in the @code{src/mobility/} directory:
|
||||
|
||||
One line is added to the class declaration:
|
||||
@verbatim
|
||||
/**
|
||||
* \brief a 2d rectangle
|
||||
*/
|
||||
class Rectangle
|
||||
{
|
||||
...
|
||||
|
||||
VALUE_HELPER_HEADER_1 (Rectangle);
|
||||
};
|
||||
@end verbatim
|
||||
|
||||
One templatized declaration, and two operators, are added below the
|
||||
class declaration:
|
||||
|
||||
@verbatim
|
||||
std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
|
||||
std::istream &operator >> (std::istream &is, Rectangle &rectangle);
|
||||
|
||||
VALUE_HELPER_HEADER_2 (Rectangle);
|
||||
@end verbatim
|
||||
|
||||
In the class definition, the code looks like this:
|
||||
|
||||
@verbatim
|
||||
VALUE_HELPER_CPP (Rectangle);
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream &os, const Rectangle &rectangle)
|
||||
{
|
||||
os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
|
||||
return os;
|
||||
}
|
||||
std::istream &
|
||||
operator >> (std::istream &is, Rectangle &rectangle)
|
||||
{
|
||||
char c1, c2, c3;
|
||||
is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 >> rectangle.yMax;
|
||||
if (c1 != '|' ||
|
||||
c2 != '|' ||
|
||||
c3 != '|')
|
||||
{
|
||||
is.setstate (std::ios_base::failbit);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
These stream operators simply convert from a string representation of the
|
||||
Rectangle ("xMin|xMax|yMin|yMax") to the underlying Rectangle, and the
|
||||
modeler must specify these operators and the string syntactical representation
|
||||
of an instance of the new class.
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
@node ns-3 Callbacks
|
||||
@chapter ns-3 Callbacks
|
||||
|
||||
Some new users to @command{ns-3} are unfamiliar with an extensively used
|
||||
programming idiom used throughout the code: the ``ns-3 callback''. This
|
||||
chapter provides some motivation on the callback, guidance on how to use
|
||||
it, and details on its implementation.
|
||||
|
||||
@menu
|
||||
* Motivation::
|
||||
* Using the Callback API::
|
||||
* Callback locations in ns-3::
|
||||
* Implementation details::
|
||||
@end menu
|
||||
|
||||
@node Motivation
|
||||
@section Motivation
|
||||
|
||||
Consider that you have two simulation models A and B, and you wish
|
||||
to have them pass information between them during the simulation. One
|
||||
way that you can do that is that you can make A and B each explicitly
|
||||
knowledgable about the other, so that they can invoke methods on each
|
||||
other.
|
||||
|
||||
@verbatim
|
||||
class A {
|
||||
public:
|
||||
void ReceiveInput ( // parameters );
|
||||
...
|
||||
}
|
||||
|
||||
(in another source file:)
|
||||
|
||||
class B {
|
||||
public:
|
||||
void ReceiveInput ( // parameters);
|
||||
void DoSomething (void);
|
||||
...
|
||||
|
||||
private:
|
||||
A* a_instance; // pointer to an A
|
||||
}
|
||||
|
||||
void
|
||||
B::DoSomething()
|
||||
{
|
||||
// Tell a_instance that something happened
|
||||
a_instance->ReceiveInput ( // parameters);
|
||||
...
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
This certainly works, but it has the drawback that it introduces a
|
||||
dependency on A and B to know about the other at compile time (this
|
||||
makes it harder to have independent compilation units in the simulator)
|
||||
and is not generalized; if in a later usage scenario, B needs to talk
|
||||
to a completely different C object, the source code for B needs to be
|
||||
changed to add a ``c_instance'' and so forth. It is easy to see that
|
||||
this is a brute force mechanism of communication that can lead to
|
||||
programming cruft in the models.
|
||||
|
||||
This is not to say that objects should not know about one another
|
||||
if there is a hard dependency between them, but that often the model
|
||||
can be made more flexible if its interactions are less constrained at
|
||||
compile time.
|
||||
|
||||
This is not an abstract problem for network simulation research,
|
||||
but rather it has been a source of problems in previous simulators,
|
||||
when researchers want to extend or modify the system to do different
|
||||
things (as they are apt to do in research). Consider, for example,
|
||||
a user who wants to add an IPsec security protocol sublayer
|
||||
between TCP and IP:
|
||||
@verbatim
|
||||
------------ -----------
|
||||
| TCP | | TCP |
|
||||
------------ -----------
|
||||
| becomes -> |
|
||||
----------- -----------
|
||||
| IP | | IPsec |
|
||||
----------- -----------
|
||||
|
|
||||
-----------
|
||||
| IP |
|
||||
-----------
|
||||
@end verbatim
|
||||
If the simulator has
|
||||
made assumptions, and hard coded into the code, that IP always talks
|
||||
to a transport protocol above, the user may be forced to hack the
|
||||
system to get the desired interconnections.
|
||||
|
||||
An alternative that provides this flexibility is to use a level of
|
||||
indirection that is commonly known in programming as a callback.
|
||||
A callback function is not invoked explicitly by the caller but is
|
||||
rather delegated to another function that receives the callback
|
||||
function's address and can call it.
|
||||
|
||||
You may be familiar with function pointers in C or C++; these can
|
||||
be used to implement callbacks. For more information on introductory
|
||||
callbacks, an online reference is:
|
||||
@uref{http://www.inquiry.com/techtips/cpp_pro/10min/10min0300.asp,,Declaring Function Pointers and Implementing Callbacks} and
|
||||
@uref{http://en.wikipedia.org/wiki/Callback_(computer_science),,Callback (computer science)-- Wikipedia}.
|
||||
|
||||
The callback API in @command{ns-3} is designed to minimize the overall
|
||||
coupling between various pieces of of the simulator
|
||||
by making each module depend on the callback API
|
||||
itself rather than depend on other modules. It acts as a sort of
|
||||
third-party to which work is delegated and which forwards this
|
||||
work to the proper target module. This callback API, being based
|
||||
on C++ templates,
|
||||
is type-safe; that is, it performs static type checks to enforce
|
||||
proper signature compatibility between callers and callees. It
|
||||
is therefore more type-safe to use than traditional function
|
||||
pointers, but the syntax may look imposing at first. This section
|
||||
is designed to walk you through the callback system so that you
|
||||
can be comfortable using it in @command{ns-3}.
|
||||
|
||||
@node Using the Callback API
|
||||
@section Using the Callback API
|
||||
|
||||
The Callback API is fairly minimal, providing only two services:
|
||||
@itemize @bullet
|
||||
@item callback type declaration: a way to declare a type of callback
|
||||
with a given signature, and,
|
||||
@item callback instantiation: a way to instantiate a
|
||||
template-generated forwarding callback which can forward any calls
|
||||
to another C++ class member method or C++ function.
|
||||
@end itemize
|
||||
|
||||
This is best observed via walking through an example, based on
|
||||
@code{samples/main-callback.cc}.
|
||||
|
||||
@node Using the Callback API with static functions
|
||||
@subsection Using the Callback API with static functions
|
||||
|
||||
Consider a function:
|
||||
@verbatim
|
||||
static double
|
||||
CbOne (double a, double b)
|
||||
{
|
||||
std::cout << "invoke cbOne a=" << a << ", b=" << b << std::endl;
|
||||
return a;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
Consider also the following main program snippett:
|
||||
@verbatim
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
// return type: double
|
||||
// first arg type: double
|
||||
// second arg type: double
|
||||
Callback<double, double, double> one;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
This class template Callback implements what is known as the Functor
|
||||
Design Pattern. It is used to declare the type of a callback. It contains
|
||||
one mandatory argument (the return type of the function to be assigned
|
||||
to this callback) and up to five optional arguments, which each specify
|
||||
the type of the arguments (if your function has more than five arguments,
|
||||
then this can be handled by extending the callback implementation).
|
||||
|
||||
So in the above, we have a declared a callback named "one" that will
|
||||
eventually hold a function pointer. The function that it will hold
|
||||
must return double and must support two double arguments. If one
|
||||
tries to pass a function whose signature does not match the declared
|
||||
callback, the compilation will fail.
|
||||
|
||||
Now, we need to tie together this callback instance and the actual
|
||||
target function (CbOne). Notice above that CbOne has the same function
|
||||
signature types as the callback-- this is important. We can
|
||||
pass in any such properly-typed function to this callback. Let's
|
||||
look at this more closely:
|
||||
@verbatim
|
||||
static double CbOne (double a, double b) {}
|
||||
^ ^ ^
|
||||
| ---| ------|
|
||||
| | |
|
||||
Callback<double, double, double> one;
|
||||
@end verbatim
|
||||
You can only bind a function to a callback if they have the matching
|
||||
signature. The first template argument is the return type, and the
|
||||
additional template arguments are the types of the arguments of
|
||||
the function signature.
|
||||
|
||||
Now, let's bind our callback "one" to the function that matches its
|
||||
signature:
|
||||
@verbatim
|
||||
// build callback instance which points to cbOne function
|
||||
one = MakeCallback (&CbOne);
|
||||
@end verbatim
|
||||
|
||||
Then, later in the program, if the callback is to be used, it can be
|
||||
used as follows:
|
||||
@verbatim
|
||||
// this is not a null callback
|
||||
NS_ASSERT (!one.IsNull ());
|
||||
// invoke cbOne function through callback instance
|
||||
double retOne;
|
||||
retOne = one (10.0, 20.0);
|
||||
@end verbatim
|
||||
|
||||
The check @code{IsNull()} ensures that the callback is not null; that there
|
||||
is a function to call behind this callback. Then, @code{one()} returns the
|
||||
same result as if @code{CbOne()} had been called directly.
|
||||
|
||||
|
||||
@node Using the Callback API with member functions
|
||||
@subsection Using the Callback API with member functions
|
||||
|
||||
Generally, you will not be calling static functions but instead
|
||||
public member functions of an object. In this case, an extra
|
||||
argument is needed to the MakeCallback function, to tell the system
|
||||
on which object the function should be invoked. Consider this example,
|
||||
also from main-callback.cc:
|
||||
|
||||
@verbatim
|
||||
class MyCb {
|
||||
public:
|
||||
int CbTwo (double a) {
|
||||
std::cout << "invoke cbTwo a=" << a << std::endl;
|
||||
return -5;
|
||||
}
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
...
|
||||
// return type: int
|
||||
// first arg type: double
|
||||
Callback<int, double> two;
|
||||
MyCb cb;
|
||||
// build callback instance which points to MyCb::cbTwo
|
||||
two = MakeCallback (&MyCb::CbTwo, &cb);
|
||||
...
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
Here, we pass a (raw) pointer to the @code{MakeCallback<>} function,
|
||||
that says, when @code{two ()} is invoked, to call the @code{CbTwo} function
|
||||
on the object pointed to by @code{&cb}.
|
||||
|
||||
A variation of this is used when objects are referred to by ns-3 smart
|
||||
pointers. The MakeCallback API takes a raw pointer, so we need to
|
||||
call @code{PeekPointer ()} to obtain this raw pointer. So the example
|
||||
above would look like:
|
||||
|
||||
@verbatim
|
||||
class MyCb : public Object {
|
||||
public:
|
||||
int CbTwo (double a) {
|
||||
std::cout << "invoke cbTwo a=" << a << std::endl;
|
||||
return -5;
|
||||
}
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
...
|
||||
// return type: int
|
||||
// first arg type: double
|
||||
Callback<int, double> two;
|
||||
Ptr<MyCb> cb = CreateObject<MyCb> ();
|
||||
// build callback instance which points to MyCb::cbTwo
|
||||
two = MakeCallback (&MyCb::CbTwo, PeekPointer (cb));
|
||||
...
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
@node Building Null Callbacks
|
||||
@subsection Building Null Callbacks
|
||||
|
||||
It is possible for callbacks to be null; hence it may be wise to
|
||||
check before using them. There is a special construct for a null
|
||||
callback, which is preferable to simply passing "0" as an argument;
|
||||
it is the @code{MakeNullCallback<>} construct:
|
||||
@verbatim
|
||||
two = MakeNullCallback<int, double> ();
|
||||
// invoking a null callback is just like
|
||||
// invoking a null function pointer:
|
||||
// it will crash at runtime.
|
||||
//int retTwoNull = two (20.0);
|
||||
NS_ASSERT (two.IsNull ());
|
||||
@end verbatim
|
||||
|
||||
@node Callback locations in ns-3
|
||||
@section Callback locations in @command{ns-3}
|
||||
|
||||
Where are callbacks frequently used in @command{ns-3}? Here are some of the
|
||||
more visible ones to typical users:
|
||||
|
||||
@subsection Socket API
|
||||
@subsection Layer-2/Layer-3 API
|
||||
@subsection Tracing subsystem
|
||||
@subsection Routing
|
||||
Route Reply
|
||||
|
||||
@node Implementation details
|
||||
@section Implementation details
|
||||
|
||||
This section is advanced explanation for C++ experts interested in
|
||||
the implementation, and may be skipped by most users.
|
||||
|
||||
This code was originally written based on the techniques described
|
||||
@uref{http://www.codeproject.com/cpp/TTLFunction.asp,,here}.
|
||||
It was subsequently rewritten to follow the architecture
|
||||
outlined in
|
||||
@uref{http://www.amazon.com/Modern-C\%2B\%2B-Design-Programming-Patterns/dp/0201704315/ref=pd_bbs_sr_1/102-0157303-1900156?ie=UTF8\&s=books\&qid=1187982662\&sr=1-1,,Modern C++ Design: Generic Programming and Design Patterns Applied-- Alexandrescu}, chapter 5, "Generalized Functors".
|
||||
|
||||
This code uses:
|
||||
@itemize @bullet
|
||||
@item default template parameters to saves users from having to
|
||||
specify empty parameters when the number of parameters
|
||||
is smaller than the maximum supported number
|
||||
@item the pimpl idiom: the Callback class is passed around by
|
||||
value and delegates the crux of the work to its pimpl pointer.
|
||||
@item two pimpl implementations which derive from CallbackImpl
|
||||
FunctorCallbackImpl can be used with any functor-type
|
||||
while MemPtrCallbackImpl can be used with pointers to
|
||||
member functions.
|
||||
@item a reference list implementation to implement the Callback's
|
||||
value semantics.
|
||||
@end itemize
|
||||
|
||||
This code most notably departs from the Alexandrescu
|
||||
implementation in that it does not use type lists to specify
|
||||
and pass around the types of the callback arguments.
|
||||
Of course, it also does not use copy-destruction semantics
|
||||
and relies on a reference list rather than autoPtr to hold
|
||||
the pointer.
|
||||
@@ -0,0 +1,18 @@
|
||||
Please write image files in a vector graphics format, when possible, and
|
||||
generate the .png and .pdf versions on the fly (see ../Makefile).
|
||||
|
||||
Currently supported tools are dia and tgif. xfig could be added similarly
|
||||
if someone wants to add it. The main requirement for adding another format
|
||||
is that the tool to edit it is freely available and that a cron script can
|
||||
autogenerate the pdf and png from the figure source.
|
||||
|
||||
Store the .dia, or .obj versions in mercurial, but not the .png or .pdfs.
|
||||
If the figure is not available in a vector graphics format, store both
|
||||
a .png and a .pdf version in this directory.
|
||||
|
||||
If you add a source (.dia, .obj) file here, remember to add it to
|
||||
the list of figure sources in the Makefile in the directory above
|
||||
|
||||
Note: tgif can convert from .obj to .pdf, but the pdf that results takes
|
||||
up a whole page. Instead, we convert to an intermediate .eps step, and
|
||||
then run epstopdf.
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,115 @@
|
||||
%TGIF 4.1.43-QPL
|
||||
state(0,37,100.000,0,0,0,32,1,9,1,1,0,0,1,2,1,0,'Courier',0,80640,0,2,0,10,0,0,1,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
color_info(11,65535,0,[
|
||||
"magenta", 65535, 0, 65535, 65535, 0, 65535, 1,
|
||||
"red", 65535, 0, 0, 65535, 0, 0, 1,
|
||||
"green", 0, 65535, 0, 0, 65535, 0, 1,
|
||||
"blue", 0, 0, 65535, 0, 0, 65535, 1,
|
||||
"yellow", 65535, 65535, 0, 65535, 65535, 0, 1,
|
||||
"pink", 65535, 49344, 52171, 65535, 49344, 52171, 1,
|
||||
"cyan", 0, 65535, 65535, 0, 65535, 65535, 1,
|
||||
"CadetBlue", 24415, 40606, 41120, 24415, 40606, 41120, 1,
|
||||
"white", 65535, 65535, 65535, 65535, 65535, 65535, 1,
|
||||
"black", 0, 0, 0, 0, 0, 0, 1,
|
||||
"DarkSlateGray", 12079, 20303, 20303, 12079, 20303, 20303, 1
|
||||
]).
|
||||
script_frac("0.6").
|
||||
fg_bg_colors('black','white').
|
||||
dont_reencode("FFDingbests:ZapfDingbats").
|
||||
page(1,"",1,'').
|
||||
text('black',272,195,2,0,1,248,36,0,13,5,0,0,0,0,2,248,36,0,0,"",0,0,0,0,208,'',[
|
||||
minilines(248,36,0,0,0,0,0,[
|
||||
mini_line(200,13,5,0,0,0,[
|
||||
str_block(0,200,13,5,0,-8,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,200,13,5,0,-8,0,0,0,0,0,
|
||||
"low-level APIs (all src/ ")])
|
||||
]),
|
||||
mini_line(248,13,5,0,0,0,[
|
||||
str_block(0,248,13,5,0,-2,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,248,13,5,0,-2,0,0,0,0,0,
|
||||
"directories except src/helper/)")])
|
||||
])
|
||||
])]).
|
||||
rcbox('black','',96,240,384,288,5,1,1,0,16,2,0,0,0,0,'1',0,[
|
||||
]).
|
||||
text('black',192,259,1,0,1,112,18,3,13,5,2,0,0,0,2,112,18,0,0,"",0,0,0,0,272,'',[
|
||||
minilines(112,18,0,0,0,0,0,[
|
||||
mini_line(112,13,5,0,0,0,[
|
||||
str_block(0,112,13,5,0,0,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,112,13,5,0,0,0,0,0,0,0,
|
||||
"ns-3 simulator")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
272,208,240,240],0,1,1,17,0,0,2,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
240,176,240,240],1,1,1,18,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
rcbox('black','',176,128,384,176,5,1,1,0,16,25,0,0,0,0,'1',0,[
|
||||
]).
|
||||
text('black',192,131,2,0,1,120,36,26,13,5,2,0,0,0,2,120,36,0,0,"",0,0,0,0,144,'',[
|
||||
minilines(120,36,0,0,0,0,0,[
|
||||
mini_line(120,13,5,0,0,0,[
|
||||
str_block(0,120,13,5,0,-1,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,120,13,5,0,-1,0,0,0,0,0,
|
||||
"ns-3 helper API")])
|
||||
]),
|
||||
mini_line(96,13,5,0,0,0,[
|
||||
str_block(0,96,13,5,0,-2,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,96,13,5,0,-2,0,0,0,0,0,
|
||||
"(src/helper)")])
|
||||
])
|
||||
])]).
|
||||
rcbox('black','',96,16,384,64,0,1,1,0,16,32,0,0,0,0,'1',0,[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
240,64,240,128],1,1,1,36,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
text('black',272,83,2,0,1,200,36,40,13,5,0,0,0,0,2,200,36,0,0,"",0,0,0,0,96,'',[
|
||||
minilines(200,36,0,0,0,0,0,[
|
||||
mini_line(200,13,5,0,0,0,[
|
||||
str_block(0,200,13,5,0,-2,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,200,13,5,0,-2,0,0,0,0,0,
|
||||
"helper APIs (src/helper/)")])
|
||||
]),
|
||||
mini_line(192,13,5,0,0,0,[
|
||||
str_block(0,192,13,5,0,-1,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,192,13,5,0,-1,0,0,0,0,0,
|
||||
"call into low-level APIs")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
272,96,240,128],0,1,1,41,0,0,2,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
text('black',128,19,2,0,1,232,36,47,13,5,0,0,0,0,2,232,36,0,0,"",0,0,0,0,32,'',[
|
||||
minilines(232,36,0,0,0,0,0,[
|
||||
mini_line(224,13,5,0,0,0,[
|
||||
str_block(0,224,13,5,0,-2,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,224,13,5,0,-2,0,0,0,0,0,
|
||||
"ns-3 scripts (main programs)")])
|
||||
]),
|
||||
mini_line(232,13,5,0,0,0,[
|
||||
str_block(0,232,13,5,0,-1,0,0,0,[
|
||||
str_seg('black','Courier',0,80640,232,13,5,0,-1,0,0,0,0,0,
|
||||
"- may use either or both APIs")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
144,64,144,240],1,1,1,50,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,227 @@
|
||||
%TGIF 4.1.43-QPL
|
||||
state(0,37,100.000,0,64,0,32,0,9,1,1,1,0,0,0,1,0,'Courier-Bold',1,103680,0,3,0,10,0,0,1,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
color_info(11,65535,0,[
|
||||
"magenta", 65535, 0, 65535, 65535, 0, 65535, 1,
|
||||
"red", 65535, 0, 0, 65535, 0, 0, 1,
|
||||
"green", 0, 65535, 0, 0, 65535, 0, 1,
|
||||
"blue", 0, 0, 65535, 0, 0, 65535, 1,
|
||||
"yellow", 65535, 65535, 0, 65535, 65535, 0, 1,
|
||||
"pink", 65535, 49344, 52171, 65535, 49344, 52171, 1,
|
||||
"cyan", 0, 65535, 65535, 0, 65535, 65535, 1,
|
||||
"CadetBlue", 24415, 40606, 41120, 24415, 40606, 41120, 1,
|
||||
"white", 65535, 65535, 65535, 65535, 65535, 65535, 1,
|
||||
"black", 0, 0, 0, 0, 0, 0, 1,
|
||||
"DarkSlateGray", 12079, 20303, 20303, 12079, 20303, 20303, 1
|
||||
]).
|
||||
script_frac("0.6").
|
||||
fg_bg_colors('black','white').
|
||||
dont_reencode("FFDingbests:ZapfDingbats").
|
||||
page(1,"",1,'').
|
||||
box('black','',32,48,240,256,0,3,1,0,0,0,0,0,0,'3',0,[
|
||||
]).
|
||||
text('black',64,10,1,0,1,121,28,3,22,6,0,0,0,0,2,121,28,0,0,"",0,0,0,0,32,'',[
|
||||
minilines(121,28,0,0,0,0,0,[
|
||||
mini_line(121,22,6,0,0,0,[
|
||||
str_block(0,121,22,6,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,138240,121,22,6,0,0,0,0,0,0,0,
|
||||
"class Packet")])
|
||||
])
|
||||
])]).
|
||||
text('black',416,100,1,0,1,116,28,15,22,6,0,0,0,0,2,116,28,0,0,"",0,0,0,0,122,'',[
|
||||
minilines(116,28,0,0,0,0,0,[
|
||||
mini_line(116,22,6,0,0,0,[
|
||||
str_block(0,116,22,6,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,138240,116,22,6,0,0,0,0,0,0,0,
|
||||
"class Buffer")])
|
||||
])
|
||||
])]).
|
||||
text('black',48,178,4,0,1,83,69,32,14,4,0,0,0,0,2,83,69,0,0,"",0,0,0,0,192,'',[
|
||||
minilines(83,69,0,0,0,0,0,[
|
||||
mini_line(80,14,4,0,0,0,[
|
||||
str_block(0,80,14,4,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Bold',1,80640,80,14,4,0,-1,0,0,0,0,0,
|
||||
"private data:")])
|
||||
]),
|
||||
mini_line(59,14,3,0,0,0,[
|
||||
str_block(0,59,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,59,14,3,0,0,0,0,0,0,0,
|
||||
"- unique id")])
|
||||
]),
|
||||
mini_line(83,14,3,0,0,0,[
|
||||
str_block(0,83,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,83,14,3,0,0,0,0,0,0,0,
|
||||
"- Buffer object")])
|
||||
]),
|
||||
mini_line(76,14,3,0,0,0,[
|
||||
str_block(0,76,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,76,14,3,0,0,0,0,0,0,0,
|
||||
"- Tags object")])
|
||||
])
|
||||
])]).
|
||||
text('black',112,288,1,0,1,103,28,82,22,6,0,0,0,0,2,103,28,0,0,"",0,0,0,0,310,'',[
|
||||
minilines(103,28,0,0,0,0,0,[
|
||||
mini_line(103,22,6,0,0,0,[
|
||||
str_block(0,103,22,6,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,138240,103,22,6,0,-1,0,0,0,0,0,
|
||||
"class Tags")])
|
||||
])
|
||||
])]).
|
||||
text('black',48,50,5,0,1,175,86,176,14,4,0,0,0,0,2,175,86,0,0,"",0,0,0,0,64,'',[
|
||||
minilines(175,86,0,0,0,0,0,[
|
||||
mini_line(105,14,4,0,0,0,[
|
||||
str_block(0,105,14,4,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Bold',1,80640,105,14,4,0,-1,0,0,0,0,0,
|
||||
"public functions:")])
|
||||
]),
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,80,14,3,0,-1,0,0,0,0,0,
|
||||
"- constructors")])
|
||||
]),
|
||||
mini_line(175,14,3,0,0,0,[
|
||||
str_block(0,175,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,175,14,3,0,-1,0,0,0,0,0,
|
||||
"- add/remove/peek at Headers")])
|
||||
]),
|
||||
mini_line(155,14,3,0,0,0,[
|
||||
str_block(0,155,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,155,14,3,0,-1,0,0,0,0,0,
|
||||
"- add/remove/peek at Tags")])
|
||||
]),
|
||||
mini_line(88,14,3,0,0,0,[
|
||||
str_block(0,88,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,88,14,3,0,0,0,0,0,0,0,
|
||||
"- fragmentation")])
|
||||
])
|
||||
])]).
|
||||
box('black','',384,144,614,352,0,3,1,245,0,0,0,0,0,'3',0,[
|
||||
]).
|
||||
text('black',400,274,4,0,1,204,69,246,14,4,0,0,0,0,2,204,69,0,0,"",0,0,0,0,288,'',[
|
||||
minilines(204,69,0,0,0,0,0,[
|
||||
mini_line(80,14,4,0,0,0,[
|
||||
str_block(0,80,14,4,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Bold',1,80640,80,14,4,0,-1,0,0,0,0,0,
|
||||
"private data:")])
|
||||
]),
|
||||
mini_line(193,14,3,0,0,0,[
|
||||
str_block(0,193,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,193,14,3,0,0,0,0,0,0,0,
|
||||
"- struct BufferData, a dynamically")])
|
||||
]),
|
||||
mini_line(160,14,3,0,0,0,[
|
||||
str_block(0,160,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,160,14,3,0,0,0,0,0,0,0,
|
||||
"varying byte buffer to which")])
|
||||
]),
|
||||
mini_line(204,14,3,0,0,0,[
|
||||
str_block(0,204,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,204,14,3,0,0,0,0,0,0,0,
|
||||
"data can be prepended or appended")])
|
||||
])
|
||||
])]).
|
||||
text('black',400,146,5,0,1,188,86,247,14,4,0,0,0,0,2,188,86,0,0,"",0,0,0,0,160,'',[
|
||||
minilines(188,86,0,0,0,0,0,[
|
||||
mini_line(105,14,4,0,0,0,[
|
||||
str_block(0,105,14,4,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Bold',1,80640,105,14,4,0,-1,0,0,0,0,0,
|
||||
"public functions:")])
|
||||
]),
|
||||
mini_line(172,14,3,0,0,0,[
|
||||
str_block(0,172,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,172,14,3,0,0,0,0,0,0,0,
|
||||
"- Iterators to move byte buffer")])
|
||||
]),
|
||||
mini_line(171,14,3,0,0,0,[
|
||||
str_block(0,171,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,171,14,3,0,0,0,0,0,0,0,
|
||||
"pointers forward or backward")])
|
||||
]),
|
||||
mini_line(188,14,3,0,0,0,[
|
||||
str_block(0,188,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,188,14,3,0,0,0,0,0,0,0,
|
||||
"- functions to read and write data")])
|
||||
]),
|
||||
mini_line(132,14,3,0,0,0,[
|
||||
str_block(0,132,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,132,14,3,0,-1,0,0,0,0,0,
|
||||
"of various sized chunks")])
|
||||
])
|
||||
])]).
|
||||
box('black','',96,324,304,532,0,3,1,264,0,0,0,0,0,'3',0,[
|
||||
]).
|
||||
text('black',112,454,4,0,1,167,69,265,14,4,0,0,0,0,2,167,69,0,0,"",0,0,0,0,468,'',[
|
||||
minilines(167,69,0,0,0,0,0,[
|
||||
mini_line(80,14,4,0,0,0,[
|
||||
str_block(0,80,14,4,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Bold',1,80640,80,14,4,0,-1,0,0,0,0,0,
|
||||
"private data:")])
|
||||
]),
|
||||
mini_line(167,14,3,0,0,0,[
|
||||
str_block(0,167,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,167,14,3,0,0,0,0,0,0,0,
|
||||
"- singly linked-list of TagData")])
|
||||
]),
|
||||
mini_line(158,14,3,0,0,0,[
|
||||
str_block(0,158,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,158,14,3,0,0,0,0,0,0,0,
|
||||
"structures, with a reference")])
|
||||
]),
|
||||
mini_line(32,14,3,0,0,0,[
|
||||
str_block(0,32,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,32,14,3,0,0,0,0,0,0,0,
|
||||
"count")])
|
||||
])
|
||||
])]).
|
||||
text('black',112,326,5,0,1,155,86,266,14,4,0,0,0,0,2,155,86,0,0,"",0,0,0,0,340,'',[
|
||||
minilines(155,86,0,0,0,0,0,[
|
||||
mini_line(105,14,4,0,0,0,[
|
||||
str_block(0,105,14,4,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Bold',1,80640,105,14,4,0,-1,0,0,0,0,0,
|
||||
"public functions:")])
|
||||
]),
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,80,14,3,0,-1,0,0,0,0,0,
|
||||
"- constructors")])
|
||||
]),
|
||||
mini_line(155,14,3,0,0,0,[
|
||||
str_block(0,155,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,155,14,3,0,-1,0,0,0,0,0,
|
||||
"- templates to add, remove,")])
|
||||
]),
|
||||
mini_line(148,14,3,0,0,0,[
|
||||
str_block(0,148,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,148,14,3,0,-1,0,0,0,0,0,
|
||||
"or peek at Tags of various")])
|
||||
]),
|
||||
mini_line(31,14,3,0,0,0,[
|
||||
str_block(0,31,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Times-Roman',0,80640,31,14,3,0,-1,0,0,0,0,0,
|
||||
"types")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
59,245,96,320],0,2,1,272,0,0,3,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
123,246,288,320],0,2,1,280,0,0,3,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
141,219,379,147],0,2,1,286,0,0,3,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
132,226,375,335],0,2,1,287,0,0,3,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,20 @@
|
||||
@node Helper Functions
|
||||
@chapter Helper Functions
|
||||
@anchor{chap:Helpers}
|
||||
This chapter describes an intermediate API for the simulator; what we
|
||||
call the "helper API". The helper API is implemented in
|
||||
@code{src/helper/} directory; it depends on (and wraps) the low-level
|
||||
API which is implemented everywhere else in @code{src/}. The following
|
||||
figure shows this relationship.
|
||||
@center @image{figures/helpers,,,,png}
|
||||
|
||||
The use of the helper API is optional. It has two main goals:
|
||||
@itemize @bullet
|
||||
@item Provide "syntactic sugar" to wrap a number of related low-level
|
||||
API calls together, that would normally be grouped together often, into
|
||||
something that is more user-friendly.
|
||||
@item Handle configuration of larger topological units (e.g., a set
|
||||
of nodes or a set of nodes on a particular link) .
|
||||
@end itemize
|
||||
|
||||
(more to follow)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
@node Logging
|
||||
@chapter Logging
|
||||
@anchor{chap:Logging}
|
||||
|
||||
This chapter is the first in a series of chapters discussing things that
|
||||
one can do to modify the input or output of existing ns-3 scripts.
|
||||
|
||||
Examples:
|
||||
@itemize @bullet
|
||||
@item Enable or disable the generation of log messages, with fine granularity
|
||||
@item Set default values for configuration values in the system
|
||||
@item Generate a report of all configuration values used during a simulation
|
||||
run (not yet implemented)
|
||||
@item Set or get values of member variables on objects already instantiated
|
||||
@item Customizing the tracing output of the script
|
||||
@item Generate statistics on (not yet implemented)
|
||||
@item Perform a large number of independent runs of the same simulation
|
||||
@end itemize
|
||||
|
||||
@node Logging Basics
|
||||
@section Logging Basics
|
||||
|
||||
@node Enabling Log Output
|
||||
@section Enabling Log Output
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,462 @@
|
||||
|
||||
@c ========================================================================
|
||||
@c Simulation Output
|
||||
@c ========================================================================
|
||||
|
||||
@node Simulation Output
|
||||
@chapter Simulation Output
|
||||
|
||||
At this point, you should be able to execute any of the built-in
|
||||
programs distributed with @command{ns-3}. Next, we will look at
|
||||
how to generate and tailor the simulation output, before turning
|
||||
to how to modify simulation scripts to do different things.
|
||||
|
||||
@node Tracing Basics
|
||||
@section Tracing Basics
|
||||
|
||||
The whole point of simulation is to generate output for further
|
||||
study, and the @command{ns-3} tracing system is a primary
|
||||
mechanism for this.
|
||||
Since @command{ns-3} is a C++ program, standard facilities for
|
||||
generating output from C++ programs apply:
|
||||
|
||||
@verbatim
|
||||
#include <iostream>
|
||||
...
|
||||
int main ()
|
||||
{
|
||||
...
|
||||
std::cout << "The value of x is " << x << std::endl;
|
||||
...
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
The goal of the @command{ns-3} tracing system is to
|
||||
provide a structured way to configure the simulator to output results
|
||||
in standard or modifiable formats.
|
||||
@itemize @bullet
|
||||
@item For basic tasks, the tracing system should allow the user to
|
||||
generate standard tracing for popular tracing sources, and to customize
|
||||
which objects generate the tracing.
|
||||
@item Intermediate users will be able to extend the tracing system to
|
||||
modify the output format generated, or to insert new tracing sources,
|
||||
without modifying the core of the simulator.
|
||||
@item Advanced users can modify the simulator core to add new
|
||||
tracing sources and sinks.
|
||||
@end itemize
|
||||
|
||||
The @command{ns-3} tracing system is fundamentally built on the
|
||||
concept of separating tracing sources from sinks.
|
||||
@enumerate
|
||||
@item Trace sources (e.g., provide access to every packet received)
|
||||
@item Trace sinks (e.g., print out the packet)
|
||||
@item A mechanism to tie together sources and sinks
|
||||
@end enumerate
|
||||
The rationale for this division is to allow users to attach new
|
||||
types of sinks to existing tracing sources, without requiring
|
||||
users to edit and recompile the core of the simulator.
|
||||
Thus, in the example above, a user could write a new tracing sink
|
||||
and attach it to an existing tracing source. What remains to
|
||||
be defined is a way for users to find these hooks (tracing sources)
|
||||
and attach sinks to them. A new tracing namespace is defined for
|
||||
this purpose.
|
||||
|
||||
We will first walk through how some pre-defined sources and sinks
|
||||
are provided and may be customized with little user effort. We
|
||||
return later in this chapter to advanced tracing configuration including
|
||||
extending the tracing namespace and creating new tracing sources.
|
||||
|
||||
@subsection ASCII tracing
|
||||
@cindex ASCII
|
||||
For Internet nodes, the ASCII trace wrapper is a wrapper around
|
||||
the @command{ns-3} low-level
|
||||
tracing system that lets you get access to underlying trace events easily.
|
||||
The output of a trace of a simulation run is an ASCII file --- thus the name.
|
||||
In the spririt of keeping things simple, you won't be able to control or
|
||||
configure the output at this stage.
|
||||
|
||||
For those familiar with @command{ns-2} output, this type of trace is
|
||||
analogous to the @command{out.tr} generated by many scripts.
|
||||
|
||||
@cindex tracing packets
|
||||
Let's just jump right in. As usual, we need to include the definitions
|
||||
related to using ASCII tracing (don't edit any files quite yet):
|
||||
|
||||
@verbatim
|
||||
#include "ns3/ascii-trace.h"
|
||||
@end verbatim
|
||||
|
||||
We then need to add the code to the script to actually enable the ASCII tracing
|
||||
code. The following code must be inserted before the call to
|
||||
@code{Simulator::Run ();}:
|
||||
|
||||
@verbatim
|
||||
AsciiTrace asciitrace ("tutorial.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
@end verbatim
|
||||
|
||||
The first line declares an object of type @code{AsciiTrace} named
|
||||
@code{asciitrace} and passes a string parameter to its constructor. This
|
||||
parameter is a file name to which all of the trace information will be written.
|
||||
The second line, @code{asciitrace.TraceAllQueues ();} asks the trace object to
|
||||
arrange that all queue operations (enqueue, dequeue, drop) on the queues
|
||||
in all of the nodes of the system be traced. On the receive side,
|
||||
@code{asciitrace.TraceAlllNetDeviceRx ()} traces packets received by
|
||||
a NetDevice. For those familiar with @command{ns-2}, these are equivalent
|
||||
to the popular trace points that log "+", "-", "d", and "r" events.
|
||||
|
||||
Try running the following program from the command line:
|
||||
@verbatim
|
||||
./waf --run tutorial-csma-echo-ascii-trace
|
||||
@end verbatim
|
||||
|
||||
@cindex tutorial.tr
|
||||
Just as you have seen previously, you will see some messages from @emph{Waf}
|
||||
and then the ``Compilation finished successfully'' message. The
|
||||
next message, @code{UDP Echo Simulation} is from the running program. When
|
||||
it ran, the program will have created a file named @code{tutorial.tr}.
|
||||
Because of the way that Waf works, the file is not created in the local
|
||||
directory, it is created at the top-level directory of the repository. So,
|
||||
change into the top level directory and take a look at the file
|
||||
@code{tutorial.tr} in your favorite editor.
|
||||
|
||||
@subsubsection Parsing Ascii Traces
|
||||
@cindex parsing ascii traces
|
||||
|
||||
This section parses in detail the structure of the ascii tracing
|
||||
output. If you find this output format self explanatory (it
|
||||
resembles tcpdump output), you may skip to the next
|
||||
section on pcap tracing.
|
||||
|
||||
@cindex trace event
|
||||
There's a lot of information there in a pretty dense form, but the first thing
|
||||
to notice is that there are a number of distinct lines in this file. It may
|
||||
be difficult to see this clearly unless you widen your windows considerably.
|
||||
Each line in the file corresponds to a @emph{trace event}. A trace event
|
||||
happens whenever specific conditions happen in the simulation. In this case
|
||||
we are tracing events on the @emph{device queue} present in every net device
|
||||
on every node in the simulation. The device queue is a queue through which
|
||||
every packet destined for a channel must pass --- it is the device
|
||||
@emph{transmit} queue. Note that each line in the trace file begins with a
|
||||
lone character (has a space after it). This character will have the following
|
||||
meaning:
|
||||
|
||||
@cindex enqueue
|
||||
@cindex dequeue
|
||||
@cindex drop
|
||||
@itemize @bullet
|
||||
@item @code{+}: An enqueue operation occurred on the device queue;
|
||||
@item @code{-}: A dequeue operation occurred on the device queue;
|
||||
@item @code{d}: A packet was dropped, typically because the queue was full.
|
||||
@end itemize
|
||||
|
||||
Let's take a more detailed view of the first line. I'll break it down into
|
||||
sections (indented for clarity) with a two digit reference number on the
|
||||
left side:
|
||||
|
||||
@verbatim
|
||||
00 +
|
||||
01 2
|
||||
02 nodeid=0
|
||||
03 device=0
|
||||
04 queue-enqueue
|
||||
05 pkt-uid=9
|
||||
06 ETHERNET
|
||||
07 length/type=0x806,
|
||||
08 source=08:00:2e:00:00:00,
|
||||
09 destination=ff:ff:ff:ff:ff:ff
|
||||
10 ARP(request
|
||||
11 source mac: 08:00:2e:00:00:00
|
||||
12 source ipv4: 10.1.1.1
|
||||
13 dest ipv4: 10.1.1.2)
|
||||
14 ETHERNET fcs=0
|
||||
@end verbatim
|
||||
|
||||
@cindex trace event
|
||||
@cindex simulation time
|
||||
The first line of this expanded trace event (reference number 00) is the
|
||||
queue operation. We have a @code{+} character, so this corresponds to an
|
||||
@emph{enqueue} operation. The second line (reference 01) is the simulation
|
||||
time expressed in seconds. You may recall that we asked the
|
||||
@code{UdpEchoClient} to start sending packets at two seconds. Here we see
|
||||
confirmation that this is, indeed, happening.
|
||||
|
||||
@cindex node number
|
||||
@cindex net device number
|
||||
@cindex smart pointer
|
||||
The next lines of the example listing (references 02 and 03) tell us that
|
||||
this trace event originated in a given node and net device. Each time a node
|
||||
is created it is given an identifying number that monotonically increases from
|
||||
zero. Therefore, @code{nodeid=0} means that the node in which the given trace
|
||||
event originated is the first node we created. In the case of our script,
|
||||
this first node is is the node pointed to by the smart pointer @code{n0}. Not
|
||||
too surpsisingly, this is also the node to which we attached the
|
||||
@code{UdpEchoClient}. The device number is local to each node, and so the
|
||||
device given by @code{device=0} is the first net device that we added to the
|
||||
node in question. In our simulation, this corresponds to the
|
||||
@code{CsmaNetDevice} we added to node zero (@code{n0}).
|
||||
|
||||
@cindex uid
|
||||
@cindex unique ID
|
||||
@cindex packet
|
||||
The next line (reference 04) is a more readable form of the operation code
|
||||
seen in the first line --- i.e., the character @code{+} means
|
||||
@code{queue-enqueue}. Reference number 05 indicates that the @emph{unique id}
|
||||
of the packet being enqueued is @code{9}. The fact that the first packet we
|
||||
see has a unique ID of 9 should indicates to you that other things have
|
||||
happened in the protocol stack before we got to this point. This will become
|
||||
clear momentarily.
|
||||
|
||||
@cindex Ethernet
|
||||
@cindex MAC address
|
||||
Reference items 06 and 14 indicate that this is an Ethernet packet with
|
||||
a zero (not computed) checksum (note the indentation to make parsing this
|
||||
trace event a little easier). Reference 08 and 09 are the source and
|
||||
destination addresses of this packet. The packet is from the MAC address we
|
||||
assigned to the node zero net device in the script, and is destined for the
|
||||
broadcast address --- this is a broadcast packet.
|
||||
|
||||
@cindex Address Resolution Protocol
|
||||
@cindex ARP
|
||||
@cindex ARP|request
|
||||
Reference items 10 through 13 make clear what is happening. This is an ARP
|
||||
(Address Resolution Protocol) request for the MAC address of the node on
|
||||
which the @code{UdpEchoServer} resides. The protocol stack can't send a UDP
|
||||
packet to be echoed until it knows (resolves) the MAC address; and this trace
|
||||
event corresponds to an ARP request being queued for transmission to the local
|
||||
network. The next line in the trace file (partially expanded),
|
||||
|
||||
@verbatim
|
||||
00 -
|
||||
01 2
|
||||
02 nodeid=0
|
||||
03 device=0
|
||||
04 queue-dequeue
|
||||
05 pkt-uid=9
|
||||
...
|
||||
@end verbatim
|
||||
|
||||
shows the (same) ARP request packet being dequeued from the device queue by
|
||||
the net device and (implicitly) being sent down the channel to the broadcast
|
||||
MAC address. We are not tracing net device reception events so we don't
|
||||
actually see all of the net devices receiving the broadcast packet. We do,
|
||||
however see the following in the third line of the trace file:
|
||||
|
||||
@verbatim
|
||||
00 +
|
||||
01 2.00207
|
||||
02 nodeid=1
|
||||
03 device=0
|
||||
04 queue-enqueue
|
||||
05 pkt-uid=10
|
||||
06 ETHERNET
|
||||
07 length/type=0x806,
|
||||
08 source=08:00:2e:00:00:01,
|
||||
09 destination=08:00:2e:00:00:00,
|
||||
10 ARP(reply
|
||||
11 source mac: 08:00:2e:00:00:01
|
||||
12 source ipv4: 10.1.1.2
|
||||
13 dest mac: 08:00:2e:00:00:00
|
||||
14 dest ipv4: 10.1.1.1)
|
||||
15 ETHERNET fcs=0
|
||||
@end verbatim
|
||||
|
||||
@cindex simulation time
|
||||
@cindex ARP|response
|
||||
Notice that this is a queue-enqueue operation (references 00 and 04) happening
|
||||
on node one (reference 02) at simulation time 2.00207 seconds (reference 01).
|
||||
Looking at the packet payload (references 10-14) we see that this is an ARP
|
||||
reply to the request sent by node one. Note that the simulation time
|
||||
(reference 01) is now 2.00207 seconds. This is direct result of the data rate
|
||||
(5 mb/s) and latency (2 ms) parameters that we passed to the
|
||||
@code{CsmaChannel} when we created it. Clearly the ARP request packet was
|
||||
sent over the channel and received approximately 2 ms later by node one. A
|
||||
corresponding ARP response packet was created and enqueued on node one's net
|
||||
device. It is this enqueue trace event that has being logged.
|
||||
|
||||
@cindex queue
|
||||
@cindex queue|transmit
|
||||
@cindex echo
|
||||
Given the current state of affairs, the next thing you may expect to see is
|
||||
this ARP request being received by node zero, but remember we are only looking
|
||||
at trace events on the device @emph{transmit} queue. The reception of the ARP
|
||||
response by node zero will not directly trigger any trace event in this case,
|
||||
but it will enable the protocol stack to continue what it was originally doing
|
||||
(trying to send an echo packet). Thus, the next line we see in the trace file
|
||||
(@code{tutorial.tr}) is the first UDP echo packet being sent to the net device.
|
||||
|
||||
@verbatim
|
||||
00 +
|
||||
01 2.00415
|
||||
02 nodeid=0
|
||||
03 device=0
|
||||
04 queue-enqueue
|
||||
05 pkt-uid=7
|
||||
06 ETHERNET
|
||||
07 length/type=0x800,
|
||||
08 source=08:00:2e:00:00:00,
|
||||
09 destination=08:00:2e:00:00:01
|
||||
10 IPV4(
|
||||
11 tos 0x0
|
||||
12 ttl 64
|
||||
13 id 0
|
||||
14 offset 0
|
||||
15 flags [none]
|
||||
16 length: 1052) 10.1.1.1 > 10.1.1.2
|
||||
17 UDP(length: 1032)
|
||||
18 49153 > 7
|
||||
19 DATA (length 1024)
|
||||
20 ETHERNET fcs=0
|
||||
@end verbatim
|
||||
|
||||
@cindex simulation time
|
||||
@cindex echo
|
||||
@cindex ARP
|
||||
@cindex ARP|request
|
||||
@cindex ARP|response
|
||||
@cindex IP
|
||||
@cindex Ipv4
|
||||
I won't go into too much detail about this packet, but I will point out a
|
||||
few key items in the trace. First, the packet was enqueued at simulation time
|
||||
of 2.00415 seconds. This time reflects the fact that the echo client
|
||||
application started at 2. seconds and there were two ARP packets transmitted
|
||||
across the network (two milliseconds + data transmission time each way). The
|
||||
packet unique identifier (reference 05) is 7. Notice that this is a lower
|
||||
number than the ARP request packet, which had a unique ID of 9. This tells
|
||||
us that the UDP packet was actually created before the ARP request packet ---
|
||||
which makes perfect sense since it was the attempt to send packet 7 that
|
||||
triggered sending the ARP request packet 9. Note that this an Ethernet
|
||||
packet (reference 06) like all other packets in this simulation, however this
|
||||
particular packet carries an IPV4 payload and therefore has an IP version 4
|
||||
header (indicated by references 10-16). This Ipv4 in turn contains a UDP
|
||||
header (references 17, 18) and finally 1024 bytes of data (reference 20).
|
||||
Clearly, this is the UDP echo packet emitted by the
|
||||
@code{UdpEchoClient Application}.
|
||||
|
||||
The next trace event is an ARP request from node one. We can infer that node
|
||||
one has received the UDP echo packet and the @code{UdpEchoServer Application}
|
||||
on that node has turned the packet around. Just as node zero needed to ARP
|
||||
for the MAC address of node one, now node one must ARP for the MAC address of
|
||||
node zero. We see the ARP request enqueued on the transmit queue of node one;
|
||||
then we see the ARP request dequeued from the tranmit queue of node one (and
|
||||
implicitly transmitted to node zero). Then we see an ARP response enqueued
|
||||
on the transmit queue of node zero; and finally the ARP response dequeued (and
|
||||
implicitly transmitted back to node one).
|
||||
|
||||
This exchange is summarized in the following trace event excerpts,
|
||||
|
||||
@verbatim
|
||||
+ 2.00786 nodeid=1 ... ARP(request ...
|
||||
- 2.00786 nodeid=1 ... ARP(request ...
|
||||
+ 2.00994 nodeid=0 ... ARP(reply ...
|
||||
- 2.00994 nodeid=0 ... ARP(reply ...
|
||||
@end verbatim
|
||||
|
||||
The final two trace events in the @code{tutorial.tr} file correspond to the
|
||||
echoed packet being enqueued for transmission on the net device for node one,
|
||||
and that packet being dequeued (and implicitly transmitted back to node zero).
|
||||
|
||||
@cindex AsciiTrace!TraceAllNetDeviceRx
|
||||
@cindex ARP!request
|
||||
If you look at the trace file (@code{tutorial.tr}) you will also see some
|
||||
entries with an @code{r} event, indicating a
|
||||
@emph{receive} trace event. Recall that the first packet sent on the network
|
||||
was a broadcast ARP request. We should then see all four nodes receive a
|
||||
copy of this request. This is the case, as the first four receive trace
|
||||
events are,
|
||||
|
||||
@verbatim
|
||||
r 2.00207 nodeid=0 device=0 dev-rx pkt-uid=9 ARP(request ...
|
||||
r 2.00207 nodeid=1 device=0 dev-rx pkt-uid=9 ARP(request ...
|
||||
r 2.00207 nodeid=2 device=0 dev-rx pkt-uid=9 ARP(request ...
|
||||
r 2.00207 nodeid=3 device=0 dev-rx pkt-uid=9 ARP(request ...
|
||||
@end verbatim
|
||||
|
||||
@cindex unique ID
|
||||
You can see that a copy of the broadcast packet with unique ID 9 was received
|
||||
by the net devices on nodes 0, 1, 2 and 3. We leave it up to you to parse the
|
||||
rest of the trace file and understand the remaining reception events.
|
||||
|
||||
@subsection PCAP Trace Wrapper
|
||||
@cindex pcap
|
||||
@cindex Wireshark
|
||||
The @command{ns-3} @emph{pcap trace wrapper} is used to create trace files in
|
||||
@code{.pcap} format. The acronym pcap (usually written in lower case) stands
|
||||
for @emph{p}acket @emph{cap}ture, and is actually an API that includes the
|
||||
definition of a @code{.pcap} file format. The most popular program that can
|
||||
read and display this format is Wireshark (formerly called Ethereal).
|
||||
However, there are many traffic trace analyzers that use this packet
|
||||
format, including X, Y, and Z. We encourage users to exploit the
|
||||
many tools available for analyzing pcap traces; below, we show how
|
||||
tcpdump and Wireshark can be used..
|
||||
|
||||
@cindex tutorial-csma-echo-ascii-trace.cc
|
||||
@cindex tutorial-csma-echo-pcap-trace.cc
|
||||
The code used to enable pcap tracing is similar to that for ASCII tracing.
|
||||
We have provided another file, @code{tutorial-csma-echo-pcap-trace.cc} that
|
||||
uses the pcap trace wrapper. We have added the code to include the pcap
|
||||
trace wrapper defintions:
|
||||
|
||||
@verbatim
|
||||
#include "ns3/pcap-trace.h"
|
||||
@end verbatim
|
||||
|
||||
And then added the following code below the AsciiTrace methods:
|
||||
|
||||
@cindex PcapTrace
|
||||
@cindex PcapTrace!TraceAllIp
|
||||
@verbatim
|
||||
PcapTrace pcaptrace ("tutorial.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
@end verbatim
|
||||
|
||||
The first line of the code immediately above declares an object of type
|
||||
@code{PcapTrace} named @code{pcaptrace} and passes a string parameter to its
|
||||
constructor. This object is used to hide the details of the actual tracing
|
||||
subsystem. The parameter is a base file name from which the actual trace file
|
||||
names will be built. The second line of code tells the @code{PcamTrace}
|
||||
object to trace all IP activity in all of the nodes present in the simulation.
|
||||
|
||||
@cindex interface index
|
||||
Trace files are not created until trace activity is detected. Each file name
|
||||
is composed of the base file name, followed by a @code{'-'}, a node id followed
|
||||
by a @code{'-}', and an IP interface index. You will soon see a file named
|
||||
@code{tutorial.pcap-0-1}, for example. This will be the trace file generated
|
||||
as events are detected on node zero, interface index one. N.B. Interface
|
||||
indices are different that net device indices --- interface index zero
|
||||
corresponds to the loopback interface and interface index one corresponds to
|
||||
the first net device you added to a node.
|
||||
|
||||
You may run the new program just like all of the others so far:
|
||||
|
||||
@cindex Waf
|
||||
@verbatim
|
||||
./waf --run tutorial-csma-echo-pcap-trace
|
||||
@end verbatim
|
||||
|
||||
If you look at the top level directory of your distribution, you should now
|
||||
see three log files: @code{tutorial.tr} is the ASCII trace file we have
|
||||
previously examined. @code{tutorial.pcap-0-1} and @code{tutorial.pcap-1-1}
|
||||
are the new pcap files we just generated. There will not be files
|
||||
corresponding to nodes two and three since we have not sent any IP packets to
|
||||
those nodes.
|
||||
|
||||
@subsubsection Reading output with tcpdump
|
||||
@cindex tcpdump
|
||||
|
||||
@subsubsection Reading output with Wireshark
|
||||
@cindex Wireshark
|
||||
If you are unfamilar with Wireshark, there is a web site available from which
|
||||
you can download programs and documentation: @uref{http://www.wireshark.org/}.
|
||||
|
||||
If you have Wireshark available, you can open each of the trace files and
|
||||
display the contents as if you had captured the packets using a
|
||||
@emph{packet sniffer}. Note that only IP packets are traced using this
|
||||
wrapper, so you will not see the ARP exchanges that were logged when using
|
||||
the ASCII trace wrapper. You are encouraged to take a look at the contents
|
||||
of these pcap files using your favorite pcap software (or Wireshark).
|
||||
|
||||
@node Advanced Tracing
|
||||
@section Advanced Tracing
|
||||
|
||||
@@ -0,0 +1,620 @@
|
||||
@node ns-3 Packets
|
||||
@chapter ns-3 Packets
|
||||
|
||||
The design of the Packet framework of @emph{ns} was heavily guided by a few
|
||||
important use-cases:
|
||||
@itemize @bullet
|
||||
@item avoid changing the core of the simulator to introduce
|
||||
new types of packet headers or trailers
|
||||
@item maximize the ease of integration with real-world code
|
||||
and systems
|
||||
@item make it easy to support fragmentation, defragmentation,
|
||||
and, concatenation which are important, especially in wireless systems.
|
||||
@item make memory management of this object efficient
|
||||
@item allow actual application data or dummy application bytes for
|
||||
emulated applications
|
||||
@end itemize
|
||||
|
||||
@emph{ns} Packet objects contain a buffer of bytes: protocol headers and
|
||||
trailers are serialized in this buffer of bytes using user-provided
|
||||
serialization and deserialization routines. The content of this byte
|
||||
buffer is expected to match bit-for-bit the content of a real packet on
|
||||
a real network implementing the protocol of interest.
|
||||
|
||||
Fragmentation and defragmentation are quite natural to implement within
|
||||
this context: since we have a buffer of real bytes, we can split it in
|
||||
multiple fragments and re-assemble these fragments. We expect that this
|
||||
choice will make it really easy to wrap our Packet data structure within
|
||||
Linux-style skb or BSD-style mbuf to integrate real-world kernel code in
|
||||
the simulator. We also expect that performing a real-time plug of the
|
||||
simulator to a real-world network will be easy.
|
||||
|
||||
Because we understand that simulation developers often wish to store in
|
||||
packet objects data which is not found in the real packets (such as
|
||||
timestamps or any kind of similar in-band data), the @emph{ns} Packet class
|
||||
can also store extra per-packet "Tags" which are 16 bytes blobs of data.
|
||||
Any Packet can store any number of unique Tags, each of which is
|
||||
uniquely identified by its C++ type. These tags make it easy to attach
|
||||
per-model data to a packet without having to patch the main Packet
|
||||
class or Packet facilities.
|
||||
|
||||
Memory management of Packet objects is entirely automatic and extremely
|
||||
efficient: memory for the application-level payload can be modelized by
|
||||
a virtual buffer of zero-filled bytes for which memory is never allocated
|
||||
unless explicitely requested by the user or unless the packet is fragmented.
|
||||
Furthermore, copying, adding, and, removing headers or trailers to a packet
|
||||
has been optimized to be virtually free through a technique known as
|
||||
Copy On Write.
|
||||
|
||||
Packets (messages) are fundamental objects in the simulator and
|
||||
their design is important from a performance and resource management
|
||||
perspective. There
|
||||
are various ways to design the simulation packet, and tradeoffs
|
||||
among the different approaches. In particular, there is a
|
||||
tension between ease-of-use, performance, and safe interface
|
||||
design.
|
||||
|
||||
There are a few requirements on this object design:
|
||||
@itemize @bullet
|
||||
@item Creation, management, and deletion of this object
|
||||
should be as simple as possible, while avoiding the
|
||||
chance for memory leaks and/or heap corruption;
|
||||
@item Packets should support serialization and deserialization
|
||||
so that network emulation is supported;
|
||||
@item Packets should support fragmentation and concatenation
|
||||
(multiple packets in a data link frame), especially for wireless
|
||||
support;
|
||||
@item It should be natural for packets to carry actual application
|
||||
data, or if there is only an emulated application and there is
|
||||
no need to carry dummy bytes, smaller packets could be used with
|
||||
just the headers and a record of the payload size, but not actual
|
||||
application bytes, conveyed in the simulated packet.
|
||||
@item Packets should facilitate BSD-like operations on mbufs, for
|
||||
support of ported operating system stacks.
|
||||
@item Additional side-information should be supported, such as
|
||||
a tag for cross-layer information.
|
||||
@end itemize
|
||||
|
||||
@section Packet design overview
|
||||
|
||||
Unlike @emph{ns-2}, in which Packet objects contain a buffer of C++
|
||||
structures corresponding to protocol headers, each network packet in
|
||||
@emph{ns-3} contains a byte Buffer and a list of Tags:
|
||||
@itemize @bullet
|
||||
@item The byte buffer stores the serialized content of the chunks
|
||||
added to a packet. The serialized representation of these chunks is
|
||||
expected to match that of real network packets bit for bit
|
||||
(although nothing forces you to do this) which means that the content
|
||||
of a packet buffer is expected to be that of a real packet.
|
||||
Packets can also be created with an arbitrary zero-filled payload
|
||||
for which no real memory is allocated.
|
||||
@item The list of tags stores an arbitrarily large set of arbitrary
|
||||
user-provided data structures in the packet. Each Tag is uniquely
|
||||
identified by its type; only one instance of each
|
||||
type of data structure is allowed in a list of tags. These tags typically
|
||||
contain per-packet cross-layer information or flow identifiers (i.e.,
|
||||
things that you wouldn't find in the bits on the wire). Each tag
|
||||
stored in the tag list can be at most 16 bytes.
|
||||
Trying to attach bigger data structures will trigger
|
||||
crashes at runtime. The 16 byte limit is a modifiable compilation
|
||||
constant.
|
||||
@end itemize
|
||||
|
||||
@float Figure,fig:packets
|
||||
@caption{Implementation overview of Packet class.}
|
||||
@image{figures/packet}
|
||||
@end float
|
||||
|
||||
Figure @ref{fig:packets} is a high-level overview of the Packet
|
||||
implementation; more detail on the byte Buffer implementation
|
||||
is provided later in Figure @ref{fig:buffer}.
|
||||
In \nsthree, the Packet byte buffer is analogous to a Linux skbuff
|
||||
or BSD mbuf; it is a serialized representation of the actual
|
||||
data in the packet. The tag list is a container for extra
|
||||
items useful for simulation convenience; if a Packet is converted
|
||||
to an emulated packet and put over an actual network, the tags
|
||||
are stripped off and the byte buffer is copied directly
|
||||
into a real packet.
|
||||
|
||||
The Packet class has value semantics: it can be freely copied around,
|
||||
allocated on the stack, and passed to functions as arguments. Whenever
|
||||
an instance is copied, the full underlying data is not copied; it
|
||||
has ``copy-on-write'' (COW) semantics. Packet instances can be passed
|
||||
by value to function arguments without any performance hit.
|
||||
|
||||
The fundamental classes for adding to and removing from the byte
|
||||
buffer are @code{class Header} and @code{class Trailer}.
|
||||
Headers are more common but the below discussion also largely applies to
|
||||
protocols using trailers. Every protocol header that needs to
|
||||
be inserted and removed from a Packet instance should derive from
|
||||
the abstract Header base class and implement the private pure
|
||||
virtual methods listed below:
|
||||
@itemize @bullet
|
||||
@item @code{ns3::Header::SerializeTo()}
|
||||
@item @code{ns3::Header::DeserializeFrom()}
|
||||
@item @code{ns3::Header::GetSerializedSize()}
|
||||
@item @code{ns3::Header::PrintTo()}
|
||||
@end itemize
|
||||
Basically, the first three functions are used to serialize and deserialize
|
||||
protocol control information to/from a Buffer. For example,
|
||||
one may define @code{class TCPHeader : public Header}. The
|
||||
TCPHeader object will typically consist of some private data
|
||||
(like a sequence number) and public interface access functions
|
||||
(such as checking the bounds of an input). But the underlying
|
||||
representation of the TCPHeader in a Packet Buffer is 20 serialized
|
||||
bytes (plus TCP options). The TCPHeader::SerializeTo() function would
|
||||
therefore be designed to write these 20 bytes properly into
|
||||
the packet, in network byte order. The last function is used
|
||||
to define how the Header object prints itself onto an output stream.
|
||||
|
||||
Similarly, user-defined Tags can be appended to the packet.
|
||||
Unlike Headers, Tags are not serialized into a contiguous buffer
|
||||
but are stored in an array. By default, Tags are limited to 16 bytes in
|
||||
size. Tags can be flexibly defined to be any type, but there
|
||||
can only be one instance of any particular object type in
|
||||
the Tags buffer at any time. The implementation makes use
|
||||
of templates to generate the proper set of Add(), Remove(),
|
||||
and Peek() functions for each Tag type.
|
||||
|
||||
@section Packet interface
|
||||
|
||||
The public member functions of a Packet object are as follows:
|
||||
|
||||
@subsection Constructors
|
||||
@verbatim
|
||||
/**
|
||||
* Create an empty packet with a new uid (as returned
|
||||
* by getUid).
|
||||
*/
|
||||
Packet ();
|
||||
/**
|
||||
* Create a packet with a zero-filled payload.
|
||||
* The memory necessary for the payload is not allocated:
|
||||
* it will be allocated at any later point if you attempt
|
||||
* to fragment this packet or to access the zero-filled
|
||||
* bytes. The packet is allocated with a new uid (as
|
||||
* returned by getUid).
|
||||
*
|
||||
* \param size the size of the zero-filled payload
|
||||
*/
|
||||
Packet (uint32_t size);
|
||||
@end verbatim
|
||||
|
||||
@subsection Adding and removing Buffer data
|
||||
The below code is reproduced for Header class only; similar functions
|
||||
exist for Trailers.
|
||||
@verbatim
|
||||
/**
|
||||
* Add header to this packet. This method invokes the
|
||||
* ns3::Header::serializeTo method to request the header to serialize
|
||||
* itself in the packet buffer.
|
||||
*
|
||||
* \param header a reference to the header to add to this packet.
|
||||
*/
|
||||
void Add (Header const &header);
|
||||
/**
|
||||
* Deserialize header from this packet. This method invokes the
|
||||
* ns3::Header::deserializeFrom method to request the header to deserialize
|
||||
* itself from the packet buffer. This method does not remove
|
||||
* the data from the buffer. It merely reads it.
|
||||
*
|
||||
* \param header a reference to the header to deserialize from the buffer
|
||||
*/
|
||||
void Peek (Header &header);
|
||||
/**
|
||||
* Remove a deserialized header from the internal buffer.
|
||||
* This method removes the bytes read by Packet::peek from
|
||||
* the packet buffer.
|
||||
*
|
||||
* \param header a reference to the header to remove from the internal buffer.
|
||||
*/
|
||||
void Remove (Header const &header);
|
||||
/**
|
||||
* Add trailer to this packet. This method invokes the
|
||||
* ns3::Trailer::serializeTo method to request the trailer to serialize
|
||||
* itself in the packet buffer.
|
||||
*
|
||||
* \param trailer a reference to the trailer to add to this packet.
|
||||
*/
|
||||
@end verbatim
|
||||
|
||||
@subsection Adding and removing Tags
|
||||
@verbatim
|
||||
/**
|
||||
* Attach a tag to this packet. The tag is fully copied
|
||||
* in a packet-specific internal buffer. This operation
|
||||
* is expected to be really fast.
|
||||
*
|
||||
* \param tag a pointer to the tag to attach to this packet.
|
||||
*/
|
||||
template <typename T>
|
||||
void AddTag (T const &tag);
|
||||
/**
|
||||
* Remove a tag from this packet. The data stored internally
|
||||
* for this tag is copied in the input tag if an instance
|
||||
* of this tag type is present in the internal buffer. If this
|
||||
* tag type is not present, the input tag is not modified.
|
||||
*
|
||||
* This operation can be potentially slow and might trigger
|
||||
* unexpectedly large memory allocations. It is thus
|
||||
* usually a better idea to create a copy of this packet,
|
||||
* and invoke removeAllTags on the copy to remove all
|
||||
* tags rather than remove the tags one by one from a packet.
|
||||
*
|
||||
* \param tag a pointer to the tag to remove from this packet
|
||||
* \returns true if an instance of this tag type is stored
|
||||
* in this packet, false otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
bool RemoveTag (T &tag);
|
||||
/**
|
||||
* Copy a tag stored internally to the input tag. If no instance
|
||||
* of this tag is present internally, the input tag is not modified.
|
||||
*
|
||||
* \param tag a pointer to the tag to read from this packet
|
||||
* \returns true if an instance of this tag type is stored
|
||||
* in this packet, false otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
bool PeekTag (T &tag) const;
|
||||
/**
|
||||
* Remove all the tags stored in this packet. This operation is
|
||||
* much much faster than invoking removeTag n times.
|
||||
*/
|
||||
void RemoveAllTags (void);
|
||||
@end verbatim
|
||||
|
||||
@subsection Fragmentation
|
||||
@verbatim
|
||||
/**
|
||||
* Create a new packet which contains a fragment of the original
|
||||
* packet. The returned packet shares the same uid as this packet.
|
||||
*
|
||||
* \param start offset from start of packet to start of fragment to create
|
||||
* \param length length of fragment to create
|
||||
* \returns a fragment of the original packet
|
||||
*/
|
||||
Packet CreateFragment (uint32_t start, uint32_t length) const;
|
||||
|
||||
/**
|
||||
* Concatenate the input packet at the end of the current
|
||||
* packet. This does not alter the uid of either packet.
|
||||
*
|
||||
* \param packet packet to concatenate
|
||||
*/
|
||||
void addAtEnd (Packet packet);
|
||||
|
||||
/oncatenate the input packet at the end of the current
|
||||
* packet. This does not alter the uid of either packet.
|
||||
*
|
||||
* \param packet packet to concatenate
|
||||
*/
|
||||
void AddAtEnd (Packet packet);
|
||||
/**
|
||||
* Concatenate the fragment of the input packet identified
|
||||
* by the offset and size parameters at the end of the current
|
||||
* packet. This does not alter the uid of either packet.
|
||||
*
|
||||
* \param packet to concatenate
|
||||
* \param offset offset of fragment to copy from the start of the input packet
|
||||
* \param size size of fragment of input packet to copy.
|
||||
*/
|
||||
void AddAtEnd (Packet packet, uint32_t offset, uint32_t size);
|
||||
/**
|
||||
* Remove size bytes from the end of the current packet
|
||||
* It is safe to remove more bytes that what is present in
|
||||
* the packet.
|
||||
*
|
||||
* \param size number of bytes from remove
|
||||
*/
|
||||
void RemoveAtEnd (uint32_t size);
|
||||
/**
|
||||
* Remove size bytes from the start of the current packet.
|
||||
* It is safe to remove more bytes that what is present in
|
||||
* the packet.
|
||||
*
|
||||
* \param size number of bytes from remove
|
||||
*/
|
||||
void RemoveAtStart (uint32_t size);
|
||||
@end verbatim
|
||||
|
||||
@subsection Miscellaneous
|
||||
@verbatim
|
||||
/**
|
||||
* \returns the size in bytes of the packet (including the zero-filled
|
||||
* initial payload)
|
||||
*/
|
||||
uint32_t GetSize (void) const;
|
||||
/**
|
||||
* If you try to change the content of the buffer
|
||||
* returned by this method, you will die.
|
||||
*
|
||||
* \returns a pointer to the internal buffer of the packet.
|
||||
*/
|
||||
uint8_t const *PeekData (void) const;
|
||||
/**
|
||||
* A packet is allocated a new uid when it is created
|
||||
* empty or with zero-filled payload.
|
||||
*
|
||||
* \returns an integer identifier which uniquely
|
||||
* identifies this packet.
|
||||
*/
|
||||
uint32_t GetUid (void) const;
|
||||
@end verbatim
|
||||
|
||||
@section Using Headers
|
||||
@emph{walk through an example of adding a UDP header}
|
||||
|
||||
@section Using Tags
|
||||
@emph{walk through an example of adding a flow ID}
|
||||
|
||||
@section Using Fragmentation
|
||||
@emph{walk through an example of link-layer fragmentation/reassembly}
|
||||
|
||||
@section Sample program
|
||||
The below sample program (from @code{ns3/samples/main-packet.cc}) illustrates
|
||||
some use of the Packet, Header, and Tag classes.
|
||||
|
||||
@verbatim
|
||||
/* -*- Mode:C++; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/header.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/* A sample Header implementation
|
||||
*/
|
||||
class MyHeader : public Header {
|
||||
public:
|
||||
MyHeader ();
|
||||
virtual ~MyHeader ();
|
||||
|
||||
void SetData (uint16_t data);
|
||||
uint16_t GetData (void) const;
|
||||
private:
|
||||
virtual void PrintTo (std::ostream &os) const;
|
||||
virtual void SerializeTo (Buffer::Iterator start) const;
|
||||
virtual void DeserializeFrom (Buffer::Iterator start);
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
|
||||
uint16_t m_data;
|
||||
};
|
||||
|
||||
MyHeader::MyHeader ()
|
||||
{}
|
||||
MyHeader::~MyHeader ()
|
||||
{}
|
||||
void
|
||||
MyHeader::PrintTo (std::ostream &os) const
|
||||
{
|
||||
os << "MyHeader data=" << m_data << std::endl;
|
||||
}
|
||||
uint32_t
|
||||
MyHeader::GetSerializedSize (void) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
void
|
||||
MyHeader::SerializeTo (Buffer::Iterator start) const
|
||||
{
|
||||
// serialize in head of buffer
|
||||
start.WriteHtonU16 (m_data);
|
||||
}
|
||||
void
|
||||
MyHeader::DeserializeFrom (Buffer::Iterator start)
|
||||
{
|
||||
// deserialize from head of buffer
|
||||
m_data = start.ReadNtohU16 ();
|
||||
}
|
||||
|
||||
void
|
||||
MyHeader::SetData (uint16_t data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
uint16_t
|
||||
MyHeader::GetData (void) const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/* A sample Tag implementation
|
||||
*/
|
||||
struct MyTag {
|
||||
uint16_t m_streamId;
|
||||
};
|
||||
|
||||
static TagRegistration<struct MyTag> g_MyTagRegistration ("ns3::MyTag", 0);
|
||||
|
||||
|
||||
static void
|
||||
Receive (Packet p)
|
||||
{
|
||||
MyHeader my;
|
||||
p.Peek (my);
|
||||
p.Remove (my);
|
||||
std::cout << "received data=" << my.GetData () << std::endl;
|
||||
struct MyTag myTag;
|
||||
p.PeekTag (myTag);
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Packet p;
|
||||
MyHeader my;
|
||||
my.SetData (2);
|
||||
std::cout << "send data=2" << std::endl;
|
||||
p.Add (my);
|
||||
struct MyTag myTag;
|
||||
myTag.m_streamId = 5;
|
||||
p.AddTag (myTag);
|
||||
Receive (p);
|
||||
return 0;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
@section Implementation details
|
||||
|
||||
@subsection Private member variables
|
||||
|
||||
A Packet object's interface provides access to some private
|
||||
data:
|
||||
@verbatim
|
||||
Buffer m_buffer;
|
||||
Tags m_tags;
|
||||
uint32_t m_uid;
|
||||
static uint32_t m_global_uid;
|
||||
@end verbatim
|
||||
Each Packet has a Buffer and a Tags object, and a 32-bit unique ID (m\_uid).
|
||||
A static member variable keeps track of the UIDs allocated. Note
|
||||
that real network packets do not have a UID; the UID is therefore an
|
||||
instance of data that normally would be stored as a Tag in the packet.
|
||||
However, it was felt that a UID is a special case that is so often
|
||||
used in simulations that it would be more convenient to store it
|
||||
in a member variable.
|
||||
|
||||
@subsection Buffer implementation
|
||||
|
||||
Class Buffer represents a buffer of bytes. Its size is
|
||||
automatically adjusted to hold any data prepended
|
||||
or appended by the user. Its implementation is optimized
|
||||
to ensure that the number of buffer resizes is minimized,
|
||||
by creating new Buffers of the maximum size ever used.
|
||||
The correct maximum size is learned at runtime during use by
|
||||
recording the maximum size of each packet.
|
||||
|
||||
Authors of new Header or Trailer classes need to know the public
|
||||
API of the Buffer class. (add summary here)
|
||||
|
||||
The byte buffer is implemented as follows:
|
||||
@verbatim
|
||||
struct BufferData {
|
||||
uint32_t m_count;
|
||||
uint32_t m_size;
|
||||
uint32_t m_initialStart;
|
||||
uint32_t m_dirtyStart;
|
||||
uint32_t m_dirtySize;
|
||||
uint8_t m_data[1];
|
||||
};
|
||||
struct BufferData *m_data;
|
||||
uint32_t m_zeroAreaSize;
|
||||
uint32_t m_start;
|
||||
uint32_t m_size;
|
||||
@end verbatim
|
||||
|
||||
@itemize @bullet
|
||||
@item @code{BufferData::m_count}: reference count for BufferData structure
|
||||
@item @code{BufferData::m_size}: size of data buffer stored in BufferData structure
|
||||
@item @code{BufferData::m_initialStart}: offset from start of data buffer where data was first inserted
|
||||
@item @code{BufferData::m_dirtyStart}: offset from start of buffer where every Buffer which holds a reference to this BufferData instance have written data so far
|
||||
@item @code{BufferData::m_dirtySize}: size of area where data has been written so far
|
||||
@item @code{BufferData::m_data}: pointer to data buffer
|
||||
@item @code{Buffer::m_zeroAreaSize}: size of zero area which extends before @code{m_initialStart}
|
||||
@item @code{Buffer::m_start}: offset from start of buffer to area used by this buffer
|
||||
@item @code{Buffer::m_size}: size of area used by this Buffer in its BufferData structure
|
||||
@end itemize
|
||||
|
||||
@float Figure,fig:buffer
|
||||
@caption{Implementation overview of a packet's byte Buffer.}
|
||||
@image{figures/buffer,15cm}
|
||||
@end float
|
||||
|
||||
This data structure is summarized in Figure @ref{fig:buffer}.
|
||||
Each Buffer holds a pointer to an instance of a BufferData. Most
|
||||
Buffers should be able to share the same underlying BufferData and
|
||||
thus simply increase the BufferData's reference count. If they have to
|
||||
change the content of a BufferData inside the Dirty Area, and if the
|
||||
reference count is not one, they first create a copy of the BufferData and
|
||||
then complete their state-changing operation.
|
||||
|
||||
@subsection Tags implementation
|
||||
Tags are implemented by a single pointer which points to the start of a
|
||||
linked list ofTagData data structures. Each TagData structure points
|
||||
to the next TagData in the list (its next pointer contains zero to
|
||||
indicate the end of the linked list). Each TagData contains an integer
|
||||
unique id which identifies the type of the tag stored in the TagData.
|
||||
@verbatim
|
||||
struct TagData {
|
||||
struct TagData *m_next;
|
||||
uint32_t m_id;
|
||||
uint32_t m_count;
|
||||
uint8_t m_data[Tags::SIZE];
|
||||
};
|
||||
class Tags {
|
||||
struct TagData *m_next;
|
||||
};
|
||||
@end verbatim
|
||||
|
||||
Adding a tag is a matter of inserting a new TagData at the head of
|
||||
the linked list. Looking at a tag requires you to find the relevant
|
||||
TagData in the linked list and copy its data into the user data
|
||||
structure. Removing a tag and updating the content of a tag
|
||||
requires a deep copy of the linked list before performing this operation.
|
||||
On the other hand, copying a Packet and its tags is a matter of
|
||||
copying the TagData head pointer and incrementing its reference count.
|
||||
|
||||
Tags are found by the unique mapping betweent the Tag type and
|
||||
its underlying id. This is why at most one instance of any Tag
|
||||
can be stored in a packet. The mapping between Tag type and
|
||||
underlying id is performed by a registration as follows:
|
||||
@verbatim
|
||||
/* A sample Tag implementation
|
||||
*/
|
||||
struct MyTag {
|
||||
uint16_t m_streamId;
|
||||
};
|
||||
@end verbatim
|
||||
|
||||
@emph{add description of TagRegistration for printing}
|
||||
|
||||
@subsection Memory management
|
||||
|
||||
@emph{Describe free list.}
|
||||
|
||||
@emph{Describe dataless vs. data-full packets.}
|
||||
|
||||
@subsection Copy-on-write semantics
|
||||
The current implementation of the byte buffers and tag list is based
|
||||
on COW (Copy On Write). An introduction to COW can be found in Scott
|
||||
Meyer's "More Effective C++", items 17 and 29). This design feature
|
||||
and aspects of the public interface borrows from the packet design
|
||||
of the Georgia Tech Network Simulator.
|
||||
This implementation of COW uses a customized reference counting
|
||||
smart pointer class.
|
||||
|
||||
What COW means is that
|
||||
copying packets without modifying them is very cheap (in terms of CPU
|
||||
and memory usage) and modifying them can be also very cheap. What is
|
||||
key for proper COW implementations is being
|
||||
able to detect when a given modification of the state of a packet triggers
|
||||
a full copy of the data prior to the modification: COW systems need
|
||||
to detect when an operation is ``dirty'' and must therefore invoke
|
||||
a true copy.
|
||||
|
||||
Dirty operations:
|
||||
@itemize @bullet
|
||||
@item Packet::RemoveTag()
|
||||
@item Packet::Add()
|
||||
@item both versions of ns3::Packet::AddAtEnd()
|
||||
@end itemize
|
||||
|
||||
Non-dirty operations:
|
||||
@itemize @bullet
|
||||
@item Packet::AddTag()
|
||||
@item Packet::RemoveAllTags()
|
||||
@item Packet::PeekTag()
|
||||
@item Packet::Peek()
|
||||
@item Packet::Remove()
|
||||
@item Packet::CreateFragment()
|
||||
@item Packet::RemoveAtStart()
|
||||
@item Packet::RemoveAtEnd()
|
||||
@end itemize
|
||||
|
||||
Dirty operations will always be slower than non-dirty operations,
|
||||
sometimes by several orders of magnitude. However, even the
|
||||
dirty operations have been optimized for common use-cases which
|
||||
means that most of the time, these operations will not trigger
|
||||
data copies and will thus be still very fast.
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
@node ns-3 routing overview
|
||||
@chapter ns-3 routing overview
|
||||
|
||||
This chapter describes the overall design of routing in the
|
||||
@code{src/internet-node}
|
||||
module, and some details about the routing approachs currently
|
||||
implemented.
|
||||
|
||||
@node Routing-Overview
|
||||
@section Overview
|
||||
|
||||
We intend to support traditional routing approaches and protocols,
|
||||
ports of open source routing implementations, and facilitate research
|
||||
into unorthodox routing techniques.
|
||||
For simulations that are not primarily focused on routing and that
|
||||
simply want correct routing tables to occur somehow, we have an
|
||||
global centralized routing capability. A singleton object
|
||||
(GlobalRouteManager) be instantiated, builds a network map, and
|
||||
populates a forwarding table on each node at time t=0 in the
|
||||
simulation. Simulation script writers can use the same node
|
||||
API to manually enter routes as well.
|
||||
|
||||
@node Support for multiple routing protocols
|
||||
@section Support for multiple routing protocols
|
||||
|
||||
Typically, multiple routing protocols are supported in user space and
|
||||
coordinate to write a single forwarding table in the kernel. Presently
|
||||
in @command{ns-3}, the implementation instead allows for multiple routing
|
||||
protocols to build/keep their own routing state, and the IPv4 implementation
|
||||
will query each one of these routing protocols (in some order determined
|
||||
by the simulation author) until a route is found.
|
||||
|
||||
We chose this approach because it may better
|
||||
faciliate the integration of disparate routing approaches that may
|
||||
be difficult to coordinate the writing to a single table, approaches
|
||||
where more information than destination IP address (e.g., source
|
||||
routing) is used to determine the next hop, and on-demand
|
||||
routing approaches where packets must be cached.
|
||||
|
||||
There are presently two routing protocols defined:
|
||||
@itemize @bullet
|
||||
@item class Ipv4StaticRouting (covering both unicast and multicast)
|
||||
@item Optimized Link State Routing (a MANET protocol defined in
|
||||
@uref{http://www.ietf.org/rfc/rfc3626.txt,,RFC 3626})
|
||||
@end itemize
|
||||
but first we describe how multiple routing protocols are supported.
|
||||
|
||||
@subsection class Ipv4RoutingProtocol
|
||||
|
||||
@code{class Ipv4RoutingProtocol} derives from ns-3 Object which means
|
||||
that it supports interface aggregation and reference counting. Routing
|
||||
protocols should inherit from this class, defined in src/node/ipv4.cc.
|
||||
|
||||
The main function that must be supported by these protocols is called
|
||||
@code{RequestRoute}.
|
||||
@verbatim
|
||||
* This method is called whenever a node's IPv4 forwarding engine
|
||||
* needs to lookup a route for a given packet and IP header.
|
||||
*
|
||||
* The routing protocol implementation may determine immediately it
|
||||
* should not be handling this particular the route request. For
|
||||
* instance, a routing protocol may decline to search for routes for
|
||||
* certain classes of addresses, like link-local. In this case,
|
||||
* RequestRoute() should return false and the routeReply callback
|
||||
* must not be invoked.
|
||||
*
|
||||
* If the routing protocol implementations assumes it can provide
|
||||
* the requested route, then it should return true, and the
|
||||
* routeReply callback must be invoked, either immediately before
|
||||
* returning true (synchronously), or in the future (asynchronous).
|
||||
* The routing protocol may use any information available in the IP
|
||||
* header and packet as routing key, although most routing protocols
|
||||
* use only the destination address (as given by
|
||||
* ipHeader.GetDestination ()). The routing protocol is also
|
||||
* allowed to add a new header to the packet, which will appear
|
||||
* immediately after the IP header, although most routing do not
|
||||
* insert any extra header.
|
||||
*/
|
||||
virtual bool RequestRoute (uint32_t ifIndex,
|
||||
const Ipv4Header &ipHeader,
|
||||
Ptr<Packet> packet,
|
||||
RouteReplyCallback routeReply) = 0;
|
||||
@end verbatim
|
||||
|
||||
This class also provides a typedef (used above) for a special Callback
|
||||
that will pass to the callback function the Ipv4Route that is found (see the
|
||||
Doxygen documentation):
|
||||
@verbatim
|
||||
typedef Callback<void, bool, const Ipv4Route&, Ptr<Packet>, const Ipv4Header&> RouteReplyCallback;
|
||||
@end verbatim
|
||||
|
||||
@subsection Ipv4::AddRoutingProtocol
|
||||
|
||||
Class Ipv4 provides a pure virtual function declaration for the
|
||||
method that allows one to add a routing protocol:
|
||||
@verbatim
|
||||
void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
|
||||
int16_t priority);
|
||||
@end verbatim
|
||||
This method is implemented by class Ipv4L3Protocol in the internet-node
|
||||
module.
|
||||
|
||||
The priority variable above governs the priority in which the routing
|
||||
protocols are inserted. Notice that it is a signed int.
|
||||
When the class Ipv4L3Protocol is instantiated, a single routing
|
||||
protocol (Ipv4StaticRouting, introduced below) is added at priority
|
||||
zero. Internally, a list of Ipv4RoutingProtocols is stored, and
|
||||
and the routing protocols are each consulted in decreasing order
|
||||
of priority to see whether a match is found. Therefore, if you
|
||||
want your Ipv4RoutingProtocol to have priority lower than the static
|
||||
routing, insert it with priority less than 0; e.g.:
|
||||
@verbatim
|
||||
m_ipv4->AddRoutingProtocol (m_routingTable, -10);
|
||||
@end verbatim
|
||||
|
||||
@subsection Ipv4L3Protocol::Lookup
|
||||
|
||||
The main function for obtaining a route is shown below:
|
||||
@verbatim
|
||||
Ipv4L3Protocol::Lookup (
|
||||
uint32_t ifIndex,
|
||||
Ipv4Header const &ipHeader,
|
||||
Ptr<Packet> packet,
|
||||
Ipv4RoutingProtocol::RouteReplyCallback routeReply)
|
||||
@end verbatim
|
||||
|
||||
This function will search the list of routing protocols, in priority order,
|
||||
until a route is found. It will then invoke the RouteReplyCallback
|
||||
and no further routing protocols will be searched. If the caller does
|
||||
not want to constrain the possible interface, it can be wildcarded
|
||||
as such:
|
||||
@verbatim
|
||||
Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
|
||||
@end verbatim
|
||||
|
||||
@node Roadmap and Future work
|
||||
@section Roadmap and Future work
|
||||
|
||||
Some goals for future support are:
|
||||
|
||||
Users should be able to trace (either debug print, or redirect to a trace
|
||||
file) the routing table in a format such as used in an
|
||||
Unix implementation:
|
||||
@verbatim
|
||||
# netstat -nr (or # route -n)
|
||||
Kernel IP routing table
|
||||
Destination Gateway Genmask Flags MSS Window irtt Iface
|
||||
127.0.0.1 * 255.255.255.255 UH 0 0 0 lo
|
||||
172.16.1.0 * 255.255.255.0 U 0 0 0 eth0
|
||||
172.16.2.0 172.16.1.1 255.255.255.0 UG 0 0 0 eth0
|
||||
|
||||
# ip route show
|
||||
192.168.99.0/24 dev eth0 scope link
|
||||
127.0.0.0/8 dev lo scope link
|
||||
default via 192.168.99.254 dev eth0
|
||||
@end verbatim
|
||||
|
||||
Global computation of multicast routing should be implemented as well.
|
||||
This would ignore group membership and ensure that a copy of every
|
||||
sourced multicast datagram would be delivered to each node.
|
||||
This might be implemented as an RPF mechanism that functioned on-demand
|
||||
by querying the forwarding table,
|
||||
and perhaps optimized by a small multicast forwarding cache. It is
|
||||
a bit trickier to implement over wireless links where the input
|
||||
interface is the same as the output interface; other aspects of the
|
||||
packet must be considered and the forwarding logic slightly changed
|
||||
to allow for forwarding out the same interface.
|
||||
|
||||
In the future, work on bringing XORP or quagga routing to ns, but it will
|
||||
take several months to port and enable.
|
||||
|
||||
There are presently no roadmap plans for IPv6.
|
||||
|
||||
@node Static routing
|
||||
@section Static routing
|
||||
|
||||
The internet-node module provides one routing protocol (Ipv4StaticRouting)
|
||||
by default. This routing protocol allows one to add unicast or multicast
|
||||
static routes to a node.
|
||||
|
||||
@node Unicast routing
|
||||
@section Unicast routing
|
||||
|
||||
The unicast static routing API may be accessed via the functions
|
||||
@verbatim
|
||||
void Ipv4::AddHostRouteTo ()
|
||||
void Ipv4::AddNetworkRouteTo ()
|
||||
void Ipv4::SetDefaultRoute ()
|
||||
uint32_t Ipv4::GetNRoutes ()
|
||||
Ipv4Route Ipv4::GetRoute ()
|
||||
@end verbatim
|
||||
|
||||
@uref{http://www.nsnam.org/doxygen/index.html,,Doxygen} documentation
|
||||
provides full documentation of these methods. These methods are forwarding
|
||||
functions to the actual implementation in Ipv4StaticRouting, when using
|
||||
the internet-node module.
|
||||
|
||||
@node Multicast routing
|
||||
@section Multicast routing
|
||||
|
||||
The following function is used to add a static multicast route
|
||||
to a node:
|
||||
@verbatim
|
||||
void
|
||||
Ipv4StaticRouting::AddMulticastRoute (Ipv4Address origin,
|
||||
Ipv4Address group,
|
||||
uint32_t inputInterface,
|
||||
std::vector<uint32_t> outputInterfaces);
|
||||
@end verbatim
|
||||
|
||||
A multicast route must specify an origin IP address, a multicast group and
|
||||
an input network interface index as conditions and provide a vector of
|
||||
output network interface indices over which packets matching the conditions
|
||||
are sent.
|
||||
|
||||
Typically there are two main types of multicast routes: routes of the
|
||||
first kind are used during forwarding. All of the conditions must be
|
||||
exlicitly provided. The second kind of routes are used to get packets off
|
||||
of a local node. The difference is in the input interface. Routes for
|
||||
forwarding will always have an explicit input interface specified. Routes
|
||||
off of a node will always set the input interface to a wildcard specified
|
||||
by the index Ipv4RoutingProtocol::IF\_INDEX\_ANY.
|
||||
|
||||
For routes off of a local node wildcards may be used in the origin and
|
||||
multicast group addresses. The wildcard used for Ipv4Adresses is that
|
||||
address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage
|
||||
of a wildcard allows one to specify default behavior to varying degrees.
|
||||
|
||||
For example, making the origin address a wildcard, but leaving the
|
||||
multicast group specific allows one (in the case of a node with multiple
|
||||
interfaces) to create different routes using different output interfaces
|
||||
for each multicast group.
|
||||
|
||||
If the origin and multicast addresses are made wildcards, you have created
|
||||
essentially a default multicast address that can forward to multiple
|
||||
interfaces. Compare this to the actual default multicast address that is
|
||||
limited to specifying a single output interface for compatibility with
|
||||
existing functionality in other systems.
|
||||
|
||||
Another command sets the default multicast route:
|
||||
@verbatim
|
||||
void
|
||||
Ipv4StaticRouting::SetDefaultMulticastRoute (uint32_t outputInterface);
|
||||
@end verbatim
|
||||
|
||||
This is the multicast equivalent of the unicast version SetDefaultRoute.
|
||||
We tell the routing system what to do in the case where a specific route
|
||||
to a destination multicast group is not found. The system forwards
|
||||
packets out the specified interface in the hope that "something out there"
|
||||
knows better how to route the packet. This method is only used in
|
||||
initially sending packets off of a host. The default multicast route is
|
||||
not consulted during forwarding -- exact routes must be specified using
|
||||
AddMulticastRoute for that case.
|
||||
|
||||
Since we're basically sending packets to some entity we think may know
|
||||
better what to do, we don't pay attention to "subtleties" like origin
|
||||
address, nor do we worry about forwarding out multiple interfaces. If the
|
||||
default multicast route is set, it is returned as the selected route from
|
||||
LookupStatic irrespective of origin or multicast group if another specific
|
||||
route is not found.
|
||||
|
||||
Finally, a number of additional functions are provided to fetch and
|
||||
remove multicast routes:
|
||||
@verbatim
|
||||
uint32_t GetNMulticastRoutes (void) const;
|
||||
|
||||
Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
|
||||
|
||||
Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const;
|
||||
|
||||
bool RemoveMulticastRoute (Ipv4Address origin,
|
||||
Ipv4Address group,
|
||||
uint32_t inputInterface);
|
||||
|
||||
void RemoveMulticastRoute (uint32_t index);
|
||||
@end verbatim
|
||||
|
||||
@node Global centralized routing
|
||||
@section Global centralized routing
|
||||
|
||||
Presently, global centralized IPv4 @emph{unicast} routing over both
|
||||
point-to-point and shared (CSMA) links is supported.
|
||||
The global centralized routing will be modified in the future to
|
||||
reduce computations once profiling finds the performance bottlenecks.
|
||||
|
||||
@node Global Unicast Routing API
|
||||
@section Global Unicast Routing API
|
||||
|
||||
The public API is very minimal. User scripts include the following:
|
||||
@verbatim
|
||||
#include "ns3/global-route-manager.h"
|
||||
@end verbatim
|
||||
|
||||
After IP addresses are configured, the following function call will
|
||||
cause all of the nodes that have an Ipv4 interface to receive
|
||||
forwarding tables entered automatically by the GlobalRouteManager:
|
||||
@verbatim
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
@end verbatim
|
||||
|
||||
@emph{Note:} A reminder that the wifi NetDevice is not yet supported
|
||||
(only CSMA and PointToPoint).
|
||||
|
||||
@node Global Routing Implementation
|
||||
@section Global Routing Implementation
|
||||
|
||||
A singleton object (GlobalRouteManager) is responsible for populating
|
||||
the static routes on each node, using the public Ipv4 API of that node.
|
||||
It queries each node in the topology for a "globalRouter" interface.
|
||||
If found, it uses the API of that interface to obtain a "link state
|
||||
advertisement (LSA)" for the router. Link State Advertisements
|
||||
are used in OSPF routing, and we follow their formatting.
|
||||
|
||||
The GlobalRouteManager populates a link state database with LSAs
|
||||
gathered from the entire topology. Then, for each router in the topology,
|
||||
the GlobalRouteManager executes the OSPF shortest path first (SPF)
|
||||
computation on the database, and populates the routing tables on each
|
||||
node.
|
||||
|
||||
The quagga (http://www.quagga.net) OSPF implementation was used as the
|
||||
basis for the routing computation logic.
|
||||
One benefit of following an existing OSPF SPF implementation is that
|
||||
OSPF already has defined link state advertisements for all common
|
||||
types of network links:
|
||||
@itemize @bullet
|
||||
@item point-to-point (serial links)
|
||||
@item point-to-multipoint (Frame Relay, ad hoc wireless)
|
||||
@item non-broadcast multiple access (ATM)
|
||||
@item broadcast (Ethernet)
|
||||
@end itemize
|
||||
Therefore, we think that enabling these other link types will be more
|
||||
straightforward now that the underlying OSPF SPF framework is in place.
|
||||
|
||||
Presently, we can handle IPv4 point-to-point, numbered links, as well
|
||||
as shared broadcast (CSMA) links, and we do not do equal-cost multipath.
|
||||
|
||||
The GlobalRouteManager first walks the list of nodes and aggregates
|
||||
a GlobalRouter interface to each one as follows:
|
||||
@verbatim
|
||||
typedef std::vector < Ptr<Node> >::iterator Iterator;
|
||||
for (Iterator i = NodeList::Begin (); i != NodeList::End (); i++)
|
||||
{
|
||||
Ptr<Node> node = *i;
|
||||
Ptr<GlobalRouter> globalRouter = CreateObject<GlobalRouter> (node);
|
||||
node->AggregateObject (globalRouter);
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
This interface is later queried and used to generate a Link State
|
||||
Advertisement for each router, and this link state database is
|
||||
fed into the OSPF shortest path computation logic. The Ipv4 API
|
||||
is finally used to populate the routes themselves.
|
||||
|
||||
@node Optimized Link State Routing (OLSR)
|
||||
@section Optimized Link State Routing (OLSR)
|
||||
|
||||
This is the first dynamic routing protocol for @command{ns-3}. The implementation
|
||||
is found in the src/routing/olsr directory, and an example script is in
|
||||
examples/simple-point-to-point-olsr.cc.
|
||||
|
||||
The following commands will enable OLSR in a simulation.
|
||||
|
||||
@verbatim
|
||||
olsr::EnableAllNodes (); // Start OLSR on all nodes
|
||||
olsr::EnableNodes(InputIterator begin, InputIterator end); // Start on
|
||||
// a list of nodes
|
||||
olsr::EnableNode (Ptr<Node> node); // Start OLSR on "node" only
|
||||
@end verbatim
|
||||
|
||||
Once instantiated, the agent can be started with the Start() command,
|
||||
and the OLSR "main interface" can be set with the SetMainInterface()
|
||||
command. A number of protocol constants are defined in olsr-agent-impl.cc.
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
@node Sockets APIs
|
||||
@chapter Sockets APIs
|
||||
|
||||
The @uref{http://en.wikipedia.org/wiki/Berkeley_sockets,,sockets API}
|
||||
is a long-standing API used by user-space applications to access
|
||||
network services in the kernel. A ``socket'' is an abstraction, like
|
||||
a Unix file handle, that allows applications to connect to other
|
||||
Internet hosts and exchange reliable byte streams and unreliable
|
||||
datagrams, among other services.
|
||||
|
||||
ns-3 provides two types of sockets APIs, and it is important to
|
||||
understand the differences between them. The first is a @emph{native}
|
||||
ns-3 API, while the second uses the services of the native API to
|
||||
provide a @uref{http://en.wikipedia.org/wiki/POSIX,,POSIX-like}
|
||||
API as part of an overall application process. Both APIs strive
|
||||
to be close to the typical sockets API that application writers
|
||||
on Unix systems are accustomed to, but the POSIX variant is much
|
||||
closer to a real system's sockets API.
|
||||
|
||||
@section ns-3 sockets API
|
||||
|
||||
The native sockets API for ns-3 provides an interface to various
|
||||
types of transport protocols (TCP, UDP) as well as to packet sockets
|
||||
and, in the future, Netlink-like sockets. However, users are cautioned
|
||||
to understand that the semantics are @strong{not} the exact same as
|
||||
one finds in a real system (for an API which is very much aligned
|
||||
to real systems, see the next section).
|
||||
|
||||
@code{class ns3::Socket} is defined in @code{src/node/socket.cc,h}.
|
||||
Readers will note that many public member functions are aligned
|
||||
with real sockets function calls, and all other things being equal,
|
||||
we have tried to align with a Posix sockets API. However, note that:
|
||||
|
||||
@itemize @bullet
|
||||
@item ns-3 applications handle a smart pointer to a Socket object, not
|
||||
a file descriptor;
|
||||
@item there is no notion of synchronous API or a ``blocking'' API;
|
||||
in fact, the model for interaction between application and socket is
|
||||
one of asynchronous I/O, which is not typically found in real systems
|
||||
(more on this below);
|
||||
@item the C-style socket address structures are not used;
|
||||
@item the API is not a complete sockets API, such as supporting
|
||||
all socket options or all function variants;
|
||||
@item many calls use @code{ns3::Packet} class to transfer data
|
||||
between application and socket. This may seem a little funny to
|
||||
people to pass ``Packets'' across a stream socket API, but think
|
||||
of these packets as just fancy byte buffers at this level (more
|
||||
on this also below).
|
||||
@end itemize
|
||||
|
||||
@subsection Basic operation and calls
|
||||
|
||||
@float Figure,fig:sockets-overview
|
||||
@caption{Implementation overview of native sockets API}
|
||||
@image{figures/sockets-overview, 10cm}
|
||||
@end float
|
||||
|
||||
@subsubsection Creating sockets
|
||||
|
||||
An application that wants to use sockets must first create one.
|
||||
On real systems, this is accomplished by calling socket():
|
||||
@verbatim
|
||||
int
|
||||
socket(int domain, int type, int protocol);
|
||||
@end verbatim
|
||||
which creates a socket in the system and returns an integer descriptor.
|
||||
|
||||
In ns-3, we have no equivalent of a system call at the lower layers,
|
||||
so we adopt the following model. There are certain @emph{factory}
|
||||
objects that can create sockets. Each factory is capable of creating
|
||||
one type of socket, and if sockets of a particular type are able to
|
||||
be created on a given node, then a factory that can create such sockets
|
||||
must be aggregated to the Node.
|
||||
@verbatim
|
||||
static Ptr<Socket> CreateSocket (Ptr<Node> node, TypeId tid);
|
||||
@end verbatim
|
||||
Examples of TypeIds to pass to this method are @code{TcpSocketFactory},
|
||||
@code{PacketSocketFactory}, and @code{UdpSocketFactory}.
|
||||
|
||||
This method returns a smart pointer to a Socket object. Here is an
|
||||
example:
|
||||
@verbatim
|
||||
Ptr<Node> n0;
|
||||
// Do some stuff to build up the Node's internet stack
|
||||
Ptr<Socket> localSocket = Socket::CreateSocket (n0, TcpSocketFactory::GetTypeId ());
|
||||
@end verbatim
|
||||
|
||||
In some ns-3 code, sockets will not be explicitly created by user's
|
||||
main programs, if an ns-3 application does it. For instance, for
|
||||
@code{class ns3::OnOffApplication}, the function @code{StartApplication()}
|
||||
performs the socket creation, and the application holds the socket
|
||||
pointer.
|
||||
|
||||
@subsubsection Using sockets
|
||||
|
||||
Below is a typical sequence of socket calls for a TCP client in a
|
||||
real implementation:
|
||||
@itemize @bullet
|
||||
@item @code{sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);}
|
||||
@item @code{bind(sock, ...);}
|
||||
@item @code{connect(sock, ...);}
|
||||
@item @code{send(sock, ...);}
|
||||
@item @code{recv(sock, ...);}
|
||||
@item @code{close(sock);}
|
||||
@end itemize
|
||||
|
||||
There are analogs to all of these calls in ns-3, but we will focus on
|
||||
two aspects here. First, most usage of sockets in real systems
|
||||
requires a way to manage I/O between the application and kernel.
|
||||
These models include @emph{blocking sockets}, @emph{signal-based I/O},
|
||||
and @emph{non-blocking sockets} with polling. In ns-3, we make use
|
||||
of the callback mechanisms to support a fourth mode, which is
|
||||
analogous to POSIX @emph{asynchronous I/O}.
|
||||
|
||||
In this model, on the sending side, if the @code{send()} call were to
|
||||
fail because of insufficient buffers, the application suspends the
|
||||
sending of more data until a function registered at the
|
||||
@code{SetSendCallback()} callback is invoked. An application can
|
||||
also ask the socket how much space is available by calling
|
||||
@code{GetTxAvailable ()}. A typical sequence of events for
|
||||
sending data (ignoring connection setup) might be:
|
||||
|
||||
@itemize @bullet
|
||||
@item @code{SetSendCallback (MakeCallback(&HandleSendCallback));}
|
||||
@item @code{Send ();}
|
||||
@item @code{Send ();}
|
||||
@item ...
|
||||
@item @code{// Send fails because buffer is full}
|
||||
@item (wait until HandleSendCallback() is called)
|
||||
@item (HandleSendCallback() is called by socket, since space now available)
|
||||
@item @code{Send (); // Start sending again}
|
||||
@end itemize
|
||||
|
||||
Similarly, on the receive side, the socket user does not block on
|
||||
a call to @code{recv()}. Instead, the application sets a callback
|
||||
with @code{SetRecvCallback ()} in which the socket will notify the
|
||||
application when (and how much) there is data to be read, and
|
||||
the application then calls @code{Recv()} to read the data until
|
||||
no more can be read.
|
||||
|
||||
@subsection Packet vs. buffer variants
|
||||
|
||||
There are two basic variants of @code{Send()} and @code{Recv()} supported:
|
||||
@verbatim
|
||||
virtual int Send (Ptr<Packet> p) = 0;
|
||||
int Send (const uint8_t* buf, uint32_t size);
|
||||
|
||||
Ptr<Packet> Recv (void);
|
||||
int Recv (uint8_t* buf, uint32_t size);
|
||||
@end verbatim
|
||||
|
||||
The non-Packet variants are left for legacy API reasons. When calling
|
||||
the raw buffer variant of @code{Send()}, the buffer is immediately
|
||||
written into a Packet and the @code{Send (Ptr<Packet> p)} is invoked.
|
||||
|
||||
Users may find it semantically odd to pass a Packet to a stream socket
|
||||
such as TCP. However, do not let the name bother you; think of
|
||||
@code{ns3::Packet} to be a fancy byte buffer. There are a few reasons why
|
||||
the Packet variants are more likely to be preferred in ns-3:
|
||||
|
||||
@itemize @bullet
|
||||
@item Users can use the Tags facility of packets to, for example, encode
|
||||
a flow ID or other helper data.
|
||||
@item Users can exploit the copy-on-write implementation to avoid
|
||||
memory copies (on the receive side, the conversion back to a
|
||||
@code{uint8_t* buf} may sometimes incur an additional copy).
|
||||
@item Use of Packet is more aligned with the rest of the ns-3 API
|
||||
@end itemize
|
||||
|
||||
@subsection Sending dummy data
|
||||
|
||||
Sometimes, users want the simulator to just pretend that there is an
|
||||
actual data payload in the packet (e.g. to calculate transmission delay)
|
||||
but do not want to actually produce or consume the data. This is
|
||||
straightforward to support in ns-3; have applications call
|
||||
@code{Create<Packet> (size);} instead of @code{Create<Packet> (buffer, size);}.
|
||||
Similarly, passing in a zero to the pointer argument in the raw buffer
|
||||
variants has the same effect. Note that, if some subsequent code tries
|
||||
to read the Packet data buffer, the fake buffer will be converted to
|
||||
a real (zero'ed) buffer on the spot, and the efficiency will be lost there.
|
||||
|
||||
@subsection Socket options
|
||||
|
||||
@emph{to be completed}
|
||||
|
||||
@subsection Socket errno
|
||||
|
||||
@emph{to be completed}
|
||||
|
||||
@subsection Example programs
|
||||
|
||||
@emph{to be completed}
|
||||
|
||||
@section POSIX-like sockets API
|
||||
|
||||
@emph{this capability is under development and is scheduled for
|
||||
inclusion in August 2008 timeframe; see the repository
|
||||
http://code.nsnam.org/mathieu/ns-3-simu for details}
|
||||
|
||||
The below is excerpted from Mathieu's post to ns-developers list
|
||||
on April 4, 2008.
|
||||
|
||||
"To summarize, the goal is that the full posix/socket API is defined in
|
||||
src/process/simu.h: each posix type and function is re-defined there
|
||||
with a simu_ or SIMU_ prefix to avoid ugly name clashes and collisions
|
||||
(feel free to come up with a better prefix).
|
||||
|
||||
Each process is created with a call to ProcessManager::Create and is
|
||||
attached to that ProcessManager instance. So, if the ProcessManager
|
||||
(which is aggregated to a Node in src/helper/process-helper.cc) is
|
||||
killed when the simulation ends, the system will automatically reclaim
|
||||
all the resources of each process associated to each manager. The same
|
||||
happens when an application "exits" from its main function.
|
||||
|
||||
The example application defines two posix "processes": the function
|
||||
ClientProgram creates a udp socket on the localhost port 2000 and the
|
||||
function ServerProgram creates a udp socket on the localhost port 2000.
|
||||
The code does not work right now because I did not get the details of
|
||||
simu_read right yet but, I do plan to make this work at some point.
|
||||
|
||||
I really think that this approach is worthwhile for many reasons, a few
|
||||
of which are outlined below:
|
||||
@itemize @bullet
|
||||
@item makes porting real world application code _much_ easier
|
||||
|
||||
@item makes write applications for new users much easier because they can
|
||||
read the bsd socket api reference and documentation and write code
|
||||
directly.
|
||||
|
||||
@item can be used to write applications which work in both simulation and
|
||||
in the real world at the same time. To do this, all you have to do is
|
||||
write your application to use the simu_ API, and, then, you can chose at
|
||||
compile-time which implementation of that API you want to use: you can
|
||||
pick one implementation which forwards all calls to the system BSD
|
||||
socket API or another one which forwards all calls to the attached
|
||||
ProcessManager. Arguably, I did not implement the version which forwards
|
||||
to system BSD sockets but, that should be pretty trivial.
|
||||
@end itemize
|
||||
|
||||
So, anyway, comments about the overall API would be welcome. Students
|
||||
interested in the gsoc project for real-world code integration should
|
||||
consider looking at this also."
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
@node Statistics
|
||||
@chapter Statistics
|
||||
@anchor{chap:Statistics}
|
||||
|
||||
ns-3 does not presently have support for statistics (automatically generated
|
||||
statistical output). This is planned
|
||||
for development later in 2008. If you are interested in contributing,
|
||||
please see @uref{http://www.nsnam.org/wiki/index.php/Suggested_Projects,,our suggested projects page} or contact the ns-developers
|
||||
list.
|
||||
@@ -0,0 +1,82 @@
|
||||
@node Troubleshooting
|
||||
@chapter Troubleshooting
|
||||
|
||||
This chapter posts some information about possibly common errors in building
|
||||
or running ns-3 programs.
|
||||
|
||||
Please note that the wiki (@uref{http://www.nsnam.org/wiki/index.php/Troubleshooting}) may have contributed items.
|
||||
|
||||
@node Build errors
|
||||
@section Build errors
|
||||
|
||||
@node Run-time errors
|
||||
@section Run-time errors
|
||||
|
||||
Sometimes, errors can occur with a program after a successful build. These
|
||||
are run-time errors, and can commonly occur when memory is corrupted or
|
||||
pointer values are unexpectedly null.
|
||||
|
||||
Here is an example of what might occur:
|
||||
|
||||
@verbatim
|
||||
ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point
|
||||
Entering directory `/home/tomh/ns-3-nsc/build'
|
||||
Compilation finished successfully
|
||||
Command ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] exited with code -11
|
||||
@end verbatim
|
||||
|
||||
The error message says that the program terminated unsuccessfully, but it is
|
||||
not clear from this information what might be wrong. To examine more
|
||||
closely, try running it under the @uref{http://sources.redhat.com/gdb/,,gdb debugger}:
|
||||
|
||||
@verbatim
|
||||
ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="gdb %s"
|
||||
Entering directory `/home/tomh/ns-3-nsc/build'
|
||||
Compilation finished successfully
|
||||
GNU gdb Red Hat Linux (6.3.0.0-1.134.fc5rh)
|
||||
Copyright 2004 Free Software Foundation, Inc.
|
||||
GDB is free software, covered by the GNU General Public License, and you are
|
||||
welcome to change it and/or distribute copies of it under certain conditions.
|
||||
Type "show copying" to see the conditions.
|
||||
There is absolutely no warranty for GDB. Type "show warranty" for details.
|
||||
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
|
||||
|
||||
(gdb) run
|
||||
Starting program: /home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point
|
||||
Reading symbols from shared object read from target memory...done.
|
||||
Loaded system supplied DSO at 0xf5c000
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0x0804aa12 in main (argc=1, argv=0xbfdfefa4)
|
||||
at ../examples/tcp-point-to-point.cc:136
|
||||
136 Ptr<Socket> localSocket = socketFactory->CreateSocket ();
|
||||
(gdb) p localSocket
|
||||
$1 = {m_ptr = 0x3c5d65}
|
||||
(gdb) p socketFactory
|
||||
$2 = {m_ptr = 0x0}
|
||||
(gdb) quit
|
||||
The program is running. Exit anyway? (y or n) y
|
||||
@end verbatim
|
||||
|
||||
Note first the way the program was invoked-- pass the command to run as
|
||||
an argument to the command template "gdb %s".
|
||||
|
||||
This tells us that there was an attempt to dereference a null pointer
|
||||
socketFactory.
|
||||
|
||||
Let's look around line 136 of tcp-point-to-point, as gdb suggests:
|
||||
@verbatim
|
||||
Ptr<SocketFactory> socketFactory = n2->GetObject<SocketFactory> (Tcp::iid);
|
||||
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
|
||||
localSocket->Bind ();
|
||||
@end verbatim
|
||||
|
||||
The culprit here is that the return value of GetObject is not being
|
||||
checked and may be null.
|
||||
|
||||
Sometimes you may need to use the @uref{http://valgrind.org,,valgrind memory
|
||||
checker} for more subtle errors. Again, you invoke the use of valgrind
|
||||
similarly:
|
||||
@verbatim
|
||||
ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="valgrind %s"
|
||||
@end verbatim
|
||||
@@ -0,0 +1,156 @@
|
||||
body {
|
||||
font-family: "Trebuchet MS", "Bitstream Vera Sans", verdana, lucida, arial, helvetica, sans-serif;
|
||||
background: white;
|
||||
color: black;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
# color: #990000;
|
||||
color: #009999;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: 10pt;
|
||||
background: #e0e0e0;
|
||||
color: black;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
color: #0047b9;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
font-weight: normal;
|
||||
text-decoration: underline;
|
||||
color: #0047b9;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#main th {
|
||||
font-size: 12pt;
|
||||
background: #b0b0b0;
|
||||
}
|
||||
|
||||
.odd {
|
||||
font-size: 12pt;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.even {
|
||||
font-size: 12pt;
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
.answer {
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.answer p {
|
||||
font-size: 12pt;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.answer ul {
|
||||
font-size: 12pt;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#feedback {
|
||||
color: #b0b0b0;
|
||||
font-size: 9pt;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#header {
|
||||
position: absolute;
|
||||
margin: 0px;
|
||||
top: 10px;
|
||||
height:96px;
|
||||
left: 175px;
|
||||
right: 10em;
|
||||
bottom: auto;
|
||||
background: white;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#middle {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#main {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 175px;
|
||||
right: 100px;
|
||||
background: white;
|
||||
padding: 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
#navbar {
|
||||
position: absolute;
|
||||
top: 75px;
|
||||
left: 0em;
|
||||
width: 146px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
#navbar a:link, #navbar a:visited {
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
color: #0047b9;
|
||||
}
|
||||
|
||||
#navbar a:hover {
|
||||
font-weight: normal;
|
||||
text-decoration: underline;
|
||||
color: #0047b9;
|
||||
}
|
||||
|
||||
#navbar dl {
|
||||
width: 146px;
|
||||
padding: 0;
|
||||
margin: 0 0 10px 0px;
|
||||
background: #99ffff url(images/box_bottom2.gif) no-repeat bottom left;
|
||||
}
|
||||
|
||||
#navbar dt {
|
||||
padding: 6px 10px;
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
background: #009999;
|
||||
margin: 0px;
|
||||
border-bottom: 1px solid #fff;
|
||||
color: white;
|
||||
background: #009999 url(images/box_top2.gif) no-repeat top left;
|
||||
}
|
||||
|
||||
#navbar dd {
|
||||
font-size: 100%;
|
||||
margin: 0 0 0 0px;
|
||||
padding: 6px 10px;
|
||||
color: #0047b9;
|
||||
}
|
||||
|
||||
dd#selected {
|
||||
background: #99ffff url(images/arrow.gif) no-repeat;
|
||||
background-position: 4px 10px;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename ns-3.info
|
||||
@settitle ns-3 tutorial
|
||||
@c @setchapternewpage odd
|
||||
@c %**end of header
|
||||
|
||||
@ifinfo
|
||||
Primary documentation for the @command{ns-3} project is available in
|
||||
three forms:
|
||||
@itemize @bullet
|
||||
@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
|
||||
@item Tutorial (this document)
|
||||
@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
|
||||
@end itemize
|
||||
|
||||
This document is written in GNU Texinfo and is to be maintained in
|
||||
revision control on the @command{ns-3} code server. Both PDF and HTML versions
|
||||
should be available on the server. Changes to
|
||||
the document should be discussed on the ns-developers@@isi.edu mailing list.
|
||||
@end ifinfo
|
||||
|
||||
@copying
|
||||
|
||||
This is an @command{ns-3} tutorial.
|
||||
Primary documentation for the @command{ns-3} project is available in
|
||||
three forms:
|
||||
@itemize @bullet
|
||||
@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
|
||||
@item Tutorial (this document)
|
||||
@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
|
||||
@end itemize
|
||||
|
||||
This document is written in GNU Texinfo and is to be maintained in
|
||||
revision control on the @command{ns-3} code server. Both PDF and HTML
|
||||
versions should be available on the server. Changes to
|
||||
the document should be discussed on the ns-developers@@isi.edu mailing list.
|
||||
|
||||
This software 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This software 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 @uref{http://www.gnu.org/licenses/}.
|
||||
@end copying
|
||||
|
||||
@titlepage
|
||||
@title ns-3 Tutorial
|
||||
@author ns-3 project
|
||||
@author feedback: ns-developers@@isi.edu
|
||||
@today{}
|
||||
|
||||
@c @page
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
@end titlepage
|
||||
|
||||
@c So the toc is printed at the start.
|
||||
@anchor{Full Table of Contents}
|
||||
@contents
|
||||
|
||||
@ifnottex
|
||||
@node Top, Overview, Full Table of Contents
|
||||
@top ns-3 Tutorial (html version)
|
||||
|
||||
For a pdf version of this tutorial,
|
||||
see @uref{http://www.nsnam.org/docs/tutorial.pdf}.
|
||||
|
||||
@insertcopying
|
||||
@end ifnottex
|
||||
|
||||
@menu
|
||||
* Tutorial Goals::
|
||||
Part 1: Getting Started with ns-3
|
||||
* Overview::
|
||||
* Browsing::
|
||||
* Resources::
|
||||
* Downloading and Compiling::
|
||||
* Some-Prerequisites::
|
||||
Part 2: Reading ns-3 Programs
|
||||
* A-First-ns-3-Script::
|
||||
Part 3: Reconfiguring Existing ns-3 Scripts
|
||||
* Logging::
|
||||
* ns-3 Attributes::
|
||||
* Tracing::
|
||||
* Statistics::
|
||||
Part 4: Creating New or Revised Topologies
|
||||
* Helper Functions::
|
||||
* Other-network-topologies::
|
||||
Part 5: Key ns-3 objects and systems
|
||||
* ns-3 Packets::
|
||||
* ns-3 Callbacks::
|
||||
* Sockets APIs::
|
||||
* ns-3 routing overview::
|
||||
Part 6: Extending ns-3
|
||||
* Nonlinear-Thinking::
|
||||
* Summary::
|
||||
* Object-Model::
|
||||
* The-Doxygen-Documentation-System::
|
||||
* How-To-Change-Things::
|
||||
* How-To-Set-Default-Values::
|
||||
* How-To-Write-A-New-Application::
|
||||
@ Troubleshooting
|
||||
@end menu
|
||||
|
||||
@include introduction.texi
|
||||
@include log.texi
|
||||
@include attributes.texi
|
||||
@include statistics.texi
|
||||
@include helpers.texi
|
||||
@include packets.texi
|
||||
@include callbacks.texi
|
||||
@include sockets.texi
|
||||
@c @include output.texi
|
||||
@include routing.texi
|
||||
@c @include other.texi
|
||||
@include troubleshoot.texi
|
||||
|
||||
@printindex cp
|
||||
|
||||
@bye
|
||||
@@ -0,0 +1,126 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//
|
||||
// Example of the sending of a datagram to a broadcast address
|
||||
//
|
||||
// Network topology
|
||||
// ==============
|
||||
// | |
|
||||
// n0 n1 n2
|
||||
// | |
|
||||
// ==========
|
||||
//
|
||||
// n0 originates UDP broadcast to 255.255.255.255/discard port, which
|
||||
// is replicated and received on both n1 and n2
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("CsmaBroadcastExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
#if 0
|
||||
LogComponentEnable ("CsmaBroadcastExample", LOG_LEVEL_INFO);
|
||||
#endif
|
||||
LogComponentEnable ("CsmaBroadcastExample", LOG_PREFIX_TIME);
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (3);
|
||||
NodeContainer c0 = NodeContainer (c.Get (0), c.Get (1));
|
||||
NodeContainer c1 = NodeContainer (c.Get (0), c.Get (2));
|
||||
|
||||
NS_LOG_INFO ("Build Topology.");
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelParameter ("BitRate", DataRateValue (DataRate(5000000)));
|
||||
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds(2)));
|
||||
|
||||
NetDeviceContainer n0 = csma.Install (c0);
|
||||
NetDeviceContainer n1 = csma.Install (c1);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.0.0", "255.255.255.0");
|
||||
ipv4.Assign (n0);
|
||||
ipv4.SetBase ("192.168.1.0", "255.255.255.0");
|
||||
ipv4.Assign (n1);
|
||||
|
||||
|
||||
// RFC 863 discard port ("9") indicates packet should be thrown away
|
||||
// by the system. We allow this silent discard to be overridden
|
||||
// by the PacketSink application.
|
||||
uint16_t port = 9;
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 512 bytes (default) at a rate of 500 Kb/s (default) from n0
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address ("255.255.255.255"), port)));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
|
||||
ApplicationContainer app = onoff.Install (c0.Get (0));
|
||||
// Start the application
|
||||
app.Start (Seconds (1.0));
|
||||
app.Stop (Seconds (10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
sink.Install (c0.Get (1));
|
||||
sink.Install (c1.Get (1));
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named
|
||||
// csma-broadcast.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -tt -r" command
|
||||
CsmaHelper::EnablePcapAll ("csma-broadcast");
|
||||
std::ofstream ascii;
|
||||
ascii.open ("csma-broadcast.tr");
|
||||
CsmaHelper::EnableAsciiAll (ascii);
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
// Network topology
|
||||
//
|
||||
// Lan1
|
||||
// ===========
|
||||
// | | |
|
||||
// n0 n1 n2 n3 n4
|
||||
// | | |
|
||||
// ===========
|
||||
// Lan0
|
||||
//
|
||||
// - Multicast source is at node n0;
|
||||
// - Multicast forwarded by node n2 onto LAN1;
|
||||
// - Nodes n0, n1, n2, n3, and n4 receive the multicast frame.
|
||||
// - Node n4 listens for the data
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("CsmaMulticastExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
//
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
//
|
||||
// LogComponentEnable ("CsmaMulticastExample", LOG_LEVEL_INFO);
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
//
|
||||
// Set up default values for the simulation.
|
||||
//
|
||||
// Select Ethernet II-style encapsulation (no LLC/Snap header)
|
||||
Config::SetDefault ("ns3::CsmaNetDevice::EncapsulationMode", StringValue ("IpArp"));
|
||||
|
||||
// Allow the user to override any of the defaults at
|
||||
// run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (5);
|
||||
// We will later want two subcontainers of these nodes, for the two LANs
|
||||
NodeContainer c0 = NodeContainer (c.Get (0), c.Get (1), c.Get (2));
|
||||
NodeContainer c1 = NodeContainer (c.Get (2), c.Get (3), c.Get (4));
|
||||
|
||||
NS_LOG_INFO ("Build Topology.");
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelParameter ("BitRate", DataRateValue (DataRate (5000000)));
|
||||
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
|
||||
|
||||
// We will use these NetDevice containers later, for IP addressing
|
||||
NetDeviceContainer nd0 = csma.Install (c0); // First LAN
|
||||
NetDeviceContainer nd1 = csma.Install (c1); // Second LAN
|
||||
|
||||
NS_LOG_INFO ("Add IP Stack.");
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4Addr;
|
||||
ipv4Addr.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
ipv4Addr.Assign (nd0);
|
||||
ipv4Addr.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
ipv4Addr.Assign (nd1);
|
||||
|
||||
NS_LOG_INFO ("Configure multicasting.");
|
||||
//
|
||||
// Now we can configure multicasting. As described above, the multicast
|
||||
// source is at node zero, which we assigned the IP address of 10.1.1.1
|
||||
// earlier. We need to define a multicast group to send packets to. This
|
||||
// can be any multicast address from 224.0.0.0 through 239.255.255.255
|
||||
// (avoiding the reserved routing protocol addresses).
|
||||
//
|
||||
|
||||
Ipv4Address multicastSource ("10.1.1.1");
|
||||
Ipv4Address multicastGroup ("225.1.2.4");
|
||||
|
||||
// Now, we will set up multicast routing. We need to do three things:
|
||||
// 1) Configure a (static) multicast route on node n2
|
||||
// 2) Set up a default multicast route on the sender n0
|
||||
// 3) Have node n4 join the multicast group
|
||||
// We have a helper that can help us with static multicast
|
||||
StaticMulticastRouteHelper multicast;
|
||||
|
||||
// 1) Configure a (static) multicast route on node n2 (multicastRouter)
|
||||
Ptr<Node> multicastRouter = c.Get (2); // The node in question
|
||||
Ptr<NetDevice> inputIf = nd0.Get (2); // The input NetDevice
|
||||
NetDeviceContainer outputDevices; // A container of output NetDevices
|
||||
outputDevices.Add (nd1.Get (0)); // (we only need one NetDevice here)
|
||||
|
||||
multicast.AddMulticastRoute (multicastRouter, multicastSource,
|
||||
multicastGroup, inputIf, outputDevices);
|
||||
|
||||
// 2) Set up a default multicast route on the sender n0
|
||||
Ptr<Node> sender = c.Get (0);
|
||||
Ptr<NetDevice> senderIf = nd0.Get(0);
|
||||
multicast.SetDefaultMulticastRoute (sender, senderIf);
|
||||
|
||||
// 3) Have node n4 join the multicast group
|
||||
Ptr<Node> receiver = c.Get (4);
|
||||
multicast.JoinMulticastGroup (receiver, multicastSource, multicastGroup);
|
||||
|
||||
//
|
||||
// Create an OnOff application to send UDP datagrams from node zero to the
|
||||
// multicast group (node four will be listening).
|
||||
//
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
|
||||
uint16_t multicastPort = 9; // Discard port (RFC 863)
|
||||
|
||||
// Configure a multicast packet generator that generates a packet
|
||||
// every few seconds
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (multicastGroup, multicastPort)));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
onoff.SetAttribute ("DataRate", DataRateValue (DataRate ("255b/s")));
|
||||
onoff.SetAttribute ("PacketSize", UintegerValue (128));
|
||||
|
||||
ApplicationContainer srcC = onoff.Install (c0.Get (0));
|
||||
|
||||
//
|
||||
// Tell the application when to start and stop.
|
||||
//
|
||||
srcC.Start(Seconds(1.));
|
||||
srcC.Stop (Seconds(10.));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny(), multicastPort));
|
||||
|
||||
ApplicationContainer sinkC = sink.Install (c1.Get (2)); // Node n4
|
||||
// Start the sink
|
||||
sinkC.Start (Seconds (1.0));
|
||||
sinkC.Stop (Seconds (10.0));
|
||||
|
||||
//
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events.
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
//
|
||||
// Ascii trace output will be sent to the file "csma-multicast.tr"
|
||||
//
|
||||
std::ofstream ascii;
|
||||
ascii.open ("csma-multicast.tr");
|
||||
CsmaHelper::EnableAsciiAll (ascii);
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced.
|
||||
// The output files will be named:
|
||||
// csma-multicast.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
CsmaHelper::EnablePcapAll ("csma-multicast");
|
||||
//
|
||||
// Now, do the actual simulation.
|
||||
//
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
// Network topology
|
||||
//
|
||||
// n0 n1 n2 n3
|
||||
// | | | |
|
||||
// =================
|
||||
// LAN
|
||||
//
|
||||
// - CBR/UDP flows from n0 to n1 and from n3 to n0
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file "csma-one-subnet.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("CsmaOneSubnetExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
//
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
//
|
||||
#if 0
|
||||
LogComponentEnable ("CsmaOneSubnetExample", LOG_LEVEL_INFO);
|
||||
#endif
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
//
|
||||
// Allow the user to override any of the defaults and the above Bind() at
|
||||
// run-time, via command-line arguments
|
||||
//
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
//
|
||||
// Explicitly create the nodes required by the topology (shown above).
|
||||
//
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (4);
|
||||
|
||||
NS_LOG_INFO ("Build Topology");
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelParameter ("BitRate", DataRateValue (5000000));
|
||||
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
|
||||
//
|
||||
// Now fill out the topology by creating the net devices required to connect
|
||||
// the nodes to the channels and hooking them up. AddIpv4CsmaNetDevice will
|
||||
// create a net device, add a MAC address (in memory of the pink flamingo) and
|
||||
// connect the net device to a nodes and also to a channel. the
|
||||
// AddIpv4CsmaNetDevice method returns a net device index for the net device
|
||||
// created on the node. Interpret nd0 as the net device we created for node
|
||||
// zero.
|
||||
//
|
||||
NetDeviceContainer nd0 = csma.Install (c);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
// We've got the "hardware" in place. Now we need to add IP addresses.
|
||||
//
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
ipv4.Assign (nd0);
|
||||
|
||||
//
|
||||
// Create an OnOff application to send UDP datagrams from node zero to node 1.
|
||||
//
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address ("10.1.1.2"), port)));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
|
||||
ApplicationContainer app = onoff.Install (c.Get (0));
|
||||
// Start the application
|
||||
app.Start (Seconds (1.0));
|
||||
app.Stop (Seconds (10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
sink.Install (c.Get (1));
|
||||
|
||||
//
|
||||
// Create a similar flow from n3 to n0, starting at time 1.1 seconds
|
||||
//
|
||||
onoff.SetAttribute ("Remote",
|
||||
AddressValue (InetSocketAddress (Ipv4Address ("10.1.1.1"), port)));
|
||||
ApplicationContainer app2 = onoff.Install (c.Get (3));
|
||||
|
||||
sink.Install (c.Get (0));
|
||||
|
||||
app2.Start(Seconds (1.1));
|
||||
app2.Stop (Seconds (10.0));
|
||||
//
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events.
|
||||
// Trace output will be sent to the file "csma-one-subnet.tr"
|
||||
//
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
std::ofstream ascii;
|
||||
ascii.open ("csma-one-subnet.tr");
|
||||
CsmaHelper::EnableAsciiAll (ascii);
|
||||
//
|
||||
// Also configure some tcpdump traces; each interface will be traced.
|
||||
// The output files will be named:
|
||||
// csma-one-subnet.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
//
|
||||
CsmaHelper::EnablePcapAll ("csma-one-subnet");
|
||||
//
|
||||
// Now, do the actual simulation.
|
||||
//
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
// Port of ns-2/tcl/ex/simple.tcl to ns-3
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0 n1 n2 n3
|
||||
// | | | |
|
||||
// =====================
|
||||
//
|
||||
// - CBR/UDP flows from n0 to n1, and from n3 to n0
|
||||
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
|
||||
// (i.e., DataRate of 448,000 bps)
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file "csma-one-subnet.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("CsmaPacketSocketExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
#if 0
|
||||
LogComponentEnable ("CsmaPacketSocketExample", LOG_LEVEL_INFO);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create four nodes.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (4);
|
||||
|
||||
PacketSocketHelper packetSocket;
|
||||
packetSocket.Install (c);
|
||||
|
||||
// create the shared medium used by all csma devices.
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
Ptr<CsmaChannel> channel = CreateObject<CsmaChannel> ("BitRate", DataRateValue (DataRate(5000000)),
|
||||
"Delay", TimeValue (MilliSeconds(2)));
|
||||
|
||||
// use a helper function to connect our nodes to the shared channel.
|
||||
NS_LOG_INFO ("Build Topology.");
|
||||
CsmaHelper csma;
|
||||
csma.SetDeviceParameter ("EncapsulationMode", StringValue ("Llc"));
|
||||
NetDeviceContainer devs = csma.Install (c, channel);
|
||||
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
// Create the OnOff application to send raw datagrams
|
||||
PacketSocketAddress socket;
|
||||
socket.SetSingleDevice(devs.Get (0)->GetIfIndex ());
|
||||
socket.SetPhysicalAddress (devs.Get (1)->GetAddress ());
|
||||
socket.SetProtocol (2);
|
||||
OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1.0)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (c.Get (0));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
socket.SetSingleDevice (devs.Get (3)->GetIfIndex ());
|
||||
socket.SetPhysicalAddress (devs.Get (0)->GetAddress ());
|
||||
socket.SetProtocol (3);
|
||||
onoff.SetAttribute ("Remote", AddressValue (socket));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
|
||||
apps = onoff.Install (c.Get (3));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the csma-packet-socket.tr file
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
std::ofstream os;
|
||||
os.open ("csma-packet-socket.tr");
|
||||
csma.EnableAsciiAll (os);
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
// This script exercises global routing code in a mixed point-to-point
|
||||
// and csma/cd environment
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0
|
||||
// \ p-p
|
||||
// \ (shared csma/cd)
|
||||
// n2 -------------------------n3
|
||||
// / | |
|
||||
// / p-p n4 n5 ---------- n6
|
||||
// n1 p-p
|
||||
//
|
||||
// - CBR/UDP flows from n0 to n6
|
||||
// - Tracing of queues and packet receptions to file "mixed-global-routing.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/global-route-manager.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("MixedGlobalRoutingExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("448kb/s"));
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind ()s at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (7);
|
||||
NodeContainer n0n2 = NodeContainer (c.Get (0), c.Get (2));
|
||||
NodeContainer n1n2 = NodeContainer (c.Get (1), c.Get (2));
|
||||
NodeContainer n5n6 = NodeContainer (c.Get (5), c.Get (6));
|
||||
NodeContainer n2345 = NodeContainer (c.Get (2), c.Get (3), c.Get (4), c.Get (5));
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer d0d2 = p2p.Install (n0n2);
|
||||
|
||||
NetDeviceContainer d1d2 = p2p.Install (n1n2);
|
||||
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
|
||||
NetDeviceContainer d5d6 = p2p.Install (n5n6);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
|
||||
csma.SetChannelParameter ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer d2345 = csma.Install (n2345);
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
ipv4.Assign (d0d2);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
ipv4.Assign (d1d2);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i5i6 = ipv4.Assign (d5d6);
|
||||
|
||||
ipv4.SetBase ("10.250.1.0", "255.255.255.0");
|
||||
ipv4.Assign (d2345);
|
||||
|
||||
// Create router nodes, initialize routing database and set up the routing
|
||||
// tables in the nodes.
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (i5i6.GetAddress (1), port));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
onoff.SetAttribute ("DataRate", StringValue ("300bps"));
|
||||
onoff.SetAttribute ("PacketSize", UintegerValue (50));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (c.Get (0));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
std::ofstream ascii;
|
||||
ascii.open ("mixed-global-routing.tr");
|
||||
PointToPointHelper::EnablePcapAll ("mixed-global-routing");
|
||||
PointToPointHelper::EnableAsciiAll (ascii);
|
||||
CsmaHelper::EnablePcapAll ("mixed-global-routing");
|
||||
CsmaHelper::EnableAsciiAll (ascii);
|
||||
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// This ns-3 example demonstrates the use of helper functions to ease
|
||||
// the construction of simulation scenarios.
|
||||
//
|
||||
// The simulation topology consists of a mixed wired and wireless
|
||||
// scenario in which a hierarchical mobility model is used.
|
||||
//
|
||||
// The simulation layout consists of N backbone routers interconnected
|
||||
// by an ad hoc wifi network.
|
||||
// Each backbone router also has a local 802.11 network and is connected
|
||||
// to a local LAN. An additional set of (K-1) nodes are connected to
|
||||
// this backbone. Finally, a local LAN is connected to each router
|
||||
// on the backbone, with L-1 additional hosts.
|
||||
//
|
||||
// The nodes are populated with TCP/IP stacks, and OLSR unicast routing
|
||||
// on the backbone. An example UDP transfer is shown. The simulator
|
||||
// be configured to output tcpdumps or traces from different nodes.
|
||||
//
|
||||
//
|
||||
// +--------------------------------------------------------+
|
||||
// | |
|
||||
// | 802.11 ad hoc, ns-2 mobility |
|
||||
// | |
|
||||
// +--------------------------------------------------------+
|
||||
// | o o o (N backbone routers) |
|
||||
// +--------+ +--------+
|
||||
// wired LAN | mobile | wired LAN | mobile |
|
||||
// -----------| router | -----------| router |
|
||||
// --------- ---------
|
||||
// | |
|
||||
// +----------------+ +----------------+
|
||||
// | 802.11 | | 802.11 |
|
||||
// | net | | net |
|
||||
// | K-1 hosts | | K-1 hosts |
|
||||
// +----------------+ +----------------+
|
||||
//
|
||||
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/common-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/contrib-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
//
|
||||
// Define logging keyword for this file
|
||||
//
|
||||
NS_LOG_COMPONENT_DEFINE ("MixedWireless");
|
||||
|
||||
//
|
||||
// This function will be used below as a trace sink
|
||||
//
|
||||
#ifdef ENABLE_FOR_TRACING_EXAMPLE
|
||||
static void
|
||||
CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
|
||||
{
|
||||
Vector position = model->GetPosition ();
|
||||
std::cout << "CourseChange " << path << " x=" << position.x << ", y=" << position.y << ", z=" << position.z << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
//
|
||||
// First, we declare and initialize a few local variables that control some
|
||||
// simulation parameters.
|
||||
//
|
||||
uint32_t backboneNodes = 10;
|
||||
uint32_t infraNodes = 5;
|
||||
uint32_t lanNodes = 5;
|
||||
uint32_t stopTime = 10;
|
||||
|
||||
//
|
||||
// Simulation defaults are typically set next, before command line
|
||||
// arguments are parsed.
|
||||
//
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", StringValue ("210"));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("448kb/s"));
|
||||
|
||||
//
|
||||
// For convenience, we add the local variables to the command line argument
|
||||
// system so that they can be overridden with flags such as
|
||||
// "--backboneNodes=20"
|
||||
//
|
||||
CommandLine cmd;
|
||||
cmd.AddValue("backboneNodes", "number of backbone nodes", backboneNodes);
|
||||
cmd.AddValue ("infraNodes", "number of leaf nodes", infraNodes);
|
||||
cmd.AddValue("lanNodes", "number of LAN nodes", lanNodes);
|
||||
cmd.AddValue("stopTime", "simulation stop time (seconds)", stopTime);
|
||||
|
||||
//
|
||||
// The system global variables and the local values added to the argument
|
||||
// system can be overridden by command line arguments by using this call.
|
||||
//
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// The metadata system (off by default) is used by ascii tracing below
|
||||
Packet::EnableMetadata ();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Construct the backbone //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Create a container to manage the nodes of the adhoc (backbone) network.
|
||||
// Later we'll create the rest of the nodes we'll need.
|
||||
//
|
||||
NodeContainer backbone;
|
||||
backbone.Create (backboneNodes);
|
||||
//
|
||||
// Create the backbone wifi net devices and install them into the nodes in
|
||||
// our container
|
||||
//
|
||||
WifiHelper wifi;
|
||||
wifi.SetMac ("ns3::AdhocWifiMac");
|
||||
wifi.SetPhy ("ns3::WifiPhy");
|
||||
NetDeviceContainer backboneDevices = wifi.Install (backbone);
|
||||
//
|
||||
// Add the IPv4 protocol stack to the nodes in our container
|
||||
//
|
||||
InternetStackHelper internet;
|
||||
internet.Install (backbone);
|
||||
//
|
||||
// Assign IPv4 addresses to the device drivers (actually to the associated
|
||||
// IPv4 interfaces) we just created.
|
||||
//
|
||||
Ipv4AddressHelper ipAddrs;
|
||||
ipAddrs.SetBase ("192.168.0.0", "255.255.255.0");
|
||||
ipAddrs.Assign (backboneDevices);
|
||||
|
||||
//
|
||||
// The ad-hoc network nodes need a mobility model so we aggregate one to
|
||||
// each of the nodes we just finished building.
|
||||
//
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc =
|
||||
CreateObject<ListPositionAllocator> ();
|
||||
double x = 0.0;
|
||||
for (uint32_t i = 0; i < backboneNodes; ++i)
|
||||
{
|
||||
positionAlloc->Add (Vector (x, 0.0, 0.0));
|
||||
x += 5.0;
|
||||
}
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
|
||||
"Bounds", RectangleValue (Rectangle (0, 1000, 0, 1000)),
|
||||
"Speed", RandomVariableValue (ConstantVariable (2000)),
|
||||
"Pause", RandomVariableValue (ConstantVariable (0.2)));
|
||||
mobility.Install (backbone);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Construct the LANs //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Reset the address base-- all of the CSMA networks will be in
|
||||
// the "172.16 address space
|
||||
ipAddrs.SetBase ("172.16.0.0", "255.255.255.0");
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < backboneNodes; ++i)
|
||||
{
|
||||
NS_LOG_INFO ("Configuring local area network for backbone node " << i);
|
||||
//
|
||||
// Create a container to manage the nodes of the LAN. We need
|
||||
// two containers here; one with all of the new nodes, and one
|
||||
// with all of the nodes including new and existing nodes
|
||||
//
|
||||
NodeContainer newLanNodes;
|
||||
newLanNodes.Create (lanNodes - 1);
|
||||
// Now, create the container with all nodes on this link
|
||||
NodeContainer lan (backbone.Get (i), newLanNodes);
|
||||
//
|
||||
// Create the CSMA net devices and install them into the nodes in our
|
||||
// collection.
|
||||
//
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelParameter ("BitRate", DataRateValue (DataRate (5000000)));
|
||||
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
|
||||
NetDeviceContainer lanDevices = csma.Install (lan);
|
||||
//
|
||||
// Add the IPv4 protocol stack to the new LAN nodes
|
||||
//
|
||||
internet.Install (newLanNodes);
|
||||
//
|
||||
// Assign IPv4 addresses to the device drivers (actually to the
|
||||
// associated IPv4 interfaces) we just created.
|
||||
//
|
||||
ipAddrs.Assign (lanDevices);
|
||||
//
|
||||
// Assign a new network prefix for the next LAN, according to the
|
||||
// network mask initialized above
|
||||
//
|
||||
ipAddrs.NewNetwork ();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Construct the mobile networks //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Reset the address base-- all of the 802.11 networks will be in
|
||||
// the "10.0" address space
|
||||
ipAddrs.SetBase ("10.0.0.0", "255.255.255.0");
|
||||
|
||||
for (uint32_t i = 0; i < backboneNodes; ++i)
|
||||
{
|
||||
NS_LOG_INFO ("Configuring wireless network for backbone node " << i);
|
||||
//
|
||||
// Create a container to manage the nodes of the LAN. We need
|
||||
// two containers here; one with all of the new nodes, and one
|
||||
// with all of the nodes including new and existing nodes
|
||||
//
|
||||
NodeContainer newInfraNodes;
|
||||
newInfraNodes.Create (infraNodes - 1);
|
||||
// Now, create the container with all nodes on this link
|
||||
NodeContainer infra (backbone.Get (i), newInfraNodes);
|
||||
//
|
||||
// Create another ad hoc network and devices
|
||||
//
|
||||
WifiHelper wifiInfra;
|
||||
wifiInfra.SetMac ("ns3::AdhocWifiMac");
|
||||
wifiInfra.SetPhy ("ns3::WifiPhy");
|
||||
NetDeviceContainer infraDevices = wifiInfra.Install (infra);
|
||||
|
||||
// Add the IPv4 protocol stack to the nodes in our container
|
||||
//
|
||||
internet.Install (newInfraNodes);
|
||||
//
|
||||
// Assign IPv4 addresses to the device drivers (actually to the associated
|
||||
// IPv4 interfaces) we just created.
|
||||
//
|
||||
ipAddrs.Assign (infraDevices);
|
||||
//
|
||||
// Assign a new network prefix for each mobile network, according to
|
||||
// the network mask initialized above
|
||||
//
|
||||
ipAddrs.NewNetwork ();
|
||||
//
|
||||
// The new wireless nodes need a mobility model so we aggregate one
|
||||
// to each of the nodes we just finished building.
|
||||
//
|
||||
Ptr<ListPositionAllocator> subnetAlloc =
|
||||
CreateObject<ListPositionAllocator> ();
|
||||
for (uint32_t j = 0; j < infra.GetN (); ++j)
|
||||
{
|
||||
subnetAlloc->Add (Vector (0.0, j, 0.0));
|
||||
}
|
||||
mobility.PushReferenceMobilityModel (backbone.Get (i));
|
||||
mobility.SetPositionAllocator (subnetAlloc);
|
||||
mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
|
||||
"Bounds", RectangleValue (Rectangle (-25, 25, -25, 25)),
|
||||
"Speed", RandomVariableValue (ConstantVariable (30)),
|
||||
"Pause", RandomVariableValue (ConstantVariable (0.4)));
|
||||
mobility.Install (infra);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Routing configuration //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_LOG_INFO ("Enabling OLSR routing on all backbone nodes");
|
||||
OlsrHelper olsr;
|
||||
olsr.Install (backbone);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Application configuration //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s, between two nodes
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
|
||||
// Let's make sure that the user does not define too few LAN nodes
|
||||
// to make this example work. We need lanNodes >= 5
|
||||
NS_ASSERT (lanNodes >= 5);
|
||||
Ptr<Node> appSource = NodeList::GetNode (11);
|
||||
Ptr<Node> appSink = NodeList::GetNode (13);
|
||||
Ipv4Address remoteAddr = Ipv4Address ("172.16.0.5");
|
||||
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (remoteAddr, port)));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
ApplicationContainer apps = onoff.Install (appSource);
|
||||
apps.Start (Seconds (3.0));
|
||||
apps.Stop (Seconds (20.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
apps = sink.Install (appSink);
|
||||
apps.Start (Seconds (3.0));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Tracing configuration //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
//
|
||||
// Let's set up some ns-2-like ascii traces, using another helper class
|
||||
//
|
||||
std::ofstream ascii;
|
||||
ascii.open ("mixed-wireless.tr");
|
||||
WifiHelper::EnableAsciiAll (ascii);
|
||||
CsmaHelper::EnableAsciiAll (ascii);
|
||||
// Look at nodes 11, 13 only
|
||||
//WifiHelper::EnableAscii (ascii, 11, 0);
|
||||
//WifiHelper::EnableAscii (ascii, 13, 0);
|
||||
|
||||
// Let's do a pcap trace on the backbone devices
|
||||
WifiHelper::EnablePcap ("mixed-wireless", backboneDevices);
|
||||
// Let's additionally trace the application Sink, ifIndex 0
|
||||
CsmaHelper::EnablePcap ("mixed-wireless", appSink->GetId (), 0);
|
||||
|
||||
#ifdef ENABLE_FOR_TRACING_EXAMPLE
|
||||
Config::Connect ("/NodeList/*/$MobilityModel/CourseChange",
|
||||
MakeCallback (&CourseChangeCallback));
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Run simulation //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Stop (Seconds (stopTime));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0
|
||||
// \ 5 Mb/s, 2ms
|
||||
// \ 1.5Mb/s, 10ms
|
||||
// n2 ------------------------n3
|
||||
// / /
|
||||
// / 5 Mb/s, 2ms /
|
||||
// n1--------------------------
|
||||
// 1.5 Mb/s, 100ms
|
||||
//
|
||||
// this is a modification of simple-global-routing to allow for
|
||||
// a single hop but higher-cost path between n1 and n3
|
||||
//
|
||||
// - Tracing of queues and packet receptions to file "simple-rerouting.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/global-route-manager.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SimpleAlternateRoutingExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
#if 0
|
||||
LogComponentEnable("GlobalRouteManager", LOG_LOGIC);
|
||||
LogComponentEnable("GlobalRouter", LOG_LOGIC);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("300b/s"));
|
||||
|
||||
// The below metric, if set to 3 or higher, will cause packets between
|
||||
// n1 and n3 to take the 2-hop route through n2
|
||||
|
||||
CommandLine cmd;
|
||||
//
|
||||
// Additionally, we plumb this metric into the default value / command
|
||||
// line argument system as well, for exemplary purposes. This means
|
||||
// that it can be resettable at the command-line to the program,
|
||||
// rather than recompiling
|
||||
// e.g. waf --run "simple-alternate-routing --AlternateCost=5"
|
||||
uint16_t sampleMetric = 1;
|
||||
cmd.AddValue ("AlternateCost",
|
||||
"This metric is used in the example script between n3 and n1 ",
|
||||
sampleMetric);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// DefaultValue::Bind ()s at run-time, via command-line arguments
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (4);
|
||||
NodeContainer n0n2 = NodeContainer (c.Get (0), c.Get (2));
|
||||
NodeContainer n1n2 = NodeContainer (c.Get (1), c.Get (2));
|
||||
NodeContainer n3n2 = NodeContainer (c.Get (3), c.Get (2));
|
||||
NodeContainer n1n3 = NodeContainer (c.Get (1), c.Get (3));
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer d0d2 = p2p.Install (n0n2);
|
||||
|
||||
NetDeviceContainer d1d2 = p2p.Install (n1n2);
|
||||
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
|
||||
NetDeviceContainer d3d2 = p2p.Install (n3n2);
|
||||
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("100ms"));
|
||||
NetDeviceContainer d1d3 = p2p.Install (n1n3);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
// Later, we add IP addresses. The middle two octets correspond to
|
||||
// the channel number.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.0.0.0", "255.255.255.0");
|
||||
ipv4.Assign (d0d2);
|
||||
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i1i2 = ipv4.Assign (d1d2);
|
||||
|
||||
ipv4.SetBase ("10.2.2.0", "255.255.255.0");
|
||||
ipv4.Assign (d3d2);
|
||||
|
||||
ipv4.SetBase ("10.3.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i1i3 = ipv4.Assign (d1d3);
|
||||
|
||||
i1i3.SetMetric (0, sampleMetric);
|
||||
i1i3.SetMetric (1, sampleMetric);
|
||||
|
||||
// Create router nodes, initialize routing database and set up the routing
|
||||
// tables in the nodes.
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
|
||||
// Create the OnOff application to send UDP datagrams
|
||||
NS_LOG_INFO ("Create Application.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
|
||||
// Create a flow from n3 to n1, starting at time 1.1 seconds
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (i1i2.GetAddress (0), port)));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (c.Get (3));
|
||||
apps.Start (Seconds (1.1));
|
||||
apps.Start (Seconds (10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
apps = sink.Install (c.Get (1));
|
||||
apps.Start (Seconds (1.1));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
std::ofstream ascii;
|
||||
ascii.open ("simple-alternate-routing.tr");
|
||||
PointToPointHelper::EnablePcapAll ("simple-alternate-routing");
|
||||
PointToPointHelper::EnableAsciiAll (ascii);
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* ns-2 simple.tcl script (ported from ns-2)
|
||||
* Originally authored by Steve McCanne, 12/19/1996
|
||||
*/
|
||||
|
||||
// Port of ns-2/tcl/ex/simple.tcl to ns-3
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0
|
||||
// \ 5 Mb/s, 2ms
|
||||
// \ 1.5Mb/s, 10ms
|
||||
// n2 -------------------------n3
|
||||
// /
|
||||
// / 5 Mb/s, 2ms
|
||||
// n1
|
||||
//
|
||||
// - all links are point-to-point links with indicated one-way BW/delay
|
||||
// - CBR/UDP flows from n0 to n3, and from n3 to n1
|
||||
// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
|
||||
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
|
||||
// (i.e., DataRate of 448,000 bps)
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file
|
||||
// "simple-error-model.tr"
|
||||
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/common-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/global-route-manager.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SimpleErrorModelExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
#if 0
|
||||
LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_INFO);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
// Set a few parameters
|
||||
Config::SetDefault ("ns3::RateErrorModel::ErrorRate", DoubleValue (0.01));
|
||||
Config::SetDefault ("ns3::RateErrorModel::ErrorUnit", StringValue ("EU_PKT"));
|
||||
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", DataRateValue (DataRate ("448kb/s")));
|
||||
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (4);
|
||||
NodeContainer n0n2 = NodeContainer (c.Get (0), c.Get (2));
|
||||
NodeContainer n1n2 = NodeContainer (c.Get (1), c.Get (2));
|
||||
NodeContainer n3n2 = NodeContainer (c.Get (3), c.Get (2));
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate (5000000)));
|
||||
p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
|
||||
NetDeviceContainer d0d2 = p2p.Install (n0n2);
|
||||
|
||||
NetDeviceContainer d1d2 = p2p.Install (n1n2);
|
||||
|
||||
p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate (1500000)));
|
||||
p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds (10)));
|
||||
NetDeviceContainer d3d2 = p2p.Install (n3n2);
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
ipv4.Assign (d0d2);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i1i2 = ipv4.Assign (d1d2);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i3i2 = ipv4.Assign (d3d2);
|
||||
|
||||
NS_LOG_INFO ("Use global routing.");
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (i3i2.GetAddress (1), port)));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable(1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable(0)));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (c.Get (0));
|
||||
apps.Start(Seconds(1.0));
|
||||
apps.Stop (Seconds(10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
apps = sink.Install (c.Get (3));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
onoff.SetAttribute ("Remote",
|
||||
AddressValue (InetSocketAddress (i1i2.GetAddress (0), port)));
|
||||
apps = onoff.Install (c.Get (3));
|
||||
apps.Start(Seconds(1.1));
|
||||
apps.Stop (Seconds(10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
sink.SetAttribute ("Local",
|
||||
AddressValue (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
apps = sink.Install (c.Get (1));
|
||||
apps.Start (Seconds (1.1));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
//
|
||||
// Error model
|
||||
//
|
||||
// Create an ErrorModel based on the implementation (constructor)
|
||||
// specified by the default classId
|
||||
Ptr<RateErrorModel> em = CreateObject<RateErrorModel> ("RanVar", RandomVariableValue (UniformVariable (0.0, 1.0)),
|
||||
"ErrorRate", DoubleValue (0.001));
|
||||
d3d2.Get (0)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
|
||||
|
||||
// Now, let's use the ListErrorModel and explicitly force a loss
|
||||
// of the packets with pkt-uids = 11 and 17 on node 2, device 0
|
||||
std::list<uint32_t> sampleList;
|
||||
sampleList.push_back (11);
|
||||
sampleList.push_back (17);
|
||||
// This time, we'll explicitly create the error model we want
|
||||
Ptr<ListErrorModel> pem = CreateObject<ListErrorModel> ();
|
||||
pem->SetList (sampleList);
|
||||
d0d2.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (pem));
|
||||
|
||||
std::ofstream ascii;
|
||||
ascii.open ("simple-error-model.tr");
|
||||
PointToPointHelper::EnablePcapAll ("simple-error-model");
|
||||
PointToPointHelper::EnableAsciiAll (ascii);
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* ns-2 simple.tcl script (ported from ns-2)
|
||||
* Originally authored by Steve McCanne, 12/19/1996
|
||||
*/
|
||||
|
||||
// Port of ns-2/tcl/ex/simple.tcl to ns-3
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0
|
||||
// \ 5 Mb/s, 2ms
|
||||
// \ 1.5Mb/s, 10ms
|
||||
// n2 -------------------------n3
|
||||
// /
|
||||
// / 5 Mb/s, 2ms
|
||||
// n1
|
||||
//
|
||||
// - all links are point-to-point links with indicated one-way BW/delay
|
||||
// - CBR/UDP flows from n0 to n3, and from n3 to n1
|
||||
// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
|
||||
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
|
||||
// (i.e., DataRate of 448,000 bps)
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file "simple-global-routing.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/global-route-manager.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SimpleGlobalRoutingExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
#if 0
|
||||
LogComponentEnable ("SimpleGlobalRoutingExample", LOG_LEVEL_INFO);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
// Set up some default values for the simulation. Use the
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("448kb/s"));
|
||||
|
||||
//DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// DefaultValue::Bind ()s at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (4);
|
||||
NodeContainer n0n2 = NodeContainer (c.Get(0), c.Get (2));
|
||||
NodeContainer n1n2 = NodeContainer (c.Get(1), c.Get (2));
|
||||
NodeContainer n3n2 = NodeContainer (c.Get(3), c.Get (2));
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer d0d2 = p2p.Install (n0n2);
|
||||
|
||||
NetDeviceContainer d1d2 = p2p.Install (n1n2);
|
||||
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
|
||||
NetDeviceContainer d3d2 = p2p.Install (n3n2);
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i0i2 = ipv4.Assign (d0d2);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i1i2 = ipv4.Assign (d1d2);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i3i2 = ipv4.Assign (d3d2);
|
||||
|
||||
// Create router nodes, initialize routing database and set up the routing
|
||||
// tables in the nodes.
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (i3i2.GetAddress (0), port)));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
ApplicationContainer apps = onoff.Install (c.Get (0));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
apps = sink.Install (c.Get (3));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
onoff.SetAttribute ("Remote",
|
||||
AddressValue (InetSocketAddress (i1i2.GetAddress (0), port)));
|
||||
apps = onoff.Install (c.Get (3));
|
||||
apps.Start (Seconds (1.1));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
apps = sink.Install (c.Get (1));
|
||||
apps.Start (Seconds (1.1));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
std::ofstream ascii;
|
||||
ascii.open ("simple-global-routing.tr");
|
||||
PointToPointHelper::EnablePcapAll ("simple-global-routing");
|
||||
PointToPointHelper::EnableAsciiAll (ascii);
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* ns-2 simple.tcl script (ported from ns-2)
|
||||
* Originally authored by Steve McCanne, 12/19/1996
|
||||
*/
|
||||
|
||||
// Port of ns-2/tcl/ex/simple.tcl to ns-3
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0
|
||||
// \ 5 Mb/s, 2ms
|
||||
// \ 1.5Mb/s, 10ms
|
||||
// n2 -------------------------n3
|
||||
// /
|
||||
// / 5 Mb/s, 2ms
|
||||
// n1
|
||||
//
|
||||
// - all links are p2p links with indicated one-way BW/delay
|
||||
// - CBR/UDP flows from n0 to n3, and from n3 to n1
|
||||
// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
|
||||
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
|
||||
// (i.e., DataRate of 448,000 bps)
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file "simple-p2p.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/debug.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/p2p-channel.h"
|
||||
#include "ns3/p2p-net-device.h"
|
||||
#include "ns3/mac-address.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/arp-ipv4-interface.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/datagram-socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/drop-tail.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/trace-root.h"
|
||||
#include "ns3/p2p-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/application-list.h"
|
||||
#include "ns3/random-variable.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#if 0
|
||||
DebugComponentEnable("Object");
|
||||
DebugComponentEnable("Queue");
|
||||
DebugComponentEnable("DropTailQueue");
|
||||
DebugComponentEnable("Channel");
|
||||
DebugComponentEnable("PointToPointChannel");
|
||||
DebugComponentEnable("PointToPointNetDevice");
|
||||
#endif
|
||||
|
||||
// Optionally, specify some default values for Queue objects.
|
||||
// For this example, we specify that we want each queue to
|
||||
// be a DropTail queue, with a limit of 30 packets.
|
||||
// Specify DropTail for default queue type (note. this is actually
|
||||
// the default, but included here as an example).
|
||||
Queue::Default(DropTailQueue());
|
||||
// Specify limit of 30 in units of packets (not implemented).
|
||||
// Queue::Default().SetLimitPackets(30);
|
||||
|
||||
// The node factory is designed to allow user specification
|
||||
// of the "type" of node desired for each node creation. This
|
||||
// is done by creating a node object (the inNode below), configuring
|
||||
// the object with the desired capabilities, and pushing the node
|
||||
// object on the prototype stack. In this simple example, the
|
||||
// default behavior of an InternetNode is adequate, so we don't
|
||||
// do any configuration in this simple example.
|
||||
InternetNode inNode;
|
||||
Node::PushNodePrototype(inNode);
|
||||
// Next create the physical node topology using the node factory
|
||||
Node* n0 = Node::Create();
|
||||
Node* n1 = Node::Create();
|
||||
Node* n2 = Node::Create();
|
||||
Node* n3 = Node::Create();
|
||||
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, Ipv4Address("10.1.1.1"),
|
||||
n2, Ipv4Address("10.1.1.2"),
|
||||
DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"),
|
||||
DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n2, Ipv4Address("10.1.3.1"),
|
||||
n3, Ipv4Address("10.1.3.2"),
|
||||
DataRate(1500000), MilliSeconds(10));
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
OnOffApplication* ooff0 = new OnOffApplication(
|
||||
*n0,
|
||||
Ipv4Address("10.1.3.2"),
|
||||
80,
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0),
|
||||
DataRate(448000),
|
||||
210);
|
||||
// Add to Node's ApplicationList (takes ownership of pointer)
|
||||
n0->GetApplicationList()->Add(ooff0);
|
||||
// Start the application
|
||||
ooff0->Start(Seconds(1.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
OnOffApplication* ooff1 = new OnOffApplication(
|
||||
*n3,
|
||||
Ipv4Address("10.1.2.1"),
|
||||
80,
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0),
|
||||
DataRate(448000),
|
||||
210);
|
||||
// Add to Node's ApplicationList (takes ownership of pointer)
|
||||
n3->GetApplicationList()->Add(ooff1);
|
||||
// Start the application
|
||||
ooff1->Start(Seconds(1.1));
|
||||
|
||||
// Here, finish off packet routing configuration
|
||||
// This will likely set by some global StaticRouting object in the future
|
||||
n0->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
|
||||
n3->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-p2p.tr file
|
||||
AsciiTrace trace ("simple-p2p.tr");
|
||||
trace.TraceAllQueues ();
|
||||
trace.TraceAllNetDeviceRx ();
|
||||
|
||||
Simulator::StopAt (Seconds(10.0));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* ns-2 simple.tcl script (ported from ns-2)
|
||||
* Originally authored by Steve McCanne, 12/19/1996
|
||||
*/
|
||||
|
||||
// Port of ns-2/tcl/ex/simple.tcl to ns-3
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0
|
||||
// \ 5 Mb/s, 2ms
|
||||
// \ 1.5Mb/s, 10ms
|
||||
// n2 -------------------------n3---------n4
|
||||
// /
|
||||
// / 5 Mb/s, 2ms
|
||||
// n1
|
||||
//
|
||||
// - all links are point-to-point links with indicated one-way BW/delay
|
||||
// - CBR/UDP flows from n0 to n3, and from n3 to n1
|
||||
// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
|
||||
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
|
||||
// (i.e., DataRate of 448,000 bps)
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file "simple-point-to-point-olsr.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SimpleGlobalRoutingExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
#if 0
|
||||
LogComponentEnable ("SimpleGlobalRoutingExample", LOG_LEVEL_INFO);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
// Set up some default values for the simulation. Use the
|
||||
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("448kb/s"));
|
||||
|
||||
//DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// DefaultValue::Bind ()s at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (5);
|
||||
NodeContainer n02 = NodeContainer (c.Get(0), c.Get (2));
|
||||
NodeContainer n12 = NodeContainer (c.Get(1), c.Get (2));
|
||||
NodeContainer n32 = NodeContainer (c.Get(3), c.Get (2));
|
||||
NodeContainer n34 = NodeContainer (c.Get (3), c.Get (4));
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer nd02 = p2p.Install (n02);
|
||||
NetDeviceContainer nd12 = p2p.Install (n12);
|
||||
p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
|
||||
p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
|
||||
NetDeviceContainer nd32 = p2p.Install (n32);
|
||||
NetDeviceContainer nd34 = p2p.Install (n34);
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i02 = ipv4.Assign (nd02);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i12 = ipv4.Assign (nd12);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i32 = ipv4.Assign (nd32);
|
||||
|
||||
ipv4.SetBase ("10.1.4.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i34 = ipv4.Assign (nd34);
|
||||
|
||||
// Enable OLSR
|
||||
NS_LOG_INFO ("Enabling OLSR Routing.");
|
||||
OlsrHelper olsr;
|
||||
olsr.InstallAll ();
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (i34.GetAddress (1), port));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (c.Get (0));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
|
||||
apps = sink.Install (c.Get (3));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
onoff.SetAttribute ("Remote",
|
||||
AddressValue (InetSocketAddress (i12.GetAddress (0), port)));
|
||||
apps = onoff.Install (c.Get (3));
|
||||
apps.Start (Seconds (1.1));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
apps = sink.Install (c.Get (1));
|
||||
apps.Start (Seconds (1.1));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
std::ofstream ascii;
|
||||
ascii.open ("simple-point-to-point-olsr.tr");
|
||||
PointToPointHelper::EnablePcapAll ("simple-point-to-point-olsr");
|
||||
PointToPointHelper::EnableAsciiAll (ascii);
|
||||
|
||||
Simulator::Stop (Seconds (30));
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// 10Mb/s, 10ms 10Mb/s, 10ms
|
||||
// n0-----------------n1-----------------n2
|
||||
//
|
||||
//
|
||||
// - Tracing of queues and packet receptions to file
|
||||
// "tcp-large-transfer.tr"
|
||||
// - pcap traces also generated in the following files
|
||||
// "tcp-large-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
|
||||
// Usage (e.g.): ./waf --run tcp-large-transfer
|
||||
|
||||
#include <ctype.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/global-route-manager.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
|
||||
|
||||
void
|
||||
ApplicationTraceSink (Ptr<const Packet> packet,
|
||||
const Address &addr)
|
||||
{
|
||||
// g_log is not declared in optimized builds
|
||||
// should convert this to use of some other flag than the logging system
|
||||
#ifdef NS3_LOG_ENABLE
|
||||
if (!g_log.IsNoneEnabled ()) {
|
||||
if (InetSocketAddress::IsMatchingType (addr) )
|
||||
{
|
||||
InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
|
||||
std::cout << "PacketSink received size " <<
|
||||
packet->GetSize () << " at time " <<
|
||||
Simulator::Now ().GetSeconds () << " from address: " <<
|
||||
address.GetIpv4 () << std::endl;
|
||||
char buf[2000];
|
||||
memcpy(buf, packet->PeekData (), packet->GetSize ());
|
||||
for (uint32_t i=0; i < packet->GetSize (); i++)
|
||||
{
|
||||
std::cout << buf[i];
|
||||
if (i && i % 60 == 0)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::endl << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CloseConnection (Ptr<Socket> localSocket)
|
||||
{
|
||||
localSocket->Close ();
|
||||
}
|
||||
|
||||
void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
|
||||
Ipv4Address servAddress,
|
||||
uint16_t servPort)
|
||||
{
|
||||
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
|
||||
localSocket->Connect (InetSocketAddress (servAddress, servPort));//connect
|
||||
localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
|
||||
Callback<void, Ptr<Socket> > (),
|
||||
Callback<void, Ptr<Socket> > ());
|
||||
//we want to close as soon as the connection is established
|
||||
//the tcp state machine and outgoing buffer will assure that
|
||||
//all of the data is delivered
|
||||
|
||||
// Perform series of 1040 byte writes (this is a multiple of 26 since
|
||||
// we want to detect data splicing in the output stream)
|
||||
uint32_t writeSize = 1040;
|
||||
uint8_t data[writeSize];
|
||||
while (nBytes > 0) {
|
||||
uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
|
||||
for(uint32_t i = 0; i < curSize; ++i)
|
||||
{
|
||||
char m = toascii (97 + i % 26);
|
||||
data[i] = m;
|
||||
}
|
||||
localSocket->Send (data, curSize);
|
||||
nBytes -= curSize;
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
|
||||
// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
|
||||
// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
|
||||
// LogComponentEnable("TcpLargeTransfer", LOG_LEVEL_ALL);
|
||||
|
||||
//
|
||||
// Make the random number generators generate reproducible results.
|
||||
//
|
||||
RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create three nodes.
|
||||
NodeContainer c0;
|
||||
c0.Create (2);
|
||||
|
||||
NodeContainer c1;
|
||||
c1.Add (c0.Get (1));
|
||||
c1.Create (1);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate(10000000)));
|
||||
p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds(10)));
|
||||
NetDeviceContainer dev0 = p2p.Install (c0);
|
||||
NetDeviceContainer dev1 = p2p.Install (c1);
|
||||
|
||||
// add ip/tcp stack to nodes.
|
||||
NodeContainer c = NodeContainer (c0, c1.Get (1));
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
// Later, we add IP addresses.
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
ipv4.Assign (dev0);
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev1);
|
||||
|
||||
// and setup ip routing tables to get total ip-level connectivity.
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Simulation 1
|
||||
//
|
||||
// Send 2000000 bytes over a connection to server port 50000 at time 0
|
||||
// Should observe SYN exchange, a lot of data segments, and FIN exchange
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int nBytes = 2000000;
|
||||
uint16_t servPort = 50000;
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::TcpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), servPort));
|
||||
|
||||
ApplicationContainer apps = sink.Install (c1.Get (1));
|
||||
apps.Start (Seconds (0.0));
|
||||
|
||||
// and generate traffic to remote sink.
|
||||
//TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory");
|
||||
Ptr<Socket> localSocket = Socket::CreateSocket (c0.Get (0), TcpSocketFactory::GetTypeId ());
|
||||
localSocket->Bind ();
|
||||
Simulator::ScheduleNow (&StartFlow, localSocket, nBytes,
|
||||
ipInterfs.GetAddress (1), servPort);
|
||||
|
||||
Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/Rx",
|
||||
MakeCallback (&ApplicationTraceSink));
|
||||
|
||||
std::ofstream ascii;
|
||||
ascii.open ("tcp-large-transfer.tr");
|
||||
PointToPointHelper::EnableAsciiAll (ascii);
|
||||
|
||||
PointToPointHelper::EnablePcapAll ("tcp-large-transfer");
|
||||
|
||||
Simulator::Stop (Seconds(1000));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
// Network topology
|
||||
//
|
||||
// n0 n1 n2 n3
|
||||
// | | | |
|
||||
// =================
|
||||
// LAN
|
||||
//
|
||||
// - UDP flows from n0 to n1 and back
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file "udp-echo.tr"
|
||||
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("UdpEchoExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
//
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
//
|
||||
#if 0
|
||||
LogComponentEnable ("UdpEchoExample", LOG_LEVEL_INFO);
|
||||
|
||||
LogComponentEnable("Object", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Queue", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Channel", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("NetDevice", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("PacketSocket", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Socket", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("UdpSocket", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("UdpL4Protocol", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Ipv4StaticRouting", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("ArpIpv4Interface", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Ipv4LoopbackInterface", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("OnOffApplication", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
|
||||
#endif
|
||||
|
||||
// Allow the user to override any of the defaults and the above Bind() at
|
||||
// run-time, via command-line arguments
|
||||
//
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
//
|
||||
// Explicitly create the nodes required by the topology (shown above).
|
||||
//
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer n;
|
||||
n.Create (4);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (n);
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
//
|
||||
// Explicitly create the channels required by the topology (shown above).
|
||||
//
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelParameter ("BitRate", DataRateValue (DataRate(5000000)));
|
||||
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
|
||||
NetDeviceContainer d = csma.Install (n);
|
||||
|
||||
Ipv4AddressHelper ipv4;
|
||||
//
|
||||
// We've got the "hardware" in place. Now we need to add IP addresses.
|
||||
//
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i = ipv4.Assign (d);
|
||||
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
//
|
||||
// Create a UdpEchoServer application on node one.
|
||||
//
|
||||
uint16_t port = 9; // well-known echo port number
|
||||
UdpEchoServerHelper server;
|
||||
server.SetPort (port);
|
||||
ApplicationContainer apps = server.Install (n.Get(1));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
//
|
||||
// Create a UdpEchoClient application to send UDP datagrams from node zero to
|
||||
// node one.
|
||||
//
|
||||
uint32_t packetSize = 1024;
|
||||
uint32_t maxPacketCount = 1;
|
||||
Time interPacketInterval = Seconds (1.);
|
||||
UdpEchoClientHelper client;
|
||||
client.SetRemote (i.GetAddress (1), port);
|
||||
client.SetAppAttribute ("MaxPackets", UintegerValue (maxPacketCount));
|
||||
client.SetAppAttribute ("Interval", TimeValue (interPacketInterval));
|
||||
client.SetAppAttribute ("PacketSize", UintegerValue (packetSize));
|
||||
apps = client.Install (n.Get (0));
|
||||
apps.Start (Seconds (2.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
|
||||
std::ofstream ascii;
|
||||
ascii.open ("udp-echo.tr");
|
||||
CsmaHelper::EnablePcapAll ("udp-echo");
|
||||
CsmaHelper::EnableAsciiAll (ascii);
|
||||
|
||||
//
|
||||
// Now, do the actual simulation.
|
||||
//
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../waf "$@"
|
||||
@@ -0,0 +1,261 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006,2007 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/common-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/contrib-module.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Main");
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
class Experiment
|
||||
{
|
||||
public:
|
||||
Experiment ();
|
||||
Experiment (std::string name);
|
||||
GnuplotDataset Run (const WifiHelper &wifi);
|
||||
private:
|
||||
void ReceivePacket (Ptr<Socket> socket);
|
||||
void SetPosition (Ptr<Node> node, Vector position);
|
||||
Vector GetPosition (Ptr<Node> node);
|
||||
void AdvancePosition (Ptr<Node> node);
|
||||
Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
|
||||
|
||||
uint32_t m_bytesTotal;
|
||||
GnuplotDataset m_output;
|
||||
};
|
||||
|
||||
Experiment::Experiment ()
|
||||
: m_output ()
|
||||
{}
|
||||
|
||||
Experiment::Experiment (std::string name)
|
||||
: m_output (name)
|
||||
{
|
||||
m_output.SetStyle (GnuplotDataset::LINES);
|
||||
}
|
||||
|
||||
void
|
||||
Experiment::SetPosition (Ptr<Node> node, Vector position)
|
||||
{
|
||||
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
|
||||
mobility->SetPosition (position);
|
||||
}
|
||||
|
||||
Vector
|
||||
Experiment::GetPosition (Ptr<Node> node)
|
||||
{
|
||||
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
|
||||
return mobility->GetPosition ();
|
||||
}
|
||||
|
||||
void
|
||||
Experiment::AdvancePosition (Ptr<Node> node)
|
||||
{
|
||||
Vector pos = GetPosition (node);
|
||||
double mbs = ((m_bytesTotal * 8.0) / 1000000);
|
||||
m_bytesTotal = 0;
|
||||
m_output.Add (pos.x, mbs);
|
||||
pos.x += 1.0;
|
||||
if (pos.x >= 210.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SetPosition (node, pos);
|
||||
//std::cout << "x="<<pos.x << std::endl;
|
||||
Simulator::Schedule (Seconds (1.0), &Experiment::AdvancePosition, this, node);
|
||||
}
|
||||
|
||||
void
|
||||
Experiment::ReceivePacket (Ptr<Socket> socket)
|
||||
{
|
||||
Ptr<Packet> packet;
|
||||
while (packet = socket->Recv ())
|
||||
{
|
||||
m_bytesTotal += packet->GetSize ();
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<Socket>
|
||||
Experiment::SetupPacketReceive (Ptr<Node> node)
|
||||
{
|
||||
TypeId tid = TypeId::LookupByName ("ns3::PacketSocketFactory");
|
||||
Ptr<Socket> sink = Socket::CreateSocket (node, tid);
|
||||
sink->Bind ();
|
||||
sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
|
||||
return sink;
|
||||
}
|
||||
|
||||
GnuplotDataset
|
||||
Experiment::Run (const WifiHelper &wifi)
|
||||
{
|
||||
m_bytesTotal = 0;
|
||||
|
||||
NodeContainer c;
|
||||
c.Create (2);
|
||||
|
||||
PacketSocketHelper packetSocket;
|
||||
packetSocket.Install (c);
|
||||
|
||||
NetDeviceContainer devices = wifi.Install (c);
|
||||
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (5.0, 0.0, 0.0));
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
mobility.SetMobilityModel ("ns3::StaticMobilityModel");
|
||||
|
||||
mobility.Install (c);
|
||||
|
||||
PacketSocketAddress socket;
|
||||
socket.SetSingleDevice(devices.Get (0)->GetIfIndex ());
|
||||
socket.SetPhysicalAddress (devices.Get (1)->GetAddress ());
|
||||
socket.SetProtocol (1);
|
||||
|
||||
OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (250)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
onoff.SetAttribute ("DataRate", DataRateValue (DataRate (60000000)));
|
||||
onoff.SetAttribute ("PacketSize", UintegerValue (2000));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (c.Get (0));
|
||||
apps.Start (Seconds (0.5));
|
||||
apps.Stop (Seconds (250.0));
|
||||
|
||||
Simulator::Schedule (Seconds (1.5), &Experiment::AdvancePosition, this, c.Get (1));
|
||||
Ptr<Socket> recvSink = SetupPacketReceive (c.Get (1));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
return m_output;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
// disable fragmentation
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
Gnuplot gnuplot = Gnuplot ("reference-rates.png");
|
||||
|
||||
Experiment experiment;
|
||||
WifiHelper wifi;
|
||||
GnuplotDataset dataset;
|
||||
|
||||
wifi.SetMac ("ns3::AdhocWifiMac");
|
||||
wifi.SetPhy ("ns3::WifiPhy");
|
||||
|
||||
NS_LOG_DEBUG ("54");
|
||||
experiment = Experiment ("54mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-54mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("48");
|
||||
experiment = Experiment ("48mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-48mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("36");
|
||||
experiment = Experiment ("36mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-36mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("24");
|
||||
experiment = Experiment ("24mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-24mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("18");
|
||||
experiment = Experiment ("18mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-18mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("12");
|
||||
experiment = Experiment ("12mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-12mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("9");
|
||||
experiment = Experiment ("9mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-9mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("6");
|
||||
experiment = Experiment ("6mb");
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("wifia-6mbs"));
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
gnuplot.GenerateOutput (std::cout);
|
||||
|
||||
|
||||
gnuplot = Gnuplot ("rate-control.png");
|
||||
Config::SetDefault ("ns3::WifiPhy::Standard", StringValue ("holland"));
|
||||
|
||||
|
||||
NS_LOG_DEBUG ("arf");
|
||||
experiment = Experiment ("arf");
|
||||
wifi.SetRemoteStationManager ("ns3::ArfWifiManager");
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("aarf");
|
||||
experiment = Experiment ("aarf");
|
||||
wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
NS_LOG_DEBUG ("ideal");
|
||||
experiment = Experiment ("ideal");
|
||||
wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
|
||||
dataset = experiment.Run (wifi);
|
||||
gnuplot.AddDataset (dataset);
|
||||
|
||||
gnuplot.GenerateOutput (std::cout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006,2007 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/common-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/contrib-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
void
|
||||
DevTxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
|
||||
{
|
||||
std::cout << " TX to=" << address << " p: " << *p << std::endl;
|
||||
}
|
||||
void
|
||||
DevRxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
|
||||
{
|
||||
std::cout << " RX from=" << address << " p: " << *p << std::endl;
|
||||
}
|
||||
void
|
||||
PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
|
||||
{
|
||||
std::cout << "PHYRXOK mode=" << mode << " snr=" << snr << " " << *packet << std::endl;
|
||||
}
|
||||
void
|
||||
PhyRxErrorTrace (std::string context, Ptr<const Packet> packet, double snr)
|
||||
{
|
||||
std::cout << "PHYRXERROR snr=" << snr << " " << *packet << std::endl;
|
||||
}
|
||||
void
|
||||
PhyTxTrace (std::string context, Ptr<const Packet> packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower)
|
||||
{
|
||||
std::cout << "PHYTX mode=" << mode << " " << *packet << std::endl;
|
||||
}
|
||||
void
|
||||
PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::State state)
|
||||
{
|
||||
std::cout << " state=";
|
||||
switch (state) {
|
||||
case WifiPhy::TX:
|
||||
std::cout << "tx ";
|
||||
break;
|
||||
case WifiPhy::SYNC:
|
||||
std::cout << "sync ";
|
||||
break;
|
||||
case WifiPhy::CCA_BUSY:
|
||||
std::cout << "cca-busy";
|
||||
break;
|
||||
case WifiPhy::IDLE:
|
||||
std::cout << "idle ";
|
||||
break;
|
||||
}
|
||||
std::cout << " start="<<start<<" duration="<<duration<<std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
SetPosition (Ptr<Node> node, Vector position)
|
||||
{
|
||||
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
|
||||
mobility->SetPosition (position);
|
||||
}
|
||||
|
||||
static Vector
|
||||
GetPosition (Ptr<Node> node)
|
||||
{
|
||||
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
|
||||
return mobility->GetPosition ();
|
||||
}
|
||||
|
||||
static void
|
||||
AdvancePosition (Ptr<Node> node)
|
||||
{
|
||||
Vector pos = GetPosition (node);
|
||||
pos.x += 5.0;
|
||||
if (pos.x >= 210.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SetPosition (node, pos);
|
||||
//std::cout << "x="<<pos.x << std::endl;
|
||||
Simulator::Schedule (Seconds (1.0), &AdvancePosition, node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Packet::EnableMetadata ();
|
||||
|
||||
// enable rts cts all the time.
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("0"));
|
||||
// disable fragmentation
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
|
||||
|
||||
WifiHelper wifi;
|
||||
MobilityHelper mobility;
|
||||
NodeContainer stas;
|
||||
NodeContainer ap;
|
||||
NetDeviceContainer staDevs;
|
||||
PacketSocketHelper packetSocket;
|
||||
|
||||
stas.Create (2);
|
||||
ap.Create (1);
|
||||
|
||||
// give packet socket powers to nodes.
|
||||
packetSocket.Install (stas);
|
||||
packetSocket.Install (ap);
|
||||
|
||||
Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
|
||||
channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
|
||||
Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
|
||||
log->SetReferenceModel (CreateObject<FriisPropagationLossModel> ());
|
||||
channel->SetPropagationLossModel (log);
|
||||
|
||||
Ssid ssid = Ssid ("wifi-default");
|
||||
wifi.SetPhy ("ns3::WifiPhy");
|
||||
wifi.SetRemoteStationManager ("ns3::ArfWifiManager");
|
||||
// setup stas.
|
||||
wifi.SetMac ("ns3::NqstaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
staDevs = wifi.Install (stas, channel);
|
||||
// setup ap.
|
||||
wifi.SetMac ("ns3::NqapWifiMac", "Ssid", SsidValue (ssid),
|
||||
"BeaconGeneration", BooleanValue (true),
|
||||
"BeaconInterval", TimeValue (Seconds (2.5)));
|
||||
wifi.Install (ap, channel);
|
||||
|
||||
// mobility.
|
||||
mobility.Install (stas);
|
||||
mobility.Install (ap);
|
||||
|
||||
Simulator::Schedule (Seconds (1.0), &AdvancePosition, ap.Get (0));
|
||||
|
||||
PacketSocketAddress socket;
|
||||
socket.SetSingleDevice(staDevs.Get (0)->GetIfIndex ());
|
||||
socket.SetPhysicalAddress (staDevs.Get (1)->GetAddress ());
|
||||
socket.SetProtocol (1);
|
||||
|
||||
OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
|
||||
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (42)));
|
||||
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (stas.Get (0));
|
||||
apps.Start (Seconds (0.5));
|
||||
apps.Stop (Seconds (43.0));
|
||||
|
||||
Simulator::Stop (Seconds (44.0));
|
||||
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/Tx", MakeCallback (&DevTxTrace));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/Rx", MakeCallback (&DevRxTrace));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxOk", MakeCallback (&PhyRxOkTrace));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxError", MakeCallback (&PhyRxErrorTrace));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/Phy/Tx", MakeCallback (&PhyTxTrace));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/Phy/State", MakeCallback (&PhyStateTrace));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
|
||||
obj = bld.create_ns3_program('mixed-wireless',
|
||||
['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-node'])
|
||||
obj.source = 'mixed-wireless.cc'
|
||||
|
||||
obj = bld.create_ns3_program('simple-global-routing',
|
||||
['point-to-point', 'internet-node', 'global-routing'])
|
||||
obj.source = 'simple-global-routing.cc'
|
||||
|
||||
obj = bld.create_ns3_program('simple-alternate-routing',
|
||||
['point-to-point', 'internet-node', 'global-routing'])
|
||||
obj.source = 'simple-alternate-routing.cc'
|
||||
|
||||
obj = bld.create_ns3_program('simple-error-model',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'simple-error-model.cc'
|
||||
|
||||
obj = bld.create_ns3_program('csma-one-subnet',
|
||||
['csma', 'internet-node'])
|
||||
obj.source = 'csma-one-subnet.cc'
|
||||
|
||||
obj = bld.create_ns3_program('udp-echo',
|
||||
['csma', 'internet-node'])
|
||||
obj.source = 'udp-echo.cc'
|
||||
|
||||
obj = bld.create_ns3_program('csma-broadcast',
|
||||
['csma', 'internet-node'])
|
||||
obj.source = 'csma-broadcast.cc'
|
||||
|
||||
obj = bld.create_ns3_program('csma-packet-socket',
|
||||
['csma', 'internet-node'])
|
||||
obj.source = 'csma-packet-socket.cc'
|
||||
|
||||
obj = bld.create_ns3_program('csma-multicast',
|
||||
['csma', 'internet-node'])
|
||||
obj.source = 'csma-multicast.cc'
|
||||
|
||||
obj = bld.create_ns3_program( 'mixed-global-routing',
|
||||
['point-to-point', 'internet-node', 'global-routing' , 'csma-cd'])
|
||||
obj.source = 'mixed-global-routing.cc'
|
||||
|
||||
obj = bld.create_ns3_program('simple-point-to-point-olsr',
|
||||
['point-to-point', 'internet-node', 'olsr'])
|
||||
obj.source = 'simple-point-to-point-olsr.cc'
|
||||
|
||||
obj = bld.create_ns3_program('tcp-large-transfer',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'tcp-large-transfer.cc'
|
||||
|
||||
obj = bld.create_ns3_program('wifi-adhoc',
|
||||
['core', 'simulator', 'mobility', 'wifi'])
|
||||
obj.source = 'wifi-adhoc.cc'
|
||||
|
||||
obj = bld.create_ns3_program('wifi-ap',
|
||||
['core', 'simulator', 'mobility', 'wifi'])
|
||||
obj.source = 'wifi-ap.cc'
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
This is a placeholder file used only to keep the ns3 directory present (needed for the WAF build system).
|
||||
@@ -0,0 +1,12 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName, "csma-broadcast")
|
||||
@@ -0,0 +1,12 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName, "csma-multicast")
|
||||
@@ -0,0 +1,12 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName, "csma-one-subnet")
|
||||
@@ -0,0 +1,13 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName,
|
||||
"csma-packet-socket")
|
||||
@@ -0,0 +1,13 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName,
|
||||
"simple-error-model")
|
||||
@@ -0,0 +1,13 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName,
|
||||
"simple-global-routing")
|
||||
@@ -0,0 +1,13 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName,
|
||||
"simple-point-to-point-olsr")
|
||||
@@ -0,0 +1,13 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName,
|
||||
"tcp-large-transfer")
|
||||
@@ -0,0 +1,12 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Generic trace-comparison-type regression test."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tracediff
|
||||
|
||||
def run(verbose, generate, refDirName):
|
||||
"""Execute a test."""
|
||||
|
||||
return tracediff.run_test(verbose, generate, refDirName, "udp-echo")
|
||||
+1
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../waf "$@"
|
||||
@@ -0,0 +1,142 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2008 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tom Henderson <tomh@tomh.org>
|
||||
*/
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/queue.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("AttributeValueSample");
|
||||
|
||||
//
|
||||
// This is a basic example of how to use the attribute system to
|
||||
// set and get a value in the underlying system; namely, an unsigned
|
||||
// integer of the maximum number of packets in a queue
|
||||
//
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
LogComponentEnable ("AttributeValueSample", LOG_LEVEL_INFO);
|
||||
|
||||
// By default, the MaxPackets attribute has a value of 100 packets
|
||||
// (this default can be observed in the function DropTailQueue::GetTypeId)
|
||||
//
|
||||
// Here, we set it to 80 packets. We could use one of two value types:
|
||||
// a string-based value or a UintegerValue value
|
||||
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("80"));
|
||||
// The below function call is redundant
|
||||
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (80));
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// SetDefaults() at run-time, via command-line arguments
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Now, we will create a few objects using the low-level API
|
||||
Ptr<Node> n0 = CreateObject<Node> ();
|
||||
|
||||
Ptr<PointToPointNetDevice> net0 = CreateObject<PointToPointNetDevice> ();
|
||||
n0->AddDevice (net0);
|
||||
|
||||
Ptr<Queue> q = CreateObject<DropTailQueue> ();
|
||||
net0->SetQueue(q);
|
||||
|
||||
// At this point, we have created a single node (Node 0) and a
|
||||
// single PointToPointNetDevice (NetDevice 0) and added a
|
||||
// DropTailQueue to it.
|
||||
|
||||
// Now, we can manipulate the MaxPackets value of the already
|
||||
// instantiated DropTailQueue. Here are various ways to do that.
|
||||
|
||||
// We assume that a smart pointer (Ptr) to a relevant network device
|
||||
// is in hand; here, it is the net0 pointer.
|
||||
|
||||
// 1. Pointer-based access
|
||||
//
|
||||
// One way to change the value is to access a pointer to the
|
||||
// underlying queue and modify its attribute.
|
||||
//
|
||||
// First, we observe that we can get a pointer to the (base class)
|
||||
// queue via the PointToPointNetDevice attributes, where it is called
|
||||
// TxQueue
|
||||
PointerValue ptr;
|
||||
net0->GetAttribute ("TxQueue", ptr);
|
||||
Ptr<Queue> txQueue = ptr.Get<Queue> ();
|
||||
|
||||
// Using the GetObject function, we can perform a safe downcast
|
||||
// to a DropTailQueue, where MaxPackets is a member
|
||||
Ptr<DropTailQueue> dtq = txQueue->GetObject <DropTailQueue> ();
|
||||
NS_ASSERT (dtq);
|
||||
|
||||
// Next, we can get the value of an attribute on this queue
|
||||
// We have introduced wrapper "Value" classes for the underlying
|
||||
// data types, similar to Java wrappers around these types, since
|
||||
// the attribute system stores values and not disparate types.
|
||||
// Here, the attribute value is assigned to a Uinteger, and
|
||||
// the Get() method on this value produces the (unwrapped) uint32_t.
|
||||
UintegerValue limit;
|
||||
dtq->GetAttribute ("MaxPackets", limit);
|
||||
NS_LOG_INFO ("1. dtq limit: " << limit.Get () << " packets");
|
||||
|
||||
// Note that the above downcast is not really needed; we could have
|
||||
// done the same using the Ptr<Queue> even though the attribute
|
||||
// is a member of the subclass
|
||||
txQueue->GetAttribute ("MaxPackets", limit);
|
||||
NS_LOG_INFO ("2. txQueue limit: " << limit.Get () << " packets");
|
||||
|
||||
// Now, let's set it to another value (60 packets)
|
||||
txQueue->SetAttribute("MaxPackets", UintegerValue (60));
|
||||
txQueue->GetAttribute ("MaxPackets", limit);
|
||||
NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get () << " packets");
|
||||
|
||||
// 2. Namespace-based access
|
||||
//
|
||||
// An alternative way to get at the attribute is to use the configuration
|
||||
// namespace. Here, this attribute resides on a known path in this
|
||||
// namespace; this approach is useful if one doesn't have access to
|
||||
// the underlying pointers and would like to configure a specific
|
||||
// attribute with a single statement.
|
||||
Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets", UintegerValue (25));
|
||||
txQueue->GetAttribute ("MaxPackets", limit);
|
||||
NS_LOG_INFO ("4. txQueue limit changed through namespace: " <<
|
||||
limit.Get () << " packets");
|
||||
|
||||
// we could have also used wildcards to set this value for all nodes
|
||||
// and all net devices (which in this simple example has the same
|
||||
// effect as the previous Set())
|
||||
Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets", UintegerValue (15));
|
||||
txQueue->GetAttribute ("MaxPackets", limit);
|
||||
NS_LOG_INFO ("5. txQueue limit changed through wildcarded namespace: " <<
|
||||
limit.Get () << " packets");
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 University of Washington
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "ns3/debug.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/drop-tail.h"
|
||||
#include "ns3/layer-connector.h"
|
||||
#include "ns3/channel.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
// ===========================================================================
|
||||
// Cook up a simplistic Internet Node
|
||||
// ===========================================================================
|
||||
class FakeInternetNode : public LayerConnectorUpper
|
||||
{
|
||||
public:
|
||||
FakeInternetNode ();
|
||||
~FakeInternetNode ();
|
||||
|
||||
void Doit (void);
|
||||
|
||||
protected:
|
||||
bool UpperDoSendUp (Packet &p);
|
||||
bool UpperDoPull (Packet &p);
|
||||
|
||||
DropTailQueue m_dtqOutbound;
|
||||
DropTailQueue m_dtqInbound;
|
||||
};
|
||||
|
||||
FakeInternetNode::FakeInternetNode ()
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakeInternetNode::FakeInternetNode ()");
|
||||
}
|
||||
|
||||
FakeInternetNode::~FakeInternetNode ()
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakeInternetNode::~FakeInternetNode ()");
|
||||
}
|
||||
|
||||
void
|
||||
FakeInternetNode::Doit (void)
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakeInternetNode::Doit ()");
|
||||
NS_DEBUG_UNCOND("FakeInternetNode::Doit (): **** Send outbound packet");
|
||||
Packet p;
|
||||
|
||||
m_dtqOutbound.Enqueue(p);
|
||||
UpperNotify();
|
||||
}
|
||||
|
||||
bool
|
||||
FakeInternetNode::UpperDoSendUp (Packet &p)
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakeInternetNode::UpperDoSendUp (" << &p << ")");
|
||||
|
||||
NS_DEBUG_UNCOND("FakeInternetNode::UpperDoSendUp (): **** Receive inbound packet");
|
||||
m_dtqInbound.Enqueue(p);
|
||||
return m_dtqInbound.Dequeue(p);
|
||||
}
|
||||
|
||||
bool
|
||||
FakeInternetNode::UpperDoPull (Packet &p)
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakeInternetNode::DoPull (" << &p << ")");
|
||||
|
||||
return m_dtqOutbound.Dequeue(p);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Cook up a simplistic Physical Layer
|
||||
// ===========================================================================
|
||||
class FakePhysicalLayer :
|
||||
public LayerConnectorLower,
|
||||
public LayerConnectorUpper
|
||||
{
|
||||
public:
|
||||
FakePhysicalLayer ();
|
||||
~FakePhysicalLayer ();
|
||||
|
||||
protected:
|
||||
bool LowerDoNotify (LayerConnectorUpper *upper);
|
||||
bool UpperDoSendUp (Packet &p);
|
||||
bool UpperDoPull (Packet &p);
|
||||
|
||||
DropTailQueue m_dtqInbound;
|
||||
DropTailQueue m_dtqOutbound;
|
||||
};
|
||||
|
||||
FakePhysicalLayer::FakePhysicalLayer ()
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakePhysicalLayer::FakePhysicalLayer ()");
|
||||
}
|
||||
|
||||
FakePhysicalLayer::~FakePhysicalLayer ()
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakePhysicalLayer::~FakePhysicalLayer ()");
|
||||
}
|
||||
|
||||
bool
|
||||
FakePhysicalLayer::LowerDoNotify (LayerConnectorUpper *upper)
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakePhysicalLayer::LowerDoNotify ()");
|
||||
|
||||
Packet p;
|
||||
|
||||
NS_DEBUG_UNCOND("FakePhysicalLayer::LowerDoNotify (): Starting pull");
|
||||
|
||||
NS_ASSERT(m_upperPartner);
|
||||
m_upperPartner->UpperPull(p);
|
||||
|
||||
m_dtqOutbound.Enqueue(p);
|
||||
|
||||
NS_DEBUG_UNCOND("FakePhysicalLayer::LowerDoNotify (): Got bits, Notify lower");
|
||||
|
||||
NS_ASSERT(m_lowerPartner);
|
||||
return m_lowerPartner->LowerNotify(this);
|
||||
}
|
||||
|
||||
bool
|
||||
FakePhysicalLayer::UpperDoSendUp (Packet &p)
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakePhysicalLayer::UpperDoSendUp (" << &p << ")");
|
||||
|
||||
NS_ASSERT(m_upperPartner);
|
||||
return m_upperPartner->UpperSendUp(p);
|
||||
}
|
||||
|
||||
bool
|
||||
FakePhysicalLayer::UpperDoPull (Packet &p)
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakePhysicalLayer::DoPull (" << &p << ")");
|
||||
|
||||
return m_dtqOutbound.Dequeue(p);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Cook up a simplistic Channel, just to add any moby hack we feel like
|
||||
// ===========================================================================
|
||||
class FakeChannel : public Channel
|
||||
{
|
||||
public:
|
||||
FakeChannel ();
|
||||
~FakeChannel ();
|
||||
};
|
||||
|
||||
FakeChannel::FakeChannel ()
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakeChannel::FakeChannel ()");
|
||||
}
|
||||
|
||||
FakeChannel::~FakeChannel ()
|
||||
{
|
||||
NS_DEBUG_UNCOND("FakeChannel::~FakeChannel ()");
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
NS_DEBUG_UNCOND("Channel Hackorama");
|
||||
|
||||
#if 0
|
||||
DebugComponentEnable("Queue");
|
||||
DebugComponentEnable("DropTailQueue");
|
||||
DebugComponentEnable("LayerConnector");
|
||||
DebugComponentEnable("Channel");
|
||||
#endif
|
||||
|
||||
FakeInternetNode node1, node2, node3, node4;
|
||||
FakePhysicalLayer phys1, phys2, phys3, phys4;
|
||||
FakeChannel channel;
|
||||
Packet pkt;
|
||||
|
||||
// all the hassle above lets us do something very simple here
|
||||
|
||||
node1.ConnectToLower(phys1);
|
||||
phys1.ConnectToUpper(node1);
|
||||
phys1.ConnectToLower(channel);
|
||||
channel.ConnectToUpper(phys1);
|
||||
|
||||
node2.ConnectToLower(phys2);
|
||||
phys2.ConnectToUpper(node2);
|
||||
phys2.ConnectToLower(channel);
|
||||
channel.ConnectToUpper(phys2);
|
||||
|
||||
node3.ConnectToLower(phys3);
|
||||
phys3.ConnectToUpper(node3);
|
||||
phys3.ConnectToLower(channel);
|
||||
channel.ConnectToUpper(phys3);
|
||||
|
||||
node4.ConnectToLower(phys4);
|
||||
phys4.ConnectToUpper(node4);
|
||||
phys4.ConnectToLower(channel);
|
||||
channel.ConnectToUpper(phys4);
|
||||
|
||||
node1.Doit();
|
||||
node2.Doit();
|
||||
node3.Doit();
|
||||
node4.Doit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
#include "ns3/debug.h"
|
||||
|
||||
NS_DEBUG_COMPONENT_DEFINE ("MyComponentB");
|
||||
|
||||
namespace foo {
|
||||
|
||||
void OneFunction (void)
|
||||
{
|
||||
NS_DEBUG ("OneFunction debug");
|
||||
}
|
||||
|
||||
}; // namespace foo
|
||||
@@ -1,27 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
#include "ns3/debug.h"
|
||||
#include "ns3/assert.h"
|
||||
|
||||
NS_DEBUG_COMPONENT_DEFINE ("MyComponentA");
|
||||
|
||||
// declare other function
|
||||
namespace foo {
|
||||
void OneFunction (void);
|
||||
}
|
||||
|
||||
int main (int argc, int argv)
|
||||
{
|
||||
NS_DEBUG ("nargc="<<argc);
|
||||
|
||||
foo::OneFunction ();
|
||||
|
||||
NS_DEBUG ("other debug output");
|
||||
|
||||
int a;
|
||||
a = 0;
|
||||
|
||||
NS_ASSERT (a == 0);
|
||||
NS_ASSERT_MSG (a == 0, "my msg");
|
||||
NS_ASSERT (a != 0);
|
||||
NS_ASSERT_MSG (a != 0, "my 2 msg");
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
NodeContainer nodes;
|
||||
|
||||
// create an array of empty nodes for testing purposes
|
||||
nodes.Create (120);
|
||||
|
||||
MobilityHelper mobility;
|
||||
// setup the grid itself: objects are layed out
|
||||
// started from (-100,-100) with 20 objects per row,
|
||||
// the x interval between each object is 5 meters
|
||||
// and the y interval between each object is 20 meters
|
||||
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
|
||||
"MinX", DoubleValue (-100.0),
|
||||
"MinY", DoubleValue (-100.0),
|
||||
"DeltaX", DoubleValue (5.0),
|
||||
"DeltaY", DoubleValue (20.0),
|
||||
"GridWidth", UintegerValue (20),
|
||||
"LayoutType", StringValue ("RowFirst"));
|
||||
// each object will be attached a static position.
|
||||
// i.e., once set by the "position allocator", the
|
||||
// position will never change.
|
||||
mobility.SetMobilityModel ("ns3::StaticMobilityModel");
|
||||
|
||||
// finalize the setup by attaching to each object
|
||||
// in the input array a position and initializing
|
||||
// this position with the calculated coordinates.
|
||||
mobility.Install (nodes);
|
||||
|
||||
// iterate our nodes and print their position.
|
||||
for (NodeContainer::Iterator j = nodes.Begin ();
|
||||
j != nodes.End (); ++j)
|
||||
{
|
||||
Ptr<Node> object = *j;
|
||||
Ptr<MobilityModel> position = object->GetObject<MobilityModel> ();
|
||||
NS_ASSERT (position != 0);
|
||||
Vector pos = position->GetPosition ();
|
||||
std::cout << "x=" << pos.x << ", y=" << pos.y << ", z=" << pos.z << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 University of Washington
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/debug.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/arp-ipv4-interface.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/p2p-channel.h"
|
||||
#include "ns3/p2p-net-device.h"
|
||||
#include "ns3/drop-tail.h"
|
||||
#include "ns3/arp-ipv4-interface.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/trace-context.h"
|
||||
#include "ns3/datagram-socket.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/trace-root.h"
|
||||
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
|
||||
Logger (std::string const &filename)
|
||||
{
|
||||
m_filestr.open (filename.c_str ());
|
||||
NS_DEBUG_UNCOND("**** Logger(string const &)");
|
||||
}
|
||||
|
||||
~Logger () {}
|
||||
|
||||
void Log (TraceContext const &context, const Packet &p)
|
||||
{
|
||||
NodeList::NodeIndex nodeIndex;
|
||||
context.Get (nodeIndex);
|
||||
m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
|
||||
Ipv4::InterfaceIndex interfaceIndex;
|
||||
context.Get (interfaceIndex);
|
||||
m_filestr << "interface=" << interfaceIndex << " ";
|
||||
enum Queue::TraceType type;
|
||||
context.Get (type);
|
||||
switch (type)
|
||||
{
|
||||
case Queue::ENQUEUE:
|
||||
m_filestr << "enqueue";
|
||||
break;
|
||||
case Queue::DEQUEUE:
|
||||
m_filestr << "dequeue";
|
||||
break;
|
||||
case Queue::DROP:
|
||||
m_filestr << "drop";
|
||||
break;
|
||||
}
|
||||
m_filestr << " bytes=" << p.GetSize () << std::endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::ofstream m_filestr;;
|
||||
};
|
||||
|
||||
static void
|
||||
GenerateTraffic (DatagramSocket *socket, uint32_t size)
|
||||
{
|
||||
std::cout << "Node: " << socket->GetNode()->GetId ()
|
||||
<< " at=" << Simulator::Now ().GetSeconds () << "s,"
|
||||
<< " tx bytes=" << size << std::endl;
|
||||
socket->SendDummy (size);
|
||||
if (size > 50)
|
||||
{
|
||||
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
|
||||
{
|
||||
std::cout << "Node: " << socket->GetNode()->GetId ()
|
||||
<< " at=" << Simulator::Now ().GetSeconds () << "s,"
|
||||
<< " rx bytes=" << size << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
PrintTraffic (DatagramSocket *socket)
|
||||
{
|
||||
socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
NS_DEBUG_UNCOND("PointToPoint Net Device Test");
|
||||
|
||||
// create two nodes and a simple PointToPointChannel
|
||||
InternetNode a;
|
||||
InternetNode b;
|
||||
PointToPointChannel ch = PointToPointChannel ("Test Channel", 1000,
|
||||
Seconds (0.1));
|
||||
|
||||
NodeList::Add (&a);
|
||||
NodeList::Add (&b);
|
||||
|
||||
// create two NetDevices and assign one to each node
|
||||
// Note: this would normally be done also in conjunction with
|
||||
// creating a Channel
|
||||
|
||||
PointToPointNetDevice neta(&a);
|
||||
|
||||
DropTailQueue dtqa;
|
||||
|
||||
neta.AddQueue(&dtqa);
|
||||
neta.SetName("a.eth0");
|
||||
|
||||
PointToPointNetDevice netb(&b);
|
||||
|
||||
DropTailQueue dtqb;
|
||||
|
||||
netb.AddQueue(&dtqb);
|
||||
netb.SetName("b.eth0");
|
||||
|
||||
// bind the two NetDevices together by using a simple Channel
|
||||
// this method changed to do a bidirectional binding
|
||||
neta.Attach (&ch);
|
||||
netb.Attach (&ch);
|
||||
|
||||
// Some simple prints to see whether it is working
|
||||
NS_DEBUG_UNCOND("neta.GetMtu() <= " << neta.GetMtu());
|
||||
NS_DEBUG_UNCOND("netb.GetMtu() <= " << netb.GetMtu());
|
||||
NS_DEBUG_UNCOND("neta.GetAddress() <= " << neta.GetAddress());
|
||||
NS_DEBUG_UNCOND("netb.GetAddress() <= " << netb.GetAddress());
|
||||
|
||||
// Note: InternetNode constructor instantiates multiple Layer-3
|
||||
// protocols and registers them with the L3Demux object.
|
||||
// This takes care of Layer-2 -> Layer-3 bindings.
|
||||
// XXX TODO: will need to create a dummy IPv4 object for insertion
|
||||
// into the Demux
|
||||
|
||||
// We now need to bind the InternetNode to the various interfaces.
|
||||
// to get the Layer-3 -> Layer-2 bindings.
|
||||
|
||||
// We do this by calling an "AddArpIpv4Interface(neta)" function on node a.
|
||||
// This should:
|
||||
// i) create an Ipv4ArpInterface object (subclass of pure virtual
|
||||
// Ipv4Interface object)
|
||||
// ii) add the Ipv4ArpInterface object to the InternetNode's internal
|
||||
// vector of Ipv4Interfaces (keyed off of ifIndex)
|
||||
|
||||
NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode a");
|
||||
ArpIpv4Interface* arpipv4interfacep = new ArpIpv4Interface(&a, &neta);
|
||||
uint32_t indexA;
|
||||
indexA = (&a)->GetIpv4 ()->AddInterface (arpipv4interfacep);
|
||||
NS_DEBUG_UNCOND("Adding Interface " << indexA);
|
||||
|
||||
|
||||
// iii) give the interface an IP address
|
||||
|
||||
NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
|
||||
arpipv4interfacep->SetAddress(Ipv4Address("10.1.1.1"));
|
||||
arpipv4interfacep->SetNetworkMask(Ipv4Mask("255.255.255.0"));
|
||||
|
||||
// iv) set the interface's state to "UP"
|
||||
|
||||
NS_DEBUG_UNCOND("Setting ARP interface to UP");
|
||||
arpipv4interfacep->SetUp();
|
||||
|
||||
a.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
|
||||
|
||||
|
||||
NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode b");
|
||||
ArpIpv4Interface* arpipv4interfacepb = new ArpIpv4Interface(&b, &netb);
|
||||
uint32_t indexB;
|
||||
indexB = (&b)->GetIpv4 ()->AddInterface (arpipv4interfacepb);
|
||||
NS_DEBUG_UNCOND("Adding Interface " << indexB);
|
||||
|
||||
|
||||
// iii) give the interface an IP address
|
||||
|
||||
NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
|
||||
arpipv4interfacepb->SetAddress(Ipv4Address("10.1.1.2"));
|
||||
arpipv4interfacepb->SetNetworkMask(Ipv4Mask("255.255.255.0"));
|
||||
|
||||
// iv) set the interface's state to "UP"
|
||||
|
||||
NS_DEBUG_UNCOND("Setting ARP interface to UP");
|
||||
arpipv4interfacepb->SetUp();
|
||||
|
||||
b.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.1"), 1);
|
||||
|
||||
|
||||
DatagramSocket *source = new DatagramSocket (&a);
|
||||
DatagramSocket *sink = new DatagramSocket(&b);
|
||||
sink->Bind (80);
|
||||
source->SetDefaultDestination (Ipv4Address ("10.1.1.2"), 80);
|
||||
|
||||
Logger logger("p2p-net-test.log");
|
||||
|
||||
TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*",
|
||||
MakeCallback (&Logger::Log, &logger));
|
||||
|
||||
PrintTraffic (sink);
|
||||
GenerateTraffic (source, 100);
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
delete source;
|
||||
delete sink;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/header.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/* A sample Header implementation
|
||||
*/
|
||||
class MyHeader : public Header
|
||||
{
|
||||
public:
|
||||
|
||||
MyHeader ();
|
||||
virtual ~MyHeader ();
|
||||
|
||||
void SetData (uint16_t data);
|
||||
uint16_t GetData (void) const;
|
||||
|
||||
static TypeId GetTypeId (void);
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
virtual void Print (std::ostream &os) const;
|
||||
virtual void Serialize (Buffer::Iterator start) const;
|
||||
virtual uint32_t Deserialize (Buffer::Iterator start);
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
private:
|
||||
uint16_t m_data;
|
||||
};
|
||||
|
||||
MyHeader::MyHeader ()
|
||||
{
|
||||
// we must provide a public default constructor,
|
||||
// implicit or explicit, but never private.
|
||||
}
|
||||
MyHeader::~MyHeader ()
|
||||
{}
|
||||
|
||||
TypeId
|
||||
MyHeader::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::MyHeader")
|
||||
.SetParent<Header> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
TypeId
|
||||
MyHeader::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
void
|
||||
MyHeader::Print (std::ostream &os) const
|
||||
{
|
||||
// This method is invoked by the packet printing
|
||||
// routines to print the content of my header.
|
||||
os << "data=" << m_data << std::endl;
|
||||
}
|
||||
uint32_t
|
||||
MyHeader::GetSerializedSize (void) const
|
||||
{
|
||||
// we reserve 2 bytes for our header.
|
||||
return 2;
|
||||
}
|
||||
void
|
||||
MyHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
// we can serialize two bytes at the start of the buffer.
|
||||
// we write them in network byte order.
|
||||
start.WriteHtonU16 (m_data);
|
||||
}
|
||||
uint32_t
|
||||
MyHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
// we can deserialize two bytes from the start of the buffer.
|
||||
// we read them in network byte order and store them
|
||||
// in host byte order.
|
||||
m_data = start.ReadNtohU16 ();
|
||||
|
||||
// we return the number of bytes effectively read.
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
MyHeader::SetData (uint16_t data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
uint16_t
|
||||
MyHeader::GetData (void) const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
// instantiate a header.
|
||||
MyHeader sourceHeader;
|
||||
sourceHeader.SetData (2);
|
||||
|
||||
// instantiate a packet
|
||||
Ptr<Packet> p = Create<Packet> ();
|
||||
|
||||
// and store my header into the packet.
|
||||
p->AddHeader (sourceHeader);
|
||||
|
||||
// print the content of my packet on the standard output.
|
||||
p->Print (std::cout);
|
||||
|
||||
// you can now remove the header from the packet:
|
||||
MyHeader destinationHeader;
|
||||
p->RemoveHeader (destinationHeader);
|
||||
|
||||
// and check that the destination and source
|
||||
// headers contain the same values.
|
||||
NS_ASSERT (sourceHeader.GetData () == destinationHeader.GetData ());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2006,2007 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/header.h"
|
||||
#include "ns3/packet-printer.h"
|
||||
#include "ns3/ipv4-header.h"
|
||||
#include "ns3/udp-header.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
// This sample file shows how to use the Packet metadata facility
|
||||
//
|
||||
// Packets are stored as ``packed'' data structures, to facilitate
|
||||
// fragmentation and network emulation. However, when debugging a program,
|
||||
// or for certain tracing applications, it may be convenient to dump out
|
||||
// the contents of a packet header in a human-friendly form.
|
||||
//
|
||||
// To do this, a few things are needed:
|
||||
// i) enable the metadata facility (disabled by default, because it causes
|
||||
// a small performance hit
|
||||
// ii) decide on whether you want to use a default or customized (you
|
||||
// provide your own) routine to dump a particular header
|
||||
//
|
||||
// This sample steps through two routines; one to use the default
|
||||
// printing of IPv4 and UDP headers, and one to show a non-default case.
|
||||
// There is a lot of emphasis in this sample of how this facility
|
||||
// interacts with packet fragmentation.
|
||||
|
||||
void DefaultPrint (void)
|
||||
{
|
||||
// We create a packet with 1000 bytes of zero payload
|
||||
// and add 3 headers to this packet.
|
||||
Ptr<Packet> p = Create<Packet> (1000);
|
||||
Ipv4Header ipv4;
|
||||
UdpHeader udp;
|
||||
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
|
||||
ipv4.SetDestination (Ipv4Address ("192.168.0.2"));
|
||||
udp.SetSource (1025);
|
||||
udp.SetDestination (80);
|
||||
udp.SetPayloadSize (1000);
|
||||
p->AddHeader (udp);
|
||||
p->AddHeader (ipv4);
|
||||
|
||||
std::cout << "full packet size=" << p->GetSize () << std::endl;
|
||||
// Here, invoke the default Print routine, directed to std out
|
||||
p->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Now, we fragment our packet in 3 consecutive pieces.
|
||||
Ptr<Packet> p1 = p->CreateFragment (0, 2);
|
||||
Ptr<Packet> p2 = p->CreateFragment (2, 1000);
|
||||
Ptr<Packet> p3 = p->CreateFragment (1002, 26);
|
||||
|
||||
std::cout << "fragment1" << std::endl;
|
||||
p1->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment2" << std::endl;
|
||||
p2->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment3" << std::endl;
|
||||
p3->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
|
||||
// And, finally, we re-aggregate the 3 consecutive pieces.
|
||||
Ptr<Packet> aggregate = p1->Copy ();
|
||||
aggregate->AddAtEnd (p2);
|
||||
aggregate->AddAtEnd (p3);
|
||||
std::cout << "aggregated" << std::endl;
|
||||
aggregate->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
DoPrintPayload (std::ostream & os,uint32_t packetUid,uint32_t size,
|
||||
struct PacketPrinter::FragmentInformation info)
|
||||
{
|
||||
os << "PAYLOAD (size " << size << " trim_start " << info.start << " trim_end " << info.end << ")";
|
||||
}
|
||||
void
|
||||
DoPrintIpv4Header (std::ostream &os, uint32_t packetUid, uint32_t size, const Ipv4Header *ipv4)
|
||||
{
|
||||
os << "IPV4 " << ipv4->GetSource () << " > " << ipv4->GetDestination ();
|
||||
}
|
||||
void
|
||||
DoPrintIpv4HeaderFragment (std::ostream &os, uint32_t packetUid, uint32_t size,
|
||||
std::string &name, struct PacketPrinter::FragmentInformation info)
|
||||
{
|
||||
os << "IPV4 fragment";
|
||||
}
|
||||
|
||||
// This function walks through a non-default case. A few features of
|
||||
// the API (defined in common/packet-printer.h) are shown.
|
||||
//
|
||||
void NonDefaultPrint (void)
|
||||
{
|
||||
// create an adhoc packet printer.
|
||||
PacketPrinter printer;
|
||||
// print from first header to last trailer
|
||||
printer.PrintForward ();
|
||||
// set a string separator automatically inserted
|
||||
// between each call to a printing function.
|
||||
printer.SetSeparator (" - ");
|
||||
// set the payload print function
|
||||
printer.SetPayloadPrinter (MakeCallback (&DoPrintPayload));
|
||||
// set the print function for the header type Ipv4Header.
|
||||
printer.SetHeaderPrinter (MakeCallback (&DoPrintIpv4Header),
|
||||
MakeCallback (&DoPrintIpv4HeaderFragment));
|
||||
|
||||
|
||||
// We create a packet with 1000 bytes of zero payload
|
||||
Ptr<Packet> p = Create<Packet> (1000);
|
||||
Ipv4Header ipv4;
|
||||
UdpHeader udp;
|
||||
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
|
||||
ipv4.SetDestination (Ipv4Address ("192.168.0.2"));
|
||||
udp.SetSource (1025);
|
||||
udp.SetDestination (80);
|
||||
udp.SetPayloadSize (1000);
|
||||
p->AddHeader (udp);
|
||||
p->AddHeader (ipv4);
|
||||
|
||||
std::cout << "full packet size=" << p->GetSize () << std::endl;
|
||||
p->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// fragment our packet in 3 pieces
|
||||
Ptr<Packet> p1 = p->CreateFragment (0, 2);
|
||||
Ptr<Packet> p2 = p->CreateFragment (2, 1000);
|
||||
Ptr<Packet> p3 = p->CreateFragment (1002, 26);
|
||||
std::cout << "fragment1" << std::endl;
|
||||
p1->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment2" << std::endl;
|
||||
p2->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment3" << std::endl;
|
||||
p3->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
|
||||
// aggregate all 3 fragments of the original packet
|
||||
// to reconstruct a copy of the original packet.
|
||||
Ptr<Packet> aggregate = p1->Copy ();
|
||||
aggregate->AddAtEnd (p2);
|
||||
aggregate->AddAtEnd (p3);
|
||||
std::cout << "aggregated" << std::endl;
|
||||
aggregate->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Packet::EnableMetadata ();
|
||||
|
||||
std::cout << "DefaultPrint()" << std::endl;
|
||||
DefaultPrint ();
|
||||
|
||||
std::cout << std::endl << "NonDefaultPrint()" << std::endl;
|
||||
NonDefaultPrint ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2006,2007 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "ns3/tag.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
// define this class in a public header
|
||||
class MyTag : public Tag
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
virtual void Serialize (TagBuffer i) const;
|
||||
virtual void Deserialize (TagBuffer i);
|
||||
|
||||
// these are our accessors to our tag structure
|
||||
void SetSimpleValue (uint8_t value);
|
||||
uint8_t GetSimpleValue (void) const;
|
||||
private:
|
||||
uint8_t m_simpleValue;
|
||||
};
|
||||
|
||||
TypeId
|
||||
MyTag::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::MyTag")
|
||||
.SetParent<Tag> ()
|
||||
.AddConstructor<MyTag> ()
|
||||
.AddAttribute ("SimpleValue",
|
||||
"A simple value",
|
||||
EmptyAttributeValue (),
|
||||
MakeUintegerAccessor (&MyTag::GetSimpleValue),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
TypeId
|
||||
MyTag::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
uint32_t
|
||||
MyTag::GetSerializedSize (void) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
void
|
||||
MyTag::Serialize (TagBuffer i) const
|
||||
{
|
||||
i.WriteU8 (m_simpleValue);
|
||||
}
|
||||
void
|
||||
MyTag::Deserialize (TagBuffer i)
|
||||
{
|
||||
m_simpleValue = i.ReadU8 ();
|
||||
}
|
||||
void
|
||||
MyTag::SetSimpleValue (uint8_t value)
|
||||
{
|
||||
m_simpleValue = value;
|
||||
}
|
||||
uint8_t
|
||||
MyTag::GetSimpleValue (void) const
|
||||
{
|
||||
return m_simpleValue;
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
// create a tag.
|
||||
MyTag tag;
|
||||
tag.SetSimpleValue (0x56);
|
||||
|
||||
// store the tag in a packet.
|
||||
Ptr<Packet> p = Create<Packet> ();
|
||||
p->AddTag (tag);
|
||||
|
||||
// create a copy of the packet
|
||||
Ptr<Packet> aCopy = p->Copy ();
|
||||
|
||||
// read the tag from the packet copy
|
||||
MyTag tagCopy;
|
||||
p->FindFirstMatchingTag (tagCopy);
|
||||
|
||||
// the copy and the original are the same !
|
||||
NS_ASSERT (tagCopy.GetSimpleValue () == tag.GetSimpleValue ());
|
||||
|
||||
aCopy->PrintTags (std::cout);
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/header.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/* A sample Header implementation
|
||||
*/
|
||||
class MyHeader : public Header {
|
||||
public:
|
||||
MyHeader ();
|
||||
virtual ~MyHeader ();
|
||||
|
||||
void SetData (uint16_t data);
|
||||
uint16_t GetData (void) const;
|
||||
private:
|
||||
virtual void PrintTo (std::ostream &os) const;
|
||||
virtual void SerializeTo (Buffer::Iterator start) const;
|
||||
virtual void DeserializeFrom (Buffer::Iterator start);
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
|
||||
uint16_t m_data;
|
||||
};
|
||||
|
||||
MyHeader::MyHeader ()
|
||||
{}
|
||||
MyHeader::~MyHeader ()
|
||||
{}
|
||||
void
|
||||
MyHeader::PrintTo (std::ostream &os) const
|
||||
{
|
||||
os << "MyHeader data=" << m_data << std::endl;
|
||||
}
|
||||
uint32_t
|
||||
MyHeader::GetSerializedSize (void) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
void
|
||||
MyHeader::SerializeTo (Buffer::Iterator start) const
|
||||
{
|
||||
// serialize in head of buffer
|
||||
start.WriteHtonU16 (m_data);
|
||||
}
|
||||
void
|
||||
MyHeader::DeserializeFrom (Buffer::Iterator start)
|
||||
{
|
||||
// deserialize from head of buffer
|
||||
m_data = start.ReadNtohU16 ();
|
||||
}
|
||||
|
||||
void
|
||||
MyHeader::SetData (uint16_t data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
uint16_t
|
||||
MyHeader::GetData (void) const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/* A sample Tag implementation
|
||||
*/
|
||||
struct MyTag {
|
||||
uint16_t m_streamId;
|
||||
};
|
||||
|
||||
static TagRegistration<struct MyTag> g_MyTagRegistration ("ns3::MyTag", 0);
|
||||
|
||||
|
||||
static void
|
||||
Receive (Packet p)
|
||||
{
|
||||
MyHeader my;
|
||||
p.Peek (my);
|
||||
p.Remove (my);
|
||||
std::cout << "received data=" << my.GetData () << std::endl;
|
||||
struct MyTag myTag;
|
||||
p.PeekTag (myTag);
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Packet p;
|
||||
MyHeader my;
|
||||
my.SetData (2);
|
||||
std::cout << "send data=2" << std::endl;
|
||||
p.Add (my);
|
||||
struct MyTag myTag;
|
||||
myTag.m_streamId = 5;
|
||||
p.AddTag (myTag);
|
||||
Receive (p);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "ns3/propagation-loss-model.h"
|
||||
#include "ns3/static-mobility-model.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/string.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
static void
|
||||
PrintOne (double minTxpower, double maxTxpower, double stepTxpower, double min, double max, double step)
|
||||
{
|
||||
Ptr<StaticMobilityModel> a = CreateObject<StaticMobilityModel> ();
|
||||
Ptr<StaticMobilityModel> b = CreateObject<StaticMobilityModel> ();
|
||||
Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
|
||||
log->SetReferenceModel (CreateObject<FriisPropagationLossModel> ());
|
||||
|
||||
Ptr<PropagationLossModel> model = log;
|
||||
|
||||
a->SetPosition (Vector (0.0, 0.0, 0.0));
|
||||
for (double x = min; x < max; x+= step)
|
||||
{
|
||||
b->SetPosition (Vector (x, 0.0, 0.0));
|
||||
std::cout << x << " ";
|
||||
for (double txpower = minTxpower; txpower < maxTxpower; txpower += stepTxpower)
|
||||
{
|
||||
double rxPowerDbm = txpower + model->GetLoss (a, b);
|
||||
std::cout << rxPowerDbm << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
|
||||
Config::SetGlobal ("LogDistancePropagationLossModel::ReferenceDistance", StringValue ("1.0"));
|
||||
Config::SetGlobal ("LogDistancePropagationLossModel::Exponent", StringValue ("4"));
|
||||
|
||||
PrintOne (-10, 20, 5, 0, 10000, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+8
-8
@@ -1,10 +1,11 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/object.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
class A
|
||||
class A : public Object
|
||||
{
|
||||
public:
|
||||
A ();
|
||||
@@ -48,7 +49,7 @@ int main (int argc, char *argv[])
|
||||
{
|
||||
// Create a new object of type A, store it in global
|
||||
// variable g_a
|
||||
Ptr<A> a = new A ();
|
||||
Ptr<A> a = CreateObject<A> ();
|
||||
a->Method ();
|
||||
Ptr<A> prev = StoreA (a);
|
||||
NS_ASSERT (prev == 0);
|
||||
@@ -57,18 +58,17 @@ int main (int argc, char *argv[])
|
||||
{
|
||||
// Create a new object of type A, store it in global
|
||||
// variable g_a, get a hold on the previous A object.
|
||||
Ptr<A> a = new A ();
|
||||
Ptr<A> a = CreateObject<A> ();
|
||||
Ptr<A> prev = StoreA (a);
|
||||
// call method on object
|
||||
prev->Method ();
|
||||
// Clear the currently-stored object
|
||||
ClearA ();
|
||||
// remove the raw pointer from its smart pointer.
|
||||
// we can do this because the refcount is exactly one
|
||||
// here
|
||||
A *raw = prev.Remove ();
|
||||
// get the raw pointer and release it.
|
||||
A *raw = GetPointer (prev);
|
||||
prev = 0;
|
||||
raw->Method ();
|
||||
delete raw;
|
||||
raw->Unref ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
static void
|
||||
CourseChange (std::string context, Ptr<const MobilityModel> position)
|
||||
{
|
||||
Vector pos = position->GetPosition ();
|
||||
std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y
|
||||
<< ", z=" << pos.z << std::endl;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
|
||||
NodeContainer c;
|
||||
c.Create (10000);
|
||||
|
||||
MobilityHelper mobility;
|
||||
mobility.SetPositionAllocator ("ns3::RandomDiscPositionAllocator",
|
||||
"X", StringValue ("100.0"),
|
||||
"Y", StringValue ("100.0"),
|
||||
"Rho", StringValue ("Uniform:0:30"));
|
||||
mobility.SetMobilityModel ("ns3::StaticMobilityModel");
|
||||
mobility.Install (c);
|
||||
|
||||
Config::Connect ("/NodeList/*/$ns3::MobilityModelNotifier/CourseChange",
|
||||
MakeCallback (&CourseChange));
|
||||
|
||||
Simulator::Stop (Seconds (100.0));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
static void
|
||||
CourseChange (std::string foo, Ptr<const MobilityModel> mobility)
|
||||
{
|
||||
Vector pos = mobility->GetPosition ();
|
||||
Vector vel = mobility->GetVelocity ();
|
||||
std::cout << Simulator::Now () << ", model=" << mobility << ", POS: x=" << pos.x << ", y=" << pos.y
|
||||
<< ", z=" << pos.z << "; VEL:" << vel.x << ", y=" << vel.y
|
||||
<< ", z=" << vel.z << std::endl;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Mode", StringValue ("Time"));
|
||||
Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Time", StringValue ("2s"));
|
||||
Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Speed", StringValue ("Constant:1.0"));
|
||||
Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Bounds", StringValue ("0|200|0|200"));
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
NodeContainer c;
|
||||
c.Create (100);
|
||||
|
||||
MobilityHelper mobility;
|
||||
mobility.SetPositionAllocator ("ns3::RandomDiscPositionAllocator",
|
||||
"X", StringValue ("100.0"),
|
||||
"Y", StringValue ("100.0"),
|
||||
"Rho", StringValue ("Uniform:0:30"));
|
||||
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
|
||||
"Mode", StringValue ("Time"),
|
||||
"Time", StringValue ("2s"),
|
||||
"Speed", StringValue ("Constant:1.0"),
|
||||
"Bounds", StringValue ("0|200|0|200"));
|
||||
mobility.InstallAll ();
|
||||
Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
|
||||
MakeCallback (&CourseChange));
|
||||
|
||||
Simulator::Stop (Seconds (100.0));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/datagram-socket.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/p2p-channel.h"
|
||||
#include "ns3/p2p-net-device.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/arp-ipv4-interface.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
|
||||
static void
|
||||
GenerateTraffic (DatagramSocket *socket, uint32_t size)
|
||||
{
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, tx bytes=" << size << std::endl;
|
||||
socket->SendDummy (size);
|
||||
if (size > 0)
|
||||
{
|
||||
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
|
||||
{
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << size << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
PrintTraffic (DatagramSocket *socket)
|
||||
{
|
||||
socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyP2PNetDevice (P2PNetDevice *dev)
|
||||
{
|
||||
delete dev;
|
||||
}
|
||||
|
||||
static void
|
||||
PrintRoutingTable (InternetNode *a, std::string name)
|
||||
{
|
||||
Ipv4 *ipv4 = a->GetIpv4 ();
|
||||
std::cout << "routing table start node=" << name << std::endl;
|
||||
for (uint32_t i = 0; i < ipv4->GetNRoutes (); i++)
|
||||
{
|
||||
Ipv4Route *route = ipv4->GetRoute (i);
|
||||
std::cout << (*route) << std::endl;
|
||||
}
|
||||
std::cout << "routing table end" << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
AddP2PLink (InternetNode *a, InternetNode *b)
|
||||
{
|
||||
P2PChannel * channel = new P2PChannel (MilliSeconds (20), 10000);
|
||||
P2PNetDevice *devA = channel->CreateNetDevice (a, MacAddress ("00:00:00:00:00:01"));
|
||||
P2PNetDevice *devB = channel->CreateNetDevice (b, MacAddress ("00:00:00:00:00:02"));
|
||||
Simulator::ScheduleDestroy (&DestroyP2PNetDevice, devA);
|
||||
Simulator::ScheduleDestroy (&DestroyP2PNetDevice, devB);
|
||||
Ipv4Interface *interfA = new ArpIpv4Interface (a, devA);
|
||||
Ipv4Interface *interfB = new ArpIpv4Interface (b, devB);
|
||||
uint32_t indexA = a->GetIpv4 ()->AddInterface (interfA);
|
||||
uint32_t indexB = b->GetIpv4 ()->AddInterface (interfB);
|
||||
Ipv4Address ipa = Ipv4Address ("192.168.0.2");
|
||||
Ipv4Address ipb = Ipv4Address ("192.168.0.3");
|
||||
Ipv4Mask netmask = Ipv4Mask ("255.255.255.0");
|
||||
a->GetIpv4 ()->AddHostRouteTo (ipb, indexA);
|
||||
b->GetIpv4 ()->AddHostRouteTo (ipa, indexB);
|
||||
|
||||
interfA->SetAddress (ipa);
|
||||
interfA->SetNetworkMask (netmask);
|
||||
interfA->SetUp ();
|
||||
|
||||
interfB->SetAddress (ipb);
|
||||
interfB->SetNetworkMask (netmask);
|
||||
interfB->SetUp ();
|
||||
|
||||
PrintRoutingTable (a, "a");
|
||||
PrintRoutingTable (b, "b");
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
|
||||
InternetNode *a = new InternetNode ();
|
||||
InternetNode *b = new InternetNode ();
|
||||
|
||||
AddP2PLink (a, b);
|
||||
|
||||
DatagramSocket *sink = new DatagramSocket (a);
|
||||
sink->Bind (80);
|
||||
DatagramSocket *source = new DatagramSocket (b);
|
||||
source->SetDefaultDestination (Ipv4Address ("192.168.0.2"), 80);
|
||||
|
||||
GenerateTraffic (source, 500);
|
||||
PrintTraffic (sink);
|
||||
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
|
||||
delete a;
|
||||
delete source;
|
||||
delete sink;
|
||||
|
||||
return 0;
|
||||
}
|
||||
+37
-45
@@ -1,69 +1,61 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/datagram-socket.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
static void TestOne (void)
|
||||
{
|
||||
InternetNode *a = new InternetNode ();
|
||||
|
||||
delete a;
|
||||
}
|
||||
|
||||
static void TestTwo (void)
|
||||
{
|
||||
InternetNode a = InternetNode ();
|
||||
|
||||
InternetNode *b = a.Copy ();
|
||||
|
||||
delete b;
|
||||
}
|
||||
|
||||
static void
|
||||
SmallTests (void)
|
||||
{
|
||||
TestOne ();
|
||||
TestTwo ();
|
||||
}
|
||||
|
||||
static void
|
||||
GenerateTraffic (DatagramSocket *socket, uint32_t size)
|
||||
GenerateTraffic (Ptr<Socket> socket, uint32_t size)
|
||||
{
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, tx bytes=" << size << std::endl;
|
||||
socket->SendDummy (size);
|
||||
socket->Send (Create<Packet> (size));
|
||||
if (size > 0)
|
||||
{
|
||||
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
|
||||
}
|
||||
else
|
||||
{
|
||||
socket->Close ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
|
||||
SocketPrinter (Ptr<Socket> socket)
|
||||
{
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << size << std::endl;
|
||||
Ptr<Packet> packet;
|
||||
while (packet = socket->Recv ())
|
||||
{
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet->GetSize () << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintTraffic (DatagramSocket *socket)
|
||||
PrintTraffic (Ptr<Socket> socket)
|
||||
{
|
||||
socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
|
||||
socket->SetRecvCallback (MakeCallback (&SocketPrinter));
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
void
|
||||
RunSimulation (void)
|
||||
{
|
||||
SmallTests ();
|
||||
NodeContainer c;
|
||||
c.Create (1);
|
||||
|
||||
InternetNode *a = new InternetNode ();
|
||||
|
||||
DatagramSocket *sink = new DatagramSocket (a);
|
||||
sink->Bind (80);
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
|
||||
DatagramSocket *source = new DatagramSocket (a);
|
||||
source->SetDefaultDestination (Ipv4Address::GetLoopback (), 80);
|
||||
|
||||
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
|
||||
Ptr<Socket> sink = Socket::CreateSocket (c.Get (0), tid);
|
||||
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
|
||||
sink->Bind (local);
|
||||
|
||||
Ptr<Socket> source = Socket::CreateSocket (c.Get (0), tid);
|
||||
InetSocketAddress remote = InetSocketAddress (Ipv4Address::GetLoopback (), 80);
|
||||
source->Connect (remote);
|
||||
|
||||
GenerateTraffic (source, 500);
|
||||
PrintTraffic (sink);
|
||||
@@ -72,11 +64,11 @@ int main (int argc, char *argv[])
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
|
||||
delete a;
|
||||
delete source;
|
||||
delete sink;
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
RunSimulation ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 University of Washington
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -18,14 +17,14 @@
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "ns3/debug.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/trace-writer.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
NS_DEBUG_UNCOND("TraceWriter Test")
|
||||
NS_LOG_UNCOND("TraceWriter Test")
|
||||
|
||||
TraceWriter writer1;
|
||||
writer1.Open("trace-writer-test.txt");
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../waf "$@"
|
||||
@@ -0,0 +1,42 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_program('main-attribute-value')
|
||||
obj.source = 'main-attribute-value.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-callback')
|
||||
obj.source = 'main-callback.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-simulator')
|
||||
obj.source = 'main-simulator.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-packet-header', ['common', 'simulator'])
|
||||
obj.source = 'main-packet-header.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-packet-tag', ['common', 'simulator'])
|
||||
obj.source = 'main-packet-tag.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-test')
|
||||
obj.source = 'main-test.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-simple',
|
||||
['node', 'internet-node', 'onoff'])
|
||||
obj.source = 'main-simple.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-grid-topology',
|
||||
['core', 'simulator', 'mobility', 'internet-node'])
|
||||
obj.source = 'main-grid-topology.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-random-topology',
|
||||
['core', 'simulator', 'mobility'])
|
||||
obj.source = 'main-random-topology.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-random-walk',
|
||||
['core', 'simulator', 'mobility'])
|
||||
obj.source = 'main-random-walk.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-propagation-loss',
|
||||
['core', 'simulator', 'mobility', 'wifi'])
|
||||
obj.source = 'main-propagation-loss.cc'
|
||||
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
//
|
||||
// Copyright (c) 2006 Georgia Tech Research Corporation
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation;
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// Author: George F. Riley<riley@ece.gatech.edu>
|
||||
//
|
||||
|
||||
// ns3 - On/Off Data Source Application class
|
||||
// George F. Riley, Georgia Tech, Spring 2007
|
||||
// Adapted from ApplicationOnOff in GTNetS.
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "onoff-application.h"
|
||||
#include "ns3/udp-socket-factory.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("OnOffApplication");
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (OnOffApplication);
|
||||
|
||||
TypeId
|
||||
OnOffApplication::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::OnOffApplication")
|
||||
.SetParent<Application> ()
|
||||
.AddConstructor<OnOffApplication> ()
|
||||
.AddAttribute ("DataRate", "The data rate in on state.",
|
||||
DataRateValue (DataRate ("500kb/s")),
|
||||
MakeDataRateAccessor (&OnOffApplication::m_cbrRate),
|
||||
MakeDataRateChecker ())
|
||||
.AddAttribute ("PacketSize", "The size of packets sent in on state",
|
||||
UintegerValue (512),
|
||||
MakeUintegerAccessor (&OnOffApplication::m_pktSize),
|
||||
MakeUintegerChecker<uint32_t> (1))
|
||||
.AddAttribute ("Remote", "The address of the destination",
|
||||
AddressValue (),
|
||||
MakeAddressAccessor (&OnOffApplication::m_peer),
|
||||
MakeAddressChecker ())
|
||||
.AddAttribute ("OnTime", "A RandomVariable used to pick the duration of the 'On' state.",
|
||||
RandomVariableValue (ConstantVariable (1.0)),
|
||||
MakeRandomVariableAccessor (&OnOffApplication::m_onTime),
|
||||
MakeRandomVariableChecker ())
|
||||
.AddAttribute ("OffTime", "A RandomVariable used to pick the duration of the 'Off' state.",
|
||||
RandomVariableValue (ConstantVariable (1.0)),
|
||||
MakeRandomVariableAccessor (&OnOffApplication::m_offTime),
|
||||
MakeRandomVariableChecker ())
|
||||
.AddAttribute ("MaxBytes",
|
||||
"The total number of bytes to send. Once these bytes are sent, "
|
||||
"no packet is sent again, even in on state. The value zero means "
|
||||
"that there is no limit.",
|
||||
UintegerValue (0),
|
||||
MakeUintegerAccessor (&OnOffApplication::m_maxBytes),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("Protocol", "The type of protocol to use.",
|
||||
TypeIdValue (UdpSocketFactory::GetTypeId ()),
|
||||
MakeTypeIdAccessor (&OnOffApplication::m_tid),
|
||||
MakeTypeIdChecker ())
|
||||
.AddTraceSource ("Tx", "A new packet is created and is sent",
|
||||
MakeTraceSourceAccessor (&OnOffApplication::m_txTrace))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
OnOffApplication::OnOffApplication ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
m_socket = 0;
|
||||
m_connected = false;
|
||||
m_residualBits = 0;
|
||||
m_lastStartTime = Seconds (0);
|
||||
m_totBytes = 0;
|
||||
}
|
||||
|
||||
OnOffApplication::~OnOffApplication()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
}
|
||||
|
||||
void
|
||||
OnOffApplication::SetMaxBytes(uint32_t maxBytes)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << maxBytes);
|
||||
m_maxBytes = maxBytes;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OnOffApplication::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
m_socket = 0;
|
||||
// chain up
|
||||
Application::DoDispose ();
|
||||
}
|
||||
|
||||
// Application Methods
|
||||
void OnOffApplication::StartApplication() // Called at time specified by Start
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
// Create the socket if not already
|
||||
if (!m_socket)
|
||||
{
|
||||
m_socket = Socket::CreateSocket (GetNode(), m_tid);
|
||||
m_socket->Bind ();
|
||||
m_socket->Connect (m_peer);
|
||||
}
|
||||
// Insure no pending event
|
||||
StopApplication();
|
||||
// If we are not yet connected, there is nothing to do here
|
||||
// The ConnectionComplete upcall will start timers at that time
|
||||
//if (!m_connected) return;
|
||||
ScheduleStartEvent();
|
||||
}
|
||||
|
||||
void OnOffApplication::StopApplication() // Called at time specified by Stop
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
if (m_sendEvent.IsRunning ())
|
||||
{ // Cancel the pending send packet event
|
||||
// Calculate residual bits since last packet sent
|
||||
Time delta(Simulator::Now() - m_lastStartTime);
|
||||
m_residualBits += (uint32_t)(m_cbrRate.GetBitRate() * delta.GetSeconds());
|
||||
}
|
||||
Simulator::Cancel(m_sendEvent);
|
||||
Simulator::Cancel(m_startStopEvent);
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
void OnOffApplication::StartSending()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
ScheduleNextTx(); // Schedule the send packet event
|
||||
}
|
||||
|
||||
void OnOffApplication::StopSending()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
Simulator::Cancel(m_sendEvent);
|
||||
}
|
||||
|
||||
// Private helpers
|
||||
void OnOffApplication::ScheduleNextTx()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
if (m_maxBytes == 0 || m_totBytes < m_maxBytes)
|
||||
{
|
||||
uint32_t bits = m_pktSize * 8 - m_residualBits;
|
||||
NS_LOG_LOGIC ("bits = " << bits);
|
||||
Time nextTime(Seconds (bits /
|
||||
static_cast<double>(m_cbrRate.GetBitRate()))); // Time till next packet
|
||||
NS_LOG_LOGIC ("nextTime = " << nextTime);
|
||||
m_sendEvent = Simulator::Schedule(nextTime,
|
||||
&OnOffApplication::SendPacket, this);
|
||||
}
|
||||
else
|
||||
{ // All done, cancel any pending events
|
||||
StopApplication();
|
||||
}
|
||||
}
|
||||
|
||||
void OnOffApplication::ScheduleStartEvent()
|
||||
{ // Schedules the event to start sending data (switch to the "On" state)
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
Time offInterval = Seconds(m_offTime.GetValue());
|
||||
NS_LOG_LOGIC ("start at " << offInterval);
|
||||
m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this);
|
||||
}
|
||||
|
||||
void OnOffApplication::ScheduleStopEvent()
|
||||
{ // Schedules the event to stop sending data (switch to "Off" state)
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
Time onInterval = Seconds(m_onTime.GetValue());
|
||||
NS_LOG_LOGIC ("stop at " << onInterval);
|
||||
Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this);
|
||||
}
|
||||
|
||||
|
||||
void OnOffApplication::SendPacket()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
NS_LOG_LOGIC ("sending packet at " << Simulator::Now());
|
||||
NS_ASSERT (m_sendEvent.IsExpired ());
|
||||
Ptr<Packet> packet = Create<Packet> (m_pktSize);
|
||||
m_txTrace (packet);
|
||||
m_socket->Send (packet);
|
||||
m_totBytes += m_pktSize;
|
||||
m_lastStartTime = Simulator::Now();
|
||||
m_residualBits = 0;
|
||||
ScheduleNextTx();
|
||||
}
|
||||
|
||||
void OnOffApplication::ConnectionSucceeded(Ptr<Socket>)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
m_connected = true;
|
||||
ScheduleStartEvent();
|
||||
}
|
||||
|
||||
void OnOffApplication::ConnectionFailed(Ptr<Socket>)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
cout << "OnOffApplication, Connection Failed" << endl;
|
||||
}
|
||||
|
||||
} // Namespace ns3
|
||||
@@ -22,83 +22,89 @@
|
||||
// George F. Riley, Georgia Tech, Spring 2007
|
||||
// Adapted from ApplicationOnOff in GTNetS.
|
||||
|
||||
// Define an on/off data source application class
|
||||
|
||||
#ifndef __onoff_application_h__
|
||||
#define __onoff_application_h__
|
||||
|
||||
#include "application.h"
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/application.h"
|
||||
#include "ns3/event-id.h"
|
||||
|
||||
#define nil 0
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Ipv4Address;
|
||||
class Address;
|
||||
class RandomVariable;
|
||||
class DatagramSocket;
|
||||
class DataRate;
|
||||
|
||||
class OnOffApplication : public Application {
|
||||
class Socket;
|
||||
|
||||
/**
|
||||
* \brief Generate traffic to a single destination according to an
|
||||
* OnOff pattern.
|
||||
*
|
||||
* This traffic follows an On/Off pattern: after Application::StartApplication
|
||||
* is called, "On" and "Off" states alternate. The duration of each of
|
||||
* these states is determined with the onTime and the offTime random
|
||||
* variables. During the "Off" state, no traffic is generated.
|
||||
* During the "On" state, cbr traffic is generated. This cbr traffic is
|
||||
* characterized by the specified "data rate" and "packet size".
|
||||
*/
|
||||
class OnOffApplication : public Application
|
||||
{
|
||||
public:
|
||||
OnOffApplication(const Node& n,
|
||||
const Ipv4Address, // Peer IP address
|
||||
uint16_t, // Peer port
|
||||
const RandomVariable&, // Random variable for On time
|
||||
const RandomVariable&, // Random variable for Off time
|
||||
DataRate = g_defaultRate, // Data rate when on
|
||||
uint32_t = g_defaultSize); // Size of packets
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
OnOffApplication ();
|
||||
|
||||
virtual ~OnOffApplication();
|
||||
|
||||
void SetMaxBytes(uint32_t maxBytes);
|
||||
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
private:
|
||||
// inherited from Application base class.
|
||||
virtual void StartApplication (void); // Called at time specified by Start
|
||||
virtual void StopApplication (void); // Called at time specified by Stop
|
||||
|
||||
void Construct (Ptr<Node> n,
|
||||
const Address &remote,
|
||||
std::string tid,
|
||||
const RandomVariable& ontime,
|
||||
const RandomVariable& offtime,
|
||||
uint32_t size);
|
||||
|
||||
OnOffApplication(const Node& n, const OnOffApplication&); // Copy constructor
|
||||
virtual ~OnOffApplication(); // Destructor
|
||||
virtual void StartApplication(); // Called at time specified by Start
|
||||
virtual void StopApplication(); // Called at time specified by Stop
|
||||
virtual OnOffApplication* Copy() const;// Make a copy of the application
|
||||
|
||||
// Event handlers
|
||||
void StartSending();
|
||||
void StopSending();
|
||||
void SendPacket();
|
||||
|
||||
virtual void MaxBytes(uint32_t m) { m_maxBytes = m;}
|
||||
|
||||
public: // Static methods
|
||||
static void DefaultRate(uint64_t r) { g_defaultRate = r;}
|
||||
|
||||
static void DefaultSize(uint32_t s) { g_defaultSize = s;}
|
||||
|
||||
public:
|
||||
DatagramSocket* m_socket; // Associated socket
|
||||
Ipv4Address m_peerIP; // Peer IP address
|
||||
uint16_t m_peerPort; // Peer port
|
||||
Ptr<Socket> m_socket; // Associated socket
|
||||
Address m_peer; // Peer address
|
||||
bool m_connected; // True if connected
|
||||
RandomVariable* m_onTime; // rng for On Time
|
||||
RandomVariable* m_offTime; // rng for Off Time
|
||||
RandomVariable m_onTime; // rng for On Time
|
||||
RandomVariable m_offTime; // rng for Off Time
|
||||
DataRate m_cbrRate; // Rate that data is generated
|
||||
uint32_t m_pktSize; // Size of packets
|
||||
uint32_t m_residualBits; // Number of generated, but not sent, bits
|
||||
Time m_lastStartTime;// Time last packet sent
|
||||
uint32_t m_maxBytes; // Limit total number of bytes sent
|
||||
uint32_t m_totBytes; // Total bytes sent so far
|
||||
bool m_startStopScheduled; // True if start or stop event scheduled
|
||||
EventId m_startStopEvent; // Event id for next start or stop event
|
||||
bool m_sendScheduled;// True of send event scheduled
|
||||
EventId m_sendEvent; // Eventid of pending "send packet" event
|
||||
bool m_sending; // True if currently in sending state
|
||||
TypeId m_tid;
|
||||
TracedCallback<Ptr<const Packet> > m_txTrace;
|
||||
|
||||
public:
|
||||
static DataRate g_defaultRate; // Default sending rate when on
|
||||
static uint32_t g_defaultSize; // Default packet size
|
||||
|
||||
private:
|
||||
void ScheduleNextTx();
|
||||
void ScheduleStartEvent();
|
||||
void ScheduleStopEvent();
|
||||
void ConnectionSucceeded(DatagramSocket*);
|
||||
void ConnectionFailed(DatagramSocket*);
|
||||
void Ignore(DatagramSocket*);
|
||||
protected:
|
||||
void ConnectionSucceeded(Ptr<Socket>);
|
||||
void ConnectionFailed(Ptr<Socket>);
|
||||
void Ignore(Ptr<Socket>);
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
+1
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../../../waf "$@"
|
||||
@@ -0,0 +1,13 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
module = bld.create_ns3_module('onoff', ['core', 'simulator', 'node'])
|
||||
module.source = [
|
||||
'onoff-application.cc',
|
||||
]
|
||||
headers = bld.create_obj('ns3header')
|
||||
headers.module = 'onoff'
|
||||
headers.source = [
|
||||
'onoff-application.h',
|
||||
]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user