Amazon Best VPN GoSearch

Favicon OnWorks

ns-3-manual - Dalam Talian di Awan

Jalankan ns-3-manual dalam penyedia pengehosan percuma OnWorks melalui Ubuntu Online, Fedora Online, emulator dalam talian Windows atau emulator dalam talian MAC OS

Ini ialah arahan ns-3-manual yang boleh dijalankan dalam penyedia pengehosan percuma OnWorks menggunakan salah satu daripada berbilang stesen kerja dalam talian percuma kami seperti Ubuntu Online, Fedora Online, emulator dalam talian Windows atau emulator dalam talian MAC OS.

JADUAL:

NAMA


ns-3-manual - ns-3 Manual

Ini adalah ns-3 manual. Dokumentasi utama untuk projek ns-3 tersedia dalam lima
borang:

· ns-3 Doksigen: Dokumentasi API awam simulator

· Tutorial, Manual (ini dokumen), dan Perpustakaan Model untuk Terkini melepaskan and
pembangunan pokok

· ns-3 wiki

KANDUNGAN


pertubuhan
Bab ini menerangkan secara keseluruhan ns-3 organisasi perisian dan yang berkaitan
organisasi manual ini.

ns-3 ialah simulator rangkaian acara diskret di mana teras simulasi dan modelnya
dilaksanakan dalam C++. ns-3 dibina sebagai perpustakaan yang mungkin statik atau dinamik
dipautkan ke program utama C++ yang mentakrifkan topologi simulasi dan memulakan
simulator. ns-3 juga mengeksport hampir semua APInya kepada Python, membenarkan program Python untuk
import modul "ns3" dengan cara yang sama seperti modul ns-3 perpustakaan dipautkan oleh boleh laku
dalam C ++.
[imej] Organisasi perisian ns-3.UNINDENT

Kod sumber untuk ns-3 kebanyakannya dianjurkan dalam src direktori dan boleh diterangkan
dengan rajah dalam perisian organisasi of ns-3. Kami akan berusaha dari bawah
atas; secara amnya, modul hanya mempunyai kebergantungan pada modul di bawahnya dalam rajah.

Kami mula-mula menerangkan teras simulator; komponen yang biasa di semua
protokol, perkakasan dan model persekitaran. Teras simulasi dilaksanakan dalam
src/teras. Paket ialah objek asas dalam simulator rangkaian dan dilaksanakan dalam
src/rangkaian. Kedua-dua modul simulasi ini dengan sendirinya bertujuan untuk terdiri daripada a
teras simulasi generik yang boleh digunakan oleh pelbagai jenis rangkaian, bukan sahaja
Rangkaian berasaskan Internet. Modul di atas bagi ns-3 adalah bebas daripada rangkaian tertentu
dan model peranti, yang diliputi dalam bahagian seterusnya manual ini.

Selain di atas ns-3 teras, kami memperkenalkan, juga dalam bahagian awal
manual, dua modul lain yang menambah teras API berasaskan C++. ns-3 program boleh
akses semua API secara langsung atau boleh menggunakan apa yang dipanggil penolong API yang menyediakan
pembalut mudah atau enkapsulasi panggilan API peringkat rendah. Hakikat bahawa ns-3 program
boleh ditulis kepada dua API (atau gabungannya) adalah aspek asas bagi
simulator. Kami juga menerangkan bagaimana Python disokong dalam ns-3 sebelum beralih ke spesifik
model perkaitan dengan simulasi rangkaian.

Baki manual tertumpu pada mendokumentasikan model dan sokongan
kemampuan. Bahagian seterusnya memfokuskan pada dua objek asas dalam ns-3: Yang nod and
NetDevice. Dua jenis NetDevice khas direka untuk menyokong penggunaan emulasi rangkaian
kes, dan emulasi diterangkan seterusnya. Bab berikut dikhaskan untuk
Model berkaitan Internet, termasuk API soket yang digunakan oleh aplikasi Internet. The
bab seterusnya merangkumi aplikasi, dan bab berikut menerangkan sokongan tambahan
untuk simulasi, seperti animator dan statistik.

Projek ini mengekalkan manual berasingan yang dikhaskan untuk ujian dan pengesahan ns-3 kod
(Lihat ns-3 Ujian and Pengesahan manual).

Random Pembolehubah
ns-3 mengandungi penjana nombor pseudo-rawak terbina dalam (PRNG). Ia penting untuk
pengguna serius simulator untuk memahami fungsi, konfigurasi dan penggunaan
PRNG ini, dan untuk memutuskan sama ada ia mencukupi untuk kegunaan penyelidikannya.

Pantas Pengenalan
ns-3 nombor rawak disediakan melalui contoh ns3::RandomVariableStream.

· secara lalai, ns-3 simulasi menggunakan benih tetap; jika terdapat sebarang rambang dalam
simulasi, setiap larian program akan menghasilkan keputusan yang sama melainkan benih dan/atau
nombor larian ditukar.

· dalam ns-3.3 dan lebih awal, ns-3 simulasi menggunakan benih rawak secara lalai; ini menandakan a
perubahan dasar bermula dengan ns-3.4.

· dalam ns-3.14 dan lebih awal, ns-3 simulasi menggunakan kelas pembalut yang berbeza dipanggil
ns3::RandomVariable. Sehingga ns-3.15, kelas ini telah digantikan dengan
ns3::RandomVariableStream; penjana nombor pseudo-rawak asas tidak mempunyai
berubah.

· untuk mendapatkan rawak merentasi berbilang larian simulasi, anda mesti sama ada menetapkan benih
berbeza atau tetapkan nombor larian secara berbeza. Untuk menetapkan benih, hubungi
ns3::RngSeedManager::SetSeed() pada permulaan program; untuk menetapkan nombor larian dengan
benih yang sama, panggil ns3::RngSeedManager::SetRun() pada permulaan program; lihat
mewujudkan rawak pembolehubah.

· setiap RandomVariableStream digunakan dalam ns-3 mempunyai penjana nombor rawak maya yang berkaitan
dengannya; semua pembolehubah rawak menggunakan sama ada benih tetap atau rawak berdasarkan penggunaan
benih global (peluru sebelumnya);

· jika anda berhasrat untuk melakukan berbilang larian senario yang sama, dengan rawak yang berbeza
nombor, sila pastikan anda membaca bahagian tentang cara melakukan replikasi bebas:
mewujudkan rawak pembolehubah.

Baca lebih lanjut untuk penjelasan lanjut tentang kemudahan nombor rawak untuk ns-3.

Latar Belakang
Simulasi menggunakan banyak nombor rawak; satu kajian mendapati bahawa kebanyakan simulasi rangkaian
membelanjakan sebanyak 50% daripada CPU menjana nombor rawak. Pengguna simulasi perlu
prihatin dengan kualiti nombor rawak (pseudo) dan kebebasan antara
aliran nombor rawak yang berbeza.

Pengguna perlu prihatin dengan beberapa isu, seperti:

· pembenihan penjana nombor rawak dan sama ada hasil simulasi adalah
deterministik atau tidak,

· bagaimana untuk memperoleh aliran nombor rawak yang berbeza yang bebas daripada satu
yang lain, dan

· berapa lama masa yang diperlukan untuk aliran berkitar

Kami akan memperkenalkan beberapa istilah di sini: RNG menyediakan urutan panjang rawak (pseudo).
nombor. Panjang jujukan ini dipanggil kitaran panjang or tempoh, selepas itu
RNG akan berulang. Urutan ini boleh dibahagikan kepada bercabang sungai. A
aliran RNG ialah subset atau blok yang bersebelahan bagi jujukan RNG. Sebagai contoh, jika
Tempoh RNG adalah panjang N, dan dua aliran disediakan daripada RNG ini, kemudian yang pertama
aliran mungkin menggunakan nilai N/2 pertama dan aliran kedua mungkin menghasilkan N/2 kedua
nilai. Sifat penting di sini ialah kedua-dua aliran tidak berkorelasi. Begitu juga,
setiap aliran boleh dibahagikan secara berpisah kepada beberapa yang tidak berkorelasi substream. Yang
pendasar RNG diharapkan menghasilkan urutan pseudo-rawak nombor dengan sangat panjang
panjang kitaran, dan membahagikannya kepada aliran dan substream dengan cara yang cekap.

ns-3 menggunakan penjana nombor rawak asas yang sama seperti yang dilakukan ns-2: MRG32k3a
penjana daripada Pierre L'Ecuyer. Penerangan terperinci boleh didapati di
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf. Penjana MRG32k3a
menyediakan 1.8x10^{19} strim bebas nombor rawak, setiap satunya terdiri daripada
2.3x10^{15} substrim. Setiap substream mempunyai tempoh (iaitu, bilangan nombor rawak
sebelum bertindih) sebanyak 7.6x10^{22}. Tempoh keseluruhan penjana ialah 3.1x10^{57}.

Kelas ns3::RandomVariableStream ialah antara muka awam kepada nombor rawak asas ini
penjana. Apabila pengguna mencipta pembolehubah rawak baharu (seperti ns3::UniformRandomVariable,
ns3::ExponentialRandomVariable, dsb.), mereka mencipta objek yang menggunakan salah satu daripada
aliran bebas yang berbeza bagi penjana nombor rawak. Oleh itu, setiap objek daripada
jenis ns3::RandomVariableStream mempunyai, secara konsep, RNG "maya"nya sendiri. Tambahan pula,
setiap ns3::RandomVariableStream boleh dikonfigurasikan untuk menggunakan salah satu set substrim yang dilukis
daripada aliran utama.

Pelaksanaan alternatif adalah untuk membenarkan setiap RandomVariable mempunyai sendiri
(berbenih berbeza) RNG. Walau bagaimanapun, kami tidak dapat menjamin dengan tegas bahawa perbezaannya
urutan tidak akan dikaitkan dalam kes sedemikian; oleh itu, kami lebih suka menggunakan RNG tunggal dan
aliran dan anak sungai daripadanya.

mewujudkan rawak pembolehubah
ns-3 menyokong beberapa objek pembolehubah rawak daripada kelas asas
RandomVariableStream. Objek ini berasal daripada ns3::Objek dan dikendalikan oleh pintar
petunjuk.

Cara yang betul untuk mencipta objek ini adalah dengan menggunakan templated CreateObject<> kaedah,
seperti:

Ptr x = CreateObject ();

maka anda boleh mengakses nilai dengan memanggil kaedah pada objek seperti:

myRandomNo = x->GetInteger ();

Jika anda cuba melakukan sesuatu seperti ini:

myRandomNo = UniformRandomVariable().GetInteger ();

program anda akan menghadapi kesalahan segmentasi, kerana pelaksanaan bergantung pada
beberapa pembinaan atribut yang berlaku hanya apabila CreateObject dipanggil.

Kebanyakan bahagian lain daripada bab ini kini membincangkan sifat-sifat aliran
nombor pseudo-rawak yang dijana daripada objek tersebut, dan bagaimana untuk mengawal pembenihan sedemikian
objek.

Pembenihan and bebas replikasi
ns-3 simulasi boleh dikonfigurasikan untuk menghasilkan keputusan deterministik atau rawak. Sekiranya
ns-3 simulasi dikonfigurasikan untuk menggunakan benih tetap, deterministik dengan nombor larian yang sama,
ia sepatutnya memberikan output yang sama setiap kali ia dijalankan.

Secara lalai, ns-3 simulasi menggunakan benih tetap dan nombor larian. Nilai ini disimpan dalam
2 ns3::GlobalValue contoh: g_rngSeed and g_rngRun.

Kes penggunaan biasa ialah menjalankan simulasi sebagai urutan percubaan bebas, supaya
mengira statistik pada sejumlah besar larian bebas. Pengguna boleh sama ada menukar
benih global dan jalankan semula simulasi, atau boleh memajukan keadaan substream RNG, yang
dirujuk sebagai menambah bilangan larian.

Kelas ns3::RngSeedManager menyediakan API untuk mengawal nombor pembenihan dan larian
tingkah laku. Tetapan keadaan pembenihan dan substream ini mesti dipanggil sebelum sebarang rawak
pembolehubah dicipta; cth:

RngSeedManager::SetSeed (3); // Menukar benih daripada lalai 1 kepada 3
RngSeedManager::SetRun (7); // Menukar nombor larian daripada lalai 1 kepada 7
// Sekarang, buat pembolehubah rawak
Ptr x = CreateObject ();
Ptr y = CreateObject ();
...

Mana yang lebih baik, menetapkan benih baru atau memajukan keadaan substream? Tidak ada
menjamin bahawa aliran yang dihasilkan oleh dua benih rawak tidak akan bertindih. Satu-satunya cara untuk
jaminan bahawa dua aliran tidak bertindih adalah dengan menggunakan keupayaan substream yang disediakan oleh
pelaksanaan RNG. Oleh itu, penggunaan yang substream keupayaan kepada menghasilkan pelbagai
bebas berjalan of yang sama simulasi. Dalam erti kata lain, lebih ketat dari segi statistik
cara untuk mengkonfigurasi berbilang replikasi bebas adalah dengan menggunakan benih tetap dan memajukan
nombor larian. Pelaksanaan ini membenarkan maksimum 2.3x10^{15} bebas
replikasi menggunakan substreams.

Untuk kemudahan penggunaan, tidak perlu mengawal benih dan nombor larian dari dalam
program; pengguna boleh menetapkan NS_GLOBAL_VALUE pembolehubah persekitaran seperti berikut:

$ NS_GLOBAL_VALUE="RngRun=3" ./waf --run program-name

Satu lagi cara untuk mengawal ini adalah dengan menghantar hujah baris arahan; kerana ini adalah ns-3
Contoh GlobalValue, ia dilakukan secara sama seperti berikut:

$ ./waf --command-template="%s --RngRun=3" --run program-name

atau, jika anda menjalankan program secara langsung di luar waf:

$ ./build/optimized/scratch/program-name --RngRun=3

Varian baris arahan di atas memudahkan untuk menjalankan banyak larian berbeza daripada shell
skrip dengan hanya melepasi indeks RngRun yang berbeza.

Kelas RandomVariableStream
Semua pembolehubah rawak harus berasal dari kelas Pembolehubah rawak. Kelas asas ini menyediakan a
beberapa kaedah untuk mengkonfigurasi kelakuan penjana nombor rawak secara global. Diperoleh
kelas menyediakan API untuk melukis variasi rawak daripada makhluk pengedaran tertentu
disokong.

Setiap RandomVariableStream yang dibuat dalam simulasi diberikan penjana yang baharu
RNNGStrim daripada PRNG asas. Digunakan dengan cara ini, pelaksanaan L'Ecuyer
membenarkan maksimum 1.8x10^19 pembolehubah rawak. Setiap pembolehubah rawak dalam satu
replikasi boleh menghasilkan sehingga 7.6x10^22 nombor rawak sebelum bertindih.

Asas kelas awam API
Di bawah dipetik beberapa kaedah kelas awam RandomVariableStream yang mengakses
nilai seterusnya dalam substream.

/ **
* \brief Mengembalikan gandaan rawak daripada taburan asas
* \return Nilai rawak titik terapung
*/
double GetValue (void) const;

/ **
* \brief Mengembalikan integer rawak daripada taburan asas
* \return lakonan Integer ::GetValue()
*/
uint32_t GetInteger (kosong) const;

Kami telah menerangkan konfigurasi pembenihan di atas. RandomVariable yang berbeza
subkelas mungkin mempunyai API tambahan.

jenis of Pembolehubah Rawak
Jenis pembolehubah rawak berikut disediakan, dan didokumenkan dalam ns-3
Doksigen atau dengan membaca src/core/model/random-variable-stream.h. Pengguna juga boleh membuat
pembolehubah rawak tersuai mereka sendiri dengan memperoleh daripada kelas RandomVariableStream.

· kelas UniformRandomVariable

· kelas ConstantRandomVariable

· kelas SequentialRandomVariable

· kelas ExponentialRandomVariable

· kelas ParetoRandomVariable

· kelas WeibullRandomVariable

· kelas NormalRandomVariable

· kelas LogNormalRandomVariable

· kelas GammaRandomVariable

· kelas ErlangRandomVariable

· kelas TriangularRandomVariable

· kelas ZipfRandomVariable

· kelas ZetaRandomVariable

· kelas DeterministicRandomVariable

· kelas EmpiricalRandomVariable

Semantik of RandomVariableStream objek
Objek RandomVariableStream berasal daripada ns3::Objek dan dikendalikan oleh penunjuk pintar.

Kejadian RandomVariableStream juga boleh digunakan dalam ns-3 atribut, yang bermaksud bahawa
nilai boleh ditetapkan untuk mereka melalui ns-3 sistem atribut. Contohnya adalah dalam
model penyebaran untuk WifiNetDevice:

JenisId
RandomPropagationDelayModel::GetTypeId (kosong)
{
static TypeId tid = TypeId ("ns3::RandomPropagationDelayModel")
.SetParent ()
.AddConstructor ()
.AddAttribute ("Pembolehubah",
"Pembolehubah rawak yang menjana kelewatan rawak (s)",
StringValue ("ns3::UniformRandomVariable"),
MakePointerAccessor (&RandomPropagationDelayModel::m_variable),
MakePointerChecker ())
;
tid balik;
}

Di sini, ns-3 pengguna boleh menukar pembolehubah rawak lalai untuk model kelewatan ini (iaitu
UniformRandomVariable antara 0 hingga 1) melalui sistem atribut.

Menggunakan lain PRNG
Pada masa ini tiada sokongan untuk menggantikan nombor rawak asas yang berbeza
penjana (cth, Perpustakaan Saintifik GNU atau pakej Akaroa). Tampalan dialu-alukan.

Menetapkan yang aliran nombor
Penjana MRG32k3a asas menyediakan 2^64 aliran bebas. Dalam ns-3, ini adalah
ditetapkan secara berurutan bermula dari aliran pertama sebagai contoh RandomVariableStream baharu
membuat panggilan pertama mereka ke GetValue().

Hasil daripada cara objek RandomVariableStream ini diperuntukkan kepada aliran asas,
tugasan adalah sensitif kepada gangguan konfigurasi simulasi. The
akibatnya ialah jika mana-mana aspek konfigurasi simulasi diubah, pemetaan
daripada RandomVariables kepada strim mungkin (atau mungkin tidak) berubah.

Sebagai contoh konkrit, pengguna yang menjalankan kajian perbandingan antara protokol penghalaan boleh
mendapati bahawa tindakan menukar satu protokol penghalaan yang lain akan melihat bahawa
corak mobiliti asas juga berubah.

Bermula dengan ns-3.15, beberapa kawalan telah diberikan kepada pengguna untuk membolehkan pengguna melakukannya
secara pilihan menetapkan penetapan objek RandomVariableStream yang dipilih kepada asas
aliran. Ini adalah Stream atribut, sebahagian daripada kelas asas RandomVariableStream.

Dengan membahagikan urutan aliran sedia ada dari sebelumnya:

<------------------------------------------------ -------------------------->
strim 0 strim (2^64 - 1)

menjadi dua set bersaiz sama:

<------------------------------------------------ -------------------------->
^ ^^ ^
| || |
strim 0 strim (2^63 - 1) strim 2^63 strim (2^64 - 1)
<- diperuntukkan secara automatik -----------><- diperuntukkan oleh pengguna ----------------->

Strim 2^63 pertama terus diperuntukkan secara automatik, manakala 2^63 terakhir adalah
indeks aliran yang diberikan bermula dengan sifar hingga 2^63-1.

Penyerahan aliran kepada nombor aliran tetap adalah pilihan; contoh daripada
RandomVariableStream yang tidak mempunyai nilai strim yang ditetapkan akan diberikan seterusnya
satu daripada kumpulan aliran automatik.

Untuk membetulkan RandomVariableStream kepada strim asas tertentu, tetapkan strim tersebut Stream
atribut kepada integer bukan negatif (nilai lalai -1 bermakna nilai akan menjadi
diperuntukkan secara automatik).

Penerbitan Matlamat keputusan
Apabila anda menerbitkan hasil simulasi, bahagian penting maklumat konfigurasi yang anda
harus selalu nyatakan bagaimana anda menggunakan penjana nombor rawak.

· apakah benih yang anda gunakan,

· apakah RNG yang anda gunakan jika bukan yang lalai,

· bagaimana larian bebas dilakukan,

· untuk simulasi besar, bagaimana anda menyemak bahawa anda tidak berbasikal.

Adalah menjadi tanggungjawab penyelidik menerbitkan hasil untuk memasukkan maklumat yang mencukupi untuk
membenarkan orang lain untuk mengeluarkan semula keputusannya. Ia juga menjadi kewajipan kepada penyelidik untuk
yakinkan diri bahawa nombor rawak yang digunakan adalah sah secara statistik, dan nyatakan dalam
kertas mengapa keyakinan sedemikian diandaikan.

Ringkasan
Mari semak perkara yang perlu anda lakukan semasa membuat simulasi.

· Tentukan sama ada anda menjalankan dengan benih tetap atau benih rawak; benih tetap ialah
lalai,

· Tentukan bagaimana anda akan menguruskan replikasi bebas, jika berkenaan,

· Yakinkan diri anda bahawa anda tidak melukis lebih banyak nilai rawak daripada panjang kitaran, jika
anda menjalankan simulasi yang sangat panjang, dan

· Apabila anda menerbitkan, ikut garis panduan di atas tentang mendokumentasikan penggunaan rawak anda
penjana nombor.

Hash Fungsi
ns-3 menyediakan antara muka generik kepada fungsi cincang tujuan umum. Dalam yang paling mudah
penggunaan, fungsi cincang mengembalikan cincangan 32-bit atau 64-bit penimbal atau rentetan data.
Fungsi cincang asas lalai ialah merungut3, dipilih kerana ia mempunyai fungsi cincang yang baik
hartanah dan menawarkan versi 64-bit. Yang dihormati FNV1a hash juga tersedia.

Terdapat mekanisme lurus ke hadapan untuk menambah (atau menyediakan pada masa jalan) cincang alternatif
pelaksanaan fungsi.

Asas Penggunaan
Cara paling mudah untuk mendapatkan nilai cincang penimbal atau rentetan data ialah:

#include "ns3/hash.h"

menggunakan ruang nama ns3;

char * penimbal = ...
size_t buffer_size = ...

uint32_t buffer_hash = Hash32 ( buffer, buffer_size);

std::rentetan s;
uint32_t string_hash = Hash32 (s);

Fungsi setara ditakrifkan untuk nilai cincang 64-bit.

Tambahan Hashing
Dalam sesetengah situasi, adalah berguna untuk mengira cincangan berbilang penimbal, seolah-olah ada
telah disatukan. (Sebagai contoh, anda mungkin mahu cincang aliran paket, tetapi tidak
mahu memasang satu penimbal dengan gabungan kandungan semua paket.)

Ini hampir sama lurus ke hadapan seperti contoh pertama:

#include "ns3/hash.h"

menggunakan ruang nama ns3;

char * penimbal;
size_t buffer_size;

Hasher hasher; // Gunakan fungsi cincang lalai

untuk ( )
{
penimbal = get_next_buffer ();
pencincang (penampan, saiz_penampan);
}
uint32_t combined_hash = hasher.GetHash32 ();

Secara lalai Hasher mengekalkan keadaan dalaman untuk membolehkan pencincangan tambahan. Jika anda mahu
guna semula a Hasher objek (contohnya kerana ia dikonfigurasikan dengan cincang bukan lalai
function), tetapi tidak mahu menambah cincang yang dikira sebelum ini, anda perlu jelas ()
pertama:

hasher.clear ().GetHash32 (buffer, buffer_size);

Ini memulakan semula keadaan dalaman sebelum mencincang penimbal.

Menggunakan an Alternatif Hash fungsi
Fungsi cincang lalai ialah merungut3. FNV1a juga tersedia. Untuk menentukan cincangan
berfungsi secara eksplisit, gunakan konstruktor ini:

Hasher hasher = Hasher ( Buat () );

Menambah Baru Hash fungsi Pelaksanaan
Untuk menambah fungsi cincang foo, ikut hash-murmur3.h/. Cc corak:

· Buat pengisytiharan kelas (.h) dan definisi (. Cc) mewarisi daripada
Hash::Pelaksanaan.

· termasuk pengisytiharan dalam hash.h (pada titik di mana hash-murmur3.h disertakan.

· Dalam kod anda sendiri, nyatakan a Hasher objek melalui pembina Hasher
(Ptr ())

Jika fungsi cincang anda ialah fungsi tunggal, mis hashf, anda tidak perlu membuat a
kelas baharu yang diperoleh daripada HashImplementation:

Hasher hasher =
Hasher ( Cipta (&hashf) );

Untuk menyusun ini, anda hashf perlu memadankan salah satu tanda tangan penunjuk fungsi:

typedef uint32_t (*Hash32Function_ptr) (const char *, const size_t);
typedef uint64_t (*Hash64Function_ptr) (const char *, const size_t);

Sumber khususnya Hash Fungsi
Sumber untuk pelaksanaan fungsi cincang yang lain termasuk:

· Peter Kankowski: http://www.strchr.com

· Arash Partow: http://www.partow.net/programming/hashfunctions/index.html

· SMHasher: http://code.google.com/p/smhasher/

· Sanmayce: http://www.sanmayce.com/Fastest_Hash/index.html

Aktiviti and Simulator
ns-3 ialah simulator rangkaian acara diskret. Secara konsep, simulator menjejaki a
bilangan acara yang dijadualkan untuk dilaksanakan pada masa simulasi yang ditentukan. Tugas daripada
simulator adalah untuk melaksanakan acara dalam urutan masa berurutan. Setelah selesai
sesuatu peristiwa berlaku, simulator akan berpindah ke acara seterusnya (atau akan keluar jika tiada
lebih banyak acara dalam baris gilir acara). Jika, sebagai contoh, acara yang dijadualkan untuk masa simulasi
"100 saat" dilaksanakan, dan acara seterusnya tidak dijadualkan sehingga "200 saat",
simulator akan segera melompat dari 100 saat kepada 200 saat (masa simulasi) ke
melaksanakan acara seterusnya. Inilah yang dimaksudkan dengan simulator "peristiwa diskret".

Untuk membuat ini semua berlaku, simulator memerlukan beberapa perkara:

1. objek simulator yang boleh mengakses baris gilir acara di mana acara disimpan dan yang boleh
menguruskan pelaksanaan acara

2. penjadual yang bertanggungjawab untuk memasukkan dan mengalih keluar acara daripada baris gilir

3. satu cara untuk mewakili masa simulasi

4. peristiwa itu sendiri

Bab manual ini menerangkan objek asas ini (simulator, penjadual,
masa, peristiwa) dan bagaimana ia digunakan.

Acara
Untuk be siap

Simulator
Kelas Simulator ialah pintu masuk awam untuk mengakses kemudahan penjadualan acara. sekali
beberapa acara telah dijadualkan untuk memulakan simulasi, pengguna boleh mula melakukannya
laksanakannya dengan memasukkan gelung utama simulator (panggilan Simulator::Lari). Sekali gelung utama
mula berjalan, ia akan melaksanakan secara berurutan semua acara yang dijadualkan mengikut urutan dari yang paling lama hingga
terbaharu sehingga tiada lagi acara yang tinggal dalam baris gilir acara atau
Simulator::Berhenti telah dipanggil.

Untuk menjadualkan acara untuk pelaksanaan oleh gelung utama simulator, kelas Simulator menyediakan
keluarga fungsi Simulator::Jadual*.

1. Mengendalikan pengendali acara dengan tandatangan yang berbeza

Fungsi ini diisytiharkan dan dilaksanakan sebagai templat C++ untuk mengendalikan secara automatik
pelbagai jenis tandatangan pengendali acara C++ yang digunakan di alam liar. Sebagai contoh, untuk menjadualkan
acara untuk melaksanakan 10 saat pada masa hadapan, dan menggunakan kaedah atau fungsi C++ dengan
hujah tertentu, anda boleh menulis ini:

pengendali void (int arg0, int arg1)
{
std::cout << "pengendali dipanggil dengan argumen arg0=" << arg0 << " dan
arg1=" << arg1 << std::endl;
}

Simulator::Jadual(Seconds(10), &pengendali, 10, 5);

Yang akan menghasilkan:

pengendali dipanggil dengan hujah arg0=10 dan arg1=5

Sudah tentu, templat C++ ini juga boleh mengendalikan kaedah ahli secara telus pada C++
objek:

Untuk be selesai: ahli kaedah contoh

Nota:

· kaedah Jadual ns-3 mengecam fungsi dan kaedah secara automatik hanya jika ia
ambil kurang daripada 5 hujah. Jika anda memerlukannya untuk menyokong lebih banyak hujah, sila failkan a
laporan pepijat.

· Pembaca yang biasa dengan istilah 'functors terikat sepenuhnya' akan mengenali
Simulator::Jadualkan kaedah sebagai cara untuk membina objek sedemikian secara automatik.

2. Operasi penjadualan biasa

API Simulator direka bentuk untuk menjadikannya sangat mudah untuk menjadualkan kebanyakan acara. Ia
menyediakan tiga varian untuk berbuat demikian (disusun daripada yang paling biasa digunakan kepada yang paling jarang digunakan):

· Jadual kaedah yang membolehkan anda menjadualkan acara pada masa hadapan dengan menyediakan
kelewatan antara masa simulasi semasa dan tarikh luput acara sasaran.

· Kaedah ScheduleNow yang membolehkan anda menjadualkan acara untuk simulasi semasa
masa: mereka akan melaksanakan _selepas_ acara semasa selesai dilaksanakan tetapi _sebelum_
masa simulasi ditukar untuk acara seterusnya.

· Kaedah ScheduleDestroy yang membolehkan anda menyambung dalam proses penutupan Simulator
untuk membersihkan sumber simulasi: setiap acara 'musnahkan' dilaksanakan apabila pengguna memanggil
kaedah Simulator:: Musnahkan.

3. Mengekalkan konteks simulasi

Terdapat dua cara asas untuk menjadualkan acara, dengan dan tanpa konteks. Apa ini?
maksudnya?

Simulator::Jadual (Masa const &time, MEM mem_ptr, OBJ obj);

vs

Simulator::ScheduleWithContext (konteks uint32_t, Masa & masa, MEM mem_ptr, OBJ obj);

Pembaca yang meluangkan masa dan usaha dalam membangunkan atau menggunakan model simulasi yang tidak remeh
akan mengetahui nilai rangka kerja pengelogan ns-3 untuk menyahpepijat simulasi mudah dan kompleks
serupa. Salah satu ciri penting yang disediakan oleh rangka kerja pembalakan ini ialah
paparan automatik id nod rangkaian yang dikaitkan dengan acara yang sedang berjalan.

Id nod bagi nod rangkaian yang sedang melaksanakan sebenarnya dijejaki oleh Simulator
kelas. Ia boleh diakses dengan kaedah Simulator::GetContext yang mengembalikan
'konteks' (integer 32-bit) dikaitkan dan disimpan dalam acara yang sedang dilaksanakan. Dalam
beberapa kes yang jarang berlaku, apabila sesuatu peristiwa tidak dikaitkan dengan nod rangkaian tertentu, ia
'konteks' ditetapkan kepada 0xffffffff.

Untuk mengaitkan konteks pada setiap acara, kaedah Jadual dan JadualNow secara automatik
gunakan semula konteks acara yang sedang dilaksanakan sebagai konteks acara yang dijadualkan
untuk pelaksanaan nanti.

Dalam sesetengah kes, terutamanya apabila mensimulasikan penghantaran paket dari nod ke
satu lagi, tingkah laku ini tidak diingini kerana konteks yang dijangkakan acara penerimaan adalah
nod penerima, bukan nod penghantar. Untuk mengelakkan masalah ini, Simulator
kelas menyediakan kaedah jadual tertentu: ScheduleWithContext yang membolehkan seseorang menyediakan
secara eksplisit id nod bagi nod penerima yang dikaitkan dengan peristiwa terima.

XXX: kod contoh

Dalam beberapa kes yang sangat jarang berlaku, pembangun mungkin perlu mengubah suai atau memahami cara konteksnya
(id nod) acara pertama ditetapkan kepada nod yang berkaitan. Ini tercapai
oleh kelas NodeList: setiap kali nod baharu dicipta, kelas NodeList menggunakan
ScheduleWithContext untuk menjadualkan acara 'memulakan' untuk nod ini. Acara 'memulakan'
dengan itu dilaksanakan dengan set konteks kepada id nod dan boleh menggunakan kepelbagaian biasa bagi
Kaedah jadual. Ia menggunakan kaedah Node::Initialize yang menyebarkan 'initialize'
acara dengan memanggil kaedah DoInitialize untuk setiap objek yang dikaitkan dengan nod. The
Kaedah DoInitialize ditindih dalam beberapa objek ini (terutamanya dalam Application
kelas asas) akan menjadualkan beberapa acara (terutamanya Application::StartApplication) yang
seterusnya akan menjadualkan acara penjanaan trafik yang akan menjadualkan pula
acara peringkat rangkaian.

Nota:

· Pengguna perlu berhati-hati untuk menyebarkan kaedah DoInitialize merentasi objek dengan memanggil
Mulakan secara eksplisit pada objek ahli mereka

· Id konteks yang dikaitkan dengan setiap kaedah ScheduleWithContext mempunyai kegunaan lain di luar
pembalakan: ia digunakan oleh cawangan eksperimen ns-3 untuk melakukan simulasi selari pada
sistem multiteras menggunakan multithreading.

Fungsi Simulator::* tidak mengetahui konteksnya: mereka hanya memastikannya
apa sahaja konteks yang anda tentukan dengan ScheduleWithContext tersedia apabila yang sepadan
acara dilaksanakan dengan ::GetContext.

Terpulang kepada model yang dilaksanakan di atas Simulator::* untuk mentafsir nilai konteks.
Dalam ns-3, model rangkaian mentafsir konteks sebagai id nod nod yang
menghasilkan sesuatu peristiwa. Inilah sebabnya mengapa penting untuk memanggil ScheduleWithContext masuk
ns3::Saluran subkelas kerana kami menjana acara daripada nod i ke nod j dan kami
ingin memastikan bahawa acara yang akan berjalan pada nod j mempunyai konteks yang betul.

Masa
Untuk be siap

Berjadual
Untuk be siap

Panggilan balik
Beberapa pengguna baharu untuk ns-3 tidak biasa dengan simpulan bahasa pengaturcaraan yang digunakan secara meluas digunakan
sepanjang kod: the ns-3 panggil balik. Bab ini memberikan sedikit motivasi mengenai
panggil balik, panduan tentang cara menggunakannya dan butiran tentang pelaksanaannya.

Panggilan balik Motivasi
Pertimbangkan bahawa anda mempunyai dua model simulasi A dan B, dan anda ingin mereka lulus
maklumat antara mereka semasa simulasi. Satu cara yang boleh anda lakukan ialah anda
boleh menjadikan A dan B masing-masing mempunyai pengetahuan yang jelas tentang satu sama lain, supaya mereka boleh memohon
kaedah antara satu sama lain:

kelas A {
awam:
void ReceiveInput ( // parameter);
...
}

(dalam fail sumber lain :)

kelas B {
awam:
void DoSomething (void);
...

peribadi:
A* a_instance; // penunjuk kepada A
}

membatalkan
B::DoSomething()
{
// Beritahu a_instance bahawa sesuatu telah berlaku
a_instance->ReceiveInput ( // parameter);
...
}

Ini sememangnya berkesan, tetapi ia mempunyai kelemahan iaitu ia memperkenalkan pergantungan pada A dan B
untuk mengetahui tentang yang lain pada masa penyusunan (ini menjadikannya lebih sukar untuk mempunyai bebas
unit kompilasi dalam simulator) dan tidak digeneralisasikan; jika dalam senario penggunaan kemudian,
B perlu bercakap dengan objek C yang berbeza sama sekali, kod sumber untuk B perlu
diubah untuk menambah a c_instance dan sebagainya. Adalah mudah untuk melihat bahawa ini adalah kuasa yang kejam
mekanisme komunikasi yang boleh membawa kepada cruft pengaturcaraan dalam model.

Ini bukan untuk mengatakan bahawa objek tidak sepatutnya tahu tentang satu sama lain jika ada yang sukar
pergantungan antara mereka, tetapi selalunya model boleh dibuat lebih fleksibel jika ia
interaksi kurang terkekang pada masa penyusunan.

Ini bukan masalah abstrak untuk penyelidikan simulasi rangkaian, tetapi ia telah menjadi a
punca masalah dalam simulator terdahulu, apabila penyelidik ingin melanjutkan atau mengubah suai
sistem untuk melakukan perkara yang berbeza (seperti yang biasa mereka lakukan dalam penyelidikan). Pertimbangkan, sebagai contoh,
pengguna yang ingin menambah sublapisan protokol keselamatan IPsec antara TCP dan IP:

------------ -----------
| TCP | | TCP |
------------ -----------
| menjadi -> |
----------- -----------
| IP | | IPsec |
----------- -----------
|
-----------
| IP |
-----------

Jika simulator telah membuat andaian, dan dikodkan keras ke dalam kod, IP itu sentiasa bercakap
kepada protokol pengangkutan di atas, pengguna mungkin terpaksa menggodam sistem untuk mendapatkan
perhubungan yang dikehendaki. Ini jelas bukan cara yang optimum untuk mereka bentuk generik
simulator.

Panggilan balik Latar Belakang
PERHATIAN:
Pembaca yang biasa dengan panggilan balik pengaturcaraan boleh melangkau bahagian tutorial ini.

Mekanisme asas yang membolehkan seseorang menangani masalah di atas dikenali sebagai a panggil balik.
Matlamat utama adalah untuk membenarkan satu kod memanggil fungsi (atau kaedah dalam C++)
tanpa sebarang pergantungan antara modul tertentu.

Ini akhirnya bermakna anda memerlukan beberapa jenis arahan -- anda merawat alamat
dipanggil fungsi sebagai pembolehubah. Pembolehubah ini dipanggil pembolehubah penunjuk kepada fungsi.
Hubungan antara fungsi dan penunjuk-ke-fungsi sebenarnya tidak berbeza
bahawa objek dan penunjuk-ke-objek.

Dalam C contoh kanonik penunjuk-ke-fungsi ialah a
pointer-to-function-returning-integer (PFI). Untuk PFI mengambil satu parameter int, ini
boleh diisytiharkan seperti,:

int (*pfi)(int arg) = 0;

Apa yang anda dapat daripada ini ialah pembolehubah bernama ringkas pfi yang dimulakan kepada nilai 0.
Jika anda ingin memulakan penunjuk ini kepada sesuatu yang bermakna, anda perlu mempunyai a
berfungsi dengan tandatangan yang sepadan. Dalam kes ini:

int MyFunction (int arg) {}

Jika anda mempunyai sasaran ini, anda boleh memulakan pembolehubah untuk menunjuk ke fungsi anda seperti:

pfi = MyFunction;

Anda kemudiannya boleh menghubungi MyFunction secara tidak langsung menggunakan bentuk panggilan yang lebih tidak senonoh:

int hasil = (*pfi) (1234);

Ini tidak semena-mena kerana nampaknya anda hanya menafikan penunjuk fungsi
seperti anda akan menyahrujuk mana-mana penunjuk. Lazimnya, bagaimanapun, orang mengambil kesempatan daripada
fakta bahawa pengkompil mengetahui apa yang sedang berlaku dan hanya akan menggunakan bentuk yang lebih pendek:

int hasil = pfi (1234);

Perhatikan bahawa penuding fungsi mematuhi semantik nilai, jadi anda boleh menyampaikannya seperti mana-mana
nilai lain. Biasanya, apabila anda menggunakan antara muka tak segerak anda akan lulus beberapa entiti
seperti ini kepada fungsi yang akan melakukan tindakan dan memanggil kembali untuk memberitahu anda
selesai. Ia memanggil semula dengan mengikut arahan dan melaksanakan fungsi yang disediakan.

Dalam C++ anda mempunyai kerumitan tambahan objek. Analogi dengan PFI di atas bermaksud anda
mempunyai penunjuk ke fungsi ahli mengembalikan int (PMI) dan bukannya penunjuk ke
fungsi mengembalikan int (PFI).

Pengisytiharan pemboleh ubah yang memberikan arahan hanya kelihatan sedikit berbeza:

int (Kelas Saya::*pmi) (int arg) = 0;

Ini mengisytiharkan pembolehubah bernama pmi sama seperti contoh sebelumnya mengisytiharkan pembolehubah bernama
pfi. Oleh kerana kehendak adalah untuk memanggil kaedah contoh kelas tertentu, seseorang mesti
mengisytiharkan kaedah itu dalam kelas:

kelas MyClass {
awam:
int MyMethod (int arg);
};

Memandangkan pengisytiharan kelas ini, seseorang kemudian akan memulakan pembolehubah itu seperti ini:

pmi = &Kelas Saya::Kaedah Saya;

Ini memberikan alamat kod yang melaksanakan kaedah kepada pembolehubah, melengkapkan
arahan itu. Untuk memanggil kaedah, kod tersebut memerlukan a ini penunjuk. Ini pula,
bermakna mesti ada objek MyClass untuk dirujuk. Contoh ringkas tentang ini adalah adil
memanggil kaedah secara tidak langsung (fikirkan fungsi maya):

int (Kelas Saya::*pmi) (int arg) = 0; // Isytiharkan PMI
pmi = &Kelas Saya::Kaedah Saya; // Tuding pada kod pelaksanaan

MyClass myClass; // Memerlukan contoh kelas
(myClass.*pmi) (1234); // Panggil kaedah dengan objek ptr

Sama seperti dalam contoh C, anda boleh menggunakannya dalam panggilan tak segerak ke modul lain
yang akan memanggil kembali menggunakan kaedah dan penunjuk objek. Sambungan yang mudah
yang mungkin dipertimbangkan ialah menghantar penunjuk kepada objek dan pembolehubah PMI. modul
hanya akan melakukan:

(*objectPtr.*pmi) (1234);

untuk melaksanakan panggilan balik pada objek yang dikehendaki.

Seseorang mungkin bertanya pada masa ini, apa yang titik? Modul yang dipanggil perlu difahami
jenis konkrit objek panggilan untuk membuat panggilan balik dengan betul. Kenapa tidak
terima sahaja ini, lulus penunjuk objek yang ditaip dengan betul dan lakukan objek->kaedah(1234) in
kod dan bukannya panggilan balik? Inilah masalah yang diterangkan di atas. Apa itu
diperlukan ialah satu cara untuk memisahkan fungsi panggilan daripada kelas yang dipanggil sepenuhnya. ini
keperluan membawa kepada pembangunan Fungsi.

Functor ialah hasil daripada sesuatu yang dicipta pada tahun 1960-an yang dipanggil penutupan. Ia adalah
pada asasnya hanya panggilan fungsi yang dibungkus, mungkin dengan beberapa keadaan.

Functor mempunyai dua bahagian, bahagian tertentu dan bahagian generik, berkaitan melalui pewarisan.
Kod panggilan (kod yang melaksanakan panggilan balik) akan melaksanakan overload generik
operator () daripada fungsi generik untuk menyebabkan panggilan balik dipanggil. Kod yang dipanggil (the
kod yang ingin dipanggil semula) perlu menyediakan pelaksanaan khusus bagi
yang operator () yang melaksanakan kerja khusus kelas yang menyebabkan gandingan rapat
masalah di atas.

Dengan fungsi tertentu dan bebannya yang berlebihan operator () dicipta, kod yang dipanggil kemudian
memberikan kod khusus kepada modul yang akan melaksanakan panggilan balik (panggilan
kod).

Kod panggilan akan mengambil fungsi generik sebagai parameter, jadi hantaran tersirat dilakukan
dalam panggilan fungsi untuk menukar fungsi tertentu kepada fungsi generik. Ini bermaksud
bahawa modul panggilan hanya perlu memahami jenis fungsi generik. Ia dipisahkan
daripada kod panggilan sepenuhnya.

Maklumat yang diperlukan untuk membuat fungsi tertentu ialah penunjuk objek dan
alamat penuding kepada kaedah.

Intipati apa yang perlu berlaku ialah sistem mengisytiharkan bahagian generik daripada
fungsi:

templat
Fungsi kelas
{
awam:
pengendali int maya() (T arg) = 0;
};

Pemanggil mentakrifkan bahagian tertentu fungsi yang benar-benar ada untuk dilaksanakan
yang khusus pengendali() kaedah:

templat
kelas SpecificFunctor : Functor awam
{
awam:
SpecificFunctor(T* p, int (T::*_pmi)(ARG arg))
{
m_p = p;
m_pmi = _pmi;
}

pengendali int maya() (ARG arg)
{
(*m_p.*m_pmi)(arg);
}
peribadi:
int (T::*m_pmi)(ARG arg);
T* m_p;
};

Berikut adalah contoh penggunaannya:

kelas A
{
awam:
A (int a0) : a (a0) {}
int Hello (int b0)
{
std::cout << "Helo daripada A, a = " << a << " b0 = " << b0 << std::endl;
}
int a;
};

int utama ()
{
A a(10);
SpecificFunctor sf(&a, &A::Hello);
sf(5);
}

PERHATIAN:
Kod sebelumnya bukan kod ns-3 sebenar. Ia adalah contoh kod ringkas yang digunakan hanya untuk
menggambarkan konsep yang terlibat dan untuk membantu anda memahami sistem dengan lebih lanjut. Jangan
mengharapkan untuk mencari kod ini di mana-mana dalam pokok ns-3.

Perhatikan bahawa terdapat dua pembolehubah yang ditakrifkan dalam kelas di atas. Pembolehubah m_p ialah
penunjuk objek dan m_pmi ialah pembolehubah yang mengandungi alamat fungsi kepada
melaksanakan.

Perhatikan bahawa apabila pengendali() dipanggil, ia pula memanggil kaedah yang disediakan dengan
penunjuk objek menggunakan sintaks C++ PMI.

Untuk menggunakan ini, seseorang kemudiannya boleh mengisytiharkan beberapa kod model yang mengambil fungsi generik sebagai a
parameter:

void LibraryFunction (Functor Functor);

Kod yang akan bercakap dengan model akan membina functor tertentu dan menghantarnya kepada
Fungsi Perpustakaan:

MyClass myClass;
SpecificFunctor functor (&myclass, MyClass::MyMethod);

Bila Fungsi Perpustakaan selesai, ia melaksanakan panggilan balik menggunakan pengendali() pada generik
functor ia telah diluluskan, dan dalam kes khusus ini, menyediakan hujah integer:

membatalkan
LibraryFunction (Functor function)
{
// Laksanakan fungsi perpustakaan
pelawak(1234);
}

Perhatikan itu Fungsi Perpustakaan dipisahkan sepenuhnya daripada jenis pelanggan tertentu.
Sambungan dibuat melalui polimorfisme Functor.

API Panggilan Balik dalam ns-3 melaksanakan panggilan balik berorientasikan objek menggunakan mekanisme functor.
API panggil balik ini, berdasarkan templat C++, adalah selamat jenis; iaitu, ia melakukan statik
semakan taip untuk menguatkuasakan keserasian tandatangan yang betul antara pemanggil dan penerima. Ia adalah
oleh itu lebih selamat jenis untuk digunakan daripada penunjuk fungsi tradisional, tetapi sintaks mungkin
nampak menarik pada mulanya. Bahagian ini direka bentuk untuk memandu anda melalui sistem Panggilan Balik
supaya anda selesa menggunakannya ns-3.

Menggunakan yang Panggil balik API
API Panggilan Balik adalah agak minimum, hanya menyediakan dua perkhidmatan:

1. pengisytiharan jenis panggil balik: cara untuk mengisytiharkan jenis panggilan balik dengan tandatangan yang diberikan,
dan,

2. instantiasi panggil balik: cara untuk membuat instantiate panggilan balik pemajuan yang dijana templat
yang boleh memajukan sebarang panggilan ke kaedah ahli kelas C++ atau fungsi C++ yang lain.

Ini paling baik diperhatikan melalui berjalan melalui contoh, berdasarkan samples/main-callback.cc.

Menggunakan yang Panggil balik API bersama statik fungsi
Pertimbangkan fungsi:

berganda statik
CbOne (double a, double b)
{
std::cout << "invoke cbOne a=" << a << ", b=" << b << std::endl;
kembalikan a;
}

Pertimbangkan juga coretan program utama berikut:

int utama (int argc, char *argv[])
{
// jenis pulangan: double
// jenis arg pertama: double
// jenis arg kedua: double
Panggilan balik satu;
}

Ini ialah contoh panggil balik gaya C -- yang tidak termasuk atau memerlukan a ini
penunjuk. Templat fungsi Panggil balik pada asasnya adalah pengisytiharan pembolehubah
mengandungi penunjuk-ke-fungsi. Dalam contoh di atas, kami secara eksplisit menunjukkan penunjuk
kepada fungsi yang mengembalikan integer dan mengambil satu integer sebagai parameter, The
Panggil balik fungsi templat ialah versi generik -- ia digunakan untuk mengisytiharkan jenis
daripada panggilan balik.

PERHATIAN:
Pembaca yang tidak biasa dengan templat C++ boleh berunding
http://www.cplusplus.com/doc/tutorial/templates/.

. Panggil balik templat memerlukan satu hujah wajib (jenis pemulangan fungsi ke
diberikan kepada panggilan balik ini) dan sehingga lima argumen pilihan, yang masing-masing menentukan
jenis argumen (jika fungsi panggil balik tertentu anda mempunyai lebih daripada lima argumen,
maka ini boleh dikendalikan dengan melanjutkan pelaksanaan panggilan balik).

Jadi dalam contoh di atas, kami telah mengisytiharkan panggilan balik bernama "satu" yang akhirnya akan
memegang penunjuk fungsi. Tandatangan fungsi yang akan dipegang mesti kembali
berganda dan mesti menyokong dua hujah berganda. Jika seseorang cuba lulus fungsi yang
tandatangan tidak sepadan dengan panggilan balik yang diisytiharkan, ralat kompilasi akan berlaku. Juga, jika
seseorang cuba menetapkan kepada panggilan balik yang tidak serasi, penyusunan akan berjaya tetapi a
NS_FATAL_ERROR masa jalan akan dinaikkan. Program contoh
src/core/examples/main-callback.cc menunjukkan kedua-dua kes ralat ini pada akhir
yang main () program.

Sekarang, kita perlu menggabungkan contoh panggilan balik ini dan fungsi sasaran sebenar
(CbOne). Perhatikan di atas bahawa CbOne mempunyai jenis tandatangan fungsi yang sama seperti panggilan balik--
ini sangat penting. Kami boleh menghantar mana-mana fungsi yang ditaip dengan betul kepada panggilan balik ini.
Mari kita lihat ini dengan lebih dekat:

berganda statik CbOne (berganda a, berganda b) {}
^^
| | |
| | |
Panggilan balik satu;

Anda hanya boleh mengikat fungsi kepada panggilan balik jika ia mempunyai tandatangan yang sepadan. Yang pertama
hujah templat ialah jenis pulangan, dan hujah templat tambahan ialah jenisnya
daripada argumen tandatangan fungsi.

Sekarang, mari kita ikat panggilan balik "satu" kami pada fungsi yang sepadan dengan tandatangannya:

// bina contoh panggilan balik yang menunjuk kepada fungsi cbOne
satu = MakeCallback (&CbOne);

Panggilan ini kepada MakeCallback adalah, pada dasarnya, mewujudkan salah satu fungsi khusus
yang disebut di atas. Pembolehubah diisytiharkan menggunakan Panggil balik fungsi templat akan
memainkan peranan sebagai fungsi generik. Tugasan 1 = MakeCallback (&CbOne) is
pelakon yang menukar functor khusus yang diketahui oleh penerima kepada functor generik
diketahui pemanggil.

Kemudian, kemudian dalam program, jika panggilan balik diperlukan, ia boleh digunakan seperti berikut:

NS_ASSERT (!one.IsNull ());

// gunakan fungsi cbOne melalui contoh panggil balik
double retOne;
retOne = satu (10.0, 20.0);

Cek untuk IsNull() memastikan bahawa panggilan balik tidak batal -- bahawa terdapat fungsi
untuk memanggil di belakang panggilan balik ini. Kemudian, satu () melaksanakan generik pengendali() yang sebenarnya
terbeban dengan pelaksanaan khusus bagi pengendali() dan mengembalikan hasil yang sama seolah-olah
CbOne() telah dipanggil secara langsung.

Menggunakan yang Panggil balik API bersama ahli fungsi
Secara amnya, anda tidak akan memanggil fungsi statik tetapi sebaliknya fungsi ahli awam
sebuah objek. Dalam kes ini, hujah tambahan diperlukan untuk fungsi MakeCallback, untuk
beritahu sistem pada objek mana fungsi itu harus digunakan. Pertimbangkan contoh ini,
juga dari main-callback.cc:

kelas MyCb {
awam:
int CbTwo (double a) {
std::cout << "invoke cbTwo a=" << a << std::endl;
pulangan -5;
}
};

int utama ()
{
...
// jenis pulangan: int
// jenis arg pertama: double
Panggilan balik dua;
MyCb cb;
// bina contoh panggil balik yang menunjuk ke MyCb::cbTwo
dua = MakeCallback (&MyCb::CbTwo, &cb);
...
}

Di sini, kami menyampaikan penuding objek tambahan ke MakeCallback<> fungsi. Ingat dari
bahagian latar belakang di atas itu Operator() akan menggunakan penuding kepada sintaks ahli apabila ia
dilaksanakan pada objek:

pengendali int maya() (ARG arg)
{
(*m_p.*m_pmi)(arg);
}

Oleh itu, kami perlu menyediakan dua pembolehubah (m_p and m_pmi) apabila kami membuat khusus
fungsi. Garisan itu:

dua = MakeCallback (&MyCb::CbTwo, &cb);

melakukannya dengan tepat. Dalam kes ini, apabila 2 () dipanggil:

int hasil = dua (1.0);

akan mengakibatkan panggilan ke CbDua fungsi ahli (kaedah) pada objek yang ditunjuk oleh
&cb.

Bangunan Menyeimbangkan Panggilan balik
Adalah mungkin untuk panggilan balik menjadi batal; oleh itu mungkin bijak untuk menyemak sebelum menggunakannya.
Terdapat binaan khas untuk panggilan balik nol, yang lebih baik daripada hanya lulus
"0" sebagai hujah; ia adalah MakeNullCallback<> membina:

dua = MakeNullCallback ();
NS_ASSERT (dua.IsNull ());

Menyebut panggilan balik nol sama seperti menggunakan penunjuk fungsi nol: ia akan ranap pada
masa berjalan.

Bound Panggilan balik
Sambungan yang sangat berguna kepada konsep functor ialah Panggilan Balik Terikat. Sebelum ini ia
telah disebut bahawa penutupan pada asalnya adalah panggilan fungsi yang dibungkus untuk kemudian
perlaksanaan. Perhatikan bahawa dalam semua huraian Panggilan Balik di atas, tiada cara untuk
pakejkan sebarang parameter untuk digunakan kemudian -- apabila Panggil balik dipanggil melalui pengendali().
Semua parameter disediakan oleh fungsi panggilan.

Bagaimana jika ia dikehendaki membenarkan fungsi klien (yang menyediakan panggilan balik) untuk
berikan beberapa parameter? Alexandrescu memanggil proses membenarkan pelanggan untuk
nyatakan salah satu parameter "mengikat". Salah satu parameter bagi pengendali() telah
terikat (tetap) oleh klien.

Beberapa kod pengesanan pcap kami memberikan contoh yang bagus tentang ini. Ada fungsi yang
perlu dipanggil setiap kali paket diterima. Fungsi ini memanggil objek yang
sebenarnya menulis paket ke cakera dalam format fail pcap. Tandatangan salah satu daripada ini
fungsi akan menjadi:

kekosongan statik DefaultSink (Ptr fail, Ptr p);

Kata kunci statik bermaksud ini adalah fungsi statik yang tidak memerlukan a ini penunjuk, jadi
ia akan menggunakan panggil balik gaya C. Kami tidak mahu kod panggilan perlu diketahui
apa-apa selain Paket. Apa yang kita mahu dalam kod panggilan hanyalah panggilan yang kelihatan seperti:

m_promiscSnifferTrace (m_currentPkt);

Apa yang kita nak buat ialah mengikat yang Ptr fail kepada panggilan balik tertentu
pelaksanaan apabila ia dicipta dan mengatur untuk pengendali() daripada Panggilan Balik kepada
berikan parameter itu secara percuma.

Kami menyediakan MakeBoundCallback fungsi templat untuk tujuan itu. Ia mengambil masa yang sama
parameter sebagai MakeCallback fungsi templat tetapi juga mengambil parameter untuk menjadi
terikat. Dalam kes contoh di atas:

MakeBoundCallback (&DefaultSink, fail);

akan membuat pelaksanaan panggilan balik khusus yang tahu untuk menambah dalam sempadan tambahan
hujah. Dari segi konsep, ia memanjangkan fungsi khusus yang diterangkan di atas dengan satu atau lebih
hujah terikat:

templat
kelas SpecificFunctor : Functor awam
{
awam:
SpecificFunctor(T* p, int (T::*_pmi)(ARG arg), BOUND_ARG boundArg)
{
m_p = p;
m_pmi = pmi;
m_boundArg = boundArg;
}

pengendali int maya() (ARG arg)
{
(*m_p.*m_pmi)(m_boundArg, arg);
}
peribadi:
batal (T::*m_pmi)(ARG arg);
T* m_p;
BOUND_ARG m_boundArg;
};

Anda boleh melihat bahawa apabila functor khusus dicipta, hujah terikat disimpan dalam
objek functor / panggil balik itu sendiri. Apabila pengendali() dipanggil dengan single
parameter, seperti dalam:

m_promiscSnifferTrace (m_currentPkt);

pelaksanaan pengendali() menambah parameter terikat ke dalam panggilan fungsi sebenar:

(*m_p.*m_pmi)(m_boundArg, arg);

Ia mungkin untuk mengikat dua atau tiga hujah juga. Katakan kita mempunyai fungsi dengan
tandatangan:

lompang statik NotifyEvent (Ptr a, Ptr b, MyEventType e);

Seseorang boleh membuat panggilan balik terikat yang mengikat dua hujah pertama seperti:

MakeBoundCallback (&NotifyEvent, a1, b1);

dengan anggapan a1 and b1 adalah objek jenis A and B masing-masing. Begitu juga untuk tiga
hujah yang akan berfungsi dengan tandatangan:

lompang statik NotifyEvent (Ptr a, Ptr b, MyEventType e);

Mengikat tiga hujah dilakukan dengan:

MakeBoundCallback (&NotifyEvent, a1, b1, c1);

sekali lagi andaian a1, b1 and c1 adalah objek jenis A, B and C masing-masing.

Ikatan jenis ini boleh digunakan untuk bertukar-tukar maklumat antara objek dalam simulasi;
khususnya, panggilan balik terikat boleh digunakan sebagai panggilan balik yang dikesan, yang akan diterangkan dalam
bahagian seterusnya.

Dikesan Panggilan balik
Pemegang Tempat subseksyen

Panggil balik lokasi in ns-3
Di manakah panggilan balik sering digunakan ns-3? Berikut adalah beberapa yang lebih kelihatan kepada
pengguna biasa:

· API Soket

· API Layer-2/Layer-3

· Mengesan subsistem

· API antara IP dan subsistem penghalaan

Pelaksanaan butir-butir
Coretan kod di atas adalah ringkas dan hanya direka bentuk untuk menggambarkan mekanisme
sendiri. Kod Panggilan Balik sebenar agak rumit dan sangat templat-intens dan a
pemahaman yang mendalam tentang kod tidak diperlukan. Jika berminat, pengguna pakar mungkin mencari
berikut berguna.

Kod ini pada asalnya ditulis berdasarkan teknik yang diterangkan dalam
http://www.codeproject.com/cpp/TTLFunction.asp. Ia kemudiannya ditulis semula untuk diikuti
seni bina yang digariskan dalam Moden C + + reka bentuk, Generik Pengaturcaraan and reka bentuk Corak
digunakan, Alexandrescu, bab 5, Umum Fungsi.

Kod ini menggunakan:

· parameter templat lalai untuk menyelamatkan pengguna daripada perlu menentukan parameter kosong apabila
bilangan parameter adalah lebih kecil daripada nombor maksimum yang disokong

· simpulan bahasa pimpl: kelas Panggilan Balik diedarkan mengikut nilai dan mewakilkan intipati
kerja ke penunjuk jerawatnya.

· dua pelaksanaan pimpl yang berasal daripada CallbackImpl FunctorCallbackImpl boleh digunakan
dengan mana-mana jenis functor manakala MemPtrCallbackImpl boleh digunakan dengan penunjuk kepada ahli
fungsi.

· pelaksanaan senarai rujukan untuk melaksanakan semantik nilai Panggilan Balik.

Kod ini terutamanya berlepas daripada pelaksanaan Alexandrescu kerana ia tidak
gunakan senarai jenis untuk menentukan dan menyampaikan jenis argumen panggil balik. Sudah tentu,
ia juga tidak menggunakan semantik pemusnahan salinan dan bergantung pada senarai rujukan dan bukannya
autoPtr untuk memegang penunjuk.

Objek model
ns-3 pada asasnya ialah sistem objek C++. Objek boleh diisytiharkan dan dijadikan instantiated sebagai
biasa, mengikut peraturan C++. ns-3 juga menambah beberapa ciri pada objek C++ tradisional, sebagai
diterangkan di bawah, untuk menyediakan fungsi dan ciri yang lebih besar. Bab manual ini ialah
bertujuan untuk memperkenalkan pembaca kepada ns-3 model objek.

Bahagian ini menerangkan reka bentuk kelas C++ untuk ns-3 objek. Secara ringkas, beberapa reka bentuk
corak yang digunakan termasuk reka bentuk berorientasikan objek klasik (antara muka polimorfik dan
pelaksanaan), pengasingan antara muka dan pelaksanaan, orang awam bukan maya
corak reka bentuk antara muka, kemudahan pengagregatan objek, dan pengiraan rujukan untuk
pengurusan ingatan. Mereka yang biasa dengan model komponen seperti COM atau Bonobo akan
mengenali elemen reka bentuk dalam ns-3 model pengagregatan objek, walaupun ns-3
reka bentuk tidak sepenuhnya mengikut sama ada.

Berorientasikan objek tingkah laku
Objek C++, secara amnya, menyediakan keupayaan berorientasikan objek biasa (abstraksi,
enkapsulasi, pewarisan dan polimorfisme) yang merupakan sebahagian daripada berorientasikan objek klasik
reka bentuk. ns-3 objek menggunakan sifat ini; contohnya:

Alamat kelas
{
awam:
Alamat ();
Alamat (jenis uint8_t, const uint8_t *buffer, uint8_t len);
Alamat (const Alamat & alamat);
Alamat &operator = (const Alamat &alamat);
...
peribadi:
uint8_t m_type;
uint8_t m_len;
...
};

Objek asas kelas
Terdapat tiga kelas asas khas yang digunakan dalam ns-3. Kelas yang mewarisi daripada pangkalan ini
kelas boleh membuat instantiate objek dengan sifat khas. Kelas asas ini ialah:

· kelas Objek

· kelas ObjectBase

· kelas SimpleRefCount

Ia tidak disyaratkan begitu ns-3 objek mewarisi daripada kelas ini, tetapi yang mendapat
sifat khas. Kelas yang berasal dari kelas Objek dapatkan sifat berikut.

· yang ns-3 jenis dan sistem atribut (lihat Atribut)

· sistem pengagregatan objek

· sistem pengiraan rujukan penunjuk pintar (kelas Ptr)

Kelas yang berasal dari kelas ObjectBase dapatkan dua sifat pertama di atas, tetapi jangan
dapatkan petunjuk pintar. Kelas yang berasal dari kelas SimpleRefCount: dapatkan hanya
sistem pengiraan rujukan penunjuk pintar.

Dalam amalan, kelas Objek ialah varian ketiga-tiga di atas iaitu ns-3 pemaju akan
paling biasa ditemui.

Memori pengurusan and kelas Ptr
Pengurusan memori dalam program C++ adalah proses yang kompleks, dan selalunya dilakukan secara tidak betul atau
secara tidak konsisten. Kami telah menyelesaikan reka bentuk pengiraan rujukan yang diterangkan seperti berikut.

Semua objek yang menggunakan pengiraan rujukan mengekalkan kiraan rujukan dalaman untuk ditentukan
apabila objek boleh memadam sendiri dengan selamat. Setiap kali penuding diperolehi ke an
antara muka, kiraan rujukan objek ditambah dengan memanggil Ruj(). Ia adalah
kewajipan pengguna penunjuk untuk secara eksplisit Unref() penunjuk apabila selesai. Bila
kiraan rujukan jatuh kepada sifar, objek dipadamkan.

· Apabila kod klien memperoleh penunjuk daripada objek itu sendiri melalui penciptaan objek,
atau melalui GetObject, ia tidak perlu menambah bilangan rujukan.

· Apabila kod klien memperoleh penunjuk daripada sumber lain (cth, menyalin penunjuk) ia mesti
memanggil Ruj() untuk menambah bilangan rujukan.

· Semua pengguna penunjuk objek mesti memanggil Unref() untuk mengeluarkan rujukan.

Beban untuk memanggil Unref() agak lega dengan penggunaan pengiraan rujukan
kelas penunjuk pintar yang diterangkan di bawah.

Pengguna yang menggunakan API peringkat rendah yang ingin memperuntukkan objek yang tidak dikira rujukan secara eksplisit
pada timbunan, menggunakan operator baru, bertanggungjawab untuk memadam objek tersebut.

Rujukan mengira pintar penunjuk (Ptr)
Memanggil Ruj() and Unref() sepanjang masa akan menyusahkan, jadi ns-3 menyediakan pintar
kelas penunjuk Ptr sama dengan Boost::intrusive_ptr. Kelas penunjuk pintar ini menganggapnya
jenis asas menyediakan sepasang Ref and Unref kaedah yang diharapkan
kenaikan dan pengurangan kiraan semula dalaman contoh objek.

Pelaksanaan ini membolehkan anda memanipulasi penunjuk pintar seolah-olah ia adalah perkara biasa
penunjuk: anda boleh membandingkannya dengan sifar, bandingkan dengan penunjuk lain, tetapkan sifar kepada
ia, dsb.

Ia adalah mungkin untuk mengekstrak penunjuk mentah daripada penunjuk pintar ini dengan GetPointer()
and PeekPointer() kaedah.

Jika anda ingin menyimpan objek baharu ke dalam penunjuk pintar, kami mengesyorkan anda menggunakan
Templat CreateObject berfungsi untuk mencipta objek dan menyimpannya dalam penunjuk pintar ke
mengelakkan kebocoran ingatan. Fungsi ini adalah fungsi kemudahan yang sangat kecil dan matlamatnya
hanyalah untuk menjimatkan sedikit menaip anda.

CreateObject and Buat
Objek dalam C++ mungkin dibuat secara statik, dinamik atau secara automatik. Ini benar
khususnya ns-3 juga, tetapi sesetengah objek dalam sistem mempunyai beberapa rangka kerja tambahan yang tersedia.
Khususnya, objek yang dikira rujukan biasanya diperuntukkan menggunakan templat Buat atau
Kaedah CreateObject, seperti berikut.

Untuk objek yang berasal dari kelas Objek:

Ptr peranti = CreateObject ();

Tolong jangan cipta objek sedemikian menggunakan operator baru; cipta mereka menggunakan CreateObject()
sebaliknya.

Untuk objek yang berasal dari kelas SimpleRefCount, atau objek lain yang menyokong penggunaan
kelas penunjuk pintar, fungsi pembantu templat tersedia dan disyorkan untuk digunakan:

Ptr b = Cipta ();

Ini hanyalah pembalut di sekitar operator baharu yang mengendalikan pengiraan rujukan dengan betul
sistem.

Secara ringkasnya, gunakan Buat jika B bukan objek tetapi hanya menggunakan pengiraan rujukan (cth
Bungkusan, dan gunakan CreateObject jika B terbit daripada ns3::Objek.

pengagregatan
. ns-3 sistem pengagregatan objek didorong sebahagian besarnya oleh pengiktirafan bahawa a
kes penggunaan biasa untuk ns-2 telah menjadi penggunaan warisan dan polimorfisme untuk melanjutkan
model protokol. Sebagai contoh, versi khusus TCP seperti RenoTcpAgent diperolehi
daripada (dan mengatasi fungsi daripada) kelas TcpAgent.

Namun, dua masalah yang timbul dalam ns-2 model adalah downcasts dan "asas lemah
kelas." Downcasting merujuk kepada prosedur menggunakan penunjuk kelas asas kepada objek dan
menanyakannya pada masa larian untuk mengetahui maklumat jenis, digunakan untuk menghantar penuding secara eksplisit
kepada penuding subkelas supaya API subkelas boleh digunakan. Kelas asas yang lemah merujuk kepada
masalah yang timbul apabila kelas tidak boleh digunakan semula dengan berkesan (diperolehi daripada) kerana ia
tidak mempunyai fungsi yang diperlukan, menyebabkan pembangun terpaksa mengubah suai kelas asas dan
menyebabkan percambahan panggilan API kelas asas, sesetengah daripadanya mungkin tidak secara semantik
betul untuk semua subkelas.

ns-3 sedang menggunakan versi corak reka bentuk antara muka pertanyaan untuk mengelakkan masalah ini.
Reka bentuk ini adalah berdasarkan unsur-unsur Komponen Objek model and GNOME Bonobo walaupun
keserasian penuh peringkat binari bagi komponen yang boleh diganti tidak disokong dan kami ada
cuba memudahkan sintaks dan kesan pada pembangun model.

Contoh
pengagregatan contoh
nod adalah contoh yang baik bagi penggunaan pengagregatan dalam ns-3. Perhatikan bahawa tidak ada terbitan
kelas Nod dalam ns-3 seperti kelas InternetNode. Sebaliknya, komponen (protokol) adalah
diagregatkan kepada nod. Mari lihat bagaimana beberapa protokol Ipv4 ditambahkan pada nod.:

kekosongan statik
AddIpv4Stack(Ptr nod)
{
Ptr ipv4 = CreateObject ();
ipv4->SetNode (nod);
nod->AggregateObject (ipv4);
Ptr ipv4Impl = CreateObject ();
ipv4Impl->SetIpv4 (ipv4);
nod->AggregateObject (ipv4Impl);
}

Ambil perhatian bahawa protokol IPv4 dicipta menggunakan CreateObject(). Kemudian, mereka diagregatkan
ke nod. Dengan cara ini, kelas asas Node tidak perlu diedit untuk membolehkan pengguna
dengan penuding Nod kelas asas untuk mengakses antara muka Ipv4; pengguna boleh meminta nod untuk a
penunjuk kepada antara muka Ipv4 pada masa jalan. Cara pengguna meminta nod diterangkan dalam
subseksyen seterusnya.

Ambil perhatian bahawa ia adalah ralat pengaturcaraan untuk mengagregatkan lebih daripada satu objek daripada jenis yang sama
an ns3::Objek. Jadi, sebagai contoh, pengagregatan bukanlah pilihan untuk menyimpan semua
soket aktif nod.

GetObject contoh
GetObject ialah cara selamat jenis untuk mencapai penurunan yang selamat dan membenarkan antara muka
ditemui pada sesuatu objek.

Pertimbangkan penunjuk nod m_node yang menunjuk kepada objek Nod yang mempunyai pelaksanaan
IPv4 sebelum ini diagregatkan kepadanya. Kod pelanggan ingin mengkonfigurasi laluan lalai. Kepada
berbuat demikian, ia mesti mengakses objek dalam nod yang mempunyai antara muka ke pemajuan IP
konfigurasi. Ia melaksanakan perkara berikut:

Ptr ipv4 = m_node->GetObject ();

Jika nod sebenarnya tidak mempunyai objek Ipv4 yang diagregatkan kepadanya, maka kaedah itu akan
kembali null. Oleh itu, adalah amalan yang baik untuk menyemak nilai pulangan daripada fungsi sedemikian
panggilan. Jika berjaya, pengguna kini boleh menggunakan Ptr ke objek Ipv4 yang sebelum ini
diagregatkan kepada nod.

Satu lagi contoh bagaimana seseorang mungkin menggunakan pengagregatan ialah menambah model pilihan pada objek. Untuk
contoh, objek Nod sedia ada mungkin mempunyai objek "Model Tenaga" yang diagregatkan padanya
masa jalankan (tanpa mengubah suai dan menyusun semula kelas nod). Model sedia ada (seperti a
peranti bersih wayarles) kemudian boleh "GetObject" untuk model tenaga dan bertindak dengan sewajarnya
jika antara muka telah dibina sama ada pada objek Nod yang mendasari atau diagregatkan kepada
ia pada masa berjalan. Walau bagaimanapun, nod lain tidak perlu mengetahui apa-apa tentang model tenaga.

Kami berharap mod pengaturcaraan ini akan memerlukan lebih sedikit keperluan untuk pembangun mengubah suai
kelas asas.

Objek kilang-kilang
Kes penggunaan biasa adalah untuk mencipta banyak objek yang dikonfigurasikan serupa. Satu boleh berulang kali
memanggil CreateObject() tetapi terdapat juga corak reka bentuk kilang yang digunakan dalam ns-3 sistem.
Ia banyak digunakan dalam API "pembantu".

Kelas ObjectFactory boleh digunakan untuk membuat instantiate objek dan untuk mengkonfigurasi atribut pada
objek tersebut:

batal SetTypeId (TidTypeId);
void Set (std::string name, const AttributeValue &value);
Ptr Cipta (kosong) const;

Kaedah pertama membolehkan seseorang menggunakan ns-3 Sistem TypeId untuk menentukan jenis objek
dicipta. Yang kedua membolehkan seseorang menetapkan atribut pada objek yang akan dibuat, dan
ketiga membolehkan seseorang mencipta objek itu sendiri.

Sebagai contoh:

kilang ObjectFactory;
// Jadikan kilang ini mencipta objek jenis FriisPropagationLossModel
factory.SetTypeId ("ns3::FriisPropagationLossModel")
// Jadikan objek kilang ini menukar nilai lalai atribut, untuk
// objek yang dicipta kemudiannya
factory.Set ("SystemLoss", DoubleValue (2.0));
// Cipta satu objek sedemikian
Ptr objek = kilang.Buat ();
factory.Set ("SystemLoss", DoubleValue (3.0));
// Cipta objek lain dengan SystemLoss yang berbeza
Ptr objek = kilang.Buat ();

Menurunkan
Soalan yang telah timbul beberapa kali ialah, "Jika saya mempunyai penunjuk kelas asas (Ptr) ke an
objek dan saya mahukan penuding kelas yang diperolehi, sekiranya saya kecewa (melalui pelakon dinamik C++) ke
dapatkan penunjuk terbitan, atau patutkah saya menggunakan sistem pengagregatan objek untuk GetObject<> ()
untuk mencari Ptr kepada antara muka kepada API subkelas?"

Jawapan untuk ini ialah dalam banyak situasi, kedua-dua teknik akan berfungsi. ns-3 menyediakan
fungsi templat untuk menjadikan sintaks pemutus dinamik Objek lebih banyak pengguna
mesra:

templat
Ptr
DynamicCast (Ptr const&p)
{
pulangkan Ptr (dynamic_cast (PeekPointer (p)));
}

DynamicCast berfungsi apabila pengaturcara mempunyai penunjuk jenis asas dan sedang menguji terhadap a
penunjuk subkelas. GetObject berfungsi apabila mencari objek yang berbeza digabungkan, tetapi juga
berfungsi dengan subkelas, dengan cara yang sama seperti DynamicCast. Jika tidak pasti, pengaturcara harus
gunakan GetObject, kerana ia berfungsi dalam semua kes. Jika pengaturcara mengetahui hierarki kelas bagi
objek yang sedang dipertimbangkan, adalah lebih langsung untuk hanya menggunakan DynamicCast.

konfigurasi and Atribut
In ns-3 simulasi, terdapat dua aspek utama untuk konfigurasi:

· Topologi simulasi dan cara objek disambungkan.

· Nilai yang digunakan oleh model yang digunakan dalam topologi.

Bab ini memfokuskan pada item kedua di atas: berapa banyak nilai yang digunakan dalam ns-3 adalah
dianjurkan, didokumenkan dan boleh diubah suai oleh ns-3 pengguna. The ns-3 sistem atribut juga adalah
asas tentang cara jejak dan statistik dikumpulkan dalam simulator.

Dalam perjalanan bab ini kita akan membincangkan pelbagai cara untuk menetapkan atau mengubah suai nilai
digunakan oleh ns-3 objek model. Dalam susunan kekhususan yang semakin meningkat, ini adalah:

┌─────────────────────────────────┬─────────────── ───────────────────┐
│Kaedah │ Skop │
├─────────────────────────────────┼─────────────── ───────────────────┤
│Nilai Atribut Lalai ditetapkan │ Mempengaruhi semua kejadian │
│apabila Atribut ditakrifkan dalam kelas │. │
GetTypeId (). │ │
└─────────────────────────────────┴─────────────── ───────────────────┘

Talian Perintah │ Menjejaskan semua kejadian akan datang. │
Config::SetDefault() │ │
ConfigStore │ │
├─────────────────────────────────┼─────────────── ───────────────────┤
ObjectFactory │ Mempengaruhi semua kejadian yang dibuat │
│ │ dengan kilang. │
├─────────────────────────────────┼─────────────── ───────────────────┤
XHelperSetAttribute () │ Mempengaruhi semua kejadian yang dibuat oleh │
│ │ penolong. │
├─────────────────────────────────┼─────────────── ───────────────────┤
MyClass::SetX () │ Mengubah contoh khusus ini. │
Objek::SetAttribute () │ Secara umumnya ini adalah satu-satunya bentuk │
Konfigurasi::Set() │ yang boleh dijadualkan untuk diubah │
│ │ contoh sekali simulasi │
│ │ sedang berjalan. │
└─────────────────────────────────┴─────────────── ───────────────────┘

Dengan "kekhususan" yang kami maksudkan bahawa kaedah dalam baris kemudian dalam jadual mengatasi nilai yang ditetapkan
oleh, dan biasanya mempengaruhi lebih sedikit contoh daripada kaedah terdahulu.

Sebelum menyelidiki butiran sistem nilai atribut, ia akan membantu untuk menyemak beberapa
sifat asas kelas Objek.

Objek Pengenalan
ns-3 pada asasnya adalah sistem berasaskan objek C++. Dengan ini kami maksudkan bahawa kelas C++ baharu
(jenis) boleh diisytiharkan, ditakrifkan dan disubkelaskan seperti biasa.

banyak ns-3 objek yang diwarisi daripada Objek kelas asas. Objek ini mempunyai beberapa tambahan
sifat yang kami eksploitasi untuk mengatur sistem dan menambah baik pengurusan memori
objek kami:

· Sistem "Metadata" yang memautkan nama kelas kepada banyak maklumat meta tentang
objek, termasuk:

· Kelas asas subkelas,

· Set pembina boleh diakses dalam subkelas,

· Set "atribut" subkelas,

· Sama ada setiap atribut boleh ditetapkan, atau dibaca sahaja,

· Julat nilai yang dibenarkan untuk setiap atribut.

· Rujukan mengira pelaksanaan penunjuk pintar, untuk pengurusan ingatan.

ns-3 objek yang menggunakan sistem atribut berasal daripada sama ada Objek or ObjectBase. Kebanyakan
ns-3 objek yang akan kita bincangkan berasal daripada Objek, tetapi beberapa yang berada di luar pintar
rangka kerja pengurusan memori penunjuk berasal daripada ObjectBase.

Mari kita semak beberapa sifat objek ini.

Pintar petunjuk
Seperti yang diperkenalkan dalam ns-3 tutorial, ns-3 objek ialah ingatan yang diuruskan oleh a rujukan
mengira pintar penunjuk pelaksanaan, kelas Ptr.

Petunjuk pintar digunakan secara meluas dalam ns-3 API, untuk mengelak daripada menghantar rujukan kepada
objek yang diperuntukkan timbunan yang boleh menyebabkan kebocoran memori. Untuk kebanyakan penggunaan asas (sintaks), rawat
penunjuk pintar seperti penunjuk biasa:

Ptr nd = ...;
nd->CallSomeFunction ();
// dan lain-lain.

Jadi bagaimana anda mendapatkan penunjuk pintar ke objek, seperti dalam baris pertama contoh ini?

CreateObject
Seperti yang kita bincangkan di atas dalam Pengurusan-memori-dan-kelas-Ptr, pada API peringkat terendah, objek
jenis Objek tidak digunakan segera operator baru seperti biasa tetapi sebaliknya dengan templat
fungsi dipanggil CreateObject ().

Cara biasa untuk mencipta objek sedemikian adalah seperti berikut:

Ptr nd = CreateObject ();

Anda boleh menganggap ini sebagai fungsi yang setara dengan:

WifiNetDevice* nd = WifiNetDevice baharu ();

Objek yang terbit daripada Objek mesti diperuntukkan pada timbunan menggunakan CreateObject (). Mereka
berasal dari ObjectBase, Seperti ns-3 fungsi pembantu dan pengepala paket dan treler,
boleh diperuntukkan pada timbunan.

Dalam sesetengah skrip, anda mungkin tidak melihat banyak skrip CreateObject () panggilan dalam kod; ini adalah
kerana terdapat beberapa objek pembantu yang berkuat kuasa yang melakukan CreateObject () panggilan
untuk anda.

JenisId
ns-3 kelas yang berasal dari kelas Objek boleh memasukkan kelas metadata yang dipanggil JenisId Bahawa
merekodkan maklumat meta tentang kelas, untuk digunakan dalam pengagregatan objek dan komponen
sistem pengurus:

· Rentetan unik yang mengenal pasti kelas.

· Kelas asas subkelas, dalam sistem metadata.

· Set pembina boleh diakses dalam subkelas.

· Senarai sifat boleh diakses secara umum ("atribut") kelas.

Objek Ringkasan
Menggabungkan semua konsep ini, mari lihat contoh khusus: kelas nod.

Fail pengepala awam nod.h mempunyai pengisytiharan yang termasuk statik GetTypeId ()
panggilan fungsi:

Nod kelas : Objek awam
{
awam:
TypeId GetTypeId statik (kosong);
...

Ini ditakrifkan dalam node.cc fail seperti berikut:

JenisId
Node::GetTypeId (kosong)
{
statik TypeId tid = TypeId ("ns3::Node")
.SetParent ()
.AddConstructor ()
.AddAttribute ("DeviceList",
"Senarai peranti yang dikaitkan dengan Nod ini.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Nod::m_devices),
MakeObjectVectorChecker ())
.AddAttribute ("ApplicationList",
"Senarai aplikasi yang dikaitkan dengan Nod ini.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Node::m_applications),
MakeObjectVectorChecker ())
.AddAttribute ("Id",
"Id (integer unik) Nod ini.",
TypeId::ATTR_GET, // benarkan mendapatkannya sahaja.
UintegerValue (0),
MakeUintegerAccessor (&Nod::m_id),
MakeUintegerChecker ())
;
tid balik;
}

Pertimbangkan JenisId daripada ns-3 Objek kelas sebagai bentuk lanjutan jenis masa larian
maklumat (RTTI). Bahasa C++ termasuk jenis RTTI yang mudah untuk menyokong
siaran_ dinamik and Typeid pengendali.

. SetParent () panggilan dalam definisi di atas digunakan bersama-sama dengan kami
mekanisme pengagregatan objek untuk membolehkan penuangan atas dan bawah yang selamat dalam pokok warisan
semasa GetObject (). Ia juga membolehkan subkelas mewarisi Atribut induknya
kelas.

. AddConstructor () panggilan digunakan bersama dengan kilang objek abstrak kami
mekanisme untuk membolehkan kami membina objek C++ tanpa memaksa pengguna mengetahui
kelas konkrit objek yang dia bina.

Ketiga-tiga memanggil TambahAtribut () kaitkan rentetan yang diberikan dengan nilai yang ditaip kuat
kelas. Perhatikan bahawa anda mesti menyediakan rentetan bantuan yang mungkin dipaparkan, sebagai contoh,
melalui pemproses baris arahan. setiap satu atribut dikaitkan dengan mekanisme untuk mengakses
pembolehubah ahli asas dalam objek (contohnya, MakeUintegerAccessor () memberitahu
yang generik atribut kod bagaimana untuk sampai ke ID nod di atas). Terdapat juga "Pemeriksa"
kaedah yang digunakan untuk mengesahkan nilai terhadap had julat, seperti maksimum dan
nilai minimum yang dibenarkan.

Apabila pengguna ingin mencipta Nod, mereka biasanya akan memanggil beberapa bentuk CreateObject (),:

Ptr n = CreateObject ();

atau lebih abstrak, menggunakan kilang objek, anda boleh membuat a nod objek tanpa genap
mengetahui jenis C++ konkrit:

kilang ObjectFactory;
const std::string typeId = "ns3::Node'';
factory.SetTypeId (typeId);
Ptr nod = kilang.Buat ();

Kedua-dua kaedah ini menghasilkan atribut yang dimulakan sepenuhnya tersedia dalam
mengakibatkan Objek contoh.

Kami seterusnya membincangkan bagaimana atribut (nilai yang dikaitkan dengan pembolehubah ahli atau fungsi
kelas) dimasukkan ke dalam perkara di atas JenisId.

Atribut
Matlamat sistem atribut adalah untuk mengatur capaian objek ahli dalaman a
simulasi. Matlamat ini timbul kerana, biasanya dalam simulasi, pengguna akan memotong dan
tampal/ubah suai skrip simulasi sedia ada, atau akan menggunakan pembinaan simulasi peringkat lebih tinggi,
tetapi selalunya akan berminat untuk mengkaji atau mengesan pembolehubah dalaman tertentu. Untuk
contohnya, kes penggunaan seperti:

· "I mahu kepada mengesan yang paket on yang wayarles antara muka hanyalah on yang pertama mengakses titik."

· "I mahu kepada mengesan yang nilai of yang TCP kesesakan tetingkap (setiap masa it perubahan) on a
tertentu TCP soket."

· "I mahu a membuang of semua nilai Bahawa adalah digunakan in my simulasi."

Begitu juga, pengguna mungkin mahukan akses terperinci kepada pembolehubah dalaman dalam simulasi, atau
mungkin mahu menukar secara meluas nilai awal yang digunakan untuk parameter tertentu dalam semua
objek yang dicipta kemudiannya. Akhir sekali, pengguna mungkin ingin mengetahui pembolehubah yang boleh ditetapkan
dan boleh diperoleh semula dalam konfigurasi simulasi. Ini bukan sahaja untuk simulasi langsung
interaksi pada baris arahan; pertimbangkan juga antara muka pengguna grafik (masa hadapan) yang
ingin dapat menyediakan ciri yang membolehkan pengguna mengklik kanan pada nod pada
kanvas dan lihat senarai parameter berhierarki dan teratur yang boleh ditetapkan pada
nod dan objek ahli konstituennya, dan teks bantuan dan nilai lalai untuk setiap satu
parameter.

Menetapkan Atribut
Kami menyediakan satu cara untuk pengguna mengakses nilai jauh di dalam sistem, tanpa perlu mencari
aksesori (penunjuk) melalui sistem dan rantai penunjuk berjalan untuk sampai ke mereka. Pertimbangkan a
kelas DropTailQueue yang mempunyai pembolehubah ahli yang merupakan integer tidak bertanda m_maxPackets;
pembolehubah ahli ini mengawal kedalaman baris gilir.

Jika kita lihat pada pengisytiharan DropTailQueue, kita lihat perkara berikut:

kelas DropTailQueue : Public Queue {
awam:
TypeId GetTypeId statik (kosong);
...

peribadi:
std:: beratur > m_paket;
uint32_t m_maxPackets;
};

Mari kita pertimbangkan perkara yang pengguna mungkin mahu lakukan dengan nilai m_maxPackets:

· Tetapkan nilai lalai untuk sistem, supaya apabila ia baru DropTailQueue dicipta,
ahli ini dimulakan kepada lalai itu.

· Tetapkan atau dapatkan nilai pada baris gilir yang telah dibuat segera.

Perkara di atas biasanya memerlukan penyediaan Tetapkan () and Dapatkan () fungsi, dan beberapa jenis
nilai lalai global.

Dalam ns-3 sistem atribut, definisi nilai ini dan pendaftaran fungsi pengakses
dipindahkan ke dalam JenisId kelas; contohnya..:

NS_OBJECT_ENSURE_REGISTERED (DropTailQueue);

JenisId
DropTailQueue::GetTypeId (kosong)
{
statik TypeId tid = TypeId ("ns3::DropTailQueue")
.SetParent ()
.AddConstructor ()
.AddAttribute ("MaxPackets",
"Bilangan maksimum paket yang diterima oleh DropTailQueue ini.",
UintegerValue (100),
MakeUintegerAccessor (&DropTailQueue::m_maxPackets),
MakeUintegerChecker ())
;

tid balik;
}

. TambahAtribut () kaedah melaksanakan beberapa perkara untuk m_maxPackets nilai:

· Mengikat pembolehubah ahli (biasanya persendirian). m_maxPackets kepada rentetan awam
"MaxPackets".

· Menyediakan nilai lalai (100 paket).

· Menyediakan beberapa teks bantuan mentakrifkan maksud nilai.

· Menyediakan "Pemeriksa" (tidak digunakan dalam contoh ini) yang boleh digunakan untuk menetapkan had pada
julat nilai yang dibenarkan.

Perkara utama ialah kini nilai pembolehubah ini dan nilai lalainya boleh diakses
dalam ruang nama atribut, yang berdasarkan rentetan seperti "MaxPackets" and JenisId nama
rentetan. Dalam bahagian seterusnya, kami akan menyediakan skrip contoh yang menunjukkan cara pengguna boleh
memanipulasi nilai-nilai ini.

Ambil perhatian bahawa permulaan atribut bergantung pada makro NS_OBJECT_ENSURE_REGISTERED
(DropTailQueue) dipanggil; jika anda meninggalkan ini daripada pelaksanaan kelas baharu anda, your
atribut tidak akan dimulakan dengan betul.

Walaupun kami telah menerangkan cara membuat atribut, kami masih belum menerangkan cara mengakses
dan mengurus nilai-nilai ini. Sebagai contoh, tidak ada globals.h fail pengepala di mana ini berada
disimpan; atribut disimpan dengan kelas mereka. Persoalan yang timbul secara semula jadi ialah bagaimana
adakah pengguna mengetahui dengan mudah tentang semua sifat model mereka dan bagaimanakah pengguna
mengakses atribut ini, atau mendokumenkan nilainya sebagai sebahagian daripada rekodnya
simulasi?

Dokumentasi terperinci tentang atribut sebenar yang ditakrifkan untuk jenis, dan senarai global
semua atribut yang ditentukan, tersedia dalam dokumentasi API. Untuk selebihnya ini
dokumen kami akan menunjukkan pelbagai cara untuk mendapatkan dan menetapkan atribut
nilai-nilai.

Menetapkan Lalai Nilai-nilai
Config::SetDefault and Talian Perintah
Mari lihat bagaimana skrip pengguna boleh mengakses nilai atribut tertentu. Kami akan
menggunakan src/point-to-point/examples/main-attribute-value.cc skrip untuk ilustrasi, dengan
beberapa butiran dilucutkan. The utama fungsi bermula:

// Ini adalah contoh asas cara menggunakan sistem atribut untuk
// tetapkan dan dapatkan nilai dalam sistem asas; iaitu, unsigned
// integer bilangan maksimum paket dalam baris gilir
//

int
utama (int argc, char *argv[])
{

// Secara lalai, atribut MaxPackets mempunyai nilai 100 paket
// (lalai ini boleh diperhatikan dalam fungsi DropTailQueue::GetTypeId)
//
// Di sini, kami menetapkannya kepada 80 paket. Kita boleh menggunakan salah satu daripada dua jenis nilai:
// nilai berasaskan rentetan atau nilai Uinteger
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("80"));
// Panggilan fungsi di bawah adalah berlebihan
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (80));

// Benarkan pengguna mengatasi mana-mana lalai dan perkara di atas
// SetDefaults () semasa run-time, melalui argumen baris arahan
// Contohnya, melalui "--ns3::DropTailQueue::MaxPackets=80"
cmd Baris Perintah;
// Ini menyediakan satu lagi cara untuk menetapkan nilai daripada baris arahan:
cmd.AddValue ("maxPackets", "ns3::DropTailQueue::MaxPackets");
cmd.Parse (argc, argv);

Perkara utama yang perlu diperhatikan dalam perkara di atas ialah dua panggilan yang setara Config::SetDefault
(). Beginilah cara kami menetapkan nilai lalai untuk semua yang dibuat kemudiannya
DropTailQueues. Kami menggambarkan bahawa dua jenis nilai kelas, a StringValue dan
UintegerValue class, boleh digunakan untuk memberikan nilai kepada atribut yang dinamakan oleh
"ns3::DropTailQueue::MaxPackets".

Ia juga mungkin untuk memanipulasi Atribut menggunakan Talian Perintah; kami melihat beberapa contoh
awal dalam Tutorial. Khususnya, adalah mudah untuk menambah hujah singkatan
nama, seperti --maxPackets, untuk Atribut yang berkaitan khusus untuk model anda,
dalam kes ini "ns3::DropTailQueue::MaxPackets". Ini mempunyai ciri tambahan yang
rentetan bantuan untuk Atribut akan dicetak sebagai sebahagian daripada mesej penggunaan untuk skrip.
Untuk maklumat lanjut lihat Talian Perintah dokumentasi API.

Sekarang, kami akan mencipta beberapa objek menggunakan API peringkat rendah. Barisan gilir kami yang baru dibuat akan
tidak ada m_maxPackets dimulakan kepada 100 paket, seperti yang ditakrifkan dalam
DropTailQueue::GetTypeId () fungsi, tetapi kepada 80 paket, kerana apa yang kami lakukan di atas
nilai lalai.:

Ptr n0 = CreateObject ();

Ptr net0 = CreateObject ();
n0->TambahPeranti (net0);

Ptr q = CreateObject ();
net0->AddQueue(q);

Pada ketika ini, kami telah mencipta satu nod (n0) dan tunggal PointToPointNetDevice
(net0), dan ditambah a DropTailQueue (q) Untuk net0.

Pembina, Pembantu and ObjectFactory
Gabungan atribut sewenang-wenangnya boleh ditetapkan dan diambil daripada pembantu dan peringkat rendah
API; sama ada daripada pembina itu sendiri:

Ptr p =
CreateObjectWithAttributes
("MinX", DoubleValue (-100.0),
"MinY", DoubleValue (-100.0),
"DeltaX", DoubleValue (5.0),
"DeltaY", DoubleValue (20.0),
"GridWidth", UintegerValue (20),
"LayoutType", StringValue ("RowFirst"));

atau daripada API pembantu peringkat lebih tinggi, seperti:

mobiliti.SetPositionAllocator
("ns3::GridPositionAllocator",
"MinX", DoubleValue (-100.0),
"MinY", DoubleValue (-100.0),
"DeltaX", DoubleValue (5.0),
"DeltaY", DoubleValue (20.0),
"GridWidth", UintegerValue (20),
"LayoutType", StringValue ("RowFirst"));

Kami tidak menggambarkannya di sini, tetapi anda juga boleh mengkonfigurasi a ObjectFactory dengan nilai-nilai baru
untuk atribut tertentu. Kejadian yang dibuat oleh ObjectFactory akan mempunyai mereka
atribut yang ditetapkan semasa pembinaan. Ini sangat serupa dengan menggunakan salah satu API pembantu
untuk kelas.

Untuk menyemak, terdapat beberapa cara untuk menetapkan nilai untuk atribut untuk contoh kelas kepada be
diwujudkan in yang masa depan:

· Config::SetDefault ()

· CommandLine::AddValue ()

· CreateObjectWithAttributes<> ()

· Pelbagai API pembantu

Tetapi bagaimana jika anda telah mencipta contoh, dan anda mahu menukar nilai
atribut? Dalam contoh ini, bagaimana kita boleh memanipulasi m_maxPackets nilai yang sudah
instantiated DropTailQueue? Berikut adalah pelbagai cara untuk melakukannya.

menukar Nilai-nilai
SmartPointer
Andaikan bahawa penunjuk pintar (Ptr) kepada peranti rangkaian yang berkaitan ada di tangan; dalam arus
contoh, ia adalah net0 penunjuk.

Satu cara untuk menukar nilai adalah dengan mengakses penuding ke baris gilir asas dan mengubah suainya
atribut.

Pertama, kita perhatikan bahawa kita boleh mendapatkan penunjuk kepada (kelas asas) Queue melalui yang
PointToPointNetDevice atribut, di mana ia dipanggil "TxQueue":

PointerValue tmp;
net0->GetAttribute ("TxQueue", tmp);
Ptr txQueue = tmp.GetObject ();

Menggunakan GetObject () fungsi, kita boleh melakukan downcast selamat ke a DropTailQueue, Di mana
"MaxPackets" ialah sifat:

Ptr dtq = txQueue->GetObject ();
NS_ASSERT (dtq != 0);

Seterusnya, kita boleh mendapatkan nilai atribut pada baris gilir ini. Kami telah memperkenalkan pembalut
nilai kelas untuk jenis data asas, serupa dengan pembalut Java di sekitar jenis ini,
kerana sistem atribut menyimpan nilai bersiri kepada rentetan, dan bukan jenis yang berbeza.
Di sini, nilai atribut diberikan kepada a UintegerValue, Dan Dapatkan () kaedah mengenai ini
nilai menghasilkan (tidak dibungkus) uint32_t.:

Had UintegerValue;
dtq->GetAttribute ("MaxPackets", had);
NS_LOG_INFO ("1. had dtq: " << had. Dapatkan () << " paket");

Ambil perhatian bahawa kemurungan di atas tidak benar-benar diperlukan; kita boleh mendapat atribut itu
nilai terus daripada txQueue, yang merupakan Objek:

txQueue->GetAttribute ("MaxPackets", had);
NS_LOG_INFO ("2. had txQueue: " << had. Dapatkan () << " paket");

Sekarang, mari kita tetapkan kepada nilai lain (60 paket):

txQueue->SetAttribute("MaxPackets", UintegerValue (60));
txQueue->GetAttribute ("MaxPackets", had);
NS_LOG_INFO ("3. had txQueue ditukar: " << had. Dapatkan () << " paket");

config Ruang nama Jalan
Cara alternatif untuk mendapatkan atribut adalah dengan menggunakan ruang nama konfigurasi. di sini,
atribut ini berada pada laluan yang diketahui dalam ruang nama ini; pendekatan ini berguna jika satu
tidak mempunyai akses kepada petunjuk asas dan ingin mengkonfigurasi yang khusus
atribut dengan satu pernyataan.:

Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets",
UintegerValue (25));
txQueue->GetAttribute ("MaxPackets", had);
NS_LOG_INFO ("4. had txQueue ditukar melalui ruang nama: "
<< had.Dapatkan () << "paket");

Laluan konfigurasi selalunya mempunyai bentuk ".../
nama>/ /.../ / " untuk merujuk kepada contoh tertentu mengikut indeks an
objek di dalam bekas. Dalam kes ini, bekas pertama ialah senarai semua nods; yang
bekas kedua ialah senarai semua NetDevices pada yang dipilih nod. Akhirnya,
laluan konfigurasi biasanya berakhir dengan penggantian atribut ahli, dalam kes ini
"MaxPackets" sifat dari "TxQueue" daripada yang terpilih NetDevice.

Kami juga boleh menggunakan kad bebas untuk menetapkan nilai ini untuk semua nod dan semua peranti bersih
(yang dalam contoh mudah ini mempunyai kesan yang sama seperti sebelumnya Konfigurasi::Tetapkan ()):

Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets",
UintegerValue (15));
txQueue->GetAttribute ("MaxPackets", had);
NS_LOG_INFO ("5. had txQueue ditukar melalui ruang nama kad bebas: "
<< had.Dapatkan () << "paket");

Objek Nama Servis
Cara lain untuk mendapatkan atribut ialah menggunakan kemudahan perkhidmatan nama objek. The
perkhidmatan nama objek membolehkan kami menambah item pada ruang nama konfigurasi di bawah
"/Nama/" laluan dengan rentetan nama yang ditentukan pengguna. Pendekatan ini berguna jika tidak
mempunyai akses kepada petunjuk asas dan sukar untuk menentukan yang diperlukan
laluan ruang nama konfigurasi konkrit.

Nama::Tambah ("pelayan", n0);
Names::Add ("server/eth0", net0);

...

Config::Set ("/Names/server/eth0/TxQueue/MaxPackets", UintegerValue (25));

Di sini kami telah menambah elemen laluan "pelayan" and "eth0" di bawah "/Nama/" ruang nama, kemudian
menggunakan laluan konfigurasi yang terhasil untuk menetapkan atribut.

Lihat Nama-objek untuk rawatan yang lebih lengkap ns-3 ruang nama konfigurasi.

Pelaksanaan Butiran
nilai kelas
Pembaca akan ambil perhatian TypeValue kelas yang merupakan subkelas daripada Nilai Atribut asas
kelas. Ini boleh dianggap sebagai kelas perantaraan yang digunakan untuk menukar daripada mentah
jenis kepada Nilai Atributs yang digunakan oleh sistem atribut. Ingat bahawa ini
pangkalan data memegang objek pelbagai jenis yang disirikan kepada rentetan. Penukaran kepada jenis ini
boleh dilakukan sama ada menggunakan kelas perantaraan (seperti IntegerValue, Atau DoubleValue khususnya
nombor titik terapung) atau melalui rentetan. Penukaran tersirat langsung jenis kepada
Nilai Atribut sebenarnya tidak praktikal. Jadi di atas, pengguna mempunyai pilihan untuk menggunakan
rentetan atau nilai:

p->Set ("cwnd", StringValue ("100")); // penetap berasaskan rentetan
p->Set ("cwnd", IntegerValue (100)); // penetap berasaskan integer

Sistem ini menyediakan beberapa makro yang membantu pengguna mengisytiharkan dan mentakrifkan AttributeValue baharu
subkelas untuk jenis baharu yang ingin mereka perkenalkan ke dalam sistem atribut:

· ATTRIBUTE_HELPER_HEADER

· ATTRIBUTE_HELPER_CPP

Lihat dokumentasi API untuk binaan ini untuk mendapatkan maklumat lanjut.

Pengawalan order
Atribut dalam sistem tidak boleh bergantung pada keadaan mana-mana Atribut lain dalam ini
sistem. Ini kerana susunan permulaan Atribut tidak ditentukan, mahupun
dikuatkuasakan, oleh sistem. Contoh khusus ini boleh dilihat dalam konfigurasi automatik
program seperti ConfigStore. Walaupun model tertentu boleh menyusunnya supaya Atribut
dimulakan dalam susunan tertentu, konfigurasi automatik lain boleh membuat keputusan
secara bebas untuk menukar Atribut dalam, sebagai contoh, susunan abjad.

Oleh kerana susunan tidak khusus ini, tiada Atribut dalam sistem mungkin mempunyai sebarang pergantungan
pada mana-mana Atribut lain. Akibatnya, penetap Atribut tidak boleh gagal kerana keadaan
daripada Atribut lain. Tiada penetap Atribut boleh mengubah (menetapkan) sebarang nilai Atribut lain sebagai a
hasil daripada perubahan nilainya.

Ini adalah sekatan yang sangat kuat dan terdapat kes di mana Atribut mesti ditetapkan
secara konsisten untuk membolehkan operasi yang betul. Untuk tujuan ini, kami membenarkan semakan konsistensi
apabila yang atribut is digunakan (cf. NS_ASSERT_MSG or NS_ABORT_MSG).

Secara umum, kod atribut untuk memberikan nilai kepada pembolehubah ahli kelas asas
dilaksanakan selepas sesuatu objek dibina. Tetapi bagaimana jika anda memerlukan nilai yang diberikan
sebelum badan pembina dilaksanakan, kerana anda memerlukannya dalam logik
pembina? Terdapat cara untuk melakukan ini, digunakan sebagai contoh dalam kelas ConfigStore: panggil
ObjectBase::ConstructSelf () seperti berikut:

ConfigStore::ConfigStore ()
{
ObjectBase::ConstructSelf (AttributeConstructionList ());
// teruskan dengan pembina.
}

Berhati-hati bahawa objek dan semua kelas terbitannya juga mesti melaksanakan a GetInstanceTypeId
() kaedah. Jika tidak ObjectBase::ConstructSelf () tidak akan dapat membaca
sifat.

Menambah Atribut
. ns-3 sistem akan meletakkan beberapa nilai dalaman di bawah sistem atribut, tetapi
sudah pasti pengguna akan mahu melanjutkan ini untuk mengambil yang kami terlepas, atau untuk menambah mereka
kelas sendiri kepada sistem.

Terdapat tiga kes penggunaan biasa:

· Menjadikan ahli data kelas sedia ada boleh diakses sebagai Atribut, apabila ia belum lagi.

· Menjadikan kelas baharu dapat mendedahkan beberapa ahli data sebagai Atribut dengan memberikannya TypeId.

· Mencipta sebuah Nilai Atribut subkelas untuk kelas baharu supaya ia boleh diakses sebagai
Atribut.

Sedia ada Member Pembolehubah
Pertimbangkan pembolehubah ini dalam TcpSocket:

uint32_t m_cWnd; // Tingkap kesesakan

Katakan seseorang yang bekerja dengan TCP ingin mendapatkan atau menetapkan nilai pembolehubah itu
menggunakan sistem metadata. Jika ia belum disediakan oleh ns-3, pengguna boleh mengisytiharkan
penambahan berikut dalam sistem metadata masa jalan (kepada GetTypeId() definisi untuk
TcpSocket):

.AddAttribute ("Tetingkap kesesakan",
"Tetingkap kesesakan Tcp (bait)",
UintegerValue (1),
MakeUintegerAccessor (&TcpSocket::m_cWnd),
MakeUintegerChecker ())

Sekarang, pengguna dengan penuding ke a TcpSocket instance boleh melakukan operasi seperti
menetapkan dan mendapatkan nilai, tanpa perlu menambah fungsi ini secara eksplisit.
Tambahan pula, kawalan akses boleh digunakan, seperti membenarkan parameter dibaca dan
tidak ditulis, atau semakan sempadan pada nilai yang dibenarkan boleh digunakan.

Baru Kelas JenisId
Di sini, kami membincangkan kesan kepada pengguna yang ingin menambah kelas baharu ns-3. Apa
perkara tambahan mesti dilakukan untuk membolehkannya memegang atribut?

Mari kita anggap kelas baru kita, dipanggil ns3::Mobiliti Saya, ialah sejenis model mobiliti. pertama,
kelas itu harus diwarisi daripada kelas induknya, ns3::MobilityModel. Di dalam mobiliti saya.h
fail pengepala:

ruang nama ns3 {

kelas MyClass :Model Mobility awam
{

Ini memerlukan kami mengisytiharkan GetTypeId () fungsi. Ini ialah fungsi awam satu baris
pengisytiharan:

awam:
/ **
* Daftar jenis ini.
* \return Objek TypeId.
*/
TypeId GetTypeId statik (kosong);

Kami telah pun memperkenalkan apa a JenisId definisi akan kelihatan seperti dalam mobiliti saya.cc
fail pelaksanaan:

NS_OBJECT_ENSURE_REGISTERED (MyMobility);

JenisId
MyMobility::GetTypeId (kosong)
{
statik TypeId tid = TypeId ("ns3::MyMobility")
.SetParent ()
.SetGroupName ("Mobilitas")
.AddConstructor ()
.AddAttribute ("Bounds",
"Sempadan kawasan untuk pelayaran.",
RectangleValue (Rectangle (0.0, 0.0, 100.0, 100.0)),
MakeRectangleAccessor (&MyMobility::m_bounds),
MakeRectangleChecker ())
.AddAttribute ("Masa",
"Tukar arah dan kelajuan semasa selepas bergerak untuk kelewatan ini.",
TimeValue (Saat (1.0)),
MakeTimeAccessor (&MyMobility::m_modeTime),
MakeTimeChecker ())
// dll (lebih banyak parameter).
;
tid balik;
}

Jika kita tidak mahu subkelas daripada kelas sedia ada, dalam fail pengepala kita hanya mewarisi
dari ns3::Objek, dan dalam fail objek kami tetapkan kelas induk kepada ns3::Objek bersama
.SetParent ().

Kesilapan biasa di sini melibatkan:

· Tidak menelefon NS_OBJECT_ENSURE_REGISTERED ()

· Tidak memanggil SetParent () kaedah, atau memanggilnya dengan jenis yang salah.

· Tidak memanggil AddConstructor () kaedah, atau memanggilnya dengan jenis yang salah.

· Memperkenalkan ralat tipografi dalam nama JenisId dalam pembinanya.

· Tidak menggunakan nama taip C++ yang layak sepenuhnya bagi kelas C++ yang disertakan sebagai nama
JenisId. Perhatikan bahawa "ns3::" adalah diperlukan.

Tiada satu pun daripada kesilapan ini dapat dikesan oleh ns-3 pangkalan kod, jadi pengguna dinasihatkan untuk menyemak
berhati-hati beberapa kali bahawa mereka mendapat hak ini.

Baru Nilai Atribut Jenis
Dari perspektif pengguna yang menulis kelas baharu dalam sistem dan mahukannya
boleh diakses sebagai atribut, terdapat terutamanya urusan menulis penukaran kepada/dari
rentetan dan nilai atribut. Kebanyakan ini boleh disalin/tampal dengan kod makro. Untuk
contoh, pertimbangkan pengisytiharan kelas untuk Segi empat tepat dalam src/mobiliti/model direktori:

Header File
/ **
* \ringkas segi empat tepat 2d
*/
kelas Segiempat
{
...

ganda xMin;
ganda xMax;
dua kali yMin;
yMax berganda;
};

Satu panggilan makro dan dua operator, mesti ditambah di bawah pengisytiharan kelas untuk
menukar Segiempat tepat kepada nilai yang boleh digunakan oleh atribut sistem:

std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
std::istream &operator >> (std::istream &is, Rectangle &rectangle);

ATTRIBUTE_HELPER_HEADER (Segi empat tepat);

Pelaksanaan File
Dalam definisi kelas (. Cc fail), kodnya kelihatan seperti ini:

ATTRIBUTE_HELPER_CPP (Segi empat tepat);

std::ostream &
operator << (std::ostream &os, const Rectangle &rectangle)
{
os << segi empat tepat.xMin << "|" << segi empat tepat.xMax << "|" << segi empat tepat.yMin << "|"
<< segi empat tepat.yMax;
kembali os;
}
std::istream &
operator >> (std::istream &is, Rectangle &rectangle)
{
char c1, c2, c3;
ialah >> segi empat tepat.xMin >> c1 >> segi empat tepat.xMax >> c2 >> segi empat tepat.yMin >> c3
>> segi empat tepat.yMax;
jika (c1 != '|' ||
c2 != '|' ||
c3 != '|')
{
is.setstate (std::ios_base::failbit);
}
pulangan ialah;
}

Pengendali strim ini hanya menukar daripada perwakilan rentetan Segiempat
("xMin|xMax|yMin|yMax") ke Segiempat tepat di bawahnya. Pemodel mesti menyatakan ini
operator dan perwakilan sintaksis rentetan bagi contoh kelas baharu.

ConfigStore
Nilai untuk ns-3 atribut boleh disimpan dalam fail teks ASCII atau XML dan dimuatkan ke dalam a
larian simulasi masa hadapan. Ciri ini dikenali sebagai ns-3 ConfigStore. The ConfigStore is
pangkalan data khusus untuk nilai atribut dan nilai lalai.

Walaupun ia adalah modul yang diselenggara secara berasingan dalam src/config-store/ direktori, kami
dokumenkan di sini kerana bergantung padanya ns-3 modul teras dan atribut.

Kita boleh meneroka sistem ini dengan menggunakan contoh daripada
src/config-store/examples/config-store-save.cc.

Pertama, semua pengguna ConfigStore mesti mengandungi pernyataan berikut:

#include "ns3/config-store-module.h"

Seterusnya, program ini menambah objek sampel ConfigContoh untuk menunjukkan bagaimana sistem dilanjutkan:

ConfigContoh kelas : Objek awam
{
awam:
Statik TypeId GetTypeId (kosong) {
static TypeId tid = TypeId ("ns3::A")
.SetParent ()
.AddAttribute ("TestInt16", "teks bantuan",
IntegerValue (-2),
MakeIntegerAccessor (&A::m_int16),
MakeIntegerChecker ())
;
tid balik;
}
int16_t m_int16;
};

NS_OBJECT_ENSURE_REGISTERED (ConfigExample);

Seterusnya, kami menggunakan subsistem Config untuk mengatasi lalai dalam beberapa cara:

Config::SetDefault ("ns3::ConfigExample::TestInt16", IntegerValue (-5));

Ptr a_obj = CreateObject ();
NS_ABORT_MSG_UNLESS (a_obj->m_int16 == -5,
"Tidak boleh menetapkan atribut integer ConfigExample melalui Config::SetDefault");

Ptr a2_obj = CreateObject ();
a2_obj->SetAttribute ("TestInt16", IntegerValue (-3));
IntegerValue iv;
a2_obj->GetAttribute ("TestInt16", iv);
NS_ABORT_MSG_UNLESS (iv.Dapatkan () == -3,
"Tidak boleh menetapkan atribut integer ConfigExample melalui SetAttribute");

Pernyataan seterusnya adalah perlu untuk memastikan bahawa (salah satu) objek yang dicipta adalah berakar
dalam ruang nama konfigurasi sebagai contoh objek. Ini biasanya berlaku apabila anda
agregat objek kepada a ns3::Nod or ns3::Saluran contohnya, tetapi di sini, kerana kita sedang bekerja
pada peringkat teras, kita perlu mencipta objek ruang nama akar baharu:

Config::RegisterRootNamespaceObject (a2_obj);

Penulisan
Seterusnya, kami ingin mengeluarkan stor konfigurasi. Contoh menunjukkan cara melakukannya dalam dua
format, XML dan teks mentah. Dalam amalan, seseorang harus melakukan langkah ini sejurus sebelum membuat panggilan
Simulator::Lari () untuk menyimpan konfigurasi akhir sejurus sebelum menjalankan simulasi.

Terdapat tiga Atribut yang mengawal tingkah laku ConfigStore: "Mod",
"Nama fail", dan "Format fail". Mod (lalai "Tiada") mengkonfigurasi sama ada ns-3 Sekiranya
memuatkan konfigurasi daripada fail yang disimpan sebelum ini (nyatakan "Mod=Muat") atau simpan ke fail
(nyatakan "Mod=Simpan"). Nama fail (lalai "") ialah tempat ConfigStore harus membaca atau
menulis datanya. Format Fail (lalai "RawTeks") mentadbir sama ada format ConfigStore
ialah teks biasa atau Xml ("Format Fail=Xml")

Contoh menunjukkan:

Config::SetDefault ("ns3::ConfigStore::Filename", StringValue ("output-attributes.xml"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("Xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("Simpan"));
ConfigStore outputConfig;
outputConfig.ConfigureDefaults ();
outputConfig.ConfigureAttributes ();

// Simpan konfigurasi output ke format txt
Config::SetDefault ("ns3::ConfigStore::Filename", StringValue ("output-attributes.txt"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("RawText"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("Simpan"));
ConfigStore outputConfig2;
outputConfig2.ConfigureDefaults ();
outputConfig2.ConfigureAttributes ();

Simulator::Jalankan ();

Simulator::Memusnahkan ();

Perhatikan peletakan penyata ini sejurus sebelum Simulator::Lari () kenyataan.
Output ini mencatatkan semua nilai yang ada sebelum memulakan simulasi (iaitu.
selepas semua konfigurasi telah berlaku).

Selepas berlari, anda boleh membuka output-attributes.txt fail dan lihat:

lalai ns3::RealtimeSimulatorImpl::SynchronizationMod "BestEffort"
lalai ns3::RealtimeSimulatorImpl::HardLimit "+100000000.0ns"
lalai ns3::PcapFileWrapper::CaptureSize "65535"
lalai ns3::PacketSocket::RcvBufSize "131072"
lalai ns3::ErrorModel::IsEnabled "true"
lalai ns3::RateErrorModel::ErrorUnit "EU_BYTE"
lalai ns3::RateErrorModel::ErrorRate "0"
lalai ns3::RateErrorModel::RanVar "Uniform:0:1"
lalai ns3::DropTailQueue::Mod "Paket"
lalai ns3::DropTailQueue::MaxPackets "100"
lalai ns3::DropTailQueue::MaxBytes "6553500"
lalai ns3::Application::StartTime "+0.0ns"
lalai ns3::Application::StopTime "+0.0ns"
lalai ns3::ConfigStore::Mod "Simpan"
lalai ns3::ConfigStore::Nama fail "output-attributes.txt"
lalai ns3::ConfigStore::FileFormat "RawText"
lalai ns3::ConfigExample::TestInt16 "-5"
RngSeed global "1"
RngRun global "1"
JenisPelaksanaan Simulator global "ns3::DefaultSimulatorImpl"
Global SchedulerType "ns3::MapScheduler"
Global ChecksumEnabled "false"
value /$ns3::ConfigExample/TestInt16 "-3"

Dalam perkara di atas, semua nilai lalai untuk atribut untuk modul teras ditunjukkan.
Kemudian, semua nilai untuk ns-3 nilai global direkodkan. Akhir sekali, nilai
contoh dari ConfigContoh yang telah berakar dalam ruang nama konfigurasi ditunjukkan. Didalam
sebenar ns-3 program, banyak lagi model, atribut dan lalai akan ditunjukkan.

Versi XML juga wujud dalam output-attributes.xml:




























Fail ini boleh diarkibkan dengan skrip simulasi dan data output anda.

Reading
Seterusnya, kami membincangkan konfigurasi simulasi melalui fail konfigurasi input yang disimpan. Disana ada
beberapa perbezaan utama berbanding dengan menulis konfigurasi simulasi akhir.
Pertama, kita perlu meletakkan kenyataan seperti ini pada permulaan program, sebelum
pernyataan konfigurasi simulasi ditulis (jadi nilai didaftarkan sebelum menjadi
digunakan dalam pembinaan objek).

Config::SetDefault ("ns3::ConfigStore::Filename", StringValue ("input-defaults.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("Muat"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("Xml"));
ConfigStore inputConfig;
inputConfig.ConfigureDefaults ();

Seterusnya, ambil perhatian bahawa pemuatan data konfigurasi input adalah terhad kepada lalai Atribut (iaitu.
bukan contoh) nilai, dan nilai global. Nilai contoh atribut tidak disokong
kerana pada peringkat simulasi ini, sebelum sebarang objek dibina, tiada
contoh objek sedemikian di sekeliling. (Nota, peningkatan masa hadapan pada kedai konfigurasi mungkin berubah
tingkah laku ini).

Kedua, manakala output daripada ConfigStore state akan menyenaraikan segala-galanya dalam pangkalan data, the
fail input hanya perlu mengandungi nilai khusus untuk ditindih. Jadi, satu cara untuk digunakan
kelas ini untuk konfigurasi fail input adalah untuk menjana konfigurasi awal menggunakan
pengeluaran ("Simpan") "Mod" yang diterangkan di atas, ekstrak daripada fail konfigurasi itu sahaja
elemen yang ingin diubah, dan alihkan elemen minimum ini ke fail konfigurasi baharu
yang kemudiannya boleh diedit dan dimuatkan dengan selamat dalam larian simulasi seterusnya.

Apabila ConfigStore objek adalah instantiated, sifat-sifatnya "Nama fail", "Mod", dan
"Format fail" mesti ditetapkan, sama ada melalui baris arahan atau melalui kenyataan program.

Membaca/Menulis Contoh
Sebagai contoh yang lebih rumit, mari kita anggap bahawa kita mahu membaca dalam konfigurasi
lalai daripada fail input bernama input-defaults.xml, dan tuliskan hasilnya
atribut kepada fail berasingan yang dipanggil output-attributes.xml.:

#include "ns3/config-store-module.h"
...
int utama (...)
{

Config::SetDefault ("ns3::ConfigStore::Filename", StringValue ("input-defaults.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("Muat"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("Xml"));
ConfigStore inputConfig;
inputConfig.ConfigureDefaults ();

//
// Benarkan pengguna mengatasi mana-mana lalai dan Bind () di atas di
// run-time, argumen baris melalui perintah
//
cmd Baris Perintah;
cmd.Parse (argc, argv);

// tetapan topologi
...

// Invoke sejurus sebelum memasuki Simulator::Run ()
Config::SetDefault ("ns3::ConfigStore::Filename", StringValue ("output-attributes.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("Simpan"));
ConfigStore outputConfig;
outputConfig.ConfigureAttributes ();
Simulator::Jalankan ();
}

ConfigStore GUI
Terdapat hujung hadapan berasaskan GTK untuk ConfigStore. Ini membolehkan pengguna menggunakan GUI untuk
capaian dan tukar pembolehubah. Tangkapan skrin ciri ini tersedia dalam |ns3|
Pengenalan persembahan.

Untuk menggunakan ciri ini, seseorang mesti memasang libgtk and libgtk-dev; contoh Ubuntu
arahan pemasangan ialah:

$ sudo apt-get install libgtk2.0-0 libgtk2.0-dev

Untuk menyemak sama ada ia dikonfigurasikan atau tidak, semak output langkah:

$ ./waf configure --enable-examples --enable-tests

---- Ringkasan ciri NS-3 pilihan:
Python Bindings : didayakan
Sokongan Pengimbasan API Python : didayakan
Integrasi Klik NS-3 : didayakan
GtkConfigStore : tidak didayakan (perpustakaan 'gtk+-2.0 >= 2.12' tidak ditemui)

Dalam contoh di atas, ia tidak didayakan, jadi ia tidak boleh digunakan sehingga versi yang sesuai digunakan
dipasang dan:

$ ./waf configure --enable-examples --enable-tests
$ ./waf

ditayangkan semula.

Penggunaan hampir sama dengan versi bukan berasaskan GTK, tetapi tidak ada ConfigStore
atribut yang terlibat:

// Invoke sejurus sebelum memasuki Simulator::Run ()
Konfigurasi GtkConfigStore;
config.ConfigureDefaults ();
config.ConfigureAttributes ();

Sekarang, apabila anda menjalankan skrip, GUI akan muncul, membolehkan anda membuka menu
atribut pada nod/objek yang berbeza, dan kemudian lancarkan pelaksanaan simulasi apabila anda
telah siap.

Masa depan bekerja
Terdapat beberapa kemungkinan penambahbaikan:

· Simpan nombor versi unik dengan tarikh dan masa pada permulaan fail.

· Simpan rng benih awal di suatu tempat.

· Jadikan setiap RandomVariable mensirikan benih awalnya sendiri dan baca semula kemudian.

Objek nama
Pemegang Tempat bab

Pembalakan
. ns-3 kemudahan pembalakan boleh digunakan untuk memantau atau menyahpepijat kemajuan simulasi
program. Output pengelogan boleh didayakan oleh penyata program dalam anda main () program atau
dengan penggunaan NS_LOG pembolehubah persekitaran.

Penyata pengelogan tidak disusun ke dalam binaan yang dioptimumkan ns-3. Untuk menggunakan pembalakan, satu
mesti membina binaan nyahpepijat (lalai). ns-3.

Projek ini tidak memberi jaminan sama ada output pembalakan akan kekal sama
masa. Pengguna diberi amaran terhadap membina rangka kerja output simulasi selain daripada pembalakan
kod, kerana output dan cara output didayakan mungkin berubah dari semasa ke semasa.

Pengenalan
ns-3 penyata pengelogan biasanya digunakan untuk log pelbagai acara pelaksanaan program, seperti
sebagai berlakunya peristiwa simulasi atau penggunaan fungsi tertentu.

Sebagai contoh, coretan kod ini adalah daripada Ipv4L3Protocol::IsDestinationAddress():

if (alamat == iaddr.GetBroadcast ())
{
NS_LOG_LOGIC ("Bagi saya (alamat siaran antara muka)");
kembali benar;
}

Jika pengelogan telah didayakan untuk Ipv4L3Protokol komponen pada tahap keterukan LOGIK or
di atas (lihat di bawah tentang keterukan log), penyata akan dicetak; jika tidak, ia
akan ditindas.

Mendayakan Output
Terdapat dua cara pengguna biasanya mengawal output log. Yang pertama adalah dengan menetapkan
NS_LOG pembolehubah persekitaran; cth:

$ NS_LOG="*" ./waf --lari dahulu

akan menjalankan pertama program tutorial dengan semua output log. (Khususnya NS_LOG
format akan dibincangkan di bawah.)

Ini boleh dibuat lebih terperinci dengan memilih komponen individu:

$ NS_LOG="Ipv4L3Protocol" ./waf --jalankan dahulu

Output boleh disesuaikan lagi dengan pilihan awalan.

Cara kedua untuk membolehkan pengelogan adalah dengan menggunakan pernyataan eksplisit dalam program anda, seperti dalam
yang pertama program tutorial:

int
utama (int argc, char *argv[])
{
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
...

(Maksud LOG_LEVEL_INFO, dan nilai lain yang mungkin, akan dibincangkan di bawah.)

NS_LOG Syntax
. NS_LOG pembolehubah persekitaran mengandungi senarai komponen log dan pilihan. Log
komponen dipisahkan oleh aksara `:':

$ NS_LOG=" : ..."

Pilihan untuk setiap komponen log diberikan sebagai bendera selepas setiap komponen log:

$ NS_LOG=" = | ...: ..."

Pilihan mengawal keterukan dan tahap untuk komponen itu, dan sama ada pilihan
maklumat harus disertakan, seperti masa simulasi, nod simulasi, fungsi
nama, dan keterukan simbolik.

Log Komponen
Secara amnya komponen log merujuk kepada satu kod sumber . Cc fail, dan merangkumi
keseluruhan fail.

Sesetengah pembantu mempunyai kaedah khas untuk membolehkan pengelogan semua komponen dalam modul,
merangkumi unit kompilasi yang berbeza, tetapi secara logik dikumpulkan bersama, seperti ns-3
kod wifi:

WifiHelper wifiHelper;
wifiHelper.EnableLogComponents ();

. NS_LOG kad bebas komponen log `*' akan membolehkan semua komponen.

Untuk melihat komponen log yang ditakrifkan, mana-mana daripada ini akan berfungsi:

$ NS_LOG="print-list" ./waf --run ...

$ NS_LOG="foo" # token tidak sepadan dengan mana-mana komponen log

Borang pertama akan mencetak nama dan bendera yang didayakan untuk semua komponen log
dipautkan dalam; cuba dengan simulator calar. Borang kedua mencetak semua log berdaftar
komponen, kemudian keluar dengan ralat.

Keterukan and Tahap Pilihan
Mesej individu tergolong dalam "kelas keterukan" tunggal yang ditetapkan oleh makro yang mencipta
mesej. Dalam contoh di atas, NS_LOG_LOGIC(..) mencipta mesej dalam LOG_LOGIK
kelas keterukan.

Kelas keterukan berikut ditakrifkan sebagai enum pemalar:

┌───────────────┬───────────────────────────────── ─┐
│Kelas Keterukan │ Maksud │
├───────────────┼───────────────────────────────── ─┤
LOG_TIADA │ Secara lalai, tiada pembalakan │
├───────────────┼───────────────────────────────── ─┤
LOG_ERROR │ Mesej ralat serius sahaja │
├───────────────┼───────────────────────────────── ─┤
LOG_WARN │ Mesej amaran │
├───────────────┼───────────────────────────────── ─┤
LOG_DEBUG │ Untuk digunakan dalam penyahpepijatan │
├───────────────┼───────────────────────────────── ─┤
LOG_INFO │ Bermaklumat │
├───────────────┼───────────────────────────────── ─┤
LOG_FUNCTION │ Pengesanan fungsi │
├───────────────┼───────────────────────────────── ─┤
LOG_LOGIK │ Kawal pengesanan aliran dalam │
│ │ fungsi │
└───────────────┴───────────────────────────────── ─┘

Biasanya seseorang ingin melihat mesej pada kelas keterukan tertentu and yang lebih tinggi. Ini dilakukan oleh
mentakrifkan "tahap" pengelogan inklusif:

┌───────────────────┬───────────────────────────── ─────┐
│Peringkat │ Maksud │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_ERROR │ Sahaja LOG_ERROR kelas keterukan │
│ │ mesej. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_WARNLOG_WARN dan ke atas. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_DEBUGLOG_DEBUG dan ke atas. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_INFOLOG_INFO dan ke atas. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_FUNCTIONLOG_FUNCTION dan ke atas. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_LOGICLOG_LOGIK dan ke atas. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_ALL │ Semua kelas keterukan. │
├───────────────────┼───────────────────────────── ─────┤
LOG_SEMUA │ Sinonim untuk LOG_LEVEL_ALL
└───────────────────┴───────────────────────────── ─────┘

Pilihan kelas dan tahap keterukan boleh diberikan dalam NS_LOG pembolehubah persekitaran oleh
token ini:

┌─────────┬────────────────┐
│Kelas │ Tahap │
├─────────┼────────────────┤
kesilapanlevel_error
├─────────┼────────────────┤
memberi amaran kepadalevel_warning
├─────────┼────────────────┤
debuglevel_debug
├─────────┼────────────────┤
maklumatlevel_info
├─────────┼────────────────┤
fungsifungsi_tingkat
├─────────┼────────────────┤
logiklogik_tahap
├─────────┼────────────────┤
│ │ peringkat_semua
│ │ semua
│ │ *
└─────────┴────────────────┘

Menggunakan token kelas keterukan mendayakan mesej log pada keterukan itu sahaja. Sebagai contoh,
NS_LOG="*=amaran" tidak akan mengeluarkan mesej dengan keterukan kesilapan. NS_LOG="*=level_debug" akan
output mesej pada tahap keterukan debug dan ke atas.

Kelas dan tahap keterukan boleh digabungkan dengan `|' pengendali:
NS_LOG="*=level_warn|logik" akan mengeluarkan mesej pada tahap keterukan kesilapan, memberi amaran kepada and logik.

. NS_LOG kad bebas tahap keterukan `*' dan semua adalah sinonim untuk peringkat_semua.

Untuk komponen log hanya disebut dalam NS_LOG

$ NS_LOG=" :..."

keterukan lalai ialah LOG_LEVEL_ALL.

Awalan Pilihan
Sebilangan awalan boleh membantu mengenal pasti dari mana dan bila mesej berasal, dan dari mana
keterukan.

Pilihan awalan yang tersedia (seperti enum pemalar) ialah

┌─────────────────┬─────────────────────────────── ───┐
│Simbol Awalan │ Maksud │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_FUNC │ Awalan nama panggilan │
│ │ fungsi. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_TIME │ Awalan masa simulasi. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_NODE │ Awalan id nod. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_LEVEL │ Awalan tahap keterukan. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_ALL │ Dayakan semua awalan. │
└─────────────────┴─────────────────────────────── ───┘

Pilihan awalan diterangkan secara ringkas di bawah.

Pilihan boleh diberikan dalam NS_LOG pembolehubah persekitaran dengan token ini:

┌─────────────┬───────────┐
│Token │ Ganti │
├─────────────┼───────────┤
prefix_funcfunc
├─────────────┼───────────┤
awalan_masamasa
└─────────────┴───────────┘

awalan_nodnod
├─────────────┼───────────┤
peringkat_awalantahap
├─────────────┼───────────┤
awalan_semuasemua
│ │ *
└─────────────┴───────────┘

Untuk komponen log hanya disebut dalam NS_LOG

$ NS_LOG=" :..."

pilihan awalan lalai ialah LOG_PREFIX_ALL.

Keterukan Awalan
Kelas keterukan mesej boleh disertakan dengan pilihan peringkat_awalan or tahap.
Sebagai contoh, nilai ini NS_LOG membolehkan pengelogan untuk semua komponen log (`*') dan semua
kelas keterukan (=semua), dan awalan mesej dengan kelas keterukan (|prefix_level).

$ NS_LOG="*=all|prefix_level" ./waf --run scratch-simulator
Simulator Calar
[ERROR] mesej ralat
[WARN] mesej amaran
[DEBUG] mesej nyahpepijat
[INFO] mesej maklumat
Mesej fungsi [FUNCT].
[LOGIK] mesej logik

Masa Awalan
Masa simulasi boleh disertakan dengan pilihan awalan_masa or masa. Ini mencetak
masa simulasi dalam beberapa saat.

nod Awalan
Id nod simulasi boleh disertakan dengan pilihan awalan_nod or nod.

fungsi Awalan
Nama fungsi panggilan boleh disertakan dengan pilihan prefix_func or func.

NS_LOG Kad Liar
Kad bebas komponen log `*' akan membolehkan semua komponen. Untuk membolehkan semua komponen di a
penggunaan tahap keterukan tertentu *=.

Kad bebas pilihan tahap keterukan `*' ialah sinonim untuk semua. Ini mesti berlaku sebelum apa-apa
`|' aksara yang memisahkan pilihan. Untuk mendayakan semua kelas keterukan, gunakan =*,
or =*|.

Pilihan kad bebas `*' atau token semua membolehkan semua pilihan awalan, tetapi mesti berlaku selepas a
`|' watak. Untuk mendayakan kelas atau tahap keterukan tertentu, dan semua awalan, gunakan
= |*.

Kad bebas pilihan gabungan ** membolehkan semua keterukan dan semua awalan; sebagai contoh,
=**.

Kad liar uber *** membolehkan semua keterukan dan semua awalan untuk semua komponen log.
Ini semua setara:

$ NS_LOG="***" ... $ NS_LOG="*=semua|*" ... $ NS_LOG="*=*|semua" ...
$ NS_LOG="*=**" ... $ NS_LOG="*=level_all|*" ... $ NS_LOG="*=*|prefix_all" ...
$ NS_LOG="*=*|*" ...

Dimaklumkan: walaupun yang remeh simulator calar menghasilkan lebih 46K baris output dengan
NS_LOG="***"!

Cara kepada menambah pembalakan kepada Matlamat kod
Menambah pengelogan pada kod anda adalah sangat mudah:

1. Serlahkan NS_LOG_COMPONENT_DEFINE (...); makro di dalam ruang nama ns3.
Buat pengecam rentetan unik (biasanya berdasarkan nama fail dan/atau kelas
ditakrifkan dalam fail) dan daftarkannya dengan panggilan makro seperti berikut:

ruang nama ns3 {

NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
...

Ini mendaftar Ipv4L3Protokol sebagai komponen log.

(Makro telah ditulis dengan teliti untuk membenarkan kemasukan sama ada di dalam atau di luar
ruang nama ns3, dan penggunaan akan berbeza-beza di seluruh pangkalan kod, tetapi tujuan asalnya adalah untuk
daftar ini di luar daripada ruang nama ns3 pada skop global fail.)

2. Tambah penyata pengelogan (panggilan makro) pada fungsi dan badan fungsi anda.

Pembalakan Makro
Makro pengelogan dan tahap keterukan yang berkaitan ialah

┌───────────────┬─────────────────┬────────────── ──‐──
│Kelas Keterukan │ Makro │
-
LOG_TIADA │ (tiada diperlukan) │
-
LOG_ERRORNS_LOG_ERROR (...);
-
LOG_WARNNS_LOG_WARN (...);
-
LOG_DEBUGNS_LOG_DEBUG (...);
-
LOG_INFONS_LOG_INFO (...);
-
LOG_FUNCTIONNS_LOG_FUNCTION (...);
-
LOG_LOGIKNS_LOG_LOGIC (...);
-

Makro berfungsi sebagai pemancar keluaran, jadi apa sahaja yang anda boleh hantar ke std::cout, menyertai
by << pengendali, dibenarkan:

batal MyClass::Semak (nilai int, char * item)
{
NS_LOG_FUNCTION (ini << arg << item);
jika (arg > 10)
{
NS_LOG_ERROR ("menghadapi nilai buruk " << nilai <
" sambil menyemak " << nama << "!");
}
...
}

Perhatikan bahawa NS_LOG_FUNCTION secara automatik memasukkan `,' (ruang koma) pemisah antara
setiap hujahnya. Ini memudahkan pengelogan argumen fungsi; hanya bercantum
mereka dengan << seperti contoh di atas.

Tidak bersyarat Pembalakan
Sebagai kemudahan, pihak NS_LOG_UNCOND (...); makro akan sentiasa log hujahnya, walaupun jika
komponen log yang berkaitan tidak didayakan pada sebarang keterukan. Makro ini tidak menggunakan sebarang
daripada pilihan awalan. Ambil perhatian bahawa pengelogan hanya didayakan dalam binaan nyahpepijat; makro ini
tidak akan menghasilkan output dalam binaan yang dioptimumkan.

Garis panduan
· Mulakan setiap kaedah kelas dengan NS_LOG_FUNCTION (ini << args...); Ini membolehkan mudah
pengesanan panggilan fungsi.

· Kecuali: jangan log operator atau pembina salinan eksplisit, kerana ini akan menyebabkan
rekursi tak terhingga dan limpahan tindanan.

· Untuk kaedah tanpa hujah gunakan bentuk yang sama: NS_LOG_FUNCTION (ini);

· Untuk fungsi statik:

· Dengan penggunaan hujah NS_LOG_FUNCTION (...); seperti biasa.

· Tanpa menggunakan hujah NS_LOG_FUNCTION_NOARGS ();

· Penggunaan NS_LOG_ERROR untuk keadaan ralat serius yang mungkin membatalkan simulasi
pelaksanaan.

· Penggunaan NS_LOG_WARN untuk keadaan luar biasa yang mungkin boleh dibetulkan. Tolong beri sedikit petunjuk
tentang sifat masalah dan bagaimana ia boleh diperbetulkan.

· NS_LOG_DEBUG biasanya digunakan dalam ad hoc cara untuk memahami pelaksanaan model.

· Penggunaan NS_LOG_INFO untuk maklumat tambahan tentang pelaksanaan, seperti saiz a
struktur data apabila menambah/mengalih keluar daripadanya.

· Penggunaan NS_LOG_LOGIC untuk mengesan cabang logik penting dalam fungsi.

· Uji bahawa perubahan pengelogan anda tidak melanggar kod. Jalankan beberapa contoh program dengan
semua komponen log dihidupkan (cth NS_LOG="***").

Penjejakan
Subsistem pengesanan adalah salah satu mekanisme yang paling penting untuk difahami ns-3. dalam
kebanyakan kes, ns-3 pengguna akan mempunyai idea yang bernas untuk beberapa rangkaian baharu dan dipertingkatkan
ciri. Untuk mengesahkan bahawa idea ini berfungsi, penyelidik akan membuat perubahan kepada a
sistem sedia ada dan kemudian jalankan percubaan untuk melihat bagaimana ciri baharu itu bertindak dengan mengumpul
statistik yang menangkap gelagat ciri tersebut.

Dalam erti kata lain, titik keseluruhan menjalankan simulasi adalah untuk menjana output untuk selanjutnya
belajar. Dalam ns-3, subsistem yang membolehkan penyelidik melakukan ini ialah pengesanan
subsistem.

Penjejakan Motivasi
Terdapat banyak cara untuk mendapatkan maklumat daripada program. Cara yang paling mudah ialah
untuk terus mencetak maklumat kepada output standard, seperti dalam,

#termasuk
...
int utama ()
{
...
std::cout << "Nilai x ialah " << x << std::endl;
...
}

Ini boleh dilaksanakan dalam persekitaran kecil, tetapi apabila simulasi anda semakin banyak
rumit, anda akan mendapat lebih banyak cetakan dan tugas menghurai dan melaksanakan
pengiraan pada output mula menjadi lebih sukar dan lebih sukar.

Perkara lain yang perlu dipertimbangkan ialah setiap kali berita baru diperlukan, teras perisian
mesti diedit dan cetakan lain diperkenalkan. Tiada cara piawai untuk mengawal semua
daripada keluaran ini, jadi jumlah keluaran cenderung berkembang tanpa had. Akhirnya, yang
lebar jalur yang diperlukan untuk hanya mengeluarkan maklumat ini mula mengehadkan masa berjalan
daripada simulasi itu. Fail keluaran membesar kepada saiz yang besar dan menghuraikannya menjadi a
masalah.

ns-3 menyediakan mekanisme mudah untuk pembalakan dan menyediakan beberapa kawalan ke atas output melalui
Log Komponen, tetapi tahap kawalan tidak berbutir sangat halus sama sekali. Pembalakan
modul adalah instrumen yang agak tumpul.

Adalah wajar untuk mempunyai kemudahan yang membolehkan seseorang mencapai ke dalam sistem teras dan sahaja
mendapatkan maklumat yang diperlukan tanpa perlu mengubah dan menyusun semula sistem teras. Malah
lebih baik ialah sistem yang memberitahu pengguna apabila item yang diminati berubah atau
peristiwa menarik berlaku.

. ns-3 sistem pengesanan direka bentuk untuk berfungsi mengikut garisan tersebut dan disepadukan dengan baik
substem Atribut dan Konfig membenarkan senario penggunaan yang agak mudah.

Pengenalan
Subsistem pengesanan sangat bergantung pada ns-3 Mekanisme panggilan balik dan Atribut. awak
hendaklah membaca dan memahami bahagian manual yang sepadan sebelum mencuba
memahami sistem pengesanan.

. ns-3 sistem pengesanan dibina berdasarkan konsep sumber pengesanan bebas dan
menjejak singki; bersama dengan mekanisme seragam untuk menyambungkan sumber ke singki.

Sumber surih ialah entiti yang boleh memberi isyarat peristiwa yang berlaku dalam simulasi dan menyediakan
akses kepada data asas yang menarik. Sebagai contoh, sumber surih boleh menunjukkan apabila a
paket diterima oleh peranti bersih dan menyediakan akses kepada kandungan paket untuk
tenggelam jejak berminat. Sumber surih mungkin juga menunjukkan apabila keadaan menarik
perubahan berlaku dalam model. Sebagai contoh, tetingkap kesesakan model TCP adalah perdana
calon untuk sumber surih.

Sumber surih tidak berguna dengan sendirinya; ia mesti disambungkan kepada kepingan kod lain
yang sebenarnya melakukan sesuatu yang berguna dengan maklumat yang diberikan oleh sumber. The
entiti yang menggunakan maklumat surih dipanggil sinki surih. Sumber surih adalah
penjana kejadian dan sinki surih adalah pengguna.

Pembahagian eksplisit ini membolehkan sejumlah besar sumber surih bertaburan di sekeliling
sistem di tempat yang penulis model percaya mungkin berguna. Melainkan pengguna menyambung a
surih tenggelam ke salah satu sumber ini, tiada apa yang keluar. Susunan ini membolehkan secara relatif
pengguna yang tidak canggih untuk melampirkan jenis sinki baharu pada sumber pengesanan sedia ada, tanpa
memerlukan penyuntingan dan penyusunan semula teras atau model simulator.

Mungkin terdapat sifar atau lebih pengguna peristiwa surih yang dijana oleh sumber surih. Satu boleh
anggap sumber surih sebagai sejenis pautan maklumat titik ke berbilang titik.

"Protokol pengangkutan" untuk pautan titik-ke-berbilang titik konsep ini ialah ns-3 Panggil balik.

Ingat dari Bahagian Panggilan Balik bahawa kemudahan panggil balik adalah cara untuk membenarkan dua modul masuk
sistem untuk berkomunikasi melalui panggilan fungsi sementara pada masa yang sama menyahgandingan panggilan
berfungsi daripada kelas yang dipanggil sepenuhnya. Ini adalah keperluan yang sama seperti yang digariskan di atas
untuk sistem pengesanan.

Pada asasnya, sumber surih is panggilan balik yang berbilang fungsi boleh didaftarkan.
Apabila sinki surih menyatakan minat untuk menerima peristiwa surih, ia menambahkan panggilan balik pada a
senarai panggilan balik yang dipegang oleh sumber surih. Apabila peristiwa menarik berlaku, jejak
sumber memanggilnya pengendali() menyediakan sifar atau lebih parameter. Ini memberitahu sumber kepada
pergi melalui senarai panggilan balik yang memanggil setiap satu secara bergilir. Dengan cara ini, parameter
disampaikan kepada singki jejak, yang hanya berfungsi.

. Paling mudah Contoh
Adalah berguna untuk mengikuti contoh pantas hanya untuk mengukuhkan apa yang telah kami katakan.:

#include "ns3/object.h"
#include "ns3/uintger.h"
#include "ns3/traced-value.h""
#include "ns3/trace-source-accessor.h"

#termasuk

menggunakan ruang nama ns3;

Perkara pertama yang perlu dilakukan ialah memasukkan fail yang diperlukan. Seperti yang dinyatakan di atas, sistem jejak
menggunakan berat sistem Objek dan Atribut. Dua yang pertama termasuk membawa masuk
pengisytiharan untuk sistem tersebut. Fail, nilai jejak.h membawa masuk yang diperlukan
pengisytiharan untuk mengesan data yang mematuhi nilai semantik.

Secara umum, nilai semantik hanya bermaksud bahawa anda boleh menghantar objek di sekeliling, bukan an
alamat. Untuk menggunakan semantik nilai sama sekali anda perlu mempunyai objek dengan
pembina salinan berkaitan dan pengendali tugasan tersedia. Kami memanjangkan keperluan
untuk bercakap tentang set pengendali yang dipratakrifkan untuk jenis data lama biasa (POD).
Operator=, operator++, operator--, operator+, operator==, dsb.

Maksud semua ini ialah anda akan dapat mengesan perubahan pada objek yang dibuat menggunakan
pengendali tersebut.:

kelas MyObject : Objek awam
{
awam:
TypeId statik GetTypeId (kosong)
{
static TypeId tid = TypeId ("MyObject")
.SetParent (Objek::GetTypeId ())
.AddConstructor ()
.AddTraceSource ("MyInteger",
"Nilai integer untuk dikesan.",
MakeTraceSourceAccessor (&MyObject::m_myInt))
;
tid balik;
}

MyObject () {}
TracedValue m_myInt;
};

Memandangkan sistem pengesanan disepadukan dengan Atribut, dan Atribut berfungsi dengan Objek,
mesti ada ns-3 Objek untuk sumber surih untuk hidup. Dua baris penting
kod adalah .AddTraceSource dan juga TracedValue pengisytiharan.

. .AddTraceSource menyediakan "cangkuk" yang digunakan untuk menyambungkan sumber surih ke
dunia luar. The TracedValue pengisytiharan menyediakan infrastruktur yang membebankan
operator yang disebutkan di atas dan memacu proses panggil balik.:

membatalkan
IntTrace (Int oldValue, Int newValue)
{
std::cout << "Dijejaki "<< oldValue << " hingga " << newValue << std::endl;
}

Ini adalah definisi sinki surih. Ia sepadan terus dengan fungsi panggil balik.
Fungsi ini akan dipanggil apabila salah satu pengendali TracedValue is
dilaksanakan.:

int
utama (int argc, char *argv[])
{
Ptr myObject = CreateObject ();

myObject->TraceConnectWithoutContext ("MyInteger", MakeCallback(&IntTrace));

myObject->m_myInt = 1234;
}

Dalam coretan ini, perkara pertama yang perlu dilakukan ialah mencipta objek di mana
sumber surih hidup.

Langkah seterusnya, iaitu TraceConnectTanpaKonteks, membentuk hubungan antara surih
sumber dan sinki surih. Perhatikan MakeCallback fungsi templat. Ingat kembali daripada
Bahagian panggil balik yang ini mewujudkan fungsi khusus yang bertanggungjawab untuk menyediakan
terlalu banyak pengendali() digunakan untuk "mematikan" panggilan balik. Pengendali terlebih beban (++, --, dsb.)
akan menggunakan ini pengendali() untuk benar-benar memanggil panggilan balik. The TraceConnectTanpaKonteks,
mengambil parameter rentetan yang memberikan nama Atribut yang diberikan kepada jejak
sumber. Mari kita abaikan sedikit tentang konteks buat masa ini kerana ia belum lagi penting.

Akhirnya, baris,:

myObject->m_myInt = 1234;

hendaklah ditafsirkan sebagai seruan kepada operator= pada pembolehubah ahli m_myInt bersama
integer 1234 diluluskan sebagai parameter. Ternyata pengendali ini ditakrifkan (oleh
TracedValue) untuk melaksanakan panggilan balik yang mengembalikan batal dan mengambil dua nilai integer sebagai
parameter -- nilai lama dan nilai baharu untuk integer yang dipersoalkan. Itu betul-betul
tandatangan fungsi untuk fungsi panggil balik yang kami sediakan -- IntTrace.

Untuk meringkaskan, sumber surih adalah, pada dasarnya, pembolehubah yang memegang senarai panggilan balik. A
sinki surih ialah fungsi yang digunakan sebagai sasaran panggilan balik. Jenis Atribut dan objek
sistem maklumat digunakan untuk menyediakan cara untuk menyambungkan sumber surih kepada singki surih. The
tindakan "memukul" sumber surih sedang melaksanakan pengendali pada sumber surih yang menyala
panggilan balik. Ini menyebabkan panggilan balik sinki surih mendaftarkan minat dalam sumber
dipanggil dengan parameter yang disediakan oleh sumber.

Menggunakan yang config Subsistem kepada Hubungi kepada Trace Sumber
. TraceConnectTanpaKonteks panggilan yang ditunjukkan di atas dalam contoh mudah sebenarnya sangat
jarang digunakan dalam sistem. Lebih lazimnya, config subsistem digunakan untuk membenarkan pemilihan
sumber surih dalam sistem menggunakan apa yang dipanggil a config jalan.

Sebagai contoh, seseorang mungkin menemui sesuatu yang kelihatan seperti berikut dalam sistem (diambil
dari examples/tcp-large-transfer.cc):

batal CwndTracer (uint32_t oldval, uint32_t newval) {}

...

Config::ConnectWithoutContext (
"/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
MakeCallback (&CwndTracer));

Ini sepatutnya kelihatan sangat biasa. Ia adalah perkara yang sama seperti contoh sebelumnya, kecuali itu
fungsi ahli statik kelas config sedang dipanggil dan bukannya kaedah dihidupkan Objek;
dan bukannya an atribut nama, laluan sedang disediakan.

Perkara pertama yang perlu dilakukan ialah membaca laluan ke belakang. Segmen terakhir laluan mestilah
an atribut daripada Objek. Malah, jika anda mempunyai penunjuk ke Objek yang mempunyai
"Tetingkap Kesesakan" atribut berguna (panggilnya objek itu), anda boleh menulis ini sama seperti
contoh sebelumnya:

batal CwndTracer (uint32_t oldval, uint32_t newval) {}

...

theObject->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer));

Ternyata kod untuk Config::ConnectWithoutContext melakukannya dengan tepat. ini
fungsi mengambil laluan yang mewakili rantaian Objek petunjuk dan mengikuti mereka sehingga ia
sampai ke penghujung laluan dan mentafsirkan segmen terakhir sebagai atribut pada yang terakhir
objek. Mari kita jalani apa yang berlaku.

Watak "/" utama dalam laluan merujuk kepada ruang nama yang dipanggil. Salah satu daripada
ruang nama yang dipratentukan dalam sistem konfigurasi ialah "NodeList" yang merupakan senarai semua
nod dalam simulasi. Item dalam senarai dirujuk oleh indeks ke dalam senarai, jadi
"/NodeList/0" merujuk kepada nod sifar dalam senarai nod yang dicipta oleh simulasi.
Nod ini sebenarnya ialah a Ptr dan begitu juga subkelas an ns3::Objek.

Seperti yang diterangkan dalam bahagian Model Objek, ns-3 menyokong model pengagregatan objek. The
segmen laluan seterusnya bermula dengan aksara "$" yang menunjukkan a GetObject panggilan sepatutnya
dibuat mencari jenis yang berikut. Apabila nod dimulakan oleh an
InternetStackHelper beberapa antara muka diagregatkan ke nod. Salah satunya ialah
Protokol tahap empat TCP. Jenis masa jalan bagi objek protokol ini ialah ns3::TcpL4Protocol''.
Bila yang ``GetObject dilaksanakan, ia mengembalikan penunjuk kepada objek jenis ini.

. TcpL4Protocol kelas mentakrifkan Atribut yang dipanggil "SocketList" yang merupakan senarai
soket. Setiap soket sebenarnya adalah ns3::Objek dengan sendiri Atribut. Item dalam
senarai soket dirujuk oleh indeks sama seperti dalam NodeList, jadi "SocketList/0"
merujuk kepada soket sifar dalam senarai soket pada nod sifar dalam NodeList --
nod pertama yang dibina dalam simulasi.

Soket ini, jenis yang ternyata menjadi ns3::TcpSocketImpl mentakrifkan atribut
dipanggil "CongestionWindow" iaitu a TracedValue. Yang
Config::ConnectWithoutContext kini melakukan,:

object->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer));

menggunakan penunjuk objek daripada "SocketList/0" yang membuat sambungan antara jejak
sumber ditakrifkan dalam soket kepada panggilan balik -- CwndTracer.

Kini, apabila perubahan dibuat pada TracedValue mewakili kesesakan
tetingkap dalam soket TCP, panggilan balik yang didaftarkan akan dilaksanakan dan fungsi
CwndTracer akan dipanggil mencetak nilai lama dan baharu kesesakan TCP
tingkap.

Menggunakan yang Penjejakan API
Terdapat tiga tahap interaksi dengan sistem pengesanan:

· Pengguna permulaan boleh mengawal objek mana yang mengambil bahagian dalam pengesanan dengan mudah;

· Pengguna pertengahan boleh melanjutkan sistem pengesanan untuk mengubah suai format output yang dihasilkan
atau gunakan sumber surih sedia ada dengan cara yang berbeza, tanpa mengubah suai teras
simulator;

· Pengguna lanjutan boleh mengubah suai teras simulator untuk menambah sumber pengesanan dan sinki baharu.

Menggunakan Trace Pembantu
. ns-3 pembantu jejak menyediakan persekitaran yang kaya untuk mengkonfigurasi dan memilih yang berbeza
mengesan peristiwa dan menulisnya ke fail. Dalam bahagian sebelumnya, terutamanya "Bangunan
Topologi," kami telah melihat beberapa jenis kaedah pembantu surih yang direka untuk digunakan
dalam pembantu (peranti) lain.

Mungkin anda akan ingat melihat beberapa variasi ini:

pointToPoint.EnablePcapAll ("second");
pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
csma.EnablePcap ("ketiga", csmaDevices.Get (0), benar);
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));

Walau bagaimanapun, apa yang mungkin tidak jelas ialah terdapat model yang konsisten untuk semua
kaedah berkaitan jejak yang terdapat dalam sistem. Kami sekarang akan mengambil sedikit masa dan melihat
pada "gambaran besar".

Pada masa ini terdapat dua kes penggunaan utama pembantu pengesanan masuk ns-3: Pembantu peranti
dan pembantu protokol. Pembantu peranti melihat masalah menentukan jejak yang sepatutnya
didayakan melalui nod, pasangan peranti. Sebagai contoh, anda mungkin mahu menentukan pcap itu
pengesanan hendaklah didayakan pada peranti tertentu pada nod tertentu. Ini berikutan daripada
ns-3 model konsep peranti, dan juga model konseptual pelbagai peranti
pembantu. Mengikuti secara semula jadi daripada ini, fail yang dibuat mengikut a
- - Konvensyen penamaan.

Pembantu protokol melihat masalah menentukan jejak yang harus didayakan
pasangan protokol dan antara muka. Ini berikutan daripada ns-3 model konsep timbunan protokol,
dan juga model konsep pembantu tindanan internet. Sememangnya, fail surih
hendaklah mengikut a - - Konvensyen penamaan.

Oleh itu, pembantu surih jatuh secara semula jadi ke dalam taksonomi dua dimensi. Disana ada
kehalusan yang menghalang keempat-empat kelas daripada berkelakuan sama, tetapi kami berusaha untuk melakukannya
buat mereka semua berfungsi dengan sama yang mungkin; dan bila boleh ada analog untuk
semua kaedah dalam semua kelas.

┌────────────────┬──────┬────────
│ │ pcap │ ascii │
├────────────────┼──────┼───────
│Pembantu Peranti │ │ │
├────────────────┼──────┼───────
│Pembantu Protokol │ │ │
└────────────────┴──────┴───────

Kami menggunakan pendekatan yang dipanggil a mixin untuk menambah fungsi pengesanan pada kelas pembantu kami. A
mixin ialah kelas yang menyediakan kefungsian kepada yang diwarisi oleh subkelas.
Mewarisi daripada mixin tidak dianggap sebagai satu bentuk pengkhususan tetapi benar-benar cara untuk
mengumpul fungsi.

Mari kita lihat dengan cepat keempat-empat kes ini dan masing-masing campuran.

Pcap Penjejakan Peranti Pembantu
Matlamat pembantu ini adalah untuk memudahkan untuk menambah kemudahan jejak pcap yang konsisten ke
ns-3 peranti. Kami mahu semua pelbagai rasa pengesanan pcap berfungsi sama di seluruh
semua peranti, jadi kaedah pembantu ini diwarisi oleh pembantu peranti. Tengoklah
at src/network/helper/trace-helper.h kalau nak ikut perbincangan sambil tengok
kod sebenar.

Kelas PcapHelperForDevice ialah mixin menyediakan fungsi tahap tinggi untuk digunakan
pengesanan pcap dalam sebuah ns-3 peranti. Setiap peranti mesti melaksanakan kaedah maya tunggal
diwarisi dari kelas ini.:

kekosongan maya EnablePcapInternal (std::prefix string, Ptr nd, bool promiscuous) = 0;

Tandatangan kaedah ini mencerminkan pandangan tertumpu peranti pada situasi ini
tahap. Semua kaedah awam yang diwarisi daripada kelas PcapUserHelperForDevice kurangkan kepada
memanggil kaedah pelaksanaan yang bergantung kepada peranti tunggal ini. Sebagai contoh, peringkat paling rendah
kaedah pcap,:

void EnablePcap (std::prefix string, Ptr nd, bool promiscuous = palsu, bool explicitFilename = false);

akan memanggil pelaksanaan peranti bagi EnablePcapInternal secara langsung. Semua pcap awam lain
kaedah pengesanan membina pelaksanaan ini untuk menyediakan tahap pengguna tambahan
kefungsian. Maksudnya kepada pengguna ialah semua pembantu peranti dalam sistem akan melakukannya
mempunyai semua kaedah jejak pcap tersedia; dan kaedah ini semua akan berfungsi dengan sama
merentasi peranti jika peranti melaksanakan EnablePcapInternal betul.

Pcap Penjejakan Peranti Penolong atau Pembantu Kaedah
void EnablePcap (std::prefix string, Ptr nd,
bool promiscuous = palsu, bool explicitFilename = palsu);
void EnablePcap (std::prefix string, std::string ndName,
bool promiscuous = palsu, bool explicitFilename = palsu);
void EnablePcap (std::prefix string, NetDeviceContainer d,
bool promiscuous = palsu);
void EnablePcap (std::prefix string, NodeContainer n,
bool promiscuous = palsu);
void EnablePcap (std::prefix string, uint32_t nodeid, uint32_t deviceid,
bool promiscuous = palsu);
void EnablePcapAll (std::prefix string, bool promiscuous = false);

Dalam setiap kaedah yang ditunjukkan di atas, terdapat parameter lalai yang dipanggil rambang mata Bahawa
lalai kepada palsu. Parameter ini menunjukkan bahawa jejak tidak boleh dikumpulkan
mod rambang mata. Jika anda mahu jejak anda memasukkan semua trafik yang dilihat oleh peranti
(dan jika peranti menyokong mod promiscuous) cuma tambahkan parameter sebenar pada mana-mana
panggilan di atas. Sebagai contoh,:

Ptr nd;
...
helper.EnablePcap ("prefix", nd, true);

akan membolehkan tangkapan mod rambang pada NetDevice ditentukan oleh nd.

Dua kaedah pertama juga termasuk parameter lalai yang dipanggil Nama fail eksplisit itu akan
dibincangkan di bawah.

Anda digalakkan membaca Doxygen untuk kelas PcapHelperForDevice untuk mencari butiran
kaedah ini; tapi untuk meringkaskan...

Anda boleh mendayakan pengesanan pcap pada pasangan nod/peranti bersih tertentu dengan menyediakan a
Ptr kepada EnablePcap kaedah. The Ptr adalah tersirat sejak peranti bersih
mesti milik tepat satu nod. Sebagai contoh,:

Ptr nd;
...
helper.EnablePcap ("prefix", nd);

Anda boleh mendayakan pengesanan pcap pada pasangan nod/peranti bersih tertentu dengan menyediakan a
std :: tali mewakili rentetan perkhidmatan nama objek kepada an EnablePcap kaedah. The
Ptr dilihat dari rentetan nama. Sekali lagi, yang adalah tersirat sejak
peranti bersih yang dinamakan mestilah milik tepat satu nod. Sebagai contoh,:

Nama::Tambah ("pelayan" ...);
Names::Add ("server/eth0" ...);
...
helper.EnablePcap ("prefix", "server/ath0");

Anda boleh mendayakan pengesanan pcap pada koleksi pasangan nod/peranti bersih dengan menyediakan a
NetDeviceContainer. Untuk setiap NetDevice dalam bekas jenis diperiksa. Untuk setiap
peranti jenis yang betul (jenis yang sama seperti yang diuruskan oleh pembantu peranti), pengesanan adalah
didayakan. Sekali lagi, yang adalah tersirat kerana peranti bersih yang ditemui mesti dimiliki dengan tepat
1 nod. Sebagai contoh,:

NetDeviceContainer d = ...;
...
helper.EnablePcap ("prefix", d);

Anda boleh mendayakan pengesanan pcap pada koleksi pasangan nod/peranti bersih dengan menyediakan a
NodeContainer. Untuk setiap nod dalam NodeContainer ia dilampirkan NetDevices diulang.
Bagi setiap NetDevice dilampirkan pada setiap nod dalam bekas, jenis peranti itu
diperiksa. Untuk setiap peranti jenis yang betul (jenis yang sama seperti yang diuruskan oleh peranti
penolong), pengesanan didayakan.:

NodeContainer n;
...
helper.EnablePcap ("prefix", n);

Anda boleh mendayakan pengesanan pcap berdasarkan ID nod dan ID peranti serta dengan eksplisit
Ptr. setiap nod dalam sistem mempunyai ID nod integer dan setiap peranti disambungkan ke nod
mempunyai ID peranti integer.:

helper.EnablePcap ("prefix", 21, 1);

Akhir sekali, anda boleh mendayakan pengesanan pcap untuk semua peranti dalam sistem, dengan jenis yang sama seperti
yang diuruskan oleh pembantu peranti.:

helper.EnablePcapAll ("awalan");

Pcap Penjejakan Peranti Penolong atau Pembantu Filename Pemilihan
Tersirat dalam huraian kaedah di atas ialah pembinaan nama fail lengkap oleh
kaedah pelaksanaan. Mengikut konvensyen, jejak pcap dalam ns-3 sistem adalah dalam bentuk
- id>- id>.pcap

Seperti yang dinyatakan sebelum ini, setiap nod dalam sistem akan mempunyai id nod yang ditetapkan oleh sistem; dan
setiap peranti akan mempunyai indeks antara muka (juga dipanggil id peranti) berbanding nodnya.
Secara lalai, fail jejak pcap dicipta hasil daripada mendayakan pengesanan pada yang pertama
peranti nod 21 menggunakan awalan "awalan" akan menjadi awalan-21-1.pcap.

Anda sentiasa boleh menggunakan ns-3 perkhidmatan nama objek untuk menjadikannya lebih jelas. Sebagai contoh, jika
anda menggunakan perkhidmatan nama objek untuk memberikan nama "pelayan" kepada nod 21, pcap yang terhasil
nama fail jejak akan secara automatik menjadi, prefix-server-1.pcap dan jika anda juga menetapkan
namakan "eth0" pada peranti, nama fail pcap anda akan secara automatik mengambilnya dan menjadi
dipanggil prefix-server-eth0.pcap.

Akhirnya, dua daripada kaedah yang ditunjukkan di atas,:

void EnablePcap (std::prefix string, Ptr nd, bool promiscuous = palsu, bool explicitFilename = false);
void EnablePcap (std::prefix string, std::string ndName, bool promiscuous = false, bool explicitFilename = false);

mempunyai parameter lalai yang dipanggil Nama fail eksplisit. Apabila ditetapkan kepada benar, parameter ini
melumpuhkan mekanisme penyiapan nama fail automatik dan membolehkan anda mencipta eksplisit
nama fail. Pilihan ini hanya tersedia dalam kaedah yang membolehkan pengesanan pcap pada a
peranti tunggal.

Sebagai contoh, untuk mengatur pembantu peranti untuk mencipta satu pcap promiscuous
tangkap fail dengan nama tertentu (my-pcap-file.pcap) pada peranti tertentu, seseorang boleh:

Ptr nd;
...
helper.EnablePcap ("my-pcap-file.pcap", nd, true, true);

Yang pertama benar parameter membolehkan jejak mod promiscuous dan yang kedua memberitahu pembantu
untuk mentafsir awalan parameter sebagai nama fail lengkap.

ASCII Penjejakan Peranti Pembantu
Tingkah laku pembantu jejak ascii mixin adalah serupa dengan versi pcap.
Sila lihat pada src/network/helper/trace-helper.h kalau nak ikut perbincangan
sambil melihat kod sebenar.

Kelas AsciiTraceHelperForDevice menambah fungsi tahap tinggi untuk menggunakan ascii
mengesan ke kelas pembantu peranti. Seperti dalam kes pcap, setiap peranti mesti melaksanakan a
kaedah maya tunggal yang diwarisi daripada jejak ascii mixin.:

kekosongan maya EnableAsciiInternal (Ptr strim, std:: awalan rentetan, Ptr nd) = 0;

Tandatangan kaedah ini mencerminkan pandangan tertumpu peranti pada situasi ini
peringkat; dan juga fakta bahawa pembantu mungkin menulis kepada aliran output yang dikongsi. Semuanya
kaedah berkaitan jejak ascii awam yang diwarisi daripada kelas AsciiTraceHelperForDevice
kurangkan untuk memanggil kaedah pelaksanaan yang bergantung kepada peranti tunggal ini. Sebagai contoh, yang
kaedah jejak ascii peringkat terendah,:

void EnableAscii (std::prefix string, Ptr nd);
batal EnableAscii (Ptr aliran, Ptr nd);

akan memanggil pelaksanaan peranti bagi EnableAsciiInternal secara langsung, menyediakan sama ada a
awalan atau aliran yang sah. Semua kaedah pengesanan ascii awam lain akan dibina berdasarkan ini
fungsi peringkat rendah untuk menyediakan fungsi peringkat pengguna tambahan. Apakah ini bermakna kepada
pengguna ialah semua pembantu peranti dalam sistem akan mempunyai semua kaedah surih ascii
tersedia; dan kaedah ini semuanya akan berfungsi dengan cara yang sama merentas peranti jika peranti itu
melaksanakan EnablAsciiInternal betul.

ASCII Penjejakan Peranti Penolong atau Pembantu Kaedah
void EnableAscii (std::prefix string, Ptr nd);
batal EnableAscii (Ptr aliran, Ptr nd);

void EnableAscii (std:: rentetan awalan, std:: string ndName);
batal EnableAscii (Ptr strim, std::string ndName);

void EnableAscii (std::prefix string, NetDeviceContainer d);
batal EnableAscii (Ptr strim, NetDeviceContainer d);

void EnableAscii (std::prefix string, NodeContainer n);
batal EnableAscii (Ptr strim, NodeContainer n);

void EnableAscii (std:: rentetan awalan, uint32_t nodeid, uint32_t deviceid);
batal EnableAscii (Ptr strim, uint32_t nodeid, uint32_t deviceid);

batal EnableAsciiAll (std:: awalan rentetan);
batal EnableAsciiAll (Ptr aliran);

Anda digalakkan membaca Doxygen untuk kelas TraceHelperForDevice untuk mencari
butiran kaedah ini; tapi untuk meringkaskan...

Terdapat dua kali lebih banyak kaedah yang tersedia untuk pengesanan ascii berbanding dengan pcap
menjejak. Ini kerana, sebagai tambahan kepada model gaya pcap di mana jejak dari setiap
pasangan nod/peranti unik ditulis pada fail unik, kami menyokong model di mana surih
maklumat untuk banyak pasangan nod/peranti ditulis pada fail biasa. Ini bermakna bahawa
- - mekanisme penjanaan nama fail digantikan dengan mekanisme untuk
merujuk kepada fail biasa; dan bilangan kaedah API digandakan untuk membolehkan semua
gabungan.

Sama seperti dalam pengesanan pcap, anda boleh mendayakan pengesanan ascii pada pasangan nod/peranti bersih tertentu
dengan menyediakan a Ptr kepada EnableAscii kaedah. The Ptr adalah tersirat sejak
peranti bersih mestilah milik tepat satu nod. Sebagai contoh,:

Ptr nd;
...
helper.EnableAscii ("prefix", nd);

Dalam kes ini, tiada konteks jejak ditulis pada fail surih ascii kerana ia akan menjadi
berlebihan. Sistem akan memilih nama fail yang akan dibuat menggunakan peraturan yang sama seperti
diterangkan dalam bahagian pcap, kecuali fail itu akan mempunyai akhiran ".tr" dan bukannya
".pcap".

Jika anda ingin mendayakan pengesanan ascii pada lebih daripada satu peranti bersih dan semua jejak dihantar
kepada satu fail, anda boleh melakukannya juga dengan menggunakan objek untuk merujuk kepada satu fail:

Ptr nd1;
Ptr nd2;
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAscii (strim, nd1);
helper.EnableAscii (strim, nd2);

Dalam kes ini, konteks surih ditulis pada fail surih ascii kerana ia diperlukan
untuk menyahkekaburan kesan daripada kedua-dua peranti. Ambil perhatian bahawa sejak pengguna sepenuhnya
dengan menyatakan nama fail, rentetan harus menyertakan ".tr" untuk konsistensi.

Anda boleh mendayakan pengesanan ascii pada pasangan nod/peranti bersih tertentu dengan menyediakan a
std :: tali mewakili rentetan perkhidmatan nama objek kepada an EnablePcap kaedah. The
Ptr dilihat dari rentetan nama. Sekali lagi, yang adalah tersirat sejak
peranti bersih yang dinamakan mestilah milik tepat satu nod. Sebagai contoh,:

Nama::Tambah ("klien" ...);
Nama::Tambah ("klien/eth0" ...);
Nama::Tambah ("pelayan" ...);
Names::Add ("server/eth0" ...);
...
helper.EnableAscii ("prefix", "client/eth0");
helper.EnableAscii ("prefix", "server/eth0");

Ini akan menghasilkan dua fail bernama prefix-client-eth0.tr and prefix-server-eth0.tr bersama
jejak untuk setiap peranti dalam fail surih masing-masing. Oleh kerana semua EnableAscii
fungsi terlebih beban untuk mengambil pembalut aliran, anda boleh menggunakan borang itu juga:

Nama::Tambah ("klien" ...);
Nama::Tambah ("klien/eth0" ...);
Nama::Tambah ("pelayan" ...);
Names::Add ("server/eth0" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAscii (strim, "klien/eth0");
helper.EnableAscii (strim, "server/eth0");

Ini akan menghasilkan satu fail jejak dipanggil trace-file-name.tr yang mengandungi semua
peristiwa surih untuk kedua-dua peranti. Peristiwa itu akan dinyahkekaburan mengikut konteks jejak
tali.

Anda boleh mendayakan pengesanan ascii pada koleksi pasangan nod/peranti bersih dengan menyediakan a
NetDeviceContainer. Untuk setiap NetDevice dalam bekas jenis diperiksa. Untuk setiap
peranti jenis yang betul (jenis yang sama seperti yang diuruskan oleh pembantu peranti), pengesanan adalah
didayakan. Sekali lagi, yang adalah tersirat kerana peranti bersih yang ditemui mesti dimiliki dengan tepat
1 nod. Sebagai contoh,:

NetDeviceContainer d = ...;
...
helper.EnableAscii ("awalan", d);

Ini akan mengakibatkan beberapa fail surih ascii dibuat, setiap satunya akan menyusul
yang - - .tr konvensyen. Menggabungkan semua jejak menjadi a
fail tunggal dicapai sama seperti contoh di atas:

NetDeviceContainer d = ...;
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAscii (strim, d);

Anda boleh mendayakan pengesanan ascii pada koleksi pasangan nod/peranti bersih dengan menyediakan a
NodeContainer. Untuk setiap nod dalam NodeContainer ia dilampirkan NetDevices diulang.
Bagi setiap NetDevice dilampirkan pada setiap nod dalam bekas, jenis peranti itu
diperiksa. Untuk setiap peranti jenis yang betul (jenis yang sama seperti yang diuruskan oleh peranti
penolong), pengesanan didayakan.:

NodeContainer n;
...
helper.EnableAscii ("awalan", n);

Ini akan mengakibatkan beberapa fail surih ascii dibuat, setiap satunya akan menyusul
yang - - .tr konvensyen. Menggabungkan semua jejak menjadi a
fail tunggal dicapai sama seperti contoh di atas:

Anda boleh mendayakan pengesanan pcap berdasarkan ID nod dan ID peranti serta dengan eksplisit
Ptr. setiap nod dalam sistem mempunyai ID nod integer dan setiap peranti disambungkan ke nod
mempunyai ID peranti integer.:

helper.EnableAscii ("prefix", 21, 1);

Sudah tentu, jejak boleh digabungkan menjadi satu fail seperti yang ditunjukkan di atas.

Akhir sekali, anda boleh mendayakan pengesanan pcap untuk semua peranti dalam sistem, dengan jenis yang sama seperti
yang diuruskan oleh pembantu peranti.:

helper.EnableAsciiAll ("awalan");

Ini akan menyebabkan beberapa fail surih ascii dibuat, satu untuk setiap peranti masuk
sistem jenis yang diuruskan oleh pembantu. Semua fail ini akan mengikuti
- - .tr konvensyen. Menggabungkan semua jejak menjadi satu
fail dicapai sama seperti contoh di atas.

ASCII Penjejakan Peranti Penolong atau Pembantu Filename Pemilihan
Tersirat dalam huraian kaedah gaya awalan di atas ialah pembinaan lengkap
nama fail dengan kaedah pelaksanaan. Mengikut konvensyen, jejak ascii dalam ns-3 sistem adalah
daripada borang tersebut - id>- id>.tr.

Seperti yang dinyatakan sebelum ini, setiap nod dalam sistem akan mempunyai id nod yang ditetapkan oleh sistem; dan
setiap peranti akan mempunyai indeks antara muka (juga dipanggil id peranti) berbanding nodnya.
Secara lalai, fail surih ascii dibuat hasil daripada mendayakan pengesanan pada yang pertama
peranti nod 21, menggunakan awalan "awalan", akan menjadi awalan-21-1.tr.

Anda sentiasa boleh menggunakan ns-3 perkhidmatan nama objek untuk menjadikannya lebih jelas. Sebagai contoh, jika
anda menggunakan perkhidmatan nama objek untuk memberikan nama "pelayan" kepada nod 21, yang terhasil
nama fail surih ascii secara automatik akan menjadi, prefix-server-1.tr dan jika anda juga menetapkan
nama "eth0" pada peranti, nama fail surih ascii anda akan mengambilnya secara automatik
dan dipanggil prefix-server-eth0.tr.

Pcap Penjejakan Protokol Pembantu
Matlamat ini campuran adalah untuk memudahkan menambah kemudahan jejak pcap yang konsisten kepada
protokol. Kami mahu semua pelbagai rasa pengesanan pcap berfungsi sama di semua
protokol, jadi kaedah pembantu ini diwarisi oleh pembantu tindanan. Lihatlah
src/network/helper/trace-helper.h kalau nak ikut perbincangan sambil tengok
kod sebenar.

Dalam bahagian ini kita akan menggambarkan kaedah seperti yang digunakan pada protokol IPv4. Untuk
nyatakan jejak dalam protokol yang serupa, cuma gantikan jenis yang sesuai. Sebagai contoh,
gunakan a Ptr bukan a Ptr dan panggil DayakanPcapIpv6 bukan DayakanPcapIpv4.

Kelas PcapHelperForIpv4 menyediakan fungsi tahap tinggi untuk menggunakan pengesanan pcap
dalam IPv4 protokol. Setiap pembantu protokol yang membolehkan kaedah ini mesti melaksanakan satu
kaedah maya yang diwarisi daripada kelas ini. Akan ada pelaksanaan yang berasingan untuk
IPv6, sebagai contoh, tetapi satu-satunya perbezaan adalah dalam nama kaedah dan tandatangan.
Nama kaedah yang berbeza diperlukan untuk menyahkekaburan kelas IPv4 dari IPv6 yang kedua-duanya
berasal dari kelas Objek, dan kaedah yang berkongsi tandatangan yang sama.:

kekosongan maya EnablePcapIpv4Internal (std::prefix string, Ptr ipv4, antara muka uint4_t) = 32;

Tandatangan kaedah ini mencerminkan protokol dan paparan berpusat antara muka
situasi di peringkat ini. Semua kaedah awam yang diwarisi daripada kelas PcapHelperForIpv4
kurangkan untuk memanggil kaedah pelaksanaan yang bergantung kepada peranti tunggal ini. Sebagai contoh, yang
kaedah pcap tahap terendah,:

void EnablePcapIpv4 (std::prefix string, Ptr ipv4, antara muka uint4_t);

akan memanggil pelaksanaan peranti bagi EnablePcapIpv4Internal secara langsung. Semua orang awam lain
kaedah pengesanan pcap membina pelaksanaan ini untuk menyediakan tahap pengguna tambahan
kefungsian. Maksudnya kepada pengguna ialah semua pembantu protokol dalam sistem akan melakukannya
mempunyai semua kaedah jejak pcap tersedia; dan kaedah ini semua akan berfungsi dengan sama
merentasi protokol jika pembantu melaksanakan EnablePcapIpv4Internal betul.

Pcap Penjejakan Protokol Penolong atau Pembantu Kaedah
Kaedah-kaedah ini direka bentuk untuk berada dalam surat-menyurat satu dengan satu dengan nod- dan
NetDevice- versi sentrik versi peranti. Sebaliknya nod and NetDevice pasangan
kekangan, kami menggunakan protokol dan kekangan antara muka.

Ambil perhatian bahawa sama seperti dalam versi peranti, terdapat enam kaedah:

void EnablePcapIpv4 (std::prefix string, Ptr ipv4, antara muka uint4_t);
void EnablePcapIpv4 (std::prefix string, std::string ipv4Name, antara muka uint32_t);
void EnablePcapIpv4 (std::prefix string, Ipv4InterfaceContainer c);
void EnablePcapIpv4 (std::prefix string, NodeContainer n);
void EnablePcapIpv4 (std::prefix string, uint32_t nodeid, uint32_t interface);
batal EnablePcapIpv4All (std::prefix string);

Anda digalakkan membaca Doxygen untuk kelas PcapHelperForIpv4 untuk mencari butiran
kaedah ini; tapi untuk meringkaskan...

Anda boleh mendayakan pengesanan pcap pada pasangan protokol/antara muka tertentu dengan menyediakan a
Ptr and antara muka kepada EnablePcap kaedah. Sebagai contoh,:

Ptr ipv4 = nod->GetObject ();
...
helper.EnablePcapIpv4 ("prefix", ipv4, 0);

Anda boleh mendayakan pengesanan pcap pada pasangan nod/peranti bersih tertentu dengan menyediakan a
std :: tali mewakili rentetan perkhidmatan nama objek kepada an EnablePcap kaedah. The
Ptr dilihat dari rentetan nama. Sebagai contoh,:

Names::Add ("serverIPv4" ...);
...
helper.EnablePcapIpv4 ("prefix", "serverIpv4", 1);

Anda boleh mendayakan pengesanan pcap pada koleksi pasangan protokol/antara muka dengan menyediakan satu
Ipv4InterfaceContainer. Untuk setiap IPv4 / antara muka pasangan dalam bekas jenis protokol
disemak. Untuk setiap protokol jenis yang betul (jenis yang sama seperti yang diuruskan oleh
pembantu peranti), pengesanan didayakan untuk antara muka yang sepadan. Sebagai contoh,:

NodeContainer nod;
...
Peranti NetDeviceContainer = deviceHelper.Install (nod);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Antara muka Ipv4InterfaceContainer = ipv4.Assign (peranti);
...
helper.EnablePcapIpv4 ("awalan", antara muka);

Anda boleh mendayakan pengesanan pcap pada koleksi pasangan protokol/antara muka dengan menyediakan a
NodeContainer. Untuk setiap nod dalam NodeContainer protokol yang sesuai ditemui. Untuk
setiap protokol, antara mukanya dikira dan pengesanan didayakan pada yang terhasil
berpasangan. Sebagai contoh,:

NodeContainer n;
...
helper.EnablePcapIpv4 ("prefix", n);

Anda boleh mendayakan pengesanan pcap berdasarkan ID nod dan antara muka juga. Dalam kes ini,
nod-id diterjemahkan kepada a Ptr dan protokol yang sesuai dicari dalam
nod. Protokol dan antara muka yang terhasil digunakan untuk menentukan jejak yang terhasil
sumber.:

helper.EnablePcapIpv4 ("prefix", 21, 1);

Akhir sekali, anda boleh mendayakan pengesanan pcap untuk semua antara muka dalam sistem, dengan yang berkaitan
protokol adalah jenis yang sama seperti yang diuruskan oleh pembantu peranti.:

helper.EnablePcapIpv4All ("awalan");

Pcap Penjejakan Protokol Penolong atau Pembantu Filename Pemilihan
Tersirat dalam semua huraian kaedah di atas adalah pembinaan lengkap
nama fail mengikut kaedah pelaksanaan. Mengikut konvensyen, jejak pcap diambil untuk peranti dalam
yang ns-3 sistem adalah dalam bentuk - id>- id>.pcap. Dalam kes
jejak protokol, terdapat surat-menyurat satu dengan satu antara protokol dan Nod. Ini adalah
kerana protokol Objek diagregatkan kepada nod Objek. Oleh kerana tiada protokol global
id dalam sistem, kami menggunakan id nod yang sepadan dalam penamaan fail. Oleh itu terdapat a
kemungkinan perlanggaran nama fail dalam nama fail surih yang dipilih secara automatik. Untuk ini
sebab, konvensyen nama fail ditukar untuk jejak protokol.

Seperti yang dinyatakan sebelum ini, setiap nod dalam sistem akan mempunyai id nod yang ditetapkan oleh sistem.
Memandangkan terdapat surat-menyurat satu dengan satu antara contoh protokol dan kejadian nod
kami menggunakan id nod. Setiap antara muka mempunyai id antara muka berbanding protokolnya. Kami guna
konvensyen" -n -i .pcap" untuk penamaan fail surih masuk
pembantu protokol.

Oleh itu, secara lalai, fail jejak pcap dicipta hasil daripada mendayakan pengesanan pada
antara muka 1 protokol Ipv4 nod 21 menggunakan awalan "awalan" akan menjadi
"prefix-n21-i1.pcap".

Anda sentiasa boleh menggunakan ns-3 perkhidmatan nama objek untuk menjadikannya lebih jelas. Sebagai contoh, jika
anda menggunakan perkhidmatan nama objek untuk memberikan nama "serverIpv4" kepada Ptr pada nod
21, nama fail jejak pcap yang terhasil secara automatik akan menjadi,
"prefix-nserverIpv4-i1.pcap".

ASCII Penjejakan Protokol Pembantu
Tingkah laku pembantu jejak ascii adalah serupa dengan kes pcap. Ambil a
lihat pada src/network/helper/trace-helper.h kalau nak ikut perbincangan sambil
melihat kod sebenar.

Dalam bahagian ini kita akan menggambarkan kaedah seperti yang digunakan pada protokol IPv4. Untuk
nyatakan jejak dalam protokol yang serupa, cuma gantikan jenis yang sesuai. Sebagai contoh,
gunakan a Ptr bukan a Ptr dan panggil EnableAsciiIpv6 bukan
EnableAsciiIpv4.

Kelas AsciiTraceHelperForIpv4 menambah fungsi tahap tinggi untuk menggunakan ascii
mengesan kepada pembantu protokol. Setiap protokol yang membolehkan kaedah ini mesti melaksanakan a
kaedah maya tunggal yang diwarisi daripada kelas ini.:

kekosongan maya EnableAsciiIpv4Internal (Ptr strim, std::awalan rentetan,
Ptr ipv4, antara muka uint4_t) = 32;

Tandatangan kaedah ini mencerminkan paparan protokol dan berpusat antara muka
keadaan pada tahap ini; dan juga fakta bahawa pembantu itu mungkin menulis kepada yang dikongsi
aliran keluaran. Semua kaedah awam yang diwarisi daripada kelas
PcapAndAsciiTraceHelperForIpv4 kurangkan panggilan yang bergantung kepada peranti tunggal ini
kaedah pelaksanaan. Sebagai contoh, kaedah surih ascii peringkat terendah,:

batal EnableAsciiIpv4 (std::awalan rentetan, Ptr ipv4, antara muka uint4_t);
batal EnableAsciiIpv4 (Ptr aliran, Ptr ipv4, antara muka uint4_t);

akan memanggil pelaksanaan peranti bagi EnableAsciiIpv4Internal secara langsung, menyediakan sama ada
awalan atau aliran. Semua kaedah pengesanan ascii awam lain akan dibina berdasarkan ini
fungsi peringkat rendah untuk menyediakan fungsi peringkat pengguna tambahan. Apakah ini bermakna kepada
pengguna ialah semua pembantu peranti dalam sistem akan mempunyai semua kaedah surih ascii
tersedia; dan kaedah ini semuanya akan berfungsi dengan cara yang sama merentas protokol jika
protokol dilaksanakan EnablAsciiIpv4Internal betul.

ASCII Penjejakan Peranti Penolong atau Pembantu Kaedah
batal EnableAsciiIpv4 (std::awalan rentetan, Ptr ipv4, antara muka uint4_t);
batal EnableAsciiIpv4 (Ptr aliran, Ptr ipv4, antara muka uint4_t);

void EnableAsciiIpv4 (std::prefix string, std::string ipv4Name, antara muka uint32_t);
batal EnableAsciiIpv4 (Ptr strim, std::string ipv4Name, antara muka uint32_t);

void EnableAsciiIpv4 (std::prefix string, Ipv4InterfaceContainer c);
batal EnableAsciiIpv4 (Ptr strim, Ipv4InterfaceContainer c);

void EnableAsciiIpv4 (std::prefix string, NodeContainer n);
batal EnableAsciiIpv4 (Ptr strim, NodeContainer n);

void EnableAsciiIpv4 (std::prefix string, uint32_t nodeid, uint32_t deviceid);
batal EnableAsciiIpv4 (Ptr strim, nodeid uint32_t, antara muka uint32_t);

batal EnableAsciiIpv4All (std::prefix string);
batal EnableAsciiIpv4All (Ptr aliran);

Anda digalakkan membaca Doxygen untuk kelas PcapAndAsciiHelperForIpv4 untuk mencari
butiran kaedah ini; tapi untuk meringkaskan...

Terdapat dua kali lebih banyak kaedah yang tersedia untuk pengesanan ascii berbanding dengan pcap
menjejak. Ini kerana, sebagai tambahan kepada model gaya pcap di mana jejak dari setiap
pasangan protokol/antara muka unik ditulis pada fail unik, kami menyokong model di mana
maklumat surih untuk banyak pasangan protokol/antara muka ditulis pada fail biasa. ini
bermakna bahawa -n - mekanisme penjanaan nama fail diganti
melalui mekanisme untuk merujuk kepada fail biasa; dan bilangan kaedah API digandakan kepada
benarkan semua kombinasi.

Sama seperti dalam pengesanan pcap, anda boleh mendayakan pengesanan ascii pada protokol/antara muka tertentu
berpasangan dengan menyediakan a Ptr dan antara muka kepada EnableAscii kaedah. Sebagai contoh,:

Ptr ipv4;
...
helper.EnableAsciiIpv4 ("prefix", ipv4, 1);

Dalam kes ini, tiada konteks jejak ditulis pada fail surih ascii kerana ia akan menjadi
berlebihan. Sistem akan memilih nama fail yang akan dibuat menggunakan peraturan yang sama seperti
diterangkan dalam bahagian pcap, kecuali fail itu akan mempunyai akhiran ".tr" dan bukannya
".pcap".

Jika anda ingin mendayakan pengesanan ascii pada lebih daripada satu antara muka dan semua jejak dihantar ke
satu fail, anda boleh melakukannya juga dengan menggunakan objek untuk merujuk kepada satu fail. Kami
sudah mempunyai sesuatu yang serupa dengan ini dalam contoh "cwnd" di atas:

Ptr protocol4 = node1->GetObject ();
Ptr protocol4 = node2->GetObject ();
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (strim, protocol1, 1);
helper.EnableAsciiIpv4 (strim, protocol2, 1);

Dalam kes ini, konteks surih ditulis pada fail surih ascii kerana ia diperlukan
untuk menyahkekaburan jejak daripada dua antara muka. Ambil perhatian bahawa sejak pengguna sepenuhnya
dengan menyatakan nama fail, rentetan harus menyertakan ".tr" untuk konsistensi.

Anda boleh mendayakan pengesanan ascii pada protokol tertentu dengan menyediakan a std :: tali
mewakili rentetan perkhidmatan nama objek kepada an EnablePcap kaedah. The Ptr is
mendongak dari rentetan nama. The dalam nama fail yang terhasil adalah tersirat sejak
terdapat surat-menyurat satu dengan satu antara contoh protokol dan nod, Contohnya,:

Names::Add ("node1Ipv4" ...);
Names::Add ("node2Ipv4" ...);
...
helper.EnableAsciiIpv4 ("prefix", "node1Ipv4", 1);
helper.EnableAsciiIpv4 ("prefix", "node2Ipv4", 1);

Ini akan menghasilkan dua fail bernama "prefix-nnode1Ipv4-i1.tr" dan
"prefix-nnode2Ipv4-i1.tr" dengan jejak untuk setiap antara muka dalam fail surih masing-masing.
Memandangkan semua fungsi EnableAscii dibebankan untuk mengambil pembalut strim, anda boleh
gunakan borang itu juga:

Names::Add ("node1Ipv4" ...);
Names::Add ("node2Ipv4" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (strim, "node1Ipv4", 1);
helper.EnableAsciiIpv4 (strim, "node2Ipv4", 1);

Ini akan menghasilkan fail surih tunggal yang dipanggil "nama fail surih.tr" yang mengandungi kesemuanya
peristiwa jejak untuk kedua-dua antara muka. Peristiwa itu akan dinyahkekaburan mengikut konteks jejak
tali.

Anda boleh mendayakan pengesanan ascii pada koleksi pasangan protokol/antara muka dengan menyediakan satu
Ipv4InterfaceContainer. Untuk setiap protokol jenis yang betul (jenis yang sama seperti yang diuruskan
oleh pembantu peranti), pengesanan didayakan untuk antara muka yang sepadan. Sekali lagi, yang
adalah tersirat kerana terdapat surat-menyurat satu dengan satu antara setiap protokol dan
nodnya. Sebagai contoh,:

NodeContainer nod;
...
Peranti NetDeviceContainer = deviceHelper.Install (nod);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Antara muka Ipv4InterfaceContainer = ipv4.Assign (peranti);
...
...
helper.EnableAsciiIpv4 ("awalan", antara muka);

Ini akan mengakibatkan beberapa fail surih ascii dibuat, setiap satunya akan menyusul
yang -n -i .tr konvensyen. Menggabungkan semua jejak menjadi a
fail tunggal dicapai sama seperti contoh di atas:

NodeContainer nod;
...
Peranti NetDeviceContainer = deviceHelper.Install (nod);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Antara muka Ipv4InterfaceContainer = ipv4.Assign (peranti);
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (strim, antara muka);

Anda boleh mendayakan pengesanan ascii pada koleksi pasangan protokol/antara muka dengan menyediakan a
NodeContainer. Untuk setiap nod dalam NodeContainer protokol yang sesuai ditemui. Untuk
setiap protokol, antara mukanya dikira dan pengesanan didayakan pada yang terhasil
berpasangan. Sebagai contoh,:

NodeContainer n;
...
helper.EnableAsciiIpv4 ("prefix", n);

Ini akan mengakibatkan beberapa fail surih ascii dibuat, setiap satunya akan menyusul
yang - - .tr konvensyen. Menggabungkan semua jejak menjadi a
fail tunggal dicapai sama seperti contoh di atas:

Anda boleh mendayakan pengesanan pcap berdasarkan ID nod dan ID peranti juga. Dalam kes ini,
nod-id diterjemahkan kepada a Ptr dan protokol yang sesuai dicari dalam
nod. Protokol dan antara muka yang terhasil digunakan untuk menentukan jejak yang terhasil
sumber.:

helper.EnableAsciiIpv4 ("prefix", 21, 1);

Sudah tentu, jejak boleh digabungkan menjadi satu fail seperti yang ditunjukkan di atas.

Akhir sekali, anda boleh mendayakan pengesanan ascii untuk semua antara muka dalam sistem, dengan yang berkaitan
protokol adalah jenis yang sama seperti yang diuruskan oleh pembantu peranti.:

helper.EnableAsciiIpv4All ("awalan");

Ini akan menyebabkan beberapa fail surih ascii dibuat, satu untuk setiap antara muka
dalam sistem yang berkaitan dengan protokol jenis yang diuruskan oleh pembantu. Semua fail ini
akan mengikuti -n -i
ke dalam satu fail dicapai sama seperti contoh di atas.

ASCII Penjejakan Peranti Penolong atau Pembantu Filename Pemilihan
Tersirat dalam huraian kaedah gaya awalan di atas ialah pembinaan lengkap
nama fail dengan kaedah pelaksanaan. Mengikut konvensyen, jejak ascii dalam ns-3 sistem adalah
dalam bentuk " - - .tr."

Seperti yang dinyatakan sebelum ini, setiap nod dalam sistem akan mempunyai id nod yang ditetapkan oleh sistem.
Oleh kerana terdapat surat-menyurat satu dengan satu antara protokol dan nod yang kami gunakan untuk nod-id
untuk mengenal pasti identiti protokol. Setiap antara muka pada protokol tertentu akan mempunyai
indeks antara muka (juga dipanggil hanya antara muka) berbanding protokolnya. Secara lalai,
kemudian, fail surih ascii dibuat hasil daripada mendayakan pengesanan pada peranti pertama
nod 21, menggunakan awalan "awalan", akan menjadi "awalan-n21-i1.tr". Gunakan awalan untuk
nyahkekaburan berbilang protokol bagi setiap nod.

Anda sentiasa boleh menggunakan ns-3 perkhidmatan nama objek untuk menjadikannya lebih jelas. Sebagai contoh, jika
anda menggunakan perkhidmatan nama objek untuk memberikan nama "serverIpv4" kepada protokol pada nod
21, dan juga tentukan antara muka satu, nama fail surih ascii yang terhasil akan secara automatik
menjadi, "prefix-nserverIpv4-1.tr".

Penjejakan pelaksanaan butir-butir
Tarikh koleksi
Bab ini menerangkan Rangka Kerja Pengumpulan Data ns-3 (DCF), yang menyediakan
keupayaan untuk mendapatkan data yang dijana oleh model dalam simulator, untuk melaksanakan dalam talian
pengurangan dan pemprosesan data, dan untuk menyusun data mentah atau diubah menjadi pelbagai output
format.

Rangka kerja pada masa ini menyokong larian ns-3 kendiri yang tidak bergantung pada sebarang luaran
kawalan pelaksanaan program. Objek yang disediakan oleh DCF mungkin disambungkan ns-3 mengesan
sumber untuk membolehkan pemprosesan data.

Kod sumber untuk kelas tinggal dalam direktori src/stats.

Bab ini disusun seperti berikut. Pertama, gambaran keseluruhan seni bina adalah
dibentangkan. Seterusnya, pembantu untuk kelas ini dibentangkan; rawatan awal ini
harus membenarkan penggunaan asas rangka kerja pengumpulan data untuk banyak kes penggunaan. Pengguna yang
ingin menghasilkan output di luar skop pembantu semasa, atau yang ingin mencipta
objek pengumpulan data mereka sendiri, harus membaca baki bab, yang seterusnya
terperinci tentang semua jenis objek DCF asas dan menyediakan pengekodan peringkat rendah
contoh.

reka bentuk
DCF terdiri daripada tiga kelas asas:

· Siasatan merupakan satu mekanisme untuk instrumen dan mengawal keluaran data simulasi iaitu
digunakan untuk memantau acara menarik. Ia menghasilkan output dalam bentuk satu atau lebih ns-3
jejak sumber. Objek siasatan disambungkan kepada satu atau lebih jejak tenggelam (dipanggil
Pengumpul), yang memproses sampel dalam talian dan menyediakannya untuk output.

· Pemungut menggunakan data yang dijana oleh satu atau lebih objek Probe. Ia melaksanakan
transformasi pada data, seperti normalisasi, pengurangan, dan pengiraan
statistik asas. Objek pengumpul tidak menghasilkan data yang dikeluarkan secara langsung oleh
larian ns-3; sebaliknya, mereka mengeluarkan data hiliran ke jenis objek lain, dipanggil
Agregator, yang melaksanakan fungsi itu. Biasanya, Pengumpul mengeluarkan data mereka
bentuk sumber surih juga, membolehkan pengumpul dirantai secara bersiri.

· Agregator ialah titik akhir data yang dikumpul oleh rangkaian Probe dan Pengumpul.
Tanggungjawab utama Agregator adalah untuk menyusun data dan yang sepadan
metadata, ke dalam format output yang berbeza seperti fail teks biasa, fail hamparan atau
pangkalan data.

Ketiga-tiga kelas ini menyediakan keupayaan untuk menghidupkan atau mematikan diri mereka secara dinamik
sepanjang simulasi.

Mana-mana kendiri ns-3 larian simulasi yang menggunakan DCF biasanya akan mencipta sekurang-kurangnya satu
contoh setiap tiga kelas di atas.
[imej] Gambaran keseluruhan Rangka Kerja Pengumpulan Data.UNINDENT

Aliran keseluruhan pemprosesan data digambarkan dalam Tarikh koleksi Rangka Kerja gambaran keseluruhan.
Di sebelah kiri, berlari ns-3 simulasi digambarkan. Dalam perjalanan menjalankan
simulasi, data disediakan oleh model melalui sumber surih, atau melalui cara lain.
Rajah menggambarkan bahawa probe boleh disambungkan kepada sumber surih ini untuk menerima data
secara tidak segerak, atau probe boleh membuat tinjauan untuk data. Data kemudiannya dihantar ke objek pengumpul
yang mengubah data. Akhir sekali, agregator boleh disambungkan kepada output
pengumpul, untuk menjana plot, fail, atau pangkalan data.
[imej] Pengagregatan Rangka Kerja Pengumpulan Data.UNINDENT

Satu variasi pada rajah di atas disediakan dalam Tarikh koleksi Rangka Kerja pengagregatan.
Angka kedua ini menggambarkan bahawa objek DCF mungkin dirantai bersama dengan cara
bahawa objek hiliran mengambil input daripada berbilang objek huluan. Angka itu
secara konseptual menunjukkan bahawa berbilang probe boleh menghasilkan output yang dimasukkan ke dalam satu
pengumpul; sebagai contoh, pengumpul yang mengeluarkan nisbah dua pembilang akan
biasanya memperoleh setiap data kaunter daripada probe berasingan. Pengumpul berbilang juga boleh
suapan ke dalam satu agregator, yang (seperti namanya) mungkin mengumpul beberapa data
aliran untuk dimasukkan ke dalam plot tunggal, fail atau pangkalan data.

Tarikh koleksi Pembantu
Fleksibiliti penuh rangka kerja pengumpulan data disediakan oleh interkoneksi
probe, pengumpul, dan agregator. Melaksanakan semua kesalinghubungan ini membawa kepada
banyak pernyataan konfigurasi dalam program pengguna. Untuk kemudahan penggunaan, beberapa yang paling biasa
operasi boleh digabungkan dan dikapsulkan dalam fungsi pembantu. Selain itu, beberapa
kenyataan yang melibatkan ns-3 sumber surih tidak mempunyai pengikatan Python, kerana batasan dalam
pengikatan.

Tarikh koleksi Pembantu Pengenalan
Dalam bahagian ini, kami menyediakan gambaran keseluruhan beberapa kelas pembantu yang telah dibuat untuk
memudahkan konfigurasi rangka kerja pengumpulan data untuk beberapa kes penggunaan biasa. The
pembantu membenarkan pengguna membentuk operasi biasa dengan hanya beberapa pernyataan dalam C++ atau
Program Python. Tetapi, kemudahan penggunaan ini datang dengan kos yang jauh lebih rendah
fleksibiliti daripada konfigurasi peringkat rendah yang boleh disediakan, dan keperluan untuk mengekod secara eksplisit
sokongan untuk jenis Probe baharu ke dalam pembantu (untuk menyelesaikan isu yang diterangkan di bawah).

Penekanan pada pembantu semasa adalah untuk mengumpulkan data daripada ns-3 surih sumber ke dalam
plot gnuplot atau fail teks, tanpa tahap penyesuaian output atau statistik yang tinggi
pemprosesan (pada mulanya). Selain itu, penggunaannya terhad kepada jenis probe yang tersedia dalam
ns-3. Bahagian kemudian dalam dokumentasi ini akan menerangkan dengan lebih terperinci tentang mencipta baharu
Jenis siasatan, serta butiran tentang mengaitkan Probe, Pengumpul dan Agregator
dalam susunan adat.

Sehingga kini, dua pembantu Pengumpulan Data telah dilaksanakan:

· GnuplotHelper

· FileHelper

GnuplotHelper
GnuplotHelper ialah kelas pembantu untuk menghasilkan fail output yang digunakan untuk membuat gnuplot. The
matlamat keseluruhan adalah untuk menyediakan keupayaan untuk pengguna membuat plot dengan cepat daripada data yang dieksport
in ns-3 jejak sumber. Secara lalai, jumlah minimum transformasi data dilakukan;
objektifnya adalah untuk menjana plot dengan penyataan konfigurasi (lalai) sesedikit
mungkin.

GnuplotHelper Pengenalan
GnuplotHelper akan mencipta 3 fail berbeza pada penghujung simulasi:

· Fail data gnuplot yang diasingkan ruang

· Fail kawalan gnuplot

· Skrip shell untuk menjana gnuplot

Terdapat dua pernyataan konfigurasi yang diperlukan untuk menghasilkan plot. Yang pertama
pernyataan mengkonfigurasi plot (nama fail, tajuk, legenda, dan jenis output, di mana output
taip lalai kepada PNG jika tidak ditentukan):

void ConfigurePlot (const std::string &outputFileNameWithoutExtension,
const std::rentetan &tajuk,
const std::string &xLegend,
const std::string &yLegend,
const std::string &terminalType = ".png");

Pernyataan kedua mengaitkan jejak sumber minat:

void PlotProbe (const std::string &typeId,
const std::string &path,
const std::string &probeTraceSource,
const std::string &title);

Dalil-dalilnya adalah seperti berikut:

· typeId: The ns-3 Id Jenis Probe

· laluan: Laluan dalam ns-3 ruang nama konfigurasi kepada satu atau lebih sumber surih

· probeTraceSource: Output probe yang mana (sendiri sebagai sumber surih) harus diplot

· tajuk: Tajuk untuk dikaitkan dengan set data (dalam legenda gnuplot)

Varian pada PlotProbe di atas adalah untuk menentukan argumen pilihan kelima yang mengawal
di mana dalam plot diletakkan kunci (legenda).

Contoh yang berfungsi sepenuhnya (dari ketujuh.cc) ditunjukkan di bawah:

// Cipta pembantu gnuplot.
GnuplotHelper plotHelper;

// Konfigurasikan plot.
// Konfigurasikan plot. Argumen pertama ialah awalan nama fail
// untuk fail output yang dihasilkan. Yang kedua, ketiga dan keempat
// argumen masing-masing ialah tajuk plot, paksi-x dan label paksi-y
plotHelper.ConfigurePlot ("kiraan bait-paket ketujuh",
"Kiraan Bait Paket lwn. Masa",
"Masa (Saat)",
"Kiraan Bait Paket",
"png");

// Nyatakan jenis probe, laluan sumber surih (dalam ruang nama konfigurasi), dan
// siasat sumber surih keluaran ("OutputBytes") untuk merancang. Hujah keempat
// menentukan nama label siri data pada plot. Yang terakhir
// argumen memformat plot dengan menyatakan tempat kunci harus diletakkan.
plotHelper.PlotProbe (probeType,
tracePath,
"OutputBytes",
"Kiraan Bait Paket",
GnuplotAggregator::KEY_BELOW);

Dalam contoh ini, probeType and tracePath adalah seperti berikut (untuk IPv4):

probeType = "ns3::Ipv4PacketProbe";
tracePath = "/NodeList/*/$ns3::Ipv4L3Protocol/Tx";

ProbeType ialah parameter utama untuk pembantu ini berfungsi. TypeId ini mesti didaftarkan
dalam sistem, dan tandatangan pada sinki surih Probe mesti sepadan dengan surih
sumber yang diminati. Jenis probe dipratakrifkan untuk beberapa jenis data
bersamaan dengan ns-3 nilai surih, dan untuk beberapa tandatangan sumber surih lain seperti
sumber surih 'Tx' ns3::Ipv4L3Protocol kelas.

Ambil perhatian bahawa laluan sumber surih yang ditentukan mungkin mengandungi kad bebas. Dalam kes ini, berbilang
set data diplot pada satu plot; satu untuk setiap laluan yang dipadankan.

Output utama yang dihasilkan ialah tiga fail:

ketujuh-packet-bait-count.dat
ketujuh-packet-byte-count.plt
ketujuh-packet-byte-count.sh

Pada ketika ini, pengguna boleh sama ada menyunting fail .plt untuk penyesuaian selanjutnya, atau
jalankan sahaja melalui gnuplot. Berlari sh ketujuh-packet-byte-count.sh hanya menjalankan plot
melalui gnplot, seperti yang ditunjukkan di bawah.
[imej] Gnuplot 2-D Dicipta oleh seventh.cc Contoh..UNINDENT

Ia boleh dilihat bahawa elemen utama (legenda, tajuk, peletakan legenda, xlabel, ylabel,
dan laluan untuk data) semuanya diletakkan pada plot. Oleh kerana terdapat dua perlawanan ke
laluan konfigurasi yang disediakan, kedua-dua siri data ditunjukkan:

· Packet Byte Count-0 sepadan dengan /NodeList/0/$ns3::Ipv4L3Protocol/Tx

· Packet Byte Count-1 sepadan dengan /NodeList/1/$ns3::Ipv4L3Protocol/Tx

GnuplotHelper ConfigurePlot
GnuplotHelper's ConfigurePlot() fungsi boleh digunakan untuk mengkonfigurasi plot.

Ia mempunyai prototaip berikut:

void ConfigurePlot (const std::string &outputFileNameWithoutExtension,
const std::rentetan &tajuk,
const std::string &xLegend,
const std::string &yLegend,
const std::string &terminalType = ".png");

Ia mempunyai hujah berikut:

┌───────────────────────────────┬─────────────────. ─────────────────┐
│Hujah │ Penerangan │
├───────────────────────────────┼─────────────────. ─────────────────┤
│outputFileNameWithoutExtension │ Nama fail berkaitan gnuplot kepada │
│ │ tulis tanpa sambungan. │
├───────────────────────────────┼─────────────────. ─────────────────┤
│tajuk │ Plot rentetan tajuk untuk digunakan untuk │
│ │ plot ini. │
├───────────────────────────────┼─────────────────. ─────────────────┤
│xLegend │ Lagenda untuk x mendatar │
│ │ paksi. │
├───────────────────────────────┼─────────────────. ─────────────────┤
│yLegend │ Lagenda untuk y menegak │
│ │ paksi. │
└───────────────────────────────┴─────────────────. ─────────────────┘

│terminalType │ Rentetan tetapan jenis terminal untuk │
│ │ keluaran. Terminal lalai │
│ │ jenis ialah "png". │
└───────────────────────────────┴─────────────────. ─────────────────┘

GnuplotHelper's ConfigurePlot() fungsi mengkonfigurasi parameter berkaitan plot untuk ini
pembantu gnuplot supaya ia akan mencipta fail data gnuplot yang dipisahkan oleh ruang bernama
outputFileNameWithoutExtension + ".dat", fail kawalan gnuplot bernama
outputFileNameWithoutExtension + ".plt", dan skrip shell untuk menjana gnuplot bernama
outputFileNameWithoutExtension + ".sh".

Contoh cara menggunakan fungsi ini boleh dilihat dalam ketujuh.cc kod yang diterangkan di atas
di mana ia digunakan seperti berikut:

plotHelper.ConfigurePlot ("kiraan bait-paket ketujuh",
"Kiraan Bait Paket lwn. Masa",
"Masa (Saat)",
"Kiraan Bait Paket",
"png");

GnuplotHelper PlotProbe
GnuplotHelper's PlotProbe() fungsi boleh digunakan untuk memplot nilai yang dihasilkan oleh probe.

Ia mempunyai prototaip berikut:

void PlotProbe (const std::string &typeId,
const std::string &path,
const std::string &probeTraceSource,
const std::rentetan &tajuk,
enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE);

Ia mempunyai hujah berikut:

┌─────────────────┬─────────────────────────────── ───┐
│Hujah │ Penerangan │
├─────────────────┼─────────────────────────────── ───┤
│typeId │ ID jenis untuk probe │
│ │ dicipta oleh pembantu ini. │
├─────────────────┼─────────────────────────────── ───┤
│path │ Config path untuk mengakses jejak │
│ │ sumber. │
├─────────────────┼─────────────────────────────── ───┤
│probeTraceSource │ Sumber jejak siasatan ke │
│ │ akses. │
├─────────────────┼─────────────────────────────── ───┤
│tajuk │ Tajuk yang akan dikaitkan dengan │
│ │ set data ini │
├─────────────────┼─────────────────────────────── ───┤
│Lokasi kunci │ Lokasi kunci dalam │
│ │ plot. Lokasi lalai ialah │
│ │ dalam. │
└─────────────────┴─────────────────────────────── ───┘

GnuplotHelper's PlotProbe() fungsi memplot set data yang dijana dengan mengaitkan ns-3
jejak sumber dengan kuar yang dicipta oleh pembantu, dan kemudian memplot nilai daripada
probeTraceSource. Set data akan mempunyai tajuk yang disediakan, dan akan terdiri daripada
'newValue' pada setiap cap waktu.

Jika laluan konfigurasi mempunyai lebih daripada satu padanan dalam sistem kerana terdapat kad bebas, maka
satu set data untuk setiap padanan akan diplot. Tajuk set data akan diakhiri dengan
aksara dipadankan untuk setiap kad bebas dalam laluan konfigurasi, dipisahkan dengan ruang. Untuk
contoh, jika tajuk set data yang dicadangkan ialah rentetan "bait", dan terdapat dua kad bebas
dalam laluan, maka tajuk set data seperti "bait-0 0" atau "bait-12 9" boleh dilakukan sebagai
label untuk set data yang diplot.

Contoh cara menggunakan fungsi ini boleh dilihat dalam ketujuh.cc kod yang diterangkan di atas
di mana ia digunakan (dengan penggantian berubah) seperti berikut:

plotHelper.PlotProbe ("ns3::Ipv4PacketProbe",
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
"OutputBytes",
"Kiraan Bait Paket",
GnuplotAggregator::KEY_BELOW);

lain-lain Contoh
Gnplot Penolong atau Pembantu Contoh
Contoh yang lebih mudah sedikit daripada ketujuh.cc contoh boleh didapati di
src/stats/example/gnuplot-helper-example.cc. Gnuplot 2-D berikut telah dibuat menggunakan
contoh.
[imej] Gnuplot 2-D Dibuat oleh gnuplot-helper-example.cc Contoh..UNINDENT

Dalam contoh ini, terdapat objek Pemancar yang menambah pembilangnya mengikut a
proses Poisson dan kemudian memancarkan nilai kaunter sebagai sumber surih.

Ptr pemancar = CreateObject ();
Nama::Tambah ("/Nama/Pemancar", pemancar);

Ambil perhatian bahawa kerana tiada kad bebas dalam laluan yang digunakan di bawah, hanya 1 aliran data yang digunakan
dilukis dalam plot. Aliran data tunggal dalam plot ini hanya dilabelkan "Pengiraan Pemancar",
tanpa akhiran tambahan seperti seseorang akan melihat jika terdapat kad bebas di laluan itu.

// Cipta pembantu gnuplot.
GnuplotHelper plotHelper;

// Konfigurasikan plot.
plotHelper.ConfigurePlot ("gnuplot-helper-example",
"Pengiraan Pemancar lwn. Masa",
"Masa (Saat)",
"Kiraan Pemancar",
"png");

// Plot nilai yang dijana oleh probe. Jalan yang kami sediakan
// membantu menyahkekaburan sumber surih.
plotHelper.PlotProbe ("ns3::Uinteger32Probe",
"/Nama/Pemancar/Pembilang",
"Pengeluaran",
"Kiraan Pemancar",
GnuplotAggregator::KEY_INSIDE);

FileHelper
FileHelper ialah kelas pembantu yang digunakan untuk meletakkan nilai data ke dalam fail. Matlamat keseluruhan ialah
untuk menyediakan keupayaan untuk pengguna membuat fail teks terformat dengan cepat daripada data yang dieksport
in ns-3 jejak sumber. Secara lalai, jumlah minimum transformasi data dilakukan;
objektifnya adalah untuk menjana fail dengan penyataan konfigurasi (lalai) sesedikit
mungkin.

FileHelper Pengenalan
FileHelper akan mencipta 1 atau lebih fail teks pada penghujung simulasi.

FileHelper boleh mencipta 4 jenis fail teks yang berbeza:

· Diformat

· Ruang diasingkan (lalai)

· Koma dipisahkan

· Tab diasingkan

Fail yang diformat menggunakan rentetan format gaya C dan fungsi sprintf() untuk mencetaknya
nilai dalam fail yang sedang ditulis.

Fail teks berikut dengan 2 lajur nilai terformat dinamakan
ketujuh-packet-byte-count-0.txt telah dicipta menggunakan lebih banyak kod baharu yang telah ditambahkan pada
asal ns-3 Kod contoh tutorial. Hanya 10 baris pertama fail ini ditunjukkan
di sini untuk ringkasnya.

Masa (Saat) = 1.000e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.004e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.004e+00 Kiraan Bait Paket = 576
Masa (Saat) = 1.009e+00 Kiraan Bait Paket = 576
Masa (Saat) = 1.009e+00 Kiraan Bait Paket = 576
Masa (Saat) = 1.015e+00 Kiraan Bait Paket = 512
Masa (Saat) = 1.017e+00 Kiraan Bait Paket = 576
Masa (Saat) = 1.017e+00 Kiraan Bait Paket = 544
Masa (Saat) = 1.025e+00 Kiraan Bait Paket = 576
Masa (Saat) = 1.025e+00 Kiraan Bait Paket = 544

...

Fail teks berbeza berikut dengan 2 lajur nilai terformat dinamakan
ketujuh-packet-byte-count-1.txt juga dibuat menggunakan kod baharu yang sama yang telah ditambahkan pada
asal ns-3 Kod contoh tutorial. Hanya 10 baris pertama fail ini ditunjukkan
di sini untuk ringkasnya.

Masa (Saat) = 1.002e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.007e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.013e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.020e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.028e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.036e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.045e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.053e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.061e+00 Kiraan Bait Paket = 40
Masa (Saat) = 1.069e+00 Kiraan Bait Paket = 40

...

Kod baharu yang telah ditambahkan untuk menghasilkan dua fail teks adalah di bawah. Butiran lanjut tentang
API ini akan dibincangkan dalam bahagian kemudian.

Ambil perhatian bahawa kerana terdapat 2 padanan untuk kad bebas dalam laluan, 2 fail teks yang berasingan
telah dicipta. Fail teks pertama, yang dinamakan "seventh-packet-byte-count-0.txt",
sepadan dengan padanan kad bebas dengan "*" digantikan dengan "0". Fail teks kedua,
yang dinamakan "seventh-packet-byte-count-1.txt", sepadan dengan padanan kad bebas dengan
"*" digantikan dengan "1". Juga, ambil perhatian bahawa fungsi memanggil ke WriteProbe() akan memberi
mesej ralat jika tiada padanan untuk laluan yang mengandungi kad bebas.

// Cipta pembantu fail.
FileHelper failHelper;

// Konfigurasikan fail yang hendak ditulis.
fileHelper.ConfigureFile ("kiraan bait-paket ketujuh",
FileAggregator::FORMATTED);

// Tetapkan label untuk fail output berformat ini.
fileHelper.Set2dFormat ("Masa (Saat) = %.3e\tKiraan Bait Paket = %.0f");

// Tulis nilai yang dijana oleh probe.
fileHelper.WriteProbe ("ns3::Ipv4PacketProbe",
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
"OutputBytes");

FileHelper ConfigureFile
The FileHelper's ConfigureFile() fungsi boleh digunakan untuk mengkonfigurasi fail teks.

Ia mempunyai prototaip berikut:

void ConfigureFile (const std::string &outputFileNameWithoutExtension,
enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED);

Ia mempunyai hujah berikut:

┌───────────────────────────────┬─────────────────. ─────────────────┐
│Hujah │ Penerangan │
├───────────────────────────────┼─────────────────. ─────────────────┤
│outputFileNameWithoutExtension │ Nama fail output untuk ditulis │
│ │ tanpa sambungan. │
├───────────────────────────────┼─────────────────. ─────────────────┤
│fileType │ Jenis fail untuk ditulis. │
│ │ jenis lalai fail ialah ruang │
│ │ dipisahkan. │
└───────────────────────────────┴─────────────────. ─────────────────┘

The FileHelper's ConfigureFile() fungsi mengkonfigurasi parameter berkaitan fail teks untuk
pembantu fail supaya ia akan mencipta fail bernama outputFileNameWithoutExtension plus
kemungkinan maklumat tambahan daripada padanan kad bebas ditambah ".txt" dengan nilai yang dicetak sebagai
ditentukan oleh fileType. Jenis fail lalai adalah dipisahkan oleh ruang.

Contoh cara menggunakan fungsi ini boleh dilihat dalam ketujuh.cc kod yang diterangkan di atas
di mana ia digunakan seperti berikut:

fileHelper.ConfigureFile ("kiraan bait-paket ketujuh",
FileAggregator::FORMATTED);

FileHelper WriteProbe
The FileHelper's WriteProbe() fungsi boleh digunakan untuk menulis nilai yang dijana oleh probe ke
fail teks.

Ia mempunyai prototaip berikut:

batal WriteProbe (const std::string &typeId,
const std::string &path,
const std::string &probeTraceSource);

Ia mempunyai hujah berikut:

┌─────────────────┬─────────────────────────────── ───┐
│Hujah │ Penerangan │
├─────────────────┼─────────────────────────────── ───┤
│typeId │ ID jenis untuk probe menjadi │
│ │ dicipta. │
├─────────────────┼─────────────────────────────── ───┤
│path │ Config path untuk mengakses jejak │
│ │ sumber. │
├─────────────────┼─────────────────────────────── ───┤
│probeTraceSource │ Sumber jejak siasatan ke │
│ │ akses. │
└─────────────────┴─────────────────────────────── ───┘

The FileHelper's WriteProbe() fungsi mencipta fail teks output yang dihasilkan dengan mengaitkan
ns-3 sumber surih dengan probe yang dicipta oleh pembantu, dan kemudian menulis nilai dari
probeTraceSource. Nama fail output akan mempunyai teks yang disimpan dalam pembolehubah ahli
m_outputFileNameWithoutExtension tambah ".txt", dan akan terdiri daripada 'newValue' pada setiap
cap masa.

Jika laluan konfigurasi mempunyai lebih daripada satu padanan dalam sistem kerana terdapat kad bebas, maka
satu fail output untuk setiap padanan akan dibuat. Nama fail output akan mengandungi
teks dalam m_outputFileNameWithoutExtension ditambah dengan aksara yang dipadankan untuk setiap satu
kad bebas dalam laluan konfigurasi, dipisahkan dengan sempang, ditambah ".txt". Sebagai contoh, jika nilai
dalam m_outputFileNameWithoutExtension ialah rentetan "packet-byte-count", dan terdapat dua
kad bebas dalam laluan, kemudian keluarkan nama fail seperti "packet-byte-count-0-0.txt" atau
"packet-byte-count-12-9.txt" boleh digunakan sebagai nama untuk fail yang akan dibuat.

Contoh cara menggunakan fungsi ini boleh dilihat dalam ketujuh.cc kod yang diterangkan di atas
di mana ia digunakan seperti berikut:

fileHelper.WriteProbe ("ns3::Ipv4PacketProbe",
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
"OutputBytes");

lain-lain Contoh
File Penolong atau Pembantu Contoh
Contoh yang lebih mudah sedikit daripada ketujuh.cc contoh boleh didapati di
src/stats/example/file-helper-example.cc. Contoh ini hanya menggunakan FileHelper.

Fail teks berikut dengan 2 lajur nilai terformat dinamakan file-helper-example.txt
telah dibuat menggunakan contoh. Hanya 10 baris pertama fail ini ditunjukkan di sini untuk
Keringkasan.

Masa (Saat) = 0.203 Kiraan = 1
Masa (Saat) = 0.702 Kiraan = 2
Masa (Saat) = 1.404 Kiraan = 3
Masa (Saat) = 2.368 Kiraan = 4
Masa (Saat) = 3.364 Kiraan = 5
Masa (Saat) = 3.579 Kiraan = 6
Masa (Saat) = 5.873 Kiraan = 7
Masa (Saat) = 6.410 Kiraan = 8
Masa (Saat) = 6.472 Kiraan = 9
...

Dalam contoh ini, terdapat objek Pemancar yang menambah pembilangnya mengikut a
proses Poisson dan kemudian memancarkan nilai kaunter sebagai sumber surih.

Ptr pemancar = CreateObject ();
Nama::Tambah ("/Nama/Pemancar", pemancar);

Ambil perhatian bahawa kerana tiada kad bebas dalam laluan yang digunakan di bawah, hanya 1 fail teks yang digunakan
dicipta. Fail teks tunggal ini hanya dinamakan "file-helper-example.txt", tanpa tambahan
akhiran seperti yang anda akan lihat jika terdapat kad bebas dalam laluan.

// Cipta pembantu fail.
FileHelper failHelper;

// Konfigurasikan fail yang hendak ditulis.
fileHelper.ConfigureFile ("file-helper-example",
FileAggregator::FORMATTED);

// Tetapkan label untuk fail output berformat ini.
fileHelper.Set2dFormat ("Masa (Saat) = %.3e\tCount = %.0f");

// Tulis nilai yang dijana oleh probe. Jalan yang kita
// memberikan bantuan untuk menyahkekaburan sumber surih.
fileHelper.WriteProbe ("ns3::Uinteger32Probe",
"/Nama/Pemancar/Pembilang",
"Pengeluaran");

Skop and Batasan
Pada masa ini, hanya Probe ini telah dilaksanakan dan disambungkan kepada GnuplotHelper dan
kepada FileHelper:

· BooleanProbe

· DoubleProbe

· Uinteger8Probe

· Uinteger16Probe

· Uinteger32Probe

· TimeProbe

· PacketProbe

· ApplicationPacketProbe

· Ipv4PacketProbe

Oleh itu, Probe ini adalah satu-satunya TypeId yang tersedia untuk digunakan PlotProbe() and
WriteProbe().

Dalam beberapa bahagian seterusnya, kami meliputi setiap jenis objek asas (Probe, Collector,
dan Aggregator) dengan lebih terperinci, dan tunjukkan cara ia boleh disambungkan bersama menggunakan
API peringkat rendah.

kuar
Bahagian ini memperincikan fungsi yang disediakan oleh kelas Probe kepada a ns-3
simulasi, dan memberikan contoh tentang cara mengekodnya dalam atur cara. Bahagian ini bertujuan untuk
pengguna yang berminat untuk membangunkan simulasi dengan ns-3 alatan dan menggunakan Data
Rangka Kerja Pengumpulan, yang merupakan sebahagian daripada kelas Probe, untuk menjana output data dengan
hasil simulasi mereka.

Siasatan Pengenalan
Objek Probe sepatutnya disambungkan kepada pembolehubah daripada simulasi yang nilainya
sepanjang percubaan adalah relevan kepada pengguna. Probe akan merekodkan apa yang berlaku
nilai yang diandaikan oleh pembolehubah sepanjang simulasi dan menghantar data tersebut kepada yang lain
ahli Rangka Kerja Pengumpulan Data. Walaupun ia di luar skop bahagian ini untuk
bincangkan apa yang berlaku selepas Probe menghasilkan outputnya, adalah memadai untuk mengatakan bahawa, oleh
penghujung simulasi, pengguna akan mempunyai maklumat terperinci tentang nilai-nilai itu
disimpan di dalam pembolehubah yang disiasat semasa simulasi.

Biasanya, Probe disambungkan ke ns-3 sumber jejak. Dengan cara ini, bila-bila masa
sumber surih mengeksport nilai baharu, Probe menggunakan nilai tersebut (dan mengeksportnya ke hiliran
ke objek lain melalui sumber surihnya sendiri).

Probe boleh dianggap sebagai sejenis penapis pada sumber surih. Sebab utama untuk
mungkin menyambung kepada Probe dan bukannya terus kepada sumber surih adalah seperti berikut:

· Prob boleh dihidupkan dan dimatikan secara dinamik semasa simulasi dengan panggilan ke Dayakan()
and Lumpuhkan(). Sebagai contoh, pengeluaran data mungkin dimatikan semasa
fasa pemanasan simulasi.

· Probe boleh melakukan operasi pada data untuk mengekstrak nilai daripada yang lebih rumit
struktur; contohnya, mengeluarkan nilai saiz paket daripada ns3::Packet yang diterima.

· Probe mendaftarkan nama dalam ruang nama ns3::Config (menggunakan Nama::Tambah ()) supaya yang lain
objek boleh merujuk kepada mereka.

· Prob menyediakan kaedah statik yang membolehkan seseorang memanipulasi Probe mengikut nama, seperti
apa yang dilakukan dalam ns2measure [Cic06]

Stat::put ("my_metric", ID, sampel);

ns-3 yang setara dengan kod ns2measure di atas ialah, cth

DoubleProbe::SetValueByPath ("/path/to/probe", sampel);

Ciptaan
Ambil perhatian bahawa objek kelas asas Probe tidak boleh dibuat kerana ia adalah asas abstrak
kelas, iaitu ia mempunyai fungsi maya tulen yang belum dilaksanakan. Objek daripada
taip DoubleProbe, yang merupakan subkelas kelas Probe, akan dibuat di sini untuk ditunjukkan
apa yang perlu dilakukan.

Seseorang mengisytiharkan DoubleProbe dalam memori dinamik dengan menggunakan kelas penunjuk pintar (Ptr ). Kepada
cipta DoubleProbe dalam memori dinamik dengan penunjuk pintar, seseorang hanya perlu memanggil
ns-3 kaedah CreateObject():

Ptr myprobe = CreateObject ();

Pengisytiharan di atas mencipta DoubleProbes menggunakan nilai lalai untuk atributnya.
Terdapat empat atribut dalam kelas DoubleProbe; dua dalam objek kelas asas
DataCollectionObject, dan dua dalam kelas asas Probe:

· "Nama" (DataCollectionObject), StringValue

· "Didayakan" (DataCollectionObject), BooleanValue

· "Mula" (Probe), sebuah TimeValue

· "Berhenti" (Probe), Nilai Masa

Seseorang boleh menetapkan atribut tersebut pada penciptaan objek dengan menggunakan kaedah berikut:

Ptr myprobe = CreateObjectWithAttributes (
"Nama", StringValue ("myprobe"),
"Didayakan", BooleanValue (palsu),
"Mula", TimeValue (Saat (100.0)),
"Berhenti", TimeValue (Saat (1000.0)));

Mula dan Berhenti ialah pembolehubah Masa yang menentukan selang tindakan Probe. The
Probe hanya akan mengeluarkan data jika masa semasa Simulasi berada di dalam masa itu
selang waktu. Nilai masa khas 0 saat untuk Berhenti akan melumpuhkan atribut ini (cth
pastikan Probe dihidupkan untuk keseluruhan simulasi). Didayakan ialah bendera yang menghidupkan Probe atau
dimatikan, dan mesti ditetapkan kepada benar untuk Probe mengeksport data. Nama ialah nama objek
dalam rangka kerja DCF.

Mengimport and mengeksport data
ns-3 sumber surih ditaip dengan kuat, jadi mekanisme untuk mengaitkan Probe ke surih
sumber dan untuk mengeksport data tergolong dalam subkelasnya. Sebagai contoh, lalai
pengedaran ns-3 menyediakan DoubleProbe kelas yang direka bentuk untuk menyambung ke surih
sumber mengeksport nilai berganda. Kami akan memperincikan operasi DoubleProbe seterusnya, dan
kemudian bincangkan bagaimana kelas Probe lain boleh ditakrifkan oleh pengguna.

DoubleProbe Pengenalan
DoubleProbe disambungkan kepada nilai berganda ns-3 sumber surih, dan sendiri mengeksport a
berbeza nilai ganda ns-3 sumber jejak.

Kod berikut, diambil daripada src/stats/example/double-probe-example.cc, menunjukkan asas
operasi paip DoubleProbe ke dalam simulasi, di mana ia sedang meneliti Kaunter
dieksport oleh objek pemancar (kelas Pemancar).

Ptr pemancar = CreateObject ();
Nama::Tambah ("/Nama/Pemancar", pemancar);
...

Ptr probe1 = CreateObject ();

// Sambungkan probe ke Kaunter pemancar
bool disambungkan = probe1->ConnectByObject ("Counter", pemancar);

Kod berikut sedang menyiasat Kaunter yang sama yang dieksport oleh objek pemancar yang sama. ini
DoubleProbe, bagaimanapun, menggunakan laluan dalam ruang nama konfigurasi untuk membuat
sambungan. Ambil perhatian bahawa pemancar mendaftarkan dirinya dalam ruang nama konfigurasi selepas
ia dicipta; jika tidak, ConnectByPath tidak akan berfungsi.

Ptr probe2 = CreateObject ();

// Nota, tiada nilai pulangan disemak di sini
probe2->ConnectByPath ("/Names/Emitter/Counter");

DoubleProbe seterusnya yang ditunjukkan yang ditunjukkan di bawah akan mempunyai nilainya ditetapkan menggunakan laluannya masuk
ruang nama konfigurasi. Ambil perhatian bahawa kali ini DoubleProbe mendaftar sendiri dalam
ruang nama konfigurasi selepas ia dicipta.

Ptr probe3 = CreateObject ();
probe3->SetName ("StaticallyAccessedProbe");

// Kita mesti menambahnya pada pangkalan data konfigurasi
Names::Add ("/Names/Probes", probe3->GetName (), probe3);

Fungsi Count() pemancar kini boleh menetapkan nilai untuk DoubleProbe ini sebagai
ikut:

membatalkan
Pemancar:: Kira (kosong)
{
...
m_kaunter += 1.0;
DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
...
}

Contoh di atas menunjukkan bagaimana kod yang memanggil Probe tidak perlu mempunyai eksplisit
merujuk kepada Probe, tetapi boleh mengarahkan tetapan nilai melalui ruang nama Config.
Ini adalah serupa dalam fungsi kepada Stat::Letakkan kaedah yang diperkenalkan oleh kertas ns2measure
[Cic06], dan membenarkan pengguna memasukkan kenyataan Probe buat sementara waktu seperti Printf kenyataan
dalam yang sedia ada ns-3 model. Ambil perhatian bahawa untuk dapat menggunakan DoubleProbe dalam ini
contoh seperti ini, 2 perkara diperlukan:

1. fail pengepala modul statistik disertakan dalam contoh fail .cc

2. contoh dibuat bergantung pada modul statistik dalam fail wscriptnya.

Perkara yang serupa perlu dilakukan untuk menambah Probe lain di tempat lain dalam ns-3
asas kod.

Nilai untuk DoubleProbe juga boleh ditetapkan menggunakan fungsi DoubleProbe::SetValue(),
manakala nilai untuk DoubleProbe boleh diperoleh menggunakan fungsi tersebut
DoubleProbe::GetValue().

DoubleProbe mengeksport nilai berganda dalam sumber surih "Output"nya; objek hiliran
boleh menyambung sinki surih (NotifyViaProbe) kepada ini seperti berikut:

disambungkan = probe1->TraceConnect ("Output", probe1->GetName (), MakeCallback (&NotifyViaProbe));

lain-lain pemeriksaan
Selain DoubleProbe, Probe berikut juga tersedia:

· Uinteger8Probe menyambung ke ns-3 surih sumber mengeksport uint8_t.

· Uinteger16Probe menyambung ke ns-3 surih sumber mengeksport uint16_t.

· Uinteger32Probe menyambung ke ns-3 surih sumber mengeksport uint32_t.

· PacketProbe bersambung ke ns-3 jejak sumber mengeksport paket.

· ApplicationPacketProbe bersambung ke ns-3 surih sumber mengeksport paket dan soket
alamat.

· Ipv4PacketProbe bersambung ke ns-3 surih sumber mengeksport paket, objek IPv4 dan
antara muka.

mewujudkan baru Siasatan jenis
Untuk mencipta jenis Probe baharu, anda perlu melakukan langkah berikut:

· Pastikan bahawa kelas Probe baharu anda diperoleh daripada kelas asas Probe.

· Pastikan bahawa fungsi maya tulen yang kelas Probe baharu anda warisi daripada
Kelas asas siasatan dilaksanakan.

· Cari kelas Probe sedia ada yang menggunakan sumber surih yang paling hampir dengan jenisnya
jenis sumber surih yang akan digunakan oleh Probe anda.

· Salin fail pengepala kelas Probe sedia ada (.h) dan fail pelaksanaan (.cc) kepada dua
fail baharu dengan nama yang sepadan dengan Probe baharu anda.

· Gantikan jenis, hujah dan pembolehubah dalam fail yang disalin dengan yang sesuai
taip untuk Probe anda.

· Buat pengubahsuaian yang diperlukan untuk membuat kod disusun dan menjadikannya berkelakuan seperti yang anda lakukan
seperti.

Contoh
Dua contoh akan dibincangkan secara terperinci di sini:

· Contoh Kuar Berganda

· Contoh Plot Paket IPv4

Dua kali ganda Siasatan Contoh
Contoh kuar berganda telah dibincangkan sebelum ini. Contoh program boleh didapati
in src/stats/example/double-probe-example.cc. Untuk meringkaskan apa yang berlaku dalam program ini,
terdapat pemancar yang mengeksport pembilang yang bertambah mengikut proses Poisson.
Khususnya, dua cara pemancaran data ditunjukkan:

1. melalui pembolehubah yang dikesan yang disambungkan pada satu Probe:

TracedValue m_kaunter; // biasanya ini adalah jenis integer

2. melalui kaunter yang nilainya disiarkan ke Probe kedua, dirujuk dengan namanya dalam
sistem Konfigurasi:

membatalkan
Pemancar:: Kira (kosong)
{
NS_LOG_FUNCTION (ini);
NS_LOG_DEBUG ("Mengira pada " << Simulator::Sekarang ().GetSeconds ());
m_kaunter += 1.0;
DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
Simulator::Jadual (Saat (m_var->GetValue ()), &Emitter::Count, this);
}

Mari lihat Probe dengan lebih teliti. Probe boleh menerima nilainya dalam berbilang
cara:

1. oleh Probe mengakses sumber surih secara terus dan menyambungkan sinki surih kepadanya

2. oleh Probe mengakses sumber surih melalui ruang nama konfigurasi dan menyambungkan a
kesan tenggelam kepadanya

3. dengan kod panggilan secara eksplisit memanggil Probe SetValue() kaedah

4. dengan kod panggilan secara eksplisit memanggil SetValueByPath
("/path/through/Config/namespace", ...)

Dua teknik pertama dijangka menjadi yang paling biasa. Juga dalam contoh,
penyambungan fungsi panggil balik biasa ditunjukkan, seperti yang biasanya dilakukan dalam ns-3. ini
fungsi panggil balik tidak dikaitkan dengan objek Probe. Kami akan memanggil kes ini 0) di bawah.

// Ini ialah fungsi untuk menguji mengaitkan fungsi mentah kepada sumber surih
membatalkan
NotifyViaTraceSource (std::string context, double oldVal, double newVal)
{
NS_LOG_DEBUG ("konteks: " << konteks << " lama " << oldVal << " baru " << newVal);
}

Pertama, pemancar perlu disediakan:

Ptr pemancar = CreateObject ();
Nama::Tambah ("/Nama/Pemancar", pemancar);

// Objek Pemancar tidak dikaitkan dengan nod ns-3, jadi
// ia tidak akan bermula secara automatik, jadi kita perlu melakukannya sendiri
Simulator::Jadual (Saat (0.0), & Pemancar::Mula, pemancar);

Pelbagai DoubleProbes berinteraksi dengan pemancar dalam contoh seperti yang ditunjukkan di bawah.

Kes 0):

// Di bawah menunjukkan fungsi biasa tanpa probe
// (sambungkan fungsi sinki ke sumber surih)
//
disambungkan = pemancar->TraceConnect ("Kaunter", "konteks sampel", MakeCallback (&NotifyViaTraceSource));
NS_ASSERT_MSG (disambungkan, "Sumber jejak tidak disambungkan");

kes 1):

//
// Probe1 akan disambungkan terus ke objek sumber surih Pemancar
//

// probe1 akan disambungkan ke sumber surih Pemancar
Ptr probe1 = CreateObject ();
// nama siasatan boleh berfungsi sebagai konteksnya dalam pengesanan
probe1->SetName ("ObjectProbe");

// Sambungkan probe ke Kaunter pemancar
disambungkan = probe1->ConnectByObject ("Counter", pemancar);
NS_ASSERT_MSG (disambungkan, "Sumber jejak tidak disambungkan ke probe1");

kes 2):

//
// Probe2 akan disambungkan ke objek sumber surih Pemancar oleh
// mengaksesnya dengan nama laluan dalam pangkalan data Config
//

// Cipta satu lagi siasatan yang serupa; ini akan disambungkan melalui laluan Config
Ptr probe2 = CreateObject ();
probe2->SetName ("PathProbe");

// Nota, tiada nilai pulangan disemak di sini
probe2->ConnectByPath ("/Names/Emitter/Counter");

kes 4) (kes 3 tidak ditunjukkan dalam contoh ini):

//
// Probe3 akan dipanggil oleh pemancar terus melalui
// kaedah statik SetValueByPath().
//
Ptr probe3 = CreateObject ();
probe3->SetName ("StaticallyAccessedProbe");
// Kita mesti menambahnya pada pangkalan data konfigurasi
Names::Add ("/Names/Probes", probe3->GetName (), probe3);

Dan akhirnya, contoh menunjukkan bagaimana probe boleh disambungkan untuk menjana output:

// Siasatan itu sendiri harus menghasilkan output. Konteks yang kami sediakan
// kepada siasatan ini (dalam kes ini, nama siasatan) akan membantu untuk menyahkekaburan
// sumber jejak
disambungkan = probe3->TraceConnect ("Output",
"/Nama/Probe/StaticallyAccessedProbe/Output",
MakeCallback (&NotifyViaProbe));
NS_ASSERT_MSG (disambungkan, "Sumber jejak tidak .. disambungkan ke Output probe3");

Panggilan balik berikut disambungkan ke Probe dalam contoh ini untuk tujuan ilustrasi;
biasanya, Probe akan disambungkan pada objek Pemungut.

// Ini adalah fungsi untuk menguji mengaitkannya ke output probe
membatalkan
NotifyViaProbe (std::string context, double oldVal, double newVal)
{
NS_LOG_DEBUG ("konteks: " << konteks << " lama " << oldVal << " baru " << newVal);
}

IPv4 Bungkusan Plot Contoh
Contoh plot paket IPv4 adalah berdasarkan contoh kelima.cc daripada ns-3 Tutorial. Ia
boleh didapati di src/stats/example/ipv4-packet-plot-example.cc.

nod 0 nod 1
+----------------+ +----------------+
| ns-3 TCP | | ns-3 TCP |
+----------------+ +----------------+
| 10.1.1.1 | | 10.1.1.2 |
+----------------+ +----------------+
| titik ke titik | | titik ke titik |
+----------------+ +----------------+
| |
+---------------------+

Kami hanya akan melihat Probe, kerana ia menggambarkan bahawa Probe mungkin juga membongkar nilai daripada
struktur (dalam kes ini, paket) dan laporkan nilai tersebut sebagai output sumber surih, sebaliknya
daripada hanya melalui jenis data yang sama.

Terdapat aspek lain dalam contoh ini yang akan diterangkan kemudian dalam dokumentasi.
Dua jenis data yang dieksport ialah paket itu sendiri (Output) dan kiraan daripada
bilangan bait dalam paket (OutputBytes).

JenisId
Ipv4PacketProbe::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::Ipv4PacketProbe")
.SetParent ()
.AddConstructor ()
.AddTraceSource ( "Output",
"Paket ditambah objek IPv4 dan antara muka yang berfungsi sebagai output untuk siasatan ini",
MakeTraceSourceAccessor (&Ipv4PacketProbe::m_output))
.AddTraceSource ( "OutputBytes",
"Bilangan bait dalam paket",
MakeTraceSourceAccessor (&Ipv4PacketProbe::m_outputBytes))
;
tid balik;
}

Apabila sinki jejak Probe mendapat satu paket, jika Probe didayakan, maka ia akan keluar
paket padanya Output sumber surih, tetapi ia juga akan mengeluarkan bilangan bait pada
OutputBytes sumber jejak.

membatalkan
Ipv4PacketProbe::TraceSink (Ptr paket, Ptr ipv4, antara muka uint4_t)
{
NS_LOG_FUNCTION (antara muka << paket << ipv4 << ini);
jika (IsEnabled ())
{
m_packet = paket;
m_ipv4 = ipv4;
m_interface = antara muka;
m_output (paket, ipv4, antara muka);

uint32_t packetSizeNew = paket->GetSize ();
m_outputBytes (m_packetSizeOld, packetSizeNew);
m_packetSizeOld = paketSizeNew;
}
}

Rujukan
[Cic06]
Claudio Cicconetti, Enzo Mingozzi, Giovanni Stea, "Rangka Kerja Bersepadu untuk
Mendayakan Pengumpulan Data dan Analisis Statistik yang Berkesan dengan ns2, Bengkel pada
ns-2 (WNS2), Pisa, Itali, Oktober 2006.

Pengumpul
Bahagian ini adalah pemegang tempat untuk memperincikan fungsi yang disediakan oleh Pemungut
kelas ke an ns-3 simulasi, dan memberikan contoh tentang cara mengekodnya dalam atur cara.

Catatan: Sehingga ns-3.18, Pengumpul masih dalam pembangunan dan belum disediakan sebagai sebahagian
daripada rangka kerja.

Pengagregat
Bahagian ini memperincikan fungsi yang disediakan oleh kelas Aggregator kepada a ns-3
simulasi. Bahagian ini bertujuan untuk pengguna yang berminat untuk membangunkan simulasi dengan
ns-3 alatan dan menggunakan Rangka Kerja Pengumpulan Data, yang mana kelas Aggregator ialah a
bahagian, untuk menjana output data dengan hasil simulasi mereka.

Agregator Pengenalan
Objek Agregator sepatutnya disambungkan pada satu atau lebih sumber surih untuk
menerima input. Agregator ialah titik akhir data yang dikumpul oleh rangkaian
Probe dan Pengumpul semasa simulasi. Ia adalah tugas Agregator untuk mengambil ini
nilai dan mengubahnya menjadi format output akhir mereka seperti fail teks biasa,
fail hamparan, plot atau pangkalan data.

Biasanya, agregator disambungkan kepada satu atau lebih Pengumpul. Dengan cara ini, bila-bila masa
sumber surih Pengumpul mengeksport nilai baharu, Agregator boleh memproses nilai tersebut
bahawa ia boleh digunakan dalam format output akhir di mana nilai data akan berada selepas
simulasi.

Perhatikan perkara berikut mengenai Agregator:

· Agregator boleh dihidupkan dan dimatikan secara dinamik semasa simulasi dengan panggilan ke
Dayakan() and Lumpuhkan(). Sebagai contoh, pengagregatan data mungkin dimatikan semasa
fasa pemanasan simulasi, yang bermaksud nilai tersebut tidak akan disertakan dalam perlawanan akhir
medium keluaran.

· Agregator menerima data daripada Pengumpul melalui panggilan balik. Apabila seorang Pemungut dikaitkan
kepada pengagregat, panggilan ke TraceConnect dibuat untuk mewujudkan jejak Pengagregat
kaedah sinki sebagai panggilan balik.

Sehingga kini, dua Agregator telah dilaksanakan:

· GnuplotAggregator

· Pengumpul Fail

GnplotAggregator
GnuplotAggregator menghasilkan fail output yang digunakan untuk membuat gnuplot.

GnuplotAggregator akan mencipta 3 fail berbeza pada penghujung simulasi:

· Fail data gnuplot yang diasingkan ruang

· Fail kawalan gnuplot

· Skrip shell untuk menjana gnuplot

Ciptaan
Objek jenis GnuplotAggregator akan dibuat di sini untuk menunjukkan perkara yang perlu dilakukan.

Seseorang mengisytiharkan GnuplotAggregator dalam memori dinamik dengan menggunakan kelas penunjuk pintar
(Ptr ). Untuk mencipta GnuplotAggregator dalam memori dinamik dengan penunjuk pintar, satu sahaja
perlu menghubungi ns-3 kaedah CreateObject(). Kod berikut daripada
src/stats/example/gnuplot-aggregator-example.cc menunjukkan cara melakukan ini:

string fileNameWithoutExtension = "gnuplot-aggregator";

// Buat agregator.
Ptr pengagregat =
CreateObject (Nama failTanpa Sambungan);

Argumen pertama untuk pembina, fileNameWithoutExtension, ialah nama bagi
fail berkaitan gnuplot untuk ditulis tanpa sambungan. GnuplotAggregator ini akan mencipta a
Fail data gnuplot yang dipisahkan ruang bernama "gnuplot-aggregator.dat", fail kawalan gnuplot
bernama "gnuplot-aggregator.plt", dan skrip shell untuk menjana gnuplot bernama +
"gnuplot-aggregator.sh".

Gnuplot yang dibuat boleh mempunyai kuncinya di 4 lokasi berbeza:

· Tiada kunci

· Kunci di dalam plot (lalai)

· Kunci di atas plot

· Kunci di bawah plot

Nilai enum lokasi kunci gnuplot berikut dibenarkan untuk menentukan kedudukan kunci:

enum KeyLocation {
NO_KEY,
KEY_INSIDE,
KEY_ABOVE,
KEY_BELOW
};

Jika ia dikehendaki mempunyai kunci di bawah dan bukannya kedudukan lalai di dalam, maka
anda boleh melakukan perkara berikut.

aggregator->SetKeyLocation(GnuplotAggregator::KEY_BELOW);

Contoh
Satu contoh akan dibincangkan secara terperinci di sini:

· Contoh Pengagregat Gnuplot

Gnplot Agregator Contoh
Contoh yang menggunakan GnuplotAggregator boleh didapati di
src/stats/example/gnuplot-aggregator-example.cc.

Gnuplot 2-D berikut telah dibuat menggunakan contoh.
[imej] Gnuplot 2-D Dibuat oleh gnuplot-aggregator-example.cc Contoh..UNINDENT

Kod ini daripada contoh menunjukkan cara membina GnuplotAggregator seperti yang telah dibincangkan
atas.

batal Create2dPlot ()
{
menggunakan ruang nama std;

string fileNameWithoutExtension = "gnuplot-aggregator";
string plotTitle = "Plot Pengagregat Gnuplot";
string plotXAxisHeading = "Masa (saat)";
string plotYAxisHeading = "Nilai Berganda";
string plotDatasetLabel = "Nilai Data";
string datasetContext = "Dataset/Context/String";

// Buat agregator.
Ptr pengagregat =
CreateObject (Nama failTanpa Sambungan);

Pelbagai atribut GnuplotAggregator ditetapkan termasuk set data 2-D yang akan
diplot.

// Tetapkan sifat agregator.
aggregator->SetTerminal ("png");
aggregator->SetTitle (plotTitle);
aggregator->SetLegend (plotXAxisHeading, plotYAxisHeading);

// Tambah set data pada agregator.
aggregator->Add2dDataset (datasetContext, plotDatasetLabel);

// agregator mesti dihidupkan
aggregator->Enable ();

Seterusnya, nilai 2-D dikira, dan setiap satu ditulis secara individu ke
GnuplotAggregator menggunakan Write2d() fungsi.

masa berganda;
nilai berganda;

// Cipta set data 2-D.
untuk (masa = -5.0; masa <= +5.0; masa += 1.0)
{
// Kira lengkung 2-D
//
/ / 2
// nilai = masa .
//
nilai = masa * masa;

// Tambahkan titik ini pada plot.
aggregator->Write2d (datasetContext, masa, nilai);
}

// Lumpuhkan pengelogan data untuk agregator.
aggregator->Lumpuhkan ();
}

FileAggregator
FileAggregator menghantar nilai yang diterimanya ke fail.

FileAggregator boleh mencipta 4 jenis fail yang berbeza:

· Diformat

· Ruang diasingkan (lalai)

· Koma dipisahkan

· Tab diasingkan

Fail yang diformat menggunakan rentetan format gaya C dan fungsi sprintf() untuk mencetaknya
nilai dalam fail yang sedang ditulis.

Ciptaan
Objek jenis FileAggregator akan dibuat di sini untuk menunjukkan perkara yang perlu dilakukan.

Seseorang mengisytiharkan FileAggregator dalam memori dinamik dengan menggunakan kelas penunjuk pintar (Ptr ).
Untuk mencipta FileAggregator dalam memori dinamik dengan penunjuk pintar, seseorang hanya perlu memanggil
yang ns-3 kaedah CreateObject. Kod berikut daripada
src/stats/example/file-aggregator-example.cc menunjukkan cara melakukan ini:

string fileName = "file-aggregator-formatted-values.txt";

// Buat agregator yang akan mempunyai nilai terformat.
Ptr pengagregat =
CreateObject (Nama fail, FileAggregator::FORMATTED);

Argumen pertama untuk pembina, nama fail, ialah nama fail untuk ditulis; yang
argumen kedua, fileType, ialah jenis fail untuk ditulis. FileAggregator ini akan membuat a
fail bernama "file-aggregator-formatted-values.txt" dengan nilainya dicetak seperti yang ditentukan oleh
FileType, iaitu, diformatkan dalam kes ini.

Nilai enum jenis fail berikut dibenarkan:

enum FileType {
BERFORMAT,
SPACE_SEPARATED,
COMMA_SEPARATED,
TAB_PISAHKAN
};

Contoh
Satu contoh akan dibincangkan secara terperinci di sini:

· Contoh Pengumpul Fail

File Agregator Contoh
Contoh yang menggunakan FileAggregator boleh didapati di
src/stats/example/file-aggregator-example.cc.

Fail teks berikut dengan 2 lajur nilai yang dipisahkan dengan koma telah dibuat menggunakan
contohnya.

-5,25
-4,16
-3,9
-2,4
-1,1
0,0
1,1
2,4
3,9
4,16
5,25

Kod ini daripada contoh menunjukkan cara membina FileAggregator seperti yang telah dibincangkan
atas.

batal CreateCommaSeparatedFile ()
{
menggunakan ruang nama std;

string fileName = "file-aggregator-comma-separated.txt";
string datasetContext = "Dataset/Context/String";

// Buat agregator.
Ptr pengagregat =
CreateObject (Nama fail, FileAggregator::COMMA_SEPARATED);

Atribut FileAggregator ditetapkan.

// agregator mesti dihidupkan
aggregator->Enable ();

Seterusnya, nilai 2-D dikira, dan setiap satu ditulis secara individu ke
FileAggregator menggunakan Write2d() fungsi.

masa berganda;
nilai berganda;

// Cipta set data 2-D.
untuk (masa = -5.0; masa <= +5.0; masa += 1.0)
{
// Kira lengkung 2-D
//
/ / 2
// nilai = masa .
//
nilai = masa * masa;

// Tambahkan titik ini pada plot.
aggregator->Write2d (datasetContext, masa, nilai);
}

// Lumpuhkan pengelogan data untuk agregator.
aggregator->Lumpuhkan ();
}

Fail teks berikut dengan 2 lajur nilai terformat juga dibuat menggunakan fail
contohnya.

Masa = -5.000e+00 Nilai = 25
Masa = -4.000e+00 Nilai = 16
Masa = -3.000e+00 Nilai = 9
Masa = -2.000e+00 Nilai = 4
Masa = -1.000e+00 Nilai = 1
Masa = 0.000e+00 Nilai = 0
Masa = 1.000e+00 Nilai = 1
Masa = 2.000e+00 Nilai = 4
Masa = 3.000e+00 Nilai = 9
Masa = 4.000e+00 Nilai = 16
Masa = 5.000e+00 Nilai = 25

Kod ini daripada contoh menunjukkan cara membina FileAggregator seperti yang telah dibincangkan
atas.

batal CreateFormattedFile ()
{
menggunakan ruang nama std;

string fileName = "file-aggregator-formatted-values.txt";
string datasetContext = "Dataset/Context/String";

// Buat agregator yang akan mempunyai nilai terformat.
Ptr pengagregat =
CreateObject (Nama fail, FileAggregator::FORMATTED);

Atribut FileAggregator ditetapkan, termasuk rentetan format gaya C untuk digunakan.

// Tetapkan format untuk nilai.
aggregator->Set2dFormat ("Masa = %.3e\tValue = %.0f");

// agregator mesti dihidupkan
aggregator->Enable ();

Seterusnya, nilai 2-D dikira, dan setiap satu ditulis secara individu ke
FileAggregator menggunakan Write2d() fungsi.

masa berganda;
nilai berganda;

// Cipta set data 2-D.
untuk (masa = -5.0; masa <= +5.0; masa += 1.0)
{
// Kira lengkung 2-D
//
/ / 2
// nilai = masa .
//
nilai = masa * masa;

// Tambahkan titik ini pada plot.
aggregator->Write2d (datasetContext, masa, nilai);
}

// Lumpuhkan pengelogan data untuk agregator.
aggregator->Lumpuhkan ();
}

Penyesuai
Bahagian ini memperincikan fungsi yang disediakan oleh kelas Penyesuai kepada a ns-3
simulasi. Bahagian ini bertujuan untuk pengguna yang berminat untuk membangunkan simulasi dengan
ns-3 alatan dan menggunakan Rangka Kerja Pengumpulan Data, di mana kelas Penyesuai adalah sebahagian,
untuk menjana output data dengan hasil simulasi mereka.

Nota: istilah 'penyesuai' juga boleh dieja sebagai 'penyesuai'; kami memilih ejaan yang selaras
dengan standard C++.

Adaptor Pengenalan
Penyesuai digunakan untuk membuat sambungan antara pelbagai jenis objek DCF.

Sehingga kini, satu Penyesuai telah dilaksanakan:

· TimeSeriesAdaptor

Masa Siri Adaptor
TimeSeriesAdaptor membolehkan Probes menyambung terus ke Aggregators tanpa memerlukan apa-apa
Pengumpul di antara.

Kedua-dua pembantu DCF yang dilaksanakan menggunakan TimeSeriesAdaptors untuk mengambil siasatan
nilai jenis yang berbeza dan keluarkan masa semasa ditambah nilai dengan kedua-duanya ditukar
untuk berganda.

Peranan kelas TimeSeriesAdaptor ialah penyesuai, yang mengambil nilai mentah
data kuar pelbagai jenis dan mengeluarkan tuple dua nilai berganda. Yang pertama ialah a
cap waktu, yang mungkin ditetapkan kepada peleraian yang berbeza (cth. Saat, Milisaat, dsb.) dalam
masa hadapan tetapi yang kini dikodkan keras kepada Seconds. Yang kedua ialah penukaran a
nilai bukan dua kali ganda kepada nilai dua kali ganda (mungkin dengan kehilangan ketepatan).

Skop/Keterbatasan
Bahagian ini membincangkan skop dan had Rangka Kerja Pengumpulan Data.

Pada masa ini, hanya Probe ini telah dilaksanakan di DCF:

· BooleanProbe

· DoubleProbe

· Uinteger8Probe

· Uinteger16Probe

· Uinteger32Probe

· TimeProbe

· PacketProbe

· ApplicationPacketProbe

· Ipv4PacketProbe

Pada masa ini, tiada Pengumpul tersedia dalam DCF, walaupun BasicStatsCollector berada di bawah
pembangunan.

Pada masa ini, hanya Agregator ini telah dilaksanakan di DCF:

· GnuplotAggregator

· Pengumpul Fail

Pada masa ini, hanya Penyesuai ini telah dilaksanakan dalam DCF:

Penyesuai Siri Masa.

Masa depan kerja
Bahagian ini membincangkan kerja masa hadapan yang perlu dilakukan pada Rangka Kerja Pengumpulan Data.

Berikut adalah beberapa perkara yang masih perlu dilakukan:

· Sambungkan lebih banyak sumber surih masuk ns-3 kod untuk mendapatkan lebih banyak nilai daripada simulator.

· Laksanakan lebih banyak jenis Probe daripada yang ada sekarang.

· Laksanakan lebih daripada sekadar Pemungut 2-D semasa tunggal, BasicStatsCollector.

· Laksanakan lebih banyak Agregator.

· Laksanakan lebih daripada sekadar Penyesuai.

Statistik Rangka Kerja
Bab ini menggariskan kerja pada pengumpulan data simulasi dan rangka kerja statistik untuk
ns-3.

Kod sumber untuk rangka kerja statistik hidup dalam direktori src/stats.

Anda
Objektif utama untuk usaha ini adalah seperti berikut:

· Menyediakan kefungsian untuk merekod, mengira dan mempersembahkan data dan statistik untuk analisis
simulasi rangkaian.

· Tingkatkan prestasi simulasi dengan mengurangkan keperluan untuk menjana log masuk jejak yang banyak
perintah untuk mengumpul data.

· Dayakan kawalan simulasi melalui statistik dalam talian, cth menamatkan simulasi atau
ujian yang berulang.

Submatlamat terbitan dan ciri sasaran lain termasuk yang berikut:

· Integrasi dengan sistem pengesanan ns-3 sedia ada sebagai rangka kerja instrumentasi asas
daripada enjin simulasi dalaman, cth susunan rangkaian, peranti bersih dan saluran.

· Membolehkan pengguna menggunakan rangka kerja statistik tanpa memerlukan penggunaan pengesanan
sistem.

· Membantu pengguna membuat, mengagregat dan menganalisis data sepanjang berbilang percubaan.

· Sokongan untuk instrumentasi ciptaan pengguna, cth acara khusus aplikasi dan
langkah-langkah.

· Memori rendah dan overhed CPU apabila pakej tidak digunakan.

· Memanfaatkan alat analisis dan output sedia ada sebaik mungkin. Rangka kerja mungkin
menyediakan beberapa statistik asas, tetapi tumpuannya adalah untuk mengumpul data dan membuatnya
boleh diakses untuk manipulasi dalam alatan yang telah ditetapkan.

· Sokongan akhirnya untuk mengedarkan replikasi bebas adalah penting tetapi tidak disertakan
dalam pusingan pertama ciri.

Pengenalan
Rangka kerja statistik termasuk ciri-ciri berikut:

· Rangka kerja teras dan dua pengumpul data asas: Pembilang, dan min/maks/pura/jumlah
pemerhati.

· Sambungan mereka untuk bekerja dengan mudah dengan masa dan paket.

· Output teks biasa diformatkan untuk OMNet++.

· Output pangkalan data menggunakan SQLite, enjin SQL yang berdiri sendiri, ringan dan berprestasi tinggi.

· Metadata mandatori dan terbuka untuk menerangkan dan bekerja dengan larian.

· Contoh berdasarkan eksperimen nosional untuk mengkaji sifat-sifat NS-3
prestasi WiFi ad hoc lalai. Ia menggabungkan perkara berikut:

· Membina rangkaian WiFi ad hoc dua nod, dengan nod jarak berparameter
selainnya.

· Sumber trafik UDP dan aplikasi sink dengan gelagat yang berbeza sedikit dan
cangkuk ukuran daripada kelas stok.

· Pengumpulan data daripada teras NS-3 melalui isyarat surih sedia ada, khususnya data pada
bingkai yang dihantar dan diterima oleh objek WiFi MAC.

· Instrumentasi aplikasi tersuai dengan menyambungkan isyarat surih baharu kepada statistik
rangka kerja, serta melalui kemas kini langsung. Maklumat direkodkan tentang jumlah paket
dihantar dan diterima, bait dihantar, dan kelewatan hujung ke hujung.

· Contoh penggunaan tag paket untuk menjejak kelewatan hujung ke hujung.

· Skrip kawalan mudah yang menjalankan beberapa percubaan percubaan pada pelbagai
jarak dan pertanyaan pangkalan data yang terhasil untuk menghasilkan graf menggunakan GNUPlot.

To-Do
Item keutamaan tinggi termasuk:

· Kemasukan kod statistik dalam talian, cth untuk selang keyakinan cekap memori.

· Peruntukan dalam pengumpul data untuk menamatkan larian, iaitu apabila ambang atau
keyakinan dipenuhi.

· Pengumpul data untuk mengelog sampel dari semasa ke semasa, dan output kepada pelbagai format.

· Tunjuk cara menulis gam acara kitaran mudah untuk kerap meninjau beberapa nilai.

Setiap daripada mereka harus terbukti mudah untuk digabungkan dalam rangka kerja semasa.

Pendekatan
Rangka kerja ini berdasarkan prinsip teras berikut:

· Satu percubaan percubaan dijalankan oleh satu contoh program simulasi, sama ada dalam
selari atau bersiri.

· Skrip kawalan melaksanakan contoh simulasi, mengubah parameter mengikut keperluan.

· Data dikumpul dan disimpan untuk plot dan analisis menggunakan skrip luaran dan
alatan sedia ada.

· Langkah-langkah dalam teras ns-3 diambil dengan menyambungkan rangka kerja statistik kepada sedia ada
jejak isyarat.

· Isyarat jejak atau manipulasi langsung rangka kerja boleh digunakan untuk tersuai instrumen
kod simulasi.

Komponen asas rangka kerja tersebut dan interaksinya digambarkan dalam
rajah berikut. [gambar]

Contoh
Bahagian ini melalui proses membina eksperimen dalam rangka kerja dan
menghasilkan data untuk analisis (graf) daripadanya, menunjukkan struktur dan API bersama-sama
Jalan.

Soalan
''Apakah prestasi (simulasi) WiFi NetDevices ns-3 (menggunakan lalai
tetapan)? Sejauh manakah nod wayarles boleh berada dalam simulasi sebelum tidak boleh
berkomunikasi dengan pasti?''

· Hipotesis: Berdasarkan pengetahuan tentang prestasi kehidupan sebenar, nod harus berkomunikasi
cukup baik hingga sekurang-kurangnya 100m dipisahkan. Komunikasi melebihi 200m tidak sepatutnya
boleh dilaksanakan.

Walaupun bukan soalan yang sangat biasa dalam konteks simulasi, ini adalah sifat penting
yang mana pembangun simulasi harus mempunyai pemahaman asas. Ia juga adalah perkara biasa
kajian dilakukan pada perkakasan langsung.

Simulasi Program
Perkara pertama yang perlu dilakukan dalam melaksanakan eksperimen ini ialah membangunkan simulasi
program. Kod untuk contoh ini boleh didapati dalam examples/stats/wifi-example-sim.cc.
Ia melakukan langkah-langkah utama berikut.

· Mengisytiharkan parameter dan menghuraikan baris arahan menggunakan ns3::CommandLine.

jarak dua kali ganda = 50.0;
format rentetan ("OMNet++");
percubaan rentetan ("ujian-jarak-wifi");
strategi rentetan ("wifi-lalai");
rentetan runID;

cmd Baris Perintah;
cmd.AddValue("jarak", "Jarak dipisahkan untuk meletakkan nod (dalam meter)", jarak);
cmd.AddValue("format", "Format untuk digunakan untuk output data.", format);
cmd.AddValue("eksperimen", "Pengecam untuk eksperimen.", percubaan);
cmd.AddValue("strategi", "Pengecam untuk strategi.", strategi);
cmd.AddValue("run", "Identifier for run.", runID);
cmd.Parse (argc, argv);

· Mencipta nod dan susunan rangkaian menggunakan ns3::NodeContainer, ns3::WiFiHelper, dan
ns3::InternetStackHelper.

NodeContainer nod;
nod.Buat(2);

WifiHelper wifi;
wifi.SetMac("ns3::AdhocWifiMac");
wifi.SetPhy("ns3::WifiPhy");
NetDeviceContainer nodeDevices = wifi.Install(nod);

InternetStackHelper internet;
internet.Pasang(nod);
Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase("192.168.0.0", "255.255.255.0");
ipAddrs.Assign(nodeDevices);

· Meletakkan nod menggunakan ns3::MobilityHelper. Secara lalai nod mempunyai statik
mobiliti dan tidak akan bergerak, tetapi mesti diletakkan pada jarak tertentu. Disana ada
beberapa cara untuk melakukan ini; ia dilakukan di sini menggunakan ns3::ListPositionAllocator, yang menarik
jawatan daripada senarai yang diberikan.

MobilityHelper mobiliti;
Ptr positionAlloc =
CreateObject ();
positionAlloc->Tambah(Vektor(0.0, 0.0, 0.0));
positionAlloc->Tambah(Vektor(0.0, jarak, 0.0));
mobiliti.SetPositionAllocator(positionAlloc);
mobiliti.Pasang(nod);

· Memasang penjana trafik dan sinki trafik. Saham Aplikasi boleh jadi
digunakan, tetapi contohnya termasuk objek tersuai dalam src/test/test02-apps.(cc|h). Ini
mempunyai tingkah laku yang mudah, menghasilkan bilangan paket tertentu yang dijarakkan pada selang waktu tertentu.
Oleh kerana hanya terdapat satu daripada setiap ia dipasang secara manual; untuk set yang lebih besar
ns3::ApplicationHelper kelas boleh digunakan. Yang dikomen-keluar Konfigurasi::Tetapkan perubahan baris
destinasi paket, ditetapkan untuk disiarkan secara lalai dalam contoh ini. Perhatikan bahawa
secara umum WiFi mungkin mempunyai prestasi yang berbeza untuk penyiaran dan bingkai unicast disebabkan oleh
kawalan kadar yang berbeza dan dasar penghantaran semula MAC.

Ptr appSource = NodeList::GetNode(0);
Ptr penghantar = CreateObject ();
appSource->AddApplication(pengirim);
penghantar->Mula(Seconds(1));

Ptr appSink = NodeList::GetNode(1);
Ptr penerima = CreateObject ();
appSink->AddApplication(receiver);
penerima->Mula(Seconds(0));

// Config::Set("/NodeList/*/ApplicationList/*/$Sender/Destination",
// Ipv4AddressValue("192.168.0.2"));

· Mengkonfigurasi data dan statistik yang akan dikumpul. Paradigma asas ialah a
ns3::Pengumpul Data objek dicipta untuk menyimpan maklumat tentang larian tertentu ini, untuk
pemerhati dan kalkulator yang dilampirkan untuk menjana data sebenarnya. yang penting,
maklumat jalankan termasuk label untuk ''percubaan'', ''strategi'', ''input'' dan
''lari''. Ini digunakan untuk mengenal pasti kemudian dan mengumpulkan data dengan mudah daripada berbilang percubaan.

· Eksperimen ialah kajian yang merupakan ahli percubaan ini. Ini adalah pada WiFi
prestasi dan jarak.

· Strategi ialah kod atau parameter yang sedang diperiksa dalam percubaan ini. Dalam contoh ini
ia telah ditetapkan, tetapi sambungan yang jelas adalah untuk menyiasat bit WiFi yang berbeza
kadar, setiap satunya adalah strategi yang berbeza.

· Input adalah masalah khusus yang diberikan kepada percubaan ini. Di sini ia adalah semata-mata
jarak antara dua nod.

· RunID ialah pengecam unik untuk percubaan ini yang mana maklumatnya ditag
untuk pengenalpastian dalam analisis kemudian. Jika tiada run ID diberikan program contoh yang dibuat
ID larian (lemah) menggunakan masa semasa.

Empat keping metadata itu diperlukan, tetapi lebih banyak lagi mungkin dikehendaki. Mereka boleh ditambah
ke rekod menggunakan ns3::DataCollector::AddMetadata() kaedah.

DataCollector;
data.DescribeRun(eksperimen, strategi, input, runID);
data.AddMetadata("pengarang", "tjkopena");

Pemerhatian dan pengiraan sebenar dilakukan oleh ns3::Kalkulator Data objek, yang mana
beberapa jenis wujud. Ini dicipta oleh program simulasi, dilampirkan pada
kod pelaporan atau pensampelan, dan kemudian didaftarkan dengan ns3::Pengumpul Data jadi mereka akan
akan ditanya kemudian untuk output mereka. Satu mekanisme pemerhatian yang mudah ialah menggunakan sedia ada
mengesan sumber, contohnya kepada objek instrumen dalam teras ns-3 tanpa mengubahnya
kod. Di sini kaunter dilampirkan terus kepada isyarat surih dalam lapisan MAC WiFi dihidupkan
nod sasaran.

Ptr totalRx = CreateObject ();
totalRx->SetKey("wifi-rx-frames");
Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Rx",
MakeCallback(&PacketCounterCalculator::FrameUpdate, totalRx));
data.AddDataCalculator(totalRx);

Kalkulator juga boleh dimanipulasi secara langsung. Dalam contoh ini, kaunter dibuat dan
dihantar ke aplikasi sinki trafik untuk dikemas kini apabila paket diterima.

Ptr > appRx = CreateObject >();
appRx->SetKey("receiver-rx-packets");
penerima->SetCounter(appRx);
data.AddDataCalculator(appRx);

Untuk menambah kiraan, kod pemprosesan paket sinki kemudian memanggil salah satu daripada
kaedah kemas kini kalkulator.

m_calc->Kemas kini();

Program ini termasuk beberapa contoh lain juga, menggunakan kedua-dua primitif
kalkulator seperti ns3::Kalkulator Kaunter dan yang disesuaikan untuk memerhati paket dan
kali. Dalam src/test/test02-apps.(cc|h) ia juga mencipta teg tersuai mudah yang digunakannya
untuk menjejaki kelewatan hujung ke hujung untuk paket yang dijana, melaporkan keputusan kepada a
ns3::TimeMinMaxAvgTotalCalculator kalkulator data.

· Menjalankan simulasi, yang sangat mudah setelah dibina.

Simulator::Run();

· Menjana sama ada OMNet++ or SQLite output, bergantung pada argumen baris arahan. Kepada
lakukan ini a ns3::DataOutputInterface objek dicipta dan dikonfigurasikan. Jenis tertentu
daripada ini akan menentukan format output. Objek ini kemudiannya diberi
ns3::Pengumpul Data objek yang disoal siasat untuk menghasilkan output.

Ptr pengeluaran;
if (format == "OMNet++") {
NS_LOG_INFO("Mencipta output data berformat OMNet++.");
output = CreateObject ();
} Lain {
# ifdef STAT_USE_DB
NS_LOG_INFO("Mencipta output data berformat SQLite.");
output = CreateObject ();
# endif
}

output->Output(data);

· Membebaskan sebarang memori yang digunakan oleh simulasi. Ini sepatutnya datang pada penghujung utama
fungsi untuk contoh.

Simulator::Memusnahkan();

Pembalakan
Untuk melihat perkara yang dilakukan oleh program contoh, aplikasi dan rangka kerja statistik secara terperinci, tetapkan
yang NS_LOG berubah dengan sewajarnya. Yang berikut akan memberikan output yang banyak daripada semua
tiga.

$ eksport NS_LOG=WiFiDistanceExperiment:WiFiDistanceApps

Ambil perhatian bahawa ini melambatkan simulasi dengan luar biasa.

Contoh Output
Menyusun dan hanya menjalankan program ujian akan ditambah OMNet++ output berformat seperti
berikut kepada data.sca.

lari lari-1212239121

percubaan attr "ujian-jarak-wifi"
strategi attr "wifi-lalai"
input attr "50"
attr penerangan ""

attr "pengarang" "tjkopena"

skalar wifi-tx-frames mengira 30
skalar wifi-rx-frames mengira 30
pengirim skalar-tx-paket kiraan 30
penerima skalar-rx-paket kiraan 30
kiraan saiz tx-pkt skalar 30
skalar tx-pkt-saiz jumlah 1920
skalar tx-pkt-saiz purata 64
skalar tx-pkt-saiz maks 64
skalar tx-pkt-saiz min 64
kiraan kelewatan skalar 30
jumlah kelewatan skalar 5884980ns
purata kelewatan skalar 196166ns
kelewatan skalar maks 196166ns
kelewatan skalar min 196166ns

Mengawal skrip
Untuk mengautomasikan pengumpulan data pada pelbagai input (jarak), Bash mudah
skrip digunakan untuk melaksanakan satu siri simulasi. Ia boleh didapati di
examples/stats/wifi-example-db.sh. Skrip dimaksudkan untuk dijalankan dari contoh/statistik/
direktori.

Skrip berjalan melalui satu set jarak, mengumpul hasil menjadi satu SQLite
pangkalan data. Pada setiap jarak lima ujian dijalankan untuk memberikan gambaran yang lebih baik tentang jangkaan
prestasi. Keseluruhan percubaan hanya mengambil masa beberapa dozen saat untuk dijalankan pada hujung rendah
mesin kerana tiada output semasa simulasi dan sedikit trafik dijana.

#!/ Bin / sh

JARAK = "25 50 75 100 125 145 147 150 152 155 157 160 162 165 167 170 172 175 177 180"
PERCUBAAN="1 2 3 4 5"

echo Contoh Eksperimen WiFi

jika [ -e data.db ]
kemudian
echo Bunuh data.db?
baca ANS
jika [ "$ANS" = "ya" -o "$ANS" = "y" ]
kemudian
echo Memadam pangkalan data
rm data.db
fi
fi

untuk percubaan dalam $TRIALS
do
untuk jarak dalam $DISTANCES
do
echo Percubaan $percubaan, jarak $jarak
./bin/test02 --format=db --distance=$distance --run=run-$distance-$trial
dilakukan
dilakukan

Analisis and Kesimpulan
Setelah semua percubaan telah dijalankan, skrip melaksanakan pertanyaan SQL mudah ke atas
pangkalan data menggunakan SQLite program baris arahan. Pertanyaan mengira purata kehilangan paket dalam
setiap set ujian yang dikaitkan dengan setiap jarak. Ia tidak mengambil kira berbeza
strategi, tetapi maklumat itu terdapat dalam pangkalan data untuk membuat beberapa sambungan mudah
dan berbuat demikian. Data yang dikumpul kemudiannya dihantar ke GNUPlot untuk digraf.

CMD="select exp.input,avg(100-((rx.value*100)/tx.value)) \
daripada Singletons rx, Singletons tx, Experiments exp \
di mana rx.run = tx.run DAN \
rx.run = exp.run DAN \
rx.name='receiver-rx-packets' DAN \
tx.name='pengirim-tx-paket' \
kumpulan mengikut exp.input \
pesanan melalui abs(exp.input) ASC;"

sqlite3 -noheader data.db "$CMD" > wifi-default.data
sed -i "s/|/ /" wifi-default.data
gnuplot wifi-example.gnuplot

Skrip GNUPlot ditemui di examples/stats/wifi-example.gnuplot hanya mentakrifkan output
format dan beberapa pemformatan asas untuk graf.

tetapkan potret postskrip terminal dipertingkatkan lw 2 "Helvetica" 14

set saiz 1.0, 0.66

#------------------------------------------------ ------
tetapkan "wifi-default.eps"
#set tajuk "Kehilangan Paket Melebihi Jarak"
tetapkan xlabel "Jarak (m) --- purata 5 percubaan setiap mata"
tetapkan julat x [0:200]
tetapkan ylabel "% Kehilangan Paket"
set yrange [0:110]

plot "wifi-default.data" dengan tajuk baris "WiFi Defaults"

akhir Hasilnya
Graf yang terhasil tidak memberikan bukti bahawa prestasi model WiFi lalai adalah
semestinya tidak munasabah dan memberikan sedikit keyakinan kepada sekurang-kurangnya tanda kesetiaan kepada
realiti. Lebih penting lagi, penyiasatan mudah ini telah dijalankan sepanjang jalan
menggunakan rangka kerja statistik. Berjaya! [gambar]

Waktu sebenar
ns-3 telah direka bentuk untuk penyepaduan ke dalam persekitaran mesin uji dan mesin maya. Kepada
berintegrasi dengan susunan rangkaian sebenar dan mengeluarkan/menggunakan paket, penjadual masa nyata adalah
diperlukan untuk cuba mengunci jam simulasi dengan jam perkakasan. Kami menerangkan di sini a
komponen ini: penjadual Masa Nyata.

Tujuan penjadual masa nyata adalah untuk menyebabkan perkembangan jam simulasi
berlaku secara serentak berkenaan dengan beberapa asas masa luaran. Tanpa kehadiran
pangkalan masa luaran (jam dinding), masa simulasi melompat serta-merta daripada satu simulasi
masa ke seterusnya.

Kelakuan
Apabila menggunakan penjadual bukan masa nyata (lalai dalam ns-3), simulator memajukan
masa simulasi ke acara yang dijadualkan seterusnya. Semasa pelaksanaan acara, masa simulasi adalah
beku. Dengan penjadual masa nyata, tingkah laku adalah serupa dari perspektif
model simulasi (iaitu, masa simulasi dibekukan semasa pelaksanaan acara), tetapi antara
kejadian, simulator akan cuba memastikan jam simulasi sejajar dengan mesin
jam.

Apabila acara selesai dilaksanakan, dan penjadual bergerak ke acara seterusnya, the
penjadual membandingkan masa pelaksanaan acara seterusnya dengan jam mesin. Jika seterusnya
acara dijadualkan untuk masa hadapan, simulator tidur sehingga masa nyata itu dicapai
dan kemudian melaksanakan acara seterusnya.

Ia mungkin berlaku bahawa, disebabkan oleh pemprosesan yang wujud dalam pelaksanaan peristiwa simulasi,
bahawa simulator tidak dapat bersaing dengan masa nyata. Dalam kes sedemikian, ia terpulang kepada pengguna
konfigurasi apa yang perlu dilakukan. Terdapat dua ns-3 sifat yang mengawal tingkah laku. The
pertama ialah ns3::RealTimeSimulatorImpl::SynchronizationMod. Dua penyertaan mungkin untuk
atribut ini ialah Usaha Terbaik (lalai) atau HardLimit. Dalam mod "Usaha Terbaik", yang
simulator hanya akan cuba mengejar masa nyata dengan melaksanakan acara sehingga ia mencapai a
titik di mana peristiwa seterusnya adalah pada masa hadapan (masa nyata), atau simulasi tamat. Dalam
Mod BestEffort, maka, adalah mungkin untuk simulasi mengambil lebih banyak masa daripada mod
masa jam dinding. Pilihan lain "HardLimit" akan menyebabkan simulasi dibatalkan jika
ambang toleransi melebihi. Atribut ini ialah ns3::RealTimeSimulatorImpl::HardLimit
dan lalai ialah 0.1 saat.

Mod operasi yang berbeza ialah mod di mana masa simulasi adalah tidak beku semasa acara
perlaksanaan. Mod simulasi masa nyata ini telah dilaksanakan tetapi dialih keluar daripada ns-3 pokok
kerana soalan sama ada ia akan berguna. Jika pengguna berminat dalam masa nyata
simulator yang mana masa simulasi tidak membeku semasa pelaksanaan acara (iaitu, setiap
panggil ke Simulator::Sekarang() mengembalikan masa jam dinding semasa, bukan masa di mana
acara mula dilaksanakan), sila hubungi senarai mel ns-developers.

Penggunaan
Penggunaan simulator masa nyata adalah mudah, dari perspektif skrip.
Pengguna hanya perlu menetapkan atribut SimulatorImplementationType ke Masa Nyata
simulator, seperti berikut:

GlobalValue::Bind ("SimulatorImplementationType",
StringValue ("ns3::RealtimeSimulatorImpl"));

Terdapat skrip dalam examples/realtime/realtime-udp-echo.cc yang mempunyai contoh bagaimana untuk
mengkonfigurasi tingkah laku masa nyata. Cuba:

$ ./waf --run realtime-udp-echo

Sama ada simulator akan berfungsi dalam usaha terbaik atau fesyen dasar had keras ditadbir
oleh atribut yang dijelaskan dalam bahagian sebelumnya.

Pelaksanaan
Pelaksanaan terkandung dalam fail berikut:

· src/core/model/realtime-simulator-impl.{cc,h}

· src/teras/model/penyegerak-jam-dinding.{cc,h}

Untuk mencipta penjadual masa nyata, kepada anggaran pertama anda hanya mahu menyebabkan
masa simulasi melompat untuk menggunakan masa nyata. Kami mencadangkan untuk melakukan ini menggunakan gabungan
tidur- dan sibuk- menunggu. Tidur-tunggu menyebabkan proses panggilan (benang) menghasilkan
pemproses untuk beberapa waktu. Walaupun jumlah masa yang ditentukan ini boleh dilalui
kepada resolusi nanosaat, ia sebenarnya ditukar kepada butiran khusus OS. Dalam
Linux, butirannya dipanggil Jiffy. Biasanya resolusi ini tidak mencukupi untuk
keperluan kita (mengikut urutan sepuluh milisaat), jadi kita bundarkan ke bawah dan tidur untuk beberapa
bilangan Jiffies yang lebih kecil. Proses itu kemudian dibangkitkan selepas bilangan yang ditentukan
Jiffies telah berlalu. Pada masa ini, kita mempunyai sedikit masa untuk menunggu. Kali ini adalah
biasanya lebih kecil daripada masa tidur minimum, jadi kami sibuk-menunggu baki masa
masa. Ini bermakna bahawa benang hanya duduk dalam kitaran penggunaan gelung untuk sehingga
masa yang dikehendaki tiba. Selepas gabungan menunggu tidur dan sibuk, masa nyata berlalu
(dinding) jam harus bersetuju dengan masa simulasi acara seterusnya dan simulasi
teruskan.

Pembantu
Bab-bab di atas memperkenalkan anda kepada pelbagai ns-3 konsep pengaturcaraan seperti pintar
penunjuk untuk pengurusan memori yang dikira rujukan, atribut, ruang nama, panggilan balik, dsb.
Pengguna yang bekerja di API peringkat rendah ini boleh saling berhubung ns-3 objek dengan butiran halus.
Walau bagaimanapun, program simulasi yang ditulis sepenuhnya menggunakan API peringkat rendah adalah agak panjang
dan membosankan untuk membuat kod. Atas sebab ini, apa yang dipanggil "API pembantu" berasingan telah ditindih
pada inti ns-3 API. Jika anda telah membaca ns-3 tutorial, anda akan sudah biasa
dengan API pembantu, kerana ia adalah API yang biasanya diperkenalkan kepada pengguna baharu dahulu.
Dalam bab ini, kami memperkenalkan falsafah reka bentuk API pembantu dan membezakannya dengan
API peringkat rendah. Jika anda menjadi pengguna berat ns-3, anda mungkin akan bergerak ke sana ke mari
antara API ini walaupun dalam program yang sama.

API pembantu mempunyai beberapa matlamat:

1. selebihnya src / tidak mempunyai pergantungan pada API pembantu; apa sahaja yang boleh dilakukan dengan
API pembantu boleh dikodkan juga pada API peringkat rendah

2. Bekas: Selalunya simulasi perlu melakukan beberapa tindakan yang sama kepada kumpulan
daripada objek. API pembantu menggunakan banyak bekas objek yang serupa dengannya
operasi yang serupa atau serupa boleh dilakukan.

3. API pembantu bukan generik; ia tidak berusaha untuk memaksimumkan penggunaan semula kod. Jadi,
binaan pengaturcaraan seperti polimorfisme dan templat yang mencapai penggunaan semula kod ialah
tidak berleluasa. Sebagai contoh, terdapat pembantu CsmaNetDevice yang berasingan dan
PointToPointNetDevice pembantu tetapi mereka tidak berasal dari pangkalan NetDevice biasa
kelas.

4. API pembantu biasanya berfungsi dengan objek yang diperuntukkan tindanan (vs. diperuntukkan timbunan). Untuk
beberapa program, ns-3 pengguna mungkin tidak perlu risau tentang sebarang Cipta Objek peringkat rendah atau
Pengendalian Ptr; mereka boleh melakukan dengan bekas objek dan pembantu yang diperuntukkan tindanan
yang beroperasi ke atas mereka.

API pembantu adalah benar-benar tentang pembuatan ns-3 program lebih mudah untuk menulis dan membaca, tanpa
menghilangkan kuasa antara muka peringkat rendah. Selebihnya bab ini menyediakan beberapa
contoh konvensyen pengaturcaraan API pembantu.

Membuat Plot menggunakan yang Gnplot Kelas
Terdapat 2 kaedah biasa untuk membuat plot menggunakan ns-3 dan gnplot (-
http://www.gnuplot.info):

1. Buat fail kawalan gnuplot menggunakan ns-3kelas Gnuplot.

2. Cipta fail data gnuplot menggunakan nilai yang dijana oleh ns-3.

Bahagian ini adalah mengenai kaedah 1, iaitu tentang cara membuat plot menggunakan ns-3Gnuplot
kelas. Jika anda berminat dengan kaedah 2, lihat subseksyen "Contoh Sebenar" di bawah
Bahagian "Menjejak" dalam ns-3 tutorial.

mewujudkan Plot Menggunakan yang Gnplot Kelas
Langkah-langkah berikut mesti diambil untuk membuat plot menggunakan ns-3kelas Gnuplot:

1. Ubah suai kod anda supaya menggunakan kelas Gnuplot dan fungsinya.

2. Jalankan kod anda supaya ia mencipta fail kawalan gnuplot.

3. Panggil gnuplot dengan nama fail kawalan gnuplot.

4. Lihat fail grafik yang dihasilkan dalam pemapar grafik kegemaran anda.

Lihat kod daripada plot contoh yang dibincangkan di bawah untuk butiran mengenai langkah 1.

An Contoh Program Bahawa kegunaan yang Gnplot Kelas
Contoh program yang menggunakan ns-3Kelas Gnuplot boleh didapati di sini:

src/stats/example/gnuplot-example.cc

Untuk menjalankan contoh ini, lakukan perkara berikut:

$ ./waf shell
$ cd bina/debug/src/stats/contoh
$ ./gnuplot-example

Ini harus menghasilkan fail kawalan gnuplot berikut dalam direktori di mana contoh
terletak:

plot-2d.plt
plot-2d-with-error-bars.plt
plot-3d.plt

Untuk memproses fail kawalan gnuplot ini, lakukan perkara berikut:

$ gnuplot plot-2d.plt
$ gnuplot plot-2d-with-error-bars.plt
$ gnuplot plot-3d.plt

Ini harus menghasilkan fail grafik berikut dalam direktori di mana contoh itu
terletak:

plot-2d.png
plot-2d-with-error-bars.png
plot-3d.png

Anda boleh melihat fail grafik ini dalam pemapar grafik kegemaran anda. Jika anda mempunyai gimp
dipasang pada mesin anda, sebagai contoh, anda boleh melakukan ini:

$ gimp plot-2d.png
$ gimp plot-2d-with-error-bars.png
$ gimp plot-3d.png

An Contoh 2-Dimensi Plot
Plot 2 Dimensi berikut
[gambar]

telah dibuat menggunakan kod berikut daripada gnuplot-example.cc:

menggunakan ruang nama std;

string fileNameWithNoExtension = "plot-2d";
string graphicsFileName = fileNameWithNoExtension + ".png";
plot rentetanFileName = fileNameWithNoExtension + ".plt";
string plotTitle = "Plot 2-D";
string dataTitle = "Data 2-D";

// Instantiate plot dan tetapkan tajuknya.
Plot Gnuplot (graphicsFileName);
plot.SetTitle (plotTitle);

// Buat fail grafik, yang akan dibuat oleh fail plot apabila ia
// digunakan dengan Gnuplot, menjadi fail PNG.
plot.SetTerminal ("png");

// Tetapkan label untuk setiap paksi.
plot.SetLegend ("Nilai X", "Nilai Y");

// Tetapkan julat untuk paksi x.
plot.AppendExtra ("tetapkan julat x [-6:+6]");

// Instantite set data, tetapkan tajuknya dan jadikan mata
// diplot bersama dengan garis penghubung.
Set data Gnuplot2dDataset;
dataset.SetTitle (dataTitle);
dataset.SetStyle (Gnuplot2dDataset::LINES_POINTS);

ganda x;
dua y;

// Cipta set data 2-D.
untuk (x = -5.0; x <= +5.0; x += 1.0)
{
// Kira lengkung 2-D
//
/ / 2
// y = x .
//
y = x * x;

// Tambah titik ini.
dataset.Tambah (x, y);
}

// Tambahkan set data pada plot.
plot.AddDataset (set data);

// Buka fail plot.
ofstream plotFile (plotFileName.c_str());

// Tulis fail plot.
plot.GenerateOutput (plotFile);

// Tutup fail plot.
plotFile.close ();

An Contoh 2-Dimensi Plot bersama ralat Bar
Plot 2 Dimensi berikut dengan bar ralat dalam arah x dan y
[gambar]

telah dibuat menggunakan kod berikut daripada gnuplot-example.cc:

menggunakan ruang nama std;

string fileNameWithNoExtension = "plot-2d-with-error-bars";
string graphicsFileName = fileNameWithNoExtension + ".png";
plot rentetanFileName = fileNameWithNoExtension + ".plt";
string plotTitle = "Plot 2-D Dengan Bar Ralat";
string dataTitle = "Data 2-D Dengan Bar Ralat";

// Instantiate plot dan tetapkan tajuknya.
Plot Gnuplot (graphicsFileName);
plot.SetTitle (plotTitle);

// Buat fail grafik, yang akan dibuat oleh fail plot apabila ia
// digunakan dengan Gnuplot, menjadi fail PNG.
plot.SetTerminal ("png");

// Tetapkan label untuk setiap paksi.
plot.SetLegend ("Nilai X", "Nilai Y");

// Tetapkan julat untuk paksi x.
plot.AppendExtra ("tetapkan julat x [-6:+6]");

// Instantite set data, tetapkan tajuknya dan jadikan mata
// diplot tanpa garis penghubung.
Set data Gnuplot2dDataset;
dataset.SetTitle (dataTitle);
dataset.SetStyle (Gnuplot2dDataset::POINTS);

// Jadikan set data mempunyai bar ralat dalam kedua-dua arah x dan y.
dataset.SetErrorBars (Gnuplot2dDataset::XY);

ganda x;
double xErrorDelta;
dua y;
yErrorDelta berganda;

// Cipta set data 2-D.
untuk (x = -5.0; x <= +5.0; x += 1.0)
{
// Kira lengkung 2-D
//
/ / 2
// y = x .
//
y = x * x;

// Jadikan ketidakpastian dalam arah x menjadi malar dan buat
// ketidakpastian dalam arah y ialah pecahan malar bagi
// nilai y.
xErrorDelta = 0.25;
yErrorDelta = 0.1 * y;

// Tambahkan titik ini dengan ketidakpastian dalam kedua-dua x dan y
// arah.
dataset.Tambah (x, y, xErrorDelta, yErrorDelta);
}

// Tambahkan set data pada plot.
plot.AddDataset (set data);

// Buka fail plot.
ofstream plotFile (plotFileName.c_str());

// Tulis fail plot.
plot.GenerateOutput (plotFile);

// Tutup fail plot.
plotFile.close ();

An Contoh 3-Dimensi Plot
Plot 3 Dimensi berikut
[gambar]

telah dibuat menggunakan kod berikut daripada gnuplot-example.cc:

menggunakan ruang nama std;

string fileNameWithNoExtension = "plot-3d";
string graphicsFileName = fileNameWithNoExtension + ".png";
plot rentetanFileName = fileNameWithNoExtension + ".plt";
string plotTitle = "Plot 3-D";
string dataTitle = "Data 3-D";

// Instantiate plot dan tetapkan tajuknya.
Plot Gnuplot (graphicsFileName);
plot.SetTitle (plotTitle);

// Buat fail grafik, yang akan dibuat oleh fail plot apabila ia
// digunakan dengan Gnuplot, menjadi fail PNG.
plot.SetTerminal ("png");

// Putar plot 30 darjah mengelilingi paksi x dan kemudian putarkan
// plot 120 darjah di sekeliling paksi z baharu.
plot.AppendExtra ("tetapkan paparan 30, 120, 1.0, 1.0");

// Jadikan sifar untuk paksi-z berada dalam satah paksi-x dan paksi-y.
plot.AppendExtra ("set ticslevel 0");

// Tetapkan label untuk setiap paksi.
plot.AppendExtra ("tetapkan xlabel 'Nilai X'");
plot.AppendExtra ("tetapkan ylabel 'Nilai Y'");
plot.AppendExtra ("tetapkan zlabel 'Nilai Z'");

// Tetapkan julat untuk paksi x dan y.
plot.AppendExtra ("tetapkan julat x [-5:+5]");
plot.AppendExtra ("set yrange [-5:+5]");

// Instantite set data, tetapkan tajuknya dan jadikan mata
// disambungkan dengan garisan.
Set data Gnuplot3dDataset;
dataset.SetTitle (dataTitle);
dataset.SetStyle ("dengan baris");

ganda x;
dua y;
z berganda;

// Cipta set data 3-D.
untuk (x = -5.0; x <= +5.0; x += 1.0)
{
untuk (y = -5.0; y <= +5.0; y += 1.0)
{
// Kira permukaan 3-D
//
// 2 2
// z = x * y .
//
z = x * x * y * y;

// Tambah titik ini.
dataset.Tambah (x, y, z);
}

// Baris kosong diperlukan pada akhir setiap data nilai x
// mata untuk grid permukaan 3-D berfungsi.
dataset.AddEmptyLine ();
}

// Tambahkan set data pada plot.
plot.AddDataset (set data);

// Buka fail plot.
ofstream plotFile (plotFileName.c_str());

// Tulis fail plot.
plot.GenerateOutput (plotFile);

// Tutup fail plot.
plotFile.close ();

Menggunakan Python kepada Main ns-3
Pengikatan Python membenarkan kod C++ masuk ns-3 untuk dipanggil daripada Python.

Bab ini menunjukkan kepada anda cara mencipta skrip Python yang boleh dijalankan ns-3 dan juga
proses mencipta pengikatan Python untuk C++ ns-3 modul.

Pengenalan
Matlamat pengikatan Python untuk ns-3 adalah dua kali ganda:

1. Benarkan pengaturcara menulis skrip simulasi lengkap dalam Python (‐
http://www.python.org);

2. Prototaip model baharu (cth protokol penghalaan).

Buat masa ini, tumpuan utama pengikatan adalah matlamat pertama, tetapi yang kedua
matlamat akhirnya akan disokong juga. Ikatan Python untuk ns-3 sedang dibangunkan
menggunakan alat baharu yang dipanggil PyBindGen (http://code.google.com/p/pybindgen).

An Contoh Python skrip Bahawa Larian ns-3
Berikut ialah beberapa contoh kod yang ditulis dalam Python dan berjalan ns-3, yang tertulis
dalam C++. Contoh Python ini boleh didapati dalam contoh/tutorial/first.py:

import ns.applications
import ns.core
import ns.internet
import ns.network
import ns.point_to_point

ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO)
ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO)

nod = ns.network.NodeContainer()
nod.Buat(2)

pointToPoint = ns.point_to_point.PointToPointHelper()
pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps"))
pointToPoint.SetChannelAttribute("Delay", ns.core.StringValue("2ms"))

peranti = pointToPoint.Install(nod)

timbunan = ns.internet.InternetStackHelper()
stack.Install(nod)

alamat = ns.internet.Ipv4AddressHelper()
address.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0"))

antara muka = ​​alamat.Serahkan (peranti);

echoServer = ns.applications.UdpEchoServerHelper(9)

serverApps = echoServer.Install(nod.Dapatkan(1))
serverApps.Start(ns.core.Seconds(1.0))
serverApps.Stop(ns.core.Seconds(10.0))

echoClient = ns.applications.UdpEchoClientHelper(antara muka.GetAddress(1), 9)
echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(1))
echoClient.SetAttribute("Selang", ns.core.TimeValue(ns.core.Detik (1.0)))
echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(1024))

clientApps = echoClient.Install(nod.Dapatkan(0))
clientApps.Start(ns.core.Seconds(2.0))
clientApps.Stop(ns.core.Seconds(10.0))

ns.core.Simulator.Run()
ns.core.Simulator.Destroy()

Berlari Python skrip
waf mengandungi beberapa pilihan yang secara automatik mengemas kini laluan python untuk mencari ns3
modul. Untuk menjalankan program contoh, terdapat dua cara untuk menggunakan waf untuk mengurus ini. satu
adalah untuk menjalankan cangkang waf; cth:

$ ./waf --shell
$ contoh python/wireless/mixed-wireless.py

dan yang lain adalah menggunakan pilihan --pyrun untuk waf:

$ ./waf --pyrun examples/wireless/mixed-wireless.py

Untuk menjalankan skrip python di bawah penyahpepijat C:

$ ./waf --shell
$ gdb --args python examples/wireless/mixed-wireless.py

Untuk menjalankan skrip Python anda sendiri yang memanggil ns-3 dan yang mempunyai jalan ini,
/path/to/your/example/my-script.py, lakukan perkara berikut:

$ ./waf --shell
$ python /path/to/your/example/my-script.py

Kaveat
Ikatan Python untuk ns-3 sedang dalam proses, dan beberapa batasan diketahui oleh
pemaju. Beberapa had ini (bukan semua) disenaraikan di sini.

Tidak lengkap Dari Masa ke Semasa
Pertama sekali, perlu diingat bahawa bukan 100% API disokong dalam Python. Sesetengah
sebabnya ialah:

1. sesetengah API melibatkan penunjuk, yang memerlukan pengetahuan tentang jenis memori
semantik lulus (siapa yang memiliki ingatan apa). Pengetahuan sedemikian bukan sebahagian daripada fungsi
tandatangan, dan sama ada didokumenkan atau kadangkala tidak didokumenkan. Anotasi ialah
diperlukan untuk mengikat fungsi tersebut;

2. Kadangkala jenis data asas yang luar biasa atau konstruk C++ digunakan yang belum lagi digunakan
disokong oleh PyBindGen;

3. GCC-XML tidak melaporkan kelas berasaskan templat melainkan ia dibuat seketika.

Kebanyakan API yang hilang boleh dibungkus, diberi masa, kesabaran dan kepakaran yang mencukupi, dan
berkemungkinan akan dibalut jika laporan pepijat diserahkan. Walau bagaimanapun, jangan failkan laporan pepijat
mengatakan "ikatan tidak lengkap", kerana kami tidak mempunyai tenaga kerja untuk menyiapkan 100% daripada
pengikatan.

Penukaran Pembina
Penukaran pembina belum disokong sepenuhnya oleh PyBindGen, dan mereka sentiasa bertindak sebagai
pembina eksplisit apabila menterjemah API ke dalam Python. Sebagai contoh, dalam C++ anda boleh lakukan
ini:

Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase ("192.168.0.0", "255.255.255.0");
ipAddrs.Assign (backboneDevices);

Dalam Python, buat masa ini anda perlu lakukan:

ipAddrs = ns3.Ipv4AddressHelper()
ipAddrs.SetBase(ns3.Ipv4Address("192.168.0.0"), ns3.Ipv4Mask("255.255.255.0"))
ipAddrs.Assign(backboneDevices)

Talian Perintah
CommandLine::AddValue() berfungsi secara berbeza dalam Python berbanding dalam ns-3. Dalam Python, the
parameter pertama ialah rentetan yang mewakili nama pilihan baris arahan. Apabila pilihan
ditetapkan, atribut dengan nama yang sama dengan nama pilihan ditetapkan pada Barisan Perintah()
objek. Contoh:

NUM_NODES_SIDE_DEFAULT = 3

cmd = ns3.CommandLine()

cmd.NumNodesSide = Tiada
cmd.AddValue("NumNodesSide", "Nod sisi grid nod (jumlah bilangan nod akan menjadi nombor ini kuasa dua)")

cmd.Parse(argv)

[...]

jika cmd.NumNodesSide ialah Tiada:
num_nodes_side = NUM_NODES_SIDE_DEFAULT
lain:
num_nodes_side = int(cmd.NumNodesSide)

Penjejakan
Pengesanan berasaskan panggilan balik belum lagi disokong dengan betul untuk Python, seperti baharu ns-3 API perlu
disediakan untuk ini disokong.

Penulisan fail Pcap disokong melalui API biasa.

Pengesanan Ascii disokong sejak itu ns-3.4 melalui C++ API biasa yang diterjemahkan kepada Python.
Walau bagaimanapun, pengesanan ascii memerlukan penciptaan objek ostream untuk masuk ke dalam ascii
kaedah mengesan. Dalam Python, C++ std::ofstream telah dibalut secara minimum untuk membenarkan
ini. Sebagai contoh:

ascii = ns3.ofstream("wifi-ap.tr") # buat fail
ns3.YansWifiPhyHelper.EnableAsciiAll(ascii)
ns3.Simulator.Run()
ns3.Simulator.Destroy()
ascii.close() # tutup fail

Terdapat satu kaveat: anda tidak boleh membenarkan objek fail menjadi sampah dikumpul semasa ns-3
masih menggunakannya. Ini bermakna pembolehubah 'ascii' di atas tidak boleh dibenarkan pergi
di luar skop atau program akan ranap.

Cygwin had
Pengikatan Python tidak berfungsi pada Cygwin. Ini disebabkan oleh pepijat gccxml.

Anda mungkin terlepas daripadanya dengan mengimbas semula definisi API dari dalam cygwin
persekitaran (./waf --python-scan). Walau bagaimanapun penyelesaian yang paling mungkin mungkin perlu
sama ada kita melumpuhkan pengikatan python dalam CygWin.

Jika anda benar-benar mengambil berat tentang pengikatan Python pada Windows, cuba bina dengan mingw dan asli
python sebaliknya. Atau sebaliknya, untuk membina tanpa pengikatan ular sawa, nyahdayakan pengikatan ular sawa dalam
peringkat konfigurasi:

$ ./waf configure --disable-python

Kerja bersama Python Pengikatan
Pada masa ini terdapat dua jenis pengikatan Python ns-3:

1. Ikatan monolitik mengandungi definisi API untuk semua modul dan boleh didapati di
satu direktori, binding/python.

2. Pengikatan modular mengandungi definisi API untuk satu modul dan boleh didapati dalam setiap modul
modul pengikatan direktori.

Python Pengikatan Workflow
Proses di mana pengikatan Python dikendalikan adalah seperti berikut:

1. Secara berkala pembangun menggunakan GCC-XML (http://www.gccxml.org) pengimbasan API berasaskan
skrip, yang menyimpan definisi API yang diimbas sebagai bindings/python/ns3_module_*.py fail
atau sebagai fail Python dalam setiap modul' pengikatan direktori. Fail-fail ini disimpan di bawah
kawalan versi dalam utama ns-3 repositori;

2. Pembangun lain mengklon repositori dan menggunakan definisi API yang telah diimbas;

3. Apabila mengkonfigurasi ns-3, pybindgen akan dimuat turun secara automatik jika belum
dipasang. Dikeluarkan ns-3 tarballs akan menghantar salinan pybindgen.

Jika ada masalah dengan menyusun pengikatan Python dan anda hanya mahu mengabaikannya
dan teruskan dengan C++, anda boleh melumpuhkan Python dengan:

$ ./waf --disable-python

arahan khususnya pengendalian Baru Fail or Berubah API
Jadi anda telah mengubah sedia ada ns-3 API dan pengikatan Python tidak lagi disusun? buat
tidak putus asa, anda boleh mengimbas semula pengikatan untuk mencipta pengikatan baharu yang mencerminkan perubahan
kepada ns-3 API.

Bergantung pada jika anda menggunakan pengikatan monolitik atau modular, lihat perbincangan di bawah untuk
ketahui cara mengimbas semula pengikatan Python anda.

Monolitik Python Pengikatan
Mengimbas yang Monolitik Python Pengikatan
Untuk mengimbas pengikatan Python monolitik lakukan perkara berikut:

$ ./waf --python-scan

pertubuhan of yang Monolitik Python Pengikatan
Takrifan API Python monolitik disusun seperti berikut. Untuk setiap ns-3 modul
, fail bindings/python/ns3_module_ .py menerangkan APInya. Setiap daripada itu
Fail mempunyai 3 fungsi peringkat atas:

1. def daftar_jenis(modul)(): fungsi ini mengurus pendaftaran jenis baharu (cth
Kelas C++, enum) yang ditakrifkan dalam modul;

2. def kaedah_daftar(modul)(): fungsi ini memanggil, untuk setiap kelas , lain
fungsi daftar_kaedah_Ns3 (modul). Fungsi-fungsi terakhir ini menambah kaedah
definisi untuk setiap kelas;

3. def daftar_fungsi(modul)(): fungsi ini mendaftar ns-3 fungsi yang dimiliki
modul itu.

Modular Python Pengikatan
Pengenalan
Sejak ns 3.11, pengikatan modular sedang ditambah, selari dengan monolitik lama
pengikatan.

Ikatan python baharu dijana ke ruang nama 'ns', bukannya 'ns3' untuk ruang nama lama
pengikatan. Contoh:

daripada ns.network import Node
n1 = Nod()

Dengan pengikatan Python modular:

1. Terdapat satu modul sambungan Python yang berasingan untuk setiap satu ns-3 modul;

2. Mengimbas takrifan API (apidefs) dilakukan berdasarkan modul per ns-;

3. Setiap fail apidefs modul disimpan dalam subdirektori 'binding' modul
direktori;

Mengimbas yang Modular Python Pengikatan
Untuk mengimbas pengikatan Python modular untuk modul teras, sebagai contoh, lakukan perkara berikut:

$ ./waf --apiscan=core

Untuk mengimbas pengikatan Python modular untuk semua modul, lakukan perkara berikut:

$ ./waf --apiscan=semua

mewujudkan a Baru Modul
Jika anda menambah modul baharu, pengikatan Python akan terus dikompil tetapi tidak
meliputi modul baharu.

Untuk merangkumi modul baharu, anda perlu membuat a bindings/python/ns3_module_ .py fail,
serupa dengan apa yang diterangkan dalam bahagian sebelumnya, dan daftarkannya dalam pembolehubah
LOCAL_MODULES() in bindings/python/ns3modulegen.py

Menambah Modular Pengikatan Untuk A Sedia ada Modul
Untuk menambah sokongan untuk pengikatan modular kepada sedia ada ns-3 modul, hanya tambah yang berikut
baris ke fungsi wscript build()nya:

bld.ns3_python_bindings()

pertubuhan of yang Modular Python Pengikatan
. src/ /ikatan direktori mungkin mengandungi fail berikut, sebahagian daripadanya
pilihan:

· callbacks_list.py: ini adalah fail yang diimbas, JANGAN SENTUH. Mengandungi senarai
Contoh templat panggil balik<...> ditemui dalam pengepala yang diimbas;

· modulegen__gcc_LP64.py: ini adalah fail yang diimbas, JANGAN SENTUH. Takrifan API yang diimbas
untuk GCC, seni bina LP64 (64-bit)

· modulegen__gcc_ILP32.py: ini adalah fail yang diimbas, JANGAN SENTUH. Takrifan API yang diimbas
untuk GCC, seni bina ILP32 (32-bit)

· modulegen_customizations.py: anda boleh menambah fail ini secara pilihan untuk menyesuaikan
penjanaan kod pybindgen

· kepala imbasan.h: anda boleh menambah fail ini secara pilihan untuk menyesuaikan fail pengepala yang diimbas
untuk modul. Pada asasnya fail ini diimbas bukannya ns3/ -modul.h.
Biasanya, pernyataan pertama ialah #include "ns3/ -module.h", serta beberapa yang lain
bahan untuk memaksa instantiasi templat;

· module_helpers.cc: anda boleh menambah fail tambahan, seperti ini, untuk dipautkan ke python
modul sambungan, tetapi mereka perlu didaftarkan dalam wscript. Lihat pada
src/core/wscript untuk contoh cara berbuat demikian;

· .py: jika fail ini wujud, ia menjadi modul python "frontend" untuk ns3
modul dan modul sambungan (.so file) menjadi _ .jadi bukannya .so.
The Fail .py perlu mengimport semua simbol daripada modul _ (ini lagi
rumit daripada kedengarannya, lihat src/core/bindings/core.py sebagai contoh), dan kemudian boleh menambah
beberapa definisi python tulen tambahan.

Lagi Maklumat khususnya Pemaju
Jika anda seorang pembangun dan memerlukan maklumat lanjut tentang ns-3Pengikatan Python, sila lihat
Python Pengikatan wiki halaman.

Ujian
Pengenalan
Dokumen ini berkaitan dengan ujian dan pengesahan ns-3 perisian.

Dokumen ini menyediakan

· latar belakang tentang istilah dan ujian perisian (Bab 2);

· penerangan tentang rangka kerja ujian ns-3 (Bab 3);

· panduan kepada pembangun model atau penyumbang model baharu untuk cara menulis ujian (Bab
4);

Secara ringkasnya, tiga bab pertama harus dibaca oleh pembangun ns dan penyumbang yang
perlu memahami cara menyumbang kod ujian dan program yang disahkan, dan selebihnya
dokumen menyediakan ruang untuk orang ramai melaporkan tentang aspek model yang dipilih
telah disahkan.

Latar Belakang
ini bab mungkin be dilangkau by pembaca biasa bersama yang asas of perisian ujian.

Menulis perisian tanpa kecacatan adalah cadangan yang sukar. Terdapat banyak dimensi untuk
masalah dan terdapat banyak kekeliruan mengenai apa yang dimaksudkan dengan istilah yang berbeza dalam
konteks yang berbeza. Kami mendapati ia berbaloi untuk meluangkan sedikit masa menyemak semula
subjek dan mentakrifkan beberapa istilah.

Ujian perisian boleh ditakrifkan secara longgar sebagai proses melaksanakan program dengan
niat mencari kesilapan. Apabila seseorang memasuki perbincangan mengenai ujian perisian, ia
dengan cepat menjadi jelas bahawa terdapat banyak set minda yang berbeza yang boleh digunakan oleh seseorang
mendekati subjek.

Sebagai contoh, seseorang boleh memecahkan proses ke dalam kategori berfungsi yang luas seperti
''ujian ketepatan,'' ''ujian prestasi,'' ''ujian kekukuhan'' dan ''keselamatan
ujian.'' Satu lagi cara untuk melihat masalah adalah dengan kitaran hayat: '' ujian keperluan,''
''ujian reka bentuk,'' ''ujian penerimaan,'' dan ''ujian penyelenggaraan.'' Satu lagi pandangan
adalah mengikut skop sistem yang diuji. Dalam kes ini seseorang boleh bercakap tentang ''ujian unit,''
''ujian komponen,'' ''ujian integrasi,'' dan ''ujian sistem.'' Istilah ini ialah
juga tidak diseragamkan dalam apa jua cara, dan sebagainya '' ujian penyelenggaraan '' dan '' regresi
ujian'' boleh didengar secara bergantian. Selain itu, istilah ini sering disalahgunakan.

Terdapat juga beberapa pendekatan falsafah yang berbeza untuk ujian perisian. Untuk
contoh, sesetengah organisasi menyokong program ujian penulisan sebelum benar-benar melaksanakan
perisian yang dikehendaki, menghasilkan ''pembangunan yang dipacu ujian.'' Sesetengah organisasi menyokong
menguji dari perspektif pelanggan secepat mungkin, berikutan selari dengan
proses pembangunan tangkas: ''uji awal dan uji kerap.'' Ini kadangkala dipanggil
''pengujian tangkas.'' Nampaknya terdapat sekurang-kurangnya satu pendekatan untuk menguji untuk setiap
metodologi pembangunan.

. ns-3 projek bukan dalam perniagaan menyokong mana-mana satu daripada proses ini, tetapi
projek secara keseluruhan mempunyai keperluan yang membantu memaklumkan proses ujian.

Seperti semua produk perisian utama, ns-3 mempunyai beberapa kualiti yang mesti ada
produk untuk berjaya. Dari perspektif ujian, beberapa kualiti ini mesti ada
ditujukan ialah itu ns-3 mestilah ''betul,'' ''teguh,'' ''berprestasi'' dan
''boleh dikekalkan.'' Sebaiknya ada metrik untuk setiap dimensi ini
diperiksa oleh ujian untuk mengenal pasti apabila produk gagal memenuhi jangkaannya /
keperluan.

Ketepatan
Tujuan penting ujian adalah untuk menentukan bahawa sesuatu perisian berfungsi
''betul.'' Untuk ns-3 ini bermakna jika kita mensimulasikan sesuatu, simulasi itu sepatutnya
dengan setia mewakili beberapa entiti atau proses fizikal kepada ketepatan yang ditentukan dan
ketepatan.

Ternyata terdapat dua perspektif dari mana seseorang boleh melihat ketepatan.
Mengesahkan bahawa model tertentu dilaksanakan mengikut spesifikasinya adalah
secara umum dipanggil pengesahan. Proses memutuskan bahawa model itu betul untuk
penggunaan yang dimaksudkan secara umum dipanggil pengesahan.

Pengesahan and Pengesahan
Model komputer ialah perwakilan matematik atau logik sesuatu. Ia boleh
mewakili kenderaan, gajah (lihat David Harel bercakap mengenai pemodelan an gajah at
Alat SIMUT 2009, atau kad rangkaian. Model juga boleh mewakili proses seperti global
pemanasan, aliran trafik lebuh raya atau spesifikasi protokol rangkaian. Model boleh
perwakilan yang benar-benar setia bagi spesifikasi proses logik, tetapi mereka
semestinya tidak dapat mensimulasikan sepenuhnya objek atau proses fizikal. Dalam kebanyakan kes, a
bilangan penyederhanaan dibuat kepada model untuk membuat simulasi secara pengiraan
boleh dikendalikan.

Setiap model mempunyai a sasaran sistem bahawa ia cuba mensimulasikan. Langkah pertama masuk
mewujudkan model simulasi adalah untuk mengenal pasti sistem sasaran ini dan tahap perincian dan
ketepatan bahawa simulasi itu ingin dihasilkan semula. Dalam kes proses logik,
sistem sasaran boleh dikenal pasti sebagai ''TCP seperti yang ditakrifkan oleh RFC 793.'' Dalam kes ini, ia
mungkin akan diingini untuk mencipta model yang benar-benar dan setia menghasilkan semula RFC
793. Dalam kes proses fizikal ini tidak akan dapat dilakukan. Jika, sebagai contoh, anda
ingin mensimulasikan kad rangkaian wayarles, anda boleh menentukan yang anda perlukan, ''an
pelaksanaan tahap MAC yang tepat bagi spesifikasi 802.11 dan [...] yang tidak begitu perlahan
Model peringkat PHY bagi spesifikasi 802.11a.''

Setelah ini dilakukan, seseorang boleh membangunkan model abstrak sistem sasaran. Ini adalah
lazimnya merupakan latihan dalam menguruskan pertukaran antara kerumitan, keperluan sumber
dan ketepatan. Proses membangunkan model abstrak telah dipanggil model
kelayakan dalam kesusasteraan. Dalam kes protokol TCP, proses ini menghasilkan a
reka bentuk untuk koleksi objek, interaksi dan tingkah laku yang akan dilaksanakan sepenuhnya
RFC 793 in ns-3. Dalam kes kad wayarles, proses ini menghasilkan beberapa
tukar ganti untuk membolehkan lapisan fizikal disimulasikan dan reka bentuk peranti rangkaian
dan saluran untuk ns-3, bersama-sama dengan objek, interaksi dan tingkah laku yang diingini.

Model abstrak ini kemudiannya dikembangkan menjadi sebuah ns-3 model yang melaksanakan abstrak
model sebagai program komputer. Proses mendapatkan pelaksanaan untuk bersetuju dengan
model abstrak dipanggil model pengesahan dalam kesusasteraan.

Proses setakat ini adalah gelung terbuka. Apa yang tinggal ialah membuat penentuan bahawa ns-3 yang diberikan
model mempunyai beberapa kaitan dengan beberapa realiti -- bahawa model adalah perwakilan yang tepat
sistem sebenar, sama ada proses logik atau entiti fizikal.

Jika seseorang akan menggunakan model simulasi untuk mencuba dan meramalkan bagaimana sesetengah sistem sebenar berlaku
untuk berkelakuan, mesti ada sebab untuk mempercayai keputusan anda -- iaitu, bolehkah seseorang mempercayainya
inferens yang dibuat daripada model diterjemahkan kepada ramalan yang betul untuk sistem sebenar.
Proses mendapatkan tingkah laku model ns-3 untuk bersetuju dengan sistem sasaran yang dikehendaki
tingkah laku seperti yang ditakrifkan oleh proses kelayakan model dipanggil model pengesahan dalam
sastera. Dalam kes pelaksanaan TCP, anda mungkin ingin membandingkan kelakuan bagi
model TCP ns-3 anda kepada beberapa pelaksanaan rujukan untuk mengesahkan model anda. Dalam
kes simulasi lapisan fizikal tanpa wayar, anda mungkin ingin membandingkan kelakuan bagi
model anda kepada perkakasan sebenar dalam tetapan terkawal,

. ns-3 persekitaran ujian menyediakan alatan untuk membolehkan kedua-dua pengesahan model dan
menguji, dan menggalakkan penerbitan keputusan pengesahan.

keteguhan
Kekukuhan ialah kualiti yang mampu menahan tekanan, atau perubahan dalam persekitaran,
input atau pengiraan, dsb. Sistem atau reka bentuk adalah ''teguh'' jika ia boleh menangani sedemikian
perubahan dengan kehilangan fungsi yang minimum.

Ujian jenis ini biasanya dilakukan dengan fokus tertentu. Sebagai contoh, sistem sebagai
keseluruhan boleh dijalankan pada banyak konfigurasi sistem yang berbeza untuk menunjukkan bahawa ia boleh
melakukan dengan betul dalam sejumlah besar persekitaran.

Sistem ini juga boleh ditekankan dengan beroperasi hampir atau melebihi kapasiti dengan menjana
atau meniru keletihan sumber pelbagai jenis. Genre ujian ini dipanggil
''ujian tekanan.''

Sistem dan komponennya mungkin terdedah kepada apa yang dipanggil ''ujian bersih'' yang menunjukkan
hasil yang positif -- iaitu sistem beroperasi dengan betul sebagai tindak balas kepada yang besar
variasi konfigurasi yang dijangkakan.

Sistem dan komponennya juga mungkin terdedah kepada ''ujian kotor'' yang memberikan input
di luar julat yang dijangkakan. Sebagai contoh, jika modul menjangkakan rentetan penamatan sifar
perwakilan integer, ujian kotor mungkin memberikan rentetan rawak yang tidak ditamatkan
aksara untuk mengesahkan bahawa sistem tidak ranap akibat daripada input yang tidak dijangka ini.
Malangnya, mengesan input "kotor" sedemikian dan mengambil langkah pencegahan untuk memastikan
sistem tidak gagal secara besar-besaran boleh memerlukan sejumlah besar overhed pembangunan.
Untuk mengurangkan masa pembangunan, keputusan telah diambil awal dalam projek untuk
meminimumkan jumlah pengesahan parameter dan pengendalian ralat dalam ns-3 asas kod. Untuk
sebab ini, kami tidak menghabiskan banyak masa untuk ujian kotor -- ia hanya akan mendedahkan
hasil keputusan reka bentuk yang kami tahu kami ambil.

Kami mahu menunjukkannya ns-3 perisian berfungsi merentasi beberapa set syarat. Kami
pinjam beberapa definisi untuk mengecilkan ini sedikit. The domain of kebolehlaksanaan is
satu set syarat yang ditetapkan yang modelnya telah diuji, dibandingkan dengannya
realiti setakat yang mungkin, dan dinilai sesuai untuk digunakan. The pelbagai of ketepatan merupakan
persetujuan antara model berkomputer dan realiti dalam domain kebolehgunaan.

. ns-3 persekitaran ujian menyediakan alatan untuk membolehkan menyediakan dan menjalankan ujian
persekitaran melalui berbilang sistem (buildbot) dan menyediakan kelas untuk menggalakkan kebersihan
ujian untuk mengesahkan operasi sistem ke atas 'domain kebolehgunaan' yang dijangkakan
dan ''julat ketepatan.''

Pelakon
Okay, ''performant'' bukan perkataan Inggeris sebenar. Walau bagaimanapun, ia adalah neologisme yang sangat ringkas
yang agak sering digunakan untuk menggambarkan apa yang kita mahu ns-3 menjadi: berkuasa dan cukup pantas untuk
selesaikan kerja.

Ini benar-benar mengenai subjek luas ujian prestasi perisian. Salah satu kunci
perkara yang dilakukan adalah untuk membandingkan dua sistem untuk mencari yang berprestasi lebih baik (lih
tanda aras). Ini digunakan untuk menunjukkan bahawa, sebagai contoh, ns-3 boleh melakukan jenis asas
simulasi sekurang-kurangnya sepantas alat bersaing, atau boleh digunakan untuk mengenal pasti bahagian
sistem yang berprestasi teruk.

Dalam ns-3 rangka kerja ujian, kami menyediakan sokongan untuk pemasaan pelbagai jenis ujian.

Pemeliharaan
Produk perisian mesti boleh diselenggara. Ini, sekali lagi, pernyataan yang sangat luas, tetapi a
rangka kerja ujian boleh membantu dengan tugas. Apabila model telah dibangunkan, disahkan dan
disahkan, kami boleh berulang kali melaksanakan set ujian untuk keseluruhan sistem untuk memastikan
bahawa ia kekal sah dan disahkan sepanjang hayatnya.

Apabila ciri berhenti berfungsi seperti yang dimaksudkan selepas beberapa jenis perubahan pada sistem
bersepadu, ia dipanggil secara umum a regresi. Pada asalnya istilah regresi
merujuk kepada perubahan yang menyebabkan pepijat yang telah diperbaiki sebelum ini muncul semula, tetapi istilah itu telah
berkembang untuk menerangkan apa-apa jenis perubahan yang memecahkan kefungsian sedia ada. Terdapat banyak
jenis regresi yang mungkin berlaku dalam amalan.

A tempatan regresi ialah satu perubahan yang mempengaruhi komponen yang diubah secara langsung. Untuk
contoh, jika komponen diubah suai untuk memperuntukkan dan membebaskan memori tetapi penunjuk basi
digunakan, komponen itu sendiri gagal.

A jauh regresi ialah satu perubahan di mana satu komponen memecahkan kefungsian
komponen lain. Ini mencerminkan pelanggaran yang tersirat tetapi mungkin tidak diiktiraf
kontrak antara komponen.

An yang dilepaskan regresi adalah satu yang mewujudkan situasi di mana pepijat yang sedia ada sebelum ini
yang tidak memberi kesan tiba-tiba terdedah dalam sistem. Ini mungkin semudah bersenam
laluan kod buat kali pertama.

A prestasi regresi adalah salah satu yang menyebabkan keperluan prestasi sistem untuk
dilanggar. Sebagai contoh, melakukan beberapa kerja dalam fungsi tahap rendah yang mungkin diulang
banyak kali tiba-tiba boleh menyebabkan sistem tidak boleh digunakan dari perspektif tertentu.

. ns-3 rangka kerja ujian menyediakan alat untuk mengautomasikan proses yang digunakan untuk mengesahkan dan
sahkan kod dalam suite ujian setiap malam untuk membantu mengenal pasti kemungkinan regresi dengan cepat.

Ujian rangka kerja
ns-3 terdiri daripada enjin teras simulasi, satu set model, program contoh dan ujian.
Dari masa ke masa, penyumbang baharu menyumbang model, ujian dan contoh. Program ujian Python
test.py berfungsi sebagai pengurus pelaksanaan ujian; test.py boleh menjalankan kod ujian dan contoh untuk
mencari regresi, boleh mengeluarkan keputusan ke dalam beberapa bentuk, dan boleh mengurus kod
alat analisis liputan. Di atas ini, kami melapisi Buildbots yang dibina secara automatik
robot yang melakukan ujian kekukuhan dengan menjalankan rangka kerja ujian pada sistem yang berbeza
dan dengan pilihan konfigurasi yang berbeza.

BuildBots
Pada tahap tertinggi ujian ns-3 ialah buildbots (membina robot). Jika anda adalah
tidak biasa dengan sistem ini lihat http://djmitche.github.com/buildbot/docs/0.7.11/.
Ini ialah sistem automatik sumber terbuka yang membolehkan ns-3 untuk dibina semula dan diuji setiap satu
masa sesuatu telah berubah. Dengan menjalankan buildbots pada beberapa sistem yang berbeza kami
boleh memastikan bahawa ns-3 membina dan melaksanakan dengan betul pada semua sistem yang disokongnya.

Pengguna (dan pembangun) biasanya tidak akan berinteraksi dengan sistem buildbot selain daripada
membaca mesejnya mengenai keputusan ujian. Jika kegagalan dikesan dalam salah satu
kerja binaan dan ujian automatik, buildbot akan menghantar e-mel ke ns-pemaju
senarai mel. E-mel ini akan kelihatan seperti

Dalam URL butiran penuh yang ditunjukkan dalam e-mel, seseorang boleh mencari kata kunci gagal and
pilih stdio pautan untuk langkah yang sepadan untuk melihat sebab kegagalan.

buildbot akan melakukan tugasnya secara senyap jika tiada ralat, dan sistem akan mengalaminya
bina dan uji kitaran setiap hari untuk mengesahkan bahawa semuanya baik-baik saja.

Test.py
The buildbots menggunakan program Python, test.py, yang bertanggungjawab untuk menjalankan semua
menguji dan mengumpul laporan yang terhasil ke dalam bentuk yang boleh dibaca manusia. Program ini adalah
juga tersedia untuk digunakan oleh pengguna dan pembangun juga.

test.py adalah sangat fleksibel dalam membenarkan pengguna untuk menentukan bilangan dan jenis ujian
lari; dan juga jumlah dan jenis keluaran untuk dijana.

Sebelum berlari test.py, pastikan contoh dan ujian ns3 telah dibina dengan melakukan
berikut

$ ./waf configure --enable-examples --enable-tests
$ ./waf

Secara lalai, test.py akan menjalankan semua ujian yang tersedia dan melaporkan status kembali dalam sangat ringkas
bentuk. Menjalankan arahan

$ ./test.py

akan mengakibatkan beberapa PAS, GAGAL, TUDUNG or SKIP petunjuk diikuti dengan jenis
ujian yang dijalankan dan nama paparannya.

Waf: Memasuki direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Meninggalkan direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'bina' berjaya diselesaikan (0.939s)
GAGAL: TestSuite ns3-wifi-propagation-loss-models
LULUS: TestSuite object-name-service
LULUS: TestSuite pcap-file-objek
LULUS: TestSuite ns3-tcp-cwnd
...
LULUS: TestSuite ns3-tcp-interoperability
LULUS: Contoh csma-broadcast
LULUS: Contoh csma-multicast

Mod ini bertujuan untuk digunakan oleh pengguna yang berminat untuk menentukan sama ada mereka
pengedaran berfungsi dengan betul, dan oleh pembangun yang berminat untuk menentukan sama ada
perubahan yang telah mereka lakukan telah menyebabkan sebarang regresi.

Terdapat beberapa pilihan yang tersedia untuk mengawal tingkah laku test.py. jika anda berlari
test.py - membantu anda harus melihat ringkasan arahan seperti:

Penggunaan: test.py [pilihan]

Pilihan:
-h, --help tunjukkan mesej bantuan ini dan keluar
-b BUILDPATH, --buildpath=BUILDPATH
nyatakan laluan di mana ns-3 dibina (lalai kepada
bina direktori untuk varian semasa)
-c JENIS, --constrain= JENIS
mengekang pelari ujian mengikut jenis ujian
-e CONTOH, --contoh=CONTOH
nyatakan satu contoh untuk dijalankan (tiada laluan relatif
diperlukan)
-g, --grind jalankan suite ujian dan contoh menggunakan valgrind
-k, --jenis mencetak jenis ujian yang ada
-l, --list cetak senarai ujian yang diketahui
-m, --multiple melaporkan pelbagai kegagalan daripada suite ujian dan ujian
kes
-n, --nowaf jangan jalankan waf sebelum memulakan ujian
-p PYEXAMPLE, --pyexample=PYEXAMPLE
nyatakan satu contoh python untuk dijalankan (dengan relative
jalan)
-r, --retain simpan semua fail sementara (yang biasanya
dipadamkan)
-s TEST-SUITE, --suite=TEST-SUITE
tentukan suite ujian tunggal untuk dijalankan
-t TEXT-FILE, --text=TEXT-FILE
tulis keputusan ujian terperinci ke dalam TEXT-FILE.txt
-v, --bermaklumat kemajuan cetakan dan mesej maklumat
-w HTML-FILE, --web=HTML-FILE, --html=HTML-FILE
tulis keputusan ujian terperinci ke dalam HTML-FILE.html
-x XML-FILE, --xml=XML-FILE
tulis keputusan ujian terperinci ke dalam XML-FILE.xml

Jika seseorang menentukan gaya keluaran pilihan, seseorang boleh menjana penerangan terperinci tentang
ujian dan status. Gaya yang ada ialah teks and HTML. The buildbots akan memilih HTML
pilihan untuk menjana laporan ujian HTML untuk binaan setiap malam menggunakan

$ ./test.py --html=nightly.html

Dalam kes ini, fail HTML bernama ''nightly.html'' akan dibuat dengan ringkasan yang cantik
daripada ujian yang dilakukan. Format "boleh dibaca manusia" tersedia untuk pengguna yang berminat dalam
butiran.

$ ./test.py --text=results.txt

Dalam contoh di atas, suite ujian menyemak ns-3 kehilangan perambatan peranti wayarles
model gagal. Secara lalai tiada maklumat lanjut diberikan.

Untuk meneroka lebih lanjut kegagalan, test.py membenarkan satu set ujian untuk ditentukan.
Menjalankan arahan

$ ./test.py --suite=ns3-wifi-propagation-loss-models

atau setaraf

$ ./test.py -s ns3-wifi-propagation-loss-models

menyebabkan suite ujian tunggal itu dijalankan.

GAGAL: TestSuite ns3-wifi-propagation-loss-models

Untuk mencari maklumat terperinci mengenai kegagalan, seseorang mesti menentukan jenis output
dikehendaki. Sebagai contoh, kebanyakan orang mungkin akan berminat dengan fail teks:

$ ./test.py --suite=ns3-wifi-propagation-loss-models --text=results.txt

Ini akan menyebabkan suite ujian tunggal itu dijalankan dengan status ujian ditulis ke
failkan ''results.txt''.

Anda harus mencari sesuatu yang serupa dengan yang berikut dalam fail itu

GAGAL: Test Suite ''ns3-wifi-propagation-loss-models'' (pengguna 0.02 sebenar 0.01 sistem 0.00)
LULUS: Kes Ujian "Semak ... Friis ... model ..." (pengguna 0.01 sebenar 0.00 sistem 0.00)
GAGAL: Kes Ujian "Semak ... Jarak Log ... model" (pengguna 0.01 sebenar 0.01 sistem 0.00)
Details:
Mesej: Mendapat nilai SNR yang tidak dijangka
Keadaan: [huraian panjang tentang perkara yang sebenarnya gagal]
Sebenar: 176.395
Had: 176.407 +- 0.0005
Fail: ../src/test/ns3wifi/propagation-loss-models-test-suite.cc
Line: 360

Perhatikan bahawa Test Suite terdiri daripada dua Kes Ujian. Kes ujian pertama memeriksa
Model kehilangan pembiakan Friis dan lulus. Kes ujian kedua gagal menyemak Log
Model perambatan jarak. Dalam kes ini, SNR sebanyak 176.395 ditemui, dan ujian
menjangkakan nilai 176.407 betul hingga tiga tempat perpuluhan. Fail yang dilaksanakan
ujian yang gagal disenaraikan serta baris kod yang mencetuskan kegagalan.

Jika anda mahu, anda boleh dengan mudah menulis fail HTML menggunakan --html pilihan
seperti yang dinyatakan di atas.

Biasanya pengguna akan menjalankan semua ujian sekurang-kurangnya sekali selepas memuat turun ns-3 untuk memastikan itu
persekitarannya telah dibina dengan betul dan menjana hasil yang betul
mengikut suite ujian. Pembangun biasanya akan menjalankan suite ujian sebelum dan
selepas membuat perubahan untuk memastikan bahawa mereka tidak memperkenalkan regresi dengan mereka
perubahan. Dalam kes ini, pembangun mungkin tidak mahu menjalankan semua ujian, tetapi hanya subset. Untuk
contoh, pembangun mungkin hanya mahu menjalankan ujian unit secara berkala semasa membuat
perubahan kepada repositori. Dalam kes ini, test.py boleh diberitahu untuk mengekang jenis
ujian dijalankan ke kelas ujian tertentu. Perintah berikut akan menghasilkan hanya
ujian unit yang dijalankan:

$ ./test.py --constrain=unit

Begitu juga, arahan berikut akan menghasilkan hanya contoh ujian asap dijalankan:

$ ./test.py --constrain=unit

Untuk melihat senarai pantas jenis kekangan undang-undang, anda boleh memintanya untuk disenaraikan.
Perintah berikut

$ ./test.py --kind

akan menyebabkan senarai berikut dipaparkan:

Waf: Memasuki direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Meninggalkan direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'bina' berjaya diselesaikan (0.939s)Waf: Memasuki direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
bvt: Ujian Pengesahan Binaan (untuk melihat sama ada binaan berjaya disiapkan)
teras: Jalankan semua ujian berasaskan TestSuite (tidak termasuk contoh)
contoh: Contoh (untuk melihat sama ada program contoh berjalan dengan jayanya)
prestasi: Ujian Prestasi (semak untuk melihat sama ada sistem sepantas yang dijangkakan)
sistem: Ujian Sistem (menjangkau modul untuk menyemak integrasi modul)
unit: Ujian Unit (dalam modul untuk menyemak kefungsian asas)

Mana-mana jenis ujian ini boleh disediakan sebagai kekangan menggunakan --kekangan pilihan.

Untuk melihat senarai pantas semua suite ujian yang tersedia, anda boleh memintanya
tersenarai. Perintah berikut,

$ ./test.py --list

akan menyebabkan senarai suite ujian dipaparkan, serupa dengan

Waf: Memasuki direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Meninggalkan direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'bina' berjaya diselesaikan (0.939s)
histogram
ns3-wifi-gangguan
ns3-tcp-cwnd
ns3-tcp-saling kendali
sampel
peranti-mesh-nyala
peranti-mesh-dot11s
peranti-mesh
...
perkhidmatan-nama-objek
panggil balik
sifat-sifat
config
nilai global
baris perintah
asas-nombor-rawak
objek

Mana-mana suite tersenarai ini boleh dipilih untuk dijalankan dengan sendirinya menggunakan --suite pilihan sebagai
ditunjukkan di atas.

Begitu juga dengan suite ujian, seseorang boleh menjalankan satu program contoh C++ menggunakan --contoh
pilihan. Ambil perhatian bahawa laluan relatif untuk contoh tidak perlu disertakan dan itu
boleh laku yang dibina untuk contoh C++ tidak mempunyai sambungan. Memasuki

$ ./test.py --example=udp-echo

mengakibatkan contoh tunggal itu dijalankan.

LULUS: Contoh contoh/udp/udp-echo

Anda boleh menentukan direktori tempat ns-3 dibina menggunakan --buildpath pilihan sebagai
ikut.

$ ./test.py --buildpath=/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build/debug --example=wifi-simple-adhoc

Seseorang boleh menjalankan satu program contoh Python menggunakan --pyexample pilihan. Perhatikan bahawa
laluan relatif untuk contoh mesti disertakan dan contoh Python memerlukannya
sambungan. Memasuki

$ ./test.py --pyexample=examples/tutorial/first.py

mengakibatkan contoh tunggal itu dijalankan.

LULUS: Contoh contoh/tutorial/first.py

Oleh kerana contoh Python tidak dibina, anda tidak perlu menentukan direktori di mana ns-3
dibina untuk menjalankan mereka.

Biasanya apabila program contoh dilaksanakan, mereka menulis sejumlah besar data fail surih.
Ini biasanya disimpan ke direktori asas pengedaran (cth,
/home/user/ns-3-dev). Bila test.py menjalankan contoh, ia benar-benar tidak peduli
dengan fail surih. Ia hanya mahu menentukan sama ada contoh boleh dibina dan dijalankan
tanpa kesilapan. Oleh kerana ini berlaku, fail surih ditulis ke dalam a
/tmp/unchecked-traces direktori. Jika anda menjalankan contoh di atas, anda sepatutnya dapat mencari
yang berkaitan udp-echo.tr and udp-echo-n-1.pcap fail di sana.

Senarai contoh yang tersedia ditakrifkan oleh kandungan direktori ''contoh'' dalam
pengagihan. Jika anda memilih contoh untuk pelaksanaan menggunakan --contoh pilihan,
test.py tidak akan membuat sebarang percubaan untuk memutuskan sama ada contoh telah dikonfigurasikan atau tidak, ia
hanya akan cuba menjalankannya dan melaporkan hasil percubaan.

Bila test.py berjalan, secara lalai ia akan terlebih dahulu memastikan bahawa sistem telah sepenuhnya
dibina. Ini boleh dikalahkan dengan memilih --nowaf pilihan.

$ ./test.py --list --nowaf

akan menghasilkan senarai suite ujian yang sedang dibina dipaparkan, serupa dengan:

ns3-wifi-propagation-loss-models
ns3-tcp-cwnd
ns3-tcp-saling kendali
pcap-file-objek
perkhidmatan-nama-objek
penjana-nombor rawak

Perhatikan ketiadaan Waf membina mesej.

test.py juga menyokong menjalankan suite ujian dan contoh di bawah valgrind. Valgrind ialah seorang
program fleksibel untuk nyahpepijat dan memprofilkan boleh laku Linux. Secara lalai, valgrind berjalan
alat yang dipanggil memcheck, yang melaksanakan pelbagai fungsi semakan memori, termasuk
mengesan akses kepada memori yang tidak dimulakan, penyalahgunaan memori yang diperuntukkan (double frees,
akses selepas percuma, dsb.) dan mengesan kebocoran memori. Ini boleh dipilih dengan menggunakan
--mengisar pilihan.

$ ./test.py --grind

Semasa ia berjalan, test.py dan program yang dijalankan secara tidak langsung, menjana sejumlah besar
fail-fail sementara. Biasanya, kandungan fail ini tidak menarik, namun dalam sesetengahnya
kes ia boleh berguna (untuk tujuan penyahpepijatan) untuk melihat fail ini. test.py menyediakan
--kekalkan pilihan yang akan menyebabkan fail sementara ini disimpan selepas dijalankan
selesai. Fail disimpan dalam direktori bernama testpy-output di bawah subdirektori
dinamakan mengikut Waktu Sejagat Selaras semasa (juga dikenali sebagai Greenwich Mean
Masa).

$ ./test.py --retain

Akhirnya, test.py menyediakan --verbose pilihan yang akan mencetak sejumlah besar maklumat
tentang kemajuannya. Ia tidak dijangka bahawa ini akan sangat berguna melainkan ada
kesilapan. Dalam kes ini, anda boleh mendapatkan akses kepada output standard dan ralat standard
dilaporkan dengan menjalankan suite ujian dan contoh. Pilih verbose dengan cara berikut:

$ ./test.py --verbose

Semua pilihan ini boleh dicampur dan dipadankan. Contohnya, untuk menjalankan semua teras ns-3
suite ujian di bawah valgrind, dalam mod verbose, sambil menjana fail output HTML, satu
akan melakukan:

$ ./test.py --verbose --grind --constrain=core --html=results.html

Taksonomi Ujian
Seperti yang dinyatakan di atas, ujian dikumpulkan ke dalam beberapa klasifikasi yang ditakrifkan secara meluas kepada
membenarkan pengguna menjalankan ujian secara terpilih untuk menangani pelbagai jenis ujian yang diperlukan
yang perlu dilakukan.

· Bina Ujian Pengesahan

· Ujian Unit

· Ujian Sistem

· Contoh

· Ujian Prestasi

BuildVerificationTests
Ini adalah ujian yang agak mudah yang dibina bersama dengan pengedaran dan digunakan
untuk memastikan binaan itu berfungsi dengan baik. Ujian unit semasa kami hidup di
fail sumber kod yang mereka uji dan dibina ke dalam modul ns-3; dan supaya sesuai dengan
penerangan tentang BVT. BVT hidup dalam kod sumber yang sama yang terbina dalam kod ns-3.
Ujian semasa kami adalah contoh ujian jenis ini.

Unit Ujian
Ujian unit adalah ujian yang lebih melibatkan yang terperinci untuk memastikan bahawa sekeping kod
berfungsi seperti yang diiklankan secara berasingan. Tidak ada sebab untuk ujian seperti ini berlaku
dibina ke dalam modul ns-3. Ternyata, sebagai contoh, unit menguji objek
perkhidmatan nama adalah kira-kira saiz yang sama dengan kod perkhidmatan nama objek itu sendiri. Ujian unit
adalah ujian yang memeriksa sedikit fungsi yang tidak dibina ke dalam kod ns-3,
tetapi tinggal dalam direktori yang sama dengan kod yang diuji. Ada kemungkinan bahawa ujian ini
semak penyepaduan berbilang fail pelaksanaan dalam modul juga. Fail
src/core/test/names-test-suite.cc ialah contoh ujian jenis ini. Fail
src/network/test/pcap-file-test-suite.cc ialah satu lagi contoh yang menggunakan pcap bagus yang diketahui
fail sebagai fail vektor ujian. Fail ini disimpan secara setempat dalam direktori src/rangkaian.

sistem Ujian
Ujian sistem ialah ujian yang melibatkan lebih daripada satu modul dalam sistem. Kami mempunyai banyak
ujian jenis ini berjalan dalam rangka kerja regresi semasa kami, tetapi biasanya
contoh terlebih muatan. Kami menyediakan tempat baharu untuk ujian jenis ini dalam direktori
src/ujian. Fail src/test/ns3tcp/ns3-interop-test-suite.cc ialah contoh jenis ini
daripada ujian. Ia menggunakan NSC TCP untuk menguji pelaksanaan ns-3 TCP. Selalunya akan ada ujian
vektor yang diperlukan untuk ujian jenis ini, dan ia disimpan dalam direktori di mana fail
menguji kehidupan. Sebagai contoh, ns3tcp-interop-response-vectors.pcap ialah fail yang terdiri daripada
bilangan pengepala TCP yang digunakan sebagai tindak balas yang dijangkakan bagi ns-3 TCP yang sedang diuji
kepada rangsangan yang dijana oleh NSC TCP yang digunakan sebagai pelaksanaan "kebaikan yang diketahui".

Contoh
Contoh-contoh diuji oleh rangka kerja untuk memastikan ia dibina dan akan dijalankan. Tiada apa-apa
diperiksa, dan pada masa ini fail pcap hanya dihapuskan ke dalam / tmp untuk dibuang. Jika
contoh berjalan (jangan ranap) mereka lulus ujian asap ini.

prestasi Ujian
Ujian prestasi ialah ujian yang menggunakan bahagian tertentu sistem dan menentukan
jika ujian telah dilaksanakan sehingga siap dalam masa yang munasabah.

Berlari Ujian
Ujian biasanya dijalankan menggunakan tahap tinggi test.py program. Untuk mendapatkan senarai
pilihan baris arahan yang tersedia, jalankan test.py - membantu

Program ujian test.py akan menjalankan kedua-dua ujian dan contoh yang telah ditambahkan
senarai untuk diperiksa. Perbezaan antara ujian dan contoh adalah seperti berikut. Ujian
secara amnya menyemak bahawa output atau peristiwa simulasi tertentu mematuhi tingkah laku yang dijangkakan.
Sebaliknya, output contoh tidak disemak, dan program ujian hanya menyemak
status keluar dari program contoh untuk memastikan ia berjalan tanpa ralat.

Secara ringkas, untuk menjalankan semua ujian, pertama mesti mengkonfigurasi ujian semasa peringkat konfigurasi, dan
juga (pilihan) contoh jika contoh hendak disemak:

$ ./waf --configure --enable-examples --enable-tests

Kemudian, bina ns-3, dan selepas ia dibina, jalankan sahaja test.py. test.py -h akan menunjukkan nombor
pilihan konfigurasi yang mengubah suai tingkah laku test.py.

Program yang test.py memanggil, untuk ujian dan contoh C++, program C++ peringkat rendah dipanggil
pelari ujian untuk benar-benar menjalankan ujian. Seperti yang dibincangkan di bawah, ini pelari ujian boleh jadi
cara yang berguna untuk menyahpepijat ujian.

Debugging Ujian
Penyahpepijatan program ujian paling baik dilakukan dengan menjalankan pelari ujian peringkat rendah
program. Pelari ujian ialah jambatan daripada kod Python generik kepada ns-3 kod. Ia adalah
ditulis dalam C++ dan menggunakan proses penemuan ujian automatik dalam ns-3 kod untuk mencari dan
membenarkan pelaksanaan semua pelbagai ujian.

Sebab utama mengapa test.py tidak sesuai untuk debugging ialah ia tidak dibenarkan
pengelogan untuk dihidupkan menggunakan NS_LOG pembolehubah persekitaran apabila test.py dijalankan. ini
had tidak terpakai kepada pelari ujian boleh laku. Oleh itu, jika anda ingin melihat pembalakan
output daripada ujian anda, anda perlu menjalankannya menggunakan test-runner secara langsung.

Untuk melaksanakan pelari ujian, anda menjalankannya seperti mana-mana ns-3 boleh laku yang lain -- menggunakan
WAF. Untuk mendapatkan senarai pilihan yang tersedia, anda boleh menaip:

$ ./waf --run "test-runner --help"

Anda sepatutnya melihat sesuatu seperti berikut

Waf: Memasuki direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Meninggalkan direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'bina' berjaya diselesaikan (0.353s)
--assert: Beritahu ujian kepada segfault (seperti assert) jika ralat dikesan
--basedir=dir: Tetapkan direktori asas (di mana untuk mencari src) kepada ''dir''
--tempdir=dir: Tetapkan direktori sementara (tempat untuk mencari fail data) kepada ''dir''
--constrain=test-type: Mengekang semakan untuk menguji suite jenis ''test-type''
--help: Cetak mesej ini
--jenis: Senaraikan semua jenis ujian yang tersedia
--list: Senaraikan semua suite ujian (secara pilihan dikekang oleh jenis ujian)
--out=file-name: Tetapkan fail output status ujian kepada ''file-name''
--suite=suite-name: Jalankan suite ujian bernama ''suite-name''
--verbose: Hidupkan mesej dalam suite ujian jalankan

Terdapat beberapa perkara yang tersedia untuk anda yang akan biasa kepada anda jika anda mempunyai
melihat test.py. Ini sepatutnya dijangka kerana pelari ujian hanyalah antara muka
antara test.py and ns-3. Anda mungkin perasan bahawa arahan berkaitan contoh tiada di sini.
Itu kerana contoh-contohnya sebenarnya tidak ns-3 ujian. test.py menjalankan mereka seolah-olah mereka
untuk membentangkan persekitaran ujian bersatu, tetapi mereka benar-benar berbeza dan tidak
boleh didapati di sini.

Pilihan baharu pertama yang muncul di sini, tetapi tidak dalam test.py ialah --tegaskan pilihan. Ini
pilihan berguna apabila menyahpepijat kes ujian apabila berjalan di bawah penyahpepijat seperti gdb. Apabila
dipilih, pilihan ini memberitahu kes ujian asas untuk menyebabkan pelanggaran pembahagian jika
ralat dikesan. Ini mempunyai kesan sampingan yang baik menyebabkan pelaksanaan program terhenti
(pecah ke penyahpepijat) apabila ralat dikesan. Jika anda menggunakan gdb, anda boleh gunakan
pilihan ini seperti,

$ ./waf shell
$ cd build/debug/utils
$ gdb pelari ujian
$ run --suite=global-value --assert

Jika ralat ditemui dalam suite ujian nilai global, segfault akan dihasilkan
dan penyahpepijat (tahap sumber) akan berhenti di NS_TEST_ASSERT_MSG yang mengesan
kesilapan.

Satu lagi pilihan baharu yang muncul di sini ialah --basedir pilihan. Ternyata beberapa
ujian mungkin perlu merujuk direktori sumber bagi ns-3 pengedaran untuk mencari tempatan
data, jadi direktori asas sentiasa diperlukan untuk menjalankan ujian.

Jika anda menjalankan ujian daripada test.py, program Python akan menyediakan pilihan berdasarkan mereka
awak. Untuk menjalankan salah satu ujian secara langsung daripada pelari ujian menggunakan WAF, anda perlu
tentukan suite ujian untuk dijalankan bersama-sama dengan direktori asas. Jadi anda boleh menggunakan cangkerang
dan lakukan:

$ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object"

Perhatikan tanda petikan ''ke belakang'' pada jentera perintah.

Jika anda menjalankan suite ujian daripada penyahpepijat, ia boleh menjadi agak menyakitkan untuk diingati
dan sentiasa menaip laluan mutlak direktori asas pengedaran. Disebabkan
ini, jika anda meninggalkan basedir, pelari ujian akan cuba memikirkan satu untuk anda. Ia
bermula dalam direktori kerja semasa dan berjalan ke atas pokok direktori mencari a
fail direktori dengan fail bernama VERSION and LESEN. Jika ia menemui satu, ia menganggapnya
mestilah berasaskan dan menyediakannya untuk anda.

ujian output
Banyak suite ujian perlu menulis fail sementara (seperti fail pcap) dalam proses
menjalankan ujian. Ujian kemudian memerlukan direktori sementara untuk menulis. Python
utiliti ujian (test.py) akan menyediakan fail sementara secara automatik, tetapi jika dijalankan secara bersendirian
direktori sementara ini mesti disediakan. Sama seperti dalam kes basedir, ia boleh
menjengkelkan untuk terus-menerus perlu menyediakan a --tempdir, jadi pelari ujian akan mengira satu
untuk anda jika anda tidak menyediakannya. Ia mula-mula mencari pembolehubah persekitaran yang dinamakan TMP
and TEMP dan menggunakan mereka. Jika tiada TMP tidak TEMP ditakrifkan ia memilih / tmp. Kodnya
kemudian tacks pada pengecam yang menunjukkan apa yang mencipta direktori (ns-3) kemudian masa
(hh.mm.ss) diikuti dengan nombor rawak yang besar. Pelari ujian mencipta direktori itu
nama untuk digunakan sebagai direktori sementara. Fail sementara kemudian pergi ke direktori yang
akan dinamakan seperti

/tmp/ns-3.10.25.37.61537845

Masa disediakan sebagai petunjuk supaya anda boleh membina semula dengan mudah
direktori telah digunakan jika anda perlu kembali dan melihat fail yang diletakkan di dalamnya
direktori.

Satu lagi kelas output ialah output ujian seperti jejak pcap yang dijana untuk dibandingkan
keluaran rujukan. Program ujian biasanya akan memadamkan ini selepas semua suite ujian
lari. Untuk melumpuhkan pemadaman output ujian, jalankan test.py dengan pilihan "kekalkan":

$ ./test.py -r

dan output ujian boleh didapati dalam testpy-output/ direktori.

laporan of ujian kegagalan
Apabila anda menjalankan suite ujian menggunakan pelari ujian, ia akan menjalankan ujian secara senyap secara lalai.
Satu-satunya petunjuk bahawa anda akan mendapat bahawa ujian itu lulus adalah ketiadaan mesej
dari WAF mengatakan bahawa program itu mengembalikan sesuatu selain kod keluar sifar. Untuk mendapatkan
beberapa output daripada ujian, anda perlu menentukan fail output yang akan digunakan oleh ujian
tulis status XML mereka menggunakan --keluar pilihan. Anda perlu berhati-hati mentafsir
keputusan kerana suite ujian akan tambah keputusan pada fail ini. cuba,

$ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object --out=myfile.xml"

Jika anda melihat fail myfile.xml anda sepatutnya melihat sesuatu seperti,


pcap-file-objek

Semak untuk melihat bahawa PcapFile::Open dengan mod ''w'' berfungsi
LULUS
sebenar 0.00 pengguna 0.00 sistem 0.00


Semak untuk melihat bahawa PcapFile::Open dengan mod ''r'' berfungsi
LULUS
sebenar 0.00 pengguna 0.00 sistem 0.00


Semak untuk melihat bahawa PcapFile::Open dengan mod ''a'' berfungsi
LULUS
sebenar 0.00 pengguna 0.00 sistem 0.00


Semak untuk melihat bahawa PcapFileHeader diurus dengan betul
LULUS
sebenar 0.00 pengguna 0.00 sistem 0.00


Semak untuk melihat bahawa PcapRecordHeader diurus dengan betul
LULUS
sebenar 0.00 pengguna 0.00 sistem 0.00


Semak untuk melihat bahawa PcapFile boleh membaca fail pcap yang terkenal
LULUS
sebenar 0.00 pengguna 0.00 sistem 0.00

LULUS
sebenar 0.00 pengguna 0.00 sistem 0.00


Jika anda sudah biasa dengan XML ini sepatutnya cukup jelas. Ia juga bukan a
fail XML yang lengkap kerana suite ujian direka bentuk supaya outputnya dilampirkan pada induk
Fail status XML seperti yang diterangkan dalam test.py bawah seksyen ini.

Debugging ujian suite kegagalan
Untuk menyahpepijat ranap ujian, seperti

CRASH: TestSuite ns3-wifi-gangguan

Anda boleh mengakses program pelari ujian asas melalui gdb seperti berikut, dan kemudian lulus
"--basedir=`pwd`" hujah untuk dijalankan (anda juga boleh menghantar argumen lain seperti yang diperlukan, tetapi
basedir adalah minimum yang diperlukan):

$ ./waf --command-template="gdb %s" --run "test-runner"
Waf: Memasuki direktori `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build'
Waf: Meninggalkan direktori `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build'
'bina' berjaya diselesaikan (0.380s)
GNU gdb 6.8-debian
Hak Cipta (C) 2008 Free Software Foundation, Inc.
L cense GPLv3+: GNU GPL versi 3 atau lebih baruhttp://gnu.org/licenses/gpl.html>
Ini adalah perisian percuma: anda bebas untuk menukar dan mengedarkannya semula.
TIADA WARANTI, setakat yang dibenarkan oleh undang-undang. Taip "tunjukkan penyalinan"
dan "tunjukkan jaminan" untuk butiran.
GDB ini telah dikonfigurasikan sebagai "x86_64-linux-gnu"...
(gdb) r --basedir=`pwd`
Memulakan program: <..>/build/debug/utils/test-runner --basedir=`pwd`
[Penyahpepijatan benang menggunakan libthread_db didayakan]
menegaskan gagal. file=../src/core/model/type-id.cc, line=138, cond="uid <= m_information.size () && uid != 0"
...

Berikut ialah satu lagi contoh cara menggunakan valgrind untuk menyahpepijat masalah ingatan seperti:

VALGR: Peranti TestSuite-mesh-dot11s-regresi

$ ./waf --command-template="valgrind %s --basedir=`pwd` --suite=devices-mesh-dot11s-regression" --run test-runner

Kelas TestRunner
Boleh laku yang menjalankan program ujian khusus menggunakan kelas TestRunner. Kelas ini
menyediakan pendaftaran dan penyenaraian ujian automatik, serta cara untuk melaksanakan
ujian individu. Suite ujian individu menggunakan pembina global C++ untuk menambah diri mereka sendiri
koleksi suite ujian yang diuruskan oleh pelari ujian. Pelari ujian digunakan untuk menyenaraikan
semua ujian yang ada dan untuk memilih ujian untuk dijalankan. Ini adalah kelas yang agak mudah
yang menyediakan tiga kaedah statik untuk menyediakan atau Menambah dan Mendapatkan suite ujian kepada a
koleksi ujian. Lihat doksigen untuk kelas ns3::TestRunner untuk maklumat lanjut.

ujian Suite
Semua ns-3 ujian dikelaskan kepada Test Suite dan Test Cases. Satu set ujian ialah a
koleksi kes ujian yang menggunakan sepenuhnya jenis fungsi tertentu. Sebagai
yang diterangkan di atas, suite ujian boleh dikelaskan sebagai,

· Bina Ujian Pengesahan

· Ujian Unit

· Ujian Sistem

· Contoh

· Ujian Prestasi

Klasifikasi ini dieksport daripada kelas TestSuite. Kelas ini agak mudah,
wujud hanya sebagai tempat untuk mengeksport jenis ini dan untuk mengumpul kes ujian. Daripada seorang pengguna
perspektif, untuk mencipta TestSuite baharu dalam sistem seseorang hanya perlu menentukan yang baharu
kelas yang diwarisi daripada kelas TestSuite dan melaksanakan dua tugas ini.

Kod berikut akan menentukan kelas baharu yang boleh dijalankan oleh test.py sebagai ujian ''unit''
dengan nama paparan, nama-suite-ujian saya.

kelas MySuite : TestSuite awam
{
awam:
MyTestSuite ();
};

MyTestSuite::MyTestSuite ()
: TestSuite ("my-test-suite-name", UNIT)
{
AddTestCase (MyTestCase baharu);
}

MyTestSuite myTestSuite;

Kelas asas menjaga semua pendaftaran dan pelaporan yang diperlukan untuk menjadi yang baik
warganegara dalam rangka kerja ujian.

ujian kes
Ujian individu dibuat menggunakan kelas TestCase. Model biasa untuk penggunaan ujian
kes termasuk "satu kes ujian setiap ciri", dan "satu kes ujian setiap kaedah." Campuran daripada
model-model ini boleh digunakan.

Untuk mencipta kes ujian baharu dalam sistem, semua yang perlu dilakukan ialah mewarisi daripada
Ujian Kes kelas asas, mengatasi pembina untuk memberi nama kes ujian dan menimpa
yang DoRun kaedah untuk menjalankan ujian.

kelas MyTestCase : TestCase awam
{
MyTestCase ();
kekosongan maya DoRun (kosong);
};

MyTestCase::MyTestCase ()
: TestCase ("Semak sedikit fungsi")
{
}

membatalkan
MyTestCase::DoRun (kosong)
{
NS_TEST_ASSERT_MSG_EQ (benar, benar, "Sesetengah mesej kegagalan");
}

Kesediaan
Terdapat beberapa jenis utiliti yang juga merupakan sebahagian daripada ujian
rangka kerja. Contohnya termasuk fail pcap umum yang berguna untuk menyimpan vektor ujian; a
bekas generik yang berguna untuk penyimpanan sementara bagi vektor ujian semasa pelaksanaan ujian; dan
alat untuk menjana persembahan berdasarkan keputusan ujian pengesahan dan pengesahan.

Utiliti ini tidak didokumenkan di sini, tetapi sebagai contoh, sila lihat cara ujian TCP
dijumpai dalam src/test/ns3tcp/ gunakan fail pcap dan output rujukan.

Cara kepada menulis ujian
Matlamat utama projek ns-3 adalah untuk membantu pengguna meningkatkan kesahan dan
kredibiliti keputusan mereka. Terdapat banyak elemen untuk mendapatkan model yang sah dan
simulasi, dan ujian adalah komponen utama. Jika anda menyumbang model atau contoh kepada
ns-3, anda mungkin diminta untuk menyumbang kod ujian. Model yang anda sumbangkan akan digunakan
selama bertahun-tahun oleh orang lain, yang mungkin tidak tahu pada pandangan pertama sama ada
model betul. Kod ujian yang anda tulis untuk model anda akan membantu mengelakkan masa depan
regresi dalam output dan akan membantu pengguna masa hadapan dalam memahami pengesahan dan
had kebolehgunaan model anda.

Terdapat banyak cara untuk mengesahkan ketepatan pelaksanaan model. Di dalam ini
bahagian, kami berharap dapat merangkumi beberapa kes biasa yang boleh digunakan sebagai panduan untuk menulis baharu
ujian.

Contoh TestSuite rangka
Apabila bermula dari awal (iaitu tidak menambah TestCase pada TestSuite sedia ada), ini
perkara perlu diputuskan terlebih dahulu:

· Apakah nama suite ujian

· Apakah jenis ujian itu (Ujian Pengesahan Binaan, Ujian Unit, Ujian Sistem, atau
Ujian Prestasi)

· Tempat kod ujian akan hidup (sama ada dalam modul ns-3 sedia ada atau secara berasingan dalam
src/test/ direktori). Anda perlu mengedit fail wscript dalam direktori itu ke
susun kod baharu anda, jika ia adalah fail baharu.

Satu program yang dipanggil src/create-module.py adalah titik permulaan yang baik. Program ini boleh
dipanggil seperti create-module.py penghala untuk modul baharu hipotesis yang dipanggil penghala. Sekali lagi
anda melakukan ini, anda akan melihat a penghala direktori, dan a test/router-test-suite.cc suite ujian.
Fail ini boleh menjadi titik permulaan untuk ujian awal anda. Ini adalah suite ujian yang berfungsi,
walaupun ujian sebenar yang dilakukan adalah remeh. Salinnya ke ujian modul anda
direktori, dan lakukan penggantian global "Penghala" dalam fail itu untuk sesuatu yang berkaitan
kepada model yang ingin anda uji. Anda juga boleh mengedit perkara seperti yang lebih deskriptif
nama kes ujian.

Anda juga perlu menambah blok ke dalam wscript anda untuk mendapatkan ujian ini untuk disusun:

module_test.source = [
'test/router-test-suite.cc',
]

Sebelum anda benar-benar mula membuat ini melakukan perkara yang berguna, anda boleh cuba menjalankannya
rangka. Pastikan ns-3 telah dikonfigurasikan dengan pilihan "--enable-tests".
Mari kita andaikan bahawa suite ujian baharu anda dipanggil "penghala" seperti di sini:

RouterTestSuite::RouterTestSuite ()
: TestSuite ("penghala", UNIT)

Cuba arahan ini:

$ ./test.py -s penghala

Output seperti di bawah perlu dihasilkan:

LULUS: Penghala TestSuite
1 daripada 1 ujian lulus (1 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Lihat src/lte/test/test-lte-antenna.cc untuk contoh yang berkesan.

ujian makro
Terdapat beberapa makro yang tersedia untuk menyemak output program ujian dengan jangkaan
pengeluaran. Makro ini ditakrifkan dalam src/core/model/test.h.

Set utama makro yang digunakan termasuk yang berikut:

NS_TEST_ASSERT_MSG_EQ(sebenar, had, mesej)
NS_TEST_ASSERT_MSG_NE(sebenar, had, mesej)
NS_TEST_ASSERT_MSG_LT(sebenar, had, mesej)
NS_TEST_ASSERT_MSG_GT(sebenar, had, mesej)
NS_TEST_ASSERT_MSG_EQ_TOL(sebenar, had, tol, msg)

Hujah pertama sebenar ialah nilai yang diuji, nilai kedua menghadkan adalah yang diharapkan
nilai (atau nilai untuk diuji), dan hujah terakhir msg ialah mesej ralat kepada
cetak jika ujian gagal.

Empat makro pertama di atas menguji kesamaan, ketaksamaan, kurang daripada, atau lebih besar daripada,
masing-masing. Makro kelima di atas menguji kesaksamaan, tetapi dalam toleransi tertentu.
Varian ini berguna apabila menguji nombor titik terapung untuk kesamaan terhadap had,
di mana anda ingin mengelakkan kegagalan ujian kerana ralat pembundaran.

Akhir sekali, terdapat varian di atas di mana kata kunci ASSERT digantikan oleh JANGKAKAN.
Varian ini direka khas untuk digunakan dalam kaedah (terutama panggilan balik) pemulangan
batal. Simpan penggunaannya untuk panggilan balik yang anda gunakan dalam program ujian anda; jika tidak, gunakan
yang ASSERT varian.

Cara kepada menambah an contoh program kepada yang ujian suite
Seseorang boleh "ujian asap" bahawa contoh disusun dan dijalankan dengan jayanya hingga selesai (tanpa
kebocoran memori) menggunakan examples-to-run.py skrip terletak dalam direktori ujian modul anda.
Secara ringkas, dengan memasukkan contoh fail ini dalam direktori ujian anda, anda boleh menyebabkan
pelari ujian untuk melaksanakan contoh yang disenaraikan. Ia biasanya terbaik untuk memastikan bahawa anda
pilih contoh yang mempunyai masa jangka pendek yang munasabah supaya tidak mengganggu ujian. Lihat
contoh dalam src/lte/test/ direktori.

Ujian khususnya boolean hasil
Ujian hasil apabila rawak is terlibat
Ujian output data terhadap a diketahui pengedaran
menyediakan tidak remeh input vektor of data
Penyimpanan and rujukan tidak remeh output data
Membentangkan Matlamat output ujian data
Khidmat Bantuan
mewujudkan a baru ns-3 model
Bab ini berjalan melalui proses reka bentuk sebuah ns-3 model. Dalam banyak kes penyelidikan,
pengguna tidak akan berpuas hati untuk hanya menyesuaikan model sedia ada, tetapi mungkin mahu melanjutkan
teras simulator dengan cara yang baru. Kami akan menggunakan contoh menambah ErrorModel ke a
mudah ns-3 pautan sebagai contoh motivasi bagaimana seseorang itu mungkin mendekati masalah ini dan
meneruskan reka bentuk dan pelaksanaan.

PERHATIAN:
dokumentasi

Di sini kami memberi tumpuan kepada proses mencipta model baharu dan modul baharu, dan beberapa daripadanya
pilihan reka bentuk yang terlibat. Demi kejelasan, kami menangguhkan perbincangan mengenai mekanik
mendokumentasikan model dan kod sumber kepada dokumentasi bab.

reka bentuk Pendekatan
Pertimbangkan bagaimana anda mahu ia berfungsi; apa yang patut dilakukan. Fikirkan perkara ini:

· fungsi: Apakah fungsi yang sepatutnya ada? Apakah atribut atau konfigurasi
terdedah kepada pengguna?

· kebolehgunaan semula: Berapa banyak orang lain boleh menggunakan semula reka bentuk saya? Bolehkah saya menggunakan semula kod daripada
ns-2 untuk memulakan? Bagaimanakah pengguna menyepadukan model dengan yang lain
simulasi?

· kebergantungan: Bagaimanakah saya boleh mengurangkan pengenalan kebergantungan luar pada kod baharu saya
sebanyak mungkin (untuk menjadikannya lebih modular)? Sebagai contoh, patutkah saya mengelak sebarang
pergantungan pada IPv4 jika saya mahu ia juga digunakan oleh IPv6? Sekiranya saya mengelakkan sebarang pergantungan
pada IP sama sekali?

Jangan teragak-agak untuk menghubungi ns-3-pengguna or ns-pemaju senaraikan jika anda mempunyai soalan.
Khususnya, adalah penting untuk memikirkan API awam model baharu anda dan memintanya
maklum balas. Ia juga membantu untuk memberitahu orang lain tentang kerja anda sekiranya anda berminat
rakan usaha sama.

Contoh: ErrorModel
Model ralat wujud dalam ns-2. Ia membolehkan paket dihantar ke objek stateful yang
menentukan, berdasarkan pembolehubah rawak, sama ada paket itu rosak. Pemanggil boleh
kemudian tentukan apa yang perlu dilakukan dengan paket (jatuhkannya, dsb.).

API utama model ralat ialah fungsi untuk menghantar paket kepada, dan nilai pulangan
fungsi ini ialah boolean yang memberitahu pemanggil sama ada sebarang rasuah berlaku. Catatan
bahawa bergantung pada model ralat, penimbal data paket mungkin atau mungkin tidak rosak.
Mari kita panggil fungsi ini "IsCorrupt()".

Setakat ini, dalam reka bentuk kami, kami mempunyai:

kelas ErrorModel
{
awam:
/ **
* \returns true jika Paket dianggap sebagai ralat/rosak
* \param pkt Paket untuk menggunakan model ralat
*/
bool IsCorrupt (Ptr pkt);
};

Ambil perhatian bahawa kami tidak lulus penunjuk const, dengan itu membenarkan fungsi untuk mengubah suai
paket jika IsCorrupt() kembali benar. Tidak semua model ralat sebenarnya akan mengubah suai paket;
sama ada penimbal data paket rosak atau tidak perlu didokumenkan.

Kami mungkin juga mahukan versi khusus ini, seperti dalam ns-2, jadi walaupun ia bukan
hanya pilihan reka bentuk untuk polimorfisme, kami menganggap bahawa kami akan mensubkelaskan kelas asas
ErrorModel untuk kelas khusus, seperti RateErrorModel, ListErrorModel, dll, seperti
dilakukan dalam ns-2.

Anda mungkin berfikir pada ketika ini, "Mengapa tidak menjadikan IsCorrupt() kaedah maya?". Itu dia
satu pendekatan; satu lagi ialah menjadikan fungsi bukan maya awam secara tidak langsung melalui a
fungsi maya peribadi (ini dalam C++ dikenali sebagai simpulan bahasa antara muka bukan maya dan adalah
diterima pakai di ns-3 kelas ErrorModel).

Seterusnya, adakah peranti ini mempunyai sebarang kebergantungan pada IP atau protokol lain? Kami tidak mahu
untuk mencipta kebergantungan pada protokol Internet (model ralat harus digunakan untuk
protokol bukan Internet juga), jadi kami akan mengingatinya kemudian.

Pertimbangan lain ialah bagaimana objek akan memasukkan model ralat ini. Kami membayangkan meletakkan
penetap eksplisit dalam pelaksanaan NetDevice tertentu, sebagai contoh.:

/ **
* Lampirkan ErrorModel terima pada PointToPointNetDevice.
*
* PointToPointNetDevice secara pilihan boleh memasukkan ErrorModel dalam
* rantai menerima paket.
*
* @lihat ErrorModel
* @param em Ptr ke ErrorModel.
*/
batal PointToPointNetDevice::SetReceiveErrorModel(Ptr em);

Sekali lagi, ini bukan satu-satunya pilihan yang kami ada (model ralat boleh diagregatkan kepada banyak model
objek lain), tetapi ia memenuhi kes penggunaan utama kami, iaitu membenarkan pengguna memaksa
ralat pada penghantaran paket yang berjaya, pada peringkat NetDevice.

Selepas berfikir dan melihat yang sedia ada ns-2 kod, berikut ialah contoh API pangkalan
kelas dan subkelas pertama yang boleh disiarkan untuk semakan awal:

kelas ErrorModel
{
awam:
ErrorModel ();
maya ~ErrorModel ();
bool IsCorrupt (Ptr pkt);
void Tetapkan semula (void);
void Membolehkan (void);
void Lumpuhkan (void);
bool IsEnabled (void) const;
peribadi:
bool maya DoCorrupt (Ptr pkt) = 0;
kekosongan maya DoReset (kosong) = 0;
};

enum ErrorUnit
{
EU_BIT,
EU_BYTE,
EU_PKT
};

// Tentukan paket mana yang ralat sepadan dengan asas
// taburan pembolehubah rawak, kadar ralat dan unit untuk kadar.
kelas RateErrorModel : ErrorModel awam
{
awam:
RateErrorModel ();
maya ~RateErrorModel ();
enum ErrorUnit GetUnit (kosong) const;
batal SetUnit (enum ErrorUnit error_unit);
double GetRate (void) const;
batal SetRate (kadar berganda);
void SetRandomVariable (const RandomVariable &ranvar);
peribadi:
bool maya DoCorrupt (Ptr pkt);
kekosongan maya DoReset (kosong);
};

Perancah
Katakan anda sudah bersedia untuk mula melaksanakan; anda mempunyai gambaran yang agak jelas
perkara yang anda ingin bina, dan anda mungkin telah meminta beberapa semakan awal atau cadangan daripada
senarai. Satu cara untuk mendekati langkah seterusnya (pelaksanaan) adalah dengan membuat perancah dan
isi butiran apabila reka bentuk matang.

Bahagian ini menelusuri banyak langkah yang perlu anda pertimbangkan untuk mentakrifkan perancah, atau
rangka tidak berfungsi yang model anda akhirnya akan melaksanakan. Ia biasanya baik
berlatih untuk tidak menunggu untuk mendapatkan butiran ini disepadukan pada akhirnya, tetapi sebaliknya untuk memasang a
rangka model anda ke dalam sistem lebih awal dan kemudian tambah fungsi kemudian setelah API dan
integrasi nampaknya betul.

Ambil perhatian bahawa anda akan mahu mengubah suai beberapa perkara dalam pembentangan di bawah untuk model anda
kerana jika anda mengikuti model ralat verbatim, kod yang anda hasilkan akan bertembung dengan
model ralat sedia ada. Di bawah hanyalah garis besar tentang cara ErrorModel dibina untuk anda
boleh menyesuaikan diri dengan model lain.

ULASAN yang ns-3 Pengekodan Style Dokumen
Pada ketika ini, anda mungkin mahu berhenti seketika dan membaca ns-3 dokumen gaya pengekodan, terutamanya
jika anda sedang mempertimbangkan untuk menyumbang kod anda kembali kepada projek. Gaya pengekodan
dokumen dipautkan dari halaman projek utama: ns-3 pengekodan gaya.

Putuskan Lokasi in yang Source Tree yang model Sekiranya Tinggal
Semua ns-3 kod sumber model ada dalam direktori src /. Anda perlu memilih yang mana
subdirektori ia berada di dalamnya. Jika ia adalah sejenis kod model baharu, masuk akal untuk meletakkannya
ke src / direktori di suatu tempat, terutamanya untuk memudahkan penyepaduan dengan binaan
sistem.

Dalam kes model ralat, ia sangat berkaitan dengan kelas paket, jadi ia masuk akal
untuk melaksanakan ini dalam src/rangkaian/ modul di mana ns-3 paket dilaksanakan.

WAF and wskrip
ns-3 menggunakan Waf membina sistem. Anda akan mahu menyepadukan baharu anda ns-3 menggunakan Waf
membina sistem. Anda akan mahu menyepadukan fail sumber baharu anda ke dalam sistem ini. ini
memerlukan anda menambah fail anda pada wskrip fail yang terdapat dalam setiap direktori.

Mari kita mulakan dengan fail kosong error-model.h dan error-model.cc, dan tambahkan ini pada
src/network/wscript. Ia sebenarnya hanya satu perkara untuk menambah fail .cc ke seluruh fail
fail sumber dan fail .h ke senarai fail pengepala.

Sekarang, muncul ke direktori peringkat atas dan taip "./test.py". Anda tidak sepatutnya patah
apa-apa dengan operasi ini.

Termasuk Pengawal
Seterusnya, mari tambah sedikit termasuk pengawal dalam fail pengepala kami.:

#ifndef ERROR_MODEL_H
#define ERROR_MODEL_H
...
#endif

ruang nama ns3
ns-3 menggunakan ns-3 ruang nama untuk mengasingkan simbolnya daripada ruang nama lain. Lazimnya, a
pengguna seterusnya akan meletakkan ns-3 blok ruang nama dalam kedua-dua fail cc dan h.:

ruang nama ns3 {
...
}

Pada ketika ini, kami mempunyai beberapa fail rangka di mana kami boleh mula menentukan kelas baharu kami.
Fail pengepala kelihatan seperti ini:

#ifndef ERROR_MODEL_H
#define ERROR_MODEL_H

ruang nama ns3 {

} // ruang nama ns3
#endif

manakala error-model.cc fail kelihatan seperti ini:

#include "error-model.h"

ruang nama ns3 {

} // ruang nama ns3

Fail ini harus disusun kerana ia tidak mempunyai sebarang kandungan. Kami kini bersedia untuk
mula menambah kelas.

Permulaan Pelaksanaan
Pada ketika ini, kami masih mengusahakan beberapa perancah, tetapi kami boleh mula menentukan perancah kami
kelas, dengan fungsi yang akan ditambahkan kemudian.

Waris dari yang Objek Kelas?
Ini adalah langkah reka bentuk yang penting; sama ada menggunakan kelas Objek sebagai kelas asas untuk baharu anda
kelas.

Seperti yang diterangkan dalam bab mengenai ns-3 Model objek, kelas yang mewarisi daripada kelas
Objek dapatkan ciri khas:

· yang ns-3 jenis dan sistem atribut (lihat Atribut)

· sistem pengagregatan objek

· sistem pengiraan rujukan penunjuk pintar (kelas Ptr)

Kelas yang berasal dari kelas ObjectBase} dapatkan dua sifat pertama di atas, tetapi jangan
dapatkan petunjuk pintar. Kelas yang berasal dari kelas RefCountBase dapatkan hanya penunjuk pintar
sistem pengiraan rujukan.

Dalam amalan, kelas Objek ialah varian ketiga-tiga di atas iaitu ns-3 pemaju akan
paling biasa ditemui.

Dalam kes kami, kami ingin menggunakan sistem atribut, dan kami akan menghantar contoh
objek ini merentasi ns-3 API awam, jadi kelas Objek sesuai untuk kita.

Permulaan kelas
Satu cara untuk meneruskan ialah bermula dengan mentakrifkan fungsi minimum dan lihat jika ia akan
menyusun. Mari kita semak semula perkara yang diperlukan untuk dilaksanakan apabila kita terbitkan daripada Objek kelas.:

#ifndef ERROR_MODEL_H
#define ERROR_MODEL_H

#include "ns3/object.h"

ruang nama ns3 {

kelas ErrorModel : Objek awam
{
awam:
TypeId GetTypeId statik (kosong);

ErrorModel ();
maya ~ErrorModel ();
};

kelas RateErrorModel : ErrorModel awam
{
awam:
TypeId GetTypeId statik (kosong);

RateErrorModel ();
maya ~RateErrorModel ();
};
#endif

Beberapa perkara yang perlu diperhatikan di sini. Kita perlu sertakan objek.h. Konvensyen di ns-3 adakah jika
fail pengepala terletak bersama dalam direktori yang sama, ia mungkin disertakan tanpa sebarang laluan
awalan. Oleh itu, jika kami melaksanakan ErrorModel dalam src/teras/model direktori, kami
boleh sahaja berkata "#include "objek.h"". Tapi kita masuk src/rangkaian/model, jadi kita mesti
masukkannya sebagai "#include "ns3/object.h"". Perhatikan juga bahawa ini berada di luar ruang nama
pengisytiharan.

Kedua, setiap kelas mesti melaksanakan fungsi ahli awam statik yang dipanggil GetTypeId (kosong).

Ketiga, adalah idea yang baik untuk melaksanakan pembina dan pemusnah daripada membiarkannya
pengkompil menjana mereka, dan untuk menjadikan pemusnah maya. Dalam C++, perhatikan juga salinan itu
pengendali tugasan dan pembina salinan dijana secara automatik jika ia tidak ditakrifkan, jadi
jika anda tidak mahu itu, anda harus melaksanakannya sebagai ahli persendirian. Aspek ini
C++ dibincangkan dalam buku C++ Effective Scott Meyers. perkara 45.

Sekarang mari kita lihat beberapa kod pelaksanaan rangka yang sepadan dalam fail .cc.:

#include "error-model.h"

ruang nama ns3 {

NS_OBJECT_ENSURE_REGISTERED (ErrorModel);

TypeId ErrorModel::GetTypeId (kosong)
{
static TypeId tid = TypeId ("ns3::ErrorModel")
.SetParent ()
;
tid balik;
}

ErrorModel::ErrorModel ()
{
}

ErrorModel::~ErrorModel ()
{
}

NS_OBJECT_ENSURE_REGISTERED (RateErrorModel);

TypeId RateErrorModel::GetTypeId (kosong)
{
static TypeId tid = TypeId ("ns3:: RateErrorModel")
.SetParent ()
.AddConstructor ()
;
tid balik;
}

RateErrorModel::RateErrorModel ()
{
}

RateErrorModel::~RateErrorModel ()
{
}

Apakah GetTypeId (kosong) fungsi? Fungsi ini melakukan beberapa perkara. Ia mendaftar a
rentetan unik ke dalam sistem TypeId. Ia menetapkan hierarki objek dalam
sistem atribut (melalui SetParent). Ia juga mengisytiharkan bahawa objek tertentu boleh dibuat melalui
rangka kerja penciptaan objek (AddConstructor).

Makro NS_OBJECT_ENSURE_REGISTERED (nama kelas) diperlukan juga sekali untuk setiap kelas itu
mentakrifkan kaedah GetTypeId baharu, dan ia melakukan pendaftaran sebenar kelas ke dalam
sistem. Bab model Objek membincangkan perkara ini dengan lebih terperinci.

Termasuk luar Fail
Pembalakan Khidmat Bantuan
Di sini, menulis a sedikit mengenai menambah |ns3| pembalakan makro. Nota Bahawa LOG_COMPONENT_DEFINE is
dilakukan di luar yang ruang nama ns3

Pembina, Kosong fungsi Prototaip
Utama Pembolehubah (Lalai nilai, Atribut)
ujian Program 1
Objek Rangka Kerja
Menambah a Contoh skrip
Pada ketika ini, seseorang mungkin ingin mencuba mengambil perancah asas yang ditakrifkan di atas dan menambahnya
ke dalam sistem. Melaksanakan langkah ini sekarang membolehkan seseorang menggunakan model yang lebih mudah semasa memasang paip
ke dalam sistem dan mungkin juga mendedahkan sama ada sebarang reka bentuk atau pengubahsuaian API perlu
dibuat. Setelah ini selesai, kami akan kembali membina kefungsian
ErrorModels sendiri.

Tambah Asas Khidmat Bantuan in yang Kelas
/* point-to-point-net-device.h */
kelas ErrorModel;

/ **
* Model ralat untuk menerima acara paket
*/
Ptr m_receiveErrorModel;

Tambah Aksesori
membatalkan
PointToPointNetDevice::SetReceiveErrorModel (Ptr em)
{
NS_LOG_FUNCTION (ini << em);
m_receiveErrorModel = em;
}

.AddAttribute ("ReceiveErrorModel",
"Model ralat penerima yang digunakan untuk mensimulasikan kehilangan paket",
Nilai Penunjuk (),
MakePointerAccessor (&PointToPointNetDevice::m_receiveErrorModel),
MakePointerChecker ())

Terbakar Ke dalam yang sistem
batal PointToPointNetDevice::Terima (Ptr paket)
{
NS_LOG_FUNCTION (paket << ini);
protokol uint16_t = 0;

jika (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (paket) )
{
//
// Jika kita mempunyai model ralat dan ia menunjukkan bahawa sudah tiba masanya untuk kehilangan a
// paket rosak, jangan majukan paket ini ke atas, biarkan ia pergi.
//
m_dropTrace (paket);
}
lagi
{
//
// Tekan cangkuk surih terima, tanggalkan pengepala protokol titik ke titik
// dan majukan paket ini ke atas timbunan protokol.
//
m_rxTrace (paket);
ProcessHeader(paket, protokol);
m_rxCallback (ini, paket, protokol, GetRemote ());
jika (!m_promiscCallback.IsNull ())
{ m_promiscCallback (ini, paket, protokol, GetRemote (),
GetAddress (), NetDevice::PACKET_HOST);
}
}
}

Buat Menyeimbangkan berfungsi skrip
/* simple-error-model.cc */

// Model ralat
// Kami ingin menambah model ralat pada NetDevice nod 3
// Kita boleh mendapatkan pemegang kepada NetDevice melalui saluran dan nod
// petunjuk
Ptr nd3 = PointToPointTopology::GetNetDevice
(n3, saluran2);
Ptr em = Buat ();
nd3->SetReceiveErrorModel (em);

bool
ErrorModel::DoCorrupt (Paket&p)
{
NS_LOG_FUNCTION;
NS_LOG_UNCOND("Korup!");
kembali palsu;
}

Pada ketika ini, kami boleh menjalankan program dengan ErrorModel remeh kami dimasukkan ke dalam penerimaan
laluan PointToPointNetDevice. Ia mencetak rentetan "Corrupt!" untuk setiap paket
diterima pada nod n3. Seterusnya, kita kembali kepada model ralat untuk menambah dalam subkelas yang berprestasi
pemodelan ralat yang lebih menarik.

Tambah a Subkelas
Kelas asas yang remeh ErrorModel tidak melakukan apa-apa yang menarik, tetapi ia menyediakan a
antara muka kelas asas yang berguna (Corrupt () dan Reset ()), dimajukan kepada fungsi maya yang
boleh disubkelaskan. Mari kita pertimbangkan seterusnya apa yang kita panggil BasicErrorModel yang berdasarkan
yang ns-2 Kelas ErrorModel (dalam ns-2/queue/errmodel.{cc,h}).

Apakah sifat yang kita mahu ini ada, dari perspektif antara muka pengguna? Kami ingin
untuk pengguna dapat menukar secara remeh jenis ErrorModel yang digunakan dalam
NetDevice. Kami juga ingin keupayaan untuk menetapkan parameter boleh dikonfigurasikan.

Berikut adalah beberapa keperluan mudah yang akan kami pertimbangkan:

· Keupayaan untuk menetapkan pembolehubah rawak yang mengawal kerugian (lalai ialah UniformVariable)

· Keupayaan untuk menetapkan unit (bit, bait, paket, masa) butiran yang terdapat ralat
terpakai.

· Keupayaan untuk menetapkan kadar ralat (cth 10^-3) sepadan dengan unit di atas
kebutiran.

· Keupayaan untuk mendayakan/melumpuhkan (lalai didayakan)

Cara kepada Subkelas
Kami mengisytiharkan BasicErrorModel sebagai subkelas ErrorModel seperti berikut,:

kelas BasicErrorModel : ErrorModel awam
{
awam:
TypeId GetTypeId statik (kosong);
...
peribadi:
// Laksanakan fungsi maya tulen kelas asas
bool maya DoCorrupt (Ptr p);
bool maya DoReset (kosong);
...
}

dan konfigurasikan fungsi GetTypeId subkelas dengan menetapkan rentetan TypeId yang unik dan
menetapkan Induk kepada ErrorModel:

TypeId RateErrorModel::GetTypeId (kosong)
{
static TypeId tid = TypeId ("ns3:: RateErrorModel")
.SetParent ()
.AddConstructor ()
...

Membina Teras Fungsi and Unit Ujian
Tegaskan Makro
Penulisan Unit Ujian
Menambah a Baru Modul kepada ns-3
Apabila anda telah membuat kumpulan kelas, contoh dan ujian yang berkaitan, ia boleh
digabungkan menjadi satu ns-3 modul supaya ia boleh digunakan dengan sedia ada ns-3 modul
dan oleh penyelidik lain.

Bab ini membimbing anda melalui langkah-langkah yang diperlukan untuk menambah modul baharu ns-3.

Langkah 0 - Modul Susun atur
Semua modul boleh didapati di src direktori. Setiap modul boleh didapati dalam direktori
yang mempunyai nama yang sama dengan modul. Sebagai contoh, yang spektrum modul boleh didapati di sini:
src/spektrum. Kami akan memetik daripada spektrum modul untuk ilustrasi.

Modul prototaip mempunyai struktur direktori berikut dan fail yang diperlukan:

src /
nama modul/
ikatan/
doc/
contoh/
wskrip
pembantu/
model/
ujian /
examples-to-run.py
wskrip

Tidak semua direktori akan hadir dalam setiap modul.

Langkah 1 - Buat a Modul Skeleton
Program python disediakan dalam direktori sumber yang akan mencipta rangka untuk yang baharu
modul. Untuk tujuan perbincangan ini kami akan menganggap bahawa modul baharu anda dipanggil
modul baru. Daripada src direktori, lakukan perkara berikut untuk mencipta modul baharu:

$ ./create-module.py new-module

Seterusnya, cd ke dalam modul baru; anda akan menemui susun atur direktori ini:

$ cd modul baru
$ls
doc contoh helper model test wscript

Secara lebih terperinci, create-module.py skrip akan mencipta direktori serta permulaan
rangka wskrip, .h, . Cc and .pertama fail. Modul lengkap dengan fail rangka kelihatan
seperti ini:

src /
modul-baru/
doc/
modul-baru.pertama
contoh/
new-module-example.cc
wskrip
pembantu/
new-module-helper.cc
new-modul-helper.h
model/
new-module.cc
modul-baru.h
ujian /
new-module-test-suite.cc
wskrip

(Jika diperlukan ikatan/ direktori yang disenaraikan dalam Langkah-0 akan dibuat secara automatik semasa
binaan.)

Kami seterusnya membincangkan cara menyesuaikan modul ini. Memaklumkan WAF tentang fail yang
membuat modul anda selesai dengan menyunting kedua-duanya wskrip fail. Kami akan berjalan melalui
langkah utama dalam bab ini.

Semua ns-3 modul bergantung kepada teras modul dan biasanya pada modul lain. pergantungan ini
dinyatakan dalam wskrip fail (di peringkat atas modul, bukan fail berasingan wskrip
fail dalam contoh direktori!). Dalam rangka wskrip panggilan yang akan mengisytiharkan anda
modul baru ke WAF akan kelihatan seperti ini (sebelum mengedit):

binaan def(bld):
modul = bld.create_ns3_module('modul-baru', ['teras'])

Mari kita anggap itu modul baru bergantung pada Internet, mobiliti, dan aodv modul. Selepas
mengeditnya wskrip fail akan kelihatan seperti:

binaan def(bld):
modul = bld.create_ns3_module('modul-baru', ['internet', 'mobiliti', 'aodv'])

Ambil perhatian bahawa hanya kebergantungan modul peringkat pertama harus disenaraikan, itulah sebabnya kami mengalih keluar
teras; yang Internet modul pula bergantung kepada teras.

Modul anda kemungkinan besar akan mempunyai fail sumber model. Rangka awal (yang akan
menyusun dengan jayanya) dicipta dalam model/modul-baru.cc and model/modul-baru.h.

Jika modul anda mempunyai fail sumber pembantu, maka ia akan masuk ke dalam pembantu/
direktori; sekali lagi, rangka awal dicipta dalam direktori itu.

Akhir sekali, adalah amalan yang baik untuk menulis ujian dan contoh. Ini hampir pasti
diperlukan untuk modul baru diterima menjadi rasmi ns-3 pokok sumber. Sebuah rangka
suite ujian dan kes ujian dicipta dalam ujian / direktori. Suite ujian rangka akan
mengandungi pembina di bawah, yang mengisytiharkan ujian unit baharu bernama modul baru, Dengan
kes ujian tunggal yang terdiri daripada kelas NewModuleTestCase1:

NewModuleTestSuite::NewModuleTestSuite ()
: TestSuite ("modul-baru", UNIT)
{
AddTestCase (NewModuleTestCase1 baharu);
}

Langkah 3 - Beritahu Source Fail
Fail pengepala awam dan kod sumber untuk modul baharu anda hendaklah dinyatakan dalam
wskrip fail dengan mengubah suainya dengan editor teks anda.

Sebagai contoh, selepas mengisytiharkan spektrum modul, yang src/spektrum/wscript menentukan
fail kod sumber dengan senarai berikut:

binaan def(bld):

modul = bld.create_ns3_module('spektrum', ['internet', 'propagasi', 'antena', 'aplikasi'])

module.source = [
'model/spectrum-model.cc',
'model/spectrum-value.cc',
.
.
.
'model/microwave-oven-spectrum-value-helper.cc',
'helper/spectrum-helper.cc',
'helper/adhoc-aloha-noack-ideal-phy-helper.cc',
'helper/waveform-generator-helper.cc',
'helper/spectrum-analyzer-helper.cc',
]

Objek yang terhasil daripada penyusunan sumber ini akan dipasang ke dalam perpustakaan pautan,
yang akan dipautkan kepada mana-mana program yang bergantung pada modul ini.

Tetapi bagaimanakah program sedemikian mempelajari API awam modul baharu kami? Teruskan membaca!

Langkah 4 - Beritahu Awam Header Fail
Fail pengepala yang mentakrifkan API awam model dan pembantu anda juga sepatutnya
dinyatakan dalam wskrip fail.

Teruskan dengan spektrum ilustrasi model, fail pengepala awam ditentukan
dengan rangkap berikut. (Perhatikan bahawa hujah kepada bld fungsi memberitahu WAF kepada
pasang pengepala modul ini dengan yang lain ns-3 tajuk):

pengepala = bld(ciri='ns3header')

headers.module = 'spektrum'

headers.source = [
'model/spektrum-model.h',
'model/spectrum-value.h',
.
.
.
'model/microwave-oven-spectrum-value-helper.h',
'helper/spectrum-helper.h',
'helper/adhoc-aloha-noack-ideal-phy-helper.h',
'helper/waveform-generator-helper.h',
'helper/spectrum-analyzer-helper.h',
]

Pengepala yang didedahkan kepada umum dengan cara ini boleh diakses oleh pengguna model anda dengan disertakan
kenyataan seperti

#include "ns3/spectrum-model.h"

Pengepala yang digunakan secara dalaman dalam pelaksanaan anda tidak seharusnya disertakan di sini. mereka
masih boleh diakses oleh pelaksanaan anda dengan memasukkan pernyataan seperti

#include "my-module-implementation.h"

Langkah 5 - Beritahu Ujian
Jika modul baharu anda mempunyai ujian, maka ia mesti dinyatakan dalam anda wskrip fail oleh
mengubah suainya dengan editor teks anda.

. spektrum ujian model ditentukan dengan rangkap berikut:

modul_test = bld.create_ns3_module_test_library('spektrum')

module_test.source = [
'test/spectrum-interference-test.cc',
'test/spectrum-value-test.cc',
]

Lihat Ujian untuk maklumat lanjut tentang cara menulis kes ujian.

Langkah 6 - Beritahu Contoh
Jika modul baharu anda mempunyai contoh, maka ia mesti dinyatakan dalam modul anda contoh/wskrip
fail. (Tingkat atas rangka wskrip akan termasuk secara rekursif contoh/wskrip hanya jika
contoh telah didayakan pada masa konfigurasi.)

. spektrum model mentakrifkan contoh pertama dalam src/spektrum/contoh/wscript bersama

binaan def(bld):
obj = bld.create_ns3_program('adhoc-aloha-ideal-phy',
['spektrum', 'mobiliti'])
obj.source = 'adhoc-aloha-ideal-phy.cc'

Perhatikan bahawa hujah kedua kepada fungsi create_ns3_program() ialah senarai modul
bahawa program yang dicipta bergantung kepada; sekali lagi, jangan lupa sertakan modul baru in
senarai. Amalan terbaik untuk menyenaraikan hanya kebergantungan modul langsung, dan biarkan WAF
menyimpulkan pokok pergantungan penuh.

Kadangkala, untuk kejelasan, anda mungkin mahu membahagikan pelaksanaan untuk contoh anda antara
beberapa fail sumber. Dalam kes ini, masukkan sahaja fail tersebut sebagai eksplisit tambahan
sumber contoh:

obj = bld.create_ns3_program('contoh-modul-baru', [modul-baru])
obj.source = ['new-module-example.cc', 'new-module-example-part.cc']

Contoh Python ditentukan menggunakan panggilan fungsi berikut. Perhatikan bahawa yang kedua
hujah untuk fungsi tersebut register_ns3_script() ialah senarai modul yang Python
contoh bergantung kepada:

bld.register_ns3_script('new-module-example.py', ['new-modul'])

Langkah 7 - Contoh Main as Ujian
Selain menjalankan kod ujian eksplisit, rangka kerja ujian juga boleh digunakan
jalankan program contoh penuh untuk cuba menangkap regresi dalam contoh. Namun, tidak semua
contoh sesuai untuk ujian regresi. Fail test/examples-to-run.py mengawal
penggunaan contoh apabila rangka kerja ujian dijalankan.

. spektrum contoh model yang dijalankan oleh test.py dinyatakan dalam
src/spectrum/test/examples-to-run.py menggunakan dua senarai C++ dan Python berikut
contoh:

# Senarai contoh C++ untuk dijalankan bagi memastikan ia kekal
# boleh dibina dan boleh dijalankan dari semasa ke semasa. Setiap tupel dalam senarai mengandungi
#
# (example_name, do_run, do_valgrind_run).
#
# Lihat test.py untuk mendapatkan maklumat lanjut.
cpp_examples = [
("adhoc-aloha-ideal-phy", "True", "True"),
("adhoc-aloha-ideal-phy-with-microwave-oven", "True", "True"),
("adhoc-aloha-ideal-phy-matrix-propagation-loss-model", "True", "True"),
]

# Senarai contoh Python untuk dijalankan bagi memastikan ia kekal
# boleh dijalankan dari semasa ke semasa. Setiap tupel dalam senarai mengandungi
#
# (nama_contoh, lakukan_jalankan).
#
# Lihat test.py untuk mendapatkan maklumat lanjut.
contoh_python = [
("sample-simulator.py", "Benar"),
]

Seperti yang ditunjukkan dalam ulasan, setiap entri dalam senarai contoh C++ untuk dijalankan mengandungi
tupel (nama_contoh, do_run, do_valgrind_run), Di mana

· contoh_nama adalah boleh laku untuk dijalankan,

· do_run adalah syarat untuk menjalankan contoh, dan

· do_valgrind_run adalah syarat untuk menjalankan contoh di bawah valgrind. (Ini
diperlukan kerana NSC menyebabkan ranap arahan tidak sah dengan beberapa ujian apabila ia berlaku
dijalankan di bawah valgrind.)

Ambil perhatian bahawa kedua-dua syarat adalah pernyataan Python yang boleh bergantung pada WAF konfigurasi
pembolehubah. Sebagai contoh,

("tcp-nsc-lfn", "NSC_ENABLED == Benar", "NSC_ENABLED == Salah"),

Setiap entri dalam senarai Python contoh untuk dijalankan mengandungi tuple (nama_contoh,
do_run), di mana, bagi contoh C++,

· contoh_nama ialah skrip Python untuk dijalankan, dan

· do_run adalah syarat untuk menjalankan contoh.

Sekali lagi, syaratnya ialah pernyataan Python yang boleh bergantung pada WAF pemboleh ubah konfigurasi.
Sebagai contoh,

("realtime-udp-echo.py", "ENABLE_REAL_TIME == Salah"),

Langkah 8 - Konfigurasi and Membina
Anda kini boleh mengkonfigurasi, membina dan menguji modul anda seperti biasa. Anda mesti mengkonfigurasi semula
projek sebagai langkah pertama supaya WAF cache maklumat baharu dalam anda wskrip fail, atau
jika tidak, modul baharu anda tidak akan disertakan dalam binaan.

$ ./waf configure --enable-examples --enable-tests
$ ./waf binaan
$ ./test.py

Cari suite ujian modul baharu anda (dan contoh program, jika modul anda ada
didayakan) dalam output ujian.

Langkah 9 - Python Pengikatan
Menambah pengikatan Python pada modul anda adalah pilihan, dan langkah itu diulas oleh
lalai dalam create-module.py skrip.

# bld.ns3_python_bindings()

Jika anda ingin memasukkan pengikatan Python (hanya diperlukan jika anda ingin menulis Python ns-3
program dan bukannya program C++ ns-3), anda harus menyahkomen di atas dan memasang
Sistem pengimbasan API Python (dilindungi di bahagian lain dalam manual ini) dan imbas modul anda ke
menghasilkan pengikatan baru.

mewujudkan dokumentasi
ns-3 membekalkan dua jenis dokumentasi: bab gaya "panduan pengguna" ekspositori, dan
dokumentasi API kod sumber.

Bab "panduan pengguna" ditulis dengan tangan reStructuredText format (.pertama), iaitu
diproses oleh sistem dokumentasi Python Sphinx untuk menjana halaman web dan fail pdf.
Dokumentasi API dihasilkan daripada kod sumber itu sendiri, menggunakan Doksigen, untuk menjana
halaman web bersilang. Kedua-duanya adalah penting: bab Sphinx menerangkan mengapa
dan gambaran keseluruhan menggunakan model; dokumentasi API menerangkan bagaimana butiran.

Bab ini memberikan gambaran ringkas tentang alatan ini, menekankan penggunaan pilihan dan
penyesuaian untuk ns-3.

Untuk membina semua dokumentasi standard:

$ ./waf docs

Untuk pilihan yang lebih khusus, baca terus.

Mendokumentasikan bersama Sphinx
Kami menggunakan Sphinx untuk menjana bab ekspositori yang menerangkan reka bentuk dan penggunaan setiap satu
modul. Sekarang anda sedang membaca dokumentasi Bab. The Tunjuk Source pautan di
bar sisi akan menunjukkan kepada anda sumber reStructuredText untuk bab ini.

Menambah Baru bab
Menambah bab baharu memerlukan tiga langkah (diterangkan dengan lebih terperinci di bawah):

1. Pilih Di mana? fail dokumentasi akan hidup.

2. pautan daripada halaman sedia ada kepada dokumentasi baharu.

3. Tambahkan fail baharu pada Makefile.

Di mana?
Dokumentasi untuk modul tertentu, foo, biasanya perlu masuk src/foo/doc/. Sebagai contoh
src/foo/doc/foo.rst akan menjadi dokumen peringkat tertinggi untuk modul. The
src/create-module.py skrip akan mencipta fail ini untuk anda.

Sesetengah model memerlukan beberapa model .pertama fail, dan angka; ini semua harus masuk ke dalam
src/foo/doc/ direktori. Dokumen itu sebenarnya dibina oleh Sphinx Makefile. Khususnya
dokumentasi yang terlibat, mungkin berguna untuk mempunyai dokumen tempatan Makefile dalam src/foo/doc/
direktori untuk memudahkan pembinaan dokumentasi untuk modul ini (Antenna adalah contoh).
Menetapkan ini tidak begitu sukar, tetapi di luar skop bab ini.

Dalam sesetengah kes, dokumentasi merangkumi pelbagai model; yang rangkaian bab adalah contoh. Dalam
kes-kes ini menambah .pertama fail terus ke doc/models/source/ mungkin sesuai.

pautan
Sphinx perlu tahu di mana bab baharu anda sepatutnya muncul. Dalam kebanyakan kes, model baharu
bab harus muncul dalam model buku. Untuk menambah bab anda di sana, edit
doc/models/source/index.rst

.. toctree::
:maxdepth: 1

organisasi
animasi
antena
aodv
aplikasi
...

Tambahkan nama dokumen anda (tanpa .pertama sambungan) ke senarai ini. Tolong simpan
Model bab dalam susunan abjad, untuk memudahkan pengimbasan visual untuk bab tertentu.

Makefile
Anda juga perlu menambah dokumen anda kepada yang sesuai Makefile, Jadi membuat tahu untuk menyemaknya
untuk kemas kini. Buku Model Makefile ialah doc/models/Makefile, Buku manual Makefile ialah
doc/manual/Makefile.

# senaraikan semua fail perpustakaan model .pertama yang perlu disalin ke $SOURCETEMP
SUMBER = \
sumber/conf.py \
sumber/_statik \
source/index.rst \
source/replace.txt \
sumber/organisasi.rst \
...
$(SRC)/antenna/doc/source/antenna.rst \
...

Anda tambahkan anda .pertama fail ke SUMBER pembolehubah. Untuk menambah angka, baca ulasan dalam
Makefile untuk melihat pembolehubah yang harus mengandungi fail imej anda. Sekali lagi, sila simpan ini
mengikut susunan abjad.

Bangunan Sphinx Docs
Membina dokumentasi Sphinx agak mudah. Untuk membina semua Sphinx
dokumentasi:

$ ./waf sphinx

Untuk membina hanya dokumentasi Model:

$ buat -C doc/models

Untuk melihat dokumentasi yang dijana, halakan pelayar anda doc/models/build/html.

Seperti yang anda lihat, Sphinx menggunakan Make untuk membimbing proses. Sasaran lalai membina semua
borang output yang didayakan, yang dalam ns-3 ialah halaman berbilang html, satu halaman singlehtml, dan
pdf (getah). Untuk membina hanya html berbilang halaman, anda menambah html sasaran:

$ buat -C doc/models html

Ini boleh membantu mengurangkan masa binaan (dan saiz perbualan binaan) semasa anda
sedang menulis bab anda.

Sebelum menyerahkan dokumentasi anda kepada repo, sila semak sama ada ia dibina tanpa
kesilapan atau amaran. Proses binaan menjana banyak output (kebanyakannya perbualan biasa
daripada LaTeX), yang boleh menyukarkan untuk melihat sama ada terdapat sebarang amaran Sphinx atau
kesilapan. Untuk mencari amaran dan ralat penting, bina hanya html versi, kemudian cari
log binaan untuk amaran or kesilapan.

ns-3 Spesifik
Sphinx dokumentasi and tutorial cukup bagus. Kami tidak akan menduplikasi asas
di sini, sebaliknya memfokuskan pada penggunaan pilihan untuk ns-3.

· Mulakan dokumen dengan dua baris ini:

.. termasuk:: replace.txt
.. sorotan:: cpp

Baris pertama membolehkan beberapa penggantian mudah. Contohnya, menaip |ns3| menjadikan sebagai
ns-3. Yang kedua menetapkan kod sumber lalai yang menyerlahkan bahasa secara eksplisit untuk
fail, kerana tekaan penghurai tidak selalu tepat. (Ia juga mungkin untuk menetapkan
bahasa secara eksplisit untuk satu blok kod, lihat di bawah.)

· Bahagian:

Sphinx cukup liberal tentang menanda tajuk bahagian. Mengikut konvensyen, kami lebih suka ini
hierarki:

.. hierarki tajuk:
------------- Bab
************* Bahagian (#.#)
============= Subseksyen (#.#.#)
############ Sub-subseksyen

· Penyertaan Sintaks:

Untuk menggunakan penyerlah sintaks lalai, hanya mulakan blok kod sumber:

┌───── memandikan ────────────────────────────────
│Sumber Sphinx │ Output Diberikan │
├───── memandikan ────────────────────────────────
│ │ Yang Frobnitz diakses oleh: │
│ ``Frobnitz`` diakses oleh:: │ │
│ │ Foo::Frobnitz frob; │
│ Foo::Frobnitz frob; │ frob.Set (...); │
│ frob.Set (...); │ │
└───── memandikan ────────────────────────────────

Untuk menggunakan penyerlah sintaks tertentu, contohnya, menampar arahan shell:

┌───── memandikan ───┐
│Sumber Sphinx │ Output Diberikan │
├───── memandikan ───┤
│ │ │
│ .. kod sumber:: bash │ $ ls │
│ │ │
│ $ ls │ │
└───── memandikan ───┘

· Notasi Shorthand:

Kata ringkas ini ditakrifkan:

-
│Sumber Sphinx │ Output Diberikan │
├────────────────────────┼─────────────────┼─────—․
│ │ ns-3
│ |ns3| │ │
├────────────────────────┼─────────────────┼─────—․
│ │ ns-2
│ |ns2| │ │
├────────────────────────┼─────────────────┼─────—․
│ │ │
│ |semak| │ │
├────────────────────────┼─────────────────┼─────—․
│ │ RFC 6282
│ :rfc:`6282` │ │
-

Mendokumentasikan bersama Doksigen
Kami menggunakan Doksigen untuk menjana boleh dilayari dokumentasi API. Doxygen menyediakan beberapa
ciri berguna:

· Jadual ringkasan semua ahli kelas.

· Graf pewarisan dan kerjasama untuk semua kelas.

· Pautan kepada kod sumber yang melaksanakan setiap fungsi.

· Pautan ke setiap tempat ahli digunakan.

· Pautan kepada setiap objek yang digunakan dalam melaksanakan fungsi.

· Pengumpulan kelas yang berkaitan, seperti semua kelas yang berkaitan dengan protokol tertentu.

Di samping itu, kami menggunakan JenisId sistem untuk menambah dokumentasi bagi setiap kelas

· The config laluan yang mana objek tersebut boleh dicapai.

· Dokumentasi untuk sebarang Atribut, Termasuk Atribut ditakrifkan dalam kelas induk.

· Dokumentasi untuk sebarang Trace sumber yang ditentukan oleh kelas.

Doxygen beroperasi dengan mengimbas kod sumber, mencari komen yang ditanda khas. Ia
juga mencipta rujukan silang, menunjukkan di mana setiap fail, kelas, kaedah dan pembolehubah adalah
terpakai.

pilihan Style
Gaya pilihan untuk komen Doxygen ialah gaya JavaDoc:

/ **
* Penerangan ringkas tentang kelas atau kaedah ini.
* Baris bersebelahan menjadi satu perenggan.
*
* Penerangan yang lebih panjang, dengan banyak butiran.
*
* Baris kosong memisahkan perenggan.
*
* Terangkan apa yang kelas atau kaedah lakukan, menggunakan algoritma apa.
* Terangkan unit hujah dan nilai pulangan.
*
* \nota Perhatikan sebarang had atau gotcha.
*
* (Untuk fungsi dengan argumen atau pulangan bernilai:)
* \param foo Frasa nama ringkas yang menerangkan hujah ini.
* bar \param Nota Kes ayat, dan tempoh penamatan.
* \return Frasa nama ringkas yang menerangkan nilai.
*
* \dalaman
*
* Anda juga boleh membincangkan butiran pelaksanaan dalaman.
* Memahami bahan ini tidak perlu digunakan
* kelas atau kaedah.
*/
Contoh kelas

Dalam gaya ini blok komen Doxygen bermula dengan dua aksara `*': / **, dan mendahului
item yang didokumenkan.

Untuk item yang hanya memerlukan penerangan ringkas, salah satu daripada bentuk ringkas ini adalah sesuai:

/** Pelaksanaan pemusnah. */
batal DoDispose ();

int m_count; //!< Kiraan ...

Perhatikan bentuk khas ulasan akhir baris, //!, menunjukkan bahawa ia merujuk kepada
sebelum item.

Beberapa perkara yang perlu diperhatikan:

· Gunakan huruf besar, termasuk huruf besar awal.

· Gunakan tanda baca, terutamanya `.' di akhir ayat atau frasa.

· The \ringkas tag tidak diperlukan; ayat pertama akan digunakan sebagai ringkas
keterangan.

Setiap kelas, kaedah, typedef, pembolehubah ahli, hujah fungsi dan nilai pulangan sepatutnya
didokumenkan dalam semua fail kod sumber yang membentuk API formal dan pelaksanaan untuk
ns-3, Seperti src/ /model/*, src/ /pembantu/* and src/ /utils/*.
Dokumentasi untuk item dalam src/ /test/* and src/ /contoh/* diutamakan,
tetapi tidak diperlukan.

Berguna Ciri-ciri
· Ahli yang diwarisi secara automatik akan mewarisi dokumen daripada ibu bapa, (tetapi boleh diganti
oleh dokumentasi tempatan).

1. Dokumenkan kelas asas.

2. Dalam tanda sub kelas mewarisi fungsi dengan ulasan biasa:

// Kaedah yang diwarisi
kekosongan maya FooBar (kosong);
maya int BarFoo (double baz);

Ambil perhatian bahawa tandatangan mesti sepadan dengan tepat, jadi sertakan hujah rasmi (kosong)

Ini tidak berfungsi untuk fungsi statik; lihat GetTypeId, di bawah, sebagai contoh.

Bangunan Doksigen Docs
Membina dokumentasi Doxygen agak mudah:

$ ./waf doksigen

Ini membina menggunakan konfigurasi lalai, yang menjana bahagian dokumentasi untuk
semua item, walaupun mereka tidak mempunyai blok dokumentasi ulasan yang jelas. Ini mempunyai
kesan menyekat amaran untuk item tidak berdokumen, tetapi memastikan semuanya muncul
dalam output yang dihasilkan.

Apabila menulis dokumentasi, selalunya lebih berguna untuk melihat item yang dijana
amaran, biasanya mengenai kehilangan dokumentasi. Untuk melihat senarai amaran penuh, gunakan
doc/doxygen.warnings.report.sh skrip:

$ doc/doxygen.warnings.report.sh
Waf: Memasuki direktori `build'
...
Waf: Meninggalkan direktori `build'
'bina' berjaya diselesaikan (3m24.094s)

Membina semula dokumen doksigen dengan ralat penuh...Selesai.

Laporan amaran Doksigen
----------------------------------------

(Semua kiraan adalah sempadan bawah.)

Amaran mengikut modul/direktori:

Direktori Kira
--------------------------------------
3844 src/lte/model
1718 src/wimax/model
1423 src/teras/model
....
138 parameter tidak berdokumen tambahan.
----------------------------------------
15765 jumlah amaran
126 direktori dengan amaran

Amaran mengikut fail (abjad)

Kira Fail
--------------------------------------
17 doc/introspected-doxygen.h
15 contoh/routing/manet-routing-compare.cc
26 contoh/statistik/wifi-contoh-aplikasi.h
....
----------------------------------------
967 fail dengan amaran

Amaran mengikut fail (nombor)

Kira Fail
--------------------------------------
374 src/lte/model/lte-asn1-header.h
280 src/lte/model/lte-rrc-sap.h
262 src/lte/model/lte-rrc-header.h
....
----------------------------------------
967 fail dengan amaran

Ringkasan Amaran Doksigen
----------------------------------------
126 direktori
Fail 967
15765 amaran

Skrip mengubah suai konfigurasi untuk menunjukkan semua amaran, dan untuk memendekkan masa jalankan.
Seperti yang anda lihat, pada penulisan ini kami ada a banyak daripada item tidak berdokumen. Laporan itu
meringkaskan amaran mengikut modul src/*/*, dan mengikut fail, dalam susunan abjad dan berangka.

Skrip mempunyai beberapa pilihan untuk mengurangkan masalah dan menjadikannya lebih mudah diurus. Untuk pertolongan,
menggunakan -h pilihan. Setelah menjalankannya sekali untuk melakukan binaan Doxygen dan menjana sepenuhnya
log amaran, anda boleh memproses semula fail log dengan pelbagai "penapis," tanpa perlu melakukannya
Doxygen penuh dibina oleh, sekali lagi menggunakan -s pilihan. Anda boleh mengecualikan amaran daripada
*/contoh/* fail (-e pilihan), dan/atau */ujian/* fail (-t).

Mungkin pilihan yang paling berguna semasa menulis komen dokumentasi ialah -m , Yang
akan mengehadkan laporan kepada hanya padanan fail src/ /*, dan ikuti laporan dengan
garis amaran sebenar. Gabungkan dengan eth dan anda boleh fokus pada amaran yang ada
paling mendesak dalam satu modul:

$ doc/doxygen.warnings.report.sh -m mesh/helper
...
Ringkasan Amaran Doksigen
----------------------------------------
1 direktori
Fail 3
149 amaran

Amaran Ditapis
========================================
src/mesh/helper/dot11s/dot11s-installer.h:72: amaran: Ahli m_root (pembolehubah) kelas ns3::Dot11sStack tidak didokumenkan.
src/mesh/helper/dot11s/dot11s-installer.h:35: amaran: jenis kembalikan ahli ns3::Dot11sStack::GetTypeId tidak didokumenkan
src/mesh/helper/dot11s/dot11s-installer.h:56: amaran: jenis kembalikan ahli ns3::Dot11sStack::InstallStack tidak didokumenkan
src/mesh/helper/flame/lfame-installer.h:40: amaran: Ahli GetTypeId() (fungsi) kelas ns3::FlameStack tidak didokumenkan.
src/mesh/helper/flame/flame-installer.h:60: amaran: kembalikan jenis ahli ns3::FlameStack::InstallStack tidak didokumenkan
src/mesh/helper/mesh-helper.h:213: amaran: Ahli m_nInterfaces (pembolehubah) kelas ns3::MeshHelper tidak didokumenkan.
src/mesh/helper/mesh-helper.h:214: amaran: Ahli m_spreadChannelPolicy (pembolehubah) kelas ns3::MeshHelper tidak didokumenkan.
src/mesh/helper/mesh-helper.h:215: amaran: Ahli m_stack (pembolehubah) kelas ns3::MeshHelper tidak didokumenkan.
src/mesh/helper/mesh-helper.h:216: amaran: Ahli m_stackFactory (pembolehubah) kelas ns3::MeshHelper tidak didokumenkan.
src/mesh/helper/mesh-helper.h:209: amaran: parameter ahli ns3::MeshHelper::CreateInterface tidak (semua) didokumenkan
src/mesh/helper/mesh-helper.h:119: amaran: parameter ahli ns3::MeshHelper::SetStandard tidak (semua) didokumenkan

Kini ia hanya soal memahami kod, dan menulis beberapa dokumen!

ns-3 Spesifik
Bagi Sphinx, Doksigen docs and rujukan cukup bagus. Kami tidak akan menduplikasi
asas di sini, sebaliknya memfokuskan pada penggunaan pilihan untuk ns-3.

· Gunakan Doksigen Modul untuk mengumpulkan item berkaitan.

Dalam pengepala utama untuk modul, buat kumpulan Doxgyen:

/ **
* \defgroup foo Foo protokol.
*/

Tandai setiap kelas yang berkaitan sebagai milik kumpulan:

/ **
* \ingroup foo
*
* Jenis paket Foo.
*/
kelas Foo

· Adakah kamu tahu mesin taip boleh mempunyai hujah rasmi? Ini membolehkan dokumentasi fungsi
tandatangan penunjuk:

/ **
* Tandatangan fungsi panggil balik bar.
*
* \param ale Saiz sepint ale, dalam auns Imperial.
*/
typedef void (* BarCallback)(const int ale);

· Salin atribut rentetan bantuan daripada GetTypeId kaedah untuk digunakan sebagai ringkas
penerangan ahli yang berkaitan.

· \bugid{298} akan membuat pautan ke pepijat 298 dalam Bugzilla kami.

· \pname{foo} dalam huraian akan diformatkan foo sebagai \param foo parameter, menjadikannya jelas
bahawa anda merujuk kepada hujah sebenar.

· \RFC{301} akan membuat pautan ke RFC 301.

· \dalaman hendaklah digunakan hanya untuk memulakan perbincangan mengenai butiran pelaksanaan, bukan untuk
tanda swasta fungsi (mereka sudah ditanda, sebagai swasta!)

· Jangan buat kelas dengan nama remeh, seperti kelas A, walaupun dalam suite ujian. Ini
menyebabkan semua contoh nama kelas literal `A' dipaparkan sebagai pautan.

Seperti yang dinyatakan di atas, fungsi statik tidak mewarisi dokumentasi fungsi yang sama dalam
kelas induk. ns-3 menggunakan beberapa fungsi statik di mana-mana; yang dicadangkan
blok dokumentasi untuk kes ini ialah:

· Pembina/pemusnah lalai:

Kelas saya (); //!< Pembina lalai
~Kelas Saya (); //!< Pemusnah

· Pemusnah tiruan dan DoDispose:

/** Pemusnah tiruan, lihat DoDispose. */
~Kelas Saya ();

/** Pelaksanaan pemusnah */
kekosongan maya DoDispose ();

· GetTypeId:

/ **
* Daftar jenis ini.
* \return Objek TypeId.
*/
TypeId GetTypeId statik (kosong);

Mendayakan Subset of ns-3 Modul
Seperti kebanyakan projek perisian, ns-3 semakin besar dari segi bilangan modul,
baris kod, dan jejak ingatan. Pengguna, bagaimanapun, hanya boleh menggunakan beberapa modul tersebut
pada satu masa. Atas sebab ini, pengguna mungkin ingin mendayakan subset secara eksplisit sahaja
mungkin ns-3 modul yang sebenarnya mereka perlukan untuk penyelidikan mereka.

Bab ini membincangkan cara untuk membolehkan hanya ns-3 modul yang anda minati
menggunakan.

Cara kepada membolehkan a subset of ns-3's modul
Jika perpustakaan kongsi sedang dibina, maka mendayakan modul akan menyebabkan sekurang-kurangnya satu
perpustakaan yang akan dibina:

libns3-modulename.so

Jika modul mempunyai perpustakaan ujian dan perpustakaan ujian sedang dibina, maka

libns3-modulename-test.so

akan dibina juga. Modul lain yang modul bergantung pada dan perpustakaan ujian mereka
juga akan dibina.

Secara lalai, semua modul terbina dalam ns-3. Terdapat dua cara untuk mendayakan subset ini
modul:

1. Menggunakan pilihan waf --enable-modules

2. Menggunakan ns-3 fail konfigurasi

enable modul menggunakan waf's --dayakan-modul pilihan
Untuk mendayakan hanya modul teras dengan contoh dan ujian, sebagai contoh, cuba arahan ini:

$ ./waf bersih
$ ./waf configure --enable-examples --enable-tests --enable-modules=core
$ ./waf binaan
$ cd build/debug/
$ls

dan perpustakaan berikut harus ada:

bindings libns3-core.so ns3 scratch utils
contoh libns3-core-test.so sampel src

Perhatikan ./waff membersihkan langkah dilakukan di sini hanya untuk menjadikannya lebih jelas perpustakaan modul mana
telah dibina. Anda tidak perlu buat ./waff membersihkan untuk membolehkan subset modul.

Menjalankan test.py akan menyebabkan hanya ujian yang bergantung pada teras modul dijalankan:

24 daripada 24 ujian lulus (24 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Ulangi langkah di atas untuk modul "rangkaian" dan bukannya modul "teras", dan
berikut akan dibina, kerana rangkaian bergantung pada teras:

bindings libns3-core.so libns3-network.so ns3 scratch utils
contoh libns3-core-test.so libns3-network-test.so sampel src

Menjalankan test.py akan menyebabkan ujian yang bergantung pada modul teras dan rangkaian sahaja
dijalankan:

31 daripada 31 ujian lulus (31 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

enable modul menggunakan yang ns-3 konfigurasi fail
Fail konfigurasi, .ns3rc, telah ditambahkan pada ns-3 yang membolehkan pengguna menentukan yang mana
modul hendaklah disertakan dalam binaan.

Apabila mendayakan subset daripada ns-3 modul, peraturan keutamaan adalah seperti berikut:

1. rentetan konfigurasi --enable-modules mengatasi mana-mana fail .ns3rc

2. fail .ns3rc di peringkat atas ns-3 direktori dirujuk seterusnya, jika ada

3. sistem mencari ~/.ns3rc jika kedua-dua di atas tidak dinyatakan

Jika tiada satu pun di atas mengehadkan modul yang akan dibina, semua modul yang waf tahu akan
dibina.

Versi fail .ns3rc yang diselenggara dalam ns-3 repositori kod sumber berada di
yang utils direktori. Sebabnya adalah jika ia berada dalam direktori peringkat atasan
repositori, ia akan terdedah kepada daftar masuk secara tidak sengaja daripada penyelenggara yang membolehkan
modul yang ingin mereka gunakan. Oleh itu, pengguna perlu menyalin .ns3rc secara manual daripada fail
utils direktori ke tempat pilihan mereka (direktori peringkat atas atau direktori rumah mereka) ke
dayakan konfigurasi binaan modular yang berterusan.

Dengan mengandaikan bahawa anda berada di peringkat teratas ns-3 direktori, anda boleh mendapatkan salinan .ns3rc
fail yang ada dalam utils direktori seperti berikut:

$ cp utils/.ns3rc .

Fail .ns3rc kini sepatutnya berada di peringkat teratas anda ns-3 direktori, dan ia mengandungi
Berikut:

#! /usr/bin/env ular sawa

# Senarai modul yang akan didayakan apabila ns-3 dijalankan.
# Modul yang bergantung pada modul yang disenaraikan akan didayakan juga.
#
# Semua modul boleh didayakan dengan memilih 'all_modules'.
modul_didayakan = ['semua_modul']

# Tetapkan ini sama dengan benar jika anda mahu contoh dijalankan.
examples_enabled = Salah

# Tetapkan ini sama dengan benar jika anda mahu ujian dijalankan.
tests_enabled = Salah

Gunakan editor kegemaran anda untuk mengubah suai fail .ns3rc untuk mendayakan modul teras sahaja
contoh dan ujian seperti ini:

#! /usr/bin/env ular sawa

# Senarai modul yang akan didayakan apabila ns-3 dijalankan.
# Modul yang bergantung pada modul yang disenaraikan akan didayakan juga.
#
# Semua modul boleh didayakan dengan memilih 'all_modules'.
modules_enabled = ['teras']

# Tetapkan ini sama dengan benar jika anda mahu contoh dijalankan.
examples_enabled = Benar

# Tetapkan ini sama dengan benar jika anda mahu ujian dijalankan.
tests_enabled = Benar

Hanya modul teras akan didayakan sekarang jika anda mencuba arahan ini:

$ ./waf bersih
konfigurasi $ ./waf
$ ./waf binaan
$ cd build/debug/
$ls

dan perpustakaan berikut harus ada:

bindings libns3-core.so ns3 scratch utils
contoh libns3-core-test.so sampel src

Perhatikan ./waff membersihkan langkah dilakukan di sini hanya untuk menjadikannya lebih jelas perpustakaan modul mana
telah dibina. Anda tidak perlu buat ./waff membersihkan untuk membolehkan subset modul.

Menjalankan test.py akan menyebabkan hanya ujian yang bergantung pada teras modul dijalankan:

24 daripada 24 ujian lulus (24 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Ulangi langkah di atas untuk modul "rangkaian" dan bukannya modul "teras", dan
berikut akan dibina, kerana rangkaian bergantung pada teras:

bindings libns3-core.so libns3-network.so ns3 scratch utils
contoh libns3-core-test.so libns3-network-test.so sampel src

Menjalankan test.py akan menyebabkan ujian yang bergantung pada modul teras dan rangkaian sahaja
dijalankan:

31 daripada 31 ujian lulus (31 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Mendayakan / melumpuhkan ns-3 Ujian and Contoh
. ns-3 pengedaran termasuk banyak contoh dan ujian yang digunakan untuk mengesahkan ns-3
sistem. Pengguna, bagaimanapun, mungkin tidak selalu mahu contoh dan ujian ini dijalankan untuk mereka
pemasangan ns-3.

Bab ini membincangkan cara membina ns-3 dengan atau tanpa contoh dan ujiannya.

Cara kepada membolehkan melumpuhkan contoh and ujian in ns-3
Terdapat 3 cara untuk mendayakan/melumpuhkan contoh dan ujian masuk ns-3:

1. Menggunakan build.py apabila ns-3 dibina buat kali pertama

2. Menggunakan waf sekali ns-3 telah dibina

3. Menggunakan ns-3 fail konfigurasi sekali ns-3 telah dibina

Membolehkan melumpuhkan contoh and ujian menggunakan build.py
Anda boleh menggunakan build.py untuk mendayakan/melumpuhkan contoh dan ujian apabila ns-3 dibina untuk yang pertama
pada bila-bila masa.

Secara lalai, contoh dan ujian tidak terbina dalam ns-3.

Daripada direktori ns-3-allinone, anda boleh membina ns-3 tanpa sebarang contoh atau ujian semata-mata
dengan melakukan:

$ ./build.py

Menjalankan test.py di peringkat atas ns-3 direktori sekarang tidak akan menyebabkan tiada contoh atau ujian
lari:

0 daripada 0 ujian lulus (0 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Jika anda ingin membina ns-3 dengan contoh dan ujian, kemudian lakukan perkara berikut daripada
Direktori ns-3-allinone:

$ ./build.py --enable-examples --enable-tests

Menjalankan test.py di peringkat atas ns-3 direktori akan menyebabkan semua contoh dan ujian
untuk dijalankan:

170 daripada 170 ujian lulus (170 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Membolehkan melumpuhkan contoh and ujian menggunakan WAF
Anda boleh menggunakan waf untuk mendayakan/melumpuhkan contoh dan ujian sekali ns-3 telah dibina.

Secara lalai, contoh dan ujian tidak terbina dalam ns-3.

Dari peringkat atasan ns-3 direktori, anda boleh membina ns-3 tanpa sebarang contoh atau ujian semata-mata
dengan melakukan:

konfigurasi $ ./waf
$ ./waf binaan

Menjalankan test.py sekarang tidak akan menyebabkan tiada contoh atau ujian dijalankan:

0 daripada 0 ujian lulus (0 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Jika anda ingin membina ns-3 dengan contoh dan ujian, kemudian lakukan perkara berikut dari atas
tahap ns-3 direktori:

$ ./waf configure --enable-examples --enable-tests
$ ./waf binaan

Menjalankan test.py akan menyebabkan semua contoh dan ujian dijalankan:

170 daripada 170 ujian lulus (170 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Membolehkan melumpuhkan contoh and ujian menggunakan yang ns-3 konfigurasi fail
Fail konfigurasi, .ns3rc, telah ditambahkan pada ns-3 yang membolehkan pengguna menentukan sama ada
contoh dan ujian perlu dibina atau tidak. Anda boleh menggunakan fail ini untuk mendayakan/melumpuhkan
contoh dan ujian sekali ns-3 telah dibina.

Apabila mendayakan melumpuhkan contoh dan ujian, peraturan keutamaan adalah seperti berikut:

1. rentetan konfigurasi --enable-examples/--disable-examples mengatasi sebarang fail .ns3rc

2. rentetan konfigurasi --enable-tests/--disable-tests mengatasi sebarang fail .ns3rc

3. fail .ns3rc di peringkat atas ns-3 direktori dirujuk seterusnya, jika ada

4. sistem mencari ~/.ns3rc jika fail .ns3rc tidak ditemui dalam langkah sebelumnya

Jika tiada satu pun di atas wujud, maka contoh dan ujian tidak akan dibina.

Versi fail .ns3rc yang diselenggara dalam ns-3 repositori kod sumber berada di
yang utils direktori. Sebabnya adalah jika ia berada dalam direktori peringkat atasan
repositori, ia akan terdedah kepada daftar masuk secara tidak sengaja daripada penyelenggara yang membolehkan
modul yang ingin mereka gunakan. Oleh itu, pengguna perlu menyalin .ns3rc secara manual daripada fail
utils direktori ke tempat pilihan mereka (direktori peringkat atas atau direktori rumah mereka) ke
membolehkan pendayaan berterusan contoh dan ujian.

Dengan mengandaikan bahawa anda berada di peringkat teratas ns-3 direktori, anda boleh mendapatkan salinan .ns3rc
fail yang ada dalam utils direktori seperti berikut:

$ cp utils/.ns3rc .

Fail .ns3rc kini sepatutnya berada di peringkat teratas anda ns-3 direktori, dan ia mengandungi
Berikut:

#! /usr/bin/env ular sawa

# Senarai modul yang akan didayakan apabila ns-3 dijalankan.
# Modul yang bergantung pada modul yang disenaraikan akan didayakan juga.
#
# Semua modul boleh didayakan dengan memilih 'all_modules'.
modul_didayakan = ['semua_modul']

# Tetapkan ini sama dengan benar jika anda mahu contoh dijalankan.
examples_enabled = Salah

# Tetapkan ini sama dengan benar jika anda mahu ujian dijalankan.
tests_enabled = Salah

Dari peringkat atasan ns-3 direktori, anda boleh membina ns-3 tanpa sebarang contoh atau ujian semata-mata
dengan melakukan:

konfigurasi $ ./waf
$ ./waf binaan

Menjalankan test.py sekarang tidak akan menyebabkan tiada contoh atau ujian dijalankan:

0 daripada 0 ujian lulus (0 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Jika anda ingin membina ns-3 dengan contoh dan ujian, gunakan editor kegemaran anda untuk menukar
nilai dalam fail .ns3rc untuk fail examples_enabled dan tests_enabled adalah Benar:

#! /usr/bin/env ular sawa

# Senarai modul yang akan didayakan apabila ns-3 dijalankan.
# Modul yang bergantung pada modul yang disenaraikan akan didayakan juga.
#
# Semua modul boleh didayakan dengan memilih 'all_modules'.
modul_didayakan = ['semua_modul']

# Tetapkan ini sama dengan benar jika anda mahu contoh dijalankan.
examples_enabled = Benar

# Tetapkan ini sama dengan benar jika anda mahu ujian dijalankan.
tests_enabled = Benar

Dari peringkat atasan ns-3 direktori, anda boleh membina ns-3 dengan contoh dan ujian hanya dengan
melakukan:

konfigurasi $ ./waf
$ ./waf binaan

Menjalankan test.py akan menyebabkan semua contoh dan ujian dijalankan:

170 daripada 170 ujian lulus (170 lulus, 0 dilangkau, 0 gagal, 0 ranap, 0 ralat valgrind)

Penyelesaian masalah
Bab ini menyiarkan beberapa maklumat tentang kemungkinan ralat biasa dalam membina atau menjalankan
ns-3 program.

Sila ambil perhatian bahawa wiki (http://www.nsnam.org/wiki/Troubleshooting) mungkin telah menyumbang
barangan.

Membina kesilapan
Masa larian kesilapan
Kadangkala, ralat boleh berlaku dengan program selepas binaan yang berjaya. Ini adalah masa larian
ralat, dan biasanya boleh berlaku apabila memori rosak atau nilai penunjuk tidak dijangka
batal

Berikut ialah contoh perkara yang mungkin berlaku:

$ ./waf --run tcp-point-to-point
Memasuki direktori '/home/tomh/ns-3-nsc/build'
Penyusunan selesai dengan jayanya
Perintah ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] keluar dengan kod -11

Mesej ralat mengatakan bahawa program ditamatkan tidak berjaya, tetapi ia tidak jelas
daripada maklumat ini apa yang mungkin salah. Untuk memeriksa dengan lebih dekat, cuba jalankan di bawah
yang gdb penyahpepijat:

$ ./waf --run tcp-point-to-point --command-template="gdb %s"
Memasuki direktori '/home/tomh/ns-3-nsc/build'
Penyusunan selesai dengan jayanya
GNU gdb Red Hat Linux (6.3.0.0-1.134.fc5rh)
Hak Cipta 2004 Free Software Foundation, Inc.
GDB ialah perisian percuma, dilindungi oleh Lesen Awam Am GNU, dan anda
dialu-alukan untuk mengubahnya dan/atau mengedarkan salinannya di bawah syarat-syarat tertentu.
Taip "tunjukkan penyalinan" untuk melihat syarat.
Tiada jaminan sama sekali untuk GDB. Taip "tunjukkan jaminan" untuk butiran.
GDB ini telah dikonfigurasikan sebagai "i386-redhat-linux-gnu"...Menggunakan hos libthread_db
perpustakaan "/lib/libthread_db.so.1".

(gdb) lari
Memulakan program: /home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point
Membaca simbol daripada objek kongsi dibaca daripada memori sasaran...selesai.
Sistem yang dimuatkan membekalkan DSO pada 0xf5c000

Program menerima isyarat SIGSEGV, Segmentation fault.
0x0804aa12 dalam utama (argc=1, argv=0xbfdfefa4)
di ../examples/tcp-point-to-point.cc:136
136 Ptr localSocket = socketFactory->CreateSocket ();
(gdb) p localSocket
$1 = {m_ptr = 0x3c5d65}
(gdb) p socketFactory
$2 = {m_ptr = 0x0}
(gdb) berhenti
Program sedang berjalan. Keluar pula? (y atau n) y

Perhatikan dahulu cara atur cara digunakan-- luluskan arahan untuk dijalankan sebagai hujah kepada
templat arahan "gdb %s".

Ini memberitahu kita bahawa terdapat percubaan untuk membatalkan rujukan socketFactory penunjuk nol.

Mari lihat sekitar baris 136 tcp-point-to-point, seperti yang dicadangkan oleh gdb:

Ptr socketFactory = n2->GetObject (Tcp::iid);
Ptr localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();

Penyebabnya di sini ialah nilai pulangan GetObject tidak disemak dan mungkin
batal

Kadangkala anda mungkin perlu menggunakan valgrind memori pemeriksa untuk kesilapan yang lebih halus. sekali lagi,
anda menggunakan penggunaan valgrind dengan cara yang sama:

$ ./waf --run tcp-point-to-point --command-template="valgrind %s"

SUMBER


Dokumen ini ditulis dalam reStructuredText khususnya Sphinx dan dikekalkan dalam
dokumen/manual direktori kod sumber ns-3.

Gunakan ns-3-manual dalam talian menggunakan perkhidmatan onworks.net


Pelayan & Stesen Kerja Percuma

Muat turun apl Windows & Linux

Arahan Linux

Ad




×
Pengiklanan
❤ ️Beli, tempah atau beli di sini — tanpa kos, membantu memastikan perkhidmatan percuma.