Compare commits
824 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e70c7ac38 | |||
| bf0d4e7154 | |||
| e8fc6ec946 | |||
| be2b52ac8f | |||
| 7bb06e0661 | |||
| b56cad3cbc | |||
| 5bec43f720 | |||
| ee5f2a5475 | |||
| 2806d0edbe | |||
| 85cbeccd3e | |||
| 147510bb00 | |||
| cdc9002e41 | |||
| f8ae534480 | |||
| c6f3793178 | |||
| 96451fdb37 | |||
| feb47b3bb1 | |||
| 4f02439cb1 | |||
| a14e1de6cc | |||
| a30e3a7e94 | |||
| 450f9db5c6 | |||
| eca7dc5b27 | |||
| b4c23f8ebf | |||
| dd8985b92d | |||
| 9fcd20505c | |||
| a142d30a9d | |||
| c3658bd810 | |||
| 6e7d9062cb | |||
| a6438d91b4 | |||
| d2d16360c1 | |||
| 3b277785c0 | |||
| c3719a2eca | |||
| 3b58cf8c0e | |||
| b390f1ef73 | |||
| 02fd903228 | |||
| 52ca0dd3f6 | |||
| 6a874b283c | |||
| fd238f3e40 | |||
| 438036550f | |||
| a0e14bd523 | |||
| c8a76b7dd5 | |||
| c86c3ce16d | |||
| dd48772c9e | |||
| 53833582b7 | |||
| f262b76a41 | |||
| 441e17174d | |||
| defd58bc77 | |||
| 38f2897c29 | |||
| d9d019c5d4 | |||
| f23152d7a7 | |||
| d625837eb9 | |||
| cecd35e20b | |||
| 5ade799440 | |||
| 2786b195ee | |||
| 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 | |||
| 013a31afdb | |||
| d09deab2f1 | |||
| 3e77a6301d | |||
| 92313a2d64 | |||
| 4a6e5ee331 | |||
| a08faa038f | |||
| 42189e5c52 | |||
| 4a6a601b5a | |||
| 5631c4d214 | |||
| 6be5ea55ce | |||
| 4bf8491d01 | |||
| a62ac4df3a | |||
| 9a7206b971 | |||
| e23f26a8f3 | |||
| 93ad9161ec | |||
| 222eea66fa | |||
| 072626d390 | |||
| e4dedb226f | |||
| acde0b6311 | |||
| 8cb57d43d6 | |||
| f597f96152 | |||
| 0f5b5f1f6c | |||
| ea0a9ae7ab | |||
| 98abf1d812 | |||
| 5b558714de | |||
| 00e998e5f9 | |||
| 0467d48201 | |||
| e85f337b2f | |||
| a7d36f9f9f | |||
| e6ef4109c8 | |||
| fc7b62e329 | |||
| 3cfda55a69 | |||
| d6cb167a0c | |||
| 1177dc94b8 | |||
| a7089873e9 | |||
| c2c7f7d71c | |||
| c2c923ba11 | |||
| e45d934cb6 | |||
| 48cf146a6f | |||
| ccd6240e23 | |||
| d3ec8f8791 | |||
| 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 | |||
| 1ac757bd60 | |||
| 9c46074145 | |||
| 2ad239b6c9 | |||
| 9bc8eb952b | |||
| 83cbc1f450 | |||
| 5ef0970789 | |||
| 41920cc74f | |||
| bda63626d2 | |||
| d0d364d729 | |||
| e896c2576b | |||
| 88b0af83b5 | |||
| 5e3d0126e3 | |||
| aef4192d6a | |||
| a85bcfc0d7 | |||
| 5cc787f648 | |||
| a011792fb6 | |||
| 2bd88ed300 | |||
| bd234eafe3 | |||
| 0405be5bb0 | |||
| c40b0f6f63 | |||
| b10c76a3a6 | |||
| 683b301fb7 | |||
| ba0f81e65c | |||
| 204352ca8b | |||
| 8b07f89d13 | |||
| 2f01154847 | |||
| 24458b4bf1 | |||
| b9c2580f22 | |||
| be946aab50 | |||
| 2aca908685 | |||
| 99ec33418a | |||
| c416887542 | |||
| dd0ff29f66 | |||
| 3e22f47624 | |||
| bda20507bd | |||
| 9111697a0b | |||
| f27587f391 | |||
| ce6536c1d8 | |||
| c0420dfa2a | |||
| 0c77aa5a69 | |||
| 96698c5783 | |||
| 038bc809cb | |||
| 71d559e1f2 | |||
| 184d929521 | |||
| 5e975db36e | |||
| 9a89cf1978 | |||
| 94c1f03300 | |||
| 872df4e54e | |||
| 5fdde955b3 | |||
| 3f87b85886 | |||
| af6777397c | |||
| 2f29b73496 | |||
| c14499b211 | |||
| 57b5993f8d | |||
| 2f8fdae0db | |||
| e57869a38e | |||
| e4d291802b | |||
| 77eb4ec65a | |||
| d27798e797 | |||
| fca6b52fba | |||
| 04ebac2279 | |||
| fb968dccdf | |||
| 1271ada6e1 | |||
| 7a86a8a8e7 | |||
| e9ee638ae9 | |||
| 965e14c3f9 | |||
| a2ca638f47 | |||
| 0197e59eb1 | |||
| 418adb52a4 | |||
| 8894524474 | |||
| 6ec6318d5f |
@@ -8,3 +8,4 @@
|
||||
^doc/latex
|
||||
^\.lock-wscript
|
||||
^\.waf
|
||||
^doc/introspected-doxygen\.h$
|
||||
|
||||
@@ -5,3 +5,8 @@
|
||||
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
|
||||
|
||||
@@ -2,6 +2,7 @@ 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)
|
||||
George F. Riley (riley@ece.gatech.edu)
|
||||
|
||||
@@ -84,12 +84,12 @@ following set of platforms:
|
||||
- linux x86 gcc 4.2, 4.1, and, 3.4.
|
||||
- linux x86_64 gcc 4.0
|
||||
- MacOS X ppc and x86
|
||||
- cygwin
|
||||
|
||||
The current codebase is expected to fail to build on
|
||||
the following platforms:
|
||||
- gcc 3.3 and earlier
|
||||
- optimized builds on linux x86 gcc 4.0
|
||||
- cygwin
|
||||
|
||||
Other platforms may or may not work: we welcome
|
||||
patches to improve the portability of the code to these
|
||||
@@ -102,17 +102,17 @@ 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-p2p
|
||||
./waf --run simple-point-to-point
|
||||
|
||||
That program should generate a simple-p2p.tr text
|
||||
trace file and a set of simple-p2p-xx-xx.pcap binary
|
||||
That program should generate a simple-point-to-point.tr text
|
||||
trace file and a set of simple-point-to-point-xx-xx.pcap binary
|
||||
pcap trace files, which can be read by tcpdump.
|
||||
|
||||
5) Getting access to the ns-3 documentation
|
||||
-------------------------------------------
|
||||
|
||||
Once you have verified that your build of ns-3 works by running
|
||||
the simple-p2p example as outlined in 4) above, it is
|
||||
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.
|
||||
|
||||
|
||||
@@ -3,6 +3,48 @@
|
||||
|
||||
This file contains ns-3 release notes (most recent releases first).
|
||||
|
||||
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
|
||||
|
||||
+18
-35
@@ -3,79 +3,62 @@ build system (http://www.freehackers.org/~tnagy/waf.html)
|
||||
|
||||
=== Installing Waf ===
|
||||
|
||||
If this file is part of a development release tarball, the top-level
|
||||
ns-3 directory should contain a current waf script.
|
||||
|
||||
However, the ns-3 Mercurial code repository does not contain the waf
|
||||
script. Instead, developers should check it out from a subversion
|
||||
repository:
|
||||
|
||||
svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf
|
||||
|
||||
[ note: 'tags/ns3' is a tag that represents the last svn version
|
||||
tested to work correctly with ns3, although 'trunk' will likely work
|
||||
as well ]
|
||||
|
||||
Then it can be installed system-wide with 'sudo waf-light install'.
|
||||
When preparing a distribution, the resulting 'waf' script, which is
|
||||
self contained (no external files needed), can be easily included in
|
||||
the tarball so that users downloading ns-3 can easily build it without
|
||||
having Waf installed (although Python >= 2.3 is still needed).
|
||||
The top-level ns-3 directory should contain a current waf script.
|
||||
|
||||
=== Building with Waf ===
|
||||
|
||||
To build ns-3 with waf type the commands:
|
||||
1. waf configure [options]
|
||||
2. 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
|
||||
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: ultradebug, debug, release, and optimized. It is
|
||||
waf --help) are: "debug" or "optimized". It is
|
||||
also possible to change the flags used for compilation with (e.g.):
|
||||
CXXFLAGS="-O3" waf configure.
|
||||
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 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
|
||||
1. ./waf check
|
||||
Runs the unit tests
|
||||
|
||||
2. waf --doxygen
|
||||
2. ./waf --doxygen
|
||||
Run doxygen to generate documentation
|
||||
|
||||
3. waf --lcov-report
|
||||
3. ./waf --lcov-report
|
||||
Run code coverage analysis (assuming the project was configured
|
||||
with --enable-gcov)
|
||||
|
||||
4. waf --run "program [args]"
|
||||
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 ..."
|
||||
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"
|
||||
./waf --run run-tests --command-template "valgrind %s"
|
||||
|
||||
5. waf --shell
|
||||
5. ./waf --shell
|
||||
Starts a nested system shell with modified environment to run ns3 programs.
|
||||
|
||||
6. waf distclean
|
||||
6. ./waf distclean
|
||||
Cleans out the entire build/ directory
|
||||
|
||||
7. waf dist
|
||||
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 ~).
|
||||
|
||||
+154
-62
@@ -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.
|
||||
@@ -186,7 +185,7 @@ TAB_SIZE = 4
|
||||
# will result in a user-defined paragraph with heading "Side Effects:".
|
||||
# You can put \n's in the value part of an alias to insert newlines.
|
||||
|
||||
ALIASES =
|
||||
ALIASES = valueref{1}="\ref DefaultValue\1 \"\1\""
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
|
||||
# sources only. Doxygen will then generate output that is more tailored for C.
|
||||
@@ -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,29 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = src doc/main.txt doc/trace-source-list.h doc/tracing.h
|
||||
INPUT = doc/modules \
|
||||
doc/main.h \
|
||||
doc/introspected-doxygen.h \
|
||||
doc/tracing.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 +527,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 +548,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).
|
||||
@@ -548,7 +613,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 +642,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 +741,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
|
||||
@@ -969,7 +1051,7 @@ MACRO_EXPANSION = NO
|
||||
|
||||
# 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
|
||||
|
||||
@@ -999,7 +1081,9 @@ INCLUDE_FILE_PATTERNS =
|
||||
# undefined via #undef or recursively expanded use the := operator
|
||||
# instead of the = operator.
|
||||
|
||||
PREDEFINED = RUN_SELF_TESTS NS3_DEBUG_ENABLE NS3_ASSERT_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.
|
||||
@@ -1072,6 +1156,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 +1221,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 +1229,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 +1266,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,68 +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. 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
|
||||
*
|
||||
* 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 debugging, \ref assert, \ref error
|
||||
* - \ref randomvariable
|
||||
* - \ref config
|
||||
* - a base class for objects which need to support reference counting
|
||||
* and QueryInterface: ns3::Object and ns3::InterfaceId
|
||||
* - a set of low-level trace facilities integrated in the ns3::Object system: \ref tracing
|
||||
* - a ns3::ComponentManager which can be used to manage the creation
|
||||
* of any object which derives from ns3::Object through an ns3::ClassId
|
||||
* - a smart-pointer class ns3::Ptr designed to work together with ns3::Object
|
||||
*
|
||||
* 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 "core" 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.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @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 error
|
||||
* - \ref randomvariable
|
||||
* - \ref config
|
||||
* - a base class for objects which need to support reference counting
|
||||
* and QueryInterface: ns3::Object and ns3::InterfaceId
|
||||
* - a set of low-level trace facilities integrated in the ns3::Object system: \ref tracing
|
||||
* - a ns3::ComponentManager which can be used to manage the creation
|
||||
* of any object which derives from ns3::Object through an ns3::ClassId
|
||||
* - a smart-pointer class ns3::Ptr designed to work together with ns3::Object
|
||||
*
|
||||
* @defgroup common Common
|
||||
* The "core" 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
|
||||
* The "devices" module contains:
|
||||
* - a PointToPoint MAC device: ns3::PointToPointNetDevice, ns3::PointToPointChannel,
|
||||
* and ns3::PointToPointTopology.
|
||||
*
|
||||
* @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 applications Applications
|
||||
*
|
||||
* @defgroup mobility Mobility
|
||||
*
|
||||
* @defgroup routing Routing
|
||||
*
|
||||
* @defgroup constants Constants
|
||||
* @brief Constants you can change
|
||||
*
|
||||
* @defgroup contrib Contrib
|
||||
*/
|
||||
|
||||
+26
-15
@@ -1,24 +1,35 @@
|
||||
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
|
||||
2. make a new "architecture.pdf" document and place it in the doc/ directory
|
||||
3. cd ns-3-dev; ./waf configure; ./waf dist
|
||||
4. test tarball on release platforms (waf check and maybe some other scripts)
|
||||
5. tag ns-3-dev with "release ns-3.0.X"
|
||||
- hg tag "release ns-3.0.x"
|
||||
- hg push
|
||||
6. clone the tagged ns-3-dev and place it on the repository
|
||||
- ssh code.nsnam.org; sudo; 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
|
||||
7. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server
|
||||
8. update web page
|
||||
- confirm that Doxygen builds cleanly and without warnings
|
||||
(./waf --doxygen), and check in any necessary changes
|
||||
2. ./waf configure; ./waf dist
|
||||
- this will create a ns-3.0.x.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; 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. upload "ns-3.0.x.tar.bz2" to the /var/www/html/releases/ directory on
|
||||
the www.nsnam.org server
|
||||
- give it 600 permissions, and user/group = apache
|
||||
8. update web pages on www.nsnam.org (source is in the www/ module)
|
||||
- add link to news.html
|
||||
- update download.html
|
||||
- update roadmap.html
|
||||
- update getting_started.html
|
||||
- update documents.html
|
||||
- update roadmap on wiki
|
||||
- build and update Doxygen directory on the server
|
||||
- update and upload software architecture document (PDF, HTML)
|
||||
-- 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
|
||||
9. announce to ns-developers, with summary of release notes
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief send ipv4 packet to outgoing interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet sent.
|
||||
/// \param arg3 index of output ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/ipv4/tx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback0 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive ipv4 packet from incoming interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
/// \param arg3 index of input ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/ipv4/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback1 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop ipv4 packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/ipv4/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback2 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief store packet in queue
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet queued.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/enqueue.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::QueueTraceType
|
||||
void TraceSinkCallback3 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief remove packet from queue
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dequeued.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/dequeue.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::QueueTraceType
|
||||
void TraceSinkCallback4 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop packet from queue
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/queue/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::QueueTraceType
|
||||
void TraceSinkCallback5 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive MAC packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::PointToPointTraceType
|
||||
void TraceSinkCallback6 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive MAC packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::CsmaTraceType
|
||||
void TraceSinkCallback7 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop MAC packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/devices/[0-n]/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::NodeNetDeviceIndex
|
||||
/// - ns3::CsmaTraceType
|
||||
void TraceSinkCallback8 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief The value of the speed vector changed
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 the mobility model whose course changed.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$MobilityModelNotifier/course-change.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
void TraceSinkCallback9 (const TraceContext & arg1, Ptr<const MobilityModel> arg2);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief send ipv4 packet to outgoing interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet sent.
|
||||
/// \param arg3 index of output ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/tx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback10 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief receive ipv4 packet from incoming interface
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet received.
|
||||
/// \param arg3 index of input ipv4 interface.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/rx.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback11 (const TraceContext & arg1, const Packet & arg2, uint32_t arg3);
|
||||
|
||||
///
|
||||
/// \ingroup TraceSourceList
|
||||
/// \brief drop ipv4 packet
|
||||
/// \param arg1 the trace context associated to the connected trace source.
|
||||
/// \param arg2 packet dropped.
|
||||
///
|
||||
///
|
||||
/// The path to this trace source is: /nodes/[0-n]/$Ipv4L3Protocol/drop.
|
||||
///
|
||||
/// The following classes can be extracted from \p arg1 with
|
||||
/// ns3::TraceContext::GetElement:
|
||||
/// - ns3::NodeListIndex
|
||||
/// - ns3::Ipv4L3ProtocolTraceContextElement
|
||||
void TraceSinkCallback12 (const TraceContext & arg1, const Packet & arg2);
|
||||
|
||||
+47
-39
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* \ingroup core
|
||||
* \defgroup TraceSourceList List of trace sources
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \defgroup tracing Tracing
|
||||
*
|
||||
* The flexibility of the ns-3 tracing system comes at the cost of quite
|
||||
@@ -55,7 +57,7 @@
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void DoSomething (Packet packet)
|
||||
* void DoSomething (Ptr<Packet> packet)
|
||||
* {
|
||||
* // report this event on packet
|
||||
* m_doSomething (packet);
|
||||
@@ -63,7 +65,7 @@
|
||||
* }
|
||||
* private:
|
||||
* // report every "something" function call.
|
||||
* CallbackTraceSource<Packet> m_doSomething;
|
||||
* CallbackTraceSource<Ptr<Packet> > m_doSomething;
|
||||
* };
|
||||
* \endcode
|
||||
* Every type of trace source derives from the ns3::TraceSource base class.
|
||||
@@ -86,10 +88,10 @@
|
||||
* std::cout << "cwnd=" << newValue << std::endl;
|
||||
* }
|
||||
* void
|
||||
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
|
||||
* DoSomethingTraceSink (const TraceContext &context, Ptr<Packet> packet)
|
||||
* {
|
||||
* // for example, print the arguments
|
||||
* std::cout << "packet " << packet << std::endl;
|
||||
* // for example, print the packet
|
||||
* std::cout << "packet " << packet->Print () << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
* Each of these sink function takes, as a first argument, a reference to a
|
||||
@@ -121,19 +123,19 @@
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void DoSomething (Packet packet)
|
||||
* void DoSomething (Ptr<Packet> packet)
|
||||
* {
|
||||
* // report this event on packet
|
||||
* m_doSomething (packet);
|
||||
* // do something
|
||||
* }
|
||||
* CallbackTraceSource<Packet> *PeekSomethingTraceSource (void) const
|
||||
* CallbackTraceSource<Ptr<Packet>> *PeekSomethingTraceSource (void) const
|
||||
* {
|
||||
* return &m_doSomething
|
||||
* }
|
||||
* private:
|
||||
* // report every "something" function call.
|
||||
* CallbackTraceSource<Packet> m_doSomething;
|
||||
* CallbackTraceSource<Ptr<Packet>> m_doSomething;
|
||||
* };
|
||||
* \endcode
|
||||
* If your users hold a pointer to an instance of MyModel, and if they want to connect
|
||||
@@ -142,12 +144,12 @@
|
||||
* sink with the MakeCallback function.
|
||||
* \code
|
||||
* void
|
||||
* MySomethingSink (const TraceContext &context, Packet packet)
|
||||
* MySomethingSink (const TraceContext &context, Ptr<Packet> packet)
|
||||
* {
|
||||
* // do whatever you want.
|
||||
* }
|
||||
* MyModel *model = ...;
|
||||
* CallbackTraceSource<Packet> *source = model->PeekSomethingTraceSource ();
|
||||
* CallbackTraceSource<Ptr<Packet>> *source = model->PeekSomethingTraceSource ();
|
||||
* source->AddCallback (MakeCallback (&MySomethingSink));
|
||||
* \endcode
|
||||
*
|
||||
@@ -170,13 +172,13 @@
|
||||
* located in some nodes of the system, we could write the following:
|
||||
* \code
|
||||
* void
|
||||
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
|
||||
* DoSomethingTraceSink (const TraceContext &context, Ptr<Packet> packet)
|
||||
* {
|
||||
* // for example, print the arguments
|
||||
* std::cout << "packet: " << packet << std::endl;
|
||||
* // for example, print the packet
|
||||
* std::cout << "packet: " << packet->Print () << std::endl;
|
||||
* }
|
||||
* // connect the above sink to a matching trace source
|
||||
* NodeList::Connect ("/nodes/* /devices/* /rx", MakeCallback &DoSomethingTraceSink);
|
||||
* NodeList::Connect ("/nodes/* /devices/* /rx", MakeCallback (&DoSomethingTraceSink));
|
||||
* \endcode
|
||||
*
|
||||
* The connection path string "/nodes/* /devices/* /rx" matches the "rx" trace source
|
||||
@@ -203,10 +205,10 @@
|
||||
* the TraceContext object:
|
||||
* \code
|
||||
* void
|
||||
* DoSomethingTraceSink (const TraceContext &context, Packet packet)
|
||||
* DoSomethingTraceSink (const TraceContext &context, Ptr<Packet> packet)
|
||||
* {
|
||||
* // for example, print the arguments
|
||||
* std::cout << "context=\"" << context << "\" packet: " << packet << std::endl;
|
||||
* // for example, print the packet
|
||||
* std::cout << "context=\"" << context << "\" packet: " << packet->Print () << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
* The above code is going to generate output which looks like the following:
|
||||
@@ -223,7 +225,7 @@
|
||||
* in the \ref TraceSourceList. For example, we could write the following to
|
||||
* generate adhoc trace output:
|
||||
* \code
|
||||
* void DeviceRxSink (const TraceContext &context, const Packet &packet)
|
||||
* void DeviceRxSink (const TraceContext &context, Ptr<const Packet> packet)
|
||||
* {
|
||||
* NodeListIndex nodeIndex;
|
||||
* NodeNetDeviceIndex deviceIndex;
|
||||
@@ -231,7 +233,7 @@
|
||||
* context.GetElement (deviceIndex);
|
||||
* std::cout << "node-index=" << nodeIndex.Get ();
|
||||
* std::cout << ", device-index=" << deviceIndex.Get ();
|
||||
* std::cout << ", packet: " << packet;
|
||||
* std::cout << ", packet: " << packet->Print ();
|
||||
* std::cout << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
@@ -247,7 +249,7 @@
|
||||
* class MyModel
|
||||
* {
|
||||
* public:
|
||||
* void DoSomething (Packet packet)
|
||||
* void DoSomething (Ptr<Packet> packet)
|
||||
* {
|
||||
* // report this event on packet with value
|
||||
* m_doSomething (packet);
|
||||
@@ -255,7 +257,7 @@
|
||||
* }
|
||||
* private:
|
||||
* // report every "something" function call.
|
||||
* CallbackTraceSource<Packet> m_doSomething;
|
||||
* CallbackTraceSource<Ptr<Packet>> m_doSomething;
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
@@ -279,7 +281,7 @@
|
||||
* virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
* private:
|
||||
* // the new trace source to export.
|
||||
* CallbackTraceSource<Packet> m_rxSource;
|
||||
* CallbackTraceSource<Ptr<Packet>> m_rxSource;
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
@@ -362,15 +364,15 @@
|
||||
* class MyModel
|
||||
* {
|
||||
* private:
|
||||
* CallbackTraceSource<Packet> m_rxSource;
|
||||
* CallbackTraceSource<Packet> m_txSource;
|
||||
* CallbackTraceSource<Packet> m_dropSource;
|
||||
* CallbackTraceSource<Ptr<Packet>> m_rxSource;
|
||||
* CallbackTraceSource<Ptr<Packet>> m_txSource;
|
||||
* CallbackTraceSource<Ptr<Packet>> m_dropSource;
|
||||
* };
|
||||
* \endcode
|
||||
* When a single sink is connected to all 3 sources here, one might want
|
||||
* to write code like the following:
|
||||
* \code
|
||||
* void DeviceRxSink (const TraceContext &context, const Packet &packet)
|
||||
* void DeviceRxSink (const TraceContext &context, Ptr<const Packet> &packet)
|
||||
* {
|
||||
* switch (type) {
|
||||
* case RX:
|
||||
@@ -407,23 +409,23 @@
|
||||
* };
|
||||
* private:
|
||||
* // generate events
|
||||
* void NotifyRxPacket (Packet p) {
|
||||
* void NotifyRxPacket (Ptr<Packet> p) {
|
||||
* m_rxSource (p, MyModel::RX);
|
||||
* }
|
||||
* void NotifyTxPacket (Packet p) {
|
||||
* void NotifyTxPacket (Ptr<Packet> p) {
|
||||
* m_rxSource (p, MyModel::TX);
|
||||
* }
|
||||
* void NotifyDropPacket (Packet p) {
|
||||
* void NotifyDropPacket (Ptr<Packet> p) {
|
||||
* m_rxSource (p, MyModel::DROP);
|
||||
* }
|
||||
* CallbackTraceSource<Packet,enum TraceType> m_rxSource;
|
||||
* CallbackTraceSource<Packet,enum TraceType> m_txSource;
|
||||
* CallbackTraceSource<Packet,enum TraceType> m_dropSource;
|
||||
* CallbackTraceSource<Ptr<Packet>,enum TraceType> m_rxSource;
|
||||
* CallbackTraceSource<Ptr<Packet>,enum TraceType> m_txSource;
|
||||
* CallbackTraceSource<Ptr<Packet>,enum TraceType> m_dropSource;
|
||||
* };
|
||||
* \endcode
|
||||
* These 3 new sources can be connected easily to a new trace sink:
|
||||
* \code
|
||||
* void ASimpleTraceSink (const TraceContext &context, const Packet &packet, enum MyModel::TraceType type)
|
||||
* void ASimpleTraceSink (const TraceContext &context, Ptr<const Packet> packet, enum MyModel::TraceType type)
|
||||
* {
|
||||
* // here, read the "type" argument
|
||||
* }
|
||||
@@ -447,7 +449,7 @@
|
||||
* define a new MyModelTraceType class which contains the type of trace, your users can
|
||||
* then write trace sink code which looks like this:
|
||||
* \code
|
||||
* void AFancyTraceSink (const TraceContext &context, const Packet &packet)
|
||||
* void AFancyTraceSink (const TraceContext &context, Ptr<const Packet> packet)
|
||||
* {
|
||||
* MyModelTraceType type;
|
||||
* if (context.GetElement (type))
|
||||
@@ -471,9 +473,9 @@
|
||||
* Of course, since the type of trace is stored in the TraceContext, your users can
|
||||
* also take the shortcut which uses the printing functionality of the TraceContext:
|
||||
* \code
|
||||
* void ALessFancyTraceSink (const TraceContext &context, const Packet &packet)
|
||||
* void ALessFancyTraceSink (const TraceContext &context, Ptr<const Packet> packet)
|
||||
* {
|
||||
* std::cout << "context=\"" << context << "\" packet: " << packet << std::endl;
|
||||
* std::cout << "context=\"" << context << "\" packet: " << packet->Print () << std::endl;
|
||||
* }
|
||||
* \endcode
|
||||
* which will generate something like the following when the trace source comes
|
||||
@@ -497,6 +499,8 @@
|
||||
* };
|
||||
* // called from MyModel::GetTraceResolver
|
||||
* MyModelTraceType (enum Type type);
|
||||
* // needed for by the tracing subsystem.
|
||||
* MyModelTraceType ();
|
||||
* // called from trace sink
|
||||
* enum Type Get (void) const;
|
||||
* // needed by the tracing subsystem
|
||||
@@ -513,10 +517,14 @@
|
||||
* \endcode
|
||||
* The implementation does not require much thinking:
|
||||
* \code
|
||||
* MyModelTraceType::MyModelTraceType ()
|
||||
* : m_type (RX)
|
||||
* {// an arbitrary default value.
|
||||
* }
|
||||
* MyModelTraceType::MyModelTraceType (enum Type type)
|
||||
* : m_type (type)
|
||||
* {}
|
||||
* enum Type
|
||||
* enum MyModelTraceType::Type
|
||||
* MyModelTraceType::Get (void) const
|
||||
* {
|
||||
* return m_type;
|
||||
@@ -531,14 +539,14 @@
|
||||
* }
|
||||
* void
|
||||
* MyModelTraceType::Print (std::ostream &os) const
|
||||
* (
|
||||
* {
|
||||
* // this method is invoked by the print function of a TraceContext
|
||||
* // if it contains an instance of this TraceContextElement.
|
||||
* switch (m_type) {
|
||||
* case RX: os << "rx"; break;
|
||||
* // ...
|
||||
* }
|
||||
* )
|
||||
* }
|
||||
* std::string
|
||||
* MyModelTraceType::GetTypeName (void) const
|
||||
* {
|
||||
|
||||
@@ -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.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,468 @@
|
||||
|
||||
@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 Logging
|
||||
@section Logging
|
||||
|
||||
@node Statistics
|
||||
@section Statistics
|
||||
|
||||
@node Advanced Tracing
|
||||
@section Advanced Tracing
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
@@ -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.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -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,111 @@
|
||||
\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::
|
||||
* A-First-ns-3-Script::
|
||||
Part 2-: Details
|
||||
* ns-3 Callbacks::
|
||||
* Simulation Output::
|
||||
* ns-3 routing overview::
|
||||
* Other-network-topologies::
|
||||
* 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 callbacks.texi
|
||||
@include output.texi
|
||||
@include routing.texi
|
||||
@include other.texi
|
||||
@include troubleshoot.texi
|
||||
|
||||
@printindex cp
|
||||
|
||||
@bye
|
||||
@@ -107,9 +107,9 @@ main (int argc, char *argv[])
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
@@ -154,7 +154,7 @@ main (int argc, char *argv[])
|
||||
// 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.");
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("255.255.255.255", port),
|
||||
"Udp",
|
||||
@@ -165,7 +165,7 @@ main (int argc, char *argv[])
|
||||
ooff->Stop (Seconds(10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
Ptr<PacketSink> sink = CreateObject<PacketSink> (
|
||||
n1,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
@@ -174,7 +174,7 @@ main (int argc, char *argv[])
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
sink = Create<PacketSink> (
|
||||
sink = CreateObject<PacketSink> (
|
||||
n2,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
|
||||
+10
-10
@@ -106,11 +106,11 @@ main (int argc, char *argv[])
|
||||
// Explicitly create the nodes required by the topology (shown above).
|
||||
//
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n3 = Create<InternetNode> ();
|
||||
Ptr<Node> n4 = Create<InternetNode> ();
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n4 = CreateObject<InternetNode> ();
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
//
|
||||
@@ -211,7 +211,7 @@ main (int argc, char *argv[])
|
||||
// a fine time to find the interface indices on node two.
|
||||
//
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
|
||||
ipv4 = n2->GetObject<Ipv4> ();
|
||||
|
||||
uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr (n2Lan0Addr);
|
||||
uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr (n2Lan1Addr);
|
||||
@@ -261,7 +261,7 @@ main (int argc, char *argv[])
|
||||
// interface to find the output interface index, and tell node zero to send
|
||||
// its multicast traffic out that interface.
|
||||
//
|
||||
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
uint32_t ifIndexSrc = ipv4->FindInterfaceForAddr (multicastSource);
|
||||
ipv4->SetDefaultMulticastRoute (ifIndexSrc);
|
||||
//
|
||||
@@ -269,7 +269,7 @@ main (int argc, char *argv[])
|
||||
// multicast data. To enable forwarding bits up the protocol stack, we need
|
||||
// to tell the stack to join the multicast group.
|
||||
//
|
||||
ipv4 = n4->QueryInterface<Ipv4> (Ipv4::iid);
|
||||
ipv4 = n4->GetObject<Ipv4> ();
|
||||
ipv4->JoinMulticastGroup (multicastSource, multicastGroup);
|
||||
//
|
||||
// Create an OnOff application to send UDP datagrams from node zero to the
|
||||
@@ -281,7 +281,7 @@ main (int argc, char *argv[])
|
||||
|
||||
// Configure a multicast packet generator that generates a packet
|
||||
// every few seconds
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress (multicastGroup, port),
|
||||
"Udp",
|
||||
@@ -298,7 +298,7 @@ main (int argc, char *argv[])
|
||||
// Create an optional packet sink to receive these packets
|
||||
// If you enable logging on this (above) it will print a log statement
|
||||
// for every packet received
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
Ptr<PacketSink> sink = CreateObject<PacketSink> (
|
||||
n4,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
|
||||
@@ -100,10 +100,10 @@ main (int argc, char *argv[])
|
||||
// Explicitly create the nodes required by the topology (shown above).
|
||||
//
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n3 = Create<InternetNode> ();
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
//
|
||||
@@ -165,7 +165,7 @@ main (int argc, char *argv[])
|
||||
//
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.1.2", port),
|
||||
"Udp",
|
||||
@@ -179,7 +179,7 @@ main (int argc, char *argv[])
|
||||
//
|
||||
// Create a similar flow from n3 to n0, starting at time 1.1 seconds
|
||||
//
|
||||
ooff = Create<OnOffApplication> (
|
||||
ooff = CreateObject<OnOffApplication> (
|
||||
n3,
|
||||
InetSocketAddress ("10.1.1.1", port),
|
||||
"Udp",
|
||||
|
||||
@@ -61,7 +61,7 @@ NS_LOG_COMPONENT_DEFINE ("CsmaPacketSocketExample");
|
||||
static Ptr<CsmaNetDevice>
|
||||
CreateCsmaDevice (Ptr<Node> node, Ptr<CsmaChannel> channel)
|
||||
{
|
||||
Ptr<CsmaNetDevice> device = Create<CsmaNetDevice> (node);
|
||||
Ptr<CsmaNetDevice> device = CreateObject<CsmaNetDevice> (node);
|
||||
device->Attach (channel);
|
||||
Ptr<Queue> queue = Queue::CreateDefault ();
|
||||
device->AddQueue (queue);
|
||||
@@ -102,14 +102,14 @@ main (int argc, char *argv[])
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<Node> ();
|
||||
Ptr<Node> n1 = Create<Node> ();
|
||||
Ptr<Node> n2 = Create<Node> ();
|
||||
Ptr<Node> n3 = Create<Node> ();
|
||||
Ptr<Node> n0 = CreateObject<Node> ();
|
||||
Ptr<Node> n1 = CreateObject<Node> ();
|
||||
Ptr<Node> n2 = CreateObject<Node> ();
|
||||
Ptr<Node> n3 = CreateObject<Node> ();
|
||||
|
||||
// create the shared medium used by all csma devices.
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
Ptr<CsmaChannel> channel = Create<CsmaChannel> (DataRate(5000000), MilliSeconds(2));
|
||||
Ptr<CsmaChannel> channel = CreateObject<CsmaChannel> (DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
// use a helper function to connect our nodes to the shared channel.
|
||||
NS_LOG_INFO ("Build Topology.");
|
||||
@@ -134,7 +134,7 @@ main (int argc, char *argv[])
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
// from n0 to n1
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
n0ToN1,
|
||||
"Packet",
|
||||
@@ -145,7 +145,7 @@ main (int argc, char *argv[])
|
||||
ooff->Stop (Seconds(10.0));
|
||||
|
||||
// Create a similar flow from n3 to n0, starting at time 1.1 seconds
|
||||
ooff = Create<OnOffApplication> (
|
||||
ooff = CreateObject<OnOffApplication> (
|
||||
n3,
|
||||
n3ToN0,
|
||||
"Packet",
|
||||
|
||||
@@ -120,13 +120,13 @@ main (int argc, char *argv[])
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n3 = Create<InternetNode> ();
|
||||
Ptr<Node> n4 = Create<InternetNode> ();
|
||||
Ptr<Node> n5 = Create<InternetNode> ();
|
||||
Ptr<Node> n6 = Create<InternetNode> ();
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n4 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n5 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n6 = CreateObject<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
@@ -191,7 +191,7 @@ main (int argc, char *argv[])
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.3.2", port),
|
||||
"Udp",
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/* -*- 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/log.h"
|
||||
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.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);
|
||||
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
|
||||
// Set up some default values for the simulation. Use the
|
||||
// DefaultValue::Bind () technique to tell the system what subclass of
|
||||
// Queue to use, and what the queue limit is
|
||||
|
||||
// The below Bind command tells the queue factory which class to
|
||||
// instantiate, when the queue factory is invoked in the topology code
|
||||
DefaultValue::Bind ("Queue", "DropTailQueue");
|
||||
|
||||
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
|
||||
DefaultValue::Bind ("OnOffApplicationDataRate", "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
|
||||
//
|
||||
// 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;
|
||||
CommandLine::AddArgValue ("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
|
||||
CommandLine::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.");
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n2, DataRate (5000000), MilliSeconds (2));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate (5000000), MilliSeconds (2));
|
||||
|
||||
Ptr<PointToPointChannel> channel2 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n2, n3, DataRate (1500000), MilliSeconds (10));
|
||||
|
||||
Ptr<PointToPointChannel> channel3 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n3, DataRate (1500000), MilliSeconds (100));
|
||||
|
||||
// Later, we add IP addresses. The middle two octets correspond to
|
||||
// the channel number.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address ("10.0.0.1"),
|
||||
n2, Ipv4Address ("10.0.0.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address ("10.1.1.1"),
|
||||
n2, Ipv4Address ("10.1.1.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel2, n2, Ipv4Address ("10.2.2.1"),
|
||||
n3, Ipv4Address ("10.2.2.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel3, n1, Ipv4Address ("10.3.3.1"),
|
||||
n3, Ipv4Address ("10.3.3.2"));
|
||||
|
||||
PointToPointTopology::SetIpv4Metric (
|
||||
channel3, n1, n3, 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
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n3,
|
||||
InetSocketAddress ("10.1.1.1", port),
|
||||
"Udp",
|
||||
ConstantVariable (1),
|
||||
ConstantVariable (0));
|
||||
// Start the application
|
||||
ooff->Start (Seconds (1.1));
|
||||
ooff->Stop (Seconds (10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = CreateObject<PacketSink> (
|
||||
n1,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.1));
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-alternate-routing.tr file
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
AsciiTrace asciitrace ("simple-alternate-routing.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
PcapTrace pcaptrace ("simple-alternate-routing.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/* -*- 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 "ns3/log.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/error-model.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
|
||||
|
||||
// Set up some default values for the simulation. Use the Bind()
|
||||
// technique to tell the system what subclass of ErrorModel to use
|
||||
DefaultValue::Bind ("ErrorModel", "RateErrorModel");
|
||||
// Set a few parameters
|
||||
DefaultValue::Bind ("RateErrorModelErrorRate", "0.01");
|
||||
DefaultValue::Bind ("RateErrorModelErrorUnit", "EU_PKT");
|
||||
|
||||
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
|
||||
DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
|
||||
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::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.");
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n2, DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
Ptr<PointToPointChannel> channel2 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n2, n3, DataRate(1500000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.1.1"),
|
||||
n2, Ipv4Address("10.1.1.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel2, n2, Ipv4Address("10.1.3.1"),
|
||||
n3, Ipv4Address("10.1.3.2"));
|
||||
|
||||
// Finally, we add static routes. These three steps (Channel and
|
||||
// NetDevice creation, IP Address assignment, and routing) are
|
||||
// separated because there may be a need to postpone IP Address
|
||||
// assignment (emulation) or modify to use dynamic routing
|
||||
NS_LOG_INFO ("Add Static Routes.");
|
||||
PointToPointTopology::AddIpv4Routes(n0, n2, channel0);
|
||||
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
|
||||
PointToPointTopology::AddIpv4Routes(n2, n3, channel2);
|
||||
|
||||
// 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)
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.3.2", port),
|
||||
"Udp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start(Seconds(1.0));
|
||||
ooff->Stop (Seconds(10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = CreateObject<PacketSink> (
|
||||
n3,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.0));
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
ooff = CreateObject<OnOffApplication> (
|
||||
n3,
|
||||
InetSocketAddress ("10.1.2.1", port),
|
||||
"Udp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start(Seconds(1.1));
|
||||
ooff->Stop (Seconds(10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
sink = CreateObject<PacketSink> (
|
||||
n1,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.1));
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Here, finish off packet routing configuration
|
||||
// This will likely set by some global StaticRouting object in the future
|
||||
NS_LOG_INFO ("Set Default Routes.");
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
|
||||
ipv4 = n3->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
|
||||
|
||||
//
|
||||
// Error model
|
||||
//
|
||||
// We want to add an error model to node 3's NetDevice
|
||||
// We can obtain a handle to the NetDevice via the channel and node
|
||||
// pointers
|
||||
Ptr<PointToPointNetDevice> nd3 = PointToPointTopology::GetNetDevice
|
||||
(n3, channel2);
|
||||
// Create an ErrorModel based on the implementation (constructor)
|
||||
// specified by the default classId
|
||||
Ptr<ErrorModel> em = ErrorModel::CreateDefault ();
|
||||
NS_ASSERT (em != 0);
|
||||
// Now, query interface on the resulting em pointer to see if a
|
||||
// RateErrorModel interface exists. If so, set the packet error rate
|
||||
Ptr<RateErrorModel> bem = em->GetObject<RateErrorModel> ();
|
||||
if (bem)
|
||||
{
|
||||
bem->SetRandomVariable (UniformVariable ());
|
||||
bem->SetRate (0.001);
|
||||
}
|
||||
nd3->AddReceiveErrorModel (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
|
||||
Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
|
||||
(n2, channel0);
|
||||
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);
|
||||
nd2->AddReceiveErrorModel (pem);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-error-model.tr file
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
AsciiTrace asciitrace ("simple-error-model.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -122,10 +122,10 @@ main (int argc, char *argv[])
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n3 = Create<InternetNode> ();
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
@@ -163,7 +163,7 @@ main (int argc, char *argv[])
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.3.2", port),
|
||||
"Udp",
|
||||
@@ -175,7 +175,7 @@ main (int argc, char *argv[])
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
// The last argument "true" disables output from the Receive callback
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
Ptr<PacketSink> sink = CreateObject<PacketSink> (
|
||||
n3,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
@@ -184,7 +184,7 @@ main (int argc, char *argv[])
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
ooff = Create<OnOffApplication> (
|
||||
ooff = CreateObject<OnOffApplication> (
|
||||
n3,
|
||||
InetSocketAddress ("10.1.2.1", port),
|
||||
"Udp",
|
||||
@@ -195,7 +195,7 @@ main (int argc, char *argv[])
|
||||
ooff->Stop (Seconds (10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
sink = Create<PacketSink> (
|
||||
sink = CreateObject<PacketSink> (
|
||||
n1,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/* -*- 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.tr"
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/olsr.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SimplePointToPointExample");
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
// Set up some default values for the simulation. Use the Bind()
|
||||
// technique to tell the system what subclass of Queue to use,
|
||||
// and what the queue limit is
|
||||
|
||||
// The below Bind command tells the queue factory which class to
|
||||
// instantiate, when the queue factory is invoked in the topology code
|
||||
DefaultValue::Bind ("Queue", "DropTailQueue");
|
||||
|
||||
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
|
||||
DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
|
||||
|
||||
//DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::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.");
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n4 = CreateObject<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n2, DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
Ptr<PointToPointChannel> channel2 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n2, n3, DataRate(1500000), MilliSeconds(10));
|
||||
|
||||
Ptr<PointToPointChannel> channel3 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n3, n4, DataRate(1500000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.1.1"),
|
||||
n2, Ipv4Address("10.1.1.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel2, n2, Ipv4Address("10.1.3.1"),
|
||||
n3, Ipv4Address("10.1.3.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel3, n3, Ipv4Address("10.1.4.1"),
|
||||
n4, Ipv4Address("10.1.4.2"));
|
||||
|
||||
// Enable OLSR
|
||||
NS_LOG_INFO ("Enabling OLSR Routing.");
|
||||
olsr::EnableAllNodes ();
|
||||
|
||||
|
||||
// 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)
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.4.2", port),
|
||||
"Udp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start(Seconds(1.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = CreateObject<PacketSink> (
|
||||
n4,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.0));
|
||||
|
||||
// Create a similar flow from n4 to n1, starting at time 1.1 seconds
|
||||
ooff = CreateObject<OnOffApplication> (
|
||||
n4,
|
||||
InetSocketAddress ("10.1.2.1", port),
|
||||
"Udp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start (Seconds(1.1));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
sink = CreateObject<PacketSink> (
|
||||
n1,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.1));
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-point-to-point.tr file
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
AsciiTrace asciitrace ("simple-point-to-point-olsr.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named
|
||||
// simple-point-to-point.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
PcapTrace pcaptrace ("simple-point-to-point-olsr.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::StopAt (Seconds (30));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -72,29 +72,7 @@ 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);
|
||||
|
||||
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);
|
||||
LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_ALL);
|
||||
#endif
|
||||
|
||||
// Set up some default values for the simulation. Use the Bind()
|
||||
@@ -108,8 +86,6 @@ main (int argc, char *argv[])
|
||||
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
|
||||
DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
|
||||
|
||||
//DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::Parse (argc, argv);
|
||||
@@ -117,10 +93,10 @@ main (int argc, char *argv[])
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n3 = Create<InternetNode> ();
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
@@ -163,27 +139,25 @@ main (int argc, char *argv[])
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.3.2", port),
|
||||
"Udp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start(Seconds(1.0));
|
||||
ooff->Stop (Seconds(10.0));
|
||||
ooff->Start (Seconds(1.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
Ptr<PacketSink> sink = CreateObject<PacketSink> (
|
||||
n3,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.0));
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
ooff = Create<OnOffApplication> (
|
||||
ooff = CreateObject<OnOffApplication> (
|
||||
n3,
|
||||
InetSocketAddress ("10.1.2.1", port),
|
||||
"Udp",
|
||||
@@ -191,24 +165,43 @@ main (int argc, char *argv[])
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start(Seconds(1.1));
|
||||
ooff->Stop (Seconds(10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
sink = Create<PacketSink> (
|
||||
sink = CreateObject<PacketSink> (
|
||||
n1,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.1));
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// TCP
|
||||
// Create a file transfer from n0 to n3, starting at time 1.2
|
||||
uint16_t servPort = 500;
|
||||
|
||||
ooff = CreateObject<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.3.2", servPort),
|
||||
"Tcp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start (Seconds(1.2));
|
||||
ooff->Stop (Seconds(1.35));
|
||||
|
||||
// Create a packet sink to receive these TCP packets
|
||||
sink = Create<PacketSink> (
|
||||
n3,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), servPort),
|
||||
"Tcp");
|
||||
sink->Start (Seconds (1.2));
|
||||
|
||||
// Here, finish off packet routing configuration
|
||||
// This will likely set by some global StaticRouting object in the future
|
||||
NS_LOG_INFO ("Set Default Routes.");
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
|
||||
ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
|
||||
ipv4 = n3->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
@@ -227,6 +220,7 @@ main (int argc, char *argv[])
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::StopAt (Seconds (3.0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/* -*- 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-errors.tr"
|
||||
// - pcap traces also generated in the following files
|
||||
// "tcp-large-transfer-errors.pcap-$n-$i" where n and i represent node and interface numbers respectively
|
||||
// Usage (e.g.): ./waf --run tcp-large-transfer-errors
|
||||
|
||||
#include <ctype.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/node-list.h"
|
||||
|
||||
#include "ns3/tcp.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpLargeTransferErrors");
|
||||
|
||||
void
|
||||
ApplicationTraceSink (const TraceContext &context, 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,
|
||||
uint16_t servPort)
|
||||
{
|
||||
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
|
||||
localSocket->Connect (InetSocketAddress ("10.1.2.2", 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("TcpLargeTransferErrors", LOG_LEVEL_ALL);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create three nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n1, DataRate(10000000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.3.1"),
|
||||
n1, Ipv4Address("10.1.3.2"));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(10000000), MilliSeconds(10));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
// Finally, we add static routes. These three steps (Channel and
|
||||
// NetDevice creation, IP Address assignment, and routing) are
|
||||
// separated because there may be a need to postpone IP Address
|
||||
// assignment (emulation) or modify to use dynamic routing
|
||||
PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
|
||||
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
|
||||
ipv4 = n2->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
n0->GetObject<SocketFactory> ();
|
||||
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
|
||||
localSocket->Bind ();
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
n2,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), servPort),
|
||||
"Tcp");
|
||||
sink->Start (Seconds (0.0));
|
||||
sink->Stop (Seconds (10000.0));
|
||||
|
||||
//
|
||||
// Error models
|
||||
//
|
||||
// We want to add an error model to node 2's NetDevice
|
||||
// We can obtain a handle to the NetDevice via the channel and node
|
||||
// pointers
|
||||
Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
|
||||
(n2, channel1);
|
||||
Ptr<RateErrorModel> rem = Create<RateErrorModel> ();
|
||||
// The first data segment for this flow is packet uid=4
|
||||
rem->SetRandomVariable (UniformVariable ());
|
||||
rem->SetUnit (EU_PKT);
|
||||
rem->SetRate (0.05);
|
||||
nd2->AddReceiveErrorModel (rem);
|
||||
|
||||
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
|
||||
servPort);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-examples.tr file
|
||||
AsciiTrace asciitrace ("tcp-large-transfer-errors.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named
|
||||
// simple-examples.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
PcapTrace pcaptrace ("tcp-large-transfer-errors.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
|
||||
|
||||
Simulator::StopAt (Seconds(10000));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/* -*- 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/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/node-list.h"
|
||||
|
||||
#include "ns3/tcp.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
|
||||
|
||||
void
|
||||
ApplicationTraceSink (const TraceContext &context, 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,
|
||||
uint16_t servPort)
|
||||
{
|
||||
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
|
||||
localSocket->Connect (InetSocketAddress ("10.1.2.2", 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);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create three nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n1, DataRate(10000000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.3.1"),
|
||||
n1, Ipv4Address("10.1.3.2"));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(10000000), MilliSeconds(10));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
// Finally, we add static routes. These three steps (Channel and
|
||||
// NetDevice creation, IP Address assignment, and routing) are
|
||||
// separated because there may be a need to postpone IP Address
|
||||
// assignment (emulation) or modify to use dynamic routing
|
||||
PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
|
||||
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
|
||||
ipv4 = n2->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
n0->GetObject<SocketFactory> ();
|
||||
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
|
||||
localSocket->Bind ();
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
n2,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), servPort),
|
||||
"Tcp");
|
||||
sink->Start (Seconds (0.0));
|
||||
sink->Stop (Seconds (100.0));
|
||||
|
||||
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
|
||||
servPort);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-examples.tr file
|
||||
AsciiTrace asciitrace ("tcp-large-transfer.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named
|
||||
// simple-examples.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
PcapTrace pcaptrace ("tcp-large-transfer.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
|
||||
|
||||
Simulator::StopAt (Seconds(1000));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/* -*- 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
|
||||
//
|
||||
// 100Kb/s, 10ms 1Mb/s, 10ms
|
||||
// n0-----------------n1-----------------n2
|
||||
//
|
||||
//
|
||||
// - Tracing of queues and packet receptions to file
|
||||
// "tcp-nonlistening-server.tr"
|
||||
// - pcap traces also generated in the following files
|
||||
// "tcp-nonlistening-server.pcap-$n-$i" where n and i represent node and interface numbers respectively
|
||||
// Usage (e.g.): ./waf --run tcp-nonlistening-server
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/error-model.h"
|
||||
|
||||
#include "ns3/tcp.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpNonListeningServer");
|
||||
|
||||
void ConnectionSucceededCallback (Ptr<Socket> localSocket)
|
||||
{
|
||||
uint32_t nBytes = 2000;
|
||||
uint8_t data[nBytes];
|
||||
for(uint32_t i = 0; i < nBytes; ++i)
|
||||
{
|
||||
char m = 'A';
|
||||
data[i] = m;
|
||||
} //put something interesting in the packets ABCDEF...
|
||||
localSocket->Send (data, nBytes);
|
||||
}
|
||||
|
||||
void ConnectionFailedCallback (Ptr<Socket> localSocket)
|
||||
{
|
||||
NS_LOG_ERROR("Connection failed at time " << Simulator::Now ().GetSeconds ());
|
||||
}
|
||||
|
||||
void StartFlow(Ptr<Socket> localSocket, uint16_t servPort)
|
||||
{
|
||||
NS_LOG_LOGIC(std::endl << "Connection attempt at time " <<
|
||||
Simulator::Now ().GetSeconds () << std::endl);
|
||||
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
|
||||
localSocket->SetConnectCallback (
|
||||
MakeCallback (&ConnectionSucceededCallback),
|
||||
MakeCallback (&ConnectionFailedCallback),
|
||||
MakeNullCallback<void, Ptr<Socket> > () );
|
||||
}
|
||||
|
||||
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("TcpNonListeningServer", LOG_LEVEL_ALL);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create three nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n1, DataRate(1000000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.3.1"),
|
||||
n1, Ipv4Address("10.1.3.2"));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(100000), MilliSeconds(10));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
// Finally, we add static routes. These three steps (Channel and
|
||||
// NetDevice creation, IP Address assignment, and routing) are
|
||||
// separated because there may be a need to postpone IP Address
|
||||
// assignment (emulation) or modify to use dynamic routing
|
||||
PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
|
||||
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
|
||||
ipv4 = n2->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Simulation 1
|
||||
//
|
||||
// Send 2000 bytes over a connection to server port 500 at time 0
|
||||
// Should observe SYN exchange, two data segments, and FIN exchange
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint16_t servPort = 500;
|
||||
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
n0->GetObject<SocketFactory> ();
|
||||
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
|
||||
localSocket->Bind ();
|
||||
|
||||
#ifdef NOTFORTHISSCRIPT
|
||||
// Create an optional packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
n2,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), servPort),
|
||||
"Tcp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (0.0));
|
||||
sink->Stop (Seconds (10.0));
|
||||
#endif
|
||||
|
||||
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, servPort);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-examples.tr file
|
||||
AsciiTrace asciitrace ("tcp-nonlistening-server.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named
|
||||
// simple-examples.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
PcapTrace pcaptrace ("tcp-nonlistening-server.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
|
||||
Simulator::StopAt (Seconds(1000));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/* -*- 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
|
||||
//
|
||||
// 100Kb/s, 10ms 1Mb/s, 10ms
|
||||
// n0-----------------n1-----------------n2
|
||||
//
|
||||
//
|
||||
// - Tracing of queues and packet receptions to file
|
||||
// "tcp-small-transfer-oneloss.tr"
|
||||
// - pcap traces also generated in the following files
|
||||
// "tcp-small-transfer-oneloss.pcap-$n-$i" where n and i represent node and interface numbers respectively
|
||||
// Usage (e.g.): ./waf --run tcp-small-transfer-oneloss
|
||||
|
||||
#include <ctype.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/node-list.h"
|
||||
|
||||
#include "ns3/tcp.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpSmallTransferOneloss");
|
||||
|
||||
void
|
||||
ApplicationTraceSink (const TraceContext &context, 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 StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
|
||||
uint16_t servPort)
|
||||
{
|
||||
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
|
||||
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
|
||||
uint8_t data[nBytes];
|
||||
for(uint32_t i = 0; i < nBytes; ++i)
|
||||
{
|
||||
char m = toascii (97 + i % 26);
|
||||
data[i] = m;
|
||||
}
|
||||
localSocket->Send (data, nBytes);
|
||||
}
|
||||
|
||||
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("TcpSmallTransferOneloss", LOG_LEVEL_ALL);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create three nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n1, DataRate(1000000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.3.1"),
|
||||
n1, Ipv4Address("10.1.3.2"));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(100000), MilliSeconds(10));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
// Finally, we add static routes. These three steps (Channel and
|
||||
// NetDevice creation, IP Address assignment, and routing) are
|
||||
// separated because there may be a need to postpone IP Address
|
||||
// assignment (emulation) or modify to use dynamic routing
|
||||
PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
|
||||
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
|
||||
ipv4 = n2->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Simulation 1
|
||||
//
|
||||
// Send 2000 bytes over a connection to server port 500 at time 0
|
||||
// Should observe SYN exchange, two data segments, and FIN exchange
|
||||
// Force the loss of the first data segment
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int nBytes = 2000;
|
||||
uint16_t servPort = 500;
|
||||
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
n0->GetObject<SocketFactory> ();
|
||||
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
|
||||
localSocket->Bind ();
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
n2,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), servPort),
|
||||
"Tcp");
|
||||
sink->Start (Seconds (0.0));
|
||||
sink->Stop (Seconds (100.0));
|
||||
|
||||
//
|
||||
// Error models
|
||||
//
|
||||
// We want to add an error model to node 2's NetDevice
|
||||
// We can obtain a handle to the NetDevice via the channel and node
|
||||
// pointers
|
||||
Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
|
||||
(n2, channel1);
|
||||
Ptr<ListErrorModel> pem = Create<ListErrorModel> ();
|
||||
std::list<uint32_t> sampleList;
|
||||
// The first data segment for this flow is packet uid=4
|
||||
sampleList.push_back (4);
|
||||
pem->SetList (sampleList);
|
||||
nd2->AddReceiveErrorModel (pem);
|
||||
|
||||
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
|
||||
servPort);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-examples.tr file
|
||||
AsciiTrace asciitrace ("tcp-small-transfer-oneloss.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named
|
||||
// simple-examples.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
PcapTrace pcaptrace ("tcp-small-transfer-oneloss.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
|
||||
|
||||
Simulator::StopAt (Seconds(1000));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/* -*- 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
|
||||
//
|
||||
// 100Kb/s, 10ms 1Mb/s, 10ms
|
||||
// n0-----------------n1-----------------n2
|
||||
//
|
||||
//
|
||||
// - Tracing of queues and packet receptions to file
|
||||
// "tcp-small-transfer.tr"
|
||||
// - pcap traces also generated in the following files
|
||||
// "tcp-small-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
|
||||
// Usage (e.g.): ./waf --run tcp-small-transfer
|
||||
|
||||
#include <ctype.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/node-list.h"
|
||||
|
||||
#include "ns3/tcp.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpSmallTransfer");
|
||||
|
||||
void
|
||||
ApplicationTraceSink (const TraceContext &context, 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,
|
||||
uint16_t servPort)
|
||||
{
|
||||
// NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
|
||||
localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
|
||||
localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
|
||||
MakeNullCallback<void, Ptr<Socket> > (),
|
||||
MakeNullCallback<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
|
||||
uint8_t data[nBytes];
|
||||
for(uint32_t i = 0; i < nBytes; ++i)
|
||||
{
|
||||
char m = toascii (97 + i % 26);
|
||||
data[i] = m;
|
||||
}
|
||||
localSocket->Send (data, nBytes);
|
||||
}
|
||||
|
||||
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("TcpSmallTransfer", LOG_LEVEL_ALL);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create three nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n1, DataRate(1000000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.3.1"),
|
||||
n1, Ipv4Address("10.1.3.2"));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(100000), MilliSeconds(10));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
// Finally, we add static routes. These three steps (Channel and
|
||||
// NetDevice creation, IP Address assignment, and routing) are
|
||||
// separated because there may be a need to postpone IP Address
|
||||
// assignment (emulation) or modify to use dynamic routing
|
||||
PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
|
||||
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
|
||||
ipv4 = n2->GetObject<Ipv4> ();
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Simulation 1
|
||||
//
|
||||
// Send 2000 bytes over a connection to server port 500 at time 0
|
||||
// Should observe SYN exchange, two data segments, and FIN exchange
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int nBytes = 2000;
|
||||
uint16_t servPort = 500;
|
||||
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
n0->GetObject<SocketFactory> ();
|
||||
Ptr<Socket> localSocket = socketFactory->CreateSocket ();
|
||||
localSocket->Bind ();
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
n2,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), servPort),
|
||||
"Tcp");
|
||||
sink->Start (Seconds (0.0));
|
||||
sink->Stop (Seconds (100.0));
|
||||
|
||||
Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
|
||||
servPort);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-examples.tr file
|
||||
AsciiTrace asciitrace ("tcp-small-transfer.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
|
||||
// Also configure some tcpdump traces; each interface will be traced
|
||||
// The output files will be named
|
||||
// simple-examples.pcap-<nodeId>-<interfaceId>
|
||||
// and can be read by the "tcpdump -r" command (use "-tt" option to
|
||||
// display timestamps correctly)
|
||||
PcapTrace pcaptrace ("tcp-small-transfer.pcap");
|
||||
pcaptrace.TraceAllIp ();
|
||||
|
||||
NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
|
||||
|
||||
Simulator::StopAt (Seconds(1000));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -100,10 +100,10 @@ main (int argc, char *argv[])
|
||||
// Explicitly create the nodes required by the topology (shown above).
|
||||
//
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n3 = Create<InternetNode> ();
|
||||
Ptr<Node> n0 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n1 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n2 = CreateObject<InternetNode> ();
|
||||
Ptr<Node> n3 = CreateObject<InternetNode> ();
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
//
|
||||
@@ -167,7 +167,7 @@ main (int argc, char *argv[])
|
||||
//
|
||||
uint16_t port = 9; // well-known echo port number
|
||||
|
||||
Ptr<UdpEchoServer> server = Create<UdpEchoServer> (n1, port);
|
||||
Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
|
||||
//
|
||||
// Create a UdpEchoClient application to send UDP datagrams from node zero to
|
||||
// node one.
|
||||
@@ -176,7 +176,7 @@ main (int argc, char *argv[])
|
||||
uint32_t maxPacketCount = 1;
|
||||
Time interPacketInterval = Seconds (1.);
|
||||
|
||||
Ptr<UdpEchoClient> client = Create<UdpEchoClient> (n0, "10.1.1.2", port,
|
||||
Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", port,
|
||||
maxPacketCount, interPacketInterval, packetSize);
|
||||
//
|
||||
// Tell the applications when to start and stop.
|
||||
|
||||
@@ -6,10 +6,18 @@ def build(bld):
|
||||
['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-point-to-point',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'simple-point-to-point.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'
|
||||
@@ -33,3 +41,29 @@ def build(bld):
|
||||
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('tcp-large-transfer-errors',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'tcp-large-transfer-errors.cc'
|
||||
|
||||
obj = bld.create_ns3_program('tcp-nonlistening-server',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'tcp-nonlistening-server.cc'
|
||||
|
||||
obj = bld.create_ns3_program('tcp-small-transfer',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'tcp-small-transfer.cc'
|
||||
|
||||
obj = bld.create_ns3_program('tcp-small-transfer-oneloss',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'tcp-small-transfer-oneloss.cc'
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/* -*- 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/wifi-net-device.h"
|
||||
#include "ns3/wifi-channel.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/static-mobility-model.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/packet-socket-address.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/gnuplot.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
static uint32_t g_bytesTotal = 0;
|
||||
static GnuplotDataset *g_output = 0;
|
||||
|
||||
static Ptr<Node>
|
||||
CreateAdhocNode (Ptr<WifiChannel> channel,
|
||||
Vector position, const char *address)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> ();
|
||||
Ptr<AdhocWifiNetDevice> device = CreateObject<AdhocWifiNetDevice> (node, Mac48Address (address));
|
||||
device->Attach (channel);
|
||||
Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
|
||||
mobility->SetPosition (position);
|
||||
node->AggregateObject (mobility);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
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);
|
||||
double mbs = ((g_bytesTotal * 8.0) / 1000000);
|
||||
g_bytesTotal = 0;
|
||||
g_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), &AdvancePosition, node);
|
||||
}
|
||||
|
||||
static void
|
||||
ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &address)
|
||||
{
|
||||
g_bytesTotal += packet->GetSize ();
|
||||
}
|
||||
|
||||
static Ptr<Socket>
|
||||
SetupPacketReceive (Ptr<Node> node, uint16_t port)
|
||||
{
|
||||
TypeId tid = TypeId::LookupByName ("Packet");
|
||||
Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
|
||||
Ptr<Socket> sink = socketFactory->CreateSocket ();
|
||||
sink->Bind ();
|
||||
sink->SetRecvCallback (MakeCallback (&ReceivePacket));
|
||||
return sink;
|
||||
}
|
||||
|
||||
static void
|
||||
RunOneExperiment (void)
|
||||
{
|
||||
g_bytesTotal = 0;
|
||||
|
||||
Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
|
||||
|
||||
Ptr<Node> a = CreateAdhocNode (channel,
|
||||
Vector (5.0,0.0,0.0),
|
||||
"00:00:00:00:00:01");
|
||||
Ptr<Node> b = CreateAdhocNode (channel,
|
||||
Vector (0.0, 0.0, 0.0),
|
||||
"00:00:00:00:00:02");
|
||||
|
||||
PacketSocketAddress destination = PacketSocketAddress ();
|
||||
destination.SetProtocol (1);
|
||||
destination.SetSingleDevice (0);
|
||||
destination.SetPhysicalAddress (Mac48Address ("00:00:00:00:00:02"));
|
||||
Ptr<Application> app = CreateObject<OnOffApplication> (a, destination,
|
||||
"Packet",
|
||||
ConstantVariable (250),
|
||||
ConstantVariable (0),
|
||||
DataRate (60000000),
|
||||
2000);
|
||||
|
||||
app->Start (Seconds (0.5));
|
||||
app->Stop (Seconds (250.0));
|
||||
|
||||
Simulator::Schedule (Seconds (1.5), &AdvancePosition, b);
|
||||
Ptr<Socket> recvSink = SetupPacketReceive (b, 10);
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Simulator::SetLinkedList ();
|
||||
|
||||
// disable fragmentation
|
||||
DefaultValue::Bind ("WifiFragmentationThreshold", "2200");
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
Gnuplot gnuplot = Gnuplot ("reference-rates.png");
|
||||
|
||||
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
|
||||
|
||||
g_output = new GnuplotDataset ("54mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "54mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("48mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "48mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("36mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "36mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("24mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "24mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("18mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "18mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("12mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "12mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("9mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "9mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("6mb");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
|
||||
DefaultValue::Bind ("WifiConstantDataRate", "6mb");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
gnuplot.GenerateOutput (std::cout);
|
||||
|
||||
gnuplot = Gnuplot ("rate-control.png");
|
||||
|
||||
DefaultValue::Bind ("WifiPhyStandard", "holland");
|
||||
|
||||
g_output = new GnuplotDataset ("arf");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "Arf");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("aarf");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "Aarf");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
g_output = new GnuplotDataset ("ideal");
|
||||
g_output->SetStyle (GnuplotDataset::LINES);
|
||||
DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "Ideal");
|
||||
RunOneExperiment ();
|
||||
gnuplot.AddDataset (*g_output);
|
||||
delete g_output;
|
||||
|
||||
gnuplot.GenerateOutput (std::cout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/* -*- 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/wifi-net-device.h"
|
||||
#include "ns3/wifi-channel.h"
|
||||
#include "ns3/wifi-phy.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/static-mobility-model.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/packet-socket-address.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/node-list.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
void
|
||||
WifiNetDeviceTrace (const TraceContext &context, Ptr<const Packet> p, Mac48Address address)
|
||||
{
|
||||
std::cout << context << " ad=" << address << " p: " << p << std::endl;
|
||||
}
|
||||
void
|
||||
WifiPhyStateTrace (const TraceContext &context, Time start, Time duration, enum WifiPhy::State state)
|
||||
{
|
||||
std::cout << context << " 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 Ptr<Node>
|
||||
CreateApNode (Ptr<WifiChannel> channel,
|
||||
Vector position,
|
||||
const char *macAddress,
|
||||
Ssid ssid,
|
||||
Time at)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> ();
|
||||
Ptr<NqapWifiNetDevice> device = CreateObject<NqapWifiNetDevice> (node, Mac48Address (macAddress));
|
||||
device->SetSsid (ssid);
|
||||
Simulator::Schedule (at, &NqapWifiNetDevice::StartBeaconing, device);
|
||||
device->Attach (channel);
|
||||
Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
|
||||
mobility->SetPosition (position);
|
||||
node->AggregateObject (mobility);
|
||||
return node;
|
||||
}
|
||||
|
||||
static Ptr<Node>
|
||||
CreateStaNode (Ptr<WifiChannel> channel,
|
||||
Vector position,
|
||||
const char *macAddress,
|
||||
Ssid ssid)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> ();
|
||||
Ptr<NqstaWifiNetDevice> device = CreateObject<NqstaWifiNetDevice> (node, Mac48Address (macAddress));
|
||||
Simulator::ScheduleNow (&NqstaWifiNetDevice::StartActiveAssociation, device,
|
||||
ssid);
|
||||
device->Attach (channel);
|
||||
Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
|
||||
mobility->SetPosition (position);
|
||||
node->AggregateObject (mobility);
|
||||
return node;
|
||||
}
|
||||
|
||||
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[])
|
||||
{
|
||||
Simulator::SetLinkedList ();
|
||||
|
||||
Packet::EnableMetadata ();
|
||||
|
||||
//Simulator::EnableLogTo ("80211.log");
|
||||
|
||||
|
||||
// enable rts cts all the time.
|
||||
DefaultValue::Bind ("WifiRtsCtsThreshold", "0");
|
||||
// disable fragmentation
|
||||
DefaultValue::Bind ("WifiFragmentationThreshold", "2200");
|
||||
DefaultValue::Bind ("WifiRateControlAlgorithm", "Aarf");
|
||||
//DefaultValue::Bind ("WifiRateControlAlgorithm", "Arf");
|
||||
|
||||
Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
|
||||
Ssid ssid = Ssid ("mathieu");
|
||||
|
||||
Ptr<Node> a = CreateApNode (channel,
|
||||
Vector (5.0,0.0,0.0),
|
||||
"00:00:00:00:00:01",
|
||||
ssid,
|
||||
Seconds (0.1));
|
||||
Simulator::Schedule (Seconds (1.0), &AdvancePosition, a);
|
||||
|
||||
Ptr<Node> b = CreateStaNode (channel,
|
||||
Vector (0.0, 0.0, 0.0),
|
||||
"00:00:00:00:00:02",
|
||||
ssid);
|
||||
|
||||
Ptr<Node> c = CreateStaNode (channel,
|
||||
Vector (0.0, 0.0, 0.0),
|
||||
"00:00:00:00:00:03",
|
||||
ssid);
|
||||
|
||||
PacketSocketAddress destination = PacketSocketAddress ();
|
||||
destination.SetProtocol (1);
|
||||
destination.SetSingleDevice (0);
|
||||
destination.SetPhysicalAddress (Mac48Address ("00:00:00:00:00:03"));
|
||||
Ptr<Application> app = CreateObject<OnOffApplication> (b, destination,
|
||||
"Packet",
|
||||
ConstantVariable (42),
|
||||
ConstantVariable (0));
|
||||
app->Start (Seconds (0.5));
|
||||
app->Stop (Seconds (43.0));
|
||||
|
||||
//NodeList::Connect ("/nodes/*/devices/*/*", MakeCallback (&WifiNetDeviceTrace));
|
||||
//NodeList::Connect ("/nodes/*/devices/*/phy/state", MakeCallback (&WifiPhyStateTrace));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,217 +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/log.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;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ChannelSample");
|
||||
|
||||
// ===========================================================================
|
||||
// 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_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
FakeInternetNode::~FakeInternetNode ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
void
|
||||
FakeInternetNode::Doit (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_INFO ("**** Send outbound packet");
|
||||
Packet p;
|
||||
|
||||
m_dtqOutbound.Enqueue(p);
|
||||
UpperNotify();
|
||||
}
|
||||
|
||||
bool
|
||||
FakeInternetNode::UpperDoSendUp (Packet &p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << &p << ")");
|
||||
NS_LOG_INFO ("**** Receive inbound packet");
|
||||
m_dtqInbound.Enqueue(p);
|
||||
return m_dtqInbound.Dequeue(p);
|
||||
}
|
||||
|
||||
bool
|
||||
FakeInternetNode::UpperDoPull (Packet &p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << &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_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
FakePhysicalLayer::~FakePhysicalLayer ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
bool
|
||||
FakePhysicalLayer::LowerDoNotify (LayerConnectorUpper *upper)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
|
||||
Packet p;
|
||||
|
||||
NS_LOG_LOGIC ("Starting pull");
|
||||
|
||||
NS_ASSERT(m_upperPartner);
|
||||
m_upperPartner->UpperPull(p);
|
||||
|
||||
m_dtqOutbound.Enqueue(p);
|
||||
|
||||
NS_LOG_LOGIC ("Got bits, Notify lower");
|
||||
|
||||
NS_ASSERT(m_lowerPartner);
|
||||
return m_lowerPartner->LowerNotify(this);
|
||||
}
|
||||
|
||||
bool
|
||||
FakePhysicalLayer::UpperDoSendUp (Packet &p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << &p << ")");
|
||||
|
||||
NS_ASSERT(m_upperPartner);
|
||||
return m_upperPartner->UpperSendUp(p);
|
||||
}
|
||||
|
||||
bool
|
||||
FakePhysicalLayer::UpperDoPull (Packet &p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << &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_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
FakeChannel::~FakeChannel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
NS_LOG_INFO ("Channel Hackorama");
|
||||
|
||||
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,38 +0,0 @@
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/component-manager.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
class AnObject : public Object
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
static const ClassId cid;
|
||||
AnObject (int a, double b);
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
};
|
||||
|
||||
const InterfaceId AnObject::iid = MakeInterfaceId ("AnObject", Object::iid);
|
||||
const ClassId AnObject::cid = MakeClassId<AnObject, int, double> ("AnObject", AnObject::iid);
|
||||
|
||||
AnObject::AnObject (int a, double b)
|
||||
{
|
||||
// enable our interface
|
||||
SetInterfaceId (AnObject::iid);
|
||||
}
|
||||
void
|
||||
AnObject::DoDispose (void)
|
||||
{
|
||||
// Do your work here.
|
||||
// chain up
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Ptr<AnObject> anObject = ComponentManager::Create<AnObject,int,double> (AnObject::cid, AnObject::iid, 10, 20.0);
|
||||
NS_ASSERT (anObject != 0);
|
||||
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");
|
||||
}
|
||||
@@ -62,7 +62,7 @@ int main (int argc, char* argv[])
|
||||
//utilize the loops variable to show that it can be read from the command line
|
||||
if(loops>0)
|
||||
{
|
||||
cout<<"You requested "<<loops<<" iterations of a loop";
|
||||
std::cerr<<"You requested "<<loops<<" iterations of a loop";
|
||||
for(uint32_t i=0;i<loops;++i)
|
||||
cout<<"iteration "<<i;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ int main (int argc, char *argv[])
|
||||
// create an array of empty nodes for testing purposes
|
||||
for (uint32_t i = 0; i < 120; i++)
|
||||
{
|
||||
nodes.push_back (Create<InternetNode> ());
|
||||
nodes.push_back (CreateObject<InternetNode> ());
|
||||
}
|
||||
|
||||
// setup the grid itself: objects are layed out
|
||||
@@ -27,7 +27,7 @@ int main (int argc, char *argv[])
|
||||
GridTopology grid (-100, -100, 20, 5, 20);
|
||||
|
||||
// each object will be attached a static position.
|
||||
grid.SetMobilityModel (StaticMobilityModel::cid);
|
||||
grid.SetMobilityModel (StaticMobilityModel::GetTypeId ());
|
||||
|
||||
// finalize the setup by attaching to each object
|
||||
// in the input array a position and initializing
|
||||
@@ -39,9 +39,9 @@ int main (int argc, char *argv[])
|
||||
j != nodes.end (); j++)
|
||||
{
|
||||
Ptr<Object> object = *j;
|
||||
Ptr<MobilityModel> position = object->QueryInterface<MobilityModel> (MobilityModel::iid);
|
||||
Ptr<MobilityModel> position = object->GetObject<MobilityModel> ();
|
||||
NS_ASSERT (position != 0);
|
||||
Position pos = position->Get ();
|
||||
Vector pos = position->GetPosition ();
|
||||
std::cout << "x=" << pos.x << ", y=" << pos.y << ", z=" << pos.z << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
#include "ns3/object.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
class AnObject : public Object
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
AnObject ();
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
};
|
||||
|
||||
const InterfaceId AnObject::iid = MakeInterfaceId ("AnObject", Object::iid);
|
||||
|
||||
AnObject::AnObject ()
|
||||
{
|
||||
// enable our interface
|
||||
SetInterfaceId (AnObject::iid);
|
||||
}
|
||||
void
|
||||
AnObject::DoDispose (void)
|
||||
{
|
||||
// Do your work here.
|
||||
// chain up
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
class AnotherObject : public Object
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
AnotherObject (int a);
|
||||
private:
|
||||
virtual void DoDispose (void);
|
||||
};
|
||||
|
||||
const InterfaceId AnotherObject::iid = MakeInterfaceId ("AnotherObject", Object::iid);
|
||||
|
||||
AnotherObject::AnotherObject (int a)
|
||||
{
|
||||
// enable our interface
|
||||
SetInterfaceId (AnotherObject::iid);
|
||||
}
|
||||
void
|
||||
AnotherObject::DoDispose (void)
|
||||
{
|
||||
// Do your work here.
|
||||
// chain up
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
class YetAnotherObject : public Object
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
YetAnotherObject (int a);
|
||||
private:
|
||||
virtual void DoDispose (void);
|
||||
};
|
||||
|
||||
const InterfaceId YetAnotherObject::iid = MakeInterfaceId ("YetAnotherObject", Object::iid);
|
||||
|
||||
YetAnotherObject::YetAnotherObject (int a)
|
||||
{
|
||||
// enable our interface
|
||||
SetInterfaceId (YetAnotherObject::iid);
|
||||
// aggregated directly to another object.
|
||||
AddInterface (Create<AnObject> ());
|
||||
}
|
||||
void
|
||||
YetAnotherObject::DoDispose (void)
|
||||
{
|
||||
// Do your work here.
|
||||
// chain up
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Ptr<Object> p;
|
||||
Ptr<AnObject> anObject;
|
||||
Ptr<AnotherObject> anotherObject;
|
||||
Ptr<YetAnotherObject> yetAnotherObject;
|
||||
|
||||
p = Create<AnObject> ();
|
||||
// p gives you access to AnObject's interface
|
||||
anObject = p->QueryInterface<AnObject> (AnObject::iid);
|
||||
NS_ASSERT (anObject != 0);
|
||||
// p does not give you access to AnotherObject's interface
|
||||
anotherObject = p->QueryInterface<AnotherObject> (AnotherObject::iid);
|
||||
NS_ASSERT (anotherObject == 0);
|
||||
|
||||
anotherObject = Create<AnotherObject> (1);
|
||||
// AnotherObject does not give you access to AnObject's interface
|
||||
anObject = anotherObject->QueryInterface<AnObject> (AnObject::iid);
|
||||
NS_ASSERT (anObject == 0);
|
||||
|
||||
// aggregate the two objects
|
||||
p->AddInterface (anotherObject);
|
||||
// p gives you access to AnObject's interface
|
||||
anObject = p->QueryInterface<AnObject> (AnObject::iid);
|
||||
NS_ASSERT (anObject != 0);
|
||||
// p gives you access to AnotherObject's interface
|
||||
anotherObject = p->QueryInterface<AnotherObject> (AnotherObject::iid);
|
||||
NS_ASSERT (anotherObject != 0);
|
||||
|
||||
|
||||
yetAnotherObject = Create<YetAnotherObject> (2);
|
||||
// gives you acess to AnObject interface too.
|
||||
anObject = yetAnotherObject->QueryInterface<AnObject> (AnObject::iid);
|
||||
NS_ASSERT (anObject != 0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/header.h"
|
||||
#include <iostream>
|
||||
@@ -105,16 +106,17 @@ int main (int argc, char *argv[])
|
||||
sourceHeader.SetData (2);
|
||||
|
||||
// instantiate a packet
|
||||
Packet p;
|
||||
Ptr<Packet> p = Create<Packet> ();
|
||||
|
||||
// and store my header into the packet.
|
||||
p.AddHeader (sourceHeader);
|
||||
p->AddHeader (sourceHeader);
|
||||
|
||||
// print the content of my packet on the standard output.
|
||||
p.Print (std::cout);
|
||||
p->Print (std::cout);
|
||||
|
||||
// you can now remove the header from the packet:
|
||||
MyHeader destinationHeader;
|
||||
p.RemoveHeader (destinationHeader);
|
||||
p->RemoveHeader (destinationHeader);
|
||||
|
||||
// and check that the destination and source
|
||||
// headers contain the same values.
|
||||
|
||||
@@ -49,7 +49,7 @@ void DefaultPrint (void)
|
||||
{
|
||||
// We create a packet with 1000 bytes of zero payload
|
||||
// and add 3 headers to this packet.
|
||||
Packet p (1000);
|
||||
Ptr<Packet> p = Create<Packet> (1000);
|
||||
Ipv4Header ipv4;
|
||||
UdpHeader udp;
|
||||
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
|
||||
@@ -57,36 +57,36 @@ void DefaultPrint (void)
|
||||
udp.SetSource (1025);
|
||||
udp.SetDestination (80);
|
||||
udp.SetPayloadSize (1000);
|
||||
p.AddHeader (udp);
|
||||
p.AddHeader (ipv4);
|
||||
p->AddHeader (udp);
|
||||
p->AddHeader (ipv4);
|
||||
|
||||
std::cout << "full packet size=" << p.GetSize () << std::endl;
|
||||
std::cout << "full packet size=" << p->GetSize () << std::endl;
|
||||
// Here, invoke the default Print routine, directed to std out
|
||||
p.Print (std::cout);
|
||||
p->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Now, we fragment our packet in 3 consecutive pieces.
|
||||
Packet p1 = p.CreateFragment (0, 2);
|
||||
Packet p2 = p.CreateFragment (2, 1000);
|
||||
Packet p3 = p.CreateFragment (1002, 26);
|
||||
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);
|
||||
p1->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment2" << std::endl;
|
||||
p2.Print (std::cout);
|
||||
p2->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment3" << std::endl;
|
||||
p3.Print (std::cout);
|
||||
p3->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
|
||||
// And, finally, we re-aggregate the 3 consecutive pieces.
|
||||
Packet aggregate = p1;
|
||||
aggregate.AddAtEnd (p2);
|
||||
aggregate.AddAtEnd (p3);
|
||||
Ptr<Packet> aggregate = p1->Copy ();
|
||||
aggregate->AddAtEnd (p2);
|
||||
aggregate->AddAtEnd (p3);
|
||||
std::cout << "aggregated" << std::endl;
|
||||
aggregate.Print (std::cout);
|
||||
aggregate->Print (std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ void NonDefaultPrint (void)
|
||||
|
||||
|
||||
// We create a packet with 1000 bytes of zero payload
|
||||
Packet p (1000);
|
||||
Ptr<Packet> p = Create<Packet> (1000);
|
||||
Ipv4Header ipv4;
|
||||
UdpHeader udp;
|
||||
ipv4.SetSource (Ipv4Address ("192.168.0.1"));
|
||||
@@ -136,35 +136,35 @@ void NonDefaultPrint (void)
|
||||
udp.SetSource (1025);
|
||||
udp.SetDestination (80);
|
||||
udp.SetPayloadSize (1000);
|
||||
p.AddHeader (udp);
|
||||
p.AddHeader (ipv4);
|
||||
p->AddHeader (udp);
|
||||
p->AddHeader (ipv4);
|
||||
|
||||
std::cout << "full packet size=" << p.GetSize () << std::endl;
|
||||
p.Print (std::cout, printer);
|
||||
std::cout << "full packet size=" << p->GetSize () << std::endl;
|
||||
p->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// fragment our packet in 3 pieces
|
||||
Packet p1 = p.CreateFragment (0, 2);
|
||||
Packet p2 = p.CreateFragment (2, 1000);
|
||||
Packet p3 = p.CreateFragment (1002, 26);
|
||||
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);
|
||||
p1->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment2" << std::endl;
|
||||
p2.Print (std::cout, printer);
|
||||
p2->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
std::cout << "fragment3" << std::endl;
|
||||
p3.Print (std::cout, printer);
|
||||
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.
|
||||
Packet aggregate = p1;
|
||||
aggregate.AddAtEnd (p2);
|
||||
aggregate.AddAtEnd (p3);
|
||||
Ptr<Packet> aggregate = p1->Copy ();
|
||||
aggregate->AddAtEnd (p2);
|
||||
aggregate->AddAtEnd (p3);
|
||||
std::cout << "aggregated" << std::endl;
|
||||
aggregate.Print (std::cout, printer);
|
||||
aggregate->Print (std::cout, printer);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,20 +116,20 @@ int main (int argc, char *argv[])
|
||||
tag.SetSimpleValue (0x56);
|
||||
|
||||
// store the tag in a packet.
|
||||
Packet p;
|
||||
p.AddTag (tag);
|
||||
Ptr<Packet> p = Create<Packet> ();
|
||||
p->AddTag (tag);
|
||||
|
||||
// create a copy of the packet
|
||||
Packet aCopy = p;
|
||||
Ptr<Packet> aCopy = p->Copy ();
|
||||
|
||||
// read the tag from the packet copy
|
||||
MyTag tagCopy;
|
||||
p.PeekTag (tagCopy);
|
||||
p->PeekTag (tagCopy);
|
||||
|
||||
// the copy and the original are the same !
|
||||
NS_ASSERT (tagCopy.GetSimpleValue () == tag.GetSimpleValue ());
|
||||
|
||||
aCopy.PrintTags (std::cout);
|
||||
aCopy->PrintTags (std::cout);
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/* -*- 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/default-value.h"
|
||||
#include "ns3/static-mobility-model.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<PropagationLossModel> model = PropagationLossModel::CreateDefault ();
|
||||
|
||||
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 = model->GetRxPower (txpower, a, b);
|
||||
std::cout << rxPowerDbm << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
|
||||
#if 0
|
||||
DefaultValue::Bind ("PropagationLossModelType", "Friis");
|
||||
DefaultValue::Bind ("FriisPropagationLossLambda", "0.6");
|
||||
DefaultValue::Bind ("FriisPropagationLossSystemLoss", "1.0");
|
||||
|
||||
PrintOne (-10, 20, 5, 0, 1000, 5);
|
||||
#endif
|
||||
|
||||
DefaultValue::Bind ("PropagationLossModelType", "LogDistance");
|
||||
DefaultValue::Bind ("LogDistancePropagationLossReferenceDistance", "1.0");
|
||||
DefaultValue::Bind ("LogDistancePropagationLossReferenceType", "Random");
|
||||
DefaultValue::Bind ("RandomPropagationLossDistribution", "Constant:10");
|
||||
DefaultValue::Bind ("LogDistancePropagationLossExponent", "4");
|
||||
|
||||
PrintOne (-10, 20, 5, 0, 10000, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+2
-2
@@ -49,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 = Create<A> ();
|
||||
Ptr<A> a = CreateObject<A> ();
|
||||
a->Method ();
|
||||
Ptr<A> prev = StoreA (a);
|
||||
NS_ASSERT (prev == 0);
|
||||
@@ -58,7 +58,7 @@ 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 = Create<A> ();
|
||||
Ptr<A> a = CreateObject<A> ();
|
||||
Ptr<A> prev = StoreA (a);
|
||||
// call method on object
|
||||
prev->Method ();
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 University of Washington
|
||||
* Authors: Tom Henderson, Craig Dowell
|
||||
*
|
||||
* 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 "ns3/log.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/component-manager.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
//
|
||||
// This sample file shows examples of how to use QueryInterface.
|
||||
//
|
||||
// QueryInterface is a templated method of class Object, defined in
|
||||
// src/core/object.h. ns-3 objects that derive from class Object
|
||||
// can have QueryInterface invoked on them.
|
||||
//
|
||||
// QueryInterface is a type-safe way to ask an object, at run-time,
|
||||
// "Do you support the interface identified by the given InterfaceId?"
|
||||
// It avoids deprecated techniques of having to downcast pointers to
|
||||
// an object to ask questions about its type. One or more interfaces
|
||||
// may be associated with a given object.
|
||||
//
|
||||
// QueryInterface is of most use when working with base class
|
||||
// pointers of objects that may be subclassed. For instance,
|
||||
// one may have a pointer to a Node, but not know whether it has
|
||||
// an IPv4 stack. Another example might be to determine whether
|
||||
// a Node has an EnergyModel, to which calls to decrement energy
|
||||
// from the node's battery might be made.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Object is the base class for ns-3 node-related objects used at
|
||||
// the public API. Object provides reference counting implementations
|
||||
// and the QueryInterface.
|
||||
//
|
||||
// A common design paradigm for an ns-3 node object, such as a Queue,
|
||||
// is that we provide an abstract base class that inherits from
|
||||
// Object. This class is assigned an interface ID (iid) and
|
||||
// contains the basic API for objects in this class and subclasses.
|
||||
// This base class is specialized to provide implementations of
|
||||
// the object in question (such as a DropTailQueue).
|
||||
//
|
||||
// The design pattern commonly used is known as the "non-virtual
|
||||
// public interface" pattern, whereby the public API for this
|
||||
// object is a set of public non-virtual functions that forward
|
||||
// to private virtual functions. The forwarding functions can
|
||||
// impose pre- and post-conditions on the forwarding call at
|
||||
// the base class level.
|
||||
//
|
||||
// We'll call this base class "AnInterface" in the example below.
|
||||
//
|
||||
//
|
||||
class AnInterface : public Object
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
void methodA (void);
|
||||
private:
|
||||
virtual void domethodA (void) = 0;
|
||||
};
|
||||
|
||||
void
|
||||
AnInterface::methodA (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// pre-dispatch asserts
|
||||
NS_LOG_LOGIC ("pre-condition");
|
||||
domethodA ();
|
||||
NS_LOG_LOGIC ("post-condition");
|
||||
// post-dispatch asserts
|
||||
}
|
||||
|
||||
//
|
||||
// The below assignment assigns the InterfaceId of the class AnInterface,
|
||||
// and declares that the parent iid is that of class Object.
|
||||
//
|
||||
const InterfaceId AnInterface::iid = MakeInterfaceId ("AnInterface", Object::iid);
|
||||
|
||||
//
|
||||
// AnImplementation is an implementation of the abstract base class
|
||||
// defined above. It provides implementation for the virtual functions
|
||||
// in the base class. It defines one ClassId for each constructor,
|
||||
// and can also provide an interface itself (in this example,
|
||||
// a methodImpl is available)
|
||||
//
|
||||
class AnImplementation : public AnInterface
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
static const ClassId cid;
|
||||
|
||||
AnImplementation ();
|
||||
void methodImpl (void);
|
||||
private:
|
||||
virtual void domethodA (void);
|
||||
};
|
||||
|
||||
void
|
||||
AnImplementation::methodImpl (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
|
||||
AnImplementation::AnImplementation (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// enable our interface
|
||||
SetInterfaceId (AnImplementation::iid);
|
||||
}
|
||||
|
||||
void
|
||||
AnImplementation::domethodA ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
//
|
||||
// The below assignment assigns the InterfaceId of the class AnImplementation,
|
||||
// and declares that the parent iid is that of class Object.
|
||||
//
|
||||
const InterfaceId AnImplementation::iid =
|
||||
MakeInterfaceId ("AnImplementation", AnInterface::iid);
|
||||
|
||||
//
|
||||
// The next few lines are used by the component manager. They
|
||||
// state that the component manager can create a new object
|
||||
// AnImplementation and return an interface corresponding to
|
||||
// the AnImplementation iid.
|
||||
//
|
||||
const ClassId AnImplementation::cid =
|
||||
MakeClassId<AnImplementation>
|
||||
("AnImplementation", AnImplementation::iid);
|
||||
|
||||
|
||||
//
|
||||
// Extending interfaces
|
||||
// ==================
|
||||
// What if AnInterface doesn't provide enough API for your
|
||||
// object type?
|
||||
// - if you aren't concerned about backward compatibility and
|
||||
// don't mind recompiling, you just add new methods to AnInterface
|
||||
// and recompile.
|
||||
// - if you want to address backward compatibiliy, or allow part
|
||||
// of the system to use the old interface, you have to do more.
|
||||
// You have to declare a new interface with the new functionality.
|
||||
//
|
||||
|
||||
class AnExtendedInterface : public AnInterface
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
void methodB (void);
|
||||
private:
|
||||
virtual void domethodB (void) = 0;
|
||||
};
|
||||
|
||||
const InterfaceId AnExtendedInterface::iid =
|
||||
MakeInterfaceId ("AnExtendedInterface", AnInterface::iid);
|
||||
|
||||
//
|
||||
// Then you need provide an implementation for the virtual
|
||||
// methods. If you are providing a new implementation for
|
||||
// everything, the answer is straightforward
|
||||
//
|
||||
|
||||
class ANewImplementation : public AnExtendedInterface
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
static const ClassId cid;
|
||||
|
||||
ANewImplementation ();
|
||||
void methodImpl (void);
|
||||
private:
|
||||
virtual void domethodA (void) { /* new-implementation-behavior (); */}
|
||||
virtual void domethodB (void) { /* new-implementation-behavior (); */}
|
||||
};
|
||||
|
||||
ANewImplementation::ANewImplementation (void)
|
||||
{
|
||||
// enable our interface
|
||||
SetInterfaceId (ANewImplementation::iid);
|
||||
}
|
||||
|
||||
void
|
||||
ANewImplementation::methodImpl (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
const InterfaceId ANewImplementation::iid =
|
||||
MakeInterfaceId ("ANewImplementation", AnExtendedInterface::iid);
|
||||
|
||||
//
|
||||
// If you want to extend an existing implementation, you can use
|
||||
// the existing class to instantiate an implementation of its
|
||||
// methods (hasa) and do the following if you can use stuff from
|
||||
// the existing class.
|
||||
//
|
||||
|
||||
class AnExtendedImplementation : public AnExtendedInterface
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
static const ClassId cid;
|
||||
|
||||
AnExtendedImplementation ();
|
||||
void methodImpl (void) { /* pImpl->methodImpl (); */ }
|
||||
void methodExtendedImpl (void);
|
||||
private:
|
||||
virtual void domethodA (void) { /* new-implementation-behavior (); */}
|
||||
virtual void domethodB (void) { /* new-implementation-behavior (); */}
|
||||
Ptr<AnImplementation> pImpl;
|
||||
};
|
||||
|
||||
AnExtendedImplementation::AnExtendedImplementation (void)
|
||||
{
|
||||
pImpl = Create<AnImplementation> ();
|
||||
SetInterfaceId (AnExtendedImplementation::iid);
|
||||
}
|
||||
|
||||
void
|
||||
AnExtendedImplementation::methodExtendedImpl (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
const InterfaceId AnExtendedImplementation::iid =
|
||||
MakeInterfaceId ("AnExtendedImplementation", AnExtendedInterface::iid);
|
||||
|
||||
//
|
||||
// Inheriting from an existing implementation (isa) and an extended
|
||||
// interface is tricky, because of the diamond multiple inheritance
|
||||
// problem. If the pImpl method above is not desirable, it may
|
||||
// be that the implementation extension could be aggregated.
|
||||
//
|
||||
// The extension will not have access to the base implementation,
|
||||
// so this design pattern may be more appropriate if the extension
|
||||
// is very modular (e.g., add an EnergyModel to a wireless interface)
|
||||
//
|
||||
// EXAMPLE NOT YET PROVIDED
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
|
||||
Ptr<AnInterface> aBase = ComponentManager::Create<AnImplementation>
|
||||
(AnImplementation::cid, AnInterface::iid);
|
||||
NS_ASSERT (aBase != 0);
|
||||
|
||||
aBase->methodA ();
|
||||
//aBase->methodImpl (); // XXX won't compile, aBase not right ptr type
|
||||
|
||||
Ptr<AnImplementation> aBaseImplPtr =
|
||||
aBase-> QueryInterface<AnImplementation> (AnImplementation::iid);
|
||||
aBaseImplPtr->methodImpl ();
|
||||
aBaseImplPtr->methodA();
|
||||
|
||||
// Test symmetric property of QueryInterface
|
||||
Ptr<AnInterface> aBase2 =
|
||||
aBaseImplPtr-> QueryInterface<AnInterface> (AnInterface::iid);
|
||||
aBase2->methodA ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -17,7 +17,7 @@ using namespace ns3;
|
||||
static void
|
||||
CourseChange (const TraceContext &context, Ptr<const MobilityModel> position)
|
||||
{
|
||||
Position pos = position->Get ();
|
||||
Vector pos = position->GetPosition ();
|
||||
std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y
|
||||
<< ", z=" << pos.z << std::endl;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ int main (int argc, char *argv[])
|
||||
std::vector<Ptr<Object> > objects;
|
||||
for (uint32_t i = 0; i < 10000; i++)
|
||||
{
|
||||
Ptr<MobilityModelNotifier> notifier = Create<MobilityModelNotifier> ();
|
||||
Ptr<MobilityModelNotifier> notifier = CreateObject<MobilityModelNotifier> ();
|
||||
notifier->TraceConnect ("/course-change", MakeCallback (&CourseChange));
|
||||
objects.push_back (notifier);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "ns3/mobility-model-notifier.h"
|
||||
#include "ns3/random-topology.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/node-list.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
static void
|
||||
CourseChange (ns3::TraceContext const&, 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[])
|
||||
{
|
||||
DefaultValue::Bind ("RandomWalk2dMode", "Time");
|
||||
DefaultValue::Bind ("RandomWalk2dTime", "2s");
|
||||
DefaultValue::Bind ("RandomWalk2dSpeed", "Constant:1.0");
|
||||
DefaultValue::Bind ("RandomWalk2dBounds", "0:200:0:100");
|
||||
|
||||
DefaultValue::Bind ("RandomDiscPositionX", "100");
|
||||
DefaultValue::Bind ("RandomDiscPositionY", "50");
|
||||
DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
|
||||
|
||||
DefaultValue::Bind ("RandomTopologyPositionType", "RandomDiscPosition");
|
||||
DefaultValue::Bind ("RandomTopologyMobilityType", "RandomWalk2dMobilityModel");
|
||||
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
RandomTopology topology;
|
||||
|
||||
for (uint32_t i = 0; i < 100; i++)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> ();
|
||||
node->AggregateObject (CreateObject<MobilityModelNotifier> ());
|
||||
}
|
||||
|
||||
topology.Layout (NodeList::Begin (), NodeList::End ());
|
||||
NodeList::Connect ("/nodes/*/$MobilityModelNotifier/course-change",
|
||||
MakeCallback (&CourseChange));
|
||||
|
||||
Simulator::StopAt (Seconds (100.0));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ static void
|
||||
GenerateTraffic (Ptr<Socket> socket, uint32_t size)
|
||||
{
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, tx bytes=" << size << std::endl;
|
||||
socket->Send (Packet (size));
|
||||
socket->Send (Create<Packet> (size));
|
||||
if (size > 0)
|
||||
{
|
||||
Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
|
||||
@@ -26,9 +26,9 @@ GenerateTraffic (Ptr<Socket> socket, uint32_t size)
|
||||
}
|
||||
|
||||
static void
|
||||
SocketPrinter (Ptr<Socket> socket, const Packet &packet, const Address &from)
|
||||
SocketPrinter (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
|
||||
{
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet.GetSize () << std::endl;
|
||||
std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet->GetSize () << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -40,10 +40,10 @@ PrintTraffic (Ptr<Socket> socket)
|
||||
void
|
||||
RunSimulation (void)
|
||||
{
|
||||
Ptr<Node> a = Create<InternetNode> ();
|
||||
Ptr<Node> a = CreateObject<InternetNode> ();
|
||||
|
||||
InterfaceId iid = InterfaceId::LookupByName ("Udp");
|
||||
Ptr<SocketFactory> socketFactory = a->QueryInterface<SocketFactory> (iid);
|
||||
TypeId tid = TypeId::LookupByName ("Udp");
|
||||
Ptr<SocketFactory> socketFactory = a->GetObject<SocketFactory> (tid);
|
||||
|
||||
Ptr<Socket> sink = socketFactory->CreateSocket ();
|
||||
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
|
||||
|
||||
+17
-3
@@ -1,9 +1,6 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_program('main-debug')
|
||||
obj.source = ['main-debug.cc', 'main-debug-other.cc']
|
||||
|
||||
obj = bld.create_ns3_program('main-callback')
|
||||
obj.source = 'main-callback.cc'
|
||||
|
||||
@@ -41,3 +38,20 @@ def build(bld):
|
||||
['core', 'simulator', 'mobility'])
|
||||
obj.source = 'main-random-topology.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-adhoc-wifi',
|
||||
['core', 'simulator', 'mobility', 'wifi'])
|
||||
obj.source = 'main-adhoc-wifi.cc'
|
||||
|
||||
obj = bld.create_ns3_program('main-ap-wifi',
|
||||
['core', 'simulator', 'mobility', 'wifi'])
|
||||
obj.source = 'main-ap-wifi.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'
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/composite-trace-resolver.h"
|
||||
#include "onoff-application.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("OnOffApplication");
|
||||
@@ -52,20 +53,20 @@ static NumericDefaultValue<uint32_t> g_defaultSize ("OnOffApplicationPacketSize"
|
||||
|
||||
OnOffApplication::OnOffApplication(Ptr<Node> n,
|
||||
const Address &remote,
|
||||
std::string iid,
|
||||
std::string tid,
|
||||
const RandomVariable& ontime,
|
||||
const RandomVariable& offtime)
|
||||
: Application(n),
|
||||
m_cbrRate (g_defaultRate.GetValue ())
|
||||
{
|
||||
Construct (n, remote, iid,
|
||||
Construct (n, remote, tid,
|
||||
ontime, offtime,
|
||||
g_defaultSize.GetValue ());
|
||||
}
|
||||
|
||||
OnOffApplication::OnOffApplication(Ptr<Node> n,
|
||||
const Address &remote,
|
||||
std::string iid,
|
||||
std::string tid,
|
||||
const RandomVariable& ontime,
|
||||
const RandomVariable& offtime,
|
||||
DataRate rate,
|
||||
@@ -74,13 +75,13 @@ OnOffApplication::OnOffApplication(Ptr<Node> n,
|
||||
m_cbrRate (rate)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
Construct (n, remote, iid, ontime, offtime, size);
|
||||
Construct (n, remote, tid, ontime, offtime, size);
|
||||
}
|
||||
|
||||
void
|
||||
OnOffApplication::Construct (Ptr<Node> n,
|
||||
const Address &remote,
|
||||
std::string iid,
|
||||
std::string tid,
|
||||
const RandomVariable& onTime,
|
||||
const RandomVariable& offTime,
|
||||
uint32_t size)
|
||||
@@ -90,14 +91,14 @@ OnOffApplication::Construct (Ptr<Node> n,
|
||||
m_socket = 0;
|
||||
m_peer = remote;
|
||||
m_connected = false;
|
||||
m_onTime = onTime.Copy ();
|
||||
m_offTime = offTime.Copy ();
|
||||
m_onTime = onTime;
|
||||
m_offTime = offTime;
|
||||
m_pktSize = size;
|
||||
m_residualBits = 0;
|
||||
m_lastStartTime = Seconds (0);
|
||||
m_maxBytes = 0xffffffff;
|
||||
m_maxBytes = 0;
|
||||
m_totBytes = 0;
|
||||
m_iid = iid;
|
||||
m_tid = tid;
|
||||
}
|
||||
|
||||
OnOffApplication::~OnOffApplication()
|
||||
@@ -109,7 +110,7 @@ void
|
||||
OnOffApplication::SetMaxBytes(uint32_t maxBytes)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << maxBytes << ")");
|
||||
NS_LOG_PARAMS (this << maxBytes);
|
||||
m_maxBytes = maxBytes;
|
||||
}
|
||||
|
||||
@@ -117,7 +118,7 @@ void
|
||||
OnOffApplication::SetDefaultRate (const DataRate &rate)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << &rate << ")");
|
||||
NS_LOG_PARAMS (&rate);
|
||||
g_defaultRate.SetValue (rate);
|
||||
}
|
||||
|
||||
@@ -125,7 +126,7 @@ void
|
||||
OnOffApplication::SetDefaultSize (uint32_t size)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << size << ")");
|
||||
NS_LOG_PARAMS (size);
|
||||
g_defaultSize.SetValue (size);
|
||||
}
|
||||
|
||||
@@ -135,12 +136,6 @@ OnOffApplication::DoDispose (void)
|
||||
NS_LOG_FUNCTION;
|
||||
|
||||
m_socket = 0;
|
||||
delete m_onTime;
|
||||
delete m_offTime;
|
||||
|
||||
m_onTime = 0;
|
||||
m_offTime = 0;
|
||||
|
||||
// chain up
|
||||
Application::DoDispose ();
|
||||
}
|
||||
@@ -153,8 +148,8 @@ void OnOffApplication::StartApplication() // Called at time specified by Start
|
||||
// Create the socket if not already
|
||||
if (!m_socket)
|
||||
{
|
||||
InterfaceId iid = InterfaceId::LookupByName (m_iid);
|
||||
Ptr<SocketFactory> socketFactory = GetNode ()->QueryInterface<SocketFactory> (iid);
|
||||
TypeId tid = TypeId::LookupByName (m_tid);
|
||||
Ptr<SocketFactory> socketFactory = GetNode ()->GetObject<SocketFactory> (tid);
|
||||
m_socket = socketFactory->CreateSocket ();
|
||||
m_socket->Bind ();
|
||||
m_socket->Connect (m_peer);
|
||||
@@ -194,6 +189,7 @@ void OnOffApplication::StopSending()
|
||||
NS_LOG_FUNCTION;
|
||||
|
||||
Simulator::Cancel(m_sendEvent);
|
||||
m_socket->Close ();
|
||||
}
|
||||
|
||||
// Private helpers
|
||||
@@ -201,7 +197,7 @@ void OnOffApplication::ScheduleNextTx()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
|
||||
if (m_totBytes < m_maxBytes)
|
||||
if (m_maxBytes == 0 || m_totBytes < m_maxBytes)
|
||||
{
|
||||
uint32_t bits = m_pktSize * 8 - m_residualBits;
|
||||
NS_LOG_LOGIC ("bits = " << bits);
|
||||
@@ -221,7 +217,7 @@ void OnOffApplication::ScheduleStartEvent()
|
||||
{ // Schedules the event to start sending data (switch to the "On" state)
|
||||
NS_LOG_FUNCTION;
|
||||
|
||||
Time offInterval = Seconds(m_offTime->GetValue());
|
||||
Time offInterval = Seconds(m_offTime.GetValue());
|
||||
NS_LOG_LOGIC ("start at " << offInterval);
|
||||
m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this);
|
||||
}
|
||||
@@ -230,7 +226,7 @@ void OnOffApplication::ScheduleStopEvent()
|
||||
{ // Schedules the event to stop sending data (switch to "Off" state)
|
||||
NS_LOG_FUNCTION;
|
||||
|
||||
Time onInterval = Seconds(m_onTime->GetValue());
|
||||
Time onInterval = Seconds(m_onTime.GetValue());
|
||||
Simulator::Schedule(onInterval, &OnOffApplication::StopSending, this);
|
||||
}
|
||||
|
||||
@@ -240,7 +236,9 @@ void OnOffApplication::SendPacket()
|
||||
NS_LOG_FUNCTION;
|
||||
|
||||
NS_ASSERT (m_sendEvent.IsExpired ());
|
||||
m_socket->Send(Packet (m_pktSize));
|
||||
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;
|
||||
@@ -261,4 +259,17 @@ void OnOffApplication::ConnectionFailed(Ptr<Socket>)
|
||||
cout << "OnOffApplication, Connection Failed" << endl;
|
||||
}
|
||||
|
||||
Ptr<TraceResolver>
|
||||
OnOffApplication::GetTraceResolver (void) const
|
||||
{
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddSource ("tx",
|
||||
TraceDoc ("A new packet is created and is sent",
|
||||
"Ptr<const Packet>",
|
||||
"The newly-created packet."),
|
||||
m_txTrace);
|
||||
resolver->SetParentResolver (Application::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
} // Namespace ns3
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/callback-trace-source.h"
|
||||
#include "ns3/random-variable.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -53,20 +55,24 @@ public:
|
||||
/**
|
||||
* \param n node associated to this application
|
||||
* \param remote remote ip address
|
||||
* \param iid
|
||||
* \param tid TypeId of the socket factory to use. Note this
|
||||
* factory should create sockets compatible with the specified
|
||||
* remote address.
|
||||
* \param ontime on time random variable
|
||||
* \param offtime off time random variable
|
||||
*/
|
||||
OnOffApplication(Ptr<Node> n,
|
||||
const Address &remote,
|
||||
std::string iid,
|
||||
std::string tid,
|
||||
const RandomVariable& ontime,
|
||||
const RandomVariable& offtime);
|
||||
|
||||
/**
|
||||
* \param n node associated to this application
|
||||
* \param remote remote ip address
|
||||
* \param iid
|
||||
* \param tid TypeId of the socket factory to use. Note this
|
||||
* factory should create sockets compatible with the specified
|
||||
* remote address.
|
||||
* \param ontime on time random variable
|
||||
* \param offtime off time random variable
|
||||
* \param rate data rate when on
|
||||
@@ -74,7 +80,7 @@ public:
|
||||
*/
|
||||
OnOffApplication(Ptr<Node> n,
|
||||
const Address &remote,
|
||||
std::string iid,
|
||||
std::string tid,
|
||||
const RandomVariable& ontime,
|
||||
const RandomVariable& offtime,
|
||||
DataRate rate,
|
||||
@@ -109,7 +115,7 @@ private:
|
||||
|
||||
void Construct (Ptr<Node> n,
|
||||
const Address &remote,
|
||||
std::string iid,
|
||||
std::string tid,
|
||||
const RandomVariable& ontime,
|
||||
const RandomVariable& offtime,
|
||||
uint32_t size);
|
||||
@@ -123,8 +129,8 @@ private:
|
||||
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
|
||||
@@ -134,9 +140,11 @@ private:
|
||||
EventId m_startStopEvent; // Event id for next start or stop event
|
||||
EventId m_sendEvent; // Eventid of pending "send packet" event
|
||||
bool m_sending; // True if currently in sending state
|
||||
std::string m_iid;
|
||||
std::string m_tid;
|
||||
CallbackTraceSource<Ptr<const Packet> > m_txTrace;
|
||||
|
||||
private:
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
void ScheduleNextTx();
|
||||
void ScheduleStartEvent();
|
||||
void ScheduleStopEvent();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
module = bld.create_ns3_module('onoff', ['core'])
|
||||
module = bld.create_ns3_module('onoff', ['core', 'simulator', 'node'])
|
||||
module.source = [
|
||||
'onoff-application.cc',
|
||||
]
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/composite-trace-resolver.h"
|
||||
#include "packet-sink.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -37,20 +38,20 @@ NS_LOG_COMPONENT_DEFINE ("PacketSinkApplication");
|
||||
|
||||
PacketSink::PacketSink (Ptr<Node> n,
|
||||
const Address &local,
|
||||
std::string iid)
|
||||
std::string tid)
|
||||
: Application(n)
|
||||
{
|
||||
Construct (n, local, iid);
|
||||
Construct (n, local, tid);
|
||||
}
|
||||
|
||||
void
|
||||
PacketSink::Construct (Ptr<Node> n,
|
||||
const Address &local,
|
||||
std::string iid)
|
||||
std::string tid)
|
||||
{
|
||||
m_socket = 0;
|
||||
m_local = local;
|
||||
m_iid = iid;
|
||||
m_tid = tid;
|
||||
}
|
||||
|
||||
PacketSink::~PacketSink()
|
||||
@@ -72,38 +73,62 @@ void PacketSink::StartApplication() // Called at time specified by Start
|
||||
// Create the socket if not already
|
||||
if (!m_socket)
|
||||
{
|
||||
InterfaceId iid = InterfaceId::LookupByName (m_iid);
|
||||
TypeId tid = TypeId::LookupByName (m_tid);
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
GetNode ()->QueryInterface<SocketFactory> (iid);
|
||||
GetNode ()->GetObject<SocketFactory> (tid);
|
||||
m_socket = socketFactory->CreateSocket ();
|
||||
m_socket->Bind (m_local);
|
||||
m_socket->Listen (0);
|
||||
}
|
||||
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
|
||||
const Address &>) MakeCallback(&PacketSink::Receive, this));
|
||||
|
||||
m_socket->SetRecvCallback (MakeCallback(&PacketSink::Receive, this));
|
||||
m_socket->SetAcceptCallback (
|
||||
MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
|
||||
MakeNullCallback<void, Ptr<Socket>, const Address&> (),
|
||||
MakeCallback(&PacketSink::CloseConnection, this) );
|
||||
}
|
||||
|
||||
void PacketSink::StopApplication() // Called at time specified by Stop
|
||||
{
|
||||
if (!m_socket)
|
||||
if (m_socket)
|
||||
{
|
||||
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
|
||||
const Address &>) NULL);
|
||||
|
||||
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket>,
|
||||
Ptr<Packet>, const Address &> ());
|
||||
}
|
||||
}
|
||||
|
||||
// This LOG output inspired by the application on Joseph Kopena's wiki
|
||||
void PacketSink::Receive(Ptr<Socket> socket, const Packet &packet,
|
||||
void PacketSink::Receive(Ptr<Socket> socket, Ptr<Packet> packet,
|
||||
const Address &from)
|
||||
{
|
||||
if (InetSocketAddress::IsMatchingType (from))
|
||||
{
|
||||
InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
|
||||
NS_LOG_INFO ("Received " << packet.GetSize() << " bytes from " <<
|
||||
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
|
||||
address.GetIpv4() << " [" << address << "]---'" <<
|
||||
packet.PeekData() << "'");
|
||||
// TODO: Add a tracing source here
|
||||
packet->PeekData() << "'");
|
||||
}
|
||||
m_rxTrace (packet, from);
|
||||
}
|
||||
|
||||
void PacketSink::CloseConnection (Ptr<Socket> socket)
|
||||
{
|
||||
socket->Close ();
|
||||
}
|
||||
|
||||
Ptr<TraceResolver>
|
||||
PacketSink::GetTraceResolver (void) const
|
||||
{
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddSource ("rx",
|
||||
TraceDoc ("A new packet has been received",
|
||||
"Ptr<const Packet>",
|
||||
"The newly-received packet.",
|
||||
"const Address &",
|
||||
"The source address of the received packet."),
|
||||
m_rxTrace);
|
||||
resolver->SetParentResolver (Application::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
} // Namespace ns3
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "ns3/application.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/callback-trace-source.h"
|
||||
#include "ns3/address.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -54,11 +56,11 @@ public:
|
||||
/**
|
||||
* \param n node associated to this application
|
||||
* \param local local address to bind to
|
||||
* \param iid string to identify transport protocol of interest
|
||||
* \param tid string to identify transport protocol of interest
|
||||
*/
|
||||
PacketSink (Ptr<Node> n,
|
||||
const Address &local,
|
||||
std::string iid);
|
||||
std::string tid);
|
||||
|
||||
virtual ~PacketSink ();
|
||||
|
||||
@@ -68,16 +70,20 @@ 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
|
||||
// inherited from Object base class.
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
|
||||
void Construct (Ptr<Node> n,
|
||||
const Address &local,
|
||||
std::string iid);
|
||||
std::string tid);
|
||||
|
||||
virtual void Receive (Ptr<Socket> socket, const Packet& packet, const Address& from);
|
||||
virtual void Receive (Ptr<Socket> socket, Ptr<Packet> packet, const Address& from);
|
||||
virtual void CloseConnection (Ptr<Socket> socket);
|
||||
|
||||
Ptr<Socket> m_socket; // Associated socket
|
||||
Address m_local; // Local address to bind to
|
||||
std::string m_iid; // Protocol name (e.g., "Udp")
|
||||
std::string m_tid; // Protocol name (e.g., "Udp")
|
||||
CallbackTraceSource<Ptr<const Packet>, const Address &> m_rxTrace;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -40,9 +40,8 @@ UdpEchoClient::UdpEchoClient (
|
||||
Application(n)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << n << ", " << serverAddress <<
|
||||
", " << serverPort << ", " << count << ", " << interval <<
|
||||
", " << size << ")");
|
||||
NS_LOG_PARAMS (this << n << serverAddress << serverPort << count
|
||||
<< interval << size);
|
||||
|
||||
Construct (n, serverAddress, serverPort, count, interval, size);
|
||||
}
|
||||
@@ -62,9 +61,8 @@ UdpEchoClient::Construct (
|
||||
uint32_t size)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << n << ", " << serverAddress <<
|
||||
", " << serverPort << ", " << count << ", " << interval <<
|
||||
", " << size << ")");
|
||||
NS_LOG_PARAMS (this << n << serverAddress << serverPort
|
||||
<< count << interval << size);
|
||||
|
||||
m_node = n;
|
||||
m_serverAddress = serverAddress;
|
||||
@@ -93,16 +91,15 @@ UdpEchoClient::StartApplication (void)
|
||||
|
||||
if (!m_socket)
|
||||
{
|
||||
InterfaceId iid = InterfaceId::LookupByName ("Udp");
|
||||
TypeId tid = TypeId::LookupByName ("Udp");
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
GetNode ()->QueryInterface<SocketFactory> (iid);
|
||||
GetNode ()->GetObject<SocketFactory> (tid);
|
||||
m_socket = socketFactory->CreateSocket ();
|
||||
m_socket->Bind ();
|
||||
m_socket->Connect (m_peer);
|
||||
}
|
||||
|
||||
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
|
||||
const Address &>) MakeCallback(&UdpEchoClient::Receive, this));
|
||||
m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::Receive, this));
|
||||
|
||||
ScheduleTransmit (Seconds(0.));
|
||||
}
|
||||
@@ -114,8 +111,8 @@ UdpEchoClient::StopApplication ()
|
||||
|
||||
if (!m_socket)
|
||||
{
|
||||
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
|
||||
const Address &>) NULL);
|
||||
m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>, Ptr<Packet>,
|
||||
const Address &> ());
|
||||
}
|
||||
|
||||
Simulator::Cancel(m_sendEvent);
|
||||
@@ -135,7 +132,7 @@ UdpEchoClient::Send (void)
|
||||
|
||||
NS_ASSERT (m_sendEvent.IsExpired ());
|
||||
|
||||
Packet p (m_size);
|
||||
Ptr<Packet> p = Create<Packet> (m_size);
|
||||
m_socket->Send (p);
|
||||
++m_sent;
|
||||
|
||||
@@ -150,16 +147,16 @@ UdpEchoClient::Send (void)
|
||||
void
|
||||
UdpEchoClient::Receive(
|
||||
Ptr<Socket> socket,
|
||||
const Packet &packet,
|
||||
Ptr<Packet> packet,
|
||||
const Address &from)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << socket << ", " << packet << ", " << from << ")");
|
||||
NS_LOG_PARAMS (this << socket << packet << from);
|
||||
|
||||
if (InetSocketAddress::IsMatchingType (from))
|
||||
{
|
||||
InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
|
||||
NS_LOG_INFO ("Received " << packet.GetSize() << " bytes from " <<
|
||||
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
|
||||
address.GetIpv4());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ private:
|
||||
void ScheduleTransmit (Time dt);
|
||||
void Send (void);
|
||||
|
||||
void Receive(Ptr<Socket> socket, const Packet &packet, const Address &from);
|
||||
void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
|
||||
|
||||
Ptr<Node> m_node;
|
||||
Ipv4Address m_serverAddress;
|
||||
|
||||
@@ -38,7 +38,7 @@ UdpEchoServer::UdpEchoServer (
|
||||
Application(n)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << n << ", " << port << ")");
|
||||
NS_LOG_PARAMS (this << n << port);
|
||||
|
||||
Construct (n, port);
|
||||
}
|
||||
@@ -54,7 +54,7 @@ UdpEchoServer::Construct (
|
||||
uint16_t port)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << n << ", " << port << ")");
|
||||
NS_LOG_PARAMS (this << n << port);
|
||||
|
||||
m_node = n;
|
||||
m_port = port;
|
||||
@@ -77,15 +77,14 @@ UdpEchoServer::StartApplication (void)
|
||||
|
||||
if (!m_socket)
|
||||
{
|
||||
InterfaceId iid = InterfaceId::LookupByName ("Udp");
|
||||
TypeId tid = TypeId::LookupByName ("Udp");
|
||||
Ptr<SocketFactory> socketFactory =
|
||||
GetNode ()->QueryInterface<SocketFactory> (iid);
|
||||
GetNode ()->GetObject<SocketFactory> (tid);
|
||||
m_socket = socketFactory->CreateSocket ();
|
||||
m_socket->Bind (m_local);
|
||||
}
|
||||
|
||||
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
|
||||
const Address &>) MakeCallback(&UdpEchoServer::Receive, this));
|
||||
m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::Receive, this));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -95,24 +94,24 @@ UdpEchoServer::StopApplication ()
|
||||
|
||||
if (!m_socket)
|
||||
{
|
||||
m_socket->SetRecvCallback((Callback<void, Ptr<Socket>, const Packet &,
|
||||
const Address &>) NULL);
|
||||
m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>,
|
||||
Ptr<Packet>, const Address &> ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UdpEchoServer::Receive(
|
||||
Ptr<Socket> socket,
|
||||
const Packet &packet,
|
||||
Ptr<Packet> packet,
|
||||
const Address &from)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << socket << ", " << packet << ", " << from << ")");
|
||||
NS_LOG_PARAMS (this << socket << packet << from);
|
||||
|
||||
if (InetSocketAddress::IsMatchingType (from))
|
||||
{
|
||||
InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
|
||||
NS_LOG_INFO ("Received " << packet.GetSize() << " bytes from " <<
|
||||
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
|
||||
address.GetIpv4());
|
||||
|
||||
NS_LOG_LOGIC ("Echoing packet");
|
||||
|
||||
@@ -44,7 +44,7 @@ private:
|
||||
virtual void StartApplication (void);
|
||||
virtual void StopApplication (void);
|
||||
|
||||
void Receive(Ptr<Socket> socket, const Packet &packet, const Address &from);
|
||||
void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
|
||||
|
||||
Ptr<Node> m_node;
|
||||
uint16_t m_port;
|
||||
|
||||
@@ -105,7 +105,7 @@ ChunkRegistry::GetName (uint32_t uid, uint8_t *instance)
|
||||
void
|
||||
ChunkRegistry::InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
|
||||
uint32_t packetUid, uint32_t size,
|
||||
Ptr<CallbackImplBase> callback)
|
||||
CallbackBase callback)
|
||||
{
|
||||
InfoVector *vec = GetInfoVector ();
|
||||
NS_ASSERT (uid >= 1 && uid <= vec->size ());
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
static bool IsTrailer (uint32_t uid);
|
||||
static void InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
|
||||
uint32_t packetUid, uint32_t size,
|
||||
Ptr<CallbackImplBase> callback);
|
||||
CallbackBase callback);
|
||||
private:
|
||||
typedef uint8_t *(*GetStaticInstanceCb) (void);
|
||||
typedef uint32_t (*DeserializeCb) (uint8_t *, Buffer::Iterator);
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
typedef std::string (*GetNameCb) (uint8_t *);
|
||||
typedef void (*InvokePrintCallbackCb) (uint8_t *instance, std::ostream &os,
|
||||
uint32_t packetUid, uint32_t size,
|
||||
Ptr<CallbackImplBase> callback);
|
||||
CallbackBase callback);
|
||||
struct Info {
|
||||
std::string uidString;
|
||||
bool isHeader;
|
||||
@@ -85,7 +85,7 @@ private:
|
||||
template <typename T>
|
||||
static void DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
|
||||
uint32_t packetUid, uint32_t size,
|
||||
Ptr<CallbackImplBase> callback);
|
||||
CallbackBase callback);
|
||||
template <typename T>
|
||||
static uint32_t GetUid (bool isHeader, std::string uidString);
|
||||
|
||||
@@ -167,7 +167,7 @@ template <typename T>
|
||||
void
|
||||
ChunkRegistry::DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
|
||||
uint32_t packetUid, uint32_t size,
|
||||
Ptr<CallbackImplBase> callback)
|
||||
CallbackBase callback)
|
||||
{
|
||||
T *obj = reinterpret_cast<T *> (instance);
|
||||
Callback<void,std::ostream&,uint32_t,uint32_t,const T*> cb;
|
||||
|
||||
@@ -145,32 +145,32 @@ uint64_t DataRate::Parse(const std::string s)
|
||||
return v;
|
||||
}
|
||||
|
||||
bool DataRate::operator < (const DataRate& rhs)
|
||||
bool DataRate::operator < (const DataRate& rhs) const
|
||||
{
|
||||
return m_bps<rhs.m_bps;
|
||||
}
|
||||
|
||||
bool DataRate::operator <= (const DataRate& rhs)
|
||||
bool DataRate::operator <= (const DataRate& rhs) const
|
||||
{
|
||||
return m_bps<=rhs.m_bps;
|
||||
}
|
||||
|
||||
bool DataRate::operator > (const DataRate& rhs)
|
||||
bool DataRate::operator > (const DataRate& rhs) const
|
||||
{
|
||||
return m_bps>rhs.m_bps;
|
||||
}
|
||||
|
||||
bool DataRate::operator >= (const DataRate& rhs)
|
||||
bool DataRate::operator >= (const DataRate& rhs) const
|
||||
{
|
||||
return m_bps>=rhs.m_bps;
|
||||
}
|
||||
|
||||
bool DataRate::operator == (const DataRate& rhs)
|
||||
bool DataRate::operator == (const DataRate& rhs) const
|
||||
{
|
||||
return m_bps==rhs.m_bps;
|
||||
}
|
||||
|
||||
bool DataRate::operator != (const DataRate& rhs)
|
||||
bool DataRate::operator != (const DataRate& rhs) const
|
||||
{
|
||||
return m_bps!=rhs.m_bps;
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ class DataRate
|
||||
*/
|
||||
DataRate (const std::string s);
|
||||
|
||||
bool operator < (const DataRate& rhs);
|
||||
bool operator <= (const DataRate& rhs);
|
||||
bool operator > (const DataRate& rhs);
|
||||
bool operator >= (const DataRate& rhs);
|
||||
bool operator == (const DataRate& rhs);
|
||||
bool operator != (const DataRate& rhs);
|
||||
bool operator < (const DataRate& rhs) const;
|
||||
bool operator <= (const DataRate& rhs) const;
|
||||
bool operator > (const DataRate& rhs) const;
|
||||
bool operator >= (const DataRate& rhs) const;
|
||||
bool operator == (const DataRate& rhs) const;
|
||||
bool operator != (const DataRate& rhs) const;
|
||||
|
||||
/**
|
||||
* \brief Calculate transmission time
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 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 <tomhend@u.washington.edu>
|
||||
* This code has been ported from ns-2 (queue/errmodel.{cc,h}
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "error-model.h"
|
||||
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/type-id-default-value.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ErrorModel");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
static TypeIdDefaultValue g_interfaceIdErrorModelDefaultValue ("ErrorModel",
|
||||
"Error Model",
|
||||
ErrorModel::GetTypeId (),
|
||||
"RateErrorModel");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ErrorModel);
|
||||
|
||||
TypeId ErrorModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ErrorModel")
|
||||
.SetParent<Object> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
ErrorModel::ErrorModel () :
|
||||
m_enable (true)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
ErrorModel::~ErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
Ptr<ErrorModel>
|
||||
ErrorModel::CreateDefault (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
TypeId interfaceId = g_interfaceIdErrorModelDefaultValue.GetValue ();
|
||||
Ptr<ErrorModel> em = interfaceId.CreateObject ()->GetObject<ErrorModel> ();
|
||||
return em;
|
||||
}
|
||||
|
||||
bool
|
||||
ErrorModel::IsCorrupt (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
bool result;
|
||||
// Insert any pre-conditions here
|
||||
result = DoCorrupt (p);
|
||||
// Insert any post-conditions here
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ErrorModel::Reset (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
DoReset ();
|
||||
}
|
||||
|
||||
void
|
||||
ErrorModel::Enable (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_enable = true;
|
||||
}
|
||||
|
||||
void
|
||||
ErrorModel::Disable (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_enable = false;
|
||||
}
|
||||
|
||||
bool
|
||||
ErrorModel::IsEnabled (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_enable;
|
||||
}
|
||||
|
||||
//
|
||||
// RateErrorModel
|
||||
//
|
||||
|
||||
// Defaults for rate/size
|
||||
static NumericDefaultValue<double> g_defaultRateErrorModelErrorRate
|
||||
("RateErrorModelErrorRate", "The error rate for the error model", 0.0);
|
||||
|
||||
static EnumDefaultValue<enum ErrorUnit>
|
||||
g_defaultRateErrorModelErrorUnit ("RateErrorModelErrorUnit",
|
||||
"The error unit for this error model",
|
||||
EU_BYTE, "EU_BYTE",
|
||||
EU_PKT, "EU_PKT",
|
||||
EU_BIT, "EU_BIT",
|
||||
0, (void*)0);
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (RateErrorModel);
|
||||
|
||||
TypeId RateErrorModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("RateErrorModel")
|
||||
.SetParent<ErrorModel> ()
|
||||
.AddConstructor<RateErrorModel> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
RateErrorModel::RateErrorModel () :
|
||||
m_unit (g_defaultRateErrorModelErrorUnit.GetValue() ),
|
||||
m_rate (g_defaultRateErrorModelErrorRate.GetValue() )
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// Assume a uniform random variable if user does not specify
|
||||
m_ranvar = UniformVariable ();
|
||||
}
|
||||
|
||||
RateErrorModel::~RateErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
enum ErrorUnit
|
||||
RateErrorModel::GetUnit (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_unit;
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::SetUnit (enum ErrorUnit error_unit)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_unit = error_unit;
|
||||
}
|
||||
|
||||
double
|
||||
RateErrorModel::GetRate (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_rate;
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::SetRate (double rate)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_rate = rate;
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::SetRandomVariable (const RandomVariable &ranvar)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_ranvar = ranvar;
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorrupt (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
if (!m_enable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
switch (m_unit)
|
||||
{
|
||||
case EU_PKT:
|
||||
return DoCorruptPkt (p);
|
||||
case EU_BYTE:
|
||||
return DoCorruptByte (p);
|
||||
case EU_BIT:
|
||||
return DoCorruptBit (p);
|
||||
default:
|
||||
NS_ASSERT_MSG (false, "m_unit not supported yet");
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorruptPkt (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return (m_ranvar.GetValue () < m_rate);
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorruptByte (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// compute pkt error rate, assume uniformly distributed byte error
|
||||
double per = 1 - pow (1.0 - m_rate, p->GetSize ());
|
||||
return (m_ranvar.GetValue () < per);
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorruptBit(Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// compute pkt error rate, assume uniformly distributed bit error
|
||||
double per = 1 - pow (1.0 - m_rate, (8 * p->GetSize ()) );
|
||||
return (m_ranvar.GetValue () < per);
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::DoReset (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
/* re-initialize any state; no-op for now */
|
||||
}
|
||||
|
||||
//
|
||||
// ListErrorModel
|
||||
//
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ListErrorModel);
|
||||
|
||||
TypeId ListErrorModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ListErrorModel")
|
||||
.SetParent<ErrorModel> ()
|
||||
.AddConstructor<ListErrorModel> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
ListErrorModel::ListErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
ListErrorModel::~ListErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
std::list<uint32_t>
|
||||
ListErrorModel::GetList (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_packetList;
|
||||
}
|
||||
|
||||
void
|
||||
ListErrorModel::SetList (const std::list<uint32_t> &packetlist)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_packetList = packetlist;
|
||||
}
|
||||
|
||||
// When performance becomes a concern, the list provided could be
|
||||
// converted to a dynamically-sized array of uint32_t to avoid
|
||||
// list iteration below.
|
||||
bool
|
||||
ListErrorModel::DoCorrupt (Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
if (!m_enable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint32_t uid = p->GetUid ();
|
||||
for (PacketListCI i = m_packetList.begin ();
|
||||
i != m_packetList.end (); i++)
|
||||
{
|
||||
if (uid == *i)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ListErrorModel::DoReset (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_packetList.clear();
|
||||
}
|
||||
|
||||
|
||||
} //namespace ns3
|
||||
@@ -0,0 +1,233 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 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 <tomhend@u.washington.edu>
|
||||
* This code has been ported from ns-2 (queue/errmodel.{cc,h}
|
||||
*/
|
||||
#ifndef ERROR_MODEL_H
|
||||
#define ERROR_MODEL_H
|
||||
|
||||
#include <list>
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/random-variable.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \brief General error model that can be used to corrupt packets
|
||||
*
|
||||
* This object is used to flag packets as being lost/errored or not.
|
||||
* It is part of the Object framework and can be aggregated to
|
||||
* other ns3 objects and handled by the Ptr class.
|
||||
*
|
||||
* The main method is IsCorrupt(Ptr<Packet> p) which returns true if
|
||||
* the packet is to be corrupted according to the underlying model.
|
||||
* Depending on the error model, the packet itself may have its packet
|
||||
* data buffer errored or not, or side information may be returned to
|
||||
* the client in the form of a packet tag.
|
||||
* The object can have state (resettable by Reset()).
|
||||
* The object can also be enabled and disabled via two public member functions.
|
||||
*
|
||||
* Typical code (simplified) to use an ErrorModel may look something like
|
||||
* this:
|
||||
* \code
|
||||
* Ptr<ErrorModel> rem = CreateObject<RateErrorModel> ();
|
||||
* rem->SetRandomVariable (UniformVariable ());
|
||||
* rem->SetRate (0.001);
|
||||
* ...
|
||||
* Ptr<Packet> p;
|
||||
* if (rem->IsCorrupt (p))
|
||||
* {
|
||||
* dropTrace(p);
|
||||
* } else {
|
||||
* Forward (p);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Two practical error models, a ListErrorModel and a RateErrorModel,
|
||||
* are currently implemented.
|
||||
*/
|
||||
class ErrorModel : public Object
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
/**
|
||||
* A factory method to generate a preconfigured default ErrorModel for use
|
||||
* \return an ErrorModel smart pointer that is the default ErrorModel
|
||||
* type defined
|
||||
*/
|
||||
static Ptr<ErrorModel> CreateDefault (void);
|
||||
|
||||
ErrorModel ();
|
||||
virtual ~ErrorModel ();
|
||||
|
||||
/**
|
||||
* \returns true if the Packet is to be considered as errored/corrupted
|
||||
* \param pkt Packet to apply error model to
|
||||
*/
|
||||
bool IsCorrupt (Ptr<Packet> pkt);
|
||||
/**
|
||||
* Reset any state associated with the error model
|
||||
*/
|
||||
void Reset (void);
|
||||
/**
|
||||
* Enable the error model
|
||||
*/
|
||||
void Enable (void);
|
||||
/**
|
||||
* Disable the error model
|
||||
*/
|
||||
void Disable (void);
|
||||
/**
|
||||
* \return true if error model is enabled; false otherwise
|
||||
*/
|
||||
bool IsEnabled (void) const;
|
||||
|
||||
protected:
|
||||
bool m_enable;
|
||||
|
||||
private:
|
||||
/*
|
||||
* These methods must be implemented by subclasses
|
||||
*/
|
||||
virtual bool DoCorrupt (Ptr<Packet>) = 0;
|
||||
virtual void DoReset (void) = 0;
|
||||
|
||||
};
|
||||
|
||||
enum ErrorUnit
|
||||
{
|
||||
EU_BIT,
|
||||
EU_BYTE,
|
||||
EU_PKT
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Determine which packets are errored corresponding to an underlying
|
||||
* distribution, rate, and unit.
|
||||
*
|
||||
* This object is used to flag packets as being lost/errored or not.
|
||||
* The two parameters that govern the behavior are the rate (or
|
||||
* equivalently, the mean duration/spacing between errors), and the
|
||||
* unit (which may be per-bit, per-byte, and per-packet).
|
||||
* Users can optionally provide a RandomVariable object; the default
|
||||
* is to use a Uniform(0,1) distribution.
|
||||
|
||||
* Reset() on this model will do nothing
|
||||
*
|
||||
* IsCorrupt() will not modify the packet data buffer
|
||||
*/
|
||||
class RateErrorModel : public ErrorModel
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
RateErrorModel ();
|
||||
virtual ~RateErrorModel ();
|
||||
|
||||
/**
|
||||
* \returns the ErrorUnit being used by the underlying model
|
||||
*/
|
||||
enum ErrorUnit GetUnit (void) const;
|
||||
/**
|
||||
* \param error_unit the ErrorUnit to be used by the underlying model
|
||||
*/
|
||||
void SetUnit (enum ErrorUnit error_unit);
|
||||
|
||||
/**
|
||||
* \returns the error rate being applied by the model
|
||||
*/
|
||||
double GetRate (void) const;
|
||||
/**
|
||||
* \param rate the error rate to be used by the model
|
||||
*/
|
||||
void SetRate (double rate);
|
||||
|
||||
/**
|
||||
* \param ranvar A random variable distribution to generate random variates
|
||||
*/
|
||||
void SetRandomVariable (const RandomVariable &ranvar);
|
||||
|
||||
private:
|
||||
virtual bool DoCorrupt (Ptr<Packet> p);
|
||||
virtual bool DoCorruptPkt (Ptr<Packet> p);
|
||||
virtual bool DoCorruptByte (Ptr<Packet> p);
|
||||
virtual bool DoCorruptBit (Ptr<Packet> p);
|
||||
virtual void DoReset (void);
|
||||
|
||||
enum ErrorUnit m_unit;
|
||||
double m_rate;
|
||||
|
||||
RandomVariable m_ranvar;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Provide a list of Packet uids to corrupt
|
||||
*
|
||||
* This object is used to flag packets as being lost/errored or not.
|
||||
* A note on performance: the list is assumed to be unordered, and
|
||||
* in general, Packet uids received may be unordered. Therefore,
|
||||
* each call to IsCorrupt() will result in a walk of the list with
|
||||
* the present underlying implementation.
|
||||
*
|
||||
* Note also that if one wants to target multiple packets from looking
|
||||
* at an (unerrored) trace file, the act of erroring a given packet may
|
||||
* cause subsequent packet uids to change. For instance, suppose one wants
|
||||
* to error packets 11 and 17 on a given device. It may be that erroring
|
||||
* packet 11 will cause the subsequent uid stream to change and 17 may no
|
||||
* longer correspond to the second packet that one wants to lose. Therefore,
|
||||
* be advised that it might take some trial and error to select the
|
||||
* right uids when multiple are provided.
|
||||
*
|
||||
* Reset() on this model will clear the list
|
||||
*
|
||||
* IsCorrupt() will not modify the packet data buffer
|
||||
*/
|
||||
class ListErrorModel : public ErrorModel
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
ListErrorModel ();
|
||||
virtual ~ListErrorModel ();
|
||||
|
||||
/**
|
||||
* \return a copy of the underlying list
|
||||
*/
|
||||
std::list<uint32_t> GetList (void) const;
|
||||
/**
|
||||
* \param packetlist The list of packet uids to error.
|
||||
*
|
||||
* This method overwrites any previously provided list.
|
||||
*/
|
||||
void SetList (const std::list<uint32_t> &packetlist);
|
||||
|
||||
private:
|
||||
virtual bool DoCorrupt (Ptr<Packet> p);
|
||||
virtual void DoReset (void);
|
||||
|
||||
typedef std::list<uint32_t> PacketList;
|
||||
typedef std::list<uint32_t>::const_iterator PacketListCI;
|
||||
|
||||
PacketList m_packetList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace ns3
|
||||
#endif
|
||||
@@ -199,7 +199,7 @@ class PacketMetadataTest : public Test {
|
||||
public:
|
||||
PacketMetadataTest ();
|
||||
virtual ~PacketMetadataTest ();
|
||||
bool CheckHistory (Packet p, const char *file, int line, uint32_t n, ...);
|
||||
bool CheckHistory (Ptr<Packet> p, const char *file, int line, uint32_t n, ...);
|
||||
virtual bool RunTests (void);
|
||||
private:
|
||||
template <int N>
|
||||
@@ -217,7 +217,7 @@ private:
|
||||
template <int N>
|
||||
void RegisterTrailer (void);
|
||||
void CleanupPrints (void);
|
||||
Packet DoAddHeader (Packet p);
|
||||
Ptr<Packet> DoAddHeader (Ptr<Packet> p);
|
||||
bool Check (const char *file, int line, std::list<int> expected);
|
||||
|
||||
|
||||
@@ -358,7 +358,7 @@ PacketMetadataTest::Check (const char *file, int line, std::list<int> expected)
|
||||
}
|
||||
|
||||
bool
|
||||
PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t n, ...)
|
||||
PacketMetadataTest::CheckHistory (Ptr<Packet> p, const char *file, int line, uint32_t n, ...)
|
||||
{
|
||||
m_headerError = false;
|
||||
m_trailerError = false;
|
||||
@@ -373,7 +373,7 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
|
||||
va_end (ap);
|
||||
|
||||
m_printer.PrintForward ();
|
||||
p.Print (Failure (), m_printer);
|
||||
p->Print (Failure (), m_printer);
|
||||
bool ok = Check (file, line, expected);
|
||||
CleanupPrints ();
|
||||
if (!ok)
|
||||
@@ -382,7 +382,7 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
|
||||
}
|
||||
|
||||
m_printer.PrintBackward ();
|
||||
p.Print (Failure (), m_printer);
|
||||
p->Print (Failure (), m_printer);
|
||||
expected.reverse ();
|
||||
ok = Check (file, line, expected);
|
||||
CleanupPrints ();
|
||||
@@ -393,25 +393,25 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
|
||||
{ \
|
||||
HistoryHeader<n> header; \
|
||||
RegisterHeader<n> (); \
|
||||
p.AddHeader (header); \
|
||||
p->AddHeader (header); \
|
||||
}
|
||||
#define ADD_TRAILER(p, n) \
|
||||
{ \
|
||||
HistoryTrailer<n> trailer; \
|
||||
RegisterTrailer<n> (); \
|
||||
p.AddTrailer (trailer); \
|
||||
p->AddTrailer (trailer); \
|
||||
}
|
||||
#define REM_HEADER(p, n) \
|
||||
{ \
|
||||
HistoryHeader<n> header; \
|
||||
RegisterHeader<n> (); \
|
||||
p.RemoveHeader (header); \
|
||||
p->RemoveHeader (header); \
|
||||
}
|
||||
#define REM_TRAILER(p, n) \
|
||||
{ \
|
||||
HistoryTrailer<n> trailer; \
|
||||
RegisterTrailer<n> (); \
|
||||
p.RemoveTrailer (trailer); \
|
||||
p->RemoveTrailer (trailer); \
|
||||
}
|
||||
#define CHECK_HISTORY(p, ...) \
|
||||
{ \
|
||||
@@ -421,9 +421,9 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
|
||||
ok = false; \
|
||||
} \
|
||||
Buffer buffer; \
|
||||
buffer = p.Serialize (); \
|
||||
Packet otherPacket; \
|
||||
otherPacket.Deserialize (buffer); \
|
||||
buffer = p->Serialize (); \
|
||||
Ptr<Packet> otherPacket = Create<Packet> ();\
|
||||
otherPacket->Deserialize (buffer); \
|
||||
if (!CheckHistory (otherPacket, __FILE__, \
|
||||
__LINE__, __VA_ARGS__)) \
|
||||
{ \
|
||||
@@ -432,8 +432,8 @@ PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t
|
||||
}
|
||||
|
||||
|
||||
Packet
|
||||
PacketMetadataTest::DoAddHeader (Packet p)
|
||||
Ptr<Packet>
|
||||
PacketMetadataTest::DoAddHeader (Ptr<Packet> p)
|
||||
{
|
||||
ADD_HEADER (p, 10);
|
||||
return p;
|
||||
@@ -446,14 +446,14 @@ PacketMetadataTest::RunTests (void)
|
||||
|
||||
PacketMetadata::Enable ();
|
||||
|
||||
Packet p = Packet (0);
|
||||
Packet p1 = Packet (0);
|
||||
Ptr<Packet> p = Create<Packet> (0);
|
||||
Ptr<Packet> p1 = Create<Packet> (0);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_TRAILER (p, 100);
|
||||
CHECK_HISTORY (p, 2, 10, 100);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 1);
|
||||
ADD_HEADER (p, 2);
|
||||
ADD_HEADER (p, 3);
|
||||
@@ -466,7 +466,7 @@ PacketMetadataTest::RunTests (void)
|
||||
CHECK_HISTORY (p, 6,
|
||||
6, 5, 3, 2, 1, 10);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 1);
|
||||
ADD_HEADER (p, 2);
|
||||
ADD_HEADER (p, 3);
|
||||
@@ -474,7 +474,7 @@ PacketMetadataTest::RunTests (void)
|
||||
CHECK_HISTORY (p, 3,
|
||||
2, 1, 10);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 1);
|
||||
ADD_HEADER (p, 2);
|
||||
ADD_HEADER (p, 3);
|
||||
@@ -483,7 +483,7 @@ PacketMetadataTest::RunTests (void)
|
||||
CHECK_HISTORY (p, 2,
|
||||
1, 10);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 1);
|
||||
ADD_HEADER (p, 2);
|
||||
ADD_HEADER (p, 3);
|
||||
@@ -492,11 +492,11 @@ PacketMetadataTest::RunTests (void)
|
||||
REM_HEADER (p, 1);
|
||||
CHECK_HISTORY (p, 1, 10);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 1);
|
||||
ADD_HEADER (p, 2);
|
||||
ADD_HEADER (p, 3);
|
||||
p1 = p;
|
||||
p1 = p->Copy ();
|
||||
REM_HEADER (p1, 3);
|
||||
REM_HEADER (p1, 2);
|
||||
REM_HEADER (p1, 1);
|
||||
@@ -524,88 +524,88 @@ PacketMetadataTest::RunTests (void)
|
||||
REM_TRAILER (p, 5);
|
||||
CHECK_HISTORY (p, 5,
|
||||
3, 2, 1, 10, 4);
|
||||
p1 = p;
|
||||
p1 = p->Copy ();
|
||||
REM_TRAILER (p, 4);
|
||||
CHECK_HISTORY (p, 4,
|
||||
3, 2, 1, 10);
|
||||
CHECK_HISTORY (p1, 5,
|
||||
3, 2, 1, 10, 4);
|
||||
p1.RemoveAtStart (3);
|
||||
p1->RemoveAtStart (3);
|
||||
CHECK_HISTORY (p1, 4,
|
||||
2, 1, 10, 4);
|
||||
p1.RemoveAtStart (1);
|
||||
p1->RemoveAtStart (1);
|
||||
CHECK_HISTORY (p1, 4,
|
||||
1, 1, 10, 4);
|
||||
p1.RemoveAtStart (1);
|
||||
p1->RemoveAtStart (1);
|
||||
CHECK_HISTORY (p1, 3,
|
||||
1, 10, 4);
|
||||
p1.RemoveAtEnd (4);
|
||||
p1->RemoveAtEnd (4);
|
||||
CHECK_HISTORY (p1, 2,
|
||||
1, 10);
|
||||
p1.RemoveAtStart (1);
|
||||
p1->RemoveAtStart (1);
|
||||
CHECK_HISTORY (p1, 1, 10);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 8);
|
||||
ADD_TRAILER (p, 8);
|
||||
ADD_TRAILER (p, 8);
|
||||
p.RemoveAtStart (8+10+8);
|
||||
p->RemoveAtStart (8+10+8);
|
||||
CHECK_HISTORY (p, 1, 8);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 10);
|
||||
ADD_HEADER (p, 8);
|
||||
ADD_TRAILER (p, 6);
|
||||
ADD_TRAILER (p, 7);
|
||||
ADD_TRAILER (p, 9);
|
||||
p.RemoveAtStart (5);
|
||||
p.RemoveAtEnd (12);
|
||||
p->RemoveAtStart (5);
|
||||
p->RemoveAtEnd (12);
|
||||
CHECK_HISTORY (p, 5, 3, 10, 10, 6, 4);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 10);
|
||||
ADD_TRAILER (p, 6);
|
||||
p.RemoveAtEnd (18);
|
||||
p->RemoveAtEnd (18);
|
||||
ADD_TRAILER (p, 5);
|
||||
ADD_HEADER (p, 3);
|
||||
CHECK_HISTORY (p, 3, 3, 8, 5);
|
||||
p.RemoveAtStart (12);
|
||||
p->RemoveAtStart (12);
|
||||
CHECK_HISTORY (p, 1, 4);
|
||||
p.RemoveAtEnd (2);
|
||||
p->RemoveAtEnd (2);
|
||||
CHECK_HISTORY (p, 1, 2);
|
||||
ADD_HEADER (p, 10);
|
||||
CHECK_HISTORY (p, 2, 10, 2);
|
||||
p.RemoveAtEnd (5);
|
||||
p->RemoveAtEnd (5);
|
||||
CHECK_HISTORY (p, 1, 7);
|
||||
|
||||
Packet p2 = Packet (0);
|
||||
Packet p3 = Packet (0);
|
||||
Ptr<Packet> p2 = Create<Packet> (0);
|
||||
Ptr<Packet> p3 = Create<Packet> (0);
|
||||
|
||||
p = Packet (40);
|
||||
p = Create<Packet> (40);
|
||||
ADD_HEADER (p, 5);
|
||||
ADD_HEADER (p, 8);
|
||||
CHECK_HISTORY (p, 3, 8, 5, 40);
|
||||
p1 = p.CreateFragment (0, 5);
|
||||
p2 = p.CreateFragment (5, 5);
|
||||
p3 = p.CreateFragment (10, 43);
|
||||
p1 = p->CreateFragment (0, 5);
|
||||
p2 = p->CreateFragment (5, 5);
|
||||
p3 = p->CreateFragment (10, 43);
|
||||
CHECK_HISTORY (p1, 1, 5);
|
||||
CHECK_HISTORY (p2, 2, 3, 2);
|
||||
CHECK_HISTORY (p3, 2, 3, 40);
|
||||
p1.AddAtEnd (p2);
|
||||
p1->AddAtEnd (p2);
|
||||
CHECK_HISTORY (p1, 2, 8, 2);
|
||||
CHECK_HISTORY (p2, 2, 3, 2);
|
||||
p1.AddAtEnd (p3);
|
||||
p1->AddAtEnd (p3);
|
||||
CHECK_HISTORY (p1, 3, 8, 5, 40);
|
||||
CHECK_HISTORY (p2, 2, 3, 2);
|
||||
CHECK_HISTORY (p3, 2, 3, 40);
|
||||
p1 = p.CreateFragment (0, 5);
|
||||
p1 = p->CreateFragment (0, 5);
|
||||
CHECK_HISTORY (p1, 1, 5);
|
||||
|
||||
p3 = Packet (50);
|
||||
p3 = Create<Packet> (50);
|
||||
ADD_HEADER (p3, 8);
|
||||
CHECK_HISTORY (p3, 2, 8, 50);
|
||||
CHECK_HISTORY (p1, 1, 5);
|
||||
p1.AddAtEnd (p3);
|
||||
p1->AddAtEnd (p3);
|
||||
CHECK_HISTORY (p1, 3, 5, 8, 50);
|
||||
ADD_HEADER (p1, 5);
|
||||
CHECK_HISTORY (p1, 4, 5, 5, 8, 50);
|
||||
@@ -613,71 +613,71 @@ PacketMetadataTest::RunTests (void)
|
||||
CHECK_HISTORY (p1, 5, 5, 5, 8, 50, 2);
|
||||
REM_HEADER (p1, 5);
|
||||
CHECK_HISTORY (p1, 4, 5, 8, 50, 2);
|
||||
p1.RemoveAtEnd (60);
|
||||
p1->RemoveAtEnd (60);
|
||||
CHECK_HISTORY (p1, 1, 5);
|
||||
p1.AddAtEnd (p2);
|
||||
p1->AddAtEnd (p2);
|
||||
CHECK_HISTORY (p1, 2, 8, 2);
|
||||
CHECK_HISTORY (p2, 2, 3, 2);
|
||||
|
||||
p3 = Packet (40);
|
||||
p3 = Create<Packet> (40);
|
||||
ADD_HEADER (p3, 5);
|
||||
ADD_HEADER (p3, 5);
|
||||
CHECK_HISTORY (p3, 3, 5, 5, 40);
|
||||
p1 = p3.CreateFragment (0, 5);
|
||||
p2 = p3.CreateFragment (5, 5);
|
||||
p1 = p3->CreateFragment (0, 5);
|
||||
p2 = p3->CreateFragment (5, 5);
|
||||
CHECK_HISTORY (p1, 1, 5);
|
||||
CHECK_HISTORY (p2, 1, 5);
|
||||
p1.AddAtEnd (p2);
|
||||
p1->AddAtEnd (p2);
|
||||
CHECK_HISTORY (p1, 2, 5, 5);
|
||||
|
||||
p = Packet (0);
|
||||
p = Create<Packet> (0);
|
||||
CHECK_HISTORY (p, 0);
|
||||
|
||||
p3 = Packet (0);
|
||||
p3 = Create<Packet> (0);
|
||||
ADD_HEADER (p3, 5);
|
||||
ADD_HEADER (p3, 5);
|
||||
CHECK_HISTORY (p3, 2, 5, 5);
|
||||
p1 = p3.CreateFragment (0, 4);
|
||||
p2 = p3.CreateFragment (9, 1);
|
||||
p1 = p3->CreateFragment (0, 4);
|
||||
p2 = p3->CreateFragment (9, 1);
|
||||
CHECK_HISTORY (p1, 1, 4);
|
||||
CHECK_HISTORY (p2, 1, 1);
|
||||
p1.AddAtEnd (p2);
|
||||
p1->AddAtEnd (p2);
|
||||
CHECK_HISTORY (p1, 2, 4, 1);
|
||||
|
||||
|
||||
p = Packet (2000);
|
||||
p = Create<Packet> (2000);
|
||||
CHECK_HISTORY (p, 1, 2000);
|
||||
|
||||
p = Packet ();
|
||||
p = Create<Packet> ();
|
||||
ADD_TRAILER (p, 10);
|
||||
ADD_HEADER (p, 5);
|
||||
p1 = p.CreateFragment (0, 8);
|
||||
p2 = p.CreateFragment (8, 7);
|
||||
p1.AddAtEnd (p2);
|
||||
p1 = p->CreateFragment (0, 8);
|
||||
p2 = p->CreateFragment (8, 7);
|
||||
p1->AddAtEnd (p2);
|
||||
CHECK_HISTORY (p, 2, 5, 10);
|
||||
|
||||
p = Packet ();
|
||||
p = Create<Packet> ();
|
||||
ADD_TRAILER (p, 10);
|
||||
REM_TRAILER (p, 10);
|
||||
ADD_TRAILER (p, 10);
|
||||
CHECK_HISTORY (p, 1, 10);
|
||||
|
||||
p = Packet ();
|
||||
p = Create<Packet> ();
|
||||
ADD_HEADER (p, 10);
|
||||
REM_HEADER (p, 10);
|
||||
ADD_HEADER (p, 10);
|
||||
CHECK_HISTORY (p, 1, 10);
|
||||
|
||||
p = Packet ();
|
||||
p = Create<Packet> ();
|
||||
ADD_HEADER (p, 10);
|
||||
p = DoAddHeader (p);
|
||||
CHECK_HISTORY (p, 2, 10, 10);
|
||||
|
||||
p = Packet (10);
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 8);
|
||||
ADD_TRAILER (p, 8);
|
||||
ADD_TRAILER (p, 8);
|
||||
p.RemoveAtStart (8+10+8);
|
||||
p->RemoveAtStart (8+10+8);
|
||||
CHECK_HISTORY (p, 1, 8);
|
||||
|
||||
return ok;
|
||||
|
||||
@@ -31,6 +31,7 @@ NS_LOG_COMPONENT_DEFINE ("PacketMetadata");
|
||||
namespace ns3 {
|
||||
|
||||
bool PacketMetadata::m_enable = false;
|
||||
bool PacketMetadata::m_metadataSkipped = false;
|
||||
uint32_t PacketMetadata::m_maxSize = 0;
|
||||
uint16_t PacketMetadata::m_chunkUid = 0;
|
||||
PacketMetadata::DataFreeList PacketMetadata::m_freeList;
|
||||
@@ -42,11 +43,19 @@ PacketMetadata::DataFreeList::~DataFreeList ()
|
||||
{
|
||||
PacketMetadata::Deallocate (*i);
|
||||
}
|
||||
PacketMetadata::m_enable = false;
|
||||
}
|
||||
|
||||
void
|
||||
PacketMetadata::Enable (void)
|
||||
{
|
||||
NS_ASSERT_MSG (!m_metadataSkipped,
|
||||
"Error: attempting to enable the packet metadata "
|
||||
"subsystem too late in the simulation, which is not allowed.\n"
|
||||
"A common cause for this problem is to enable ASCII tracing "
|
||||
"after sending any packets. One way to fix this problem is "
|
||||
"to call ns3::PacketMetadata::Enable () near the beginning of"
|
||||
" the program, before any packets are sent.");
|
||||
m_enable = true;
|
||||
}
|
||||
|
||||
@@ -635,6 +644,11 @@ PacketMetadata::Create (uint32_t size)
|
||||
void
|
||||
PacketMetadata::Recycle (struct PacketMetadata::Data *data)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
PacketMetadata::Deallocate (data);
|
||||
return;
|
||||
}
|
||||
NS_LOG_LOGIC ("recycle size="<<data->m_size<<", list="<<m_freeList.size ());
|
||||
NS_ASSERT (data->m_count == 0);
|
||||
if (m_freeList.size () > 1000 ||
|
||||
@@ -686,8 +700,11 @@ PacketMetadata::DoAddHeader (uint32_t uid, uint32_t size)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
NS_LOG_PARAMS ("(uid=" << uid << ", size=" << size << ")");
|
||||
|
||||
struct PacketMetadata::SmallItem item;
|
||||
item.next = m_head;
|
||||
item.prev = 0xffff;
|
||||
@@ -703,8 +720,10 @@ PacketMetadata::DoRemoveHeader (uint32_t uid, uint32_t size)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
NS_LOG_PARAMS ("(uid=" << uid << ", size=" << size << ")");
|
||||
struct PacketMetadata::SmallItem item;
|
||||
struct PacketMetadata::ExtraItem extraItem;
|
||||
uint32_t read = ReadItems (m_head, &item, &extraItem);
|
||||
@@ -738,6 +757,7 @@ PacketMetadata::DoAddTrailer (uint32_t uid, uint32_t size)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
struct PacketMetadata::SmallItem item;
|
||||
@@ -755,6 +775,7 @@ PacketMetadata::DoRemoveTrailer (uint32_t uid, uint32_t size)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
struct PacketMetadata::SmallItem item;
|
||||
@@ -790,6 +811,7 @@ PacketMetadata::AddAtEnd (PacketMetadata const&o)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
if (m_tail == 0xffff)
|
||||
@@ -846,6 +868,7 @@ PacketMetadata::AddPaddingAtEnd (uint32_t end)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -854,6 +877,7 @@ PacketMetadata::RemoveAtStart (uint32_t start)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
NS_ASSERT (m_data != 0);
|
||||
@@ -910,6 +934,7 @@ PacketMetadata::RemoveAtEnd (uint32_t end)
|
||||
{
|
||||
if (!m_enable)
|
||||
{
|
||||
m_metadataSkipped = true;
|
||||
return;
|
||||
}
|
||||
NS_ASSERT (m_data != 0);
|
||||
|
||||
@@ -190,7 +190,9 @@ private:
|
||||
public:
|
||||
~DataFreeList ();
|
||||
};
|
||||
|
||||
|
||||
friend DataFreeList::~DataFreeList ();
|
||||
|
||||
PacketMetadata ();
|
||||
void DoAddHeader (uint32_t uid, uint32_t size);
|
||||
void DoRemoveHeader (uint32_t uid, uint32_t size);
|
||||
@@ -234,6 +236,12 @@ private:
|
||||
|
||||
static DataFreeList m_freeList;
|
||||
static bool m_enable;
|
||||
|
||||
// set to true when adding metadata to a packet is skipped because
|
||||
// m_enable is false; used to detect enabling of metadata in the
|
||||
// middle of a simulation, which isn't allowed.
|
||||
static bool m_metadataSkipped;
|
||||
|
||||
static uint32_t m_maxSize;
|
||||
static uint16_t m_chunkUid;
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ PacketPrinter::PrintChunk (uint32_t chunkUid,
|
||||
// if the over did not override this type of chunk,
|
||||
// we print something by default.
|
||||
std::string name = ChunkRegistry::GetName (chunkUid, instance);
|
||||
os << name;
|
||||
os << name << " ";
|
||||
ChunkRegistry::Print (chunkUid, instance, os);
|
||||
}
|
||||
void
|
||||
|
||||
@@ -134,7 +134,7 @@ private:
|
||||
struct Printer
|
||||
{
|
||||
uint32_t m_chunkUid;
|
||||
Ptr<CallbackImplBase> m_printer;
|
||||
CallbackBase m_printer;
|
||||
Callback<void,std::ostream &,uint32_t,uint32_t,std::string &,
|
||||
struct PacketPrinter::FragmentInformation> m_fragmentPrinter;
|
||||
};
|
||||
@@ -158,7 +158,7 @@ PacketPrinter::SetHeaderPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,
|
||||
{
|
||||
Printer p;
|
||||
p.m_chunkUid = T::GetUid ();
|
||||
p.m_printer = printer.GetImpl ();
|
||||
p.m_printer = printer;
|
||||
p.m_fragmentPrinter = fragmentPrinter;
|
||||
m_printerList.push_back (p);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ PacketPrinter::SetTrailerPrinter (Callback<void,std::ostream &,uint32_t,uint32_t
|
||||
{
|
||||
Printer p;
|
||||
p.m_chunkUid = T::GetUid ();
|
||||
p.m_printer = printer.GetImpl ();
|
||||
p.m_printer = printer;
|
||||
p.m_fragmentPrinter = fragmentPrinter;
|
||||
m_printerList.push_back (p);
|
||||
}
|
||||
|
||||
+71
-18
@@ -26,22 +26,72 @@ namespace ns3 {
|
||||
|
||||
uint32_t Packet::m_globalUid = 0;
|
||||
|
||||
void
|
||||
Packet::Ref (void) const
|
||||
{
|
||||
m_refCount++;
|
||||
}
|
||||
void
|
||||
Packet::Unref (void) const
|
||||
{
|
||||
m_refCount--;
|
||||
if (m_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<Packet>
|
||||
Packet::Copy (void) const
|
||||
{
|
||||
// we need to invoke the copy constructor directly
|
||||
// rather than calling Create because the copy constructor
|
||||
// is private.
|
||||
return Ptr<Packet> (new Packet (*this), false);
|
||||
}
|
||||
|
||||
Packet::Packet ()
|
||||
: m_buffer (),
|
||||
m_metadata (m_globalUid, 0)
|
||||
m_tags (),
|
||||
m_metadata (m_globalUid, 0),
|
||||
m_refCount (1)
|
||||
{
|
||||
m_globalUid++;
|
||||
}
|
||||
|
||||
Packet::Packet (const Packet &o)
|
||||
: m_buffer (o.m_buffer),
|
||||
m_tags (o.m_tags),
|
||||
m_metadata (o.m_metadata),
|
||||
m_refCount (1)
|
||||
{}
|
||||
|
||||
Packet &
|
||||
Packet::operator = (const Packet &o)
|
||||
{
|
||||
if (this == &o)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
m_buffer = o.m_buffer;
|
||||
m_tags = o.m_tags;
|
||||
m_metadata = o.m_metadata;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet::Packet (uint32_t size)
|
||||
: m_buffer (size),
|
||||
m_metadata (m_globalUid, size)
|
||||
m_tags (),
|
||||
m_metadata (m_globalUid, size),
|
||||
m_refCount (1)
|
||||
{
|
||||
m_globalUid++;
|
||||
}
|
||||
Packet::Packet (uint8_t const*buffer, uint32_t size)
|
||||
: m_buffer (),
|
||||
m_metadata (m_globalUid, size)
|
||||
m_tags (),
|
||||
m_metadata (m_globalUid, size),
|
||||
m_refCount (1)
|
||||
{
|
||||
m_globalUid++;
|
||||
m_buffer.AddAtStart (size);
|
||||
@@ -52,17 +102,20 @@ Packet::Packet (uint8_t const*buffer, uint32_t size)
|
||||
Packet::Packet (Buffer buffer, Tags tags, PacketMetadata metadata)
|
||||
: m_buffer (buffer),
|
||||
m_tags (tags),
|
||||
m_metadata (metadata)
|
||||
m_metadata (metadata),
|
||||
m_refCount (1)
|
||||
{}
|
||||
|
||||
Packet
|
||||
Ptr<Packet>
|
||||
Packet::CreateFragment (uint32_t start, uint32_t length) const
|
||||
{
|
||||
Buffer buffer = m_buffer.CreateFragment (start, length);
|
||||
NS_ASSERT (m_buffer.GetSize () >= start + length);
|
||||
uint32_t end = m_buffer.GetSize () - (start + length);
|
||||
PacketMetadata metadata = m_metadata.CreateFragment (start, end);
|
||||
return Packet (buffer, m_tags, metadata);
|
||||
// again, call the constructor directly rather than
|
||||
// through Create because it is private.
|
||||
return Ptr<Packet> (new Packet (buffer, m_tags, metadata), false);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -72,9 +125,9 @@ Packet::GetSize (void) const
|
||||
}
|
||||
|
||||
void
|
||||
Packet::AddAtEnd (Packet packet)
|
||||
Packet::AddAtEnd (Ptr<const Packet> packet)
|
||||
{
|
||||
Buffer src = packet.m_buffer.CreateFullCopy ();
|
||||
Buffer src = packet->m_buffer.CreateFullCopy ();
|
||||
Buffer dst = m_buffer.CreateFullCopy ();
|
||||
|
||||
dst.AddAtEnd (src.GetSize ());
|
||||
@@ -86,7 +139,7 @@ Packet::AddAtEnd (Packet packet)
|
||||
* XXX: we might need to merge the tag list of the
|
||||
* other packet into the current packet.
|
||||
*/
|
||||
m_metadata.AddAtEnd (packet.m_metadata);
|
||||
m_metadata.AddAtEnd (packet->m_metadata);
|
||||
}
|
||||
void
|
||||
Packet::AddPaddingAtEnd (uint32_t size)
|
||||
@@ -233,20 +286,20 @@ PacketTest::RunTests (void)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
Packet pkt1 (reinterpret_cast<const uint8_t*> ("hello"), 5);
|
||||
Packet pkt2 (reinterpret_cast<const uint8_t*> (" world"), 6);
|
||||
Packet packet;
|
||||
packet.AddAtEnd (pkt1);
|
||||
packet.AddAtEnd (pkt2);
|
||||
Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
|
||||
Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
|
||||
Ptr<Packet> packet = Create<Packet> ();
|
||||
packet->AddAtEnd (pkt1);
|
||||
packet->AddAtEnd (pkt2);
|
||||
|
||||
if (packet.GetSize () != 11)
|
||||
if (packet->GetSize () != 11)
|
||||
{
|
||||
Failure () << "expected size 11, got " << packet.GetSize () << std::endl;
|
||||
Failure () << "expected size 11, got " << packet->GetSize () << std::endl;
|
||||
ok = false;
|
||||
}
|
||||
|
||||
std::string msg = std::string (reinterpret_cast<const char *>(packet.PeekData ()),
|
||||
packet.GetSize ());
|
||||
std::string msg = std::string (reinterpret_cast<const char *>(packet->PeekData ()),
|
||||
packet->GetSize ());
|
||||
if (msg != "hello world")
|
||||
{
|
||||
Failure () << "expected 'hello world', got '" << msg << "'" << std::endl;
|
||||
|
||||
+37
-5
@@ -30,6 +30,7 @@
|
||||
#include "tag.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/ptr.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -74,6 +75,11 @@ class PacketPrinter;
|
||||
*/
|
||||
class Packet {
|
||||
public:
|
||||
void Ref (void) const;
|
||||
void Unref (void) const;
|
||||
|
||||
Ptr<Packet> Copy (void) const;
|
||||
|
||||
/**
|
||||
* Create an empty packet with a new uid (as returned
|
||||
* by getUid).
|
||||
@@ -107,7 +113,7 @@ public:
|
||||
* \param length length of fragment to create
|
||||
* \returns a fragment of the original packet
|
||||
*/
|
||||
Packet CreateFragment (uint32_t start, uint32_t length) const;
|
||||
Ptr<Packet> CreateFragment (uint32_t start, uint32_t length) const;
|
||||
/**
|
||||
* \returns the size in bytes of the packet (including the zero-filled
|
||||
* initial payload)
|
||||
@@ -152,15 +158,27 @@ public:
|
||||
template <typename T>
|
||||
uint32_t RemoveTrailer (T &trailer);
|
||||
/**
|
||||
* \param tag a pointer to the tag to attach to this packet.
|
||||
*
|
||||
* 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. The copy constructor of the
|
||||
* tag is invoked to copy it into the tag buffer.
|
||||
*
|
||||
* \param tag a pointer to the tag to attach to this packet.
|
||||
* Note that adding a tag is a const operation which is pretty
|
||||
* un-intuitive. The rationale is that the content and behavior of
|
||||
* a packet is _not_ changed when a tag is added to a packet: any
|
||||
* code which was not aware of the new tag is going to work just
|
||||
* the same if the new tag is added. The real reason why adding a
|
||||
* tag was made a const operation is to allow a trace sink which gets
|
||||
* a packet to tag the packet, even if the packet is const (and most
|
||||
* trace sources should use const packets because it would be
|
||||
* totally evil to allow a trace sink to modify the content of a
|
||||
* packet).
|
||||
*
|
||||
*/
|
||||
template <typename T>
|
||||
void AddTag (T const &tag);
|
||||
void AddTag (T const &tag) const;
|
||||
/**
|
||||
* Remove a tag from this packet. The data stored internally
|
||||
* for this tag is copied in the input tag if an instance
|
||||
@@ -210,7 +228,7 @@ public:
|
||||
*
|
||||
* \param packet packet to concatenate
|
||||
*/
|
||||
void AddAtEnd (Packet packet);
|
||||
void AddAtEnd (Ptr<const Packet> packet);
|
||||
/**
|
||||
* \param size number of padding bytes to add.
|
||||
*/
|
||||
@@ -244,6 +262,16 @@ public:
|
||||
* A packet is allocated a new uid when it is created
|
||||
* empty or with zero-filled payload.
|
||||
*
|
||||
* Note: This uid is an internal uid and cannot be counted on to
|
||||
* provide an accurate counter of how many "simulated packets" of a
|
||||
* particular protocol are in the system. It is not trivial to make
|
||||
* this uid into such a counter, because of questions such as what
|
||||
* should the uid be when the packet is sent over broadcast media, or
|
||||
* when fragmentation occurs. If a user wants to trace actual packet
|
||||
* counts, he or she should look at e.g. the IP ID field or transport
|
||||
* sequence numbers, or other packet or frame counters at other
|
||||
* protocol layers.
|
||||
*
|
||||
* \returns an integer identifier which uniquely
|
||||
* identifies this packet.
|
||||
*/
|
||||
@@ -322,15 +350,19 @@ public:
|
||||
void Deserialize (Buffer buffer);
|
||||
private:
|
||||
Packet (Buffer buffer, Tags tags, PacketMetadata metadata);
|
||||
Packet (const Packet &o);
|
||||
Packet &operator = (const Packet &o);
|
||||
Buffer m_buffer;
|
||||
Tags m_tags;
|
||||
PacketMetadata m_metadata;
|
||||
mutable uint32_t m_refCount;
|
||||
static uint32_t m_globalUid;
|
||||
};
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, const Packet &packet);
|
||||
|
||||
/**
|
||||
* \ingroup common
|
||||
* \defgroup packetperf Packet Performance
|
||||
* 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
|
||||
@@ -431,7 +463,7 @@ Packet::RemoveTrailer (T &trailer)
|
||||
|
||||
|
||||
template <typename T>
|
||||
void Packet::AddTag (T const& tag)
|
||||
void Packet::AddTag (T const& tag) const
|
||||
{
|
||||
const Tag *parent;
|
||||
// if the following assignment fails, it is because the
|
||||
|
||||
@@ -89,7 +89,7 @@ PcapWriter::WriteHeader (uint32_t network)
|
||||
|
||||
|
||||
void
|
||||
PcapWriter::WritePacket (Packet const packet)
|
||||
PcapWriter::WritePacket (Ptr<const Packet> packet)
|
||||
{
|
||||
if (m_writer != 0)
|
||||
{
|
||||
@@ -98,9 +98,9 @@ PcapWriter::WritePacket (Packet const packet)
|
||||
uint64_t us = current % 1000000;
|
||||
Write32 (s & 0xffffffff);
|
||||
Write32 (us & 0xffffffff);
|
||||
Write32 (packet.GetSize ());
|
||||
Write32 (packet.GetSize ());
|
||||
WriteData (packet.PeekData (), packet.GetSize ());
|
||||
Write32 (packet->GetSize ());
|
||||
Write32 (packet->GetSize ());
|
||||
WriteData (packet->PeekData (), packet->GetSize ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,11 @@
|
||||
|
||||
#include "ns3/callback.h"
|
||||
#include <stdint.h>
|
||||
#include "packet.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \brief Pcap output for Packet logger
|
||||
*
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
/**
|
||||
* \param packet packet to write to output file
|
||||
*/
|
||||
void WritePacket (Packet const packet);
|
||||
void WritePacket (Ptr<const Packet> packet);
|
||||
|
||||
private:
|
||||
void WriteData (uint8_t const*buffer, uint32_t size);
|
||||
|
||||
+4
-4
@@ -30,7 +30,7 @@ struct Tags::TagData *Tags::gFree = 0;
|
||||
uint32_t Tags::gN_free = 0;
|
||||
|
||||
struct Tags::TagData *
|
||||
Tags::AllocData (void)
|
||||
Tags::AllocData (void) const
|
||||
{
|
||||
struct Tags::TagData *retval;
|
||||
if (gFree != 0)
|
||||
@@ -47,7 +47,7 @@ Tags::AllocData (void)
|
||||
}
|
||||
|
||||
void
|
||||
Tags::FreeData (struct TagData *data)
|
||||
Tags::FreeData (struct TagData *data) const
|
||||
{
|
||||
if (gN_free > 1000)
|
||||
{
|
||||
@@ -61,7 +61,7 @@ Tags::FreeData (struct TagData *data)
|
||||
}
|
||||
#else
|
||||
struct Tags::TagData *
|
||||
Tags::AllocData (void)
|
||||
Tags::AllocData (void) const
|
||||
{
|
||||
struct Tags::TagData *retval;
|
||||
retval = new struct Tags::TagData ();
|
||||
@@ -69,7 +69,7 @@ Tags::AllocData (void)
|
||||
}
|
||||
|
||||
void
|
||||
Tags::FreeData (struct TagData *data)
|
||||
Tags::FreeData (struct TagData *data) const
|
||||
{
|
||||
delete data;
|
||||
}
|
||||
|
||||
+14
-6
@@ -44,7 +44,7 @@ public:
|
||||
inline ~Tags ();
|
||||
|
||||
template <typename T>
|
||||
void Add (T const&tag);
|
||||
void Add (T const&tag) const;
|
||||
|
||||
template <typename T>
|
||||
bool Remove (T &tag);
|
||||
@@ -71,8 +71,8 @@ private:
|
||||
};
|
||||
|
||||
bool Remove (uint32_t id);
|
||||
struct Tags::TagData *AllocData (void);
|
||||
void FreeData (struct TagData *data);
|
||||
struct Tags::TagData *AllocData (void) const;
|
||||
void FreeData (struct TagData *data) const;
|
||||
|
||||
static struct Tags::TagData *gFree;
|
||||
static uint32_t gN_free;
|
||||
@@ -96,7 +96,7 @@ namespace ns3 {
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
Tags::Add (T const&tag)
|
||||
Tags::Add (T const&tag) const
|
||||
{
|
||||
const Tag *parent;
|
||||
// if the following assignment fails, it is because the
|
||||
@@ -116,7 +116,7 @@ Tags::Add (T const&tag)
|
||||
void *buf = &newStart->m_data;
|
||||
new (buf) T (tag);
|
||||
newStart->m_next = m_next;
|
||||
m_next = newStart;
|
||||
const_cast<Tags *> (this)->m_next = newStart;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -128,7 +128,15 @@ Tags::Remove (T &tag)
|
||||
// input to this function is not a subclass of the Tag class.
|
||||
parent = &tag;
|
||||
NS_ASSERT (sizeof (T) <= Tags::SIZE);
|
||||
return Remove (T::GetUid ());
|
||||
if (Peek (tag))
|
||||
{
|
||||
Remove (T::GetUid ());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -13,6 +13,7 @@ def build(bld):
|
||||
'tag-registry.cc',
|
||||
'pcap-writer.cc',
|
||||
'data-rate.cc',
|
||||
'error-model.cc',
|
||||
]
|
||||
|
||||
headers = bld.create_obj('ns3header')
|
||||
@@ -29,4 +30,5 @@ def build(bld):
|
||||
'packet-metadata.h',
|
||||
'pcap-writer.h',
|
||||
'data-rate.h',
|
||||
'error-model.h',
|
||||
]
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
|
||||
#include "delay-jitter-estimation.h"
|
||||
#include "ns3/tag.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class TimestampTag : public ns3::Tag
|
||||
{
|
||||
public:
|
||||
TimestampTag ();
|
||||
static uint32_t GetUid (void);
|
||||
void Print (std::ostream &os) const;
|
||||
void Serialize (ns3::Buffer::Iterator start) const;
|
||||
uint32_t Deserialize (ns3::Buffer::Iterator start);
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
|
||||
ns3::Time GetTxTime (void) const;
|
||||
private:
|
||||
uint64_t m_creationTime;
|
||||
};
|
||||
|
||||
TimestampTag::TimestampTag ()
|
||||
: m_creationTime (ns3::Simulator::Now ().GetTimeStep ())
|
||||
{}
|
||||
uint32_t
|
||||
TimestampTag::GetUid (void)
|
||||
{
|
||||
static uint32_t uid = ns3::Tag::AllocateUid<TimestampTag> ("mathieu.paper.TimestampTag");
|
||||
return uid;
|
||||
}
|
||||
void
|
||||
TimestampTag::Print (std::ostream &os) const
|
||||
{
|
||||
os << ns3::TimeStep (m_creationTime);
|
||||
}
|
||||
void
|
||||
TimestampTag::Serialize (ns3::Buffer::Iterator start) const
|
||||
{}
|
||||
uint32_t
|
||||
TimestampTag::Deserialize (ns3::Buffer::Iterator start)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint32_t
|
||||
TimestampTag::GetSerializedSize (void) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ns3::Time
|
||||
TimestampTag::GetTxTime (void) const
|
||||
{
|
||||
return ns3::TimeStep (m_creationTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
DelayJitterEstimation::DelayJitterEstimation ()
|
||||
: m_previousRx (Simulator::Now ()),
|
||||
m_previousRxTx (Simulator::Now ()),
|
||||
m_jitter (Seconds (0.0)),
|
||||
m_delay (Seconds (0.0))
|
||||
{}
|
||||
void
|
||||
DelayJitterEstimation::PrepareTx (Ptr<const Packet> packet)
|
||||
{
|
||||
TimestampTag tag;
|
||||
packet->AddTag (tag);
|
||||
}
|
||||
void
|
||||
DelayJitterEstimation::RecordRx (Ptr<const Packet> packet)
|
||||
{
|
||||
TimestampTag tag;
|
||||
bool found;
|
||||
found = packet->PeekTag (tag);
|
||||
if (!found)
|
||||
{
|
||||
return;
|
||||
}
|
||||
tag.GetTxTime ();
|
||||
|
||||
Time delta = (Simulator::Now () - m_previousRx) - (tag.GetTxTime () - m_previousRxTx);
|
||||
m_jitter += (Abs (delta) - m_jitter ) / Scalar (16.0);
|
||||
m_previousRx = Simulator::Now ();
|
||||
m_previousRxTx = tag.GetTxTime ();
|
||||
m_delay = Simulator::Now () - tag.GetTxTime ();
|
||||
}
|
||||
|
||||
Time
|
||||
DelayJitterEstimation::GetLastDelay (void) const
|
||||
{
|
||||
return m_delay;
|
||||
}
|
||||
Time
|
||||
DelayJitterEstimation::GetLastJitter (void) const
|
||||
{
|
||||
return m_jitter;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef DELAY_JITTER_ESTIMATION_H
|
||||
#define DELAY_JITTER_ESTIMATION_H
|
||||
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/packet.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief quick and diry delay and jitter estimation
|
||||
*
|
||||
*/
|
||||
class DelayJitterEstimation
|
||||
{
|
||||
public:
|
||||
DelayJitterEstimation ();
|
||||
|
||||
/**
|
||||
* \param packet the packet to send over a wire
|
||||
*
|
||||
* This method should be invoked once on each packet to
|
||||
* record within the packet the tx time which is used upon
|
||||
* packet reception to calculate the delay and jitter. The
|
||||
* tx time is stored in the packet as an ns3::Tag which means
|
||||
* that it does not use any network ressources and is not
|
||||
* taken into account in transmission delay calculations.
|
||||
*/
|
||||
static void PrepareTx (Ptr<const Packet> packet);
|
||||
/**
|
||||
* \param packet the packet received
|
||||
*
|
||||
* Invoke this method to update the delay and jitter calculations
|
||||
* After a call to this method, \ref GetLastDelay and \ref GetLastJitter
|
||||
* will return an updated delay and jitter.
|
||||
*/
|
||||
void RecordRx (Ptr<const Packet> packet);
|
||||
|
||||
/**
|
||||
* \returns the updated delay.
|
||||
*/
|
||||
Time GetLastDelay (void) const;
|
||||
/**
|
||||
* The jitter is calculated using the RFC 1889 (RTP) jitter
|
||||
* definition.
|
||||
*
|
||||
* \returns the updated jitter.
|
||||
*/
|
||||
Time GetLastJitter (void) const;
|
||||
|
||||
private:
|
||||
Time m_previousRx;
|
||||
Time m_previousRxTx;
|
||||
Time m_jitter;
|
||||
Time m_delay;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* DELAY_JITTER_ESTIMATION_H */
|
||||
@@ -0,0 +1,153 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INESC Porto
|
||||
*
|
||||
* 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: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
|
||||
*/
|
||||
#include "event-garbage-collector.h"
|
||||
|
||||
#define CLEANUP_CHUNK_MIN_SIZE 8
|
||||
#define CLEANUP_CHUNK_MAX_SIZE 128
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
EventGarbageCollector::EventGarbageCollector () :
|
||||
m_nextCleanupSize (CLEANUP_CHUNK_MIN_SIZE)
|
||||
{}
|
||||
|
||||
void
|
||||
EventGarbageCollector::Track (EventId event)
|
||||
{
|
||||
m_events.insert (event);
|
||||
if (m_events.size () >= m_nextCleanupSize)
|
||||
Cleanup ();
|
||||
}
|
||||
|
||||
void
|
||||
EventGarbageCollector::Grow ()
|
||||
{
|
||||
m_nextCleanupSize += (m_nextCleanupSize < CLEANUP_CHUNK_MAX_SIZE?
|
||||
m_nextCleanupSize : CLEANUP_CHUNK_MAX_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
EventGarbageCollector::Shrink ()
|
||||
{
|
||||
while (m_nextCleanupSize > m_events.size ())
|
||||
m_nextCleanupSize >>= 1;
|
||||
Grow ();
|
||||
}
|
||||
|
||||
// Called when a new event was added and the cleanup limit was exceeded in consequence.
|
||||
void
|
||||
EventGarbageCollector::Cleanup ()
|
||||
{
|
||||
for (EventList::iterator iter = m_events.begin (); iter != m_events.end ();)
|
||||
{
|
||||
if ((*iter).IsExpired ())
|
||||
{
|
||||
m_events.erase (iter++);
|
||||
}
|
||||
else
|
||||
break; // EventIds are sorted by timestamp => further events are not expired for sure
|
||||
}
|
||||
|
||||
// If after cleanup we are still over the limit, increase the limit.
|
||||
if (m_events.size () >= m_nextCleanupSize)
|
||||
Grow ();
|
||||
else
|
||||
Shrink ();
|
||||
}
|
||||
|
||||
|
||||
EventGarbageCollector::~EventGarbageCollector ()
|
||||
{
|
||||
for (EventList::iterator event = m_events.begin ();
|
||||
event != m_events.end (); event++)
|
||||
{
|
||||
Simulator::Cancel (*event);
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
|
||||
|
||||
#ifdef RUN_SELF_TESTS
|
||||
|
||||
#include "ns3/test.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class EventGarbageCollectorTests : public Test
|
||||
{
|
||||
int m_counter;
|
||||
EventGarbageCollector *m_events;
|
||||
|
||||
void EventGarbageCollectorCallback ();
|
||||
|
||||
public:
|
||||
|
||||
EventGarbageCollectorTests ();
|
||||
virtual ~EventGarbageCollectorTests ();
|
||||
virtual bool RunTests (void);
|
||||
};
|
||||
|
||||
EventGarbageCollectorTests::EventGarbageCollectorTests ()
|
||||
: Test ("EventGarbageCollector"), m_counter (0), m_events (0)
|
||||
{}
|
||||
|
||||
EventGarbageCollectorTests::~EventGarbageCollectorTests ()
|
||||
{}
|
||||
|
||||
void
|
||||
EventGarbageCollectorTests::EventGarbageCollectorCallback ()
|
||||
{
|
||||
m_counter++;
|
||||
if (m_counter == 50)
|
||||
{
|
||||
// this should cause the remaining (50) events to be cancelled
|
||||
delete m_events;
|
||||
m_events = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventGarbageCollectorTests::RunTests (void)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
m_events = new EventGarbageCollector ();
|
||||
|
||||
for (int n = 0; n < 100; n++)
|
||||
{
|
||||
m_events->Track (Simulator::Schedule
|
||||
(Simulator::Now (),
|
||||
&EventGarbageCollectorTests::EventGarbageCollectorCallback,
|
||||
this));
|
||||
}
|
||||
Simulator::Run ();
|
||||
NS_TEST_ASSERT_EQUAL (m_events, 0);
|
||||
NS_TEST_ASSERT_EQUAL (m_counter, 50);
|
||||
return result;
|
||||
}
|
||||
|
||||
static EventGarbageCollectorTests g_eventCollectorTests;
|
||||
|
||||
};
|
||||
|
||||
#endif /* RUN_SELF_TESTS */
|
||||
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INESC Porto
|
||||
*
|
||||
* 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: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
|
||||
*/
|
||||
#ifndef EVENT_GARBAGE_COLLECTOR_H
|
||||
#define EVENT_GARBAGE_COLLECTOR_H
|
||||
|
||||
#include <set>
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief An object that tracks scheduled events and automatically
|
||||
* cancels them when it is destroyed. It is useful in situations
|
||||
* where multiple instances of the same type of event can
|
||||
* simultaneously be scheduled, and when the events should be limited
|
||||
* to the lifetime of a container object.
|
||||
*/
|
||||
class EventGarbageCollector
|
||||
{
|
||||
public:
|
||||
|
||||
EventGarbageCollector ();
|
||||
|
||||
/**
|
||||
* \brief Tracks a new event
|
||||
*/
|
||||
void Track (EventId event);
|
||||
|
||||
~EventGarbageCollector ();
|
||||
|
||||
private:
|
||||
|
||||
struct EventIdLessThanTs
|
||||
{
|
||||
bool operator () (const EventId &a, const EventId &b) const
|
||||
{
|
||||
return (a.GetTs () < b.GetTs ());
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::multiset<EventId, EventIdLessThanTs> EventList;
|
||||
|
||||
EventList::size_type m_nextCleanupSize;
|
||||
EventList m_events;
|
||||
|
||||
void Cleanup ();
|
||||
void Grow ();
|
||||
void Shrink ();
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
#endif /* EVENT_GARBAGE_COLLECTOR_H */
|
||||
@@ -0,0 +1,186 @@
|
||||
/* -*- 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 "gnuplot.h"
|
||||
#include "ns3/assert.h"
|
||||
#include <ostream>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
GnuplotDataset::GnuplotDataset (std::string title)
|
||||
: m_title (title),
|
||||
m_style (LINES),
|
||||
m_errorBars (NONE)
|
||||
{}
|
||||
void
|
||||
GnuplotDataset::SetStyle (enum Style style)
|
||||
{
|
||||
m_style = style;
|
||||
}
|
||||
void
|
||||
GnuplotDataset::SetErrorBars (enum ErrorBars errorBars)
|
||||
{
|
||||
m_errorBars = errorBars;
|
||||
}
|
||||
void
|
||||
GnuplotDataset::Add (double x, double y)
|
||||
{
|
||||
NS_ASSERT (m_errorBars == NONE);
|
||||
struct Data data;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
data.dx = 0.0;
|
||||
data.dy = 0.0;
|
||||
m_dataset.push_back (data);
|
||||
}
|
||||
void
|
||||
GnuplotDataset::Add (double x, double y, double errorDelta)
|
||||
{
|
||||
NS_ASSERT (m_errorBars == X || m_errorBars == Y);
|
||||
struct Data data;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
data.dx = errorDelta;
|
||||
data.dy = errorDelta;
|
||||
m_dataset.push_back (data);
|
||||
}
|
||||
|
||||
Gnuplot::Gnuplot (std::string pngFilename)
|
||||
: m_pngFilename (pngFilename)
|
||||
{}
|
||||
|
||||
Gnuplot::~Gnuplot ()
|
||||
{
|
||||
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end (); i++)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
m_datasets.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot::SetLegend (std::string xLegend, std::string yLegend)
|
||||
{
|
||||
m_xLegend = xLegend;
|
||||
m_yLegend = yLegend;
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot::AddDataset (const GnuplotDataset &dataset)
|
||||
{
|
||||
m_datasets.push_back (new GnuplotDataset (dataset));
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot::GenerateOutput (std::ostream &os)
|
||||
{
|
||||
os << "set terminal png" << std::endl;
|
||||
os << "set output '" << m_pngFilename << "'" << std::endl;
|
||||
os << "set xlabel '" << m_xLegend << "'" << std::endl;
|
||||
os << "set ylabel '" << m_yLegend << "'" << std::endl;
|
||||
os << "plot ";
|
||||
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end ();)
|
||||
{
|
||||
os << "'-' title '" << (*i)->m_title << "'";
|
||||
switch ((*i)->m_style) {
|
||||
case GnuplotDataset::LINES:
|
||||
os << " with lines";
|
||||
break;
|
||||
case GnuplotDataset::POINTS:
|
||||
switch ((*i)->m_errorBars)
|
||||
{
|
||||
case GnuplotDataset::NONE:
|
||||
os << " with points";
|
||||
break;
|
||||
case GnuplotDataset::X:
|
||||
os << " with xerrorbars";
|
||||
break;
|
||||
case GnuplotDataset::Y:
|
||||
os << " with yerrorbars";
|
||||
break;
|
||||
case GnuplotDataset::XY:
|
||||
os << " with xyerrorbars";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GnuplotDataset::LINES_POINTS:
|
||||
switch ((*i)->m_errorBars)
|
||||
{
|
||||
case GnuplotDataset::NONE:
|
||||
os << " with linespoints";
|
||||
break;
|
||||
case GnuplotDataset::X:
|
||||
os << " with xerrorlines";
|
||||
break;
|
||||
case GnuplotDataset::Y:
|
||||
os << " with yerrorlines";
|
||||
break;
|
||||
case GnuplotDataset::XY:
|
||||
os << " with xyerrorlines";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GnuplotDataset::DOTS:
|
||||
os << " with dots";
|
||||
break;
|
||||
case GnuplotDataset::IMPULSES:
|
||||
os << " with impulses";
|
||||
break;
|
||||
case GnuplotDataset::STEPS:
|
||||
os << " with steps";
|
||||
break;
|
||||
case GnuplotDataset::FSTEPS:
|
||||
os << " with fsteps";
|
||||
break;
|
||||
case GnuplotDataset::HISTEPS:
|
||||
os << " with histeps";
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
if (i != m_datasets.end ())
|
||||
{
|
||||
os << ", ";
|
||||
}
|
||||
}
|
||||
os << std::endl;
|
||||
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end (); i++)
|
||||
{
|
||||
for (GnuplotDataset::Dataset::const_iterator j = (*i)->m_dataset.begin ();
|
||||
j != (*i)->m_dataset.end (); j++)
|
||||
{
|
||||
switch ((*i)->m_errorBars) {
|
||||
case GnuplotDataset::NONE:
|
||||
os << j->x << " " << j->y << std::endl;
|
||||
break;
|
||||
case GnuplotDataset::X:
|
||||
os << j->x << " " << j->y << " " << j->dx << std::endl;
|
||||
break;
|
||||
case GnuplotDataset::Y:
|
||||
os << j->x << " " << j->y << " " << j->dy << std::endl;
|
||||
break;
|
||||
case GnuplotDataset::XY:
|
||||
os << j->x << " " << j->y << " " << j->dx << " " << j->dy << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
os << "e" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
@@ -0,0 +1,91 @@
|
||||
/* -*- 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>
|
||||
*/
|
||||
#ifndef GNUPLOT_H
|
||||
#define GNUPLOT_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class GnuplotDataset
|
||||
{
|
||||
public:
|
||||
enum Style {
|
||||
LINES,
|
||||
POINTS,
|
||||
LINES_POINTS,
|
||||
DOTS,
|
||||
IMPULSES,
|
||||
STEPS,
|
||||
FSTEPS,
|
||||
HISTEPS,
|
||||
};
|
||||
enum ErrorBars {
|
||||
NONE,
|
||||
X,
|
||||
Y,
|
||||
XY
|
||||
};
|
||||
|
||||
GnuplotDataset (std::string title);
|
||||
void SetStyle (enum Style style);
|
||||
void SetErrorBars (enum ErrorBars errorBars);
|
||||
void Add (double x, double y);
|
||||
void Add (double x, double y, double errorDelta);
|
||||
void Add (double x, double y, double errorDeltaX, double errorDeltaY);
|
||||
private:
|
||||
friend class Gnuplot;
|
||||
struct Data {
|
||||
double x;
|
||||
double y;
|
||||
double dx;
|
||||
double dy;
|
||||
};
|
||||
typedef std::vector<struct Data> Dataset;
|
||||
Dataset m_dataset;
|
||||
std::string m_title;
|
||||
enum Style m_style;
|
||||
enum ErrorBars m_errorBars;
|
||||
};
|
||||
|
||||
class Gnuplot
|
||||
{
|
||||
public:
|
||||
Gnuplot (std::string pngFilename);
|
||||
~Gnuplot ();
|
||||
|
||||
void SetLegend (std::string xLegend, std::string yLegend);
|
||||
|
||||
void AddDataset (const GnuplotDataset &dataset);
|
||||
|
||||
void GenerateOutput (std::ostream &os);
|
||||
private:
|
||||
typedef std::vector<GnuplotDataset *> Datasets;
|
||||
Datasets m_datasets;
|
||||
std::string m_xLegend;
|
||||
std::string m_yLegend;
|
||||
std::string m_pngFilename;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* GNUPLOT_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
module = bld.create_ns3_module('contrib', ['simulator'])
|
||||
module.source = [
|
||||
'event-garbage-collector.cc',
|
||||
'gnuplot.cc',
|
||||
'delay-jitter-estimation.cc',
|
||||
]
|
||||
|
||||
headers = bld.create_obj('ns3header')
|
||||
headers.source = [
|
||||
'event-garbage-collector.h',
|
||||
'gnuplot.h',
|
||||
'delay-jitter-estimation.h',
|
||||
]
|
||||
@@ -0,0 +1,306 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 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>
|
||||
*/
|
||||
#include "array-trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
ArrayTraceResolverMatcher::ArrayTraceResolverMatcher (std::string element)
|
||||
: m_element (element)
|
||||
{}
|
||||
bool
|
||||
ArrayTraceResolverMatcher::Matches (uint32_t i) const
|
||||
{
|
||||
if (m_element == "*")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
std::string::size_type tmp;
|
||||
tmp = m_element.find ("|");
|
||||
if (tmp != std::string::npos)
|
||||
{
|
||||
std::string left = m_element.substr (0, tmp-0);
|
||||
std::string right = m_element.substr (tmp+1, m_element.size () - (tmp + 1));
|
||||
ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (left);
|
||||
if (matcher.Matches (i))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
matcher = ArrayTraceResolverMatcher (right);
|
||||
if (matcher.Matches (i))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::string::size_type leftBracket = m_element.find ("[");
|
||||
std::string::size_type rightBracket = m_element.find ("]");
|
||||
std::string::size_type dash = m_element.find ("-");
|
||||
if (leftBracket == 0 && rightBracket == m_element.size () - 1 &&
|
||||
dash > leftBracket && dash < rightBracket)
|
||||
{
|
||||
std::string lowerBound = m_element.substr (leftBracket + 1, dash - (leftBracket + 1));
|
||||
std::string upperBound = m_element.substr (dash + 1, rightBracket - (dash + 1));
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
if (StringToUint32 (lowerBound, &min) &&
|
||||
StringToUint32 (upperBound, &max) &&
|
||||
i >= min && i <= max)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint32_t value;
|
||||
if (StringToUint32 (m_element, &value) &&
|
||||
i == value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayTraceResolverMatcher::StringToUint32 (std::string str, uint32_t *value) const
|
||||
{
|
||||
std::istringstream iss;
|
||||
iss.str (str);
|
||||
iss >> (*value);
|
||||
return !iss.bad () && !iss.fail ();
|
||||
}
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
|
||||
#ifdef RUN_SELF_TESTS
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "test.h"
|
||||
#include "object.h"
|
||||
#include "array-trace-resolver.h"
|
||||
#include "callback-trace-source.h"
|
||||
#include "composite-trace-resolver.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class ObjectTraceTesterIndex : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
ObjectTraceTesterIndex ();
|
||||
ObjectTraceTesterIndex (uint32_t index);
|
||||
void Print (std::ostream &os);
|
||||
static uint16_t GetUid (void);
|
||||
uint32_t Get (void) const;
|
||||
std::string GetTypeName (void) const;
|
||||
private:
|
||||
uint32_t m_index;
|
||||
};
|
||||
|
||||
|
||||
ObjectTraceTesterIndex::ObjectTraceTesterIndex ()
|
||||
: m_index (0)
|
||||
{}
|
||||
ObjectTraceTesterIndex::ObjectTraceTesterIndex (uint32_t index)
|
||||
: m_index (index)
|
||||
{}
|
||||
void
|
||||
ObjectTraceTesterIndex::Print (std::ostream &os)
|
||||
{
|
||||
os << "nodeid=" << m_index;
|
||||
}
|
||||
uint16_t
|
||||
ObjectTraceTesterIndex::GetUid (void)
|
||||
{
|
||||
static uint16_t uid = AllocateUid<ObjectTraceTesterIndex> ("ObjectTraceTesterIndex");
|
||||
return uid;
|
||||
}
|
||||
uint32_t
|
||||
ObjectTraceTesterIndex::Get (void) const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
std::string
|
||||
ObjectTraceTesterIndex::GetTypeName (void) const
|
||||
{
|
||||
return "ns3::ObjectTraceTesterIndex";
|
||||
}
|
||||
|
||||
|
||||
class ObjectTraceTester : public Object
|
||||
{
|
||||
public:
|
||||
void Do (uint32_t i);
|
||||
protected:
|
||||
virtual Ptr<TraceResolver> GetTraceResolver (void) const;
|
||||
private:
|
||||
CallbackTraceSource<uint32_t> m_test;
|
||||
};
|
||||
|
||||
void
|
||||
ObjectTraceTester::Do (uint32_t i)
|
||||
{
|
||||
m_test (i);
|
||||
}
|
||||
|
||||
Ptr<TraceResolver>
|
||||
ObjectTraceTester::GetTraceResolver (void) const
|
||||
{
|
||||
Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
|
||||
resolver->AddSource ("test",
|
||||
TraceDoc ("Test"),
|
||||
m_test);
|
||||
resolver->SetParentResolver (Object::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
class ArrayTraceResolverTest : public Test
|
||||
{
|
||||
public:
|
||||
ArrayTraceResolverTest ();
|
||||
virtual bool RunTests (void);
|
||||
private:
|
||||
bool RunOne (uint32_t n, std::string str,
|
||||
uint32_t nExpected, ...);
|
||||
void OneItem (const TraceContext &context,
|
||||
uint32_t i);
|
||||
|
||||
typedef std::vector<uint32_t> Got;
|
||||
Got m_got;
|
||||
};
|
||||
|
||||
ArrayTraceResolverTest::ArrayTraceResolverTest ()
|
||||
: Test ("ArrayTraceResolver")
|
||||
{}
|
||||
bool
|
||||
ArrayTraceResolverTest::RunOne (uint32_t n, std::string str,
|
||||
uint32_t nExpected, ...)
|
||||
{
|
||||
bool result = true;
|
||||
std::vector<uint32_t> expected;
|
||||
va_list ap;
|
||||
va_start (ap, nExpected);
|
||||
for (uint32_t k = 0; k < nExpected; k++)
|
||||
{
|
||||
uint32_t v = va_arg (ap, uint32_t);
|
||||
expected.push_back (v);
|
||||
}
|
||||
va_end (ap);
|
||||
std::sort (expected.begin (), expected.end ());
|
||||
std::sort (m_got.begin (), m_got.end ());
|
||||
|
||||
std::vector<Ptr<ObjectTraceTester> > vec;
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
{
|
||||
vec.push_back (CreateObject<ObjectTraceTester> ());
|
||||
}
|
||||
ArrayTraceResolver<ObjectTraceTesterIndex> resolver;
|
||||
resolver.SetIterators (vec.begin (), vec.end ());
|
||||
|
||||
TraceContext context;
|
||||
resolver.Connect (str, MakeCallback (&ArrayTraceResolverTest::OneItem, this), context);
|
||||
uint32_t l = 0;
|
||||
for (std::vector<Ptr<ObjectTraceTester> >::const_iterator j = vec.begin (); j != vec.end (); j++)
|
||||
{
|
||||
(*j)->Do (l);
|
||||
l++;
|
||||
}
|
||||
NS_TEST_ASSERT_EQUAL (m_got.size (), expected.size ());
|
||||
for (uint32_t m = 0; m < expected.size (); m++)
|
||||
{
|
||||
NS_TEST_ASSERT_EQUAL (m_got[m], expected[m]);
|
||||
}
|
||||
m_got.clear ();
|
||||
resolver.Disconnect (str, MakeCallback (&ArrayTraceResolverTest::OneItem, this));
|
||||
for (std::vector<Ptr<ObjectTraceTester> >::const_iterator j = vec.begin (); j != vec.end (); j++)
|
||||
{
|
||||
(*j)->Do (l);
|
||||
l++;
|
||||
}
|
||||
NS_TEST_ASSERT_EQUAL (m_got.size (), 0);
|
||||
m_got.clear ();
|
||||
|
||||
return result;
|
||||
}
|
||||
void
|
||||
ArrayTraceResolverTest::OneItem (const TraceContext &context,
|
||||
uint32_t i)
|
||||
{
|
||||
ObjectTraceTesterIndex index;
|
||||
bool found = context.GetElement (index);
|
||||
if (!found)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (index.Get () != i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_got.push_back (i);
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayTraceResolverTest::RunTests (void)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
NS_TEST_ASSERT (RunOne (0, "/*/test", 0));
|
||||
NS_TEST_ASSERT (RunOne (1, "/*/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (1, "/0/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (1, "/[0-0]/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (1, "/0|0/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (2, "/*/test", 2, 0, 1));
|
||||
NS_TEST_ASSERT (RunOne (2, "/0|1/test", 2, 0, 1));
|
||||
NS_TEST_ASSERT (RunOne (2, "/1/test", 1, 1));
|
||||
NS_TEST_ASSERT (RunOne (2, "/|1|/test", 1, 1));
|
||||
NS_TEST_ASSERT (RunOne (2, "/0/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (2, "/0|/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (2, "/|0/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (2, "/[0-1]/test", 2, 0, 1));
|
||||
NS_TEST_ASSERT (RunOne (2, "/[0-0]/test", 1, 0));
|
||||
NS_TEST_ASSERT (RunOne (2, "/[1-1]/test", 1, 1));
|
||||
NS_TEST_ASSERT (RunOne (2, "/0|[1-1]/test", 2, 0, 1));
|
||||
NS_TEST_ASSERT (RunOne (3, "/1|0/test", 2, 0, 1));
|
||||
NS_TEST_ASSERT (RunOne (3, "/2|0/test", 2, 0, 2));
|
||||
NS_TEST_ASSERT (RunOne (3, "/2|1/test", 2, 1, 2));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[0-1]/test", 2, 0, 1));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[1-2]/test", 2, 1, 2));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[0-2]/test", 3, 0, 1, 2));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[1-2]|0/test", 3, 0, 1, 2));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[1-1]|0|[2-2]/test", 3, 0, 1, 2));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[1-2]||/test", 2, 1, 2));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[1-2]||/test", 2, 2, 1));
|
||||
NS_TEST_ASSERT (RunOne (3, "/||||/test", 0));
|
||||
NS_TEST_ASSERT (RunOne (20, "/[5-10]|[2-3]|[15-17]/test", 11, 2, 3, 5, 6, 7, 8, 9, 10, 15, 16, 17));
|
||||
NS_TEST_ASSERT (RunOne (3, "/[1-2]|[0-1]/test", 3, 0, 1, 2));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ArrayTraceResolverTest g_arrayTraceResolverTest;
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* RUN_SELF_TESTS */
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "callback.h"
|
||||
#include "trace-resolver.h"
|
||||
#include "object.h"
|
||||
@@ -78,6 +79,17 @@ private:
|
||||
};
|
||||
IteratorBase *m_iter;
|
||||
};
|
||||
|
||||
class ArrayTraceResolverMatcher
|
||||
{
|
||||
public:
|
||||
ArrayTraceResolverMatcher (std::string element);
|
||||
bool Matches (uint32_t i) const;
|
||||
bool StringToUint32 (std::string str, uint32_t *value) const;
|
||||
private:
|
||||
std::string m_element;
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
|
||||
|
||||
@@ -133,19 +145,20 @@ ArrayTraceResolver<INDEX>::Connect (std::string path, CallbackBase const &cb, co
|
||||
}
|
||||
std::string id = GetElement (path);
|
||||
std::string subpath = GetSubpath (path);
|
||||
if (id == "*")
|
||||
{
|
||||
uint32_t j = 0;
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
TraceContext tmp = context;
|
||||
INDEX index = j;
|
||||
tmp.AddElement (index);
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->GetTraceResolver ()->Connect (subpath, cb, tmp);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (id);
|
||||
uint32_t i = 0;
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
if (matcher.Matches (i))
|
||||
{
|
||||
TraceContext tmp = context;
|
||||
INDEX index = i;
|
||||
tmp.AddElement (index);
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->GetTraceResolver ()->Connect (subpath, cb, tmp);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
template <typename INDEX>
|
||||
void
|
||||
@@ -157,14 +170,17 @@ ArrayTraceResolver<INDEX>::Disconnect (std::string path, CallbackBase const &cb)
|
||||
}
|
||||
std::string id = GetElement (path);
|
||||
std::string subpath = GetSubpath (path);
|
||||
if (id == "*")
|
||||
{
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->TraceDisconnect (subpath, cb);
|
||||
}
|
||||
}
|
||||
ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (id);
|
||||
uint32_t i = 0;
|
||||
for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
|
||||
{
|
||||
if (matcher.Matches (i))
|
||||
{
|
||||
Ptr<Object> obj = m_iter->Get ();
|
||||
obj->TraceDisconnect (subpath, cb);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
template <typename INDEX>
|
||||
void
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user