InggrisPerancisSpanyol

favorit OnWorks

ns-3-manual - Online di Cloud

Jalankan ns-3-manual di penyedia hosting gratis OnWorks melalui Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS

Ini adalah perintah ns-3-manual yang dapat dijalankan di penyedia hosting gratis OnWorks menggunakan salah satu dari beberapa stasiun kerja online gratis kami seperti Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS

PROGRAM:

NAMA


ns-3-manual - ns-3 Panduan

Ini adalah ns-3 panduan. Dokumentasi utama untuk proyek ns-3 tersedia dalam lima
formulir:

· ns-3 Doksigen: Dokumentasi API publik dari simulator

· Tutorial, Panduan (ini dokumen), dan Perpustakaan Model untuk Terbaru melepaskan dan
pengembangan pohon

· ns-3 wiki

ISI


Organisasi
Bab ini menjelaskan secara keseluruhan ns-3 organisasi perangkat lunak dan yang sesuai
organisasi manual ini.

ns-3 adalah simulator jaringan peristiwa-diskrit di mana inti dan model simulasi berada
diimplementasikan dalam C++. ns-3 dibangun sebagai perpustakaan yang mungkin statis atau dinamis
ditautkan ke program utama C++ yang mendefinisikan topologi simulasi dan memulai
simulator. ns-3 juga mengekspor hampir semua API-nya ke Python, memungkinkan program Python untuk
mengimpor modul "ns3" dengan cara yang sama seperti ns-3 perpustakaan ditautkan oleh executable
dalam C++.
[image] Organisasi perangkat lunak dari ns-3.TIDAK INDENT

Kode sumber untuk ns-3 sebagian besar diselenggarakan di src direktori dan dapat dijelaskan
dengan diagram di Perangkat lunak organisasi of ns-3. Kami akan bekerja dengan cara kami dari bawah
ke atas; secara umum, modul hanya memiliki dependensi pada modul di bawahnya pada gambar.

Kami pertama-tama menjelaskan inti dari simulator; komponen-komponen yang umum di semua
protokol, perangkat keras, dan model lingkungan. Inti simulasi diimplementasikan dalam
src/inti. Paket adalah objek mendasar dalam simulator jaringan dan diimplementasikan dalam
src/jaringan. Kedua modul simulasi ini sendiri dimaksudkan untuk terdiri dari:
inti simulasi generik yang dapat digunakan oleh berbagai jenis jaringan, bukan hanya
jaringan berbasis internet. Modul di atas dari ns-3 tidak tergantung pada jaringan tertentu
dan model perangkat, yang tercakup dalam bagian selanjutnya dari manual ini.

Selain di atas ns-3 inti, kami perkenalkan, juga di bagian awal
manual, dua modul lain yang melengkapi API inti berbasis C++. ns-3 program mungkin
mengakses semua API secara langsung atau dapat menggunakan apa yang disebut penolong API yang menyediakan
pembungkus yang nyaman atau enkapsulasi panggilan API tingkat rendah. Fakta bahwa ns-3 program
dapat ditulis ke dua API (atau kombinasinya) adalah aspek mendasar dari
simulator. Kami juga menjelaskan bagaimana Python didukung di ns-3 sebelum pindah ke spesifik
model relevansi dengan simulasi jaringan.

Sisa dari manual ini difokuskan pada pendokumentasian model dan pendukungnya
kemampuan. Bagian selanjutnya berfokus pada dua objek mendasar dalam ns-3: Yang Node dan
Perangkat Bersih. Dua jenis NetDevice khusus dirancang untuk mendukung penggunaan emulasi jaringan
kasus, dan emulasi dijelaskan selanjutnya. Bab berikut dikhususkan untuk
Model terkait Internet, termasuk API soket yang digunakan oleh aplikasi Internet. Itu
bab berikutnya mencakup aplikasi, dan bab berikut menjelaskan dukungan tambahan
untuk simulasi, seperti animator dan statistik.

Proyek memelihara manual terpisah yang ditujukan untuk pengujian dan validasi ns-3 kode
(Lihat ns-3 pengujian dan Pengesahan panduan).

Acak Variabel
ns-3 berisi generator nomor pseudo-acak bawaan (PRNG). Penting untuk
pengguna serius simulator untuk memahami fungsionalitas, konfigurasi, dan penggunaan
PRNG ini, dan untuk memutuskan apakah itu cukup untuk penggunaan penelitiannya.

Cepat Ringkasan
ns-3 nomor acak disediakan melalui contoh ns3::Aliran Variabel Acak.

· secara default, ns-3 simulasi menggunakan benih tetap; jika ada keacakan di
simulasi, setiap menjalankan program akan menghasilkan hasil yang identik kecuali benih dan/atau
nomor lari diubah.

· di ns-3.3 dan sebelumnya, ns-3 simulasi menggunakan seed acak secara default; ini menandai
perubahan kebijakan dimulai dengan ns-3.4.

· di ns-3.14 dan sebelumnya, ns-3 simulasi menggunakan kelas pembungkus berbeda yang disebut
ns3::Variabel Acak. Pada ns-3.15, kelas ini telah digantikan oleh
ns3::Aliran Variabel Acak; generator nomor pseudo-acak yang mendasarinya belum
berubah.

· untuk mendapatkan keacakan di beberapa simulasi, Anda harus mengatur seed
berbeda atau atur nomor lari secara berbeda. Untuk mengatur benih, hubungi
ns3::RngSeedManager::SetSeed() di awal program; untuk mengatur nomor lari dengan
benih yang sama, sebut ns3::RngSeedManager::SetRun() di awal program; melihat
membuat acak variabel.

· setiap RandomVariableStream digunakan dalam ns-3 memiliki generator nomor acak virtual yang terkait
dengan itu; semua variabel acak menggunakan benih tetap atau acak berdasarkan penggunaan
benih global (peluru sebelumnya);

· jika Anda berniat untuk melakukan beberapa run dari skenario yang sama, dengan acak yang berbeda
nomor, pastikan untuk membaca bagian tentang cara melakukan replikasi independen:
membuat acak variabel.

Baca lebih lanjut untuk penjelasan lebih lanjut tentang fasilitas nomor acak untuk ns-3.

Latar Belakang
Simulasi menggunakan banyak angka acak; satu studi menemukan bahwa sebagian besar simulasi jaringan
menghabiskan sebanyak 50% dari CPU menghasilkan angka acak. Pengguna simulasi harus
berkaitan dengan kualitas angka acak (semu) dan independensi antara
aliran angka acak yang berbeda.

Pengguna perlu memperhatikan beberapa masalah, seperti:

· penyemaian generator nomor acak dan apakah hasil simulasi adalah
deterministik atau tidak,

· cara memperoleh aliran angka acak yang berbeda yang independen dari satu
lain, dan

· berapa lama waktu yang dibutuhkan aliran untuk berputar

Kami akan memperkenalkan beberapa istilah di sini: RNG menyediakan urutan panjang (semu) acak
angka. Panjang barisan ini disebut siklus panjangnya or periode, setelah itu
RNG akan berulang. Urutan ini dapat dipartisi menjadi disjoint stream. Sebuah
aliran RNG adalah subset atau blok yang berdekatan dari urutan RNG. Misalnya, jika
Periode RNG adalah panjang N, dan dua aliran disediakan dari RNG ini, lalu yang pertama
aliran mungkin menggunakan nilai N/2 pertama dan aliran kedua mungkin menghasilkan N/2 . kedua
nilai-nilai. Properti penting di sini adalah bahwa kedua aliran tidak berkorelasi. Juga,
setiap aliran dapat dipartisi secara terputus-putus ke sejumlah yang tidak berkorelasi anak sungai. itu
yang mendasari RNG diharapkan menghasilkan urutan angka pseudo-acak dengan sangat panjang
panjang siklus, dan membaginya menjadi aliran dan sub-aliran dengan cara yang efisien.

ns-3 menggunakan generator nomor acak yang sama seperti halnya ns-2: MRG32k3a
generator dari Pierre L'Ecuyer. Penjelasan rinci dapat ditemukan di
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf. Generator MRG32k3a
menyediakan 1.8x10^{19} aliran bilangan acak independen, yang masing-masing terdiri dari
2.3x10^{15} sub-aliran. Setiap substream memiliki periode (yaitu, banyaknya bilangan acak
sebelum tumpang tindih) sebesar 7.6x10^{22}. Periode seluruh generator adalah 3.1x10^{57}.

Kelas ns3::Aliran Variabel Acak adalah antarmuka publik ke nomor acak yang mendasari ini
generator. Saat pengguna membuat variabel acak baru (seperti ns3::Variabel Acak Seragam,
ns3::VariabelAcak Eksponensial, dll.), mereka membuat objek yang menggunakan salah satu dari
berbeda, aliran independen dari generator nomor acak. Oleh karena itu, setiap objek dari
mengetik ns3::Aliran Variabel Acak memiliki, secara konseptual, RNG "virtual" miliknya sendiri. Lebih-lebih lagi,
setiap ns3::Aliran Variabel Acak dapat dikonfigurasi untuk menggunakan salah satu set substream yang ditarik
dari arus utama.

Implementasi alternatif akan memungkinkan setiap RandomVariable memiliki sendiri
(diunggulkan berbeda) RNG. Namun, kami tidak dapat menjamin dengan kuat bahwa perbedaan
urutan akan berkorelasi dalam kasus seperti itu; karenanya, kami lebih suka menggunakan RNG tunggal dan
aliran dan sub-aliran darinya.

membuat acak variabel
ns-3 mendukung sejumlah objek variabel acak dari kelas dasar
Aliran Variabel Acak. Benda-benda tersebut berasal dari ns3::Objek dan ditangani oleh smart
pointer.

Cara yang benar untuk membuat objek ini adalah dengan menggunakan templated BuatObjek<> metode,
seperti:

Ptr x = Buat Objek ();

maka Anda dapat mengakses nilai dengan memanggil metode pada objek seperti:

myRandomNo = x->GetInteger();

Jika Anda mencoba melakukan sesuatu seperti ini:

myRandomNo = UniformRandomVariable().GetInteger();

program Anda akan mengalami kesalahan segmentasi, karena implementasinya bergantung pada
beberapa konstruksi atribut yang terjadi hanya ketika BuatObjek disebut.

Sebagian besar sisa bab ini sekarang membahas sifat-sifat aliran
angka pseudo-acak yang dihasilkan dari objek tersebut, dan bagaimana mengontrol penyemaian seperti itu
benda.

Penyemaian dan independen ulangan
ns-3 simulasi dapat dikonfigurasi untuk menghasilkan hasil deterministik atau acak. jika
ns-3 simulasi dikonfigurasi untuk menggunakan seed deterministik tetap dengan nomor run yang sama,
itu harus memberikan output yang sama setiap kali dijalankan.

Secara default, ns-3 simulasi menggunakan seed dan run number tetap. Nilai-nilai ini disimpan dalam
dua ns3::Nilai Global contoh: g_rngSeed dan g_rngRun.

Kasus penggunaan yang khas adalah menjalankan simulasi sebagai urutan percobaan independen, sehingga:
menghitung statistik pada sejumlah besar proses independen. Pengguna dapat mengubah
benih global dan jalankan kembali simulasi, atau dapat memajukan status substream RNG, yang
disebut sebagai penambahan nomor run.

Kelas ns3::RngSeedManager menyediakan API untuk mengontrol penyemaian dan menjalankan nomor
perilaku. Pengaturan status seeding dan substream ini harus dipanggil sebelum ada yang acak
variabel dibuat; misalnya:

RngSeedManager::SetSeed (3); // Mengubah seed dari default 1 menjadi 3
RngSeedManager::SetRun (7); // Mengubah nomor lari dari default 1 menjadi 7
// Sekarang, buat variabel acak
Ptr x = Buat Objek ();
Ptr y = BuatObjek ();
...

Mana yang lebih baik, menetapkan benih baru atau memajukan keadaan substream? Tidak ada
menjamin bahwa aliran yang dihasilkan oleh dua benih acak tidak akan tumpang tindih. Satu-satunya cara untuk
menjamin bahwa dua aliran tidak tumpang tindih adalah dengan menggunakan kemampuan sub-aliran yang disediakan oleh
pelaksanaan RNG. Oleh karena itu, menggunakan itu sub-aliran kemampuan untuk menghasilkan beberapa
independen berjalan of itu sama simulasi. Dengan kata lain, semakin ketat secara statistik
cara untuk mengonfigurasi beberapa ulangan independen adalah dengan menggunakan benih tetap dan memajukan
nomor lari. Implementasi ini memungkinkan maksimum 2.3x10^{15} independen
ulangan menggunakan substream.

Untuk kemudahan penggunaan, tidak perlu mengontrol seed dan run number dari dalam
program; pengguna dapat mengatur NS_GLOBAL_VALUE variabel lingkungan sebagai berikut:

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

Cara lain untuk mengontrol ini adalah dengan melewatkan argumen baris perintah; karena ini adalah ns-3
Contoh GlobalValue, itu sama dilakukan seperti berikut:

$ ./waf --command-template="%s --RngRun=3" --jalankan nama-program

atau, jika Anda menjalankan program langsung di luar waf:

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

Varian baris perintah di atas memudahkan menjalankan banyak operasi berbeda dari shell
skrip hanya dengan melewatkan indeks RngRun yang berbeda.

Kelas Aliran Variabel Acak
Semua variabel acak harus diturunkan dari kelas Variabel acak. Kelas dasar ini menyediakan
beberapa metode untuk mengonfigurasi perilaku generator bilangan acak secara global. Berasal dari
kelas menyediakan API untuk menggambar variasi acak dari distribusi tertentu
didukung.

Setiap RandomVariableStream yang dibuat dalam simulasi diberikan generator yang baru
RNGStream dari PRNG yang mendasarinya. Digunakan dengan cara ini, implementasi L'Ecuyer
memungkinkan maksimum 1.8x10^19 variabel acak. Setiap variabel acak dalam satu
replikasi dapat menghasilkan hingga 7.6x10^22 angka acak sebelum tumpang tindih.

Mendasarkan kelas publik API
Di bawah ini adalah kutipan beberapa metode publik kelas Aliran Variabel Acak yang mengakses
nilai berikutnya di substream.

/ **
* \brief Mengembalikan double acak dari distribusi yang mendasarinya
* \mengembalikan Nilai acak titik mengambang
*/
ganda GetValue (batal) const;

/ **
* \brief Mengembalikan bilangan bulat acak dari distribusi yang mendasarinya
* \return Integer cast dari ::GetValue()
*/
uint32_t GetInteger (batal) const;

Kami telah menjelaskan konfigurasi seeding di atas. Variabel Acak Berbeda
subclass mungkin memiliki API tambahan.

jenis of Variabel Acak
Jenis variabel acak berikut disediakan, dan didokumentasikan dalam: ns-3
Doxygen atau dengan membaca src/core/model/random-variable-stream.h. Pengguna juga dapat membuat
variabel acak kustom mereka sendiri dengan menurunkan dari kelas Aliran Variabel Acak.

· kelas SeragamAcakVariabel

· kelas VariabelAcak Konstan

· kelas SequentialRandomVariabel

· kelas VariabelAcak Eksponensial

· kelas ParetoVariabel Acak

· kelas WeibullVariabel Acak

· kelas VariabelAcak Normal

· kelas LogNormalAcakVariabel

· kelas VariabelAcak Gamma

· kelas VariabelAcak Erlang

· kelas SegitigaAcakVariabel

· kelas ZipfRandomVariabel

· kelas ZetaAcakVariabel

· kelas DeterministikAcakVariabel

· kelas VariabelAcak Empiris

Semantik of Aliran Variabel Acak objek
Objek RandomVariableStream berasal dari ns3::Objek dan ditangani oleh pointer pintar.

Instans RandomVariableStream juga dapat digunakan di ns-3 atribut, yang berarti bahwa
nilai dapat diatur untuk mereka melalui ns-3 sistem atribut. Contohnya ada di
model propagasi untuk WifiNetDevice:

TypeId
RandomPropagationDelayModel::GetTypeId (batal)
{
static TypeId tid = TypeId ("ns3::RandomPropagationDelayModel")
.SetInduk ()
.TambahkanKonstruktor ()
.AddAttribute ("Variabel",
"Variabel acak yang menghasilkan penundaan acak (s).",
StringValue ("ns3::UniformRandomVariable"),
MakePointerAccessor (&RandomPropagationDelayModel::m_variable),
MakePointerChecker ())
;
kembali tid;
}

Ini, ns-3 pengguna dapat mengubah variabel acak default untuk model penundaan ini (yaitu
UniformRandomVariable mulai dari 0 hingga 1) melalui sistem atribut.

Menggunakan lain PRNG
Saat ini tidak ada dukungan untuk mengganti nomor acak dasar yang berbeda
generator (misalnya, Perpustakaan Ilmiah GNU atau paket Akaroa). Patch dipersilakan.

Pengaturan itu aliran jumlah
Generator MRG32k3a yang mendasari menyediakan 2^64 aliran independen. Di ns-3, ini adalah
ditugaskan secara berurutan mulai dari aliran pertama sebagai instans RandomVariableStream baru
membuat panggilan pertama mereka ke GetValue().

Sebagai hasil dari bagaimana objek RandomVariableStream ini ditetapkan ke aliran yang mendasarinya,
penugasan sensitif terhadap gangguan konfigurasi simulasi. Itu
konsekuensinya adalah jika ada aspek konfigurasi simulasi yang diubah, pemetaan
RandomVariables ke aliran mungkin (atau mungkin tidak) berubah.

Sebagai contoh nyata, pengguna yang menjalankan studi perbandingan antara protokol perutean mungkin:
menemukan bahwa tindakan mengubah satu protokol perutean ke yang lain akan memperhatikan bahwa
pola mobilitas yang mendasarinya juga berubah.

Dimulai dengan ns-3.15, beberapa kontrol telah diberikan kepada pengguna untuk memungkinkan pengguna untuk
secara opsional, perbaiki penetapan objek RandomVariableStream yang dipilih ke yang mendasarinya
sungai. Ini adalah Aliran atribut, bagian dari kelas dasar RandomVariableStream.

Dengan mempartisi urutan aliran yang ada dari sebelumnya:

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

menjadi dua set berukuran sama:

<------------------------------------------------- ------------------------->
^ ^ ^ ^
| || |
aliran 0 aliran (2^63 - 1) aliran 2^63 aliran (2^64 - 1)
<- secara otomatis ditetapkan -----------><- ditetapkan oleh pengguna ----------------->

2^63 aliran pertama terus ditetapkan secara otomatis, sedangkan 2^63 terakhir adalah
indeks aliran yang diberikan mulai dari nol hingga 2^63-1.

Penetapan aliran ke nomor aliran tetap adalah opsional; contoh dari
RandomVariableStream yang tidak memiliki nilai aliran yang ditetapkan akan ditetapkan berikutnya
satu dari kumpulan aliran otomatis.

Untuk memperbaiki RandomVariableStream ke aliran dasar tertentu, tetapkan Aliran
atribut ke bilangan bulat non-negatif (nilai default -1 berarti nilai akan menjadi
dialokasikan secara otomatis).

Penerbitan Tujuan hasil
Saat Anda mempublikasikan hasil simulasi, bagian penting dari informasi konfigurasi yang Anda
harus selalu menyatakan adalah bagaimana Anda menggunakan generator nomor acak.

· benih apa yang Anda gunakan,

· RNG apa yang Anda gunakan jika bukan default,

· bagaimana lari independen dilakukan,

· untuk simulasi besar, bagaimana Anda memeriksa bahwa Anda tidak bersepeda.

Adalah kewajiban bagi peneliti untuk menerbitkan hasil untuk memasukkan informasi yang cukup untuk
memungkinkan orang lain untuk mereproduksi hasil nya. Peneliti juga berkewajiban untuk
meyakinkan diri sendiri bahwa angka acak yang digunakan valid secara statistik, dan untuk menyatakan
makalah mengapa kepercayaan seperti itu diasumsikan.

Kesimpulan
Mari kita tinjau hal-hal apa yang harus Anda lakukan saat membuat simulasi.

· Putuskan apakah Anda menjalankan dengan benih tetap atau benih acak; benih tetap adalah
bawaan,

· Putuskan bagaimana Anda akan mengelola replikasi independen, jika berlaku,

· Yakinkan diri Anda bahwa Anda tidak menggambar lebih banyak nilai acak daripada panjang siklus, jika
Anda menjalankan simulasi yang sangat panjang, dan

· Saat Anda menerbitkan, ikuti panduan di atas tentang mendokumentasikan penggunaan Anda secara acak
pembuat nomor.

Hash Fungsi
ns-3 menyediakan antarmuka generik untuk fungsi hash tujuan umum. Secara sederhana
penggunaan, fungsi hash mengembalikan hash 32-bit atau 64-bit dari buffer data atau string.
Fungsi hash default yang mendasarinya adalah gumam3, dipilih karena memiliki fungsi hash yang baik
properties dan menawarkan versi 64-bit. Yang Mulia FNV1a hash juga tersedia.

Ada mekanisme langsung untuk menambahkan (atau menyediakan saat run time) hash alternatif
implementasi fungsi.

Dasar penggunaan
Cara paling sederhana untuk mendapatkan nilai hash dari buffer data atau string adalah:

#sertakan "ns3/hash.h"

menggunakan namespace ns3;

karakter * penyangga = ...
ukuran_t buffer_size = ...

uint32_t buffer_hash = Hash32 ( buffer, buffer_size);

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

Fungsi yang setara didefinisikan untuk nilai hash 64-bit.

Tambahan Hashing
Dalam beberapa situasi ini berguna untuk menghitung hash dari beberapa buffer, seolah-olah mereka memiliki
telah bergabung bersama. (Misalnya, Anda mungkin menginginkan hash dari aliran paket, tetapi tidak
ingin merakit buffer tunggal dengan konten gabungan dari semua paket.)

Ini hampir sama lurusnya dengan contoh pertama:

#sertakan "ns3/hash.h"

menggunakan namespace ns3;

karakter * penyangga;
ukuran_t ukuran_buffer;

hasher hasher; // Gunakan fungsi hash default

untuk ( )
{
buffer = get_next_buffer();
hasher (buffer, buffer_size);
}
uint32_t gabungan_hash = hasher.GetHash32();

Secara default Penggiling daging mempertahankan keadaan internal untuk mengaktifkan hashing tambahan. Jika Anda menghendaki
menggunakan kembali Penggiling daging objek (misalnya karena dikonfigurasi dengan hash non-default
function), tetapi tidak ingin menambahkan hash yang dihitung sebelumnya, Anda perlu bersih()
pertama:

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

Ini menginisialisasi ulang keadaan internal sebelum melakukan hashing pada buffer.

Menggunakan an Alternatif Hash fungsi
Fungsi hash default adalah gumam3. FNV1a juga tersedia. Untuk menentukan hash
berfungsi secara eksplisit, gunakan konstruktor ini:

Hasher hasher = Hasher ( Buat () );

Menambahkan New Hash fungsi Implementasi
Untuk menambahkan fungsi hash foo, ikuti hash-murmur3.h/Cc. pola:

· Buat deklarasi kelas (.h) dan definisi (Cc.) mewarisi dari
Hash::Implementasi.

· memasukkan deklarasi di hash.h (pada titik di mana hash-murmur3.h disertakan.

· Dalam kode Anda sendiri, buat contoh a Penggiling daging objek melalui konstruktor Penggiling daging
(Ptr ())

Jika fungsi hash Anda adalah fungsi tunggal, mis hashf, Anda bahkan tidak perlu membuat
kelas baru yang berasal dari HashImplementation:

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

Agar ini dapat dikompilasi, Anda hashf harus cocok dengan 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 untuk Hash Fungsi
Sumber untuk implementasi fungsi hash lainnya meliputi:

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

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

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

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

Kegiatan dan simulator
ns-3 adalah simulator jaringan peristiwa-diskrit. Secara konseptual, simulator melacak a
jumlah kejadian yang dijadwalkan untuk dieksekusi pada waktu simulasi yang ditentukan. pekerjaan dari
simulator adalah untuk mengeksekusi peristiwa dalam urutan waktu berurutan. Setelah selesai
suatu peristiwa terjadi, simulator akan pindah ke peristiwa berikutnya (atau akan keluar jika tidak ada
lebih banyak acara dalam antrian acara). Jika, misalnya, acara yang dijadwalkan untuk waktu simulasi
"100 detik" dijalankan, dan acara berikutnya tidak dijadwalkan hingga "200 detik", the
simulator akan segera melompat dari 100 detik menjadi 200 detik (waktu simulasi) ke
melaksanakan acara berikutnya. Inilah yang dimaksud dengan simulator "discrete-event".

Untuk mewujudkan semua ini, simulator membutuhkan beberapa hal:

1. objek simulator yang dapat mengakses antrian acara tempat acara disimpan dan yang dapat
mengelola pelaksanaan acara

2. penjadwal yang bertanggung jawab untuk memasukkan dan menghapus acara dari antrian

3. cara untuk merepresentasikan waktu simulasi

4. peristiwa itu sendiri

Bab manual ini menjelaskan objek dasar ini (simulator, scheduler,
waktu, peristiwa) dan bagaimana mereka digunakan.

Acara
Untuk be selesai

simulator
Kelas Simulator adalah titik masuk publik untuk mengakses fasilitas penjadwalan acara. Sekali
beberapa acara telah dijadwalkan untuk memulai simulasi, pengguna dapat mulai
jalankan dengan memasukkan loop utama simulator (panggil Simulator::Lari). Setelah loop utama
mulai berjalan, itu akan secara berurutan menjalankan semua acara terjadwal dalam urutan dari yang terlama hingga
terbaru sampai tidak ada lagi acara yang tersisa di antrean acara atau
Simulator::Stop telah dipanggil.

Untuk menjadwalkan acara untuk dieksekusi oleh loop utama simulator, kelas Simulator menyediakan
Keluarga fungsi Simulator::Jadwal*.

1. Menangani event handler dengan tanda tangan yang berbeda

Fungsi-fungsi ini dideklarasikan dan diimplementasikan sebagai template C++ untuk menangani secara otomatis
berbagai macam tanda tangan event handler C++ yang digunakan di alam liar. Misalnya, untuk menjadwalkan
untuk mengeksekusi 10 detik di masa mendatang, dan memanggil metode atau fungsi C++ dengan
argumen tertentu, Anda dapat menulis ini:

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

Simulator::Jadwal(Detik(10), &penangan, 10, 5);

Yang akan menghasilkan:

handler dipanggil dengan argumen arg0=10 dan arg1=5

Tentu saja, template C++ ini juga dapat menangani metode anggota secara transparan di C++
benda:

Untuk be lengkap: anggota metode contoh

Catatan:

· Metode Jadwal ns-3 mengenali fungsi dan metode secara otomatis hanya jika mereka
mengambil kurang dari 5 argumen. Jika Anda membutuhkannya untuk mendukung lebih banyak argumen, silakan ajukan
laporan bug.

· Pembaca yang akrab dengan istilah 'fungsi yang terikat penuh' akan mengenali
Simulator::Jadwalkan metode sebagai cara untuk membuat objek tersebut secara otomatis.

2. Operasi penjadwalan umum

Simulator API dirancang untuk membuatnya sangat mudah untuk menjadwalkan sebagian besar acara. Dia
menyediakan tiga varian untuk melakukannya (diurutkan dari yang paling sering digunakan hingga yang paling jarang digunakan):

· Jadwalkan metode yang memungkinkan Anda menjadwalkan acara di masa mendatang dengan menyediakan
penundaan antara waktu simulasi saat ini dan tanggal kedaluwarsa acara target.

· Metode ScheduleNow yang memungkinkan Anda menjadwalkan acara untuk simulasi saat ini
waktu: mereka akan mengeksekusi _setelah_ acara saat ini selesai dijalankan tetapi _sebelum_
waktu simulasi diubah untuk acara berikutnya.

· Metode ScheduleDestroy yang memungkinkan Anda untuk menghubungkan proses shutdown Simulator
untuk membersihkan sumber daya simulasi: setiap acara 'hancurkan' dijalankan saat pengguna menelepon
Simulator::Destroy metode.

3. Mempertahankan konteks simulasi

Ada dua cara dasar untuk menjadwalkan acara, dengan dan tanpa konteks. Apa ini?
artinya?

Simulator::Jadwal (Waktu & waktu const, MEM mem_ptr, OBJ obj);

vs

Simulator::ScheduleWithContext (konteks uint32_t, Waktu & waktu const, MEM mem_ptr, OBJ obj);

Pembaca yang menginvestasikan waktu dan tenaga dalam mengembangkan atau menggunakan model simulasi non-sepele
akan mengetahui nilai kerangka kerja logging ns-3 untuk men-debug simulasi sederhana dan kompleks
sama. Salah satu fitur penting yang disediakan oleh kerangka kerja logging ini adalah
tampilan otomatis id simpul jaringan yang terkait dengan acara yang 'saat ini' berjalan.

Id node dari node jaringan yang sedang dieksekusi sebenarnya dilacak oleh Simulator
kelas. Itu dapat diakses dengan Simulator::GetContext metode yang mengembalikan
'konteks' (bilangan bulat 32-bit) yang terkait dan disimpan dalam acara yang sedang dijalankan. Di
beberapa kasus yang jarang terjadi, ketika suatu peristiwa tidak terkait dengan node jaringan tertentu, itu
'konteks' diatur ke 0xffffffff.

Untuk mengaitkan konteks ke setiap acara, metode Schedule, dan ScheduleNow secara otomatis
menggunakan kembali konteks acara yang sedang dijalankan sebagai konteks acara yang dijadwalkan
untuk eksekusi nanti.

Dalam beberapa kasus, terutama ketika mensimulasikan transmisi paket dari sebuah node ke
lain, perilaku ini tidak diinginkan karena konteks yang diharapkan dari acara resepsi adalah
node penerima, bukan node pengirim. Untuk menghindari masalah ini, Simulator
class menyediakan metode jadwal khusus: ScheduleWithContext yang memungkinkan seseorang untuk menyediakan
secara eksplisit id node dari node penerima yang terkait dengan acara penerima.

XXX: kode contoh

Dalam beberapa kasus yang sangat jarang terjadi, pengembang mungkin perlu memodifikasi atau memahami bagaimana konteksnya
(node ​​id) dari event pertama disetel ke node terkait. Ini tercapai
oleh kelas NodeList: setiap kali simpul baru dibuat, kelas NodeList menggunakan
ScheduleWithContext untuk menjadwalkan acara 'menginisialisasi' untuk node ini. Acara 'inisialisasi'
dengan demikian dieksekusi dengan konteks yang disetel ke id simpul dan dapat menggunakan variasi normal dari
Metode jadwal. Itu memanggil metode Node::Initialize yang menyebarkan 'inisialisasi'
event dengan memanggil metode DoInitialize untuk setiap objek yang terkait dengan node. Itu
Metode DoInitialize diganti di beberapa objek ini (terutama di Aplikasi
kelas dasar) akan menjadwalkan beberapa acara (terutama Application::StartApplication) yang
pada gilirannya akan menjadwalkan acara pembuatan lalu lintas yang pada gilirannya akan menjadwalkan
peristiwa tingkat jaringan.

Catatan:

· Pengguna harus berhati-hati untuk menyebarkan metode DoInitialize di seluruh objek dengan memanggil
Inisialisasi secara eksplisit pada objek anggotanya

· Id konteks yang terkait dengan setiap metode ScheduleWithContext memiliki kegunaan lain di luar
logging: digunakan oleh cabang eksperimental ns-3 untuk melakukan simulasi paralel pada
sistem multicore menggunakan multithreading.

Simulator::* fungsi tidak tahu apa konteksnya: mereka hanya memastikan bahwa
konteks apa pun yang Anda tentukan dengan ScheduleWithContext tersedia saat yang sesuai
acara dijalankan dengan ::GetContext.

Terserah model yang diterapkan di atas Simulator::* untuk menafsirkan nilai konteks.
Dalam ns-3, model jaringan menafsirkan konteks sebagai id simpul dari simpul yang
dihasilkan suatu peristiwa. Inilah mengapa penting untuk memanggil ScheduleWithContext di
ns3::Subkelas saluran karena kami membuat acara dari simpul i ke simpul j dan kami
ingin memastikan bahwa acara yang akan berjalan pada simpul j memiliki konteks yang tepat.

Waktu
Untuk be selesai

Penjadwal
Untuk be selesai

Telepon balik
Beberapa pengguna baru untuk ns-3 tidak terbiasa dengan idiom pemrograman yang digunakan secara luas digunakan
seluruh kode: the ns-3 Telepon kembali. Bab ini memberikan beberapa motivasi tentang
callback, panduan cara menggunakannya, dan detail implementasinya.

Telepon balik Motivasi
Pertimbangkan bahwa Anda memiliki dua model simulasi A dan B, dan Anda ingin mereka lulus
informasi di antara mereka selama simulasi. Salah satu cara yang dapat Anda lakukan adalah Anda
dapat membuat A dan B masing-masing secara eksplisit mengetahui yang lain, sehingga mereka dapat memanggil
metode satu sama lain:

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

(dalam file sumber lain :)

kelas B {
publik:
void DoSomething (batal);
...

pribadi:
A* a_instance; // pointer ke A
}

membatalkan
B::Melakukan Sesuatu()
{
// Beri tahu a_instance bahwa sesuatu telah terjadi
a_instance->ReceiveInput ( // parameter);
...
}

Ini tentu berhasil, tetapi memiliki kelemahan yang memperkenalkan ketergantungan pada A dan B
untuk mengetahui tentang yang lain pada waktu kompilasi (ini membuat lebih sulit untuk memiliki yang independen
unit kompilasi dalam simulator) dan tidak digeneralisasi; jika dalam skenario penggunaan selanjutnya,
B perlu berbicara dengan objek C yang sama sekali berbeda, kode sumber untuk B harus
diubah untuk menambahkan c_instance Dan seterusnya. Sangat mudah untuk melihat bahwa ini adalah kekuatan kasar
mekanisme komunikasi yang dapat menyebabkan cacat pemrograman dalam model.

Ini bukan untuk mengatakan bahwa objek tidak boleh tahu satu sama lain jika ada hard
ketergantungan di antara mereka, tetapi seringkali model dapat dibuat lebih fleksibel jika
interaksi kurang dibatasi pada waktu kompilasi.

Ini bukan masalah abstrak untuk penelitian simulasi jaringan, melainkan telah menjadi
sumber masalah di simulator sebelumnya, ketika peneliti ingin memperluas atau memodifikasi
sistem untuk melakukan hal-hal yang berbeda (seperti yang cenderung dilakukan dalam penelitian). Pertimbangkan, misalnya,
pengguna yang ingin menambahkan sublapisan protokol keamanan IPsec antara TCP dan IP:

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

Jika simulator telah membuat asumsi, dan kode keras ke dalam kode, IP itu selalu berbicara
ke protokol transport di atas, pengguna mungkin terpaksa meretas sistem untuk mendapatkan
interkoneksi yang diinginkan. Ini jelas bukan cara yang optimal untuk mendesain generik
simulator.

Telepon balik Latar Belakang
CATATAN:
Pembaca yang akrab dengan panggilan balik pemrograman dapat melewati bagian tutorial ini.

Mekanisme dasar yang memungkinkan seseorang untuk mengatasi masalah di atas dikenal sebagai Telepon kembali.
Tujuan utamanya adalah mengizinkan satu bagian kode untuk memanggil fungsi (atau metode dalam C++)
tanpa ketergantungan antar-modul tertentu.

Ini pada akhirnya berarti Anda memerlukan semacam tipuan -- Anda memperlakukan alamat dari
disebut fungsi sebagai variabel. Variabel ini disebut variabel pointer-ke-fungsi.
Hubungan antara fungsi dan pointer-ke-fungsi benar-benar tidak berbeda
bahwa dari objek dan pointer-to-objek.

Dalam C contoh kanonik dari pointer-to-function adalah a
pointer-to-function-returning-integer (PFI). Untuk PFI yang mengambil satu parameter int, ini
dapat dinyatakan seperti,:

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

Apa yang Anda dapatkan dari ini adalah variabel bernama sederhana pfi yang diinisialisasi ke nilai 0.
Jika Anda ingin menginisialisasi penunjuk ini ke sesuatu yang berarti, Anda harus memiliki a
fungsi dengan tanda tangan yang cocok. Pada kasus ini:

int Fungsiku (int arg) {}

Jika Anda memiliki target ini, Anda dapat menginisialisasi variabel untuk menunjuk ke fungsi Anda seperti:

pfi = Fungsi Saya;

Anda kemudian dapat memanggil MyFunction secara tidak langsung menggunakan bentuk panggilan yang lebih sugestif:

int hasil = (*pfi) (1234);

Ini sugestif karena sepertinya Anda hanya mereferensikan pointer fungsi
seperti Anda akan mereferensikan pointer apa pun. Biasanya, bagaimanapun, orang mengambil keuntungan dari
fakta bahwa kompiler tahu apa yang sedang terjadi dan hanya akan menggunakan formulir yang lebih pendek:

int hasil = pfi (1234);

Perhatikan bahwa penunjuk fungsi mematuhi semantik nilai, sehingga Anda dapat menyebarkannya seperti apa pun
nilai lainnya. Biasanya, ketika Anda menggunakan antarmuka asinkron, Anda akan melewati beberapa entitas
seperti ini ke fungsi yang akan melakukan tindakan dan panggilan kembali untuk memberi tahu Anda
lengkap. Itu memanggil kembali dengan mengikuti tipuan dan menjalankan fungsi yang disediakan.

Di C++ Anda memiliki kompleksitas objek tambahan. Analogi dengan PFI di atas berarti Anda
memiliki pointer ke fungsi anggota yang mengembalikan int (PMI) alih-alih pointer ke
fungsi mengembalikan sebuah int (PFI).

Deklarasi variabel yang memberikan tipuan hanya terlihat sedikit berbeda:

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

Ini mendeklarasikan variabel bernama pmi seperti contoh sebelumnya mendeklarasikan variabel bernama
pfi. Karena keinginan untuk memanggil metode turunan dari kelas tertentu, seseorang harus
mendeklarasikan metode itu di kelas:

kelas Kelasku {
publik:
int Metode Saya (int arg);
};

Mengingat deklarasi kelas ini, seseorang kemudian akan menginisialisasi variabel itu seperti ini:

pmi = &KelasSaya::Metode Saya;

Ini memberikan alamat kode yang mengimplementasikan metode ke variabel, menyelesaikan
tipuan itu. Untuk memanggil suatu metode, kode tersebut membutuhkan a ini penunjuk. Ini, pada gilirannya,
berarti harus ada objek MyClass untuk dirujuk. Contoh sederhana dari ini adalah
memanggil metode secara tidak langsung (pikirkan fungsi virtual):

int (Kelas Saya::*pmi) (int arg) = 0; // Deklarasikan PMI
pmi = &KelasSaya::Metode Saya; // Arahkan ke kode implementasi

KelaskuKelasku; // Butuh turunan dari kelas
(Kelasku.*pmi) (1234); // Panggil metode dengan objek ptr

Sama seperti pada contoh C, Anda dapat menggunakan ini dalam panggilan asinkron ke modul lain
yang akan panggilan kembali menggunakan metode dan penunjuk objek. Ekstensi langsung
satu mungkin mempertimbangkan adalah untuk melewati pointer ke objek dan variabel PMI. Modul
hanya akan melakukan:

(*objekPtr.*pmi) (1234);

untuk menjalankan panggilan balik pada objek yang diinginkan.

Seseorang mungkin bertanya saat ini, apa itu titik? Modul yang dipanggil harus mengerti
jenis konkret dari objek panggilan untuk melakukan panggilan balik dengan benar. Kenapa tidak
terima saja ini, berikan penunjuk objek yang diketik dengan benar dan lakukan objek->metode(1234) in
kode alih-alih panggilan balik? Inilah tepatnya masalah yang dijelaskan di atas. Apa
diperlukan adalah cara untuk memisahkan fungsi panggilan dari kelas yang dipanggil sepenuhnya. Ini
kebutuhan menyebabkan perkembangan fungsi.

Functor adalah hasil dari sesuatu yang ditemukan pada tahun 1960-an yang disebut penutupan. Dia
pada dasarnya hanya panggilan fungsi yang dikemas, mungkin dengan beberapa status.

Functor memiliki dua bagian, bagian khusus dan bagian umum, yang terkait melalui pewarisan.
Kode panggilan (kode yang mengeksekusi panggilan balik) akan mengeksekusi kelebihan beban umum
operator () dari functor generik untuk menyebabkan panggilan balik dipanggil. Kode yang disebut (
kode yang ingin dipanggil kembali) harus menyediakan implementasi khusus dari
itu operator () yang melakukan pekerjaan khusus kelas yang menyebabkan penggabungan-dekat
masalah di atas.

Dengan functor spesifik dan kelebihan bebannya operator () dibuat, kode yang disebut kemudian
memberikan kode khusus ke modul yang akan menjalankan panggilan balik (panggilan
kode).

Kode panggilan akan menggunakan fungsi umum sebagai parameter, jadi pemeran implisit selesai
dalam pemanggilan fungsi untuk mengonversi functor tertentu ke functor generik. Ini berarti
bahwa modul pemanggil hanya perlu memahami tipe functor generik. Itu dipisahkan
dari kode panggilan sepenuhnya.

Informasi yang dibutuhkan seseorang untuk membuat functor tertentu adalah penunjuk objek dan
alamat pointer-to-method.

Inti dari apa yang perlu terjadi adalah bahwa sistem mendeklarasikan bagian generik dari
fungsi:

templat
kelas functor
{
publik:
operator int virtual() (T arg) = 0;
};

Penelepon mendefinisikan bagian tertentu dari functor yang benar-benar ada untuk diimplementasikan
spesifik operator() Metode:

templat
class SpecificFunctor : public Functor
{
publik:
Fungsi Khusus(T* p, int (T::*_pmi)(ARG arg))
{
m_p = hal;
m_pmi = _pmi;
}

operator int virtual() (ARG arg)
{
(*m_p.*m_pmi)(arg);
}
pribadi:
int (T::*m_pmi)(ARG arg);
T* m_p;
};

Berikut adalah contoh penggunaannya:

kelas A
{
publik:
A (ke dalam a0): a (a0) {}
int Halo (int b0)
{
std::cout << "Halo dari A, a = " << a << " b0 = " << b0 << std::endl;
}
int a;
};

int main ()
{
A a(10);
Fungsi tertentu sf(&a, &A::Halo);
sf(5);
}

CATATAN:
Kode sebelumnya bukan kode ns-3 asli. Ini adalah contoh kode sederhana yang hanya digunakan untuk
mengilustrasikan konsep yang terlibat dan untuk membantu Anda lebih memahami sistem. Tidak
berharap untuk menemukan kode ini di mana saja di pohon ns-3.

Perhatikan bahwa ada dua variabel yang didefinisikan dalam kelas di atas. Variabel m_p adalah
penunjuk objek dan m_pmi adalah variabel yang berisi alamat fungsi untuk
menjalankan.

Perhatikan bahwa ketika operator() dipanggil, itu pada gilirannya memanggil metode yang disediakan dengan
penunjuk objek menggunakan sintaks C++ PMI.

Untuk menggunakan ini, seseorang kemudian dapat mendeklarasikan beberapa kode model yang menggunakan functor generik sebagai
parameter:

batal LibraryFunction (Functor functor);

Kode yang akan berbicara dengan model akan membangun functor tertentu dan meneruskannya ke
PerpustakaanFungsi:

KelaskuKelasku;
Fungsi tertentu functor (&kelasku, Kelasku::Metodeku);

Ketika PerpustakaanFungsi selesai, itu mengeksekusi panggilan balik menggunakan operator() secara umum
functor itu diteruskan, dan dalam kasus khusus ini, memberikan argumen integer:

membatalkan
Fungsi Perpustakaan (Fungsi Fungsi)
{
// Jalankan fungsi perpustakaan
fungsi(1234);
}

Perhatikan bahwa PerpustakaanFungsi benar-benar dipisahkan dari jenis klien tertentu.
Koneksi dibuat melalui polimorfisme Functor.

API Panggilan Balik di ns-3 mengimplementasikan callback berorientasi objek menggunakan mekanisme functor.
API panggilan balik ini, yang didasarkan pada template C++, aman untuk tipe; yaitu, ia melakukan statis
ketik pemeriksaan untuk menegakkan kompatibilitas tanda tangan yang tepat antara penelepon dan penerima panggilan. Dia
oleh karena itu lebih aman untuk digunakan daripada pointer fungsi tradisional, tetapi sintaksnya mungkin
terlihat mengesankan pada awalnya. Bagian ini dirancang untuk memandu Anda melalui sistem Callback
sehingga Anda bisa nyaman menggunakannya di ns-3.

Menggunakan itu Callback API
Callback API cukup minim, hanya menyediakan dua layanan:

1. deklarasi tipe panggilan balik: cara untuk mendeklarasikan tipe panggilan balik dengan tanda tangan yang diberikan,
dan,

2. instantiasi panggilan balik: cara untuk membuat instance panggilan balik penerusan yang dihasilkan template
yang dapat meneruskan panggilan apa pun ke metode anggota kelas C++ lain atau fungsi C++.

Ini paling baik diamati melalui berjalan melalui contoh, berdasarkan sampel/main-callback.cc.

Menggunakan itu Callback API dengan statis fungsi
Pertimbangkan sebuah fungsi:

ganda statis
CbOne (ganda a, ganda b)
{
std::cout << "panggil cbOne a=" << a << ", b=" << b << std::endl;
kembalikan;
}

Pertimbangkan juga cuplikan program utama berikut:

int utama (int argc, char *argv[])
{
// tipe pengembalian: ganda
// tipe argumen pertama: double
// tipe argumen kedua: double
panggilan balik satu;
}

Ini adalah contoh panggilan balik gaya-C -- yang tidak menyertakan atau memerlukan ini
penunjuk. Templat fungsi Callback pada dasarnya adalah deklarasi variabel
berisi pointer-to-fungsi. Dalam contoh di atas, kami secara eksplisit menunjukkan pointer
ke fungsi yang mengembalikan bilangan bulat dan mengambil satu bilangan bulat sebagai parameter, The
Callback fungsi template adalah versi generik dari itu -- digunakan untuk mendeklarasikan tipe
dari panggilan balik.

CATATAN:
Pembaca yang tidak terbiasa dengan template C++ dapat berkonsultasi
http://www.cplusplus.com/doc/tutorial/templates/.

Callback template memerlukan satu argumen wajib (tipe pengembalian fungsi ke
ditugaskan ke panggilan balik ini) dan hingga lima argumen opsional, yang masing-masing menentukan
jenis argumen (jika fungsi panggilan balik khusus Anda memiliki lebih dari lima argumen,
maka ini dapat ditangani dengan memperluas implementasi panggilan balik).

Jadi dalam contoh di atas, kami memiliki panggilan balik yang dideklarasikan bernama "satu" yang pada akhirnya akan
memegang penunjuk fungsi. Tanda tangan dari fungsi yang akan dipegangnya harus kembali
ganda dan harus mendukung dua argumen ganda. Jika seseorang mencoba untuk melewatkan fungsi yang
tanda tangan tidak cocok dengan panggilan balik yang dideklarasikan, kesalahan kompilasi akan terjadi. Juga, jika
seseorang mencoba untuk menetapkan panggilan balik yang tidak kompatibel, kompilasi akan berhasil tetapi a
run-time NS_FATAL_ERROR akan dinaikkan. Contoh program
src/core/examples/main-callback.cc menunjukkan kedua kasus kesalahan ini di akhir
itu utama() program.

Sekarang, kita perlu menyatukan instance panggilan balik ini dan fungsi target yang sebenarnya
(CbOne). Perhatikan di atas bahwa CbOne memiliki tipe tanda tangan fungsi yang sama dengan panggilan balik--
ini penting. Kami dapat meneruskan fungsi yang diketik dengan benar ke panggilan balik ini.
Mari kita lihat ini lebih dekat:

CbOne ganda statis (ganda a, ganda b) {}
^ ^ ^
| | |
| | |
panggilan balik satu;

Anda hanya dapat mengikat fungsi ke panggilan balik jika mereka memiliki tanda tangan yang cocok. Pertama
argumen templat adalah tipe pengembalian, dan argumen templat tambahan adalah tipenya
argumen dari tanda tangan fungsi.

Sekarang, mari kita ikat panggilan balik kita "satu" ke fungsi yang cocok dengan tanda tangannya:

// membangun instance panggilan balik yang menunjuk ke fungsi cbOne
satu = MakeCallback (&CbOne);

Panggilan ini untuk Lakukan Panggilan Balik adalah, pada dasarnya, menciptakan salah satu fungsi khusus
disebutkan di atas. Variabel yang dideklarasikan menggunakan Callback fungsi template akan menjadi
akan memainkan bagian dari functor generik. Tugas satu = Lakukan Panggilan Balik (&CbOne) is
pemeran yang mengubah functor khusus yang dikenal oleh callee menjadi functor generik
diketahui oleh penelepon.

Kemudian nanti di program, jika diperlukan callback, dapat digunakan sebagai berikut:

NS_ASSERT (!one.IsNull());

// memanggil fungsi cbOne melalui instance callback
retOne ganda;
retOne = satu (10.0, 20.0);

Cek untuk ApakahNull() memastikan bahwa panggilan balik tidak nol -- bahwa ada fungsi
untuk memanggil di balik panggilan balik ini. Kemudian, satu() mengeksekusi generik operator() yang sebenarnya
kelebihan beban dengan implementasi spesifik dari operator() dan mengembalikan hasil yang sama seperti jika
CbOne() telah dipanggil langsung.

Menggunakan itu Callback API dengan anggota fungsi
Umumnya, Anda tidak akan memanggil fungsi statis melainkan fungsi anggota publik dari
Sebuah Objek. Dalam hal ini, argumen tambahan diperlukan untuk fungsi MakeCallback, untuk
memberi tahu sistem tentang objek mana fungsi tersebut harus dipanggil. Perhatikan contoh ini,
juga dari main-callback.cc:

kelas MyCb {
publik:
int CbTwo (ganda a) {
std::cout << "panggil cbTwo a=" << a << std::endl;
kembali -5;
}
};

int utama()
{
...
// tipe kembalian: int
// tipe argumen pertama: double
panggilan balik dua;
MyCb cb;
// membangun instance panggilan balik yang menunjuk ke MyCb::cbTwo
two = MakeCallback (&MyCb::CbTwo, &cb);
...
}

Di sini, kami memberikan pointer objek tambahan ke Lakukan Panggilan Balik<> fungsi. Ingat dari
bagian latar belakang di atas itu Operator() akan menggunakan pointer ke sintaks anggota ketika itu
dijalankan pada objek:

operator int virtual() (ARG arg)
{
(*m_p.*m_pmi)(arg);
}

Jadi kami perlu menyediakan dua variabel (m_p dan m_pmi) ketika kami membuat spesifik
fungsi. Garis:

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

melakukan hal itu dengan tepat. Dalam hal ini, ketika dua () dipanggil:

int hasil = dua (1.0);

akan menghasilkan panggilan ke CbDua fungsi anggota (metode) pada objek yang ditunjuk oleh
&cb.

Bangunan Null Telepon balik
Dimungkinkan untuk panggilan balik menjadi nol; oleh karena itu mungkin bijaksana untuk memeriksa sebelum menggunakannya.
Ada konstruksi khusus untuk panggilan balik nol, yang lebih disukai daripada sekadar lewat
"0" sebagai argumen; ini adalah MakeNullCallback<> membangun:

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

Meminta panggilan balik nol sama seperti memanggil penunjuk fungsi nol: itu akan macet di
waktu berjalan.

Terikat Telepon balik
Perpanjangan yang sangat berguna untuk konsep functor adalah dari Bound Callback. Sebelumnya itu
disebutkan bahwa penutupan pada awalnya adalah panggilan fungsi yang dikemas untuk nanti
eksekusi. Perhatikan bahwa dalam semua deskripsi Panggilan Balik di atas, tidak ada cara untuk
mengemas parameter apa pun untuk digunakan nanti -- saat Callback disebut melalui operator().
Semua parameter disediakan oleh fungsi panggilan.

Bagaimana jika diinginkan untuk mengizinkan fungsi klien (yang menyediakan panggilan balik) untuk
memberikan beberapa parameter? Alexandrescu memanggil proses yang memungkinkan klien untuk
tentukan salah satu parameter "mengikat". Salah satu parameter dari operator() telah
terikat (tetap) oleh klien.

Beberapa kode penelusuran pcap kami memberikan contoh yang bagus tentang ini. Ada fungsi yang
perlu dipanggil setiap kali sebuah paket diterima. Fungsi ini memanggil objek yang
sebenarnya menulis paket ke disk dalam format file pcap. Tanda tangan salah satunya
fungsi akan menjadi:

static void DefaultSink (Ptr file, Ptr P);

Kata kunci static berarti ini adalah fungsi statis yang tidak memerlukan a ini penunjuk, jadi
itu akan menggunakan panggilan balik gaya-C. Kami tidak ingin kode panggilan harus tahu tentang
apa pun kecuali Paket. Yang kami inginkan dalam kode panggilan hanyalah panggilan yang terlihat seperti:

m_promiscSnifferTrace (m_currentPkt);

Yang ingin kami lakukan adalah mengikat itu Ptr fillet ke panggilan balik tertentu
implementasi ketika dibuat dan diatur untuk operator() dari Panggilan Balik ke
memberikan parameter itu secara gratis.

Kami menyediakan Lakukan Panggilan Balik fungsi template untuk tujuan itu. Dibutuhkan hal yang sama
parameter sebagai Lakukan Panggilan Balik fungsi template tetapi juga mengambil parameter menjadi
melompat. Dalam kasus contoh di atas:

MakeBoundCallback (&DefaultSink, file);

akan membuat implementasi panggilan balik khusus yang tahu untuk menambahkan batas ekstra
argumen. Secara konseptual, ini memperluas fungsi spesifik yang dijelaskan di atas dengan satu atau lebih
argumen terikat:

templat
kelas SpecificFunctor : Fungsi publik
{
publik:
SpecificFunctor(T* p, int (T::*_pmi)(ARG arg), BOUND_ARG terikatArg)
{
m_p = hal;
m_pmi = pmi;
m_boundArg = terikatArg;
}

operator int virtual() (ARG arg)
{
(*m_p.*m_pmi)(m_boundArg, arg);
}
pribadi:
batal (T::*m_pmi)(ARG arg);
T* m_p;
BOUND_ARG m_boundArg;
};

Anda dapat melihat bahwa ketika fungsi tertentu dibuat, argumen terikat disimpan di
functor / objek panggilan balik itu sendiri. Ketika operator() dipanggil dengan single
parameter, seperti pada:

m_promiscSnifferTrace (m_currentPkt);

pelaksanaan operator() menambahkan parameter terikat ke dalam panggilan fungsi yang sebenarnya:

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

Dimungkinkan untuk mengikat dua atau tiga argumen juga. Katakanlah kita memiliki fungsi dengan
tanda tangan:

static void NotifyEvent (Ptr a, Ptr b, MyEventType e);

Seseorang dapat membuat pengikatan panggilan balik terikat dua argumen pertama seperti:

MakeBoundCallback (&NotifyEvent, a1, b1);

asumsi a1 dan b1 adalah objek bertipe A dan B masing-masing. Demikian pula untuk tiga
argumen yang akan berfungsi dengan tanda tangan:

static void NotifyEvent (Ptr a, Ptr b, MyEventType e);

Mengikat tiga argumen dilakukan dengan:

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

lagi asumsi a1, b1 dan c1 adalah objek bertipe A, B dan C masing.

Jenis pengikatan ini dapat digunakan untuk bertukar informasi antar objek dalam simulasi;
khusus, panggilan balik terikat dapat digunakan sebagai panggilan balik terlacak, yang akan dijelaskan dalam
bagian berikutnya.

Ditelusuri Telepon balik
placeholder ayat

Callback lokasi in ns-3
Di mana panggilan balik yang sering digunakan? ns-3? Berikut adalah beberapa yang lebih terlihat untuk
pengguna biasa:

· Soket API

· Lapisan-2/Lapisan-3 API

· Menelusuri subsistem

· API antara IP dan subsistem perutean

Organisasi details
Cuplikan kode di atas sederhana dan hanya dirancang untuk menggambarkan mekanismenya
diri. Kode Callback yang sebenarnya cukup rumit dan sangat template-intense dan a
pemahaman yang mendalam tentang kode tidak diperlukan. Jika tertarik, pengguna ahli dapat menemukan
berikut bermanfaat.

Kode awalnya ditulis berdasarkan teknik yang dijelaskan dalam
http://www.codeproject.com/cpp/TTLFunction.asp. Itu kemudian ditulis ulang untuk mengikuti
arsitektur yang diuraikan dalam modern C + + Desain, Umum Pemrograman dan Mendesain Pola
Terapan, Alexandrecu, bab 5, Disamaratakan fungsi.

Kode ini menggunakan:

· parameter template default untuk menyelamatkan pengguna dari keharusan menentukan parameter kosong saat
jumlah parameter lebih kecil dari jumlah maksimum yang didukung

· idiom pimpl: kelas Callback diedarkan berdasarkan nilai dan mendelegasikan inti dari
pekerjaan ke penunjuk jerawatnya.

· dua implementasi pimpl yang berasal dari CallbackImpl FunctorCallbackImpl dapat digunakan
dengan tipe functor apa pun sementara MemPtrCallbackImpl dapat digunakan dengan pointer ke anggota
fungsi.

· implementasi daftar referensi untuk mengimplementasikan semantik nilai Callback.

Kode ini terutama berangkat dari implementasi Alexandrescu karena tidak
gunakan daftar tipe untuk menentukan dan menyebarkan tipe argumen panggilan balik. Tentu saja,
itu juga tidak menggunakan semantik penghancuran salinan dan bergantung pada daftar referensi daripada
autoPtr untuk menahan pointer.

obyek model
ns-3 pada dasarnya adalah sistem objek C++. Objek dapat dideklarasikan dan dipakai sebagai
biasa, sesuai aturan C++. ns-3 juga menambahkan beberapa fitur ke objek C++ tradisional, seperti
dijelaskan di bawah ini, untuk menyediakan fungsionalitas dan fitur yang lebih baik. Bab manual ini adalah
dimaksudkan untuk memperkenalkan pembaca kepada ns-3 model objek.

Bagian ini menjelaskan desain kelas C++ untuk ns-3 objek. Singkatnya, beberapa desain
pola yang digunakan termasuk desain berorientasi objek klasik (antarmuka polimorfik dan
implementasi), pemisahan antarmuka dan implementasi, publik non-virtual
pola desain antarmuka, fasilitas agregasi objek, dan penghitungan referensi untuk
manajemen memori. Mereka yang akrab dengan model komponen seperti COM atau Bonobo akan
mengenali elemen desain dalam ns-3 model agregasi objek, meskipun ns-3
desain tidak sepenuhnya sesuai dengan baik.

Berorientasi pada objek laku
Objek C++, secara umum, menyediakan kemampuan berorientasi objek umum (abstraksi,
enkapsulasi, pewarisan, dan polimorfisme) yang merupakan bagian dari berorientasi objek klasik
desain. ns-3 objek memanfaatkan properti ini; misalnya:

alamat kelas
{
publik:
Alamat ();
Alamat (tipe uint8_t, const uint8_t *buffer, uint8_t len);
Alamat (const Alamat & alamat);
Alamat &operator = (const Alamat &alamat);
...
pribadi:
uint8_t m_type;
uint8_t m_len;
...
};

obyek mendasarkan kelas-kelas
Ada tiga kelas dasar khusus yang digunakan dalam ns-3. Kelas yang mewarisi dari pangkalan ini
kelas dapat membuat instance objek dengan properti khusus. Kelas dasar ini adalah:

· kelas obyek

· kelas Basis Objek

· kelas SederhanaRefCount

Itu tidak wajib ns-3 objek mewarisi dari kelas ini, tetapi objek yang mendapatkan
properti khusus. Kelas yang berasal dari kelas obyek mendapatkan sifat-sifat berikut.

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

· sistem agregasi objek

· sistem penghitungan referensi penunjuk pintar (kelas Ptr)

Kelas yang berasal dari kelas Basis Objek dapatkan dua properti pertama di atas, tetapi jangan
dapatkan petunjuk cerdas. Kelas yang berasal dari kelas SederhanaRefCount: dapatkan hanya
sistem penghitungan referensi penunjuk pintar.

Dalam prakteknya, kelas obyek adalah varian dari tiga di atas bahwa ns-3 pengembang akan
paling sering ditemui.

Memori pengelolaan dan kelas Ptr
Manajemen memori dalam program C++ adalah proses yang kompleks, dan sering dilakukan secara tidak benar atau
tidak konsisten. Kami telah menetapkan desain penghitungan referensi yang dijelaskan sebagai berikut.

Semua objek yang menggunakan penghitungan referensi mempertahankan penghitungan referensi internal untuk menentukan
ketika suatu objek dapat dengan aman menghapus dirinya sendiri. Setiap kali pointer diperoleh ke
antarmuka, jumlah referensi objek bertambah dengan memanggil ref(). Ini adalah
kewajiban pengguna pointer untuk secara eksplisit tidak dirujuk() penunjuk saat selesai. Kapan
jumlah referensi jatuh ke nol, objek dihapus.

· Ketika kode klien memperoleh pointer dari objek itu sendiri melalui pembuatan objek,
atau melalui GetObject, tidak harus menambah jumlah referensi.

· Ketika kode klien memperoleh pointer dari sumber lain (misalnya, menyalin pointer) itu harus
panggilan ref() untuk menambah jumlah referensi.

· Semua pengguna penunjuk objek harus memanggil tidak dirujuk() untuk melepaskan referensi.

Beban untuk menelepon tidak dirujuk() agak lega dengan penggunaan penghitungan referensi
kelas penunjuk pintar dijelaskan di bawah ini.

Pengguna yang menggunakan API tingkat rendah yang ingin secara eksplisit mengalokasikan objek yang dihitung tanpa referensi
di heap, menggunakan operator new, bertanggung jawab untuk menghapus objek tersebut.

Referensi perhitungan pintar petunjuk (Ptr)
panggilan ref() dan tidak dirujuk() sepanjang waktu akan merepotkan, jadi ns-3 menyediakan pintar
kelas penunjuk Ptr mirip dengan Peningkatan::intrusive_ptr. Kelas penunjuk pintar ini mengasumsikan bahwa
tipe yang mendasari menyediakan sepasang Ref dan Batalkan referensi metode yang diharapkan
menambah dan mengurangi penghitungan ulang internal dari instance objek.

Implementasi ini memungkinkan Anda untuk memanipulasi penunjuk pintar seolah-olah itu normal
pointer: Anda dapat membandingkannya dengan nol, membandingkannya dengan pointer lain, menetapkan nol untuk
itu, dll.

Dimungkinkan untuk mengekstrak pointer mentah dari pointer pintar ini dengan DapatkanPointer()
dan PeekPointer() metode.

Jika Anda ingin menyimpan objek baru ke dalam smart pointer, kami menyarankan Anda untuk menggunakan
Template CreateObject berfungsi untuk membuat objek dan menyimpannya di smart pointer ke
menghindari kebocoran memori. Fungsi-fungsi ini adalah fungsi kenyamanan yang sangat kecil dan tujuannya
hanya untuk menghemat sedikit pengetikan.

BuatObjek dan membuat
Objek dalam C++ dapat dibuat secara statis, dinamis, atau otomatis. Ini benar
untuk ns-3 juga, tetapi beberapa objek dalam sistem memiliki beberapa kerangka kerja tambahan yang tersedia.
Secara khusus, objek terhitung referensi biasanya dialokasikan menggunakan template Create or
metode CreateObject, sebagai berikut.

Untuk objek yang diturunkan dari kelas obyek:

Ptr perangkat = BuatObjek ();

Tolong jangan membuat objek seperti itu menggunakan operator yang baru; buat mereka menggunakan BuatObjek()
sebagai gantinya.

Untuk objek yang diturunkan dari kelas SederhanaRefCount, atau objek lain yang mendukung penggunaan
kelas penunjuk pintar, fungsi pembantu templat tersedia dan direkomendasikan untuk digunakan:

Ptr b = Buat ();

Ini hanyalah pembungkus di sekitar operator baru yang menangani penghitungan referensi dengan benar
sistem.

Singkatnya, gunakan Membuat jika B bukan objek tetapi hanya menggunakan penghitungan referensi (mis
Paket), dan gunakan BuatObjek jika B diturunkan dari ns3::Objek.

Pengumpulan
ns-3 sistem agregasi objek dimotivasi sebagian besar oleh pengakuan bahwa a
kasus penggunaan umum untuk ns-2 telah menggunakan pewarisan dan polimorfisme untuk memperpanjang
model protokol. Misalnya, versi khusus TCP seperti RenoTcpAgent diturunkan
dari (dan menimpa fungsi dari) kelas TcpAgent.

Namun, dua masalah yang muncul di ns-2 model downcasts dan "dasar lemah
class." Downcasting mengacu pada prosedur menggunakan pointer kelas dasar ke suatu objek dan
menanyakannya saat dijalankan untuk mengetahui informasi tipe, digunakan untuk secara eksplisit melemparkan pointer
ke pointer subclass sehingga API subclass dapat digunakan. Kelas dasar yang lemah mengacu pada
masalah yang muncul ketika kelas tidak dapat digunakan kembali secara efektif (berasal dari) karena
tidak memiliki fungsionalitas yang diperlukan, membuat pengembang harus memodifikasi kelas dasar dan
menyebabkan proliferasi panggilan API kelas dasar, beberapa di antaranya mungkin tidak semantik
benar untuk semua subclass.

ns-3 menggunakan versi pola desain antarmuka kueri untuk menghindari masalah ini.
Desain ini didasarkan pada elemen Komponen obyek Model dan GNOME Bonobo meskipun
kompatibilitas tingkat biner penuh dari komponen yang dapat diganti tidak didukung dan kami memiliki
mencoba menyederhanakan sintaks dan berdampak pada pengembang model.

contoh
Pengumpulan contoh
Node adalah contoh yang baik dari penggunaan agregasi di ns-3. Perhatikan bahwa tidak ada turunan
kelas Node di ns-3 seperti kelas Node Internet. Sebaliknya, komponen (protokol) adalah
dikumpulkan menjadi sebuah node. Mari kita lihat bagaimana beberapa protokol IPv4 ditambahkan ke sebuah node.:

kekosongan statis
TambahkanIpv4Stack(Ptr simpul)
{
Ptr ipv4 = BuatObjek ();
ipv4->SetNode (simpul);
node->AggregateObject (ipv4);
Ptr ipv4Impl = BuatObjek ();
ipv4Impl->SetIpv4 (ipv4);
node->AggregateObject (ipv4Impl);
}

Perhatikan bahwa protokol IPv4 dibuat menggunakan BuatObjek(). Kemudian, mereka dikumpulkan
ke simpul. Dengan cara ini, kelas dasar Node tidak perlu diedit untuk mengizinkan pengguna
dengan penunjuk Node kelas dasar untuk mengakses antarmuka IPv4; pengguna dapat meminta node untuk a
pointer ke antarmuka IPv4 saat runtime. Bagaimana pengguna meminta node dijelaskan dalam
subbagian berikutnya.

Perhatikan bahwa ini adalah kesalahan pemrograman untuk menggabungkan lebih dari satu objek dari jenis yang sama ke
an ns3::Objek. Jadi, misalnya, agregasi bukanlah opsi untuk menyimpan semua
soket aktif dari sebuah node.

DapatkanObjek contoh
GetObject adalah cara tipe-safe untuk mencapai downcasting yang aman dan memungkinkan antarmuka menjadi
ditemukan pada suatu objek.

Pertimbangkan penunjuk simpul m_node yang menunjuk ke objek Node yang memiliki implementasi dari
IPv4 sebelumnya diagregasi ke dalamnya. Kode klien ingin mengkonfigurasi rute default. Ke
melakukannya, itu harus mengakses objek di dalam node yang memiliki antarmuka ke penerusan IP
konfigurasi. Ini melakukan hal berikut:

Ptr ipv4 = m_node->GetObject ();

Jika node sebenarnya tidak memiliki objek IPv4 yang diagregasi, maka metodenya akan
kembali nol. Oleh karena itu, praktik yang baik adalah memeriksa nilai kembalian dari fungsi seperti itu
panggilan. Jika berhasil, pengguna sekarang dapat menggunakan Ptr ke objek IPv4 yang sebelumnya
dikumpulkan ke node.

Contoh lain tentang bagaimana seseorang dapat menggunakan agregasi adalah dengan menambahkan model opsional ke objek. Untuk
misalnya, objek Node yang ada mungkin memiliki objek "Model Energi" yang dikumpulkan di
run time (tanpa memodifikasi dan mengkompilasi ulang kelas node). Model yang ada (seperti
perangkat jaringan nirkabel) kemudian dapat "GetObject" untuk model energi dan bertindak dengan tepat
jika antarmuka telah dibangun ke objek Node yang mendasarinya atau digabungkan ke
itu pada saat dijalankan. Namun, node lain tidak perlu tahu apa-apa tentang model energi.

Kami berharap mode pemrograman ini membutuhkan lebih sedikit kebutuhan bagi pengembang untuk memodifikasi
kelas-kelas dasar.

obyek pabrik
Kasus penggunaan yang umum adalah membuat banyak objek yang dikonfigurasi serupa. Seseorang dapat berulang kali
panggilan BuatObjek() tetapi ada juga pola desain pabrik yang digunakan di ns-3 sistem.
Ini banyak digunakan dalam API "pembantu".

Kelas Pabrik Objek dapat digunakan untuk membuat instance objek dan mengonfigurasi atribut pada
benda-benda itu:

batal SetTypeId (TipeId tid);
void Set (std::nama string, const AttributeValue &nilai);
Ptr Buat (batal) const;

Metode pertama memungkinkan seseorang untuk menggunakan ns-3 Sistem TypeId untuk menentukan jenis objek
dibuat. Yang kedua memungkinkan seseorang untuk mengatur atribut pada objek yang akan dibuat, dan
ketiga memungkinkan seseorang untuk membuat objek sendiri.

Sebagai contoh:

Pabrik ObjectFactory;
// Buat pabrik ini membuat objek bertipe FriisPropagationLossModel
factory.SetTypeId ("ns3::FriisPropagationLossModel")
// Jadikan objek pabrik ini mengubah nilai default atribut, untuk
// selanjutnya membuat objek
factory.Set ("SystemLoss", DoubleValue (2.0));
// Buat satu objek seperti itu
Ptr objek = pabrik.Buat();
factory.Set ("SystemLoss", DoubleValue (3.0));
// Buat objek lain dengan SystemLoss yang berbeda
Ptr objek = pabrik.Buat();

downcasting
Sebuah pertanyaan yang muncul beberapa kali adalah, "Jika saya memiliki pointer kelas dasar (Ptr) ke sebuah
objek dan saya ingin pointer kelas turunan, haruskah saya downcast (melalui C++ dynamic cast) ke
dapatkan pointer turunan, atau haruskah saya menggunakan sistem agregasi objek untuk GetObject<> ()
untuk menemukan Ptr ke antarmuka ke API subkelas?"

Jawabannya adalah bahwa dalam banyak situasi, kedua teknik akan berhasil. ns-3 menyediakan
fungsi templated untuk membuat sintaks Object dynamic casting lebih banyak pengguna
ramah:

templat
Ptr
DynamicCast (Ptr konstan&p)
{
kembali Ptr (dinamis_cast (PeekPointer (p)));
}

DynamicCast berfungsi ketika programmer memiliki pointer tipe dasar dan sedang menguji a
penunjuk subkelas. GetObject berfungsi saat mencari objek berbeda yang dikumpulkan, tetapi juga
bekerja dengan subkelas, dengan cara yang sama seperti DynamicCast. Jika tidak yakin, programmer harus
gunakan GetObject, karena berfungsi di semua kasus. Jika programmer mengetahui hierarki kelas dari
objek yang sedang dipertimbangkan, lebih langsung menggunakan DynamicCast.

konfigurasi dan atribut
In ns-3 simulasi, ada dua aspek utama untuk konfigurasi:

· Topologi simulasi dan bagaimana objek terhubung.

· Nilai yang digunakan oleh model yang dipakai dalam topologi.

Bab ini berfokus pada item kedua di atas: berapa banyak nilai yang digunakan dalam ns-3 adalah
terorganisir, didokumentasikan, dan dimodifikasi oleh ns-3 pengguna. Itu ns-3 sistem atribut juga merupakan
yang mendasari bagaimana jejak dan statistik dikumpulkan dalam simulator.

Dalam perjalanan bab ini kita akan membahas berbagai cara untuk mengatur atau memodifikasi nilai-nilai
digunakan oleh ns-3 objek model. Dalam urutan spesifisitas yang meningkat, ini adalah:

┌─────────────────────────────────┬─────────────── ───────────────────┐
Metode Lingkup
├─────────────────────────────────┼─────────────── ───────────────────┤
Nilai Atribut Default ditetapkan Mempengaruhi semua instance dari
ketika Atribut didefinisikan dalam kelas .
DapatkanTypeId (). │ │
└─────────────────────────────────┴─────────────── ───────────────────┘

Garis komando Mempengaruhi semua kejadian di masa depan.
Konfigurasi::SetDefault() │ │.
Toko Konfigurasi │ │.
├─────────────────────────────────┼─────────────── ───────────────────┤
Pabrik Objek Mempengaruhi semua instance yang dibuat
dengan pabrik.
├─────────────────────────────────┼─────────────── ───────────────────┤
XHelperSetAttribute () Mempengaruhi semua instance yang dibuat oleh
penolong.
├─────────────────────────────────┼─────────────── ───────────────────┤
Kelas Saya::SetX () Mengubah contoh khusus ini.
Objek::SetAttribute () Umumnya ini adalah satu-satunya bentuk
Konfigurasi::Set() yang dapat dijadwalkan untuk mengubah
contoh sekali simulasi
sedang berjalan.
└─────────────────────────────────┴─────────────── ───────────────────┘

Dengan "kekhususan" yang kami maksudkan bahwa metode di baris selanjutnya dalam tabel menimpa nilai yang ditetapkan
oleh, dan biasanya mempengaruhi lebih sedikit contoh daripada, metode sebelumnya.

Sebelum mempelajari detail sistem nilai atribut, akan membantu untuk meninjau beberapa
sifat dasar kelas obyek.

obyek Ringkasan
ns-3 pada dasarnya adalah sistem berbasis objek C++. Yang kami maksud adalah kelas C++ baru
(tipe) dapat dideklarasikan, didefinisikan, dan disubklasifikasikan seperti biasa.

Banyak ns-3 benda-benda yang diwarisi dari obyek kelas dasar. Benda-benda ini memiliki beberapa tambahan
properti yang kami manfaatkan untuk mengatur sistem dan meningkatkan manajemen memori
dari objek kami:

· Sistem "Metadata" yang menghubungkan nama kelas ke banyak meta-informasi tentang
objek, antara lain:

· Kelas dasar dari subkelas,

· Himpunan konstruktor yang dapat diakses di subclass,

· Himpunan "atribut" dari subclass,

· Apakah setiap atribut dapat diatur, atau hanya-baca,

· Rentang nilai yang diperbolehkan untuk setiap atribut.

· Referensi menghitung implementasi smart pointer, untuk manajemen memori.

ns-3 objek yang menggunakan sistem atribut berasal dari obyek or Basis Objek. Paling
ns-3 objek yang akan kita bahas berasal dari obyek, tetapi beberapa yang berada di luar pintar
kerangka kerja manajemen memori pointer berasal dari Basis Objek.

Mari kita tinjau beberapa properti dari objek-objek ini.

Cerdas pointer
Seperti yang diperkenalkan dalam ns-3 tutorial, ns-3 objek adalah memori yang dikelola oleh a referensi
perhitungan pintar petunjuk implementasi, kelas Ptr.

Pointer pintar digunakan secara luas di ns-3 API, untuk menghindari meneruskan referensi ke
objek yang dialokasikan tumpukan yang dapat menyebabkan kebocoran memori. Untuk sebagian besar penggunaan dasar (sintaks), perlakukan
pointer pintar seperti pointer biasa:

Ptr nd = ...;
nd->CallSomeFunction();
// dll.

Jadi bagaimana Anda mendapatkan penunjuk pintar ke suatu objek, seperti pada baris pertama contoh ini?

BuatObjek
Seperti yang telah kita bahas di atas dalam Manajemen-memori-dan-kelas-Ptr, pada API tingkat terendah, objek
jenis obyek tidak dipakai menggunakan operator yang baru seperti biasa tetapi dengan templated
fungsi yang disebut BuatObjek ().

Cara khas untuk membuat objek seperti itu adalah sebagai berikut:

Ptr nd = BuatObjek ();

Anda dapat menganggap ini secara fungsional setara dengan:

WifiNetDevice* nd = WifiNetDevice baru ();

Benda yang berasal dari obyek harus dialokasikan pada heap menggunakan BuatObjek (). Itu
berasal dari Basis Objek, Seperti ns-3 fungsi pembantu dan header dan trailer paket,
dapat dialokasikan pada stack.

Dalam beberapa skrip, Anda mungkin tidak melihat banyak BuatObjek () panggilan dalam kode; ini
karena ada beberapa objek pembantu yang berlaku yang melakukan BuatObjek () panggilan
untuk Anda.

TypeId
ns-3 kelas yang berasal dari kelas obyek dapat menyertakan kelas metadata yang disebut TypeId bahwa
merekam meta-informasi tentang kelas, untuk digunakan dalam agregasi objek dan komponen
sistem manajer:

· Sebuah string unik yang mengidentifikasi kelas.

· Kelas dasar dari subkelas, dalam sistem metadata.

· Himpunan konstruktor yang dapat diakses di subclass.

· Daftar properti yang dapat diakses publik ("atribut") dari kelas.

obyek Kesimpulan
Menempatkan semua konsep ini bersama-sama, mari kita lihat contoh spesifik: class Node.

File header publik simpul.h memiliki deklarasi yang menyertakan static DapatkanTypeId ()
panggilan fungsi:

kelas Node : Obyek publik
{
publik:
static TypeId GetTypeId (batal);
...

Ini didefinisikan dalam simpul.cc file sebagai berikut:

TypeId
Node::GetTypeId (batal)
{
static TypeId tid = TypeId ("ns3::Node")
.SetInduk ()
.TambahkanKonstruktor ()
.AddAttribute ("Daftar Perangkat",
"Daftar perangkat yang terkait dengan Node ini.",
ObjekVectorValue (),
MakeObjectVectorAccessor (&Node::m_devices),
MakeObjectVectorChecker ())
.AddAttribute ("Daftar Aplikasi",
"Daftar aplikasi yang terkait dengan Node ini.",
ObjekVectorValue (),
MakeObjectVectorAccessor (&Node::m_applications),
MakeObjectVectorChecker ())
.AddAttribute ("Id",
"Id (bilangan bulat unik) dari Node ini.",
TypeId::ATTR_GET, // izinkan hanya mendapatkannya.
NilaiUinteger (0),
MakeUintegerAccessor (&Node::m_id),
MakeUintegerChecker ())
;
kembali tid;
}

Pertimbangkan TypeId dari ns-3 obyek class sebagai bentuk diperpanjang dari tipe run time
informasi (RTTI). Bahasa C++ menyertakan jenis RTTI sederhana untuk mendukung
dinamis_cast dan Ketik operator.

SetInduk () panggilan dalam definisi di atas digunakan bersama dengan kami
mekanisme agregasi objek untuk memungkinkan transmisi naik dan turun yang aman di pohon warisan
selama DapatkanObjek (). Itu juga memungkinkan subclass untuk mewarisi Atribut dari induknya
kelas.

TambahkanKonstruktor () panggilan digunakan bersama dengan pabrik objek abstrak kami
mekanisme untuk memungkinkan kita membangun objek C++ tanpa memaksa pengguna untuk mengetahui
kelas beton dari objek yang dia bangun.

Tiga panggilan ke Tambahkan Atribut () kaitkan string yang diberikan dengan nilai yang diketik dengan kuat di
kelas. Perhatikan bahwa Anda harus memberikan string bantuan yang mungkin ditampilkan, misalnya,
melalui prosesor baris perintah. Setiap Atribut dikaitkan dengan mekanisme untuk mengakses
variabel anggota yang mendasari dalam objek (misalnya, MakeUintegerAccessor () mengatakan
yang generik Atribut kode cara menuju ke ID simpul di atas). Ada juga "Pemeriksa"
metode yang digunakan untuk memvalidasi nilai terhadap batasan rentang, seperti maksimum dan
nilai minimum yang diizinkan.

Ketika pengguna ingin membuat Node, mereka biasanya akan memanggil beberapa bentuk BuatObjek (),:

Ptr n = BuatObjek ();

atau lebih abstrak, menggunakan pabrik objek, Anda dapat membuat Node objek tanpa genap
mengetahui tipe C++ yang konkret:

Pabrik ObjectFactory;
const std::string typeId = "ns3::Node'';
pabrik.SetTypeId (typeId);
Ptr simpul = pabrik.Buat ();

Kedua metode ini menghasilkan atribut yang sepenuhnya diinisialisasi tersedia di
dihasilkan obyek contoh.

Kami selanjutnya membahas bagaimana atribut (nilai yang terkait dengan variabel anggota atau fungsi dari
kelas) diarahkan ke atas TypeId.

atribut
Tujuan dari sistem atribut adalah untuk mengatur akses objek anggota internal a
simulasi. Tujuan ini muncul karena, biasanya dalam simulasi, pengguna akan memotong dan
menempel/memodifikasi skrip simulasi yang ada, atau akan menggunakan konstruksi simulasi tingkat tinggi,
tetapi seringkali akan tertarik untuk mempelajari atau menelusuri variabel internal tertentu. Untuk
contoh, gunakan kasus seperti:

· "I ingin untuk jejak itu paket on itu nirkabel antarmuka hanya on itu pertama mengakses titik."

· "I ingin untuk jejak itu nilai of itu TCP kemacetan jendela (setiap waktu it perubahan) on a
tertentu TCP stopkontak."

· "I ingin a membuang of semua nilai-nilai bahwa adalah bekas in my simulasi."

Demikian pula, pengguna mungkin menginginkan akses halus ke variabel internal dalam simulasi, atau
mungkin ingin secara luas mengubah nilai awal yang digunakan untuk parameter tertentu di semua
objek yang kemudian dibuat. Terakhir, pengguna mungkin ingin mengetahui variabel apa yang dapat diatur
dan dapat diambil dalam konfigurasi simulasi. Ini bukan hanya untuk simulasi langsung
interaksi pada baris perintah; pertimbangkan juga antarmuka pengguna grafis (masa depan) yang
ingin dapat menyediakan fitur di mana pengguna dapat mengklik kanan pada sebuah node di
kanvas dan lihat daftar parameter hierarkis dan terorganisir yang dapat diatur di
node dan objek anggota konstituennya, dan teks bantuan dan nilai default untuk masing-masing
parameter.

Mendefinisikan atribut
Kami menyediakan cara bagi pengguna untuk mengakses nilai jauh di dalam sistem, tanpa harus menyelami
pengakses (penunjuk) melalui sistem dan berjalan rantai penunjuk untuk sampai ke sana. Pertimbangkan
kelas DropEkor Antrian yang memiliki variabel anggota yang merupakan bilangan bulat yang tidak ditandatangani m_maxPackets;
variabel anggota ini mengontrol kedalaman antrian.

Jika kita melihat deklarasi DropEkor Antrian, kita lihat berikut ini:

kelas DropTailQueue : Antrian publik {
publik:
static TypeId GetTypeId (batal);
...

pribadi:
std::antrian > m_paket;
uint32_t m_maxPackets;
};

Mari kita pertimbangkan hal-hal yang mungkin ingin dilakukan pengguna dengan nilai m_maxPackets:

· Tetapkan nilai default untuk sistem, sehingga setiap kali baru DropEkor Antrian dibuat,
anggota ini diinisialisasi ke default itu.

· Tetapkan atau dapatkan nilai pada antrian yang sudah dipakai.

Hal-hal di atas biasanya membutuhkan penyediaan set () dan Dapatkan () fungsi, dan beberapa jenis
nilai default global.

Dalam majalah ns-3 sistem atribut, definisi nilai ini, dan pendaftaran fungsi pengakses
dipindahkan ke TypeId kelas; mis..:

NS_OBJECT_ENSURE_REGISTERED (DropTailQueue);

TypeId
DropTailQueue::GetTypeId (batal)
{
static TypeId tid = TypeId ("ns3::DropTailQueue")
.SetInduk ()
.TambahkanKonstruktor ()
.AddAttribute ("MaxPackets",
"Jumlah maksimum paket yang diterima oleh DropTailQueue ini.",
NilaiUinteger (100),
MakeUintegerAccessor (&DropTailQueue::m_maxPackets),
MakeUintegerChecker ())
;

kembali tid;
}

Tambahkan Atribut () metode ini melakukan beberapa hal untuk m_maxPackets nilai:

· Mengikat variabel anggota (biasanya pribadi) m_maxPackets ke string publik
"Paket Maks".

· Memberikan nilai default (100 paket).

· Menyediakan beberapa teks bantuan yang mendefinisikan arti dari nilai.

· Menyediakan "Pemeriksa" (tidak digunakan dalam contoh ini) yang dapat digunakan untuk menetapkan batas pada
rentang nilai yang diizinkan.

Poin kuncinya adalah sekarang nilai variabel ini dan nilai defaultnya dapat diakses
di namespace atribut, yang didasarkan pada string seperti "Paket Maks" dan TypeId nama
string. Di bagian selanjutnya, kami akan memberikan contoh skrip yang menunjukkan bagaimana pengguna dapat
memanipulasi nilai-nilai ini.

Perhatikan bahwa inisialisasi atribut bergantung pada makro NS_OBJECT_ENSURE_REGISTERED
(Jatuhkan Antrian) dipanggil; jika Anda mengabaikan ini dari implementasi kelas baru Anda, Anda
atribut tidak akan diinisialisasi dengan benar.

Meskipun kami telah menjelaskan cara membuat atribut, kami masih belum menjelaskan cara mengakses
dan mengelola nilai-nilai ini. Misalnya, tidak ada global.h file header di mana ini
disimpan; atribut disimpan dengan kelasnya. Pertanyaan yang secara alami muncul adalah bagaimana
apakah pengguna dengan mudah mempelajari semua atribut model mereka, dan bagaimana cara pengguna?
mengakses atribut ini, atau mendokumentasikan nilainya sebagai bagian dari catatan
simulasi?

Dokumentasi terperinci dari atribut aktual yang ditentukan untuk suatu tipe, dan daftar global
semua atribut yang ditentukan, tersedia dalam dokumentasi API. Untuk sisa ini
dokumen kita akan menunjukkan berbagai cara untuk mendapatkan dan mengatur atribut
nilai-nilai.

Pengaturan Default Nilai - Nilai
Konfigurasi::SetDefault dan Garis komando
Mari kita lihat bagaimana skrip pengguna dapat mengakses nilai atribut tertentu. Akan
gunakan src/point-to-point/examples/main-attribute-value.cc skrip untuk ilustrasi, dengan
beberapa detail dihilangkan. Itu utama fungsi dimulai:

// Ini adalah contoh dasar bagaimana menggunakan sistem atribut untuk
// mengatur dan mendapatkan nilai dalam sistem yang mendasarinya; yaitu, sebuah unsigned
// bilangan bulat dari jumlah maksimum paket dalam antrian
//

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

// Secara default, atribut MaxPackets memiliki nilai 100 paket
// (default ini dapat diamati pada fungsi DropTailQueue::GetTypeId)
//
// Di sini, kita set ke 80 paket. Kita bisa menggunakan salah satu dari dua tipe nilai:
// nilai berbasis string atau nilai Uinteger
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("80"));
// Panggilan fungsi di bawah ini berlebihan
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (80));

// Izinkan pengguna untuk mengganti salah satu default dan di atas
// SetDefaults () saat run-time, melalui argumen baris perintah
// Misalnya, melalui "--ns3::DropTailQueue::MaxPackets=80"
cmd baris perintah;
// Ini memberikan cara lain untuk mengatur nilai dari baris perintah:
cmd.AddValue("maxPackets", "ns3::DropTailQueue::MaxPackets");
cmd.Parse (argc, argv);

Hal utama yang perlu diperhatikan di atas adalah dua panggilan yang setara ke Konfigurasi::SetDefault
(). Ini adalah bagaimana kami menetapkan nilai default untuk semua yang selanjutnya dipakai
DropEkor Antrians. Kami menggambarkan bahwa dua jenis Nilai kelas, a StringNilai dan
NilaiUinteger class, dapat digunakan untuk menetapkan nilai ke atribut bernama oleh
"ns3::DropTailQueue::MaxPackets".

Dimungkinkan juga untuk memanipulasi Atribut menggunakan Garis komando; kami melihat beberapa contoh
di awal Tutorial. Secara khusus, sangat mudah untuk menambahkan argumen singkat
nama, seperti --maxPackets, untuk Atribut yang relevan secara khusus untuk model Anda,
pada kasus ini "ns3::DropTailQueue::MaxPackets". Ini memiliki fitur tambahan yang
string bantuan untuk Atribut akan dicetak sebagai bagian dari pesan penggunaan untuk skrip.
Untuk informasi lebih lanjut, lihat Garis komando Dokumentasi API.

Sekarang, kita akan membuat beberapa objek menggunakan API level rendah. Antrian kami yang baru dibuat akan
tidak punya m_maxPackets diinisialisasi ke 100 paket, seperti yang didefinisikan dalam
DropTailQueue::GetTypeId () fungsi, tetapi untuk 80 paket, karena apa yang kami lakukan di atas dengan
nilai dasar.:

Ptr n0 = BuatObjek ();

Ptr net0 = BuatObjek ();
n0->AddDevice (net0);

Ptr q = Buat Objek ();
net0->AddQueue(q);

Pada titik ini, kami telah membuat single Node (n0) dan satu Perangkat PointToPointNet
(net0), dan menambahkan DropEkor Antrian (q) ke net0.

Konstruktor, Pembantu dan Pabrik Objek
Kombinasi atribut yang sewenang-wenang dapat diatur dan diambil dari helper dan level rendah
Lebah; baik dari konstruktor itu sendiri:

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

atau dari API pembantu tingkat yang lebih tinggi, seperti:

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

Kami tidak mengilustrasikannya di sini, tetapi Anda juga dapat mengonfigurasi Pabrik Objek dengan nilai-nilai baru
untuk atribut tertentu. Instance yang dibuat oleh Pabrik Objek akan memiliki itu
atribut yang ditetapkan selama konstruksi. Ini sangat mirip dengan menggunakan salah satu API pembantu
untuk kelas.

Untuk meninjau, ada beberapa cara untuk menetapkan nilai atribut untuk instance kelas untuk be
dibuat in itu masa depan:

· Konfigurasi::SetDefault ()

· Baris Perintah::Nilai Tambah ()

· CreateObjectWithAttributes<> ()

· Berbagai API pembantu

Tetapi bagaimana jika Anda telah membuat sebuah instance, dan Anda ingin mengubah nilai dari
atribut? Dalam contoh ini, bagaimana kita bisa memanipulasi m_maxPackets nilai sudah
dipakai DropEkor Antrian? Berikut adalah berbagai cara untuk melakukannya.

Mengubah Nilai - Nilai
Penunjuk Cerdas
Asumsikan bahwa penunjuk pintar (Ptr) ke perangkat jaringan yang relevan ada di tangan; pada saat ini
contohnya adalah net0 penunjuk.

Salah satu cara untuk mengubah nilainya adalah dengan mengakses pointer ke antrian yang mendasarinya dan memodifikasi
atribut.

Pertama, kita amati bahwa kita bisa mendapatkan pointer ke (kelas dasar) Antre melalui itu
Perangkat PointToPointNet atribut, di mana itu disebut "TxAntrian":

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

Menggunakan DapatkanObjek () fungsi, kita dapat melakukan downcast yang aman ke a DropEkor Antrian, Di mana
"Paket Maks" adalah atribut:

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

Selanjutnya, kita bisa mendapatkan nilai atribut pada antrian ini. Kami telah memperkenalkan pembungkus
Nilai kelas untuk tipe data yang mendasarinya, mirip dengan pembungkus Java di sekitar tipe ini,
karena sistem atribut menyimpan nilai yang diserialkan ke string, dan bukan tipe yang berbeda.
Di sini, nilai atribut ditetapkan ke a NilaiUinteger, Dan Dapatkan () metode ini
nilai menghasilkan (membuka) uint32_t.:

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

Perhatikan bahwa downcast di atas tidak terlalu dibutuhkan; kita bisa mendapatkan atributnya
nilai langsung dari txAntrian, yang merupakan obyek:

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

Sekarang, mari kita set ke nilai lain (60 paket):

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

config Namespace xtra
Cara alternatif untuk mendapatkan atribut adalah dengan menggunakan namespace konfigurasi. Di Sini,
atribut ini berada di jalur yang dikenal di namespace ini; pendekatan ini berguna jika salah satu
tidak memiliki akses ke pointer yang mendasarinya dan ingin mengonfigurasi tertentu
atribut dengan satu pernyataan.:

Konfigurasi::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets",
NilaiUinteger (25));
txQueue->GetAttribute("MaxPackets", batas);
NS_LOG_INFO ("4. txQueue limit diubah melalui namespace: "
<< batas.Dapatkan () << "paket");

Jalur konfigurasi sering berbentuk ".../
nama>/ /.../ / " untuk merujuk ke contoh tertentu dengan indeks an
benda di dalam wadah. Dalam hal ini wadah pertama adalah daftar semuanya NodeS; NS
wadah kedua adalah daftar semuanya Perangkat Bersihs pada yang dipilih Node. Akhirnya,
jalur konfigurasi biasanya diakhiri dengan suksesi atribut anggota, dalam hal ini
"Paket Maks" atribut dari "TxAntrian" dari yang terpilih Perangkat Bersih.

Kami juga bisa menggunakan wildcard untuk menetapkan nilai ini untuk semua node dan semua perangkat bersih
(yang dalam contoh sederhana ini memiliki efek yang sama seperti sebelumnya Konfigurasi::Setel ()):

Konfigurasi::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets",
NilaiUinteger (15));
txQueue->GetAttribute("MaxPackets", batas);
NS_LOG_INFO ("5. txQueue limit diubah melalui namespace wildcard: "
<< batas.Dapatkan () << "paket");

obyek Nama Pelayanan
Cara lain untuk mendapatkan atribut adalah dengan menggunakan fasilitas layanan nama objek. Itu
layanan nama objek memungkinkan kita untuk menambahkan item ke ruang nama konfigurasi di bawah
"/Nama/" jalur dengan string nama yang ditentukan pengguna. Pendekatan ini berguna jika seseorang tidak
memiliki akses ke pointer yang mendasarinya dan sulit untuk menentukan yang diperlukan
jalur namespace konfigurasi beton.

Nama::Tambah ("server", n0);
Nama::Tambahkan ("server/eth0", net0);

...

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

Di sini kami telah menambahkan elemen jalur "pelayan" dan "et0" bawah "/Nama/" ruang nama, lalu
menggunakan jalur konfigurasi yang dihasilkan untuk mengatur atribut.

Lihat Nama-Objek untuk perawatan yang lebih lengkap dari ns-3 ruang nama konfigurasi.

Organisasi Rincian
Nilai Kelas
Pembaca akan mencatat JenisNilai kelas yang merupakan subkelas dari Nilai Atribut mendasarkan
kelas. Ini dapat dianggap sebagai kelas menengah yang digunakan untuk mengkonversi dari mentah
jenis ke Nilai Atributs yang digunakan oleh sistem atribut. Ingatlah bahwa ini
database memegang objek dari banyak jenis serial ke string. Konversi ke jenis ini
dapat dilakukan dengan menggunakan kelas perantara (seperti Nilai Bilangan Bulat, atau Nilai Ganda untuk
angka floating point) atau melalui string. Konversi implisit langsung dari tipe ke
Nilai Atribut sebenarnya tidak praktis. Jadi di atas, pengguna memiliki pilihan untuk menggunakan
string atau nilai:

p->Set("cwnd", StringValue ("100")); // penyetel berbasis string
p->Set ("cwnd", Nilai Integer (100)); // penyetel berbasis bilangan bulat

Sistem menyediakan beberapa makro yang membantu pengguna mendeklarasikan dan mendefinisikan AttributeValue baru
subkelas untuk tipe baru yang ingin mereka perkenalkan ke dalam sistem atribut:

· ATTRIBUTE_HELPER_HEADER

· ATTRIBUTE_HELPER_CPP

Lihat dokumentasi API untuk konstruksi ini untuk informasi selengkapnya.

Inisialisasi Memesan
Atribut dalam sistem tidak boleh bergantung pada status Atribut lain dalam hal ini
sistem. Ini karena pengurutan inisialisasi Atribut tidak ditentukan, juga tidak
ditegakkan, oleh sistem. Contoh spesifik dari ini dapat dilihat dalam konfigurasi otomatis
program seperti Toko Konfigurasi. Meskipun model tertentu dapat mengaturnya sedemikian rupa sehingga Atribut
diinisialisasi dalam urutan tertentu, konfigurator otomatis lain dapat memutuskan
independen untuk mengubah Atribut, misalnya, urutan abjad.

Karena pengurutan non-spesifik ini, tidak ada Atribut dalam sistem yang mungkin memiliki ketergantungan
pada setiap Atribut lainnya. Sebagai konsekuensinya, Atribut setter tidak boleh gagal karena keadaan
dari Atribut lain. Tidak ada penyetel Atribut yang dapat mengubah (mengatur) nilai Atribut lainnya sebagai
hasil dari perubahan nilainya.

Ini adalah batasan yang sangat kuat dan ada kasus di mana Atribut harus ditetapkan
konsisten untuk memungkinkan operasi yang benar. Untuk tujuan ini, kami mengizinkan pemeriksaan konsistensi
ketika itu atribut is bekas (cf. NS_ASSERT_MSG or NS_ABORT_MSG).

Secara umum, kode atribut untuk menetapkan nilai ke variabel anggota kelas yang mendasarinya
dieksekusi setelah sebuah objek dibangun. Tetapi bagaimana jika Anda membutuhkan nilai yang ditetapkan?
sebelum badan konstruktor dijalankan, karena Anda membutuhkannya dalam logika
konstruktor? Ada cara untuk melakukan ini, digunakan misalnya di kelas Toko Konfigurasi: panggilan
Basis Objek::ConstructSelf () sebagai berikut:

ConfigStore::ConfigStore ()
{
ObjectBase::ConstructSelf (AttributeConstructionList ());
// lanjutkan dengan konstruktor.
}

Hati-hati bahwa objek dan semua kelas turunannya juga harus mengimplementasikan a DapatkanInstanceTypeId
() metode. Jika tidak, Basis Objek::ConstructSelf () tidak akan bisa membaca
atribut.

Menambahkan atribut
ns-3 sistem akan menempatkan sejumlah nilai internal di bawah sistem atribut, tetapi
tidak diragukan lagi pengguna akan ingin memperpanjang ini untuk mengambil yang kami lewatkan, atau untuk menambahkan mereka
kelas sendiri ke sistem.

Ada tiga kasus penggunaan yang khas:

· Membuat anggota data kelas yang ada dapat diakses sebagai Atribut, padahal belum.

· Membuat kelas baru mampu mengekspos beberapa anggota data sebagai Atribut dengan memberikan TypeId.

· Membuat Nilai Atribut subclass untuk kelas baru sehingga dapat diakses sebagai
Atribut.

yang ada Anggota Variabel
Pertimbangkan variabel ini dalam soket tcp:

uint32_t m_cWnd; // Jendela kemacetan

Misalkan seseorang yang bekerja dengan TCP ingin mendapatkan atau mengatur nilai variabel itu
menggunakan sistem metadata. Jika belum disediakan oleh ns-3, pengguna dapat mendeklarasikan
tambahan berikut dalam sistem metadata runtime (untuk DapatkanTypeId() definisi untuk
soket tcp):

.AddAttribute ("Jendela kemacetan",
"Jendela kemacetan TCP (byte)",
NilaiUinteger (1),
MakeUintegerAccessor (&TcpSocket::m_cWnd),
MakeUintegerChecker ())

Sekarang, pengguna dengan pointer ke a soket tcp instance dapat melakukan operasi seperti
pengaturan dan mendapatkan nilai, tanpa harus menambahkan fungsi-fungsi ini secara eksplisit.
Selanjutnya, kontrol akses dapat diterapkan, seperti mengizinkan parameter untuk dibaca dan
tidak tertulis, atau pemeriksaan batas pada nilai yang diizinkan dapat diterapkan.

New Kelas TypeId
Di sini, kami membahas dampak pada pengguna yang ingin menambahkan kelas baru ke ns-3. Apa
hal-hal tambahan yang harus dilakukan untuk memungkinkannya menyimpan atribut?

Mari kita asumsikan kelas baru kita, yang disebut ns3::Mobilitas Saya, adalah jenis model mobilitas. Pertama,
kelas harus mewarisi dari kelas induknya, ns3::Model Mobilitas. di mobilitas saya.h
berkas kepala:

ruang nama ns3 {

kelas Kelas Saya : Model Mobilitas publik
{

Ini mengharuskan kami menyatakan DapatkanTypeId () fungsi. Ini adalah fungsi publik satu baris
pernyataan:

publik:
/ **
* Daftarkan jenis ini.
* \return Objek TypeId.
*/
static TypeId GetTypeId (batal);

Kami telah memperkenalkan apa yang TypeId definisi akan terlihat seperti di mobilitas-saya.cc
file implementasi:

NS_OBJECT_ENSURE_REGISTERED (Mobilitas Saya);

TypeId
MyMobility::GetTypeId (batal)
{
static TypeId tid = TypeId ("ns3::MyMobility")
.SetInduk ()
.SetGroupName ("Mobilitas")
.TambahkanKonstruktor ()
.AddAttribute ("Bounds",
"Batas area untuk berlayar.",
Nilai Persegi Panjang (Persegi Panjang (0.0, 0.0, 100.0, 100.0)),
MakeRectangleAccessor (&Mobilitas Saya::m_bounds),
MakeRectangleChecker ())
.AddAttribute ("Waktu",
"Ubah arah dan kecepatan saat ini setelah bergerak untuk penundaan ini.",
TimeValue (Detik (1.0)),
MakeTimeAccessor (&MyMobility::m_modeTime),
Pemeriksa Waktu ())
// dll (lebih banyak parameter).
;
kembali tid;
}

Jika kita tidak ingin subclass dari kelas yang ada, di file header kita hanya mewarisi
dari ns3::Objek, dan dalam file objek kami mengatur kelas induk ke ns3::Objek dengan
.SetInduk ().

Kesalahan umum di sini melibatkan:

· Tidak menelepon NS_OBJECT_ENSURE_REGISTERED ()

· Tidak memanggil SetInduk () metode, atau memanggilnya dengan tipe yang salah.

· Tidak memanggil TambahkanKonstruktor () metode, atau memanggilnya dengan tipe yang salah.

· Memperkenalkan kesalahan ketik atas nama TypeId dalam konstruktornya.

· Tidak menggunakan nama tipe C++ yang sepenuhnya memenuhi syarat dari kelas C++ terlampir sebagai nama dari
TypeId. Catat itu "ns3::" Dibutuhkan.

Tak satu pun dari kesalahan ini dapat dideteksi oleh ns-3 basis kode, jadi pengguna disarankan untuk memeriksa
hati-hati beberapa kali bahwa mereka punya hak ini.

New Nilai Atribut Tipe
Dari perspektif pengguna yang menulis kelas baru di sistem dan menginginkannya
dapat diakses sebagai atribut, terutama masalah penulisan konversi ke/dari
string dan nilai atribut. Sebagian besar dari ini dapat disalin/ditempel dengan kode makro. Untuk
misalnya, pertimbangkan deklarasi kelas untuk empat persegi panjang dalam src/mobilitas/model direktori:

Header File
/ **
* \singkat persegi panjang 2d
*/
kelas persegi panjang
{
...

xMin ganda;
xMax ganda;
yMin ganda;
ganda yMax;
};

Satu panggilan makro dan dua operator, harus ditambahkan di bawah deklarasi kelas untuk
mengubah Persegi Panjang menjadi nilai yang dapat digunakan oleh Atribut sistem:

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

ATTRIBUTE_HELPER_HEADER (Persegi Panjang);

Organisasi File
Dalam definisi kelas (Cc. file), kodenya terlihat seperti ini:

ATTRIBUTE_HELPER_CPP (Persegi Panjang);

std::ostream &
operator << (std::ostream &os, const Persegi Panjang &persegi panjang)
{
os << persegi panjang.xMin << "|" << persegi panjang.xMaks << "|" << persegi panjang.yMin << "|"
<< persegi panjang.yMax;
kembalikan;
}
std::istream &
operator >> (std::istream &is, Rectangle &rectangle)
{
karakter c1, c2, c3;
adalah >> persegi panjang.xMin >> c1 >> persegi panjang.xMax >> c2 >> persegi panjang.yMin >> c3
>> persegi panjang.yMax;
jika (c1 != '|' ||
c2 != '|' ||
c3 != '|')
{
is.setstate (std::ios_base::failbit);
}
kembali adalah;
}

Operator aliran ini hanya mengonversi dari representasi string dari Rectangle
("xMin|xMax|yMin|yMax") ke Rectangle di bawahnya. Pemodel harus menentukan ini
operator dan representasi sintaksis string dari instance kelas baru.

Toko Konfigurasi
Nilai untuk ns-3 atribut dapat disimpan dalam file teks ASCII atau XML dan dimuat ke dalam a
simulasi masa depan. Fitur ini dikenal sebagai ns-3 Toko Konfigurasi. Itu Toko Konfigurasi is
database khusus untuk nilai atribut dan nilai default.

Meskipun ini adalah modul yang dikelola secara terpisah di src/config-store/ direktori, kami
dokumentasikan di sini karena ketergantungannya satu-satunya pada ns-3 modul inti dan atribut.

Kita dapat menjelajahi sistem ini dengan menggunakan contoh dari
src/config-store/examples/config-store-save.cc.

Pertama, semua pengguna Toko Konfigurasi harus menyertakan pernyataan berikut:

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

Selanjutnya, program ini menambahkan objek sampel Contoh Konfigurasi untuk menunjukkan bagaimana sistem diperluas:

kelas ConfigContoh : Objek publik
{
publik:
static TypeId GetTypeId (batal) {
static TypeId tid = TypeId ("ns3::A")
.SetInduk ()
.AddAttribute ("TestInt16", "teks bantuan",
Nilai Integer (-2),
MakeIntegerAccessor (&A::m_int16),
JadikanIntegerChecker ())
;
kembali tid;
}
int16_t m_int16;
};

NS_OBJECT_ENSURE_REGISTERED (ConfigureContoh);

Selanjutnya, kami menggunakan subsistem Config untuk mengganti default dalam beberapa cara:

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

Ptr a_obj = BuatObjek ();
NS_ABORT_MSG_UNLESS (a_obj->m_int16 == -5,
"Tidak dapat menyetel atribut integer ConfigExample melalui Config::SetDefault");

Ptr a2_obj = BuatObjek ();
a2_obj->SetAttribute("TestInt16", Nilai Integer (-3));
Nilai Integer iv;
a2_obj->GetAttribute("TestInt16", iv);
NS_ABORT_MSG_UNLESS (iv.Dapatkan () == -3,
"Tidak dapat menyetel atribut integer ConfigExample melalui SetAttribute");

Pernyataan berikutnya diperlukan untuk memastikan bahwa (salah satu) objek yang dibuat telah di-root
dalam namespace konfigurasi sebagai instance objek. Ini biasanya terjadi ketika Anda
agregat objek ke a ns3::Simpul or ns3::Saluran misalnya, tapi di sini, karena kita sedang bekerja
di tingkat inti, kita perlu membuat objek namespace root baru:

Konfigurasi::RegisterRootNamespaceObject (a2_obj);

Writing
Selanjutnya, kami ingin menampilkan penyimpanan konfigurasi. Contoh menunjukkan bagaimana melakukannya dalam dua
format, XML dan teks mentah. Dalam praktiknya, seseorang harus melakukan langkah ini sebelum menelepon
Simulator::Lari () untuk menyimpan konfigurasi akhir sebelum menjalankan simulasi.

Ada tiga Atribut yang mengatur perilaku ConfigStore: "Mode",
"Nama file", dan "Format Berkas". Modus (default "Tidak ada") mengonfigurasi apakah ns-3 harus
memuat konfigurasi dari file yang disimpan sebelumnya (sebutkan "Mode = Beban") atau simpan ke file
(menentukan "Modus = Simpan"). Nama File (default "") adalah tempat ConfigStore harus membaca atau
menulis datanya. FileFormat (default "Teks Mentah") mengatur apakah format ConfigStore
adalah teks biasa atau Xml ("Format Berkas = 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"));
Keluaran ConfigStoreConfig;
outputConfig.ConfigureDefaults();
outputConfig.ConfigureAttributes();

// Keluarkan config store 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 keluaranConfig2;
outputConfig2.ConfigureDefaults();
outputConfig2.ConfigureAttributes();

Simulator::Jalankan ();

Simulator::Hancurkan ();

Perhatikan penempatan pernyataan-pernyataan ini tepat sebelum Simulator::Lari () pernyataan.
Keluaran ini mencatat semua nilai yang ada sesaat sebelum memulai simulasi (yaitu.
setelah semua konfigurasi telah terjadi).

Setelah berjalan, Anda dapat membuka atribut-output.txt file dan lihat:

default ns3::RealtimeSimulatorImpl::SynchronizationMode "BestEffort"
default ns3::RealtimeSimulatorImpl::HardLimit "+100000000.0ns"
default ns3::PcapFileWrapper::CaptureSize "65535"
default ns3::PacketSocket::RcvBufSize "131072"
default ns3::ErrorModel::IsEnabled "benar"
default ns3::RateErrorModel::ErrorUnit "EU_BYTE"
default ns3::RateErrorModel::ErrorRate "0"
default ns3::RateErrorModel::RanVar "Uniform:0:1"
default ns3::DropTailQueue::Mode "Paket"
default ns3::DropTailQueue::MaxPackets "100"
default ns3::DropTailQueue::MaxBytes "6553500"
default ns3::Aplikasi::StartTime "+0.0ns"
default ns3::Aplikasi::StopTime "+0.0ns"
default ns3::ConfigStore::Mode "Simpan"
default ns3::ConfigStore::Nama file "output-attributes.txt"
default ns3::ConfigStore::FileFormat "RawText"
default ns3::ConfigExample::TestInt16 "-5"
RngSeed global "1"
RngRun global "1"
global SimulatorImplementationType "ns3::DefaultSimulatorImpl"
SchedulerType global "ns3::MapScheduler"
global ChecksumEnabled "salah"
nilai /$ns3::ConfigExample/TestInt16 "-3"

Di atas, semua nilai default untuk atribut untuk modul inti ditampilkan.
Kemudian, semua nilai untuk ns-3 nilai global dicatat. Akhirnya, nilai
contoh Contoh Konfigurasi yang di-root di namespace konfigurasi ditampilkan. Di sebuah
nyata ns-3 program, lebih banyak model, atribut, dan default akan ditampilkan.

Versi XML juga ada di atribut-output.xml:




























File ini dapat diarsipkan dengan skrip simulasi dan data keluaran Anda.

Bacaan
Selanjutnya, kita membahas konfigurasi simulasi melalui file konfigurasi input yang tersimpan. Ada
beberapa perbedaan utama dibandingkan dengan menulis konfigurasi simulasi akhir.
Pertama, kita perlu menempatkan pernyataan seperti ini di awal program, sebelum
pernyataan konfigurasi simulasi ditulis (sehingga nilainya didaftarkan sebelum
digunakan dalam konstruksi objek).

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

Selanjutnya, perhatikan bahwa memuat data konfigurasi input terbatas pada Atribut default (yaitu.
bukan contoh) nilai, dan nilai global. Nilai instance atribut tidak didukung
karena pada tahap simulasi ini, sebelum objek dibangun, tidak ada
contoh objek seperti itu di sekitar. (Catatan, peningkatan di masa mendatang ke toko konfigurasi dapat berubah
perilaku ini).

Kedua, sedangkan keluaran dari Toko Konfigurasi negara akan mencantumkan semua yang ada di database, the
file input hanya perlu berisi nilai spesifik yang akan diganti. Jadi, salah satu cara untuk menggunakan
kelas ini untuk konfigurasi file input adalah untuk menghasilkan konfigurasi awal menggunakan
keluaran ("Menyimpan") "Mode" dijelaskan di atas, ekstrak dari file konfigurasi itu hanya
elemen yang ingin diubah, dan pindahkan elemen minimal ini ke file konfigurasi baru
yang kemudian dapat dengan aman diedit dan dimuat dalam simulasi berikutnya.

Ketika Toko Konfigurasi objek dipakai, atributnya "Nama file", "Mode", dan
"Format Berkas" harus diatur juga melalui baris perintah atau melalui pernyataan program.

Membaca/Menulis Example
Sebagai contoh yang lebih rumit, mari kita asumsikan bahwa kita ingin membaca dalam konfigurasi
default dari file input bernama masukan-default.xml, dan tuliskan hasilnya
atribut ke file terpisah yang disebut atribut-output.xml.:

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

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

//
// Izinkan pengguna untuk mengganti salah satu default dan Bind () di atas di
// run-time, melalui argumen baris perintah
//
cmd baris perintah;
cmd.Parse (argc, argv);

// mengatur topologi
...

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

Toko Konfigurasi GUI
Ada front end berbasis GTK untuk ConfigStore. Ini memungkinkan pengguna untuk menggunakan GUI untuk
mengakses dan mengubah variabel. Tangkapan layar dari fitur ini tersedia di |ns3|
Ringkasan presentasi.

Untuk menggunakan fitur ini, seseorang harus menginstal libgtk dan libgtk-dev; contoh Ubuntu
perintah instalasi adalah:

$ sudoapt-get install libgtk2.0-0 libgtk2.0-dev

Untuk memeriksa apakah sudah dikonfigurasi atau tidak, periksa output dari langkah:

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

---- Ringkasan fitur NS-3 opsional:
Binding Python: diaktifkan
Dukungan Pemindaian API Python: diaktifkan
Integrasi Klik NS-3 : diaktifkan
GtkConfigStore : tidak diaktifkan (pustaka 'gtk+-2.0 >= 2.12' tidak ditemukan)

Dalam contoh di atas, itu tidak diaktifkan, sehingga tidak dapat digunakan sampai versi yang sesuai adalah
diinstal dan:

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

dijalankan ulang.

Penggunaannya hampir sama dengan versi non-GTK, tetapi tidak ada Toko Konfigurasi
atribut yang terlibat:

// Panggil sebelum memasuki Simulator::Run ()
konfigurasi GtkConfigStore;
config.ConfigureDefaults();
config.ConfigureAttributes();

Sekarang, ketika Anda menjalankan skrip, GUI akan muncul, memungkinkan Anda untuk membuka menu dari
atribut pada node/objek yang berbeda, lalu luncurkan eksekusi simulasi saat Anda
selesai.

Masa depan kerja
Ada beberapa kemungkinan peningkatan:

· Simpan nomor versi unik dengan tanggal dan waktu di awal file.

· Simpan benih awal rng di suatu tempat.

· Buat setiap RandomVariable membuat serial seed awalnya sendiri dan membacanya kembali nanti.

obyek nama
placeholder bab

Logging
ns-3 fasilitas logging dapat digunakan untuk memantau atau men-debug kemajuan simulasi
program. Keluaran logging dapat diaktifkan dengan pernyataan program di . Anda utama() program atau
dengan menggunakan NS_LOG variabel lingkungan.

Pernyataan logging tidak dikompilasi ke dalam build yang dioptimalkan dari ns-3. Untuk menggunakan logging, satu
harus membangun build debug (default) dari ns-3.

Proyek tidak menjamin apakah hasil logging akan tetap sama atau tidak
waktu. Pengguna diperingatkan agar tidak membangun kerangka kerja keluaran simulasi di atas logging
kode, karena output dan cara output diaktifkan dapat berubah seiring waktu.

Ringkasan
ns-3 pernyataan logging biasanya digunakan untuk mencatat berbagai acara eksekusi program, seperti:
sebagai terjadinya peristiwa simulasi atau penggunaan fungsi tertentu.

Misalnya, cuplikan kode ini berasal dari Protokol Ipv4L3::IsDestinationAddress():

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

Jika logging telah diaktifkan untuk Protokol IPv4L3 komponen pada tingkat keparahan LOGIKA or
di atas (lihat di bawah tentang tingkat keparahan log), pernyataan akan dicetak; jika tidak, itu
akan ditekan.

Mengaktifkan Keluaran
Ada dua cara yang biasanya digunakan pengguna untuk mengontrol keluaran log. Yang pertama adalah dengan mengatur
NS_LOG variabel lingkungan; misalnya:

$ NS_LOG="*" ./waf --jalankan dulu

akan menjalankan pertama program tutorial dengan semua output logging. (Spesifikasi dari NS_LOG
format akan dibahas di bawah.)

Ini dapat dibuat lebih terperinci dengan memilih komponen individual:

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

Outputnya dapat disesuaikan lebih lanjut dengan opsi awalan.

Cara kedua untuk mengaktifkan logging adalah dengan menggunakan pernyataan eksplisit dalam program Anda, seperti di
itu pertama program tutorial:

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

(Arti dari LOG_LEVEL_INFO, dan kemungkinan nilai lainnya, akan dibahas di bawah.)

NS_LOG Sintaksis
NS_LOG variabel lingkungan berisi daftar komponen dan opsi log. Catatan
komponen dipisahkan oleh karakter `:':

$NS_LOG=" : ..."

Opsi untuk setiap komponen log diberikan sebagai tanda setelah setiap komponen log:

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

Opsi mengontrol tingkat keparahan dan level untuk komponen itu, dan apakah opsional
informasi harus disertakan, seperti waktu simulasi, simpul simulasi, fungsi
nama, dan tingkat keparahan simbolis.

Log Komponen
Umumnya komponen log mengacu pada satu kode sumber Cc. file, dan mencakup
seluruh file.

Beberapa helper memiliki metode khusus untuk mengaktifkan pencatatan semua komponen dalam modul,
mencakup unit kompilasi yang berbeda, tetapi secara logis dikelompokkan bersama, seperti ns-3
kode wifi:

Wifi Pembantu wifi Pembantu;
wifiHelper.EnableLogComponents();

NS_LOG wildcard komponen log `*' akan mengaktifkan semua komponen.

Untuk melihat komponen log apa yang ditentukan, salah satu dari ini akan berfungsi:

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

$ NS_LOG="foo" # token tidak cocok dengan komponen log mana pun

Formulir pertama akan mencetak nama dan flag yang diaktifkan untuk semua komponen log yang
terhubung dalam; coba dengan awal-simulator. Formulir kedua mencetak semua log yang terdaftar
komponen, lalu keluar dengan kesalahan.

Kerasnya dan Tingkat Opsi
Pesan individual termasuk dalam satu "kelas tingkat keparahan", yang ditetapkan oleh makro yang membuat
pesan. Pada contoh di atas, NS_LOG_LOGIC(..) membuat pesan di LOG_LOGIC
kelas keparahan.

Kelas keparahan berikut didefinisikan sebagai: enum konstanta:

┌────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
Kelas Keparahan Artinya
├────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
LOG_TIDAK ADA Default, tidak ada logging
├────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
LOG_ERROR Hanya pesan kesalahan serius
├────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
LOG_PERINGATAN Pesan peringatan
├────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
LOG_DEBUG Untuk digunakan dalam debugging
├────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
LOG_INFO Informasi
├────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
LOG_FUNGSI Pelacakan fungsi
├────── teks acoran───X chambatan uracebookansans XNUMX. Missacam "" "" "XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX Chsansansans XNUMX Chsans XNUMX Chss XNUMX Chs XNUMX XNUMX XNUMX XNUMX XNUMX Chssp
LOG_LOGIC Kontrol penelusuran aliran di dalam
fungsi
└─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Chocanding "" "" "" XNUMXirim XNUMXirim XNUMXans XNUMXans XNUMX Choll XNUMX Chosans XNUMX Chosansans XNUMX ChosososES Miss── Denganstrbum XNUMXirim XNUMXirim XNUMXkan XNUMXansansans Ch

Biasanya seseorang ingin melihat pesan pada kelas keparahan tertentu dan lebih tinggi. Ini dilakukan oleh
mendefinisikan "level" logging inklusif:

┌───────────────────┬───────────────────────────── ─────┐
Tingkat Artinya
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_ERROR Hanya LOG_ERROR kelas keparahan
pesan.
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_PERINGATANLOG_PERINGATAN dan di atas.
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_DEBUGLOG_DEBUG dan di atas.
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_INFOLOG_INFO dan di atas.
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_FUNCTIONLOG_FUNGSI dan di atas.
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_LOGICLOG_LOGIC dan di atas.
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_ALL Semua kelas keparahan.
├───────────────────┼───────────────────────────── ─────┤
LOG_SEMUA Sinonim untuk LOG_LEVEL_ALL
└───────────────────┴───────────────────────────── ─────┘

Kelas keparahan dan opsi level dapat diberikan di NS_LOG variabel lingkungan dengan
token ini:

┌─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
Kelas Tingkat
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
kesalahantingkat_kesalahan
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
memperingatkanlevel_peringatan
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
men-debuglevel_debug
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
Infoinfo_level
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
fungsilevel_fungsi
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
logikalevel_logika
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans
│ │. level_semua
│ │. semua
│ │. *
└─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Choll XNUMXX XNUMX Chack XNUMX Chack XNUMX Chack XNUMXososoto Miss padamans

Menggunakan token kelas keparahan hanya mengaktifkan pesan log pada tingkat keparahan itu. Sebagai contoh,
NS_LOG="*=peringatkan" tidak akan menampilkan pesan dengan tingkat keparahan kesalahan. NS_LOG="*=level_debug" akan
pesan keluaran pada tingkat keparahan men-debug dan di atas.

Kelas dan tingkat keparahan dapat digabungkan dengan `|' operator:
NS_LOG="*=level_warn|logika" akan menampilkan pesan pada tingkat keparahan kesalahan, memperingatkan dan logika.

NS_LOG wildcard tingkat keparahan `*' dan semua adalah sinonim untuk level_semua.

Untuk komponen log yang hanya disebutkan di NS_LOG

$NS_LOG=" :..."

tingkat keparahan default adalah LOG_LEVEL_ALL.

Awalan Opsi
Sejumlah awalan dapat membantu mengidentifikasi di mana dan kapan pesan berasal, dan pada apa
kerasnya.

Opsi awalan yang tersedia (sebagai enum konstanta) adalah

┌─────────────────┬─────────────────────────────── ───┐
Simbol Awalan Artinya
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_FUNC Awalan nama panggilan
fungsi.
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_TIME Awalan waktu simulasi.
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_NODE Awalan id simpul.
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_LEVEL Awalan tingkat keparahan.
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_ALL Aktifkan semua awalan.
└─────────────────┴─────────────────────────────── ───┘

Opsi awalan dijelaskan secara singkat di bawah ini.

Pilihan dapat diberikan di NS_LOG variabel lingkungan dengan token ini:

┌─ans───── Chasan XNUMX Chollans XNUMX Choll XNUMXX XNUMX Choll XNUMX XNUMX XNUMX Chack XNUMX Chosmacol─ans─ans─
Token Alternatif
├─ans───── Chasan XNUMX Chollans XNUMX Choll XNUMXX XNUMX Choll XNUMX XNUMX XNUMX Chack XNUMX Chosmacol─ans─ans─
awalan_fungsifungsi
├─ans───── Chasan XNUMX Chollans XNUMX Choll XNUMXX XNUMX Choll XNUMX XNUMX XNUMX Chack XNUMX Chosmacol─ans─ans─
awalan_waktuwaktu
└─ans───── Chasan XNUMX Chollans XNUMX Choll XNUMXX XNUMX Choll XNUMX XNUMX XNUMX Chack XNUMX Chosmacol padaman─ansans Miss

awalan_nodesimpul
├─ans───── Chasan XNUMX Chollans XNUMX Choll XNUMXX XNUMX Choll XNUMX XNUMX XNUMX Chack XNUMX Chosmacol─ans─ans─
awalan_leveltingkat
├─ans───── Chasan XNUMX Chollans XNUMX Choll XNUMXX XNUMX Choll XNUMX XNUMX XNUMX Chack XNUMX Chosmacol─ans─ans─
awalan_semuasemua
│ │. *
└─ans───── Chasan XNUMX Chollans XNUMX Choll XNUMXX XNUMX Choll XNUMX XNUMX XNUMX Chack XNUMX Chosmacol padaman─ansans Miss

Untuk komponen log yang hanya disebutkan di NS_LOG

$NS_LOG=" :..."

opsi awalan default adalah LOG_PREFIX_ALL.

Kerasnya Awalan
Kelas keparahan pesan dapat disertakan dengan opsi awalan_level or tingkat.
Misalnya, nilai ini NS_LOG mengaktifkan logging untuk semua komponen log (`*') dan semua
kelas keparahan (= semua), dan mengawali pesan dengan kelas keparahan (|tingkat_awalan).

$ NS_LOG="*=all|prefix_level" ./waf --run scratch-simulator
Simulator Goresan
[KESALAHAN] pesan kesalahan
[PERINGATAN] pesan peringatan
[DEBUG] pesan debug
[INFO] pesan info
Pesan fungsi [FUNCT]
[LOGIKA] pesan logika

Waktu Awalan
Waktu simulasi dapat disertakan dengan opsi awalan_waktu or waktu. Ini mencetak
waktu simulasi dalam hitungan detik.

Node Awalan
Id simpul simulasi dapat disertakan dengan opsi awalan_node or simpul.

fungsi Awalan
Nama fungsi panggilan dapat disertakan dengan opsi awalan_fungsi or fungsi.

NS_LOG Kartu liar
Wildcard komponen log `*' akan mengaktifkan semua komponen. Untuk mengaktifkan semua komponen di a
penggunaan tingkat keparahan tertentu *=.

Wildcard opsi tingkat keparahan `*' adalah sinonim untuk semua. Ini harus terjadi sebelum
`|' opsi pemisahan karakter. Untuk mengaktifkan semua kelas keparahan, gunakan ==,
or =*|.

Opsi wildcard `*' atau token semua mengaktifkan semua opsi awalan, tetapi harus terjadi setelah a
`|' karakter. Untuk mengaktifkan kelas atau tingkat keparahan tertentu, dan semua awalan, gunakan
= |*.

Wildcard opsi gabungan ** mengaktifkan semua tingkat keparahan dan semua awalan; Misalnya,
=**.

uber-wildcard *** mengaktifkan semua tingkat keparahan 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="*=*|*" ...

Diberitahukan: bahkan yang sepele awal-simulator menghasilkan lebih dari 46 ribu baris output dengan
NS_LOG="***"!

Seterpercayaapakah Olymp Trade? Kesimpulan untuk menambahkan penebangan untuk Tujuan kode
Menambahkan logging ke kode Anda sangat sederhana:

1. Panggil NS_LOG_COMPONENT_DEFINE (...); makro di dalam namespace ns3.
Buat pengidentifikasi string unik (biasanya berdasarkan nama file dan/atau kelas
didefinisikan dalam file) dan mendaftarkannya dengan panggilan makro seperti berikut:

ruang nama ns3 {

NS_LOG_COMPONENT_DEFINE ("Protokol IPv4L3");
...

Ini mendaftar Protokol IPv4L3 sebagai komponen log.

(Makro ditulis dengan hati-hati untuk memungkinkan penyertaan baik di dalam maupun di luar
namespace ns3, dan penggunaan akan bervariasi di seluruh basis kode, tetapi tujuan awalnya adalah untuk
daftarkan ini di luar dari namespace ns3 di file lingkup global.)

2. Tambahkan pernyataan logging (panggilan makro) ke fungsi dan badan fungsi Anda.

Logging Macro
Makro logging dan tingkat keparahan terkait adalah

┌────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
Kelas Keparahan Makro
├────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
LOG_TIDAK ADA (tidak diperlukan)
├────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
LOG_ERRORNS_LOG_ERROR (...);
├────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
LOG_PERINGATANNS_LOG_PERINGATAN (...);
├────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
LOG_DEBUGNS_LOG_DEBUG (...);
├────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
LOG_INFONS_LOG_INFO (...);
├────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
LOG_FUNGSINS_LOG_FUNCTION (...);
├────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig
LOG_LOGICNS_LOG_LOGIC (...);
└────── teks acoran───X chambatan ilangan ilangan Phace urans XNUMXansansansansans potacksILirimirim "irim XNUMXirimirimirim XNUMXirim "" XNUMXirimansansansansansans pig

Makro berfungsi sebagai streamer keluaran, jadi apa pun yang dapat Anda kirim ke std::keluar, bergabung
by << operator, diperbolehkan:

void MyClass::Check (nilai int, char * item)
{
NS_LOG_FUNCTION (ini << arg << item);
jika (arg > 10)
{
NS_LOG_ERROR ("menemukan nilai buruk " << nilai <
" sambil memeriksa " << nama << "!");
}
...
}

Perhatikan bahwa NS_LOG_FUNCTION secara otomatis memasukkan `,' (koma-spasi) pemisah antara
masing-masing argumennya. Ini menyederhanakan pencatatan argumen fungsi; hanya menggabungkan
mereka dengan << seperti pada contoh di atas.

Tak bersyarat Logging
Sebagai kemudahan, NS_LOG_UNCOND (...); makro akan selalu mencatat argumennya, bahkan jika
komponen log terkait tidak diaktifkan pada tingkat keparahan apa pun. Makro ini tidak menggunakan apapun
dari opsi awalan. Perhatikan bahwa logging hanya diaktifkan di build debug; makro ini
tidak akan menghasilkan output dalam build yang dioptimalkan.

Panduan
· Mulai setiap metode kelas dengan NS_LOG_FUNCTION (ini << argumen...); Ini memungkinkan mudah
pelacakan panggilan fungsi.

· Kecuali: jangan mencatat operator atau menyalin konstruktor secara eksplisit, karena ini akan menyebabkan
rekursi tak terbatas dan stack overflow.

· Untuk metode tanpa argumen gunakan bentuk yang sama: NS_LOG_FUNCTION (ini);

· Untuk fungsi statis:

· Dengan argumen gunakan NS_LOG_FUNCTION (...); seperti biasa.

· Tanpa argumen gunakan NS_LOG_FUNCTION_NOARGS ();

· Menggunakan NS_LOG_ERROR untuk kondisi kesalahan serius yang mungkin membatalkan simulasi
eksekusi.

· Menggunakan NS_LOG_PERINGATAN untuk kondisi yang tidak biasa yang mungkin dapat diperbaiki. Tolong beri beberapa petunjuk
tentang sifat masalah dan bagaimana hal itu dapat diperbaiki.

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

· Menggunakan NS_LOG_INFO untuk informasi tambahan tentang eksekusi, seperti ukuran a
struktur data saat menambahkan/menghapusnya.

· Menggunakan NS_LOG_LOGIC untuk melacak cabang logika penting dalam suatu fungsi.

· Uji bahwa perubahan logging Anda tidak merusak kode. Jalankan beberapa contoh program dengan
semua komponen log dihidupkan (mis NS_LOG="***").

jiplakan
Subsistem penelusuran adalah salah satu mekanisme terpenting untuk dipahami dalam ns-3. di
Kebanyakan kasus, ns-3 pengguna akan memiliki ide cemerlang untuk beberapa jaringan baru dan lebih baik
fitur. Untuk memverifikasi bahwa ide ini berhasil, peneliti akan membuat perubahan pada
sistem yang ada dan kemudian menjalankan eksperimen untuk melihat bagaimana fitur baru berperilaku dengan mengumpulkan
statistik yang menangkap perilaku fitur.

Dengan kata lain, inti dari menjalankan simulasi adalah untuk menghasilkan output untuk lebih lanjut
belajar. Di ns-3, subsistem yang memungkinkan peneliti melakukan ini adalah penelusuran
subsistem.

jiplakan Motivasi
Ada banyak cara untuk mendapatkan informasi dari sebuah program. Cara yang paling mudah adalah
untuk langsung mencetak informasi ke output standar, seperti pada,

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

Ini bisa diterapkan di lingkungan kecil, tetapi saat simulasi Anda semakin banyak
rumit, Anda berakhir dengan semakin banyak cetakan dan tugas menguraikan dan melakukan
perhitungan pada output mulai semakin sulit.

Hal lain yang perlu dipertimbangkan adalah bahwa setiap kali berita gembira baru diperlukan, inti perangkat lunak
harus diedit dan cetakan lain diperkenalkan. Tidak ada cara standar untuk mengendalikan semua
output ini, sehingga jumlah output cenderung tumbuh tanpa batas. Akhirnya,
bandwidth yang diperlukan hanya untuk mengeluarkan informasi ini mulai membatasi waktu berjalan
dari simulasi. File output tumbuh menjadi ukuran yang sangat besar dan menguraikannya menjadi
masalah.

ns-3 menyediakan mekanisme sederhana untuk mencatat dan menyediakan beberapa kontrol atas keluaran melalui
Log Komponen, tetapi tingkat kontrolnya tidak berbutir halus sama sekali. Pencatatan
modul adalah instrumen yang relatif tumpul.

Diinginkan untuk memiliki fasilitas yang memungkinkan seseorang untuk menjangkau ke dalam sistem inti dan hanya
mendapatkan informasi yang diperlukan tanpa harus mengubah dan mengkompilasi ulang sistem inti. Bahkan
lebih baik sistem yang memberi tahu pengguna ketika item yang menarik berubah atau
peristiwa menarik terjadi.

ns-3 sistem pelacakan dirancang untuk bekerja di sepanjang garis itu dan terintegrasi dengan baik dengan
Substem Atribut dan Config memungkinkan skenario penggunaan yang relatif sederhana.

Ringkasan
Subsistem penelusuran sangat bergantung pada ns-3 Mekanisme Callback dan Atribut. Anda
harus membaca dan memahami bagian yang sesuai dari manual sebelum mencoba untuk
memahami sistem pelacakan.

ns-3 sistem penelusuran dibangun di atas konsep sumber penelusuran independen dan
menelusuri wastafel; bersama dengan mekanisme seragam untuk menghubungkan sumber ke sink.

Sumber jejak adalah entitas yang dapat memberi sinyal peristiwa yang terjadi dalam simulasi dan menyediakan
akses ke data dasar yang menarik. Misalnya, sumber jejak dapat menunjukkan kapan a
paket diterima oleh perangkat net dan menyediakan akses ke isi paket untuk
jejak tertarik tenggelam. Sumber jejak mungkin juga menunjukkan kapan keadaan menarik
perubahan terjadi dalam sebuah model. Misalnya, jendela kemacetan model TCP adalah prima
kandidat untuk sumber jejak.

Sumber jejak tidak berguna dengan sendirinya; mereka harus terhubung ke potongan kode lainnya
yang benar-benar melakukan sesuatu yang berguna dengan informasi yang diberikan oleh sumbernya. Itu
entitas yang menggunakan informasi jejak disebut penyerap jejak. Sumber jejak adalah
generator acara dan jejak tenggelam adalah konsumen.

Pembagian eksplisit ini memungkinkan sejumlah besar sumber jejak tersebar di sekitar
sistem di tempat-tempat yang menurut penulis model mungkin berguna. Kecuali jika pengguna menghubungkan a
melacak wastafel ke salah satu sumber ini, tidak ada yang keluar. Pengaturan ini memungkinkan relatif
pengguna yang tidak mahir untuk melampirkan jenis sink baru ke sumber penelusuran yang ada, tanpa
membutuhkan pengeditan dan kompilasi ulang inti atau model simulator.

Mungkin ada nol atau lebih konsumen dari peristiwa jejak yang dihasilkan oleh sumber jejak. Satu bisa
pikirkan sumber jejak sebagai semacam tautan informasi point-to-multipoint.

"Protokol transportasi" untuk link point-to-multipoint konseptual ini adalah ns-3 Callback.

Ingat dari Bagian Panggilan Balik bahwa fasilitas panggilan balik adalah cara untuk mengizinkan dua modul masuk
sistem untuk berkomunikasi melalui panggilan fungsi sementara pada saat yang sama memisahkan panggilan
fungsi dari kelas yang dipanggil sepenuhnya. Ini adalah persyaratan yang sama seperti yang diuraikan di atas
untuk sistem pelacakan.

Pada dasarnya, sumber jejak is panggilan balik di mana beberapa fungsi dapat didaftarkan.
Saat trace sink menunjukkan minat untuk menerima peristiwa trace, ia menambahkan panggilan balik ke a
daftar panggilan balik yang dipegang oleh sumber jejak. Ketika sebuah peristiwa menarik terjadi, jejaknya
sumber memanggilnya operator() memberikan nol atau lebih parameter. Ini memberitahu sumber untuk
buka daftar panggilan baliknya yang memanggil masing-masing secara bergantian. Dengan cara ini, parameter
dikomunikasikan ke trace sink, yang hanya berfungsi.

Paling sederhana Example
Akan berguna untuk memberikan contoh singkat hanya untuk memperkuat apa yang telah kami katakan.:

#sertakan "ns3/object.h"
#sertakan "ns3/uinteger.h"
#sertakan "ns3/traced-value.h""
#sertakan "ns3/trace-source-accessor.h"

#termasuk

menggunakan namespace ns3;

Hal pertama yang harus dilakukan adalah memasukkan file yang diperlukan. Seperti disebutkan di atas, sistem pelacakan
banyak menggunakan sistem Object dan Attribute. Dua yang pertama termasuk membawa
deklarasi untuk sistem tersebut. Berkas, nilai terlacak.h membawa yang dibutuhkan
deklarasi untuk melacak data yang mematuhi semantik nilai.

Secara umum, semantik nilai hanya berarti bahwa Anda dapat meneruskan objek, bukan an
alamat. Untuk menggunakan semantik nilai sama sekali, Anda harus memiliki objek dengan
konstruktor salinan terkait dan operator penugasan tersedia. Kami memperluas persyaratan
untuk berbicara tentang set operator yang telah ditentukan sebelumnya untuk tipe data lama (POD).
Operator=, operator++, operator--, operator+, operator==, dll.

Apa artinya semua ini adalah bahwa Anda akan dapat melacak perubahan pada objek yang dibuat menggunakan
operator tersebut.:

kelas MyObject : Objek publik
{
publik:
TypeId statis GetTypeId (batal)
{
static TypeId tid = TypeId ("MyObject")
.SetParent (Objek::GetTypeId ())
.TambahkanKonstruktor ()
.AddTraceSource ("Integer Saya",
"Nilai integer untuk dilacak.",
MakeTraceSourceAccessor (&MyObject::m_myInt))
;
kembali tid;
}

Objek Saya () {}
Nilai Tertelusur m_myInt;
};

Karena sistem penelusuran terintegrasi dengan Atribut, dan Atribut bekerja dengan Objek,
pasti ada ns-3 obyek untuk sumber jejak untuk hidup. Dua baris penting dari
kode adalah .TambahkanTraceSource dan Nilai Tertelusur pernyataan.

.TambahkanTraceSource menyediakan "kait" yang digunakan untuk menghubungkan sumber jejak ke
dunia luar. Itu Nilai Tertelusur deklarasi menyediakan infrastruktur yang membebani
operator yang disebutkan di atas dan mendorong proses panggilan balik.:

membatalkan
IntTrace (Int OldValue, Int NewValue)
{
std::cout << "Dilacak " << oldValue << " ke " << newValue << std::endl;
}

Seperti itu penjelasan definisi sebenarnya dari kata trace sink. Ini berhubungan langsung dengan fungsi panggilan balik.
Fungsi ini akan dipanggil setiap kali salah satu operator dari Nilai Tertelusur is
dieksekusi.:

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

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

myObject->m_myInt = 1234;
}

Dalam cuplikan ini, hal pertama yang perlu dilakukan adalah membuat objek di mana
sumber jejak hidup.

Langkah selanjutnya, JejakHubungkanTanpa Konteks, membentuk hubungan antara jejak
sumber dan jejak tenggelam. Perhatikan Lakukan Panggilan Balik fungsi templat. Ingat dari
Bagian panggilan balik bahwa ini menciptakan fungsi khusus yang bertanggung jawab untuk menyediakan
kelebihan beban operator() digunakan untuk "memecat" panggilan balik. Operator yang kelebihan beban (++, --, dll.)
akan menggunakan ini operator() untuk benar-benar memanggil panggilan balik. Itu JejakHubungkanTanpa Konteks,
mengambil parameter string yang memberikan nama Atribut yang ditetapkan ke jejak
sumber. Mari kita abaikan sedikit tentang konteks untuk saat ini karena itu belum penting.

Akhirnya, baris,:

myObject->m_myInt = 1234;

harus ditafsirkan sebagai seruan dari operator= pada variabel anggota m_myInt dengan
bilangan bulat 1234 dilewatkan sebagai parameter. Ternyata operator ini didefinisikan (oleh
Nilai Tertelusur) untuk menjalankan panggilan balik yang mengembalikan void dan mengambil dua nilai integer sebagai
parameter -- nilai lama dan nilai baru untuk bilangan bulat yang dimaksud. Itu persis
tanda tangan fungsi untuk fungsi panggilan balik yang kami sediakan -- Jejak Int.

Untuk meringkas, sumber jejak, pada dasarnya, adalah variabel yang menyimpan daftar panggilan balik. SEBUAH
trace sink adalah fungsi yang digunakan sebagai target panggilan balik. Atribut dan tipe objek
sistem informasi digunakan untuk menyediakan cara untuk menghubungkan sumber jejak untuk melacak sink. Itu
tindakan "memukul" sumber jejak sedang mengeksekusi operator pada sumber jejak yang menyala
panggilan balik. Ini menghasilkan panggilan balik jejak sink yang mendaftarkan minat pada sumbernya
dipanggil dengan parameter yang disediakan oleh sumber.

Menggunakan itu config Subsistem untuk Terhubung untuk Jejak sumber
JejakHubungkanTanpa Konteks panggilan yang ditunjukkan di atas dalam contoh sederhana sebenarnya sangat
jarang digunakan dalam sistem. Lebih biasanya, config subsistem digunakan untuk memungkinkan pemilihan
sumber jejak dalam sistem menggunakan apa yang disebut a config path.

Misalnya, seseorang mungkin menemukan sesuatu yang terlihat seperti berikut ini dalam sistem (diambil
dari contoh/tcp-besar-transfer.cc):

membatalkan CwndTracer (uint32_t oldval, uint32_t newval) {}

...

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

Ini akan terlihat sangat akrab. Ini adalah hal yang sama seperti contoh sebelumnya, kecuali bahwa
fungsi anggota statis dari kelas config sedang dipanggil alih-alih metode aktif obyek;
dan bukannya Atribut nama, jalan sedang disediakan.

Hal pertama yang harus dilakukan adalah membaca jalur mundur. Segmen terakhir dari jalan harus
an Atribut dari obyek. Faktanya, jika Anda memiliki penunjuk ke obyek yang memiliki
"Jendela Kemacetan" Atribut berguna (sebut saja objek), Anda bisa menulis ini seperti
contoh sebelumnya:

membatalkan CwndTracer (uint32_t oldval, uint32_t newval) {}

...

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

Ternyata kode untuk Konfigurasi::HubungkanTanpaKonteks melakukan hal itu. Ini
fungsi mengambil jalur yang mewakili rantai obyek pointer dan mengikuti mereka sampai
sampai ke ujung jalan dan menafsirkan segmen terakhir sebagai Atribut di akhir
obyek. Mari kita berjalan melalui apa yang terjadi.

Karakter "/" terkemuka di jalur mengacu pada apa yang disebut namespace. salah satu dari
ruang nama yang telah ditentukan dalam sistem konfigurasi adalah "NodeList" yang merupakan daftar semua
node dalam simulasi. Item dalam daftar dirujuk oleh indeks ke dalam daftar, jadi
"/NodeList/0" mengacu pada node nol dalam daftar node yang dibuat oleh simulasi.
Simpul ini sebenarnya adalah Ptr dan begitu juga subkelas dari an ns3::Objek.

Seperti yang dijelaskan di bagian Model objek, ns-3 mendukung model agregasi objek. Itu
segmen jalur berikutnya dimulai dengan karakter "$" yang menunjukkan a DapatkanObjek panggilan harus
dibuat mencari jenis yang berikut. Ketika sebuah node diinisialisasi oleh
InternetStackHelper sejumlah antarmuka dikumpulkan ke node. Salah satunya adalah
TCP tingkat empat protokol. Jenis runtime dari objek protokol ini adalah ns3::TcpL4Protocol''.
Ketika itu ``Dapatkan Objek dijalankan, ia mengembalikan pointer ke objek jenis ini.

TCPL4Protokol class mendefinisikan Atribut yang disebut "SocketList" yang merupakan daftar dari
soket. Setiap soket sebenarnya adalah ns3::Objek dengan miliknya sendiri atribut. Barang-barang di
daftar soket dirujuk oleh indeks seperti di NodeList, jadi "SocketList/0"
mengacu pada soket ke-nol dalam daftar soket pada simpul ke-nol di NodeList --
node pertama dibangun dalam simulasi.

Soket ini, yang jenisnya ternyata adalah ns3::TcpSocketImpl mendefinisikan atribut
disebut "CongestionWindow" yang merupakan Nilai Tertelusur. itu
Konfigurasi::HubungkanTanpaKonteks sekarang melakukan,:

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

menggunakan penunjuk objek dari "SocketList/0" yang membuat koneksi antara jejak
sumber yang ditentukan dalam soket ke panggilan balik -- Pelacak Cwnd.

Sekarang, setiap kali ada perubahan pada Nilai Tertelusur mewakili kemacetan
jendela di soket TCP, panggilan balik terdaftar akan dieksekusi dan fungsinya
Pelacak Cwnd akan dipanggil untuk mencetak nilai-nilai lama dan baru dari kemacetan TCP
jendela.

Menggunakan itu jiplakan API
Ada tiga tingkat interaksi dengan sistem penelusuran:

· Pengguna pemula dapat dengan mudah mengontrol objek mana yang berpartisipasi dalam penelusuran;

· Pengguna perantara dapat memperluas sistem penelusuran untuk mengubah format keluaran yang dihasilkan
atau gunakan sumber jejak yang ada dengan cara yang berbeda, tanpa mengubah inti dari
simulator;

· Pengguna tingkat lanjut dapat memodifikasi inti simulator untuk menambahkan sumber penelusuran dan sink baru.

Menggunakan Jejak Pembantu
ns-3 trace helper menyediakan lingkungan yang kaya untuk mengonfigurasi dan memilih yang berbeda
melacak peristiwa dan menulisnya ke file. Di bagian sebelumnya, terutama "Bangunan
Topologi," kami telah melihat beberapa jenis metode trace helper yang dirancang untuk digunakan
di dalam pembantu (perangkat) lainnya.

Mungkin Anda akan ingat melihat beberapa variasi ini:

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

Apa yang mungkin tidak jelas, bagaimanapun, adalah bahwa ada model yang konsisten untuk semua
metode terkait jejak yang ditemukan dalam sistem. Sekarang kita akan mengambil sedikit waktu dan melihat-lihat
pada "gambaran besar".

Saat ini ada dua kasus penggunaan utama dari tracing helper di ns-3: Pembantu perangkat
dan pembantu protokol. Pembantu perangkat melihat masalah menentukan jejak mana yang harus
diaktifkan melalui node, pasangan perangkat. Misalnya, Anda mungkin ingin menentukan pcap . itu
tracing harus diaktifkan pada perangkat tertentu pada node tertentu. Ini mengikuti dari
ns-3 model konseptual perangkat, dan juga model konseptual dari berbagai perangkat
pembantu. Mengikuti secara alami dari ini, file yang dibuat mengikuti
- - Konvensi penamaan.

Pembantu protokol melihat masalah menentukan jejak mana yang harus diaktifkan melalui
pasangan protokol dan antarmuka. Ini mengikuti dari ns-3 model konseptual tumpukan protokol,
dan juga model konseptual internet stack helper. Secara alami, file jejak
harus mengikuti - - Konvensi penamaan.

Oleh karena itu, trace helper secara alami masuk ke dalam taksonomi dua dimensi. Ada
seluk-beluk yang mencegah keempat kelas berperilaku identik, tetapi kami berusaha untuk
buat semuanya bekerja semirip mungkin; dan bila memungkinkan ada analog untuk
semua metode di semua kelas.

┌─ans──── Chasan XNUMXirim XNUMXirim "" XNUMXirim "" "XNUMXirim" XNUMXirim "" XNUMXirim XNUMX olakkan ilangan ilangan olakkan─ans─ qewanding
pcap ascii
├─ans──── Chasan XNUMXirim XNUMXirim "" XNUMXirim "" "XNUMXirim" XNUMXirim "" XNUMXirim XNUMX olakkan ilangan ilangan olakkan─ans─ qewanding
Pembantu Perangkat
├─ans──── Chasan XNUMXirim XNUMXirim "" XNUMXirim "" "XNUMXirim" XNUMXirim "" XNUMXirim XNUMX olakkan ilangan ilangan olakkan─ans─ qewanding
Pembantu Protokol │
└────── Chasan XNUMXirim XNUMXirim "" "" "XNUMXirim tolasan tolasanasanasanaskanaskanaskan tolasanarmaskan XNUMX Chargater menolakansansansans pILESATANANANANANANANANANAN

Kami menggunakan pendekatan yang disebut a mixin untuk menambahkan fungsionalitas penelusuran ke kelas pembantu kami. SEBUAH
mixin adalah kelas yang menyediakan fungsionalitas yang diwarisi oleh subkelas.
Mewarisi dari mixin tidak dianggap sebagai bentuk spesialisasi tetapi benar-benar cara untuk
mengumpulkan fungsionalitas.

Mari kita lihat sekilas keempat kasus ini dan masing-masingnya mixin.

Pcap jiplakan alat Pembantu
Tujuan dari helper ini adalah untuk memudahkan penambahan fasilitas pcap trace yang konsisten ke
ns-3 perangkat. Kami ingin semua jenis pelacakan pcap bekerja sama di seluruh
semua perangkat, sehingga metode pembantu ini diwarisi oleh pembantu perangkat. Lihatlah
at src/network/helper/trace-helper.h jika Anda ingin mengikuti diskusi sambil melihat
kode nyata.

Kelas PcapHelperForDevice adalah mixin menyediakan fungsionalitas tingkat tinggi untuk digunakan
pelacakan pcap di ns-3 perangkat. Setiap perangkat harus menerapkan satu metode virtual
diwarisi dari kelas ini.:

virtual void EnablePcapInternal (awalan std::string, Ptr nd, bool promiscuous) = 0;

Tanda tangan dari metode ini mencerminkan pandangan perangkat-sentris dari situasi saat ini
tingkat. Semua metode publik yang diwarisi dari kelas PcapUserHelperForDevice kurangi menjadi
memanggil metode implementasi yang bergantung pada perangkat tunggal ini. Misalnya, level terendah
metode pcap,:

void EnablePcap (awalan std::string, Ptr nd, bool promiscuous = false, bool eksplisitFilename = false);

akan memanggil implementasi perangkat dari AktifkanPcapInternal secara langsung. Semua pcap publik lainnya
metode penelusuran membangun implementasi ini untuk memberikan tingkat pengguna tambahan
Kegunaan. Apa artinya ini bagi pengguna adalah bahwa semua pembantu perangkat dalam sistem akan
memiliki semua metode jejak pcap yang tersedia; dan semua metode ini akan bekerja dengan cara yang sama
jalan lintas perangkat jika perangkat mengimplementasikan AktifkanPcapInternal benar.

Pcap jiplakan alat Pembantu metode
void EnablePcap (awalan std::string, Ptr dan,
bool promiscuous = salah, bool eksplisitNamaFile = salah);
void EnablePcap (awalan std::string, std::string ndName,
bool promiscuous = salah, bool eksplisitNamaFile = salah);
void EnablePcap (awalan std::string, NetDeviceContainer d,
bool promiscuous = salah);
void EnablePcap (awalan std::string, NodeContainer n,
bool promiscuous = salah);
void EnablePcap (std::string awalan, uint32_t nodeid, uint32_t deviceid,
bool promiscuous = salah);
void EnablePcapAll (std::awalan string, bool promiscuous = false);

Di setiap metode yang ditunjukkan di atas, ada parameter default yang disebut promiscuous bahwa
default ke salah. Parameter ini menunjukkan bahwa jejak tidak boleh dikumpulkan di
modus promiscuous. Jika Anda ingin jejak Anda menyertakan semua lalu lintas yang terlihat oleh perangkat
(dan jika perangkat mendukung mode promiscuous) cukup tambahkan parameter true ke salah satu dari
panggilan di atas. Sebagai contoh,:

Ptr dan;
...
helper.EnablePcap ("awalan", nd, benar);

akan mengaktifkan pengambilan mode promiscuous di Perangkat Bersih ditentukan oleh nd.

Dua metode pertama juga menyertakan parameter default yang disebut eksplisitNama file itu akan
dibahas di bawah ini.

Anda didorong untuk membaca dengan teliti Doxygen untuk kelas PcapHelperForDevice untuk menemukan detailnya
dari metode ini; tapi untuk meringkas...

Anda dapat mengaktifkan pelacakan pcap pada pasangan node/net-device tertentu dengan menyediakan a
Ptr ke AktifkanPcap metode. Itu Ptr tersirat karena perangkat bersih
harus milik tepat satu Node. Sebagai contoh,:

Ptr dan;
...
helper.EnablePcap ("awalan", nd);

Anda dapat mengaktifkan pelacakan pcap pada pasangan node/net-device tertentu dengan menyediakan a
std::string mewakili string layanan nama objek ke AktifkanPcap metode. Itu
Ptr dicari dari string nama. Sekali lagi, tersirat karena
perangkat bersih bernama harus milik tepat satu Node. Sebagai contoh,:

Nama::Tambahkan ("server" ...);
Nama::Tambahkan ("server/eth0" ...);
...
helper.EnablePcap ("awalan", "server/ath0");

Anda dapat mengaktifkan pelacakan pcap pada kumpulan pasangan node/net-device dengan menyediakan a
Kontainer Perangkat Bersih. Untuk setiap Perangkat Bersih dalam wadah jenisnya dicentang. Untuk setiap
perangkat dari jenis yang tepat (jenis yang sama seperti yang dikelola oleh pembantu perangkat), tracing adalah
diaktifkan. Sekali lagi, tersirat karena perangkat bersih yang ditemukan harus benar-benar milik
satu Node. Sebagai contoh,:

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

Anda dapat mengaktifkan pelacakan pcap pada kumpulan pasangan node/net-device dengan menyediakan a
Kontainer Node. Untuk setiap Node dalam Kontainer Node terlampir Perangkat Bersih diulang.
Untuk setiap Perangkat Bersih dilampirkan ke setiap node dalam wadah, jenis perangkat itu adalah
diperiksa. Untuk setiap perangkat dari jenis yang tepat (jenis yang sama seperti yang dikelola oleh perangkat
helper), pelacakan diaktifkan.:

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

Anda dapat mengaktifkan pelacakan pcap berdasarkan ID node dan ID perangkat serta dengan eksplisit
Ptr. Masing-masing Node dalam sistem memiliki ID simpul bilangan bulat dan setiap perangkat terhubung ke simpul
memiliki ID perangkat bilangan bulat.:

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

Terakhir, Anda dapat mengaktifkan pelacakan pcap untuk semua perangkat di sistem, dengan tipe yang sama seperti
yang dikelola oleh pembantu perangkat.:

helper.EnablePcapAll ("awalan");

Pcap jiplakan alat Pembantu Filename Seleksi
Tersirat dalam deskripsi metode di atas adalah konstruksi nama file lengkap dengan
metode pelaksanaan. Dengan konvensi, jejak pcap di ns-3 sistem berbentuk
- identitas>- id>.pcap

Seperti disebutkan sebelumnya, setiap node dalam sistem akan memiliki id node yang ditetapkan sistem; dan
setiap perangkat akan memiliki indeks antarmuka (juga disebut id perangkat) relatif terhadap simpulnya.
Secara default, kemudian, file jejak pcap dibuat sebagai hasil dari mengaktifkan pelacakan pada yang pertama
perangkat node 21 menggunakan awalan "awalan" adalah awalan-21-1.pcap.

Anda selalu dapat menggunakan ns-3 layanan nama objek untuk membuatnya lebih jelas. Misalnya, jika
anda menggunakan layanan nama objek untuk menetapkan nama "server" ke node 21, pcap yang dihasilkan
nama file trace secara otomatis akan menjadi, awalan-server-1.pcap dan jika Anda juga menetapkan
beri nama "eth0" ke perangkat, nama file pcap Anda akan secara otomatis mengambil ini dan menjadi
bernama awalan-server-eth0.pcap.

Akhirnya, dua metode yang ditunjukkan di atas,:

void EnablePcap (awalan std::string, Ptr nd, bool promiscuous = false, bool eksplisitFilename = false);
void EnablePcap (awalan std::string, std::string ndName, bool promiscuous = false, bool eksplisitFilename = false);

memiliki parameter default yang disebut eksplisitNama file. Ketika disetel ke true, parameter ini
menonaktifkan mekanisme penyelesaian nama file otomatis dan memungkinkan Anda membuat eksplisit
nama file. Opsi ini hanya tersedia dalam metode yang mengaktifkan pelacakan pcap di a
perangkat tunggal.

Misalnya, untuk mengatur pembantu perangkat untuk membuat pcap promiscuous tunggal
ambil file dengan nama tertentu (file-pcap-saya.pcap) pada perangkat tertentu, seseorang dapat:

Ptr dan;
...
helper.EnablePcap ("file-pcap-saya.pcap", nd, benar, benar);

Pertama benar parameter memungkinkan jejak mode promiscuous dan yang kedua memberi tahu helper
untuk menafsirkan awalan parameter sebagai nama file lengkap.

ASCII jiplakan alat Pembantu
Perilaku pembantu jejak ascii mixin secara substansial mirip dengan versi pcap.
Melihat src/network/helper/trace-helper.h jika Anda ingin mengikuti diskusi
sambil melihat kode nyata.

Kelas AsciiTraceHelperForDevice menambahkan fungsionalitas tingkat tinggi untuk menggunakan ascii
menelusuri ke kelas pembantu perangkat. Seperti dalam kasus pcap, setiap perangkat harus mengimplementasikan a
metode virtual tunggal yang diwarisi dari jejak ascii mixin.:

virtual void EnableAsciiInternal (Ptr aliran, std::awalan string, Ptr nd) = 0;

Tanda tangan dari metode ini mencerminkan pandangan perangkat-sentris dari situasi saat ini
tingkat; dan juga fakta bahwa helper mungkin menulis ke aliran keluaran bersama. Semua
metode terkait ascii-trace publik yang diwarisi dari kelas AsciiTraceHelperForDevice
kurangi untuk memanggil metode implementasi yang bergantung pada perangkat tunggal ini. Misalnya,
metode jejak ascii tingkat terendah,:

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

akan memanggil implementasi perangkat dari AktifkanAsciiInternal secara langsung, menyediakan baik a
awalan atau aliran yang valid. Semua metode penelusuran ascii publik lainnya akan dibangun di atas ini
fungsi tingkat rendah untuk menyediakan fungsionalitas tingkat pengguna tambahan. Apa artinya ini bagi
pengguna adalah bahwa semua pembantu perangkat dalam sistem akan memiliki semua metode pelacakan ascii
tersedia; dan semua metode ini akan bekerja dengan cara yang sama di seluruh perangkat jika perangkat
melaksanakan AktifkanAsciiInternal benar.

ASCII jiplakan alat Pembantu metode
void EnableAscii (awalan std::string, Ptr nd);
void EnableAscii (Ptr aliran, Ptr nd);

void EnableAscii (awalan std::string, std::string ndName);
void EnableAscii (Ptr aliran, std::string ndName);

membatalkan EnableAscii (std::string awalan, NetDeviceContainer d);
void EnableAscii (Ptr aliran, NetDeviceContainer d);

void EnableAscii (awalan std::string, NodeContainer n);
void EnableAscii (Ptr aliran, NodeContainer n);

batal EnableAscii (std::string awalan, uint32_t nodeid, uint32_t deviceid);
void EnableAscii (Ptr aliran, uint32_t nodeid, uint32_t deviceid);

void EnableAsciiAll (awalan std::string);
void EnableAsciiAll (Ptr sungai kecil);

Anda didorong untuk membaca dengan teliti Doxygen untuk kelas TraceHelperForDevice untuk menemukan
rincian metode ini; tapi untuk meringkas...

Ada dua kali lebih banyak metode yang tersedia untuk penelusuran ascii dibandingkan dengan pcap
pelacakan. Ini karena, selain model gaya pcap di mana jejak dari masing-masing
pasangan node/perangkat unik ditulis ke file unik, kami mendukung model di mana trace
informasi untuk banyak pasangan simpul/perangkat ditulis ke file umum. Ini berarti bahwa
- - mekanisme pembuatan nama file digantikan oleh mekanisme untuk
merujuk ke file umum; dan jumlah metode API digandakan untuk memungkinkan semua
kombinasi.

Sama seperti dalam pelacakan pcap, Anda dapat mengaktifkan pelacakan ascii pada pasangan node/net-device tertentu
dengan menyediakan Ptr ke Aktifkan Ascii metode. Itu Ptr tersirat karena
perangkat bersih harus milik tepat satu Node. Sebagai contoh,:

Ptr dan;
...
helper.EnableAscii ("awalan", nd);

Dalam hal ini, tidak ada konteks jejak yang ditulis ke file jejak ascii karena mereka akan menjadi
berulang. Sistem akan memilih nama file yang akan dibuat menggunakan aturan yang sama seperti
dijelaskan di bagian pcap, kecuali bahwa file tersebut akan memiliki akhiran ".tr" alih-alih
".pcap".

Jika Anda ingin mengaktifkan pelacakan ascii di lebih dari satu perangkat bersih dan semua jejak terkirim
ke satu file, Anda juga dapat melakukannya dengan menggunakan objek untuk merujuk ke satu file:

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

Dalam hal ini, konteks jejak ditulis ke file jejak ascii karena diperlukan
untuk membedakan jejak dari kedua perangkat. Perhatikan bahwa karena pengguna sepenuhnya
menentukan nama file, string harus menyertakan ".tr" untuk konsistensi.

Anda dapat mengaktifkan pelacakan ascii pada pasangan node/net-device tertentu dengan menyediakan a
std::string mewakili string layanan nama objek ke AktifkanPcap metode. Itu
Ptr dicari dari string nama. Sekali lagi, tersirat karena
perangkat bersih bernama harus milik tepat satu Node. Sebagai contoh,:

Nama::Tambahkan ("klien" ...);
Nama::Tambahkan ("klien/eth0" ...);
Nama::Tambahkan ("server" ...);
Nama::Tambahkan ("server/eth0" ...);
...
helper.EnableAscii ("awalan", "klien/eth0");
helper.EnableAscii ("awalan", "server/eth0");

Ini akan menghasilkan dua file bernama awalan-klien-eth0.tr dan awalan-server-eth0.tr dengan
jejak untuk setiap perangkat di file jejak masing-masing. Karena semua EnableAscii
fungsi kelebihan beban untuk mengambil pembungkus aliran, Anda dapat menggunakan formulir itu juga:

Nama::Tambahkan ("klien" ...);
Nama::Tambahkan ("klien/eth0" ...);
Nama::Tambahkan ("server" ...);
Nama::Tambahkan ("server/eth0" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAscii (aliran, "klien/eth0");
helper.EnableAscii (aliran, "server/eth0");

Ini akan menghasilkan satu file jejak bernama jejak-file-nama.tr yang berisi semua
peristiwa pelacakan untuk kedua perangkat. Peristiwa akan disamarkan oleh konteks jejak
string.

Anda dapat mengaktifkan pelacakan ascii pada kumpulan pasangan node/net-device dengan menyediakan a
Kontainer Perangkat Bersih. Untuk setiap Perangkat Bersih dalam wadah jenisnya dicentang. Untuk setiap
perangkat dari jenis yang tepat (jenis yang sama seperti yang dikelola oleh pembantu perangkat), tracing adalah
diaktifkan. Sekali lagi, tersirat karena perangkat bersih yang ditemukan harus benar-benar milik
satu Node. Sebagai contoh,:

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

Ini akan menghasilkan sejumlah file jejak ascii yang dibuat, yang masing-masing mengikuti:
itu - - konvensi .tr. Menggabungkan semua jejak menjadi
file tunggal dilakukan mirip dengan contoh di atas:

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

Anda dapat mengaktifkan pelacakan ascii pada kumpulan pasangan node/net-device dengan menyediakan a
Kontainer Node. Untuk setiap Node dalam Kontainer Node terlampir Perangkat Bersih diulang.
Untuk setiap Perangkat Bersih dilampirkan ke setiap node dalam wadah, jenis perangkat itu adalah
diperiksa. Untuk setiap perangkat dari jenis yang tepat (jenis yang sama seperti yang dikelola oleh perangkat
helper), pelacakan diaktifkan.:

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

Ini akan menghasilkan sejumlah file jejak ascii yang dibuat, yang masing-masing mengikuti:
itu - - konvensi .tr. Menggabungkan semua jejak menjadi
file tunggal dilakukan mirip dengan contoh di atas:

Anda dapat mengaktifkan pelacakan pcap berdasarkan ID node dan ID perangkat serta dengan eksplisit
Ptr. Masing-masing Node dalam sistem memiliki ID simpul bilangan bulat dan setiap perangkat terhubung ke simpul
memiliki ID perangkat bilangan bulat.:

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

Tentu saja, jejak dapat digabungkan menjadi satu file seperti yang ditunjukkan di atas.

Terakhir, Anda dapat mengaktifkan pelacakan pcap untuk semua perangkat di sistem, dengan tipe yang sama seperti
yang dikelola oleh pembantu perangkat.:

helper.EnableAsciiAll ("awalan");

Ini akan menghasilkan sejumlah file jejak ascii yang dibuat, satu untuk setiap perangkat di
sistem tipe yang dikelola oleh helper. Semua file ini akan mengikuti
- - .tr konvensi. Menggabungkan semua jejak menjadi satu
file dilakukan mirip dengan contoh di atas.

ASCII jiplakan alat Pembantu Filename Seleksi
Tersirat dalam deskripsi metode gaya awalan di atas adalah konstruksi yang lengkap
nama file dengan metode implementasi. Dengan konvensi, jejak ascii di ns-3 sistem
dari bentuk - identitas>- id>.tr.

Seperti disebutkan sebelumnya, setiap node dalam sistem akan memiliki id node yang ditetapkan sistem; dan
setiap perangkat akan memiliki indeks antarmuka (juga disebut id perangkat) relatif terhadap simpulnya.
Secara default, kemudian, file pelacakan ascii dibuat sebagai hasil dari mengaktifkan pelacakan pada yang pertama
perangkat node 21, menggunakan awalan "awalan", akan menjadi awalan-21-1.tr.

Anda selalu dapat menggunakan ns-3 layanan nama objek untuk membuatnya lebih jelas. Misalnya, jika
Anda menggunakan layanan nama objek untuk menetapkan nama "server" ke node 21, hasilnya
nama file trace ascii secara otomatis akan menjadi, awalan-server-1.tr dan jika Anda juga menugaskan
nama "eth0" ke perangkat, nama file jejak ascii Anda akan secara otomatis mengambil ini
dan dipanggil awalan-server-eth0.tr.

Pcap jiplakan Protokol Pembantu
Tujuan dari ini mixin adalah untuk memudahkan penambahan fasilitas pelacakan pcap yang konsisten ke
protokol. Kami ingin semua jenis penelusuran pcap bekerja sama di semua
protokol, sehingga metode pembantu ini diwarisi oleh pembantu tumpukan. Melihat
src/network/helper/trace-helper.h jika Anda ingin mengikuti diskusi sambil melihat
kode nyata.

Di bagian ini kami akan mengilustrasikan metode yang diterapkan pada protokol IPv4. Untuk
tentukan jejak dalam protokol serupa, cukup ganti jenis yang sesuai. Sebagai contoh,
Gunakan Ptr bukannya a Ptr dan telepon AktifkanPcapIpv6 alih-alih AktifkanPcapIpv4.

Kelas PcapHelperForIpv4 menyediakan fungsionalitas tingkat tinggi untuk menggunakan pelacakan pcap
dalam IPv4 protokol. Setiap pembantu protokol yang mengaktifkan metode ini harus mengimplementasikan satu
metode virtual yang diwarisi dari kelas ini. Akan ada implementasi terpisah untuk
IPv6, misalnya, tetapi satu-satunya perbedaan adalah pada nama metode dan tanda tangan.
Nama metode yang berbeda diperlukan untuk membedakan kelas IPv4 dari IPv6 yang keduanya
berasal dari kelas obyek, dan metode yang memiliki tanda tangan yang sama.:

virtual void EnablePcapIpv4Internal (awalan std::string, Ptr ipv4, antarmuka uint4_t) = 32;

Tanda tangan dari metode ini mencerminkan protokol dan tampilan antarmuka-sentris dari
situasi pada tingkat ini. Semua metode publik yang diwarisi dari kelas PcapHelperForIpv4
kurangi untuk memanggil metode implementasi yang bergantung pada perangkat tunggal ini. Misalnya,
metode pcap level terendah,:

void EnablePcapIpv4 (awalan std::string, Ptr ipv4, antarmuka uint4_t);

akan memanggil implementasi perangkat dari AktifkanPcapIpv4Internal secara langsung. Semua publik lainnya
metode pelacakan pcap dibangun di atas implementasi ini untuk memberikan tingkat pengguna tambahan
Kegunaan. Apa artinya ini bagi pengguna adalah bahwa semua pembantu protokol dalam sistem akan
memiliki semua metode jejak pcap yang tersedia; dan semua metode ini akan bekerja dengan cara yang sama
melewati protokol jika helper mengimplementasikan AktifkanPcapIpv4Internal benar.

Pcap jiplakan Protokol Pembantu metode
Metode-metode ini dirancang untuk berkorespondensi satu-ke-satu dengan Node- Dan
Perangkat Bersih- versi sentris dari versi perangkat. Dari pada Node dan Perangkat Bersih pasangan
kendala, kami menggunakan kendala protokol dan antarmuka.

Perhatikan bahwa seperti di versi perangkat, ada enam metode:

void EnablePcapIpv4 (awalan std::string, Ptr ipv4, antarmuka uint4_t);
void EnablePcapIpv4 (std::string awalan, std::string ipv4Name, antarmuka uint32_t);
membatalkan EnablePcapIpv4 (std::string awalan, Ipv4InterfaceContainer c);
void EnablePcapIpv4 (awalan std::string, NodeContainer n);
void EnablePcapIpv4 (awalan std::string, uint32_t nodeid, antarmuka uint32_t);
void EnablePcapIpv4All (awalan std::string);

Anda didorong untuk membaca dengan teliti Doxygen untuk kelas PcapHelperForIpv4 untuk menemukan detailnya
dari metode ini; tapi untuk meringkas...

Anda dapat mengaktifkan pelacakan pcap pada pasangan protokol/antarmuka tertentu dengan menyediakan a
Ptr dan antarmuka ke AktifkanPcap metode. Sebagai contoh,:

Ptr ipv4 = simpul->GetObject ();
...
helper.EnablePcapIpv4 ("awalan", ipv4, 0);

Anda dapat mengaktifkan pelacakan pcap pada pasangan node/net-device tertentu dengan menyediakan a
std::string mewakili string layanan nama objek ke AktifkanPcap metode. Itu
Ptr dicari dari string nama. Sebagai contoh,:

Nama::Tambahkan ("serverIPv4" ...);
...
helper.EnablePcapIpv4 ("awalan", "serverIpv4", 1);

Anda dapat mengaktifkan pelacakan pcap pada kumpulan pasangan protokol/antarmuka dengan menyediakan
IPv4InterfaceContainer. Untuk setiap IPv4 / pasangan antarmuka dalam wadah jenis protokol
diperiksa. Untuk setiap protokol dengan tipe yang tepat (tipe yang sama seperti yang dikelola oleh
pembantu perangkat), penelusuran diaktifkan untuk antarmuka yang sesuai. Sebagai contoh,:

NodeContainer node;
...
Perangkat NetDeviceContainer = deviceHelper.Install (node);
...
IPv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Antarmuka Ipv4InterfaceContainer = ipv4.Assign (perangkat);
...
helper.EnablePcapIpv4 ("awalan", antarmuka);

Anda dapat mengaktifkan pelacakan pcap pada kumpulan pasangan protokol/antarmuka dengan menyediakan a
Kontainer Node. Untuk setiap Node dalam Kontainer Node protokol yang sesuai ditemukan. Untuk
setiap protokol, antarmukanya dihitung dan penelusuran diaktifkan pada hasil
berpasangan. Sebagai contoh,:

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

Anda dapat mengaktifkan pelacakan pcap berdasarkan ID node dan antarmuka juga. Pada kasus ini,
node-id diterjemahkan ke Ptr dan protokol yang sesuai dicari di
simpul. Protokol dan antarmuka yang dihasilkan digunakan untuk menentukan jejak yang dihasilkan
sumber.:

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

Terakhir, Anda dapat mengaktifkan pelacakan pcap untuk semua antarmuka dalam sistem, dengan terkait
protokol menjadi tipe yang sama seperti yang dikelola oleh pembantu perangkat.:

helper.EnablePcapIpv4All ("awalan");

Pcap jiplakan Protokol Pembantu Filename Seleksi
Tersirat dalam semua deskripsi metode di atas adalah konstruksi yang lengkap
nama file dengan metode implementasi. Dengan konvensi, jejak pcap diambil untuk perangkat di
itu ns-3 sistem berbentuk - identitas>- id>.pcap. Dalam kasus
jejak protokol, ada korespondensi satu-ke-satu antara protokol dan Nodes. Ini
karena protokol benda dijumlahkan menjadi Node benda. Karena tidak ada protokol global
id dalam sistem, kami menggunakan id node yang sesuai dalam penamaan file. Oleh karena itu ada
kemungkinan untuk tabrakan nama file dalam nama file jejak yang dipilih secara otomatis. Untuk ini
alasan, konvensi nama file diubah untuk jejak protokol.

Seperti yang disebutkan sebelumnya, setiap node dalam sistem akan memiliki id node yang ditetapkan sistem.
Karena ada korespondensi satu-ke-satu antara instance protokol dan instance node
kami menggunakan id simpul. Setiap antarmuka memiliki id antarmuka relatif terhadap protokolnya. Kita gunakan
konvensi " -n -saya .pcap" untuk melacak penamaan file di
pembantu protokol.

Oleh karena itu, secara default, file pelacakan pcap dibuat sebagai hasil dari mengaktifkan pelacakan pada
antarmuka 1 dari protokol IPv4 node 21 menggunakan awalan "awalan" adalah
"awalan-n21-i1.pcap".

Anda selalu dapat menggunakan ns-3 layanan nama objek untuk membuatnya lebih jelas. Misalnya, jika
Anda menggunakan layanan nama objek untuk menetapkan nama "serverIpv4" ke Ptr pada simpul
21, nama file jejak pcap yang dihasilkan akan secara otomatis menjadi,
"awalan-nserverIpv4-i1.pcap".

ASCII jiplakan Protokol Pembantu
Perilaku pembantu jejak ascii secara substansial mirip dengan kasus pcap. Ambil
melihat src/network/helper/trace-helper.h jika Anda ingin mengikuti diskusi sambil
melihat kode nyata.

Di bagian ini kami akan mengilustrasikan metode yang diterapkan pada protokol IPv4. Untuk
tentukan jejak dalam protokol serupa, cukup ganti jenis yang sesuai. Sebagai contoh,
Gunakan Ptr bukannya a Ptr dan telepon AktifkanAsciiIpv6 alih-alih
AktifkanAsciiIpv4.

Kelas AsciiTraceHelperForIpv4 menambahkan fungsionalitas tingkat tinggi untuk menggunakan ascii
tracing ke protokol helper. Setiap protokol yang memungkinkan metode ini harus mengimplementasikan a
metode virtual tunggal yang diwarisi dari kelas ini.:

virtual void EnableAsciiIpv4Internal (Ptr aliran, std::awalan string,
Ptr ipv4, antarmuka uint4_t) = 32;

Tanda tangan dari metode ini mencerminkan tampilan protokol dan antarmuka-sentris dari
situasi pada tingkat ini; dan juga fakta bahwa penolong mungkin sedang menulis ke sebuah shared
aliran keluaran. Semua metode publik yang diwarisi dari kelas
PcapAndAsciiTraceHelperForIpv4 kurangi untuk memanggil perangkat tunggal ini-tergantung
metode implementasi. Misalnya, metode penelusuran ascii tingkat terendah,:

void EnableAsciiIpv4 (awalan std::string, Ptr ipv4, antarmuka uint4_t);
void EnableAsciiIpv4 (Ptr aliran, Ptr ipv4, antarmuka uint4_t);

akan memanggil implementasi perangkat dari AktifkanAsciiIpv4Internal secara langsung, menyediakan
awalan atau aliran. Semua metode penelusuran ascii publik lainnya akan dibangun di atas ini
fungsi tingkat rendah untuk menyediakan fungsionalitas tingkat pengguna tambahan. Apa artinya ini bagi
pengguna adalah bahwa semua pembantu perangkat dalam sistem akan memiliki semua metode pelacakan ascii
tersedia; dan semua metode ini akan bekerja dengan cara yang sama di seluruh protokol jika
implementasi protokol Aktifkan AsciiIpv4Internal benar.

ASCII jiplakan alat Pembantu metode
void EnableAsciiIpv4 (awalan std::string, Ptr ipv4, antarmuka uint4_t);
void EnableAsciiIpv4 (Ptr aliran, Ptr ipv4, antarmuka uint4_t);

void EnableAsciiIpv4 (awalan std::string, std::string ipv4Name, antarmuka uint32_t);
void EnableAsciiIpv4 (Ptr aliran, std::string ipv4Name, antarmuka uint32_t);

void EnableAsciiIpv4 (awalan std::string, Ipv4InterfaceContainer c);
void EnableAsciiIpv4 (Ptr aliran, IPv4InterfaceContainer c);

void EnableAsciiIpv4 (awalan std::string, NodeContainer n);
void EnableAsciiIpv4 (Ptr aliran, NodeContainer n);

void EnableAsciiIpv4 (awalan std::string, uint32_t nodeid, uint32_t deviceid);
void EnableAsciiIpv4 (Ptr aliran, uint32_t nodeid, antarmuka uint32_t);

void EnableAsciiIpv4All (awalan std::string);
void EnableAsciiIpv4All (Ptr sungai kecil);

Anda didorong untuk membaca dengan teliti Doxygen untuk kelas PcapAndAsciiHelperForIpv4 untuk menemukan
rincian metode ini; tapi untuk meringkas...

Ada dua kali lebih banyak metode yang tersedia untuk penelusuran ascii dibandingkan dengan pcap
pelacakan. Ini karena, selain model gaya pcap di mana jejak dari masing-masing
pasangan protokol/antarmuka unik ditulis ke file unik, kami mendukung model di mana
melacak informasi untuk banyak pasangan protokol/antarmuka ditulis ke file umum. Ini
berarti bahwa -n - mekanisme pembuatan nama file diganti
dengan mekanisme untuk merujuk ke file umum; dan jumlah metode API digandakan menjadi
memungkinkan semua kombinasi.

Sama seperti dalam pelacakan pcap, Anda dapat mengaktifkan pelacakan ascii pada protokol/antarmuka tertentu
berpasangan dengan memberikan a Ptr dan antarmuka ke Aktifkan Ascii metode. Sebagai contoh,:

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

Dalam hal ini, tidak ada konteks jejak yang ditulis ke file jejak ascii karena mereka akan menjadi
berulang. Sistem akan memilih nama file yang akan dibuat menggunakan aturan yang sama seperti
dijelaskan di bagian pcap, kecuali bahwa file tersebut akan memiliki akhiran ".tr" alih-alih
".pcap".

Jika Anda ingin mengaktifkan pelacakan ascii di lebih dari satu antarmuka dan semua jejak dikirim ke
satu file, Anda juga dapat melakukannya dengan menggunakan objek untuk merujuk ke satu file. Kita
sudah memiliki sesuatu yang mirip dengan ini dalam contoh "cwnd" di atas:

Ptr protokol4 = node1->GetObject ();
Ptr protokol4 = node2->GetObject ();
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (aliran, protokol1, 1);
helper.EnableAsciiIpv4 (aliran, protokol2, 1);

Dalam hal ini, konteks jejak ditulis ke file jejak ascii karena diperlukan
untuk membedakan jejak dari dua antarmuka. Perhatikan bahwa karena pengguna sepenuhnya
menentukan nama file, string harus menyertakan ".tr" untuk konsistensi.

Anda dapat mengaktifkan pelacakan ascii pada protokol tertentu dengan menyediakan a std::string
mewakili string layanan nama objek ke AktifkanPcap metode. Itu Ptr is
mendongak dari string nama. Itu dalam nama file yang dihasilkan tersirat karena
ada korespondensi satu-ke-satu antara instance protokol dan node, Misalnya,:

Nama::Tambahkan ("node1Ipv4" ...);
Nama::Tambahkan ("node2Ipv4" ...);
...
helper.EnableAsciiIpv4 ("awalan", "node1Ipv4", 1);
helper.EnableAsciiIpv4 ("awalan", "node2Ipv4", 1);

Ini akan menghasilkan dua file bernama "prefix-nnode1Ipv4-i1.tr" dan
"prefix-nnode2Ipv4-i1.tr" dengan jejak untuk setiap antarmuka di file jejak masing-masing.
Karena semua fungsi EnableAscii kelebihan beban untuk mengambil pembungkus aliran, Anda dapat
gunakan formulir itu juga:

Nama::Tambahkan ("node1Ipv4" ...);
Nama::Tambahkan ("node2Ipv4" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (aliran, "node1Ipv4", 1);
helper.EnableAsciiIpv4 (aliran, "node2Ipv4", 1);

Ini akan menghasilkan satu file jejak yang disebut "trace-file-name.tr" yang berisi semua
peristiwa jejak untuk kedua antarmuka. Peristiwa akan disamarkan oleh konteks jejak
string.

Anda dapat mengaktifkan pelacakan ascii pada kumpulan pasangan protokol/antarmuka dengan menyediakan
IPv4InterfaceContainer. Untuk setiap protokol dengan tipe yang tepat (tipe yang sama seperti yang dikelola
oleh pembantu perangkat), penelusuran diaktifkan untuk antarmuka yang sesuai. Sekali lagi,
implisit karena ada korespondensi satu-ke-satu antara setiap protokol dan
simpulnya. Sebagai contoh,:

NodeContainer node;
...
Perangkat NetDeviceContainer = deviceHelper.Install (node);
...
IPv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Antarmuka Ipv4InterfaceContainer = ipv4.Assign (perangkat);
...
...
helper.EnableAsciiIpv4 ("awalan", antarmuka);

Ini akan menghasilkan sejumlah file jejak ascii yang dibuat, yang masing-masing mengikuti:
itu -n -saya konvensi .tr. Menggabungkan semua jejak menjadi
file tunggal dilakukan mirip dengan contoh di atas:

NodeContainer node;
...
Perangkat NetDeviceContainer = deviceHelper.Install (node);
...
IPv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Antarmuka Ipv4InterfaceContainer = ipv4.Assign (perangkat);
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (aliran, antarmuka);

Anda dapat mengaktifkan pelacakan ascii pada kumpulan pasangan protokol/antarmuka dengan menyediakan a
Kontainer Node. Untuk setiap Node dalam Kontainer Node protokol yang sesuai ditemukan. Untuk
setiap protokol, antarmukanya dihitung dan penelusuran diaktifkan pada hasil
berpasangan. Sebagai contoh,:

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

Ini akan menghasilkan sejumlah file jejak ascii yang dibuat, yang masing-masing mengikuti:
itu - - konvensi .tr. Menggabungkan semua jejak menjadi
file tunggal dilakukan mirip dengan contoh di atas:

Anda dapat mengaktifkan pelacakan pcap berdasarkan ID node dan ID perangkat juga. Pada kasus ini,
node-id diterjemahkan ke Ptr dan protokol yang sesuai dicari di
simpul. Protokol dan antarmuka yang dihasilkan digunakan untuk menentukan jejak yang dihasilkan
sumber.:

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

Tentu saja, jejak dapat digabungkan menjadi satu file seperti yang ditunjukkan di atas.

Terakhir, Anda dapat mengaktifkan penelusuran ascii untuk semua antarmuka dalam sistem, dengan
protokol menjadi tipe yang sama seperti yang dikelola oleh pembantu perangkat.:

helper.EnableAsciiIpv4All ("awalan");

Ini akan menghasilkan sejumlah file jejak ascii yang dibuat, satu untuk setiap antarmuka
dalam sistem yang terkait dengan protokol jenis yang dikelola oleh pembantu. Semua file ini
akan mengikuti -n -saya
menjadi satu file dilakukan mirip dengan contoh di atas.

ASCII jiplakan alat Pembantu Filename Seleksi
Tersirat dalam deskripsi metode gaya awalan di atas adalah konstruksi yang lengkap
nama file dengan metode implementasi. Dengan konvensi, jejak ascii di ns-3 sistem
dari bentuk" - - .tr."

Seperti yang disebutkan sebelumnya, setiap node dalam sistem akan memiliki id node yang ditetapkan sistem.
Karena ada korespondensi satu-ke-satu antara protokol dan node yang kita gunakan untuk node-id
untuk mengidentifikasi identitas protokol. Setiap antarmuka pada protokol tertentu akan memiliki
indeks antarmuka (juga disebut antarmuka saja) relatif terhadap protokolnya. Secara default,
kemudian, file pelacakan ascii dibuat sebagai hasil dari mengaktifkan pelacakan pada perangkat pertama
node 21, menggunakan awalan "awalan", akan menjadi "awalan-n21-i1.tr". Gunakan awalan untuk
disambiguate beberapa protokol per node.

Anda selalu dapat menggunakan ns-3 layanan nama objek untuk membuatnya lebih jelas. Misalnya, jika
anda menggunakan layanan nama objek untuk menetapkan nama "serverIpv4" ke protokol pada node
21, dan juga menentukan antarmuka satu, nama file jejak ascii yang dihasilkan akan secara otomatis
menjadi, "awalan-nserverIpv4-1.tr".

jiplakan implementasi details
Data Koleksi
Bab ini menjelaskan Kerangka Pengumpulan Data ns-3 (DCF), yang menyediakan
kemampuan untuk mendapatkan data yang dihasilkan oleh model di simulator, untuk melakukan on-line
reduksi dan pemrosesan data, dan untuk menyusun data mentah atau yang diubah menjadi berbagai keluaran
format.

Kerangka kerja saat ini mendukung berjalan ns-3 mandiri yang tidak bergantung pada eksternal apa pun
pengendalian eksekusi program. Objek yang disediakan oleh DCF mungkin terhubung ke ns-3 jejak
sumber untuk memungkinkan pemrosesan data.

Kode sumber untuk kelas tinggal di direktori src/statistik.

Bab ini disusun sebagai berikut. Pertama, ikhtisar arsitekturnya adalah
disajikan. Selanjutnya, pembantu untuk kelas-kelas ini disajikan; pengobatan awal ini
harus memungkinkan penggunaan dasar kerangka pengumpulan data untuk banyak kasus penggunaan. Pengguna yang
ingin menghasilkan keluaran di luar cakupan pembantu saat ini, atau yang ingin membuat
objek pengumpulan data mereka sendiri, harus membaca sisa bab ini, yang berbunyi
ke detail tentang semua jenis objek DCF dasar dan menyediakan pengkodean tingkat rendah
contoh.

Mendesain
DCF terdiri dari tiga kelas dasar:

· Penyelidikan adalah mekanisme untuk instrumen dan kontrol output dari data simulasi yang
digunakan untuk memantau peristiwa-peristiwa menarik. Ini menghasilkan output dalam bentuk satu atau lebih ns-3
melacak sumber. Objek probe dihubungkan ke satu atau lebih jejak tenggelam (dipanggil
Kolektor), yang memproses sampel secara online dan menyiapkannya untuk keluaran.

· Pengumpul mengkonsumsi data yang dihasilkan oleh satu atau lebih objek Probe. Ini berfungsi
transformasi pada data, seperti normalisasi, reduksi, dan komputasi
statistik dasar. Objek kolektor tidak menghasilkan data yang langsung dikeluarkan oleh
ns-3 lari; sebagai gantinya, mereka mengeluarkan data hilir ke jenis objek lain, yang disebut
Agregator, yang melakukan fungsi tersebut. Biasanya, Kolektor mengeluarkan data mereka di
bentuk sumber jejak juga, memungkinkan kolektor untuk dirantai secara seri.

· Agregator adalah titik akhir dari data yang dikumpulkan oleh jaringan Probe dan Kolektor.
Tanggung jawab utama Agregator adalah mengumpulkan data dan yang terkait
metadata, ke dalam format output yang berbeda seperti file teks biasa, file spreadsheet, atau
database.

Ketiga kelas ini menyediakan kemampuan untuk menghidupkan atau mematikan secara dinamis
sepanjang simulasi.

Setiap mandiri ns-3 menjalankan simulasi yang menggunakan DCF biasanya akan membuat setidaknya satu
contoh dari masing-masing dari tiga kelas di atas.
[image] Ikhtisar Kerangka Pengumpulan Data.UNINDENT

Alur pemrosesan data secara keseluruhan digambarkan dalam Data Koleksi Kerangka ikhtisar.
Di sisi kiri, berlari ns-3 simulasi digambarkan. Dalam menjalankan
simulasi, data dibuat tersedia oleh model melalui sumber jejak, atau melalui cara lain.
Diagram menggambarkan bahwa probe dapat dihubungkan ke sumber jejak ini untuk menerima data
secara tidak sinkron, atau probe dapat melakukan polling untuk data. Data kemudian diteruskan ke objek kolektor
yang mengubah data. Akhirnya, agregator dapat dihubungkan ke output dari
kolektor, untuk menghasilkan plot, file, atau database.
[image] Agregasi Kerangka Pengumpulan Data.UNINDENT

Variasi pada gambar di atas disediakan dalam Data Koleksi Kerangka pengumpulan.
Gambar kedua ini menggambarkan bahwa objek DCF dapat dirantai bersama dengan cara
bahwa objek hilir mengambil input dari beberapa objek hulu. Sosok itu
konseptual menunjukkan bahwa beberapa probe dapat menghasilkan output yang dimasukkan ke dalam satu
pengumpul; sebagai contoh, kolektor yang mengeluarkan rasio dua penghitung akan
biasanya memperoleh setiap data counter dari probe terpisah. Beberapa kolektor juga bisa
masukkan ke dalam satu agregator, yang (sesuai namanya) dapat mengumpulkan sejumlah data
stream untuk dimasukkan ke dalam satu plot, file, atau database.

Data Koleksi Pembantu
Fleksibilitas penuh dari kerangka pengumpulan data disediakan oleh interkoneksi
probe, kolektor, dan agregator. Melakukan semua interkoneksi ini mengarah ke
banyak pernyataan konfigurasi dalam program pengguna. Untuk kemudahan penggunaan, beberapa yang paling umum
operasi dapat digabungkan dan dienkapsulasi dalam fungsi pembantu. Selain itu, beberapa
pernyataan yang melibatkan ns-3 sumber jejak tidak memiliki ikatan Python, karena keterbatasan dalam
ikatan.

Data Koleksi Pembantu Ringkasan
Di bagian ini, kami memberikan gambaran tentang beberapa kelas pembantu yang telah dibuat untuk
memudahkan konfigurasi kerangka pengumpulan data untuk beberapa kasus penggunaan umum. NS
helper memungkinkan pengguna untuk membentuk operasi umum dengan hanya beberapa pernyataan di C++ atau
Program Python. Tapi, kemudahan penggunaan ini datang dengan biaya yang jauh lebih sedikit
fleksibilitas daripada yang dapat disediakan oleh konfigurasi tingkat rendah, dan kebutuhan untuk kode secara eksplisit
dukungan untuk jenis Probe baru ke dalam helper (untuk mengatasi masalah yang dijelaskan di bawah).

Penekanan pada helper saat ini adalah mengumpulkan data dari ns-3 melacak sumber ke dalam
plot gnuplot atau file teks, tanpa kustomisasi output atau statistik tingkat tinggi
pengolahan (awalnya). Juga, penggunaannya dibatasi pada jenis probe yang tersedia di
ns-3. Bagian selanjutnya dari dokumentasi ini akan membahas lebih detail tentang membuat yang baru
Jenis probe, serta detail tentang menghubungkan Probe, Kolektor, dan Agregator
dalam pengaturan adat.

Sampai saat ini, dua pembantu Pengumpulan Data telah diimplementasikan:

· Pembantu Gnuplot

· Pembantu File

Pembantu Gnuplot
GnuplotHelper adalah kelas pembantu untuk memproduksi file keluaran yang digunakan untuk membuat gnuplot. NS
tujuan keseluruhan adalah untuk memberikan kemampuan bagi pengguna untuk dengan cepat membuat plot dari data yang diekspor
in ns-3 melacak sumber. Secara default, jumlah minimal transformasi data dilakukan;
tujuannya adalah untuk menghasilkan plot dengan pernyataan konfigurasi (default) sesedikit
mungkin.

Pembantu Gnuplot Ringkasan
GnuplotHelper akan membuat 3 file berbeda di akhir simulasi:

· File data gnuplot yang dipisahkan spasi

· File kontrol gnuplot

· Skrip shell untuk menghasilkan gnuplot

Ada dua pernyataan konfigurasi yang diperlukan untuk menghasilkan plot. Pertama
pernyataan mengkonfigurasi plot (nama file, judul, legenda, dan tipe output, di mana output
ketik default ke PNG jika tidak ditentukan):

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

Pernyataan kedua mengaitkan sumber jejak yang menarik:

void PlotProbe (const std::string &typeId,
const std::string &jalur,
const std::string &probeTraceSource,
const std::string &judul);

Argumennya adalah sebagai berikut:

· typeId: Itu ns-3 TypeId dari Probe

· jalur: Jalur di ns-3 konfigurasi namespace ke satu atau lebih sumber jejak

· probeTraceSource: Output probe mana (itu sendiri merupakan trace source) yang harus diplot

· judul: Judul untuk dikaitkan dengan kumpulan data (dalam legenda gnuplot)

Sebuah varian pada PlotProbe di atas adalah untuk menentukan argumen opsional kelima yang mengontrol
di mana dalam plot kunci (legenda) ditempatkan.

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

// Buat pembantu gnuplot.
GnuplotHelper plotHelper;

// Konfigurasi plotnya.
// Konfigurasi plotnya. Argumen pertama adalah awalan nama file
// untuk file keluaran yang dihasilkan. Yang kedua, ketiga, dan keempat
// argumen masing-masing adalah judul plot, sumbu x, dan label sumbu y
plotHelper.ConfigurePlot ("jumlah-paket-ketujuh",
"Jumlah Byte Paket vs. Waktu",
"Waktu (Sekon)",
"Jumlah Byte Paket",
"png");

// Tentukan jenis probe, lacak jalur sumber (dalam ruang nama konfigurasi), dan
// menyelidiki sumber jejak keluaran ("OutputBytes") untuk diplot. Argumen keempat
// menentukan nama label seri data pada plot. Yang terakhir
// argumen memformat plot dengan menentukan di mana kunci harus ditempatkan.
plotHelper.PlotProbe (probeType,
jejakJalan,
"OutputByte",
"Jumlah Byte Paket",
GnuplotAggregator::KEY_BELOW);

Dalam contoh ini, the jenis probe dan jejakJalan adalah sebagai berikut (untuk IPv4):

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

probeType adalah parameter kunci agar helper ini berfungsi. TypeId ini harus terdaftar
dalam sistem, dan tanda tangan pada penyerap jejak Probe harus cocok dengan jejaknya
sumber itu sedang terhubung ke. Jenis probe telah ditentukan sebelumnya untuk sejumlah tipe data
sesuai dengan ns-3 nilai yang dilacak, dan untuk beberapa tanda tangan sumber jejak lainnya seperti
sumber jejak 'Tx' dari ns3::Protokol IPv4L3 kelas.

Perhatikan bahwa jalur sumber pelacakan yang ditentukan mungkin berisi karakter pengganti. Dalam hal ini, banyak
kumpulan data diplot pada satu plot; satu untuk setiap jalur yang cocok.

Output utama yang dihasilkan akan menjadi tiga file:

paket-ketujuh-byte-count.dat
paket-ketujuh-byte-count.plt
paket-ketujuh-byte-count.sh

Pada titik ini, pengguna dapat mengedit file .plt untuk penyesuaian lebih lanjut, atau
jalankan saja melalui gnuplot. Berlari sh paket-ketujuh-byte-count.sh jalankan saja plotnya
melalui gnuplot, seperti yang ditunjukkan di bawah ini.
[image] Gnuplot 2-D Dibuat oleh ketujuh.cc Contoh..UNINDENT

Terlihat bahwa elemen kunci (legenda, judul, penempatan legenda, xlabel, ylabel,
dan jalur untuk data) semuanya ditempatkan di plot. Karena ada dua pertandingan untuk
jalur konfigurasi yang disediakan, dua seri data ditampilkan:

· Jumlah Byte Paket-0 sesuai dengan /NodeList/0/$ns3::Ipv4L3Protocol/Tx

· Jumlah Byte Paket-1 sesuai dengan /NodeList/1/$ns3::Ipv4L3Protocol/Tx

Pembantu Gnuplot Konfigurasi Plot
GnuplotHelper's Konfigurasi Plot() fungsi dapat digunakan untuk mengkonfigurasi plot.

Ini memiliki prototipe berikut:

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

Ini memiliki argumen berikut:

┌───────────────────────────────┬───────────────── ─────────────────┐
Argumen Deskripsi
├───────────────────────────────┼───────────────── ─────────────────┤
outputFileNameWithoutExtension Nama file terkait gnuplot ke
menulis tanpa ekstensi. │
├───────────────────────────────┼───────────────── ─────────────────┤
judul Plot string judul yang akan digunakan untuk
plot ini. │
├───────────────────────────────┼───────────────── ─────────────────┤
xLegend Legenda untuk x horizontal
sumbu. │
├───────────────────────────────┼───────────────── ─────────────────┤
yLegend Legenda untuk vertikal y
sumbu. │
└───────────────────────────────┴───────────────── ─────────────────┘

terminalType String pengaturan tipe terminal untuk
keluaran. Terminal bawaan
jenisnya adalah "png". │
└───────────────────────────────┴───────────────── ─────────────────┘

GnuplotHelper's Konfigurasi Plot() fungsi mengonfigurasi parameter terkait plot untuk ini
gnuplot helper sehingga akan membuat file data gnuplot yang dipisahkan spasi bernama
outputFileNameWithoutExtension + ".dat", file kontrol gnuplot bernama
outputFileNameWithoutExtension + ".plt", dan skrip shell untuk menghasilkan gnuplot bernama
outputFileNameWithoutExtension + ".sh".

Contoh cara menggunakan fungsi ini dapat dilihat di ketujuh.cc kode yang dijelaskan di atas
di mana itu digunakan sebagai berikut:

plotHelper.ConfigurePlot ("jumlah-paket-ketujuh",
"Jumlah Byte Paket vs. Waktu",
"Waktu (Sekon)",
"Jumlah Byte Paket",
"png");

Pembantu Gnuplot Penyelidikan Plot
GnuplotHelper's Penyelidikan Plot() fungsi dapat digunakan untuk memplot nilai yang dihasilkan oleh probe.

Ini memiliki prototipe berikut:

void PlotProbe (const std::string &typeId,
const std::string &jalur,
const std::string &probeTraceSource,
const std::string &judul,
enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE);

Ini memiliki argumen berikut:

┌─────────────────┬─────────────────────────────── ───┐
Argumen Deskripsi
├─────────────────┼─────────────────────────────── ───┤
typeId ID tipe untuk probe
dibuat oleh penolong ini. │
├─────────────────┼─────────────────────────────── ───┤
path Konfigurasi jalur untuk mengakses jejak
sumber. │
├─────────────────┼─────────────────────────────── ───┤
probeTraceSource Sumber jejak probe ke
akses. │
├─────────────────┼─────────────────────────────── ───┤
judul Judul yang akan dikaitkan dengan
kumpulan data ini
├─────────────────┼─────────────────────────────── ───┤
Lokasi kunci Lokasi kunci di
plot. Lokasi default adalah
di dalam. │
└─────────────────┴─────────────────────────────── ───┘

GnuplotHelper's Penyelidikan Plot() fungsi memplot kumpulan data yang dihasilkan dengan mengaitkan ns-3
melacak sumber dengan probe yang dibuat oleh helper, dan kemudian memplot nilai dari
probeTraceSource. Dataset akan memiliki judul yang disediakan, dan akan terdiri dari:
'newValue' di setiap stempel waktu.

Jika jalur konfigurasi memiliki lebih dari satu kecocokan dalam sistem karena ada wildcard, maka
satu dataset untuk setiap pertandingan akan diplot. Judul dataset akan diberi akhiran dengan
karakter yang cocok untuk setiap karakter pengganti di jalur konfigurasi, dipisahkan oleh spasi. Untuk
contoh, jika judul kumpulan data yang diusulkan adalah string "byte", dan ada dua wildcard
di jalur, maka judul kumpulan data seperti "byte-0 0" atau "byte-12 9" akan dimungkinkan karena
label untuk dataset yang diplot.

Contoh cara menggunakan fungsi ini dapat dilihat di ketujuh.cc kode yang dijelaskan di atas
di mana itu digunakan (dengan substitusi variabel) sebagai berikut:

plotHelper.PlotProbe ("ns3::Ipv4PacketProbe",
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
"OutputByte",
"Jumlah Byte Paket",
GnuplotAggregator::KEY_BELOW);

Lainnya contoh
gnuplot Pembantu Example
Contoh yang sedikit lebih sederhana daripada ketujuh.cc contohnya bisa dilihat di
src/stats/examples/gnuplot-helper-example.cc. Gnuplot 2-D berikut dibuat menggunakan
Contoh.
[image] Gnuplot 2-D Dibuat oleh gnuplot-helper-example.cc Contoh..UNINDENT

Dalam contoh ini, ada objek Emitor yang menambah penghitungnya sesuai dengan a
Proses Poisson dan kemudian memancarkan nilai penghitung sebagai sumber jejak.

Ptr emitor = BuatObjek ();
Nama::Tambahkan ("/Nama/Emitter", emitor);

Perhatikan bahwa karena tidak ada wildcard di jalur yang digunakan di bawah, hanya 1 aliran data yang
digambar dalam plot. Aliran data tunggal dalam plot ini diberi label "Jumlah Emitter",
tanpa sufiks tambahan seperti orang akan melihat apakah ada wildcard di jalan.

// Buat pembantu gnuplot.
GnuplotHelper plotHelper;

// Konfigurasi plotnya.
plotHelper.ConfigurePlot ("gnuplot-helper-example",
"Jumlah Emitter vs. Waktu",
"Waktu (Sekon)",
"Jumlah emitor",
"png");

// Plot nilai yang dihasilkan oleh probe. Jalan yang kami sediakan
// membantu untuk membedakan sumber jejak.
plotHelper.PlotProbe ("ns3::Uinteger32Probe",
"/Nama/Emitter/Counter",
"Keluaran",
"Jumlah emitor",
GnuplotAggregator::KEY_INSIDE);

Pembantu File
FileHelper adalah kelas pembantu yang digunakan untuk memasukkan nilai data ke dalam file. Tujuan keseluruhan adalah
untuk memberikan kemampuan bagi pengguna untuk dengan cepat membuat file teks berformat dari data yang diekspor
in ns-3 melacak sumber. Secara default, jumlah minimal transformasi data dilakukan;
tujuannya adalah untuk menghasilkan file dengan pernyataan konfigurasi (default) sesedikit
mungkin.

Pembantu File Ringkasan
FileHelper akan membuat 1 atau lebih file teks di akhir simulasi.

FileHelper dapat membuat 4 jenis file teks yang berbeda:

· Diformat

· Spasi dipisahkan (default)

· Dipisahkan koma

· Tab dipisahkan

File yang diformat menggunakan string format gaya-C dan fungsi sprintf() untuk mencetaknya
nilai dalam file yang sedang ditulis.

File teks berikut dengan 2 kolom nilai yang diformat bernama
paket-ketujuh-byte-count-0.txt dibuat menggunakan lebih banyak kode baru yang ditambahkan ke
Garis Keturunan Asli ns-3 Kode contoh tutorial. Hanya 10 baris pertama dari file ini yang ditampilkan
di sini untuk singkatnya.

Waktu (Detik) = 1.000e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.004e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.004e+00 Jumlah Byte Paket = 576
Waktu (Detik) = 1.009e+00 Jumlah Byte Paket = 576
Waktu (Detik) = 1.009e+00 Jumlah Byte Paket = 576
Waktu (Detik) = 1.015e+00 Jumlah Byte Paket = 512
Waktu (Detik) = 1.017e+00 Jumlah Byte Paket = 576
Waktu (Detik) = 1.017e+00 Jumlah Byte Paket = 544
Waktu (Detik) = 1.025e+00 Jumlah Byte Paket = 576
Waktu (Detik) = 1.025e+00 Jumlah Byte Paket = 544

...

File teks berbeda berikut dengan 2 kolom nilai yang diformat bernama
paket-ketujuh-byte-count-1.txt juga dibuat menggunakan kode baru yang sama yang ditambahkan ke
asli ns-3 Kode contoh tutorial. Hanya 10 baris pertama dari file ini yang ditampilkan
di sini untuk singkatnya.

Waktu (Detik) = 1.002e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.007e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.013e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.020e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.028e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.036e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.045e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.053e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.061e+00 Jumlah Byte Paket = 40
Waktu (Detik) = 1.069e+00 Jumlah Byte Paket = 40

...

Kode baru yang ditambahkan untuk menghasilkan dua file teks di bawah ini. Lebih detail tentang
API ini akan dibahas di bagian selanjutnya.

Perhatikan bahwa karena ada 2 kecocokan untuk wildcard di jalur, 2 file teks terpisah
diciptakan. File teks pertama, yang bernama "seventh-packet-byte-count-0.txt",
sesuai dengan kecocokan wildcard dengan "*" diganti dengan "0". File teks kedua,
yang bernama "seventh-packet-byte-count-1.txt", sesuai dengan kecocokan wildcard dengan
tanda "*" diganti dengan "1". Juga, perhatikan bahwa fungsi memanggil ke TulisProbe() akan memberikan
pesan kesalahan jika tidak ada kecocokan untuk jalur yang berisi wildcard.

// Buat file pembantu.
FileHelper fileHelper;

// Konfigurasi file yang akan ditulis.
fileHelper.ConfigureFile ("jumlah-paket-ketujuh",
FileAggregator::DIFORMAT);

// Tetapkan label untuk file output yang diformat ini.
fileHelper.Set2dFormat ("Waktu (Detik) = %.3e\tJumlah Byte Paket = %.0f");

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

Pembantu File Konfigurasi File
FileHelper's Konfigurasi File() fungsi dapat digunakan untuk mengkonfigurasi file teks.

Ini memiliki prototipe berikut:

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

Ini memiliki argumen berikut:

┌───────────────────────────────┬───────────────── ─────────────────┐
Argumen Deskripsi
├───────────────────────────────┼───────────────── ─────────────────┤
outputFileNameWithoutExtension Nama file output yang akan ditulis
tanpa ekstensi. │
├───────────────────────────────┼───────────────── ─────────────────┤
fileType Jenis file yang akan ditulis. The
jenis file default adalah spasi
dipisahkan. │
└───────────────────────────────┴───────────────── ─────────────────┘

FileHelper's Konfigurasi File() fungsi mengonfigurasi parameter terkait file teks untuk
file helper sehingga akan membuat file bernama outputFileNameWithoutExtension plus
kemungkinan informasi tambahan dari kecocokan wildcard plus ".txt" dengan nilai yang dicetak sebagai
ditentukan oleh fileType. Jenis file default dipisahkan oleh spasi.

Contoh cara menggunakan fungsi ini dapat dilihat di ketujuh.cc kode yang dijelaskan di atas
di mana itu digunakan sebagai berikut:

fileHelper.ConfigureFile ("jumlah-paket-ketujuh",
FileAggregator::DIFORMAT);

Pembantu File TulisProbe
FileHelper's TulisProbe() fungsi dapat digunakan untuk menulis nilai yang dihasilkan oleh probe ke
file teks.

Ini memiliki prototipe berikut:

void WriteProbe (const std::string &typeId,
const std::string &jalur,
const std::string &probeTraceSource);

Ini memiliki argumen berikut:

┌─────────────────┬─────────────────────────────── ───┐
Argumen Deskripsi
├─────────────────┼─────────────────────────────── ───┤
typeId Jenis ID untuk probe yang akan
dibuat. │
├─────────────────┼─────────────────────────────── ───┤
path Konfigurasi jalur untuk mengakses jejak
sumber. │
├─────────────────┼─────────────────────────────── ───┤
probeTraceSource Sumber jejak probe ke
akses. │
└─────────────────┴─────────────────────────────── ───┘

FileHelper's TulisProbe() fungsi membuat file teks keluaran yang dihasilkan dengan mengaitkan
ns-3 melacak sumber dengan probe yang dibuat oleh helper, dan kemudian menulis nilai dari
probeTraceSource. Nama file keluaran akan memiliki teks yang disimpan dalam variabel anggota
m_outputFileNameWithoutExtension plus ".txt", dan akan terdiri dari 'newValue' di setiap
stempel waktu.

Jika jalur konfigurasi memiliki lebih dari satu kecocokan dalam sistem karena ada wildcard, maka
satu file output untuk setiap pertandingan akan dibuat. Nama file keluaran akan berisi:
teks dalam m_outputFileNameWithoutExtension ditambah karakter yang cocok untuk masing-masing
wildcard di jalur konfigurasi, dipisahkan dengan tanda hubung, ditambah ".txt". Misalnya, jika nilai
di m_outputFileNameWithoutExtension adalah string "packet-byte-count", dan ada dua
wildcard di jalur, lalu keluarkan nama file seperti "packet-byte-count-0-0.txt" atau
"packet-byte-count-12-9.txt" akan dimungkinkan sebagai nama untuk file yang akan dibuat.

Contoh cara menggunakan fungsi ini dapat dilihat di ketujuh.cc kode yang dijelaskan di atas
di mana itu digunakan sebagai berikut:

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

Lainnya contoh
File Pembantu Example
Contoh yang sedikit lebih sederhana daripada ketujuh.cc contohnya bisa dilihat di
src/stats/examples/file-helper-example.cc. Contoh ini hanya menggunakan FileHelper.

File teks berikut dengan 2 kolom nilai yang diformat bernama file-helper-example.txt
dibuat menggunakan contoh. Hanya 10 baris pertama dari file ini yang ditampilkan di sini untuk
keringkasan.

Waktu (Detik) = 0.203 Hitungan = 1
Waktu (Detik) = 0.702 Hitungan = 2
Waktu (Detik) = 1.404 Hitungan = 3
Waktu (Detik) = 2.368 Hitungan = 4
Waktu (Detik) = 3.364 Hitungan = 5
Waktu (Detik) = 3.579 Hitungan = 6
Waktu (Detik) = 5.873 Hitungan = 7
Waktu (Detik) = 6.410 Hitungan = 8
Waktu (Detik) = 6.472 Hitungan = 9
...

Dalam contoh ini, ada objek Emitor yang menambah penghitungnya sesuai dengan a
Proses Poisson dan kemudian memancarkan nilai penghitung sebagai sumber jejak.

Ptr emitor = BuatObjek ();
Nama::Tambahkan ("/Nama/Emitter", emitor);

Perhatikan bahwa karena tidak ada wildcard di jalur yang digunakan di bawah ini, hanya 1 file teks yang
dibuat. File teks tunggal ini bernama "file-helper-example.txt", tanpa tambahan
sufiks seperti Anda akan melihat apakah ada wildcard di jalan.

// Buat file pembantu.
FileHelper fileHelper;

// Konfigurasi file yang akan ditulis.
fileHelper.ConfigureFile ("file-helper-contoh",
FileAggregator::DIFORMAT);

// Tetapkan label untuk file output yang diformat ini.
fileHelper.Set2dFormat ("Waktu (Detik) = %.3e\tCount = %.0f");

// Tulis nilai yang dihasilkan oleh probe. Jalan yang kita
// menyediakan bantuan untuk membedakan sumber jejak.
fileHelper.WriteProbe ("ns3::Uinteger32Probe",
"/Nama/Emitter/Counter",
"Keluaran");

Cakupan dan keterbatasan
Saat ini, hanya Probe ini yang telah diimplementasikan dan terhubung ke GnuplotHelper dan
ke FileHelper:

· Penyelidikan Boolean

· Penyelidikan Ganda

· Uinteger8Probe

· Uinteger16Probe

· Uinteger32Probe

· Penyelidikan Waktu

· PaketProbe

· ApplicationPacketProbe

· IPv4PacketProbe

Oleh karena itu, Probe ini adalah satu-satunya TypeId yang tersedia untuk digunakan di Penyelidikan Plot() dan
TulisProbe().

Dalam beberapa bagian berikutnya, kita membahas masing-masing tipe objek dasar (Probe, Collector,
dan Agregator) secara lebih rinci, dan tunjukkan bagaimana mereka dapat dihubungkan bersama menggunakan
API tingkat rendah.

Probe
Bagian ini merinci fungsionalitas yang disediakan oleh kelas Probe untuk ns-3
simulasi, dan memberikan contoh bagaimana mengkodekannya dalam sebuah program. Bagian ini dimaksudkan untuk
pengguna yang tertarik untuk mengembangkan simulasi dengan ns-3 alat dan menggunakan Data
Collection Framework, di mana kelas Probe merupakan bagiannya, untuk menghasilkan output data dengan
hasil simulasi mereka.

Penyelidikan Ringkasan
Objek Probe seharusnya terhubung ke variabel dari simulasi yang nilainya
seluruh eksperimen relevan bagi pengguna. Probe akan merekam apa yang
nilai yang diasumsikan oleh variabel selama simulasi dan meneruskan data tersebut ke yang lain
anggota Kerangka Pengumpulan Data. Meskipun di luar cakupan bagian ini untuk
membahas apa yang terjadi setelah Probe menghasilkan outputnya, cukup untuk mengatakan bahwa, dengan
akhir simulasi, pengguna akan memiliki informasi rinci tentang nilai-nilai apa yang
disimpan di dalam variabel yang diperiksa selama simulasi.

Biasanya, Probe terhubung ke ns-3 sumber jejak. Dengan cara ini, setiap kali
trace source mengekspor nilai baru, Probe mengkonsumsi nilai (dan mengekspornya ke hilir
ke objek lain melalui sumber jejaknya sendiri).

Probe dapat dianggap sebagai semacam filter pada sumber jejak. Alasan utama untuk
mungkin mengaitkan ke Probe daripada langsung ke sumber jejak adalah sebagai berikut:

· Probe dapat dihidupkan dan dimatikan secara dinamis selama simulasi dengan panggilan ke Memungkinkan()
dan Cacat(). Misalnya, keluaran data mungkin dimatikan selama
fase pemanasan simulasi.

· Probe dapat melakukan operasi pada data untuk mengekstrak nilai dari yang lebih rumit
struktur; misalnya, mengeluarkan nilai ukuran paket dari ns3::Packet yang diterima.

· Probe mendaftarkan nama di ns3::Config namespace (menggunakan Nama::Tambah ()) sehingga lainnya
objek dapat merujuk kepada mereka.

· Probe menyediakan metode statis yang memungkinkan seseorang untuk memanipulasi Probe dengan nama, seperti
apa yang dilakukan di ns2measure [Cic06]

Stat::put ("my_metric", ID, sampel);

Persamaan ns-3 dari kode ns2measure di atas adalah, mis

DoubleProbe::SetValueByPath ("/path/ke/probe", sampel);

Penciptaan
Perhatikan bahwa objek kelas dasar Probe tidak dapat dibuat karena merupakan basis abstrak
kelas, yaitu memiliki fungsi virtual murni yang belum diimplementasikan. Sebuah objek dari
ketik DoubleProbe, yang merupakan subkelas dari kelas Probe, akan dibuat di sini untuk menunjukkan
apa yang perlu dilakukan.

Seseorang mendeklarasikan DoubleProbe dalam memori dinamis dengan menggunakan kelas penunjuk pintar (Ptr ). Ke
buat DoubleProbe dalam memori dinamis dengan smart pointer, hanya perlu memanggil
ns-3 metode BuatObjek():

Ptr myprobe = BuatObjek ();

Deklarasi di atas membuat DoubleProbes menggunakan nilai default untuk atributnya.
Ada empat atribut di kelas DoubleProbe; dua di objek kelas dasar
DataCollectionObject, dan dua di kelas dasar Probe:

· "Nama" (DataCollectionObject), sebuah StringValue

· "Diaktifkan" (DataCollectionObject), sebuah BooleanValue

· "Mulai" (Penyelidikan), Nilai Waktu

· "Berhenti" (Penyelidikan), Nilai Waktu

Seseorang dapat mengatur atribut tersebut pada pembuatan objek dengan menggunakan metode berikut:

Ptr myprobe = CreateObjectWithAttributes (
"Nama", StringValue ("probe saya"),
"Diaktifkan", BooleanValue (salah),
"Mulai", Nilai Waktu (Detik (100.0)),
"Berhenti", Nilai Waktu (Detik (1000.0)));

Mulai dan Berhenti adalah variabel Waktu yang menentukan interval aksi Probe. NS
Probe hanya akan menampilkan data jika waktu Simulasi saat ini ada di dalamnya
selang. Nilai waktu khusus 0 detik untuk Stop akan menonaktifkan atribut ini (mis
pertahankan Probe untuk seluruh simulasi). Diaktifkan adalah bendera yang menyalakan Probe atau
off, dan harus disetel ke true agar Probe dapat mengekspor data. Nama adalah nama objek
dalam kerangka DCF.

Pengimporan dan mengekspor data
ns-3 sumber jejak diketik dengan kuat, jadi mekanisme untuk mengaitkan Probe ke jejak
sumber dan untuk mengekspor data milik subkelasnya. Misalnya, default
distribusi ns-3 menyediakan kelas DoubleProbe yang dirancang untuk menghubungkan ke jejak
sumber mengekspor nilai ganda. Kami selanjutnya akan merinci pengoperasian DoubleProbe, dan
kemudian diskusikan bagaimana kelas Probe lainnya dapat didefinisikan oleh pengguna.

Penyelidikan Ganda Ringkasan
DoubleProbe terhubung ke nilai ganda ns-3 melacak sumber, dan dirinya sendiri mengekspor a
nilai ganda yang berbeda ns-3 sumber jejak.

Kode berikut, diambil dari src/stats/examples/double-probe-example.cc, menunjukkan dasar
operasi pemipaan DoubleProbe ke dalam simulasi, di mana ia memeriksa Counter
diekspor oleh objek emitor (kelas Emitter).

Ptr emitor = BuatObjek ();
Nama::Tambahkan ("/Nama/Emitter", emitor);
...

Ptr probe1 = BuatObjek ();

// Hubungkan probe ke Penghitung emitor
bool terhubung = probe1->ConnectByObject ("Counter", emitor);

Kode berikut sedang menyelidiki Penghitung yang sama yang diekspor oleh objek emitor yang sama. Ini
DoubleProbe, bagaimanapun, menggunakan jalur di namespace konfigurasi untuk membuat
koneksi. Perhatikan bahwa emitor mendaftarkan dirinya di namespace konfigurasi setelah
itu telah dibuat; jika tidak, ConnectByPath tidak akan berfungsi.

Ptr probe2 = BuatObjek ();

// Catatan, tidak ada nilai balik yang diperiksa di sini
probe2->ConnectByPath ("/Nama/Emitter/Counter");

DoubleProbe berikutnya yang ditunjukkan di bawah ini akan memiliki nilainya yang disetel menggunakan jalurnya di
ruang nama konfigurasi. Perhatikan bahwa kali ini DoubleProbe mendaftarkan dirinya di
konfigurasi namespace setelah dibuat.

Ptr probe3 = BuatObjek ();
probe3->SetName("Probe yang Diakses Secara Statis");

// Kita harus menambahkannya ke database konfigurasi
Names::Add ("/Names/Probes", probe3->GetName(), probe3);

Fungsi Count() emitor sekarang dapat menetapkan nilai untuk DoubleProbe ini sebagai
berikut:

membatalkan
Emitor::Hitung (void)
{
...
m_counter += 1.0;
DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
...
}

Contoh di atas menunjukkan bagaimana kode yang memanggil Probe tidak harus memiliki eksplisit
referensi ke Probe, tetapi dapat mengarahkan pengaturan nilai melalui namespace Config.
Ini mirip dalam fungsinya dengan Stat::Menempatkan metode yang diperkenalkan oleh kertas ns2measure
[Cic06], dan memungkinkan pengguna untuk memasukkan pernyataan Probe untuk sementara seperti Printf Laporan
dalam yang ada ns-3 model. Perhatikan bahwa untuk dapat menggunakan DoubleProbe dalam ini
contoh seperti ini, 2 hal yang diperlukan:

1. file header modul stats disertakan dalam contoh file .cc

2. contoh dibuat bergantung pada modul stats dalam file wscript-nya.

Hal serupa perlu dilakukan untuk menambahkan Probe lain di tempat lain di ns-3
basis kode.

Nilai untuk DoubleProbe juga dapat diatur menggunakan fungsi DoubleProbe::SetValue(),
sedangkan nilai untuk DoubleProbe dapat diperoleh dengan menggunakan fungsi
Pemeriksaan Ganda::DapatkanNilai().

DoubleProbe mengekspor nilai ganda dalam sumber jejak "Output"-nya; objek hilir
dapat menghubungkan wastafel jejak (NotifyViaProbe) ke ini sebagai berikut:

terhubung = probe1->TraceConnect ("Output", probe1->GetName (), MakeCallback (&NotifyViaProbe));

Lainnya probe
Selain DoubleProbe, Probe berikut juga tersedia:

· Uinteger8Probe terhubung ke ns-3 melacak sumber mengekspor uint8_t.

· Uinteger16Probe terhubung ke ns-3 melacak sumber mengekspor uint16_t.

· Uinteger32Probe terhubung ke ns-3 melacak sumber mengekspor uint32_t.

· PacketProbe terhubung ke sebuah ns-3 melacak sumber mengekspor paket.

· ApplicationPacketProbe terhubung ke ns-3 melacak sumber mengekspor paket dan soket
alamat.

· IPv4PacketProbe terhubung ke ns-3 trace source mengekspor paket, objek IPv4, dan
sebuah antarmuka.

membuat yang baru Penyelidikan jenis
Untuk membuat jenis Probe baru, Anda perlu melakukan langkah-langkah berikut:

· Pastikan bahwa kelas Probe baru Anda berasal dari kelas dasar Probe.

· Pastikan bahwa fungsi virtual murni yang diwarisi oleh kelas Probe baru Anda dari
Kelas dasar probe diimplementasikan.

· Temukan kelas Probe yang ada yang menggunakan sumber jejak yang paling dekat jenisnya dengan
jenis sumber jejak yang akan digunakan Probe Anda.

· Salin file header kelas Probe yang ada (.h) dan file implementasi (.cc) ke dua
file baru dengan nama yang cocok dengan Probe baru Anda.

· Ganti tipe, argumen, dan variabel dalam file yang disalin dengan yang sesuai
ketik untuk Probe Anda.

· Buat modifikasi yang diperlukan untuk membuat kode dikompilasi dan membuatnya berperilaku seperti yang Anda inginkan
suka.

contoh
Dua contoh akan dibahas secara rinci di sini:

· Contoh Penyelidikan Ganda

· Contoh Plot Paket IPv4

Dua kali lipat Penyelidikan Example
Contoh probe ganda telah dibahas sebelumnya. Contoh program dapat ditemukan
in src/stats/examples/double-probe-example.cc. Untuk meringkas apa yang terjadi dalam program ini,
ada emitor yang mengekspor penghitung yang bertambah sesuai dengan proses Poisson.
Secara khusus, dua cara memancarkan data ditampilkan:

1. melalui variabel terlacak yang terhubung ke satu Probe:

Nilai Tertelusur m_konter; // biasanya ini adalah tipe integer

2. melalui penghitung yang nilainya diposting ke Probe kedua, direferensikan dengan namanya di
sistem konfigurasi:

membatalkan
Emitor::Hitung (void)
{
NS_LOG_FUNCTION (ini);
NS_LOG_DEBUG("Menghitung pada " << Simulator::Sekarang ().GetSeconds ());
m_counter += 1.0;
DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
Simulator::Jadwal (Detik (m_var->GetValue ()), &Emitter::Count, this);
}

Mari kita lihat Probe lebih hati-hati. Probe dapat menerima nilainya dalam beberapa
cara:

1. oleh Probe mengakses sumber jejak secara langsung dan menghubungkan wastafel jejak ke sana

2. oleh Probe mengakses sumber jejak melalui namespace konfigurasi dan menghubungkan a
jejak tenggelam untuk itu

3. dengan kode panggilan yang secara eksplisit memanggil Probe's SetNilai() metode

4. dengan kode panggilan yang secara eksplisit memanggil SetNilaiDenganPath
("/path/melalui/Config/namespace", ...)

Dua teknik pertama diharapkan menjadi yang paling umum. Juga dalam contoh,
pengait dari fungsi panggilan balik normal ditampilkan, seperti yang biasanya dilakukan di ns-3. Ini
fungsi panggilan balik tidak terkait dengan objek Probe. Kami akan menyebut kasus ini 0) di bawah ini.

// Ini adalah fungsi untuk menguji pengait fungsi mentah ke sumber jejak
membatalkan
NotifyViaTraceSource (std::string konteks, double oldVal, double newVal)
{
NS_LOG_DEBUG("konteks: " << konteks << " lama " << oldVal << " baru " << newVal);
}

Pertama, emitor perlu diatur:

Ptr emitor = BuatObjek ();
Nama::Tambahkan ("/Nama/Emitter", emitor);

// Objek Emitter tidak terkait dengan node ns-3, jadi
// itu tidak akan dimulai secara otomatis, jadi kita harus melakukannya sendiri
Simulator::Jadwal (Detik (0.0), &Emitter::Start, emitter);

Berbagai DoubleProbes berinteraksi dengan emitor dalam contoh seperti yang ditunjukkan di bawah ini.

Kasus 0):

// Di bawah ini menunjukkan fungsionalitas tipikal tanpa probe
// (menghubungkan fungsi sink ke sumber jejak)
//
terhubung = emitor->TraceConnect ("Penghitung", "konteks sampel", MakeCallback (&NotifyViaTraceSource));
NS_ASSERT_MSG (terhubung, "Jejak sumber tidak terhubung");

kasus 1):

//
// Probe1 akan terhubung langsung ke objek sumber jejak Emitor
//

// probe1 akan terhubung ke sumber jejak Emitter
Ptr probe1 = BuatObjek ();
// nama probe dapat berfungsi sebagai konteksnya dalam penelusuran
probe1->SetName("ObjectProbe");

// Hubungkan probe ke Penghitung emitor
terhubung = probe1->ConnectByObject ("Counter", emitor);
NS_ASSERT_MSG (terhubung, "Sumber jejak tidak terhubung ke probe1");

kasus 2):

//
// Probe2 akan terhubung ke objek sumber jejak Emitter dengan
// mengaksesnya dengan nama jalur di database Config
//

// Buat probe serupa lainnya; ini akan terhubung melalui jalur Config
Ptr probe2 = BuatObjek ();
probe2->SetName("PathProbe");

// Catatan, tidak ada nilai balik yang diperiksa di sini
probe2->ConnectByPath ("/Nama/Emitter/Counter");

kasus 4) (kasus 3 tidak ditampilkan dalam contoh ini):

//
// Probe3 akan dipanggil oleh emitor langsung melalui
// metode statis SetValueByPath().
//
Ptr probe3 = BuatObjek ();
probe3->SetName("Probe yang Diakses Secara Statis");
// Kita harus menambahkannya ke database konfigurasi
Names::Add ("/Names/Probes", probe3->GetName(), probe3);

Dan akhirnya, contoh menunjukkan bagaimana probe dapat dihubungkan untuk menghasilkan output:

// Probe itu sendiri harus menghasilkan output. Konteks yang kami sediakan
// untuk probe ini (dalam hal ini, nama probe) akan membantu untuk memperjelas
// sumber jejak
terhubung = probe3->TraceConnect ("Output",
"/Nama/Probe/Probe/Output yang Diakses Secara Statis",
MakeCallback (&BeritahuViaProbe));
NS_ASSERT_MSG (connected, "Trace source not.. connected to probe3 Output");

Callback berikut terhubung ke Probe dalam contoh ini untuk tujuan ilustrasi;
biasanya, Probe akan terhubung ke objek Kolektor.

// Ini adalah fungsi untuk menguji pengaitnya ke keluaran probe
membatalkan
NotifyViaProbe (std::string konteks, double oldVal, double newVal)
{
NS_LOG_DEBUG("konteks: " << konteks << " lama " << oldVal << " baru " << newVal);
}

IPv4 Paket Merencanakan Example
Contoh plot paket IPv4 didasarkan pada contoh kelima.cc dari ns-3 tutorial. Dia
dapat ditemukan di src/stats/examples/ipv4-packet-plot-example.cc.

simpul 0 simpul 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, karena menggambarkan bahwa Probe juga dapat membongkar nilai dari
struktur (dalam hal ini, paket) dan melaporkan nilai-nilai tersebut sebagai keluaran sumber jejak, bukan
daripada hanya melewati jenis data yang sama.

Ada aspek lain dari contoh ini yang akan dijelaskan nanti dalam dokumentasi.
Dua jenis data yang diekspor adalah paket itu sendiri (Keluaran) dan jumlah
jumlah byte dalam paket (OutputByte).

TypeId
IPv4PacketProbe::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::Ipv4PacketProbe")
.SetInduk ()
.TambahkanKonstruktor ()
.AddTraceSource ("Keluaran",
"Paket ditambah objek IPv4 dan antarmuka yang berfungsi sebagai output untuk probe ini",
MakeTraceSourceAccessor (&Ipv4PacketProbe::m_output))
.AddTraceSource ("OutputBytes",
"Jumlah byte dalam paket",
MakeTraceSourceAccessor (&Ipv4PacketProbe::m_outputBytes))
;
kembali tid;
}

Ketika trace sink Probe mendapat paket, jika Probe diaktifkan, maka akan keluar
paket di nya Keluaran trace source, tetapi juga akan menampilkan jumlah byte pada
OutputByte sumber jejak.

membatalkan
IPv4PacketProbe::TraceSink (Ptr paket, Ptr ipv4, antarmuka uint4_t)
{
NS_LOG_FUNCTION (ini << paket << ipv4 << antarmuka);
jika (Diaktifkan ())
{
m_paket = paket;
m_ipv4 = ipv4;
m_interface = antarmuka;
m_output (paket, ipv4, antarmuka);

uint32_t packetSizeNew = paket->GetSize();
m_outputBytes (m_packetSizeOld, packetSizeNew);
m_packetSizeOld = paketSizeNew;
}
}

Referensi
[Cic06]
Claudio Cicconetti, Enzo Mingozzi, Giovanni Stea, "Kerangka Terintegrasi untuk
Mengaktifkan Pengumpulan Data dan Analisis Statistik yang Efektif dengan ns2, Lokakarya tentang
ns-2 (WNS2), Pisa, Italia, Oktober 2006.

Kolektor
Bagian ini adalah tempat untuk merinci fungsi yang disediakan oleh Kolektor
kelas ke ns-3 simulasi, dan memberikan contoh bagaimana mengkodekannya dalam sebuah program.

Catatan: Pada ns-3.18, Kolektor masih dalam pengembangan dan belum disediakan sebagai bagian
dari kerangka kerja.

Agregator
Bagian ini merinci fungsionalitas yang disediakan oleh kelas Aggregator untuk ns-3
simulasi. Bagian ini dimaksudkan untuk pengguna yang tertarik untuk mengembangkan simulasi dengan
ns-3 alat dan menggunakan Kerangka Pengumpulan Data, di mana kelas Aggregator adalah
bagian, untuk menghasilkan output data dengan hasil simulasi mereka.

Agregator Ringkasan
Objek Agregator seharusnya terhubung ke satu atau lebih sumber jejak untuk
menerima masukan. Agregator adalah titik akhir dari data yang dikumpulkan oleh jaringan
Probe dan Kolektor selama simulasi. Adalah tugas Agregator untuk mengambil ini
nilai dan mengubahnya ke dalam format output akhir mereka seperti file teks biasa,
file spreadsheet, plot, atau database.

Biasanya, agregator terhubung ke satu atau lebih Kolektor. Dengan cara ini, kapanpun
sumber jejak Kolektor mengekspor nilai baru, Agregator dapat memproses nilai sehingga
bahwa itu dapat digunakan dalam format keluaran akhir di mana nilai data akan berada setelah
simulasi.

Perhatikan hal berikut tentang Agregator:

· Agregator dapat dihidupkan dan dimatikan secara dinamis selama simulasi dengan panggilan ke
Memungkinkan() dan Cacat(). Misalnya, agregasi data mungkin dimatikan selama
fase pemanasan simulasi, yang berarti nilai-nilai itu tidak akan dimasukkan ke dalam final
media keluaran.

· Agregator menerima data dari Kolektor melalui panggilan balik. Ketika Kolektor dikaitkan
ke agregator, panggilan ke TraceConnect dilakukan untuk membuat jejak Aggregator
sink metode sebagai panggilan balik.

Sampai saat ini, dua Agregator telah diterapkan:

· GnuplotAggregator

· Pengumpul File

Agregator Gnuplot
GnuplotAggregator menghasilkan file keluaran yang digunakan untuk membuat gnuplot.

GnuplotAggregator akan membuat 3 file berbeda di akhir simulasi:

· File data gnuplot yang dipisahkan spasi

· File kontrol gnuplot

· Skrip shell untuk menghasilkan gnuplot

Penciptaan
Objek bertipe GnuplotAggregator akan dibuat di sini untuk menunjukkan apa yang perlu dilakukan.

Seseorang mendeklarasikan GnuplotAggregator dalam memori dinamis dengan menggunakan kelas penunjuk pintar
(Ptr ). Untuk membuat GnuplotAggregator dalam memori dinamis dengan smart pointer, satu saja
perlu menelepon ns-3 metode BuatObjek(). Kode berikut dari
src/stats/examples/gnuplot-aggregator-example.cc menunjukkan bagaimana melakukan ini:

string fileNameWithoutExtension = "gnuplot-agregator";

// Buat agregator.
Ptr agregator =
BuatObjek (fileNameWithoutExtension);

Argumen pertama untuk konstruktor, fileNameWithoutExtension, adalah nama dari
file terkait gnuplot untuk ditulis tanpa ekstensi. GnuplotAggregator ini akan membuat
file data gnuplot yang dipisahkan spasi bernama "gnuplot-aggregator.dat", file kontrol gnuplot
bernama "gnuplot-aggregator.plt", dan skrip shell untuk menghasilkan gnuplot bernama +
"gnuplot-agregator.sh".

Gnuplot yang dibuat dapat memiliki kuncinya di 4 lokasi berbeda:

· Tidak ada kunci

· Kunci di dalam plot (default)

· Kunci di atas plot

· Kunci di bawah plot

Nilai enum lokasi kunci gnuplot berikut diizinkan untuk menentukan posisi kunci:

enum Lokasi Kunci {
TIDAK_KUNCI,
KUNCI_ DALAM,
KUNCI_ DI ATAS,
KUNCI_BAWAH
};

Jika diinginkan untuk memiliki kunci di bawah daripada posisi default di dalam, maka
Anda dapat melakukan hal berikut.

agregator->SetKeyLocation(GnuplotAggregator::KEY_BELOW);

contoh
Salah satu contoh akan dibahas secara rinci di sini:

· Contoh Agregator Gnuplot

gnuplot Agregator Example
Contoh latihan GnuplotAggregator dapat ditemukan di
src/stats/examples/gnuplot-aggregator-example.cc.

Gnuplot 2-D berikut dibuat menggunakan contoh.
[image] Gnuplot 2-D Dibuat oleh gnuplot-aggregator-example.cc Contoh..UNINDENT

Kode dari contoh ini menunjukkan bagaimana membangun GnuplotAggregator seperti yang telah dibahas
atas.

batal Buat2dPlot ()
{
menggunakan namespace std;

string fileNameWithoutExtension = "gnuplot-agregator";
string plotTitle = "Plot Agregator Gnuplot";
string plotXAxisHeading = "Waktu (detik)";
string plotYAxisHeading = "Nilai Ganda";
string plotDatasetLabel = "Nilai Data";
string datasetContext = "Dataset/Konteks/String";

// Buat agregator.
Ptr agregator =
BuatObjek (fileNameWithoutExtension);

Berbagai atribut GnuplotAggregator diatur termasuk dataset 2-D yang akan
diplot.

// Setel properti agregator.
agregator->SetTerminal ("png");
agregator->SetTitle (plotTitle);
agregator->SetLegend (plotXAxisHeading, plotYAxisHeading);

// Tambahkan kumpulan data ke agregator.
aggregator->Add2dDataset (datasetContext, plotDatasetLabel);

// agregator harus diaktifkan
agregator->Aktifkan ();

Selanjutnya, nilai 2-D dihitung, dan masing-masing secara individual ditulis ke
GnuplotAggregator menggunakan tulis2d() fungsi.

waktu ganda;
nilai ganda;

// Buat kumpulan data 2-D.
untuk (waktu = -5.0; waktu <= +5.0; waktu += 1.0)
{
// Hitung kurva 2-D
//
// 2
// nilai = waktu .
//
nilai = waktu * waktu;

// Tambahkan titik ini ke plot.
aggregator->Write2d (datasetContext, waktu, nilai);
}

// Nonaktifkan pencatatan data untuk agregator.
agregator->Nonaktifkan ();
}

Agregator File
FileAggregator mengirimkan nilai yang diterimanya ke file.

FileAggregator dapat membuat 4 jenis file yang berbeda:

· Diformat

· Spasi dipisahkan (default)

· Dipisahkan koma

· Tab dipisahkan

File yang diformat menggunakan string format gaya-C dan fungsi sprintf() untuk mencetaknya
nilai dalam file yang sedang ditulis.

Penciptaan
Objek bertipe FileAggregator akan dibuat di sini untuk menunjukkan apa yang perlu dilakukan.

Seseorang mendeklarasikan FileAggregator dalam memori dinamis dengan menggunakan kelas penunjuk pintar (Ptr ).
Untuk membuat FileAggregator dalam memori dinamis dengan smart pointer, Anda hanya perlu memanggil
itu ns-3 metode CreateObject. Kode berikut dari
src/stats/examples/file-agregator-example.cc menunjukkan bagaimana melakukan ini:

string fileName = "file-agregator-formatted-values.txt";

// Buat agregator yang akan memiliki nilai yang diformat.
Ptr agregator =
BuatObjek (namafile, FileAggregator::FORMATTED);

Argumen pertama untuk konstruktor, nama file, adalah nama file yang akan ditulis; itu
argumen kedua, fileType, adalah tipe file yang akan ditulis. FileAggregator ini akan membuat
file bernama "file-aggregator-formatted-values.txt" dengan nilainya dicetak seperti yang ditentukan oleh
fileType, yaitu, diformat dalam kasus ini.

Nilai enum jenis file berikut diizinkan:

enum Jenis File {
diformat,
SPASI_TERPISAH,
KOMA_TERPISAH,
TAB_TERPISAH
};

contoh
Salah satu contoh akan dibahas secara rinci di sini:

· Contoh File Agregator

File Agregator Example
Contoh latihan FileAggregator dapat ditemukan di
src/stats/examples/file-agregator-example.cc.

File teks berikut dengan 2 kolom nilai yang dipisahkan oleh koma dibuat menggunakan:
contoh.

-5,25
-4,16
-3,9
-2,4
-1,1
0,0
1,1
2,4
3,9
4,16
5,25

Kode dari contoh ini menunjukkan cara membuat FileAggregator seperti yang telah dibahas
atas.

batal CreateCommaSeparatedFile()
{
menggunakan namespace std;

string fileName = "file-agregator-comma-separated.txt";
string datasetContext = "Dataset/Konteks/String";

// Buat agregator.
Ptr agregator =
BuatObjek (namafile, FileAggregator::COMMA_SEPARATED);

Atribut FileAggregator diatur.

// agregator harus diaktifkan
agregator->Aktifkan ();

Selanjutnya, nilai 2-D dihitung, dan masing-masing secara individual ditulis ke
FileAggregator menggunakan tulis2d() fungsi.

waktu ganda;
nilai ganda;

// Buat kumpulan data 2-D.
untuk (waktu = -5.0; waktu <= +5.0; waktu += 1.0)
{
// Hitung kurva 2-D
//
// 2
// nilai = waktu .
//
nilai = waktu * waktu;

// Tambahkan titik ini ke plot.
aggregator->Write2d (datasetContext, waktu, nilai);
}

// Nonaktifkan pencatatan data untuk agregator.
agregator->Nonaktifkan ();
}

File teks berikut dengan 2 kolom nilai yang diformat juga dibuat menggunakan
contoh.

Waktu = -5.000e+00 Nilai = 25
Waktu = -4.000e+00 Nilai = 16
Waktu = -3.000e+00 Nilai = 9
Waktu = -2.000e+00 Nilai = 4
Waktu = -1.000e+00 Nilai = 1
Waktu = 0.000e+00 Nilai = 0
Waktu = 1.000e+00 Nilai = 1
Waktu = 2.000e+00 Nilai = 4
Waktu = 3.000e+00 Nilai = 9
Waktu = 4.000e+00 Nilai = 16
Waktu = 5.000e+00 Nilai = 25

Kode dari contoh ini menunjukkan cara membuat FileAggregator seperti yang telah dibahas
atas.

batal CreateFormattedFile ()
{
menggunakan namespace std;

string fileName = "file-agregator-formatted-values.txt";
string datasetContext = "Dataset/Konteks/String";

// Buat agregator yang akan memiliki nilai yang diformat.
Ptr agregator =
BuatObjek (namafile, FileAggregator::FORMATTED);

Atribut FileAggregator diatur, termasuk string format gaya-C yang akan digunakan.

// Tetapkan format untuk nilai.
aggregator->Set2dFormat("Waktu = %.3e\tValue = %.0f");

// agregator harus diaktifkan
agregator->Aktifkan ();

Selanjutnya, nilai 2-D dihitung, dan masing-masing secara individual ditulis ke
FileAggregator menggunakan tulis2d() fungsi.

waktu ganda;
nilai ganda;

// Buat kumpulan data 2-D.
untuk (waktu = -5.0; waktu <= +5.0; waktu += 1.0)
{
// Hitung kurva 2-D
//
// 2
// nilai = waktu .
//
nilai = waktu * waktu;

// Tambahkan titik ini ke plot.
aggregator->Write2d (datasetContext, waktu, nilai);
}

// Nonaktifkan pencatatan data untuk agregator.
agregator->Nonaktifkan ();
}

Adaptor
Bagian ini merinci fungsionalitas yang disediakan oleh kelas Adaptor untuk ns-3
simulasi. Bagian ini dimaksudkan untuk pengguna yang tertarik untuk mengembangkan simulasi dengan
ns-3 alat dan menggunakan Kerangka Pengumpulan Data, di mana kelas Adaptor adalah bagiannya,
untuk menghasilkan output data dengan hasil simulasi mereka.

Catatan: istilah 'adaptor' juga bisa dieja 'adaptor'; kami memilih ejaan yang selaras
dengan standar C++.

Adaptor Ringkasan
Adaptor digunakan untuk membuat koneksi antara berbagai jenis objek DCF.

Sampai saat ini, satu Adaptor telah diterapkan:

· Adaptor Seri Waktu

Waktu Seri Adaptor
TimeSeriesAdaptor memungkinkan Probe terhubung langsung ke Agregator tanpa perlu apa pun
Kolektor di antaranya.

Kedua helper DCF yang diimplementasikan menggunakan TimeSeriesAdaptors untuk melakukan penyelidikan
nilai dari berbagai jenis dan keluaran waktu saat ini ditambah nilai dengan keduanya dikonversi
untuk menggandakan.

Peran kelas TimeSeriesAdaptor adalah sebagai adaptor, yang mengambil nilai mentah
menyelidiki data dari tipe yang berbeda dan mengeluarkan sebuah tupel dengan dua nilai ganda. Yang pertama adalah
timestamp, yang dapat diatur ke resolusi yang berbeda (mis. Detik, Milidetik, dll.) di
masa depan tetapi yang saat ini di-hardcode ke Detik. Yang kedua adalah konversi dari
nilai non-ganda menjadi nilai ganda (mungkin dengan hilangnya presisi).

Cakupan/Batasan
Bagian ini membahas ruang lingkup dan batasan Kerangka Pengumpulan Data.

Saat ini, hanya Probe ini yang telah diimplementasikan di DCF:

· Penyelidikan Boolean

· Penyelidikan Ganda

· Uinteger8Probe

· Uinteger16Probe

· Uinteger32Probe

· Penyelidikan Waktu

· PaketProbe

· ApplicationPacketProbe

· IPv4PacketProbe

Saat ini, tidak ada Kolektor yang tersedia di DCF, meskipun BasicStatsCollector berada di bawah
pembangunan.

Saat ini, hanya Agregator berikut yang telah diterapkan di DCF:

· GnuplotAggregator

· Pengumpul File

Saat ini, hanya Adaptor ini yang telah diterapkan di DCF:

Adaptor Seri Waktu.

Masa depan Kerja
Bagian ini membahas pekerjaan masa depan yang harus dilakukan pada Kerangka Pengumpulan Data.

Berikut beberapa hal yang masih perlu dilakukan:

· Hubungkan lebih banyak sumber jejak di ns-3 kode untuk mendapatkan lebih banyak nilai dari simulator.

· Menerapkan lebih banyak jenis Probe daripada yang ada saat ini.

· Menerapkan lebih dari sekedar Kolektor 2-D tunggal saat ini, BasicStatsCollector.

· Terapkan lebih banyak Agregator.

· Menerapkan lebih dari sekedar Adaptor.

Statistik Kerangka
Bab ini menguraikan pekerjaan pengumpulan data simulasi dan kerangka statistik untuk
ns-3.

Kode sumber untuk kerangka statistik tinggal di direktori src/statistik.

Anda
Tujuan utama dari upaya ini adalah sebagai berikut:

· Menyediakan fungsionalitas untuk merekam, menghitung, dan menyajikan data dan statistik untuk analisis
dari simulasi jaringan.

· Tingkatkan kinerja simulasi dengan mengurangi kebutuhan untuk menghasilkan log jejak yang ekstensif
perintah untuk mengumpulkan data.

· Aktifkan kontrol simulasi melalui statistik online, misalnya mengakhiri simulasi atau
percobaan berulang.

Sub-tujuan yang diturunkan dan fitur target lainnya mencakup hal-hal berikut:

· Integrasi dengan sistem penelusuran ns-3 yang ada sebagai kerangka instrumentasi dasar
dari mesin simulasi internal, misalnya tumpukan jaringan, perangkat bersih, dan saluran.

· Memungkinkan pengguna untuk memanfaatkan kerangka statistik tanpa memerlukan penggunaan penelusuran
sistem.

· Membantu pengguna membuat, menggabungkan, dan menganalisis data melalui beberapa percobaan.

· Dukungan untuk instrumentasi yang dibuat pengguna, misalnya peristiwa khusus aplikasi dan
langkah-langkah.

· Memori rendah dan overhead CPU saat paket tidak digunakan.

· Memanfaatkan alat analisis dan keluaran yang ada sebanyak mungkin. Kerangka kerja mungkin
memberikan beberapa statistik dasar, tetapi fokusnya adalah mengumpulkan data dan membuatnya
dapat diakses untuk manipulasi dalam alat yang sudah ada.

· Dukungan akhirnya untuk mendistribusikan replikasi independen adalah penting tetapi tidak termasuk
di babak pertama fitur.

Ringkasan
Kerangka statistik mencakup fitur-fitur berikut:

· Kerangka inti dan dua pengumpul data dasar: Penghitung, dan min/maks/rata-rata/total
pengamat.

· Ekstensi dari mereka untuk dengan mudah bekerja dengan waktu dan paket.

· Output teks biasa diformat untuk OMNet++.

· Keluaran basis data menggunakan SQLite, mesin SQL mandiri, ringan, dan berkinerja tinggi.

· Metadata wajib dan terbuka untuk mendeskripsikan dan bekerja dengan proses.

· Contoh berdasarkan eksperimen nosional dalam memeriksa sifat-sifat NS-3
kinerja WiFi ad hoc default. Ini mencakup berikut ini:

· Konstruksi jaringan WiFi ad hoc dua node, dengan jarak node yang diparameterisasi
selain.

· Sumber lalu lintas UDP dan aplikasi sink dengan perilaku yang sedikit berbeda dan
kait pengukuran daripada kelas stok.

· Pengumpulan data dari inti NS-3 melalui sinyal jejak yang ada, khususnya data di
frame ditransmisikan dan diterima oleh objek WiFi MAC.

· Instrumentasi aplikasi khusus dengan menghubungkan sinyal jejak baru ke stat
framework, serta melalui pembaruan langsung. Informasi dicatat tentang total paket
dikirim dan diterima, byte yang ditransmisikan, dan penundaan ujung ke ujung.

· Contoh penggunaan tag paket untuk melacak penundaan end-to-end.

· Sebuah skrip kontrol sederhana yang menjalankan sejumlah percobaan percobaan di berbagai
jarak dan query database yang dihasilkan untuk menghasilkan grafik menggunakan GNUPlot.

Melakukan
Item prioritas tinggi meliputi:

· Penyertaan kode statistik online, misalnya untuk interval kepercayaan yang efisien memori.

· Ketentuan dalam pengumpul data untuk mengakhiri berjalan, yaitu ketika ambang batas atau
kepercayaan terpenuhi.

· Pengumpul data untuk sampel logging dari waktu ke waktu, dan output ke berbagai format.

· Mendemonstrasikan menulis lem acara siklik sederhana untuk secara teratur mengumpulkan beberapa nilai.

Masing-masing harus terbukti mudah untuk dimasukkan ke dalam kerangka kerja saat ini.

Pendekatan
Kerangka kerja ini didasarkan pada prinsip-prinsip inti berikut:

· Satu percobaan percobaan dilakukan oleh satu contoh program simulasi, baik dalam
paralel atau serial.

· Sebuah skrip kontrol mengeksekusi contoh simulasi, memvariasikan parameter yang diperlukan.

· Data dikumpulkan dan disimpan untuk diplot dan dianalisis menggunakan skrip eksternal dan
alat yang ada.

· Langkah-langkah dalam inti ns-3 diambil dengan menghubungkan kerangka kerja stat ke yang ada
jejak sinyal.

· Jejak sinyal atau manipulasi langsung dari kerangka kerja dapat digunakan untuk instrumen adat
kode simulasi.

Komponen dasar kerangka kerja tersebut dan interaksinya digambarkan dalam
gambar berikut. [gambar]

Example
Bagian ini membahas proses membangun eksperimen dalam kerangka dan
menghasilkan data untuk analisis (grafik) darinya, menunjukkan struktur dan API bersama
jalan.

Pertanyaan
''Berapa performa (simulasi) WiFi NetDevices ns-3 (menggunakan default .)
pengaturan)? Seberapa jauh jarak node nirkabel dalam simulasi sebelum mereka tidak bisa
berkomunikasi dengan andal?''

· Hipotesis: Berdasarkan pengetahuan tentang kinerja kehidupan nyata, node harus berkomunikasi
cukup baik untuk setidaknya 100 m terpisah. Komunikasi di luar 200m seharusnya tidak
layak.

Meskipun bukan pertanyaan yang sangat umum dalam konteks simulasi, ini adalah properti penting
yang pengembang simulasi harus memiliki pemahaman dasar. Itu juga umum
studi dilakukan pada perangkat keras langsung.

Simulasi program
Hal pertama yang harus dilakukan dalam melaksanakan percobaan ini adalah mengembangkan simulasi
program. Kode untuk contoh ini dapat ditemukan di contoh/statistik/wifi-contoh-sim.cc.
Ia melakukan langkah-langkah utama berikut.

· Mendeklarasikan parameter dan mengurai baris perintah menggunakan ns3::Baris Perintah.

jarak ganda = 50.0;
format string("OMNet++");
percobaan string ("wifi-distance-test");
strategi string ("wifi-default");
string runID;

cmd baris perintah;
cmd.AddValue("jarak", "Jarak terpisah untuk menempatkan node (dalam meter).", jarak);
cmd.AddValue("format", "Format yang digunakan untuk keluaran data.", format);
cmd.AddValue("eksperimen", "Identifier untuk eksperimen.", eksperimen);
cmd.AddValue("strategi", "Identifier untuk strategi.", strategi);
cmd.AddValue("run", "Identifier untuk dijalankan.", runID);
cmd.Parse (argc, argv);

· Membuat node dan tumpukan jaringan menggunakan ns3::Kontainer Node, ns3::Pembantu WiFi, dan
ns3::InternetStackHelper.

NodeContainer node;
node.Buat(2);

Wifi Pembantu wifi;
wifi.SetMac("ns3::AdhocWifiMac");
wifi.SetPhy("ns3::WifiPhy");
NetDeviceContainer nodeDevices = wifi.Install(node);

InternetStackHelperinternet;
internet.Instal(node);
Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase("192.168.0.0", "255.255.255.0");
ipAddrs.Assign(nodeDevices);

· Memposisikan node menggunakan ns3::Pembantu Mobilitas. Secara default node memiliki static
mobilitas dan tidak akan bergerak, tetapi harus diposisikan dengan jarak tertentu. Ada
beberapa cara untuk melakukan ini; itu dilakukan di sini menggunakan ns3::ListPositionAllocator, yang menarik
posisi dari daftar yang diberikan.

MobilitasMobilitas pembantu;
Ptr alokasi posisi =
BuatObjek ();
positionAlloc->Add(Vector(0.0, 0.0, 0.0));
positionAlloc->Add(Vector(0.0, jarak, 0.0));
mobilitas.SetPositionAllocator(positionAlloc);
mobilitas.Instal(node);

· Memasang generator lalu lintas dan wastafel lalu lintas. saham Aplikasi bisa
digunakan, tetapi contohnya termasuk objek khusus di src/test/test02-apps.(cc|h). Ini
memiliki perilaku sederhana, menghasilkan sejumlah paket yang ditempatkan pada interval tertentu.
Karena hanya ada satu dari masing-masing yang diinstal secara manual; untuk set yang lebih besar
ns3::ApplicationHelper kelas dapat digunakan. Yang dikomentari Konfigurasi::Setel perubahan garis
tujuan paket, diatur untuk disiarkan secara default dalam contoh ini. Perhatikan bahwa
secara umum WiFi mungkin memiliki kinerja yang berbeda untuk frame siaran dan unicast karena
kontrol tingkat yang berbeda dan kebijakan transmisi ulang MAC.

Ptr appSource = DaftarNode::DapatkanNode(0);
Ptr pengirim = BuatObjek ();
appSource->AddApplication(pengirim);
pengirim->Mulai(Detik(1));

Ptr appSink = DaftarNode::DapatkanNode(1);
Ptr penerima = BuatObjek ();
appSink->AddApplication(penerima);
penerima->Mulai(Detik(0));

// Config::Set("/NodeList/*/ApplicationList/*/$Sender/Destination",
// Ipv4AddressValue("192.168.0.2"));

· Konfigurasi data dan statistik yang akan dikumpulkan. Paradigma dasarnya adalah bahwa
ns3::Pengumpul Data objek dibuat untuk menyimpan informasi tentang proses khusus ini, untuk
yang pengamat dan kalkulator dilampirkan untuk benar-benar menghasilkan data. Penting,
menjalankan informasi termasuk label untuk ''eksperimen'', ''strategi'', ''input'', dan
''Lari''. Ini digunakan untuk kemudian mengidentifikasi dan dengan mudah mengelompokkan data dari beberapa percobaan.

· Eksperimen adalah studi di mana percobaan ini menjadi anggotanya. Ini dia di WiFi
kinerja dan jarak.

· Strategi adalah kode atau parameter yang diperiksa dalam uji coba ini. Dalam contoh ini
sudah diperbaiki, tetapi ekstensi yang jelas adalah menyelidiki bit WiFi yang berbeda
tarif, yang masing-masing akan menjadi strategi yang berbeda.

· Masukan adalah masalah khusus yang diberikan pada percobaan ini. Ini dia
jarak antara dua node.

· RunID adalah pengidentifikasi unik untuk percobaan ini yang informasinya ditandai
untuk identifikasi dalam analisis selanjutnya. Jika tidak ada ID run yang diberikan, contoh program membuat
a (lemah) menjalankan ID menggunakan waktu saat ini.

Keempat bagian metadata tersebut diperlukan, tetapi mungkin lebih banyak lagi yang diinginkan. Mereka dapat ditambahkan
untuk merekam menggunakan ns3::DataCollector::TambahkanMetadata() Metode.

Data Kolektor data;
data.DescribeRun(eksperimen, strategi, masukan, runID);
data.AddMetadata("penulis", "tjkopena");

Pengamatan dan perhitungan yang sebenarnya dilakukan oleh ns3::Kalkulator Data benda, yang mana
beberapa jenis yang berbeda ada. Ini dibuat oleh program simulasi, dilampirkan ke
pelaporan atau kode pengambilan sampel, dan kemudian didaftarkan ke ns3::Pengumpul Data jadi mereka akan
akan diminta kemudian untuk output mereka. Salah satu mekanisme pengamatan yang mudah adalah dengan menggunakan yang ada
melacak sumber, misalnya ke objek instrumen di inti ns-3 tanpa mengubah
kode. Di sini penghitung terpasang langsung ke sinyal jejak di lapisan MAC WiFi di
simpul sasaran.

Ptr totalRx = BuatObjek ();
totalRx->SetKey("wifi-rx-frame");
Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Rx",
MakeCallback(&PacketCounterCalculator::FrameUpdate, totalRx));
data.AddDataCalculator(totalRx);

Kalkulator juga dapat dimanipulasi secara langsung. Dalam contoh ini, penghitung dibuat dan
diteruskan ke aplikasi traffic sink untuk diperbarui ketika paket diterima.

Ptr > appRx = CreateObject >();
appRx->SetKey("penerima-rx-paket");
penerima->SetCounter(appRx);
data.AddDataCalculator(appRx);

Untuk menambah hitungan, kode pemrosesan paket sink kemudian memanggil salah satu dari
metode pembaruan kalkulator.

m_calc->Perbarui();

Program ini mencakup beberapa contoh lain juga, menggunakan kedua primitif
kalkulator seperti ns3::CounterCalculator dan yang diadaptasi untuk mengamati paket dan
waktu. Di src/test/test02-apps.(cc|h) itu juga membuat tag khusus sederhana yang digunakannya
untuk melacak penundaan end-to-end untuk paket yang dihasilkan, melaporkan hasil ke a
ns3::TimeMinMaxAvgTotalCalculator kalkulator data.

· Menjalankan simulasi, yang sangat mudah setelah dibangun.

Simulator::Jalankan();

· Menghasilkan baik OMNet++ or SQLite output, tergantung pada argumen baris perintah. Ke
lakukan ini ns3::DataOutputInterface objek dibuat dan dikonfigurasi. Jenis tertentu
ini akan menentukan format output. Benda ini kemudian diberi
ns3::Pengumpul Data objek yang diinterogasi untuk menghasilkan output.

Ptr keluaran;
if (format == "OMNet++") {
NS_LOG_INFO("Membuat keluaran data berformat OMNet++.");
keluaran = BuatObjek ();
} Else {
#ifdef STAT_USE_DB
NS_LOG_INFO("Membuat keluaran data berformat SQLite.");
keluaran = BuatObjek ();
# berakhir jika
}

keluaran->Keluaran(data);

· Membebaskan memori yang digunakan oleh simulasi. Ini harus datang di akhir main
fungsi untuk contoh.

Simulator::Hancurkan();

Logging
Untuk melihat apa yang dilakukan contoh program, aplikasi, dan kerangka kerja stat secara detail, set
itu NS_LOG variabel dengan tepat. Berikut ini akan memberikan hasil yang banyak dari semua
tiga.

$ ekspor NS_LOG=WiFiDistanceExperiment:WiFiDistanceApps

Perhatikan bahwa ini memperlambat simulasi secara luar biasa.

Contoh Keluaran
Mengkompilasi dan menjalankan program pengujian akan ditambahkan OMNet++ keluaran yang diformat seperti
berikut ini data.sca.

lari lari-1212239121

percobaan attr "wifi-distance-test"
strategi attr "wifi-default"
masukan attr "50"
deskripsi attr ""

attr "penulis" "tjkopena"

skalar wifi-tx-frame menghitung 30
skalar wifi-rx-frame menghitung 30
skalar pengirim-tx-paket menghitung 30
penerima skalar-rx-paket menghitung 30
skalar tx-pkt-ukuran hitungan 30
skalar tx-pkt-ukuran total 1920
skalar tx-pkt-ukuran rata-rata 64
skalar tx-pkt-ukuran maks 64
skalar ukuran tx-pkt min 64
hitung penundaan skalar 30
penundaan skalar total 5884980ns
skalar penundaan rata-rata 196166ns
penundaan skalar maks 196166ns
penundaan skalar min 196166ns

kontrol Naskah
Untuk mengotomatisasi pengumpulan data pada berbagai input (jarak), Bash . sederhana
script digunakan untuk menjalankan serangkaian simulasi. Dapat ditemukan di
contoh/statistik/wifi-contoh-db.sh. Script dimaksudkan untuk dijalankan dari contoh/statistik/
direktori.

Script berjalan melalui serangkaian jarak, mengumpulkan hasilnya ke dalam SQLite
basis data. Pada setiap jarak lima percobaan dilakukan untuk memberikan gambaran yang lebih baik dari yang diharapkan
pertunjukan. Seluruh eksperimen hanya membutuhkan beberapa lusin detik untuk berjalan di low end
mesin karena tidak ada output selama simulasi dan sedikit lalu lintas yang dihasilkan.

#!/ Bin / sh

JARAK="25 50 75 100 125 145 147 150 152 155 157 160 162 165 167 170 172 175 177 180"
PERCOBAAN="1 2 3 4 5"

echo Contoh Percobaan WiFi

jika [ -e data.db ]
kemudian
echo Bunuh data.db?
baca ANS
if [ "$ANS" = "ya" -o "$ANS" = "y" ]
kemudian
echo Menghapus basis data
rm data.db
fi
fi

untuk uji coba di $TRIALS
do
untuk jarak dalam $DISTANCES
do
echo Percobaan $percobaan, jarak $jarak
./bin/test02 --format=db --jarak=$jarak --run=run-$jarak-$percobaan
dilakukan
dilakukan

Analisis dan Kesimpulan
Setelah semua uji coba dilakukan, skrip mengeksekusi kueri SQL sederhana melalui
database menggunakan SQLite program baris perintah. Kueri menghitung kehilangan paket rata-rata dalam
setiap set percobaan yang terkait dengan setiap jarak. Itu tidak memperhitungkan perbedaan
strategi, tetapi informasinya ada dalam database untuk membuat beberapa ekstensi sederhana
dan melakukannya. Data yang dikumpulkan kemudian diteruskan ke GNUPlot untuk grafik.

CMD="pilih exp.input,avg(100-((rx.value*100)/tx.value)) \
dari Lajang rx, Lajang tx, Eksperimen exp \
di mana rx.run = tx.run DAN \
rx.run = exp.run DAN \
rx.name='receiver-rx-packets' DAN \
tx.name='pengirim-tx-paket' \
kelompokkan menurut exp.input \
diurutkan berdasarkan abs(exp.input) ASC;"

sqlite3 -noheader data.db "$CMD"> wifi-default.data
sed -i "s/|/ /" wifi-default.data
gnuplot wifi-contoh.gnuplot

Skrip GNUPlot ditemukan di contoh/statistik/wifi-contoh.gnuplot hanya mendefinisikan output
format dan beberapa format dasar untuk grafik.

setel potret postscript terminal ditingkatkan lw 2 "Helvetica" 14

atur ukuran 1.0, 0.66

#------------------------------------------------- ------
setel "wifi-default.eps"
#set judul "Paket Hilang Karena Jarak"
atur xlabel "Jarak (m) --- rata-rata 5 percobaan per titik"
atur xrange [0:200]
atur ylabel "% Packet Loss"
atur rentang [0:110]

plot "wifi-default.data" dengan judul baris "WiFi Defaults"

Akhir Hasil
Grafik yang dihasilkan tidak memberikan bukti bahwa kinerja model WiFi default adalah
tentu tidak masuk akal dan memberikan kepercayaan pada setidaknya kesetiaan tanda untuk
realitas. Lebih penting lagi, penyelidikan sederhana ini telah dilakukan sepenuhnya
menggunakan kerangka statistik. Kesuksesan! [gambar]

Waktu sebenarnya
ns-3 telah dirancang untuk integrasi ke dalam lingkungan testbed dan mesin virtual. Ke
berintegrasi dengan tumpukan jaringan nyata dan memancarkan/mengkonsumsi paket, penjadwal waktu nyata adalah
diperlukan untuk mencoba mengunci jam simulasi dengan jam perangkat keras. Kami jelaskan di sini
komponen ini: penjadwal RealTime.

Tujuan dari penjadwal waktu nyata adalah untuk menyebabkan perkembangan jam simulasi
terjadi serempak sehubungan dengan beberapa basis waktu eksternal. Tanpa kehadiran
basis waktu eksternal (jam dinding), waktu simulasi melompat secara instan dari satu simulasi
waktu ke waktu berikutnya.

Tingkah laku
Saat menggunakan penjadwal non-waktu nyata (default dalam ns-3), simulator memajukan
waktu simulasi ke acara yang dijadwalkan berikutnya. Selama eksekusi acara, waktu simulasi adalah
beku. Dengan penjadwal waktu nyata, perilakunya serupa dari perspektif
model simulasi (yaitu, waktu simulasi dibekukan selama eksekusi acara), tetapi antara
peristiwa, simulator akan berusaha untuk menjaga jam simulasi selaras dengan mesin
jam.

Ketika sebuah acara selesai dieksekusi, dan penjadwal pindah ke acara berikutnya,
scheduler membandingkan waktu eksekusi acara berikutnya dengan jam mesin. Jika selanjutnya
acara dijadwalkan untuk waktu mendatang, simulator tidur sampai waktu nyata tercapai
dan kemudian mengeksekusi acara berikutnya.

Mungkin terjadi bahwa, karena pemrosesan yang melekat dalam pelaksanaan acara simulasi,
bahwa simulator tidak dapat mengikuti secara realtime. Dalam kasus seperti itu, terserah pengguna
konfigurasi apa yang harus dilakukan. Ada dua ns-3 atribut yang mengatur perilaku. Itu
pertama adalah ns3::RealTimeSimulatorImpl::Mode Sinkronisasi. Dua entri mungkin untuk
atribut ini adalah Usaha terbaik (default) atau Batas Keras. Dalam mode "BestEffort",
simulator hanya akan mencoba mengejar waktu nyata dengan menjalankan acara hingga mencapai
titik di mana acara berikutnya berada di masa depan (waktu nyata), atau simulasi berakhir. Di
Mode BestEffort, maka, simulasi mungkin menghabiskan lebih banyak waktu daripada
waktu jam dinding. Opsi lain "HardLimit" akan menyebabkan simulasi dibatalkan jika
batas toleransi terlampaui. Atribut ini adalah ns3::RealTimeSimulatorImpl::HardLimit
dan defaultnya adalah 0.1 detik.

Mode operasi yang berbeda adalah mode di mana waktu simulasi adalah tidak dibekukan selama acara
eksekusi. Mode simulasi waktu nyata ini diimplementasikan tetapi dihapus dari ns-3 pohon
karena pertanyaan apakah itu akan berguna. Jika pengguna tertarik secara realtime
simulator yang waktu simulasinya tidak membeku selama eksekusi acara (yaitu, setiap
panggilan ke Simulator::Sekarang() mengembalikan waktu jam dinding saat ini, bukan waktu di mana
acara mulai dijalankan), silakan hubungi milis ns-developers.

penggunaan
Penggunaan simulator waktu nyata sangat mudah, dari perspektif skrip.
Pengguna hanya perlu mengatur atribut Tipe Implementasi Simulator ke waktu nyata
simulator, seperti berikut:

GlobalValue::Bind ("SimulatorImplementationType",
StringValue("ns3::RealtimeSimulatorImpl"));

Ada naskah di contoh/realtime/realtime-udp-echo.cc itu ada contoh caranya
mengkonfigurasi perilaku waktu nyata. Mencoba:

$ ./waf --jalankan realtime-udp-echo

Apakah simulator akan bekerja dalam upaya terbaik atau mode kebijakan batas keras diatur
oleh atribut yang dijelaskan di bagian sebelumnya.

Organisasi
Implementasinya terkandung dalam file-file berikut:

· src/core/model/realtime-simulator-impl.{cc,h}

· src/core/model/sinkronisasi jam dinding.{cc,h}

Untuk membuat penjadwal waktu nyata, ke perkiraan pertama yang hanya ingin Anda sebabkan
waktu simulasi melompat untuk mengkonsumsi waktu nyata. Kami mengusulkan melakukan ini menggunakan kombinasi dari
tidur- dan sibuk- menunggu. Sleep-wait menyebabkan proses pemanggilan (utas) menghasilkan
prosesor untuk beberapa waktu. Meskipun jumlah waktu yang ditentukan ini dapat dilewati
ke resolusi nanodetik, itu sebenarnya dikonversi ke perincian khusus OS. Di
Linux, granularity disebut Jiffy. Biasanya resolusi ini tidak cukup untuk
kebutuhan kita (dalam urutan sepuluh milidetik), jadi kita membulatkan dan tidur untuk beberapa
jumlah Jiffies yang lebih kecil. Prosesnya kemudian dibangunkan setelah jumlah yang ditentukan
Jiffie telah berlalu. Saat ini, kami memiliki sisa waktu untuk menunggu. Kali ini adalah
umumnya lebih kecil dari waktu tidur minimum, jadi kami sibuk-menunggu sisa waktu
waktu. Ini berarti bahwa utas hanya duduk dalam siklus konsumsi loop for sampai
waktu yang diinginkan tiba. Setelah kombinasi tidur-dan sibuk-menunggu, waktu nyata berlalu
(dinding) jam harus sesuai dengan waktu simulasi acara berikutnya dan simulasi
hasil.

Pembantu
Bab-bab di atas memperkenalkan Anda pada berbagai ns-3 konsep pemrograman seperti smart
pointer untuk manajemen memori yang dihitung dengan referensi, atribut, ruang nama, panggilan balik, dll.
Pengguna yang bekerja di API tingkat rendah ini dapat saling terhubung ns-3 objek dengan butiran halus.
Namun, program simulasi yang ditulis seluruhnya menggunakan API tingkat rendah akan cukup panjang
dan membosankan untuk kode. Untuk alasan ini, apa yang disebut "API pembantu" terpisah telah di-overlay
pada intinya ns-3 API. Jika Anda telah membaca ns-3 tutorial, Anda akan terbiasa
dengan API pembantu, karena ini adalah API yang biasanya pertama kali diperkenalkan kepada pengguna baru.
Dalam bab ini, kami memperkenalkan filosofi desain API pembantu dan membandingkannya dengan
API tingkat rendah. Jika Anda menjadi pengguna berat ns-3, Anda mungkin akan bergerak maju mundur
antara API ini bahkan dalam program yang sama.

API pembantu memiliki beberapa tujuan:

1. sisanya src / tidak memiliki ketergantungan pada API pembantu; apa saja yang bisa dilakukan dengan
API pembantu dapat dikodekan juga di API tingkat rendah

2. Wadah: Seringkali simulasi perlu melakukan sejumlah tindakan yang identik dengan kelompok
dari objek. API pembantu banyak menggunakan wadah dari objek serupa yang
operasi serupa atau identik dapat dilakukan.

3. API pembantu tidak umum; itu tidak berusaha untuk memaksimalkan penggunaan kembali kode. Jadi,
konstruksi pemrograman seperti polimorfisme dan templat yang mencapai penggunaan kembali kode adalah
tidak begitu lazim. Misalnya, ada pembantu CsmaNetDevice terpisah dan
Helper PointToPointNetDevice tetapi mereka tidak berasal dari basis NetDevice yang sama
kelas.

4. API pembantu biasanya bekerja dengan objek alokasi tumpukan (vs. alokasi tumpukan). Untuk
beberapa program, ns-3 pengguna mungkin tidak perlu khawatir tentang Pembuatan Objek tingkat rendah atau
penanganan Ptr; mereka dapat puas dengan wadah objek dan pembantu yang dialokasikan tumpukan
yang beroperasi pada mereka.

API pembantu benar-benar tentang membuat ns-3 program lebih mudah untuk ditulis dan dibaca, tanpa
menghilangkan kekuatan antarmuka tingkat rendah. Sisa bab ini menyediakan beberapa
contoh konvensi pemrograman API pembantu.

Membuat Plot menggunakan itu gnuplot Kelas
Ada 2 metode umum untuk membuat plot menggunakan ns-3 dan gnuplot (-
http://www.gnuplot.info):

1. Buat file kontrol gnuplot menggunakan ns-3kelas Gnuplot.

2. Buat file data gnuplot menggunakan nilai yang dihasilkan oleh ns-3.

Bagian ini tentang metode 1, yaitu tentang cara membuat plot menggunakan ns-3Gnuplot
kelas. Jika Anda tertarik dengan metode 2, lihat subbagian "Contoh Nyata" di bawah
Bagian "Melacak" di ns-3 Tutorial.

membuat Plot Menggunakan itu gnuplot Kelas
Langkah-langkah berikut harus diambil untuk membuat plot menggunakan ns-3kelas Gnuplot:

1. Ubah kode Anda sehingga menggunakan kelas Gnuplot dan fungsinya.

2. Jalankan kode Anda sehingga membuat file kontrol gnuplot.

3. Panggil gnuplot dengan nama file kontrol gnuplot.

4. Lihat file grafik yang dihasilkan di penampil grafik favorit Anda.

Lihat kode dari contoh plot yang dibahas di bawah ini untuk detail pada langkah 1.

An Example program bahwa penggunaan itu gnuplot Kelas
Contoh program yang menggunakan ns-3's Gnuplot kelas dapat ditemukan di sini:

src/stats/examples/gnuplot-example.cc

Untuk menjalankan contoh ini, lakukan hal berikut:

$ ./waf cangkang
$ cd build/debug/src/stats/contoh
$ ./gnuplot-contoh

Ini akan menghasilkan file kontrol gnuplot berikut di direktori tempat contoh
terletak:

plot-2d.plt
plot-2d-dengan-error-bars.plt
plot-3d.plt

Untuk memproses file kontrol gnuplot ini, lakukan hal berikut:

$gnuplotplot-2d.plt
$ gnuplot plot-2d-dengan-batang kesalahan.plt
$gnuplotplot-3d.plt

Ini akan menghasilkan file grafik berikut di direktori di mana contohnya adalah:
terletak:

plot-2d.png
plot-2d-dengan-error-bars.png
plot-3d.png

Anda dapat melihat file grafik ini di penampil grafik favorit Anda. Jika Anda memiliki gimp
diinstal pada mesin Anda, misalnya, Anda dapat melakukan ini:

$ gimp plot-2d.png
$ gimp plot-2d-dengan-batang kesalahan.png
$ gimp plot-3d.png

An Example 2-Dimensi Merencanakan
Plot 2 Dimensi berikut
[gambar]

dibuat menggunakan kode berikut dari gnuplot-example.cc:

menggunakan namespace std;

string fileNameWithNoExtension = "plot-2d";
string graphicsFileName = fileNameWithNoExtension + ".png";
string plotFileName = namafileDenganNoExtension + ".plt";
string plotTitle = "Plot 2-D";
string dataTitle = "Data 2-D";

// Instansiasi plot dan atur judulnya.
Plot Gnuplot (namaFilegrafis);
plot.SetTitle (plotTitle);

// Buat file grafik, yang akan dibuat file plot ketika
// digunakan dengan Gnuplot, menjadi file PNG.
plot.SetTerminal("png");

// Mengatur label untuk setiap sumbu.
plot.SetLegend("Nilai X", "Nilai Y");

// Tetapkan rentang untuk sumbu x.
plot.AppendExtra ("set xrange [-6:+6]");

// Instansiasi dataset, atur judulnya, dan buat poinnya menjadi
// diplot bersama dengan garis penghubung.
kumpulan data Gnuplot2dDataset;
kumpulan data.SetTitle (dataTitle);
kumpulan data.SetStyle (Gnuplot2dDataset::LINES_POINTS);

ganda x;
ganda y;

// Buat kumpulan data 2-D.
untuk (x = -5.0; x <= +5.0; x += 1.0)
{
// Hitung kurva 2-D
//
// 2
// kamu = x .
//
kamu = x * x;

// Tambahkan titik ini.
kumpulan data.Tambahkan (x, y);
}

// Tambahkan kumpulan data ke plot.
plot.AddDataset (set data);

// Buka file plotnya.
ofstream plotFile (plotFileName.c_str());

// Tulis file plotnya.
plot.GenerateOutput (plotFile);

// Tutup file plotnya.
plotFile.close();

An Example 2-Dimensi Merencanakan dengan error Bar
Plot 2 Dimensi berikut dengan bilah kesalahan dalam arah x dan y
[gambar]

dibuat menggunakan kode berikut dari gnuplot-example.cc:

menggunakan namespace std;

string fileNameWithNoExtension = "plot-2d-with-error-bars";
string graphicsFileName = fileNameWithNoExtension + ".png";
string plotFileName = namafileDenganNoExtension + ".plt";
string plotTitle = "Plot 2-D Dengan Bilah Kesalahan";
string dataTitle = "Data 2-D Dengan Bilah Kesalahan";

// Instansiasi plot dan atur judulnya.
Plot Gnuplot (namaFilegrafis);
plot.SetTitle (plotTitle);

// Buat file grafik, yang akan dibuat file plot ketika
// digunakan dengan Gnuplot, menjadi file PNG.
plot.SetTerminal("png");

// Mengatur label untuk setiap sumbu.
plot.SetLegend("Nilai X", "Nilai Y");

// Tetapkan rentang untuk sumbu x.
plot.AppendExtra ("set xrange [-6:+6]");

// Instansiasi dataset, atur judulnya, dan buat poinnya menjadi
// diplot tanpa garis penghubung.
kumpulan data Gnuplot2dDataset;
kumpulan data.SetTitle (dataTitle);
dataset.SetStyle (Gnuplot2dDataset::POINTS);

// Membuat kumpulan data memiliki bilah kesalahan di kedua arah x dan y.
kumpulan data.SetErrorBars (Gnuplot2dDataset::XY);

ganda x;
xErrorDelta ganda;
ganda y;
ganda yErrorDelta;

// Buat kumpulan data 2-D.
untuk (x = -5.0; x <= +5.0; x += 1.0)
{
// Hitung kurva 2-D
//
// 2
// kamu = x .
//
kamu = x * x;

// Jadikan ketidakpastian dalam arah x konstan dan buat
// ketidakpastian dalam arah y menjadi pecahan konstan dari
// nilai y.
xErrorDelta = 0.25;
yErrorDelta = 0.1 * y;

// Tambahkan titik ini dengan ketidakpastian di x dan y
// arah.
kumpulan data.Tambahkan (x, y, xErrorDelta, yErrorDelta);
}

// Tambahkan kumpulan data ke plot.
plot.AddDataset (set data);

// Buka file plotnya.
ofstream plotFile (plotFileName.c_str());

// Tulis file plotnya.
plot.GenerateOutput (plotFile);

// Tutup file plotnya.
plotFile.close();

An Example 3-Dimensi Merencanakan
Plot 3 Dimensi berikut
[gambar]

dibuat menggunakan kode berikut dari gnuplot-example.cc:

menggunakan namespace std;

string fileNameWithNoExtension = "plot-3d";
string graphicsFileName = fileNameWithNoExtension + ".png";
string plotFileName = namafileDenganNoExtension + ".plt";
string plotTitle = "Plot 3-D";
string dataTitle = "Data 3-D";

// Instansiasi plot dan atur judulnya.
Plot Gnuplot (namaFilegrafis);
plot.SetTitle (plotTitle);

// Buat file grafik, yang akan dibuat file plot ketika
// digunakan dengan Gnuplot, menjadi file PNG.
plot.SetTerminal("png");

// Putar plot 30 derajat di sekitar sumbu x dan kemudian putar
// plot 120 derajat di sekitar sumbu z baru.
plot.AppendExtra ("mengatur tampilan 30, 120, 1.0, 1.0");

// Jadikan nol untuk sumbu z berada pada bidang sumbu x dan sumbu y.
plot.AppendExtra("set ticslevel 0");

// Mengatur label untuk setiap sumbu.
plot.AppendExtra ("set xlabel 'Nilai X'");
plot.AppendExtra ("setel ylabel 'Nilai Y'");
plot.AppendExtra ("setel zlabel 'Nilai Z'");

// Tetapkan rentang untuk sumbu x dan y.
plot.AppendExtra ("set xrange [-5:+5]");
plot.AppendExtra("set yrange [-5:+5]");

// Instansiasi dataset, atur judulnya, dan buat poinnya menjadi
// dihubungkan dengan garis.
kumpulan data Gnuplot3dDataset;
kumpulan data.SetTitle (dataTitle);
dataset.SetStyle("dengan garis");

ganda x;
ganda y;
z ganda;

// Buat kumpulan data 3-D.
untuk (x = -5.0; x <= +5.0; x += 1.0)
{
untuk (y = -5.0; y <= +5.0; y += 1.0)
{
// Hitung permukaan 3-D
//
// 2 2
// z = x * kamu .
//
z = x * x * kamu * kamu;

// Tambahkan titik ini.
kumpulan data.Tambahkan (x, y, z);
}

// Baris kosong diperlukan di akhir setiap data nilai x
// menunjuk agar kisi permukaan 3-D berfungsi.
dataset.AddEmptyLine();
}

// Tambahkan kumpulan data ke plot.
plot.AddDataset (set data);

// Buka file plotnya.
ofstream plotFile (plotFileName.c_str());

// Tulis file plotnya.
plot.GenerateOutput (plotFile);

// Tutup file plotnya.
plotFile.close();

Menggunakan Ular sanca untuk Run ns-3
Binding Python memungkinkan kode C++ masuk ns-3 untuk dipanggil dari Python.

Bab ini menunjukkan cara membuat skrip Python yang dapat dijalankan ns-3 dan juga
proses membuat binding Python untuk C++ ns-3 modul.

Pengantar
Tujuan binding Python untuk ns-3 adalah dua kali lipat:

1. Izinkan programmer untuk menulis skrip simulasi lengkap dengan Python (‐
http://www.python.org);

2. Prototipe model baru (misalnya protokol routing).

Untuk saat ini, fokus utama dari binding adalah tujuan pertama, tetapi yang kedua
tujuan akhirnya akan didukung juga. Binding python untuk ns-3 sedang dikembangkan
menggunakan alat baru bernama PyBindGen (http://code.google.com/p/pybindgen).

An Example Ular sanca Naskah bahwa Berjalan ns-3
Berikut adalah beberapa contoh kode yang ditulis dengan Python dan berjalan ns-3, yang tertulis
dalam C++. Contoh Python ini dapat ditemukan di contoh/tutorial/pertama.py:

impor ns.aplikasi
impor ns.core
impor ns.internet
impor ns.network
impor ns.point_to_point

ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO)
ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO)

node = ns.network.NodeContainer()
node.Buat(2)

pointToPoint = ns.point_to_point.PointToPointHelper()
pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps"))
pointToPoint.SetChannelAttribute("Delay", ns.core.StringValue("2ms"))

perangkat = pointToPoint.Install(node)

tumpukan = ns.internet.InternetStackHelper()
tumpukan.Instal (node)

alamat = ns.internet.Ipv4AddressHelper()
alamat.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0"))

interfaces = address.Assign (perangkat);

server gema = ns.applications.UdpEchoServerHelper(9)

serverApps = echoServer.Instal(node.Dapatkan(1))
serverApps.Mulai(ns.core.Detik(1.0))
serverApps.Stop(ns.core.Seconds(10.0))

echoClient = ns.aplikasi.UdpEchoClientHelper(antarmuka.GetAddress(1), 9)
echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(1))
echoClient.SetAttribute("Interval", ns.core.TimeValue(ns.core.Seconds (1.0)))
echoClient.SetAttribute("Ukuran Paket", ns.core.UintegerValue(1024))

clientApps = echoClient.Instal(node.Dapatkan(0))
clientApps.Mulai(ns.core.Seconds(2.0))
clientApps.Stop(ns.core.Seconds(10.0))

ns.core.Simulator.Jalankan()
ns.core.Simulator.Hancurkan()

Running Ular sanca Script
waf berisi beberapa opsi yang secara otomatis memperbarui jalur python untuk menemukan ns3
modul. Untuk menjalankan program contoh, ada dua cara menggunakan waf untuk menangani ini. Satu
adalah menjalankan shell waf; misalnya:

$ ./waf --kulit
$ contoh python/nirkabel/campuran-nirkabel.py

dan yang lainnya adalah menggunakan opsi --pyrun untuk waf:

$ ./waf --pyrun contoh/nirkabel/campuran-nirkabel.py

Untuk menjalankan skrip python di bawah debugger C:

$ ./waf --kulit
$ gdb --args python contoh/nirkabel/campuran-nirkabel.py

Untuk menjalankan skrip Python Anda sendiri yang memanggil ns-3 dan yang memiliki jalan ini,
/path/ke/your/example/my-script.py, lakukan hal berikut:

$ ./waf --kulit
$ python /path/ke/Anda/contoh/skrip-saya.py

Peringatan
Binding python untuk ns-3 adalah pekerjaan yang sedang berlangsung, dan beberapa batasan diketahui oleh
pengembang. Beberapa batasan ini (tidak semua) tercantum di sini.

Tidak lengkap Liputan
Pertama-tama, perlu diingat bahwa tidak 100% API didukung dengan Python. Beberapa dari
alasannya adalah:

1. beberapa API melibatkan pointer, yang membutuhkan pengetahuan tentang jenis memori apa
melewati semantik (siapa yang memiliki memori apa). Pengetahuan seperti itu bukan bagian dari fungsi
tanda tangan, dan didokumentasikan atau kadang-kadang bahkan tidak didokumentasikan. Anotasi adalah
diperlukan untuk mengikat fungsi-fungsi tersebut;

2. Terkadang tipe data fundamental yang tidak biasa atau konstruk C++ digunakan yang belum
didukung oleh PyBindGen;

3. GCC-XML tidak melaporkan kelas berbasis template kecuali jika dibuat instance-nya.

Sebagian besar API yang hilang dapat dibungkus, dengan waktu, kesabaran, dan keahlian yang cukup, dan
kemungkinan akan dibungkus jika laporan bug dikirimkan. Namun, jangan mengajukan laporan bug
mengatakan "pengikatan tidak lengkap", karena kami tidak memiliki tenaga untuk menyelesaikan 100% dari
ikatan.

Konversi Konstruktor
Konversi konstruktor belum sepenuhnya didukung oleh PyBindGen, dan mereka selalu bertindak sebagai
konstruktor eksplisit saat menerjemahkan API ke Python. Misalnya, di C++ Anda dapat melakukan
ini:

Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase ("192.168.0.0", "255.255.255.0");
ipAddrs.Assign (perangkat tulang punggung);

Dengan Python, untuk saat ini Anda harus melakukan:

ipAddrs = ns3.Ipv4AddressHelper()
ipAddrs.SetBase(ns3.Ipv4Address("192.168.0.0"), ns3.Ipv4Mask("255.255.255.0"))
ipAddrs.Assign(Perangkat tulang punggung)

Garis komando
Baris Perintah::TambahkanNilai() bekerja secara berbeda di Python daripada di ns-3. Dengan Python,
parameter pertama adalah string yang mewakili nama opsi baris perintah. Ketika pilihan
diatur, atribut dengan nama yang sama dengan nama opsi diatur pada Garis komando()
obyek. Contoh:

NUM_NODES_SIDE_DEFAULT = 3

cmd = ns3.CommandLine()

cmd.NumNodesSide = Tidak Ada
cmd.AddValue("NumNodesSide", "Jumlah simpul sisi kisi (jumlah total simpul akan menjadi bilangan kuadrat ini)")

cmd.Parse(argv)

[...]

jika cmd.NumNodesSide Tidak Ada:
num_nodes_side = NUM_NODES_SIDE_DEFAULT
lain:
num_nodes_side = int(cmd.NumNodesSide)

jiplakan
Pelacakan berbasis panggilan balik belum didukung dengan benar untuk Python, seperti baru ns-3 API perlu
disediakan untuk ini untuk didukung.

Penulisan file Pcap didukung melalui API normal.

Pelacakan Ascii didukung sejak ns-3.4 melalui C++ API normal yang diterjemahkan ke Python.
Namun, penelusuran ascii membutuhkan pembuatan objek ostream untuk masuk ke ascii
metode penelusuran. Dengan Python, C++ std::ofstream telah dibungkus minimal untuk memungkinkan
ini. Sebagai contoh:

ascii = ns3.ofstream("wifi-ap.tr") # buat file
ns3.YansWifiPhyHelper.EnableAsciiAll(ascii)
ns3.Simulator.Jalankan()
ns3.Simulator.Hancurkan()
ascii.close() # tutup file

Ada satu peringatan: Anda tidak boleh membiarkan objek file menjadi sampah yang dikumpulkan saat ns-3
masih menggunakannya. Artinya variabel 'ascii' di atas tidak boleh dibiarkan
keluar dari ruang lingkup atau program akan macet.

Cygwin pembatasan
Binding python tidak berfungsi di Cygwin. Ini karena bug gccxml.

Anda mungkin lolos dengan memindai ulang definisi API dari dalam cygwin
lingkungan (./waf --python-scan). Namun solusi yang paling mungkin mungkin harus
adalah bahwa kami menonaktifkan ikatan python di CygWin.

Jika Anda benar-benar peduli dengan binding Python di Windows, coba buat dengan mingw dan native
python sebagai gantinya. Atau, untuk membangun tanpa ikatan python, nonaktifkan ikatan python di
tahap konfigurasi:

$ ./waf konfigurasikan --disable-python

Kerja dengan Ular sanca Bindings
Saat ini ada dua jenis binding Python di ns-3:

1. Binding monolitik berisi definisi API untuk semua modul dan dapat ditemukan di
satu direktori, binding/python.

2. Binding modular berisi definisi API untuk satu modul dan dapat ditemukan di masing-masing
modul bindings direktori.

Ular sanca Bindings Workflow
Proses penanganan binding Python adalah sebagai berikut:

1. Secara berkala pengembang menggunakan GCC-XML (http://www.gccxml.org) pemindaian API berbasis
skrip, yang menyimpan definisi API yang dipindai sebagai binding/python/ns3_module_*.py arsip
atau sebagai file Python di setiap modul ' bindings direktori. File-file ini disimpan di bawah
kontrol versi di utama ns-3 gudang;

2. Pengembang lain mengkloning repositori dan menggunakan definisi API yang sudah dipindai;

3. Saat mengonfigurasi ns-3, pybindgen akan diunduh secara otomatis jika belum
diinstal. Dilepaskan ns-3 tarballs akan mengirimkan salinan pybindgen.

Jika ada yang salah dengan kompilasi binding Python dan Anda hanya ingin mengabaikannya
dan lanjutkan dengan C++, Anda dapat menonaktifkan Python dengan:

$ ./waf --disable-python

petunjuk untuk Penanganan New File or Berubah API
Jadi Anda telah mengubah yang ada ns-3 API dan binding Python tidak lagi dikompilasi? Mengerjakan
tidak putus asa, Anda dapat memindai ulang ikatan untuk membuat ikatan baru yang mencerminkan perubahan
ke ns-3 API.

Tergantung pada apakah Anda menggunakan binding monolitik atau modular, lihat diskusi di bawah ini untuk
pelajari cara memindai ulang binding Python Anda.

Monolitis Ular sanca Bindings
Scanning itu Monolitis Ular sanca Bindings
Untuk memindai binding Python monolitik lakukan hal berikut:

$ ./waf --python-scan

Organisasi of itu Monolitis Ular sanca Bindings
Definisi API Python monolitik diatur sebagai berikut. Untuk setiap ns-3 modul
, berkas binding/python/ns3_module_ .py menjelaskan API-nya. Masing-masing
file memiliki 3 fungsi tingkat atas:

1. def register_types(modul)(): fungsi ini menangani pendaftaran tipe baru (mis
kelas C++, enums) yang didefinisikan dalam modul tha;

2. def daftar_metode(modul)(): fungsi ini memanggil, untuk setiap kelas , lain
fungsi register_methods_Ns3 (modul). Fungsi terakhir ini menambahkan metode
definisi untuk setiap kelas;

3. def register_fungsi(modul)(): fungsi ini mendaftar ns-3 fungsi yang dimiliki
modul itu.

Modular Ular sanca Bindings
Ringkasan
Sejak ns 3.11, ikatan modular ditambahkan, secara paralel dengan monolitik lama
ikatan.

Binding python baru dibuat menjadi namespace 'ns', bukan 'ns3' untuk yang lama
ikatan. Contoh:

dari ns.network import Node
n1 = Simpul()

Dengan binding Python modular:

1. Ada satu modul ekstensi Python terpisah untuk masing-masing ns-3 modul;

2. Pemindaian definisi API (apidefs) dilakukan pada basis per ns-modul;

3. Setiap file apidefs modul disimpan dalam subdirektori 'bindings' dari modul
direktori;

Scanning itu Modular Ular sanca Bindings
Untuk memindai binding Python modular untuk modul inti, misalnya, lakukan hal berikut:

$ ./waf --apiscan=inti

Untuk memindai binding Python modular untuk semua modul, lakukan hal berikut:

$ ./waf --apiscan=semua

membuat a New Modul
Jika Anda menambahkan modul baru, binding Python akan terus dikompilasi tetapi tidak akan
menutupi modul baru.

Untuk menutupi modul baru, Anda harus membuat binding/python/ns3_module_ .py file,
mirip dengan apa yang dijelaskan di bagian sebelumnya, dan mendaftarkannya di variabel
LOKAL_MODULES() in binding/python/ns3modulegen.py

Menambahkan Modular Bindings Untuk A yang ada Modul
Untuk menambahkan dukungan untuk binding modular ke yang sudah ada ns-3 modul, cukup tambahkan berikut ini
baris ke fungsi wscript build():

bld.ns3_python_bindings()

Organisasi of itu Modular Ular sanca Bindings
src/ /binding direktori mungkin berisi file-file berikut, beberapa di antaranya
pilihan:

· callbacks_list.py: ini adalah file yang dipindai, JANGAN SENTUH. Berisi daftar
Callback<...> contoh template ditemukan di header yang dipindai;

· modulegen__gcc_LP64.py: ini adalah file yang dipindai, JANGAN SENTUH. Definisi API yang dipindai
untuk GCC, arsitektur LP64 (64-bit)

· modulegen__gcc_ILP32.py: ini adalah file yang dipindai, JANGAN SENTUH. Definisi API yang dipindai
untuk GCC, arsitektur ILP32 (32-bit)

· modulegen_customizations.py: Anda dapat menambahkan file ini secara opsional untuk menyesuaikan
pembuatan kode pybindgen

· pindai-header.h: Anda dapat menambahkan file ini secara opsional untuk menyesuaikan file header yang dipindai
untuk modul. Pada dasarnya file ini dipindai alih-alih ns3/ -modul.h.
Biasanya, pernyataan pertama adalah #include "ns3/ -modul.h", ditambah beberapa lainnya
hal-hal untuk memaksa instantiasi template;

· module_helpers.cc: Anda dapat menambahkan file tambahan, seperti ini, untuk ditautkan ke python
modul ekstensi, tetapi mereka harus terdaftar di wscript. Melihat
src/core/wscript untuk contoh bagaimana melakukannya;

· .py: jika file ini ada, itu menjadi modul python "frontend" untuk ns3
modul, dan modul ekstensi (.so file) menjadi _ .jadi bukannya .jadi.
Itu File .py harus mengimpor semua simbol dari modul _ (ini lebih
rumit daripada kedengarannya, lihat src/core/bindings/core.py untuk contoh), dan kemudian dapat menambahkan
beberapa definisi python murni tambahan.

More Informasi untuk Pengembang
Jika Anda seorang pengembang dan membutuhkan informasi lebih lanjut tentang ns-3binding Python, silakan lihat
Ular sanca Bindings wiki halaman.

Tes
Ringkasan
Dokumen ini berkaitan dengan pengujian dan validasi dari ns-3 perangkat lunak.

Dokumen ini menyediakan

· latar belakang tentang terminologi dan pengujian perangkat lunak (Bab 2);

· deskripsi kerangka pengujian ns-3 (Bab 3);

· panduan untuk pengembang model atau kontributor model baru tentang cara menulis tes (Bab
4);

Singkatnya, tiga bab pertama harus dibaca oleh pengembang dan kontributor ns yang
perlu memahami cara menyumbangkan kode pengujian dan program yang divalidasi, dan sisanya
dokumen menyediakan ruang bagi orang untuk melaporkan aspek apa dari model yang dipilih
telah divalidasi.

Latar Belakang
Kredensial mikro bab mungkin be dilewati by pembaca akrab dengan itu dasar-dasar of perangkat lunak pengujian.

Menulis perangkat lunak bebas cacat adalah proposisi yang sulit. Ada banyak dimensi untuk
masalah dan ada banyak kebingungan mengenai apa yang dimaksud dengan istilah yang berbeda dalam
konteks yang berbeda. Kami merasa perlu meluangkan sedikit waktu untuk meninjau
subjek dan mendefinisikan beberapa istilah.

Pengujian perangkat lunak dapat secara longgar didefinisikan sebagai proses mengeksekusi program dengan
maksud untuk menemukan kesalahan. Ketika seseorang memasuki diskusi tentang pengujian perangkat lunak, itu
dengan cepat menjadi jelas bahwa ada banyak pola pikir berbeda yang dapat digunakan seseorang
mendekati subjek.

Misalnya, seseorang dapat memecah proses menjadi kategori fungsional yang luas seperti
''pengujian kebenaran,'' ''pengujian kinerja,'' ''pengujian kekokohan'' dan ''keamanan
pengujian.'' Cara lain untuk melihat masalah adalah dengan siklus hidup: ''pengujian persyaratan,''
''pengujian desain,'' ''pengujian penerimaan,'' dan ''pengujian pemeliharaan.'' Namun pandangan lain
adalah dengan ruang lingkup sistem yang diuji. Dalam hal ini seseorang dapat berbicara tentang ''pengujian unit,''
''pengujian komponen,'' ''pengujian integrasi,'' dan ''pengujian sistem.'' Istilah-istilah ini adalah
juga tidak distandarisasi dengan cara apa pun, dan karenanya ''pengujian pemeliharaan'' dan ''regresi
pengujian'' mungkin terdengar bergantian. Selain itu, istilah ini sering disalahgunakan.

Ada juga sejumlah pendekatan filosofis yang berbeda untuk pengujian perangkat lunak. Untuk
contoh, beberapa organisasi menganjurkan program tes menulis sebelum benar-benar mengimplementasikannya
perangkat lunak yang diinginkan, menghasilkan ''pengembangan yang digerakkan oleh tes.'' Beberapa organisasi menganjurkan
pengujian dari perspektif pelanggan sesegera mungkin, mengikuti paralel dengan
proses pengembangan tangkas: ''menguji lebih awal dan sering menguji.'' Ini kadang-kadang disebut
''pengujian tangkas.'' Tampaknya setidaknya ada satu pendekatan untuk pengujian untuk setiap
metodologi pembangunan.

ns-3 proyek tidak dalam bisnis mengadvokasi salah satu dari proses ini, tetapi
proyek secara keseluruhan memiliki persyaratan yang membantu menginformasikan proses pengujian.

Seperti semua produk perangkat lunak utama, ns-3 memiliki sejumlah kualitas yang harus ada untuk
produk untuk berhasil. Dari perspektif pengujian, beberapa kualitas ini yang harus
ditujukan adalah bahwa ns-3 harus ''benar,'' ''kuat,'' ''berperforma'' dan
''dapat dipertahankan.'' Idealnya harus ada metrik untuk masing-masing dimensi ini yang
diperiksa oleh tes untuk mengidentifikasi ketika produk gagal memenuhi harapannya /
persyaratan.

Kebenaran
Tujuan penting dari pengujian adalah untuk menentukan bahwa perangkat lunak berperilaku
''benar.'' Untuk ns-3 ini berarti bahwa jika kita mensimulasikan sesuatu, simulasi harus
dengan tepat mewakili beberapa entitas fisik atau proses dengan akurasi tertentu dan
presisi.

Ternyata ada dua perspektif dari mana seseorang dapat melihat kebenaran.
Memverifikasi bahwa model tertentu diimplementasikan sesuai dengan spesifikasinya adalah
secara umum disebut verifikasi. Proses memutuskan bahwa model tersebut benar untuk
tujuan penggunaannya secara umum disebut pengesahan.

Pengesahan dan Verifikasi
Model komputer adalah representasi matematis atau logis dari sesuatu. Bisa
mewakili kendaraan, gajah (lihat David Harel's berbicara tentang pemodelan an gajah at
SIMUtools 2009, atau kartu jaringan. Model juga dapat mewakili proses seperti global
pemanasan, arus lalu lintas jalan bebas hambatan atau spesifikasi protokol jaringan. Model bisa
representasi yang benar-benar setia dari spesifikasi proses logis, tetapi mereka
tentu tidak pernah dapat sepenuhnya mensimulasikan objek atau proses fisik. Dalam kebanyakan kasus,
sejumlah penyederhanaan dibuat pada model untuk membuat simulasi secara komputasi
penurut.

Setiap model memiliki target sistem bahwa ia mencoba untuk mensimulasikan. Langkah pertama dalam
membuat model simulasi adalah mengidentifikasi sistem target ini dan tingkat detailnya dan
akurasi simulasi yang diinginkan untuk direproduksi. Dalam kasus proses logis,
sistem target dapat diidentifikasi sebagai ''TCP seperti yang didefinisikan oleh RFC 793.'' Dalam hal ini, itu
mungkin akan diinginkan untuk membuat model yang sepenuhnya dan setia mereproduksi RFC
793. Dalam hal proses fisik hal ini tidak mungkin. Jika, misalnya, Anda
ingin mensimulasikan kartu jaringan nirkabel, Anda dapat menentukan yang Anda butuhkan, ''an
implementasi level MAC yang akurat dari spesifikasi 802.11 dan [...] yang tidak terlalu lambat
Model tingkat PHY dari spesifikasi 802.11a.''

Setelah ini selesai, seseorang dapat mengembangkan model abstrak dari sistem target. Ini adalah
biasanya merupakan latihan dalam mengelola pertukaran antara kompleksitas, kebutuhan sumber daya
dan akurasi. Proses mengembangkan model abstrak disebut model
kualifikasi di dalam literatur. Dalam kasus protokol TCP, proses ini menghasilkan a
desain untuk kumpulan objek, interaksi, dan perilaku yang akan sepenuhnya diimplementasikan
RFC 793 inci ns-3. Dalam kasus kartu nirkabel, proses ini menghasilkan sejumlah:
pengorbanan untuk memungkinkan lapisan fisik disimulasikan dan desain perangkat jaringan
dan saluran untuk ns-3, bersama dengan objek, interaksi, dan perilaku yang diinginkan.

Model abstrak ini kemudian dikembangkan menjadi sebuah ns-3 model yang mengimplementasikan abstrak
model sebagai program komputer. Proses mendapatkan implementasi untuk setuju dengan
model abstrak disebut model verifikasi di dalam literatur.

Proses sejauh ini adalah loop terbuka. Yang tersisa adalah membuat penentuan bahwa ns-3 yang diberikan
model memiliki beberapa koneksi ke beberapa realitas -- bahwa model adalah representasi akurat dari
sistem nyata, apakah proses logis atau entitas fisik.

Jika seseorang akan menggunakan model simulasi untuk mencoba dan memprediksi bagaimana beberapa sistem nyata berjalan
untuk berperilaku, harus ada alasan untuk memercayai hasil Anda -- yaitu, dapatkah seseorang memercayai itu
inferensi yang dibuat dari model diterjemahkan ke dalam prediksi yang benar untuk sistem nyata.
Proses mendapatkan perilaku model ns-3 agar sesuai dengan sistem target yang diinginkan
perilaku seperti yang didefinisikan oleh proses kualifikasi model disebut model pengesahan dalam
literatur. Dalam hal implementasi TCP, Anda mungkin ingin membandingkan perilaku dari
model TCP ns-3 Anda ke beberapa implementasi referensi untuk memvalidasi model Anda. Di
kasus simulasi lapisan fisik nirkabel, Anda mungkin ingin membandingkan perilaku
model Anda dengan perangkat keras nyata dalam pengaturan terkontrol,

ns-3 lingkungan pengujian menyediakan alat untuk memungkinkan validasi model dan
pengujian, dan mendorong publikasi hasil validasi.

Kekokohan
Kekokohan adalah kualitas kemampuan untuk menahan tekanan, atau perubahan lingkungan,
input atau perhitungan, dll. Sebuah sistem atau desain "kuat" jika dapat menangani hal tersebut
perubahan dengan hilangnya fungsionalitas minimal.

Pengujian semacam ini biasanya dilakukan dengan fokus tertentu. Misalnya, sistem sebagai
keseluruhan dapat dijalankan pada banyak konfigurasi sistem yang berbeda untuk menunjukkan bahwa itu dapat
melakukan dengan benar di sejumlah besar lingkungan.

Sistem juga dapat ditekankan dengan beroperasi mendekati atau melampaui kapasitas dengan menghasilkan
atau simulasi kelelahan sumber daya dari berbagai jenis. Genre pengujian ini disebut
''uji stres.''

Sistem dan komponennya mungkin terkena apa yang disebut ''tes bersih'' yang menunjukkan
hasil positif -- yaitu sistem beroperasi dengan benar sebagai respons terhadap
variasi konfigurasi yang diharapkan.

Sistem dan komponennya juga dapat terkena ''tes kotor'' yang memberikan masukan
di luar kisaran yang diharapkan. Misalnya, jika sebuah modul mengharapkan string yang diakhiri nol
representasi bilangan bulat, tes kotor mungkin memberikan string acak yang tidak diakhiri
karakter untuk memverifikasi bahwa sistem tidak macet sebagai akibat dari input yang tidak diharapkan ini.
Sayangnya, mendeteksi input "kotor" seperti itu dan mengambil tindakan pencegahan untuk memastikan
sistem tidak gagal secara serempak dapat membutuhkan biaya pengembangan yang sangat besar.
Untuk mengurangi waktu pengembangan, keputusan diambil di awal proyek untuk
meminimalkan jumlah validasi parameter dan penanganan kesalahan di ns-3 basis kode. Untuk
alasan ini, kami tidak menghabiskan banyak waktu untuk pengujian kotor -- itu hanya akan mengungkap
hasil keputusan desain yang kami tahu kami ambil.

Kami ingin menunjukkan itu ns-3 perangkat lunak tidak bekerja di beberapa set kondisi. Kita
meminjam beberapa definisi untuk mempersempit ini sedikit. Itu domain of penerapan is
satu set kondisi yang ditentukan untuk model yang telah diuji, dibandingkan dengan
realitas sejauh mungkin, dan dinilai layak untuk digunakan. Itu jarak of ketepatan adalah
kesepakatan antara model komputerisasi dan realitas dalam domain penerapan.

ns-3 lingkungan pengujian menyediakan alat untuk memungkinkan pengaturan dan menjalankan pengujian
lingkungan melalui beberapa sistem (buildbot) dan menyediakan kelas untuk mendorong clean
tes untuk memverifikasi pengoperasian sistem di atas ''domain penerapan'' yang diharapkan
dan ''rentang akurasi.''

pemain
Oke, ''performant'' bukanlah kata bahasa Inggris yang sebenarnya. Namun, ini adalah neologisme yang sangat ringkas
yang cukup sering digunakan untuk menggambarkan apa yang kita inginkan ns-3 menjadi: kuat dan cukup cepat untuk
menyelesaikan pekerjaan.

Ini benar-benar tentang subjek yang luas dari pengujian kinerja perangkat lunak. Salah satu kuncinya
hal yang dilakukan adalah membandingkan dua sistem untuk menemukan mana yang berkinerja lebih baik (lih
tolak ukur). Ini digunakan untuk menunjukkan bahwa, misalnya, ns-3 dapat melakukan jenis dasar
simulasi setidaknya secepat alat yang bersaing, atau dapat digunakan untuk mengidentifikasi bagian-bagian dari
sistem yang berkinerja buruk.

Dalam majalah ns-3 kerangka pengujian, kami menyediakan dukungan untuk mengatur waktu berbagai jenis pengujian.

Maintainability
Produk perangkat lunak harus dapat dipelihara. Sekali lagi, ini adalah pernyataan yang sangat luas, tetapi a
kerangka pengujian dapat membantu tugas tersebut. Setelah model dikembangkan, divalidasi dan
diverifikasi, kami dapat berulang kali menjalankan rangkaian tes untuk seluruh sistem untuk memastikan
bahwa itu tetap valid dan diverifikasi selama masa pakainya.

Ketika fitur berhenti berfungsi sebagaimana dimaksud setelah beberapa jenis perubahan pada sistem adalah
terintegrasi, secara umum disebut a regresi. Awalnya istilah regresi
merujuk pada perubahan yang menyebabkan bug yang sebelumnya diperbaiki muncul kembali, tetapi istilah tersebut telah
berevolusi untuk menggambarkan segala jenis perubahan yang merusak fungsionalitas yang ada. Ada banyak
jenis regresi yang mungkin terjadi dalam praktek.

A lokal regresi adalah salah satu di mana perubahan mempengaruhi komponen yang diubah secara langsung. Untuk
contoh, jika suatu komponen dimodifikasi untuk mengalokasikan dan mengosongkan memori tetapi pointer basi adalah
digunakan, komponen itu sendiri gagal.

A terpencil regresi adalah salah satu di mana perubahan pada satu komponen merusak fungsionalitas di
komponen lain. Ini mencerminkan pelanggaran tersirat tetapi mungkin tidak diakui
kontrak antar komponen.

An membuka kedok regresi adalah salah satu yang menciptakan situasi di mana bug yang sudah ada sebelumnya
yang tidak berpengaruh tiba-tiba terekspos dalam sistem. Ini mungkin sesederhana berolahraga
jalur kode untuk pertama kalinya.

A prestasi regresi adalah salah satu yang menyebabkan persyaratan kinerja sistem untuk
dilanggar. Misalnya, melakukan beberapa pekerjaan dalam fungsi tingkat rendah yang dapat diulang
sejumlah besar kali mungkin tiba-tiba membuat sistem tidak dapat digunakan dari perspektif tertentu.

ns-3 kerangka pengujian menyediakan alat untuk mengotomatisasi proses yang digunakan untuk memvalidasi dan
verifikasi kode dalam rangkaian pengujian malam untuk membantu mengidentifikasi kemungkinan regresi dengan cepat.

pengujian kerangka
ns-3 terdiri dari mesin inti simulasi, satu set model, program contoh, dan tes.
Seiring waktu, kontributor baru menyumbangkan model, pengujian, dan contoh. Program uji Python
tes.py berfungsi sebagai manajer pelaksanaan tes; tes.py dapat menjalankan kode uji dan contoh untuk
mencari regresi, dapat menampilkan hasilnya ke dalam beberapa bentuk, dan dapat mengelola kode
alat analisis cakupan. Di atas ini, kami melapisi Buildbot yang merupakan pembuatan otomatis
robot yang melakukan pengujian ketahanan dengan menjalankan kerangka pengujian pada sistem yang berbeda
dan dengan opsi konfigurasi yang berbeda.

BuildBot
Pada pengujian ns-3 level tertinggi adalah buildbots (robot build). Jika Anda
tidak terbiasa dengan sistem ini lihat http://djmitche.github.com/buildbot/docs/0.7.11/.
Ini adalah sistem otomatis sumber terbuka yang memungkinkan ns-3 untuk dibangun kembali dan diuji masing-masing
waktu sesuatu telah berubah. Dengan menjalankan buildbot pada sejumlah sistem yang berbeda, kami
dapat memastikan bahwa ns-3 membangun dan mengeksekusi dengan benar pada semua sistem yang didukungnya.

Pengguna (dan pengembang) biasanya tidak akan berinteraksi dengan sistem buildbot selain untuk
membaca pesannya tentang hasil tes. Jika kegagalan terdeteksi di salah satu
membangun dan menguji pekerjaan otomatis, buildbot akan mengirim email ke ns-developer
milis. Email ini akan terlihat seperti

Di URL detail lengkap yang ditampilkan di email, seseorang dapat mencari kata kunci gagal dan
pilih tempat tinggal tautan untuk langkah yang sesuai untuk melihat alasan kegagalan.

Buildbot akan melakukan tugasnya dengan tenang jika tidak ada kesalahan, dan sistem akan mengalami
membangun dan menguji siklus setiap hari untuk memverifikasi bahwa semuanya baik-baik saja.

Tes.py
Buildbot menggunakan program Python, tes.py, yang bertanggung jawab untuk menjalankan semua
menguji dan mengumpulkan laporan yang dihasilkan ke dalam bentuk yang dapat dibaca manusia. Program ini adalah
juga tersedia untuk digunakan oleh pengguna dan pengembang juga.

tes.py sangat fleksibel dalam memungkinkan pengguna untuk menentukan jumlah dan jenis tes untuk
Lari; dan juga jumlah dan jenis output yang akan dihasilkan.

Sebelum berlari tes.py, pastikan bahwa contoh dan pengujian ns3 telah dibuat dengan melakukan
pengikut

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

Secara default, tes.py akan menjalankan semua tes yang tersedia dan melaporkan status kembali dengan sangat ringkas
membentuk. Menjalankan perintah

$ ./test.py

akan menghasilkan sejumlah LULUS, GAGAL, JATUH or MELEWATKAN indikasi diikuti oleh jenis
tes yang dijalankan dan nama tampilannya.

Waf: Masuk ke direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Keluar dari direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'build' berhasil diselesaikan (0.939 detik)
GAGAL: TestSuite ns3-wifi-propagation-loss-models
LULUS: Layanan nama objek TestSuite
LULUS: TestSuite pcap-file-object
LULUS: TestSuite ns3-tcp-cwnd
...
LULUS: TestSuite ns3-tcp-interoperabilitas
LULUS: Contoh csma-broadcast
LULUS: Contoh csma-multicast

Mode ini dimaksudkan untuk digunakan oleh pengguna yang tertarik untuk menentukan apakah mereka
distribusi bekerja dengan benar, dan oleh pengembang yang tertarik untuk menentukan apakah
perubahan yang mereka buat telah menyebabkan kemunduran.

Ada sejumlah opsi yang tersedia untuk mengontrol perilaku tes.py. jika kamu lari
tes.py --membantu anda akan melihat ringkasan perintah seperti:

Penggunaan: test.py [opsi]

Pilihan:
-h, --help tampilkan pesan bantuan ini dan keluar
-b BUILDPATH, --buildpath=BUILDPATH
tentukan jalur di mana ns-3 dibangun (default ke
membangun direktori untuk varian saat ini)
-c JENIS, --constrain=JENIS
membatasi pelari tes dengan jenis tes
-e CONTOH, --example=CONTOH
tentukan satu contoh untuk dijalankan (tidak ada jalur relatif
dibutuhkan)
-g, --grind menjalankan rangkaian pengujian dan contoh menggunakan valgrind
-k, --kinds mencetak jenis tes yang tersedia
-l, --list mencetak daftar tes yang diketahui
-m, --multiple melaporkan beberapa kegagalan dari rangkaian pengujian dan pengujian
kasus
-n, --nowaf jangan jalankan waf sebelum memulai pengujian
-p PYEXAMPLE, --pyexample=PYEXAMPLE
tentukan satu contoh python untuk dijalankan (dengan relative
jalan)
-r, --retain menyimpan semua file sementara (yang biasanya
dihapus)
-S TEST-SUITE, --suite=TEST-SUITE
tentukan satu test suite untuk dijalankan
-t FILE-TEKS, --text=FILE-TEKS
tulis hasil tes terperinci ke dalam TEXT-FILE.txt
-v, --progres pencetakan verbose dan pesan informasi
-w HTML-FILE, --web=HTML-FILE, --html=HTML-FILE
tulis hasil tes terperinci ke dalam HTML-FILE.html
-x FILE XML, --xml=FILE XML
tulis hasil tes terperinci ke dalam XML-FILE.xml

Jika seseorang menentukan gaya keluaran opsional, seseorang dapat menghasilkan deskripsi rinci tentang
tes dan status. Gaya yang tersedia adalah: teks dan HTML. Buildbots akan memilih HTML
opsi untuk menghasilkan laporan pengujian HTML untuk build malam menggunakan

$ ./test.py --html=nightly.html

Dalam hal ini, file HTML bernama ''nightly.html'' akan dibuat dengan ringkasan yang cantik
dari pengujian yang dilakukan. Format ''yang dapat dibaca manusia'' tersedia untuk pengguna yang tertarik dengan
rincian.

$ ./test.py --text=hasil.txt

Pada contoh di atas, test suite memeriksa ns-3 kehilangan propagasi perangkat nirkabel
model gagal. Secara default tidak ada informasi lebih lanjut yang diberikan.

Untuk lebih mendalami kegagalan tersebut, tes.py memungkinkan satu test suite untuk ditentukan.
Menjalankan perintah

$ ./test.py --suite=ns3-wifi-propagation-loss-models

atau setara

$ ./test.py -s ns3-wifi-propagation-loss-models

menghasilkan rangkaian pengujian tunggal yang dijalankan.

GAGAL: TestSuite ns3-wifi-propagation-loss-models

Untuk menemukan informasi rinci mengenai kegagalan, seseorang harus menentukan jenis output
diinginkan. Misalnya, kebanyakan orang mungkin akan tertarik dengan file teks:

$ ./test.py --suite=ns3-wifi-propagation-loss-models --text=results.txt

Ini akan menghasilkan rangkaian pengujian tunggal yang dijalankan dengan status pengujian yang ditulis ke
file ''results.txt''.

Anda harus menemukan sesuatu yang mirip dengan yang berikut di file itu

GAGAL: Test Suite ''ns3-wifi-propagation-loss-models'' (pengguna nyata 0.02 sistem 0.01 sistem 0.00)
LULUS: Uji Kasus "Periksa ... Friis ... model ..." (pengguna 0.01 nyata 0.00 sistem 0.00)
GAGAL: Uji Kasus "Periksa ... Jarak Log ... model" (pengguna 0.01 nyata 0.01 sistem 0.00)
rincian:
Pesan: Mendapat nilai SNR yang tidak terduga
Kondisi: [deskripsi panjang tentang apa yang sebenarnya gagal]
Sebenarnya: 176.395
Batas: 176.407 +- 0.0005
Berkas: ../src/test/ns3wifi/propagation-loss-models-test-suite.cc
Line: 360

Perhatikan bahwa Test Suite terdiri dari dua Test Case. Kasus uji pertama memeriksa
Model kerugian propagasi Friis dan lulus. Kasus uji kedua gagal memeriksa Log
Model propagasi jarak. Dalam hal ini, SNR 176.395 ditemukan, dan tes
diharapkan nilai 176.407 benar untuk tiga tempat desimal. File yang diimplementasikan
tes gagal terdaftar serta baris kode yang memicu kegagalan.

Jika diinginkan, Anda dapat dengan mudah menulis file HTML menggunakan --html Option
seperti dijelaskan di atas.

Biasanya pengguna akan menjalankan semua tes setidaknya sekali setelah mengunduh ns-3 untuk memastikan bahwa
lingkungannya telah dibangun dengan benar dan menghasilkan hasil yang benar
sesuai dengan test suite. Pengembang biasanya akan menjalankan rangkaian pengujian sebelum dan
setelah membuat perubahan untuk memastikan bahwa mereka tidak memperkenalkan regresi dengan
perubahan. Dalam hal ini, pengembang mungkin tidak ingin menjalankan semua pengujian, tetapi hanya sebagian. Untuk
contoh, pengembang mungkin hanya ingin menjalankan unit test secara berkala sambil membuat
perubahan ke repositori. Pada kasus ini, tes.py dapat diberitahu untuk membatasi jenis
tes yang dijalankan ke kelas tes tertentu. Perintah berikut hanya akan menghasilkan
unit test yang sedang dijalankan:

$ ./test.py --constrain=satuan

Demikian pula, perintah berikut hanya akan menghasilkan contoh tes asap yang dijalankan:

$ ./test.py --constrain=satuan

Untuk melihat daftar singkat dari jenis kendala hukum, Anda dapat meminta mereka untuk dicantumkan.
Perintah berikut

$ ./test.py --jenis

akan menghasilkan daftar berikut yang ditampilkan:

Waf: Masuk ke direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Keluar dari direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'build' berhasil diselesaikan (0.939s)Waf: Masuk ke direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
bvt: Tes Verifikasi Build (untuk melihat apakah build berhasil diselesaikan)
inti: Jalankan semua pengujian berbasis TestSuite (kecualikan contoh)
contoh: Contoh (untuk melihat apakah contoh program berjalan dengan sukses)
kinerja: Tes Kinerja (periksa untuk melihat apakah sistem secepat yang diharapkan)
sistem: Pengujian Sistem (mencakup modul untuk memeriksa integrasi modul)
unit: Tes Unit (dalam modul untuk memeriksa fungsionalitas dasar)

Salah satu dari jenis tes ini dapat diberikan sebagai kendala menggunakan --paksaan .

Untuk melihat daftar singkat dari semua test suite yang tersedia, Anda dapat meminta mereka untuk menjadi
terdaftar. Perintah berikut,

$ ./test.py --daftar

akan menghasilkan daftar test suite yang ditampilkan, mirip dengan

Waf: Masuk ke direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Keluar dari direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'build' berhasil diselesaikan (0.939 detik)
histogram
ns3-wifi-interferensi
ns3-tcp-cwnd
ns3-tcp-interoperabilitas
mencicipi
perangkat-mesh-api
perangkat-mesh-dot11s
perangkat-mesh
...
nama-objek-layanan
Telepon kembali
atribut
config
nilai global
baris perintah
dasar-acak-angka
obyek

Salah satu suite yang terdaftar ini dapat dipilih untuk dijalankan dengan sendirinya menggunakan --rangkaian pilihan sebagai
ditunjukkan di atas.

Sama halnya dengan suite pengujian, seseorang dapat menjalankan program contoh C++ tunggal menggunakan --contoh
pilihan. Perhatikan bahwa jalur relatif untuk contoh tidak perlu disertakan dan bahwa
executable yang dibuat untuk contoh C++ tidak memiliki ekstensi. Memasuki

$ ./test.py --contoh=udp-echo

menghasilkan contoh tunggal yang dijalankan.

LULUS: Contoh contoh/udp/udp-echo

Anda dapat menentukan direktori tempat ns-3 dibangun menggunakan --jalur pembangunan pilihan sebagai
mengikuti.

$ ./test.py --buildpath=/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build/debug --example=wifi-simple-adhoc

Seseorang dapat menjalankan program contoh Python tunggal menggunakan --contoh pilihan. Perhatikan bahwa
jalur relatif untuk contoh harus disertakan dan contoh Python memang membutuhkannya
ekstensi. Memasuki

$ ./test.py --pyexample=contoh/tutorial/pertama.py

menghasilkan contoh tunggal yang dijalankan.

LULUS: Contoh contoh/tutorial/first.py

Karena contoh Python tidak dibuat, Anda tidak perlu menentukan direktori tempat ns-3
dibangun untuk menjalankannya.

Biasanya ketika program contoh dijalankan, mereka menulis sejumlah besar data file jejak.
Ini biasanya disimpan ke direktori dasar distribusi (misalnya,
/home/user/ns-3-dev). Kapan tes.py menjalankan sebuah contoh, itu benar-benar tidak peduli
dengan file jejak. Itu hanya ingin menentukan apakah contoh dapat dibangun dan dijalankan
tanpa error. Karena ini masalahnya, file jejak ditulis ke dalam
/tmp/jejak-tidak dicentang direktori. Jika Anda menjalankan contoh di atas, Anda seharusnya dapat menemukan
yang terkait udp-echo.tr dan udp-echo-n-1.pcap file di sana.

Daftar contoh yang tersedia ditentukan oleh isi direktori ''contoh'' di
distribusi. Jika Anda memilih contoh untuk dieksekusi menggunakan --contoh pilihan,
tes.py tidak akan melakukan upaya apa pun untuk memutuskan apakah contoh telah dikonfigurasi atau tidak, itu
hanya akan mencoba menjalankannya dan melaporkan hasil usahanya.

Ketika tes.py berjalan, secara default pertama-tama akan memastikan bahwa sistem telah sepenuhnya
dibuat. Ini dapat dikalahkan dengan memilih --sekarang .

$ ./test.py --daftar --sekarang

akan menghasilkan daftar suite pengujian yang saat ini dibangun, mirip dengan:

ns3-wifi-propagation-loss-model
ns3-tcp-cwnd
ns3-tcp-interoperabilitas
pcap-file-objek
nama-objek-layanan
generator-angka-acak

Perhatikan tidak adanya Waf membangun pesan.

tes.py juga mendukung menjalankan test suite dan contoh di bawah valgrind. Valgrind adalah seorang
program fleksibel untuk debugging dan profil executable Linux. Secara default, valgrind berjalan
alat yang disebut memcheck, yang melakukan berbagai fungsi pemeriksaan memori, termasuk
mendeteksi akses ke memori yang tidak diinisialisasi, penyalahgunaan memori yang dialokasikan (pembebasan ganda,
akses setelah gratis, dll.) dan mendeteksi kebocoran memori. Ini dapat dipilih dengan menggunakan
--menggiling .

$ ./test.py --menggiling

Saat berjalan, tes.py dan program yang dijalankannya secara tidak langsung, menghasilkan sejumlah besar
berkas sementara. Biasanya, isi dari file-file ini tidak menarik, namun di beberapa
kasus ini dapat berguna (untuk tujuan debugging) untuk melihat file-file ini. tes.py menyediakan
--mempertahankan opsi yang akan menyebabkan file-file sementara ini disimpan setelah dijalankan adalah
lengkap. File disimpan dalam direktori bernama keluaran testpy di bawah subdirektori
dinamai menurut Waktu Universal Terkoordinasi saat ini (juga dikenal sebagai Greenwich Mean
Waktu).

$ ./test.py --mempertahankan

Terakhir, tes.py menyediakan --bertele-tele opsi yang akan mencetak informasi dalam jumlah besar
tentang kemajuannya. Tidak diharapkan bahwa ini akan sangat berguna kecuali ada
sebuah kesalahan. Dalam hal ini, Anda bisa mendapatkan akses ke output standar dan kesalahan standar
dilaporkan dengan menjalankan rangkaian pengujian dan contoh. Pilih verbose dengan cara berikut:

$ ./test.py --verbose

Semua opsi ini dapat dicampur dan dicocokkan. Misalnya, untuk menjalankan semua inti ns-3
suite uji di bawah valgrind, dalam mode verbose, sambil menghasilkan file output HTML, satu
akan melakukan:

$ ./test.py --verbose --grind --constrain=core --html=results.html

TesTaksonomi
Seperti disebutkan di atas, tes dikelompokkan ke dalam sejumlah klasifikasi yang didefinisikan secara luas untuk:
memungkinkan pengguna menjalankan pengujian secara selektif untuk mengatasi berbagai jenis pengujian yang diperlukan
harus dilakukan.

· Membangun Tes Verifikasi

· Tes Unit

· Tes Sistem

· Contoh

· Tes Kinerja

Tes Verifikasi Bangun
Ini adalah tes yang relatif sederhana yang dibangun bersama dengan distribusi dan digunakan
untuk memastikan bahwa build cukup berfungsi. Tes unit kami saat ini tinggal di
file sumber dari kode yang mereka uji dan dibangun ke dalam modul ns-3; dan sangat cocok
deskripsi BVT. BVT hidup dalam kode sumber yang sama yang dibangun ke dalam kode ns-3.
Tes kami saat ini adalah contoh dari tes semacam ini.

Satuan Tes
Tes unit adalah tes yang lebih melibatkan yang masuk ke detail untuk memastikan bahwa sepotong kode
bekerja seperti yang diiklankan secara terpisah. Benar-benar tidak ada alasan untuk tes semacam ini
dibangun ke dalam modul ns-3. Ternyata, misalnya, unit menguji objek
name service kira-kira berukuran sama dengan kode layanan nama objek itu sendiri. Tes unit
adalah tes yang memeriksa satu bit fungsionalitas yang tidak dibangun ke dalam kode ns-3,
tetapi tinggal di direktori yang sama dengan kode yang diuji. Ada kemungkinan bahwa tes ini
periksa integrasi beberapa file implementasi dalam modul juga. Berkas
src/core/test/names-test-suite.cc adalah contoh dari jenis tes ini. Berkas
src/network/test/pcap-file-test-suite.cc adalah contoh lain yang menggunakan pcap bagus yang terkenal
file sebagai file vektor uji. File ini disimpan secara lokal di direktori src/network.

System Tes
Pengujian sistem adalah pengujian yang melibatkan lebih dari satu modul dalam sistem. Kami memiliki banyak
tes semacam ini berjalan dalam kerangka regresi kami saat ini, tetapi biasanya
contoh kelebihan beban. Kami menyediakan tempat baru untuk tes semacam ini di direktori
src/tes. File src/test/ns3tcp/ns3-interop-test-suite.cc adalah contoh dari jenis ini
dari tes. Ia menggunakan NSC TCP untuk menguji implementasi TCP ns-3. Seringkali akan ada ujian
vektor yang diperlukan untuk pengujian semacam ini, dan mereka disimpan di direktori tempat
menguji kehidupan. Misalnya, ns3tcp-interop-response-vectors.pcap adalah file yang terdiri dari
jumlah header TCP yang digunakan sebagai respons yang diharapkan dari ns-3 TCP yang sedang diuji
ke stimulus yang dihasilkan oleh NSC TCP yang digunakan sebagai implementasi ''yang diketahui''.

contoh
Contoh diuji oleh kerangka kerja untuk memastikan mereka dibangun dan akan berjalan. Tidak ada yang
diperiksa, dan saat ini file pcap baru saja dihapus menjadi / Tmp untuk dibuang. Jika
contoh dijalankan (jangan crash) mereka lulus tes asap ini.

Performance Tes
Tes kinerja adalah tes yang melatih bagian tertentu dari sistem dan menentukan
jika tes telah dilaksanakan sampai selesai dalam waktu yang wajar.

Running Tes
Tes biasanya dijalankan menggunakan level tinggi tes.py program. Untuk mendapatkan daftar
opsi baris perintah yang tersedia, jalankan tes.py --membantu

Program percobaan tes.py akan menjalankan kedua tes dan contoh-contoh yang telah ditambahkan ke
daftar untuk diperiksa. Perbedaan antara tes dan contoh adalah sebagai berikut. tes
umumnya memeriksa apakah keluaran atau peristiwa simulasi tertentu sesuai dengan perilaku yang diharapkan.
Sebaliknya, output dari contoh tidak diperiksa, dan program pengujian hanya memeriksa
status keluar dari program contoh untuk memastikan program itu berjalan tanpa kesalahan.

Secara singkat, untuk menjalankan semua pengujian, pertama-tama harus mengonfigurasi pengujian selama tahap konfigurasi, dan
juga (opsional) contoh jika contoh harus diperiksa:

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

Kemudian, build ns-3, dan setelah dibangun, jalankan saja tes.py. tes.py -h akan menunjukkan nomor
opsi konfigurasi yang mengubah perilaku test.py.

Program tes.py memanggil, untuk pengujian dan contoh C++, program C++ tingkat rendah yang disebut
ujian-pelari untuk benar-benar menjalankan tes. Seperti yang dibahas di bawah ini, ini ujian-pelari bisa menjadi
cara yang membantu untuk men-debug tes.

Debugging Tes
Proses debug program pengujian paling baik dilakukan dengan menjalankan uji coba tingkat rendah
program. Test-runner adalah jembatan dari kode Python generik ke ns-3 kode. Dia
ditulis dalam C++ dan menggunakan proses penemuan tes otomatis di ns-3 kode untuk menemukan dan
memungkinkan pelaksanaan semua berbagai tes.

Alasan utama kenapa tes.py tidak cocok untuk debugging adalah tidak diperbolehkan untuk
logging untuk diaktifkan menggunakan NS_LOG variabel lingkungan saat test.py berjalan. Ini
batasan tidak berlaku untuk test-runner yang dapat dieksekusi. Karenanya, jika Anda ingin melihat logging
output dari pengujian Anda, Anda harus menjalankannya menggunakan test-runner secara langsung.

Untuk menjalankan test-runner, Anda menjalankannya seperti eksekusi ns-3 lainnya -- menggunakan
WAF. Untuk mendapatkan daftar opsi yang tersedia, Anda dapat mengetik:

$ ./waf --jalankan "test-runner --help"

Anda akan melihat sesuatu seperti berikut

Waf: Masuk ke direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
Waf: Keluar dari direktori `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
'build' berhasil diselesaikan (0.353 detik)
--assert: Beri tahu tes ke segfault (seperti tegaskan) jika kesalahan terdeteksi
--basedir=dir: Setel direktori dasar (tempat menemukan src) ke ''dir''
--tempdir=dir: Setel direktori sementara (tempat menemukan file data) ke ''dir''
--constrain=test-type: Batasi pemeriksaan untuk menguji suite tipe ''test-type''
--help: Cetak pesan ini
--kinds: Daftar semua jenis tes yang tersedia
--list: Daftar semua test suite (opsional dibatasi oleh test-type)
--out=file-name: Setel file keluaran status pengujian ke ''nama-file''
--suite=suite-name: Jalankan test suite bernama ''suite-name''
--verbose: Aktifkan pesan di run test suite

Ada sejumlah hal yang tersedia bagi Anda yang akan akrab bagi Anda jika Anda memilikinya
memandang tes.py. Ini harus diharapkan karena test-runner hanyalah sebuah antarmuka
antara tes.py dan ns-3. Anda mungkin memperhatikan bahwa perintah terkait contoh tidak ada di sini.
Itu karena contohnya benar-benar tidak ns-3 tes. tes.py menjalankan mereka seolah-olah mereka
untuk menghadirkan lingkungan pengujian terpadu, tetapi mereka benar-benar berbeda dan tidak
dapat ditemukan di sini.

Opsi baru pertama yang muncul di sini, tetapi tidak di test.py adalah --menegaskan pilihan. Ini
opsi berguna saat men-debug kasus uji saat berjalan di bawah debugger seperti gdb. Ketika
dipilih, opsi ini memberi tahu kasus uji yang mendasari untuk menyebabkan pelanggaran segmentasi jika
kesalahan terdeteksi. Ini memiliki efek samping yang bagus yang menyebabkan eksekusi program berhenti
(membobol debugger) ketika kesalahan terdeteksi. Jika Anda menggunakan gdb, Anda bisa menggunakan
opsi ini seperti,

$ ./waf cangkang
$ cd membangun/debug/utils
$gdb test-runner
$ jalankan --suite=nilai global --tegaskan

Jika kesalahan kemudian ditemukan di rangkaian uji nilai global, segfault akan dihasilkan
dan debugger (tingkat sumber) akan berhenti di NS_TEST_ASSERT_MSG yang mendeteksi
kesalahan.

Opsi baru lainnya yang muncul di sini adalah --basedir pilihan. Ternyata beberapa
tes mungkin perlu merujuk ke direktori sumber dari ns-3 distribusi untuk menemukan lokal
data, jadi direktori dasar selalu diperlukan untuk menjalankan pengujian.

Jika Anda menjalankan tes dari test.py, program Python akan menyediakan opsi berdasarkan untuk
Anda. Untuk menjalankan salah satu tes langsung dari test-runner menggunakan WAF, kamu akan membutuhkan
tentukan test suite untuk dijalankan bersama dengan direktori dasar. Jadi Anda bisa menggunakan cangkangnya
dan lakukan:

$ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object"

Perhatikan tanda kutip ''mundur'' pada pwd perintah.

Jika Anda menjalankan test suite dari debugger, itu bisa sangat menyakitkan untuk diingat
dan terus-menerus ketik jalur absolut dari direktori basis distribusi. Karena
ini, jika Anda menghilangkan baseir, test-runner akan mencoba mencari tahu untuk Anda. Dia
dimulai di direktori kerja saat ini dan berjalan ke atas pohon direktori mencari a
file direktori dengan file bernama VERSION dan LISENSI. Jika menemukan satu, itu mengasumsikan bahwa
harus berbasis dan menyediakannya untuk Anda.

uji keluaran
Banyak test suite perlu menulis file sementara (seperti file pcap) dalam proses
menjalankan tes. Tes kemudian membutuhkan direktori sementara untuk menulis. Python
utilitas tes (test.py) akan menyediakan file sementara secara otomatis, tetapi jika dijalankan secara mandiri
direktori sementara ini harus disediakan. Sama seperti dalam kasus mereka, itu bisa
menjengkelkan untuk terus-menerus harus memberikan --tempdir, jadi pelari tes akan mencari satu
keluar untuk Anda jika Anda tidak menyediakannya. Ini pertama kali mencari variabel lingkungan bernama tmp
dan TEMP dan menggunakan itu. Jika tidak tmp maupun TEMP didefinisikan itu memilih / Tmp. Kode
lalu menempelkan pengidentifikasi yang menunjukkan apa yang membuat direktori (ns-3) lalu waktunya
(hh.mm.ss) diikuti dengan angka acak yang besar. Pelari uji membuat direktori itu
nama yang akan digunakan sebagai direktori sementara. File sementara kemudian masuk ke direktori yang
akan diberi nama seperti

/tmp/ns-3.10.25.37.61537845

Waktu disediakan sebagai petunjuk sehingga Anda dapat dengan mudah merekonstruksi apa
direktori digunakan jika Anda perlu kembali dan melihat file yang ditempatkan di dalamnya
direktori.

Kelas keluaran lainnya adalah keluaran uji seperti jejak pcap yang dihasilkan untuk dibandingkan dengan
keluaran referensi. Program pengujian biasanya akan menghapus ini setelah rangkaian pengujian semua
Lari. Untuk menonaktifkan penghapusan hasil pengujian, jalankan tes.py dengan opsi "pertahankan":

$ ./test.py -r

dan hasil pengujian dapat ditemukan di testpy-keluaran/ direktori.

Pelaporan of uji kegagalan
Saat Anda menjalankan test suite menggunakan test-runner itu akan menjalankan tes secara diam-diam secara default.
Satu-satunya indikasi bahwa Anda akan mendapatkan bahwa tes lulus adalah ketiadaan pesan
dari WAF mengatakan bahwa program mengembalikan sesuatu selain kode keluar nol. Mendapatkan
beberapa output dari tes, Anda perlu menentukan file output yang akan tes
tulis status XML mereka menggunakan --keluar pilihan. Anda harus berhati-hati dalam menafsirkan
hasil karena suite tes akan menambahkan hasil ke file ini. Mencoba,

$ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object --out=myfile.xml"

Jika Anda melihat file file saya.xml Anda harus melihat sesuatu seperti,


pcap-file-objek

Periksa untuk melihat bahwa PcapFile::Buka dengan mode ''w'' berfungsi
LULUS
nyata 0.00 pengguna 0.00 sistem 0.00


Periksa untuk melihat bahwa PcapFile::Open dengan mode ''r'' berfungsi
LULUS
nyata 0.00 pengguna 0.00 sistem 0.00


Periksa untuk melihat bahwa PcapFile::Open dengan mode ''a'' berfungsi
LULUS
nyata 0.00 pengguna 0.00 sistem 0.00


Periksa untuk melihat bahwa PcapFileHeader dikelola dengan benar
LULUS
nyata 0.00 pengguna 0.00 sistem 0.00


Periksa untuk melihat bahwa PcapRecordHeader dikelola dengan benar
LULUS
nyata 0.00 pengguna 0.00 sistem 0.00


Periksa untuk melihat bahwa PcapFile dapat membacakan file pcap bagus yang diketahui
LULUS
nyata 0.00 pengguna 0.00 sistem 0.00

LULUS
nyata 0.00 pengguna 0.00 sistem 0.00


Jika Anda terbiasa dengan XML, ini seharusnya cukup jelas. Itu juga bukan
menyelesaikan file XML karena suite uji dirancang agar outputnya ditambahkan ke master
File status XML seperti yang dijelaskan dalam tes.py bagian.

Debugging uji rangkaian kegagalan
Untuk men-debug crash pengujian, seperti

CRASH: TestSuite ns3-wifi-interferensi

Anda dapat mengakses program test-runner yang mendasari melalui gdb sebagai berikut, dan kemudian lulus
Argumen "--basedir=`pwd`" untuk dijalankan (Anda juga dapat meneruskan argumen lain sesuai kebutuhan, tetapi
basedir adalah minimum yang dibutuhkan):

$ ./waf --command-template="gdb %s" --jalankan "test-runner"
Waf: Masuk ke direktori `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build'
Waf: Keluar dari direktori `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build'
'build' berhasil diselesaikan (0.380 detik)
GNU gdb 6.8-debian
Hak Cipta (C) 2008 Free Software Foundation, Inc.
L cense GPLv3+: GNU GPL versi 3 atau yang lebih baruhttp://gnu.org/licenses/gpl.html>
Ini adalah perangkat lunak gratis: Anda bebas mengubah dan mendistribusikannya kembali.
TIDAK ADA JAMINAN, sejauh diizinkan oleh hukum. Ketik "tampilkan penyalinan"
dan "tunjukkan garansi" untuk detailnya.
GDB ini dikonfigurasi sebagai "x86_64-linux-gnu"...
(gdb) r --basedir=`pwd`
Memulai program: <..>/build/debug/utils/test-runner --basedir=`pwd`
[Debug utas menggunakan libthread_db diaktifkan]
menegaskan gagal. file=../src/core/model/type-id.cc, line=138, cond="uid <= m_information.size () && uid != 0"
...

Berikut adalah contoh lain tentang cara menggunakan valgrind untuk men-debug masalah memori seperti:

VALGR: Perangkat TestSuite-mesh-dot11s-regresi

$ ./waf --command-template="valgrind %s --basedir=`pwd` --suite=devices-mesh-dot11s-regression" --run test-runner

Kelas Pelari Uji
Eksekusi yang menjalankan program pengujian khusus menggunakan kelas TestRunner. Kelas ini
menyediakan pendaftaran dan daftar tes otomatis, serta cara untuk menjalankan
tes individu. Suite pengujian individu menggunakan konstruktor global C++ untuk menambahkan diri mereka sendiri ke
kumpulan test suite yang dikelola oleh test runner. Pelari uji digunakan untuk mendaftar
semua tes yang tersedia dan untuk memilih tes yang akan dijalankan. Ini adalah kelas yang cukup sederhana
yang menyediakan tiga metode statis untuk menyediakan atau Menambahkan dan Mendapatkan rangkaian pengujian ke a
kumpulan tes. Lihat doxygen untuk kelas ns3::Pelari Tes untuk rincian.

uji Rangkaian
Semua ns-3 tes diklasifikasikan ke dalam Test Suites dan Test Case. Sebuah test suite adalah
kumpulan kasus uji yang sepenuhnya menjalankan jenis fungsi tertentu. Sebagai
dijelaskan di atas, test suite dapat diklasifikasikan sebagai,

· Membangun Tes Verifikasi

· Tes Unit

· Tes Sistem

· Contoh

· Tes Kinerja

Klasifikasi ini diekspor dari kelas TestSuite. Kelas ini cukup sederhana,
yang ada hanya sebagai tempat untuk mengekspor jenis ini dan untuk mengumpulkan kasus uji. Dari pengguna
perspektif, untuk membuat TestSuite baru dalam sistem, seseorang hanya perlu mendefinisikan yang baru
kelas yang mewarisi dari kelas TestSuite dan melakukan dua tugas ini.

Kode berikut akan mendefinisikan kelas baru yang dapat dijalankan oleh: tes.py sebagai tes ''satuan''
dengan nama tampilan, nama-test-suite saya.

kelas MySuite : TestSuite publik
{
publik:
MyTestSuite();
};

MyTestSuite::MyTestSuite ()
: TestSuite ("nama-test-suite-saya", UNIT)
{
AddTestCase (MyTestCase baru);
}

MyTestSuite myTestSuite;

Kelas dasar mengurus semua pendaftaran dan pelaporan yang diperlukan untuk menjadi baik
warga negara dalam kerangka uji.

uji Kasus
Tes individu dibuat menggunakan kelas TestCase. Model umum untuk penggunaan tes
case termasuk "satu test case per fitur", dan "satu test case per metode." Campuran dari
model-model ini dapat digunakan.

Untuk membuat kasus uji baru dalam sistem, yang harus dilakukan adalah mewarisi dari
Kasus cobaan kelas dasar, timpa konstruktor untuk memberi nama kasus uji dan timpa
itu Jalankan metode untuk menjalankan tes.

kelas MyTestCase : TestCase publik
{
MyTestCase();
virtual void DoRun (batal);
};

Kasus Uji Saya::Kasus Uji Saya ()
: TestCase ("Periksa sedikit fungsionalitas")
{
}

membatalkan
MyTestCase::DoRun (batal)
{
NS_TEST_ASSERT_MSG_EQ (benar, benar, "Beberapa pesan gagal");
}

Utilitas
Ada sejumlah utilitas dari berbagai jenis yang juga merupakan bagian dari pengujian
kerangka. Contohnya termasuk file pcap umum yang berguna untuk menyimpan vektor uji; sebuah
wadah generik yang berguna untuk penyimpanan sementara vektor uji selama pelaksanaan uji; dan
alat untuk menghasilkan presentasi berdasarkan hasil pengujian validasi dan verifikasi.

Utilitas ini tidak didokumentasikan di sini, tetapi misalnya, silakan lihat bagaimana tes TCP
ditemukan di src/tes/ns3tcp/ gunakan file pcap dan output referensi.

Seterpercayaapakah Olymp Trade? Kesimpulan untuk menulis tes
Tujuan utama dari proyek ns-3 adalah untuk membantu pengguna meningkatkan validitas dan
kredibilitas hasil mereka. Ada banyak elemen untuk mendapatkan model yang valid dan
simulasi, dan pengujian adalah komponen utama. Jika Anda menyumbangkan model atau contoh untuk
ns-3, Anda mungkin diminta untuk menyumbangkan kode pengujian. Model yang Anda sumbangkan akan digunakan
selama bertahun-tahun oleh orang lain, yang mungkin tidak tahu pada pandangan pertama apakah
modelnya benar. Kode pengujian yang Anda tulis untuk model Anda akan membantu menghindari masa depan
regresi dalam output dan akan membantu pengguna masa depan dalam memahami verifikasi dan
batas penerapan model Anda.

Ada banyak cara untuk memverifikasi kebenaran implementasi model. Di dalam
bagian, kami berharap dapat mencakup beberapa kasus umum yang dapat digunakan sebagai panduan untuk menulis baru
tes.

Contoh TestSuite kerangka
Saat memulai dari awal (yaitu tidak menambahkan TestCase ke TestSuite yang ada), ini
hal-hal yang perlu diputuskan di muka:

· Apa nama test suite itu

· Jenis pengujian apa yang akan dilakukan (Uji Verifikasi Bangun, Uji Unit, Uji Sistem, atau
Uji kinerja)

· Di mana kode uji akan hidup (baik dalam modul ns-3 yang ada atau secara terpisah di
direktori src/test/). Anda harus mengedit file wscript di direktori itu untuk
kompilasi kode baru Anda, jika itu adalah file baru.

Sebuah program yang disebut src/buat-module.py merupakan titik awal yang baik. Program ini dapat
dipanggil seperti buat-modul.py router untuk modul baru hipotetis yang disebut router. Sekali
Anda melakukan ini, Anda akan melihat router direktori, dan tes/router-test-suite.cc rangkaian tes.
File ini dapat menjadi titik awal untuk pengujian awal Anda. Ini adalah rangkaian uji yang berfungsi,
meskipun tes yang sebenarnya dilakukan adalah sepele. Salin ke pengujian modul Anda
direktori, dan lakukan substitusi global "Router" di file itu untuk sesuatu yang berkaitan
ke model yang ingin Anda uji. Anda juga dapat mengedit hal-hal seperti lebih deskriptif
nama kasus uji.

Anda juga perlu menambahkan blok ke wscript Anda agar tes ini dapat dikompilasi:

module_test.sumber = [
'test/router-test-suite.cc',
]

Sebelum Anda benar-benar mulai membuat ini melakukan hal-hal yang berguna, mungkin membantu untuk mencoba menjalankan
kerangka. Pastikan ns-3 telah dikonfigurasi dengan opsi "--enable-tests".
Mari kita asumsikan bahwa rangkaian pengujian baru Anda disebut "router" seperti di sini:

RouterTestSuite::RouterTestSuite ()
: TestSuite ("router", UNIT)

Coba perintah ini:

$ ./test.py -s router

Output seperti di bawah ini harus dihasilkan:

LULUS: Router TestSuite
1 dari 1 tes lulus (1 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Lihat src/lte/test/test-lte-antenna.cc untuk contoh yang berhasil.

uji Macro
Ada sejumlah makro yang tersedia untuk memeriksa keluaran program pengujian dengan yang diharapkan
keluaran. Makro ini didefinisikan dalam src/core/model/test.h.

Set utama makro yang digunakan meliputi berikut ini:

NS_TEST_ASSERT_MSG_EQ(aktual, batas, pesan)
NS_TEST_ASSERT_MSG_NE(aktual, batas, pesan)
NS_TEST_ASSERT_MSG_LT(aktual, batas, pesan)
NS_TEST_ASSERT_MSG_GT(aktual, batas, pesan)
NS_TEST_ASSERT_MSG_EQ_TOL(aktual, batas, tol, pesan)

Argumen pertama sebenarnya adalah nilai yang diuji, nilai kedua membatasi adalah yang diharapkan
nilai (atau nilai untuk diuji), dan argumen terakhir msg adalah pesan kesalahan ke
print out jika tes gagal.

Empat makro pertama di atas menguji kesetaraan, ketidaksetaraan, kurang dari, atau lebih besar dari,
masing-masing. Makro kelima di atas menguji kesetaraan, tetapi dalam toleransi tertentu.
Varian ini berguna saat menguji angka floating point untuk kesetaraan terhadap batas,
di mana Anda ingin menghindari kegagalan pengujian karena kesalahan pembulatan.

Akhirnya, ada varian di atas di mana kata kuncinya MENEGASKAN diganti oleh MENGHARAPKAN.
Varian ini dirancang khusus untuk digunakan dalam pengembalian metode (terutama callback).
ruang kosong. Cadangan penggunaannya untuk panggilan balik yang Anda gunakan dalam program pengujian Anda; jika tidak, gunakan
itu MENEGASKAN varian.

Seterpercayaapakah Olymp Trade? Kesimpulan untuk menambahkan an contoh program untuk itu uji rangkaian
Seseorang dapat "menguji asap" bahwa contoh dikompilasi dan dijalankan dengan sukses hingga selesai (tanpa
kebocoran memori) menggunakan contoh-untuk-run.py skrip yang terletak di direktori pengujian modul Anda.
Secara singkat, dengan menyertakan contoh file ini di direktori pengujian Anda, Anda dapat menyebabkan
pelari uji untuk menjalankan contoh yang terdaftar. Biasanya yang terbaik adalah memastikan bahwa Anda
pilih contoh yang memiliki waktu kerja yang cukup singkat agar tidak menghambat pengujian. Melihat
contoh di src/lte/tes/ direktori.

pengujian untuk boolean hasil
pengujian hasil ketika keserampangan is terlibat
pengujian keluaran data terhadap a dikenal distribusi
Menyediakan tidak sepele memasukkan vektor of data
Menyimpan dan referensi tidak sepele keluaran data
Presenting Tujuan keluaran uji data
Bantuan
membuat a yang baru ns-3 model
Bab ini berjalan melalui proses desain dari sebuah ns-3 model. Dalam banyak kasus penelitian,
pengguna tidak akan puas hanya mengadaptasi model yang ada, tetapi mungkin ingin memperluasnya
inti dari simulator dengan cara baru. Kami akan menggunakan contoh menambahkan ErrorModel ke a
sederhana ns-3 tautan sebagai contoh yang memotivasi tentang bagaimana seseorang dapat mendekati masalah ini dan
melanjutkan melalui desain dan implementasi.

CATATAN:
Dokumentasi

Di sini kami fokus pada proses pembuatan model baru dan modul baru, dan beberapa di antaranya
pilihan desain yang terlibat. Demi kejelasan, kami menunda diskusi tentang mekanika
mendokumentasikan model dan kode sumber ke Dokumentasi bab.

Mendesain Pendekatan
Pertimbangkan bagaimana Anda menginginkannya bekerja; apa yang harus dilakukan. Pikirkan tentang hal-hal ini:

· fungsi: Fungsi apa yang harus dimiliki? Atribut atau konfigurasi apa itu
terpapar ke pengguna?

· dapat digunakan kembali: Seberapa banyak orang lain dapat menggunakan kembali desain saya? Dapatkah saya menggunakan kembali kode dari
ns-2 untuk memulai? Bagaimana cara pengguna mengintegrasikan model dengan model lainnya
simulasi?

· dependensi: Bagaimana saya bisa mengurangi pengenalan ketergantungan luar pada kode baru saya
sebanyak mungkin (agar lebih modular)? Misalnya, haruskah saya menghindari
ketergantungan pada IPv4 jika saya ingin juga digunakan oleh IPv6? Haruskah saya menghindari ketergantungan apa pun
pada IP sama sekali?

Jangan ragu untuk menghubungi ns-3-pengguna or ns-developer daftar jika Anda memiliki pertanyaan.
Secara khusus, penting untuk memikirkan tentang API publik model baru Anda dan memintanya
masukan. Ini juga membantu untuk memberi tahu orang lain tentang pekerjaan Anda jika Anda tertarik
kolaborator.

Contoh: Model Kesalahan
Model kesalahan ada di ns-2. Ini memungkinkan paket untuk diteruskan ke objek stateful itu
menentukan, berdasarkan variabel acak, apakah paket rusak. Penelepon bisa
lalu putuskan apa yang harus dilakukan dengan paket tersebut (jatuhkan, dll.).

API utama dari model kesalahan adalah fungsi untuk meneruskan paket, dan nilai pengembaliannya
fungsi ini adalah boolean yang memberi tahu penelepon apakah terjadi kerusakan. Catatan
bahwa tergantung pada model kesalahan, buffer data paket mungkin rusak atau tidak.
Sebut saja fungsi ini "IsCorrupt()".

Sejauh ini, dalam desain kami, kami memiliki:

kelas ErrorModel
{
publik:
/ **
* \returns true jika Paket dianggap salah/rusak
* \param pkt Paket untuk menerapkan model kesalahan
*/
bool IsCorrupt (Ptr pkt);
};

Perhatikan bahwa kami tidak meneruskan pointer const, sehingga memungkinkan fungsi untuk memodifikasi
paket jika IsCorrupt() mengembalikan nilai true. Tidak semua model error benar-benar akan mengubah paket;
apakah buffer data paket rusak atau tidak harus didokumentasikan.

Kami mungkin juga menginginkan versi khusus dari ini, seperti di ns-2, jadi meskipun bukan
hanya pilihan desain untuk polimorfisme, kami berasumsi bahwa kami akan mensubklasifikasikan kelas dasar
ErrorModel untuk kelas khusus, seperti RateErrorModel, ListErrorModel, dll, seperti
selesai di ns-2.

Anda mungkin berpikir pada titik ini, "Mengapa tidak menjadikan IsCorrupt() sebagai metode virtual?". Itu adalah
satu pendekatan; yang lainnya adalah membuat fungsi non-virtual publik tidak langsung melalui a
fungsi virtual pribadi (ini dalam C++ dikenal sebagai idiom antarmuka non virtual dan
diadopsi di ns-3 kelas ErrorModel).

Selanjutnya, haruskah perangkat ini memiliki ketergantungan pada IP atau protokol lain? Kami tidak mau
untuk membuat dependensi pada protokol Internet (model kesalahan harus berlaku untuk
protokol non-Internet juga), jadi kami akan mengingatnya nanti.

Pertimbangan lain adalah bagaimana objek akan menyertakan model kesalahan ini. Kami membayangkan menempatkan
penyetel eksplisit dalam implementasi NetDevice tertentu, misalnya.:

/ **
* Lampirkan ErrorModel terima ke PointToPointNetDevice.
*
* PointToPointNetDevice secara opsional dapat menyertakan ErrorModel di
* paket menerima rantai.
*
* @lihat ErrorModel
* @param em Ptr ke ErrorModel.
*/
batal PointToPointNetDevice::SetReceiveErrorModel(Ptr mereka);

Sekali lagi, ini bukan satu-satunya pilihan yang kami miliki (model kesalahan dapat digabungkan menjadi banyak
objek lain), tetapi memenuhi kasus penggunaan utama kami, yang memungkinkan pengguna untuk memaksa
kesalahan pada transmisi paket yang berhasil, di tingkat NetDevice.

Setelah berpikir dan melihat yang ada ns-2 kode, ini adalah contoh API dari sebuah basis
kelas dan subkelas pertama yang dapat diposting untuk tinjauan awal:

kelas ErrorModel
{
publik:
Model Kesalahan();
maya ~ErrorModel();
bool IsCorrupt (Ptr pkt);
batal Reset (batal);
batal Aktifkan (batal);
batal Nonaktifkan (batal);
bool IsEnabled (batal) const;
pribadi:
virtual bool DoCorrupt (Ptr pkt) = 0;
kekosongan virtual DoReset (batal) = 0;
};

enum Unit Kesalahan
{
EU_BIT,
EU_BYTE,
EU_PKT
};

// Tentukan paket mana yang mengalami kesalahan terkait dengan yang mendasarinya
// distribusi variabel acak, tingkat kesalahan, dan satuan untuk tingkat.
kelas RateErrorModel : ErrorModel publik
{
publik:
RateErrorModel();
virtual ~RateErrorModel();
enum ErrorUnit GetUnit (batal) const;
membatalkan SetUnit (enum ErrorUnit error_unit);
ganda GetRate (batal) const;
membatalkan SetRate (tarif ganda);
batal SetRandomVariable (const RandomVariable &ranvar);
pribadi:
virtual bool DoCorrupt (Ptr pkt);
kekosongan virtual DoReset (batal);
};

Perancah
Katakanlah Anda siap untuk mulai mengimplementasikan; Anda memiliki gambaran yang cukup jelas tentang
apa yang ingin Anda bangun, dan Anda mungkin telah meminta beberapa tinjauan atau saran awal
Daftar. Salah satu cara untuk mendekati langkah selanjutnya (implementasi) adalah dengan membuat scaffolding dan
isi detailnya saat desain matang.

Bagian ini membahas banyak langkah yang harus Anda pertimbangkan untuk menentukan scaffolding, atau
kerangka non-fungsional dari apa yang pada akhirnya akan diterapkan oleh model Anda. Hal ini biasanya baik
berlatih untuk tidak menunggu untuk mendapatkan rincian ini terintegrasi pada akhirnya, melainkan untuk menyelami a
kerangka model Anda ke dalam sistem lebih awal dan kemudian menambahkan fungsi nanti setelah API dan
integrasi tampaknya benar.

Perhatikan bahwa Anda ingin memodifikasi beberapa hal dalam presentasi di bawah ini untuk model Anda
karena jika Anda mengikuti model kesalahan kata demi kata, kode yang Anda hasilkan akan bertabrakan dengan
model kesalahan yang ada. Di bawah ini hanyalah garis besar tentang bagaimana ErrorModel dibuat untuk Anda
dapat beradaptasi dengan model lain.

ULASAN itu ns-3 Pengkodean Gaya Dokumen
Pada titik ini, Anda mungkin ingin menjeda dan membaca ns-3 dokumen gaya pengkodean, khususnya
jika Anda mempertimbangkan untuk menyumbangkan kode Anda kembali ke proyek. Gaya pengkodean
dokumen ditautkan dari halaman proyek utama: ns-3 coding gaya.

Memutuskan Where in itu sumber Pohon itu Model Harus Tinggal
Semua ns-3 kode sumber model ada di direktori src /. Anda harus memilih yang mana
subdirektori tempatnya berada. Jika ini semacam kode model baru, masuk akal untuk meletakkannya
ke dalam src / direktori di suatu tempat, terutama untuk kemudahan integrasi dengan build
sistem.

Dalam kasus model kesalahan, ini sangat terkait dengan kelas paket, jadi masuk akal
untuk mengimplementasikannya di src/jaringan/ modul dimana ns-3 paket diimplementasikan.

WAF dan wscript.dll
ns-3 menggunakan Waf membangun sistem. Anda akan ingin mengintegrasikan yang baru ns-3 menggunakan Waf
membangun sistem. Anda ingin mengintegrasikan file sumber baru Anda ke dalam sistem ini. Ini
mengharuskan Anda menambahkan file Anda ke wscript.dll file yang ditemukan di setiap direktori.

Mari kita mulai dengan file kosong error-model.h dan error-model.cc, dan tambahkan ini ke
src/jaringan/wscript. Ini benar-benar hanya masalah menambahkan file .cc ke file lainnya
file sumber, dan file .h ke daftar file header.

Sekarang, buka direktori tingkat atas dan ketik "./test.py". Anda seharusnya tidak rusak
apapun dengan operasi ini.

Memasukkan Penjaga
Selanjutnya, mari tambahkan beberapa memasukkan penjaga di file header kami.:

#jikandef ERROR_MODEL_H
#menentukan ERROR_MODEL_H
...
#berakhir jika

namespace ns3
ns-3 menggunakan ns-3 namespace untuk mengisolasi simbolnya dari ruang nama lain. Biasanya, a
pengguna selanjutnya akan menempatkan ns-3 blok namespace di file cc dan h.:

ruang nama ns3 {
...
}

Pada titik ini, kami memiliki beberapa file kerangka di mana kami dapat mulai mendefinisikan kelas baru kami.
File header terlihat seperti ini:

#jikandef ERROR_MODEL_H
#menentukan ERROR_MODEL_H

ruang nama ns3 {

} // ruang nama ns3
#berakhir jika

selagi kesalahan-model.cc file hanya terlihat seperti ini:

#sertakan "model-kesalahan.h"

ruang nama ns3 {

} // ruang nama ns3

File-file ini harus dikompilasi karena tidak benar-benar memiliki konten apa pun. Kami sekarang siap untuk
mulai menambahkan kelas.

Awal Organisasi
Pada titik ini, kami masih mengerjakan beberapa perancah, tetapi kami dapat mulai menentukan
kelas, dengan fungsi yang akan ditambahkan nanti.

Mewarisi dari itu obyek Kelas?
Ini adalah langkah desain yang penting; apakah akan menggunakan kelas obyek sebagai kelas dasar untuk yang baru
kelas.

Seperti yang dijelaskan dalam bab tentang ns-3 Objek-model, kelas yang mewarisi dari kelas
obyek dapatkan properti khusus:

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

· sistem agregasi objek

· sistem penghitungan referensi penunjuk pintar (kelas Ptr)

Kelas yang berasal dari kelas Basis Objek} dapatkan dua properti pertama di atas, tetapi tidak
dapatkan petunjuk cerdas. Kelas yang berasal dari kelas RefCountBase dapatkan hanya smart-pointer
sistem penghitungan referensi.

Dalam prakteknya, kelas obyek adalah varian dari tiga di atas bahwa ns-3 pengembang akan
paling sering ditemui.

Dalam kasus kami, kami ingin menggunakan sistem atribut, dan kami akan meneruskan instance
dari objek ini di seluruh ns-3 API publik, jadi kelas obyek cocok untuk kita.

Awal Kelas
Salah satu cara untuk melanjutkan adalah mulai dengan mendefinisikan fungsi minimum dan lihat apakah mereka mau
menyusun. Mari kita tinjau apa saja yang diperlukan untuk diterapkan saat kita menurunkan dari kelas Object.:

#jikandef ERROR_MODEL_H
#menentukan ERROR_MODEL_H

#sertakan "ns3/object.h"

ruang nama ns3 {

kelas ErrorModel : Objek publik
{
publik:
static TypeId GetTypeId (batal);

Model Kesalahan();
maya ~ErrorModel();
};

kelas RateErrorModel : ErrorModel publik
{
publik:
static TypeId GetTypeId (batal);

RateErrorModel();
virtual ~RateErrorModel();
};
#berakhir jika

Beberapa hal yang perlu diperhatikan di sini. Kita perlu menyertakan objek.h. Konvensi di ns-3 apakah itu jika
file header terletak bersama di direktori yang sama, mungkin disertakan tanpa jalur apa pun
awalan. Oleh karena itu, jika kami menerapkan ErrorModel di src/inti/model direktori, kami
bisa saja berkata "#include "objek.h"". Tapi kita masuk src/jaringan/model, jadi kita harus
sertakan sebagai"#include "ns3/objek.h"". Perhatikan juga bahwa ini berada di luar namespace
pernyataan.

Kedua, setiap kelas harus mengimplementasikan fungsi anggota publik statis yang disebut DapatkanTypeId (ruang kosong).

Ketiga, adalah ide yang bagus untuk mengimplementasikan konstruktor dan destruktor daripada membiarkannya
kompiler menghasilkannya, dan membuat destruktor menjadi virtual. Di C++, perhatikan juga salinan itu
operator penugasan dan pembuat salinan dihasilkan secara otomatis jika tidak ditentukan, jadi
jika Anda tidak menginginkannya, Anda harus menerapkannya sebagai anggota pribadi. Aspek ini
C++ dibahas dalam buku C++ Efektif Scott Meyers. butir 45.

Sekarang mari kita lihat beberapa kode implementasi kerangka yang sesuai di file .cc.:

#sertakan "model-kesalahan.h"

ruang nama ns3 {

NS_OBJECT_ENSURE_REGISTERED (Model Kesalahan);

TypeId ErrorModel::GetTypeId (batal)
{
statis TypeId tid = TypeId ("ns3::ErrorModel")
.SetInduk ()
;
kembali tid;
}

Model Kesalahan::Model Kesalahan ()
{
}

Model Kesalahan::~Model Kesalahan ()
{
}

NS_OBJECT_ENSURE_REGISTERED (RateErrorModel);

TypeId RateErrorModel::GetTypeId (batal)
{
statis TypeId tid = TypeId ("ns3::RateErrorModel")
.SetParent ()
.AddConstructor ()
;
kembali tid;
}

RateErrorModel::RateErrorModel ()
{
}

RateErrorModel::~RateErrorModel ()
{
}

Apa DapatkanTypeId (ruang kosong) fungsi? Fungsi ini melakukan beberapa hal. Ini mendaftar a
string unik ke dalam sistem TypeId. Ini menetapkan hierarki objek di
sistem atribut (melalui SetInduk). Itu juga menyatakan bahwa objek tertentu dapat dibuat melalui
kerangka pembuatan objek (TambahkanKonstruktor).

makro NS_OBJECT_ENSURE_REGISTERED (nama kelas) diperlukan juga sekali untuk setiap kelas itu
mendefinisikan metode GetTypeId baru, dan melakukan pendaftaran sebenarnya dari kelas ke dalam
sistem. Bab Object-model membahas hal ini secara lebih rinci.

Termasuk Luar File
Logging Bantuan
Di sini, menulis a sedikit tentang menambahkan |ns3| penebangan makro. Note bahwa LOG_COMPONENT_DEFINE is
dilakukan di luar itu namespace ns3

Konstruktor, Empty fungsi Prototip
kunci Variabel (Bawaan Nilai, Atribut)
uji program 1
obyek Kerangka
Menambahkan a Contoh Naskah
Pada titik ini, seseorang mungkin ingin mencoba mengambil perancah dasar yang ditentukan di atas dan menambahkannya
ke dalam sistem. Melakukan langkah ini sekarang memungkinkan seseorang untuk menggunakan model yang lebih sederhana saat pipa ledeng
ke dalam sistem dan juga dapat mengungkapkan apakah diperlukan modifikasi desain atau API
dibuat. Setelah ini selesai, kami akan kembali membangun fungsionalitas dari
ErrorModel sendiri.

Add Dasar Bantuan in itu Kelas
/* titik-ke-titik-net-device.h */
kelas ErrorModel;

/ **
* Model kesalahan untuk menerima acara paket
*/
Ptr m_receiveErrorModel;

Add Aksesor
membatalkan
PointToPointNetDevice::SetReceiveErrorModel (Ptr em)
{
NS_LOG_FUNCTION (ini << em);
m_receiveErrorModel = em;
}

.AddAttribute ("ReceiveErrorModel",
"Model kesalahan penerima digunakan untuk mensimulasikan kehilangan paket",
Nilai Penunjuk (),
MakePointerAccessor (&PointToPointNetDevice::m_receiveErrorModel),
MakePointerChecker ())

tegak lurus Ke itu System
void PointToPointNetDevice::Receive (Ptr paket)
{
NS_LOG_FUNCTION (paket << ini);
protokol uint16_t = 0;

jika (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (paket) )
{
//
// Jika kita memiliki model kesalahan dan ini menunjukkan bahwa sudah saatnya kehilangan a
// paket rusak, jangan teruskan paket ini, biarkan saja.
//
m_dropTrace (paket);
}
lain
{
//
// Tekan hook terima jejak, lepaskan header protokol point-to-point
// dan teruskan paket ini ke tumpukan 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);
}
}
}

membuat Null fungsional Naskah
/* model-kesalahan-sederhana.cc */

// Model kesalahan
// Kami ingin menambahkan model kesalahan ke NetDevice node 3
// Kita bisa mendapatkan pegangan ke NetDevice melalui saluran dan node
// pointer
Ptr nd3 = PointToPointTopology::GetNetDevice
(n3, saluran2);
Ptr em = Buat ();
nd3->SetReceiveErrorModel (em);

bool
ErrorModel::DoCorrupt (Paket& p)
{
NS_LOG_FUNCTION;
NS_LOG_UNCOND("Rusak!");
return false;
}

Pada titik ini, kita dapat menjalankan program dengan ErrorModel sepele kita yang dimasukkan ke dalam penerima
jalur PointToPointNetDevice. Itu mencetak string "Rusak!" untuk setiap paket
diterima di simpul n3. Selanjutnya, kita kembali ke model kesalahan untuk menambahkan subkelas yang berfungsi
pemodelan kesalahan yang lebih menarik.

Add a Subkelas
ErrorModel kelas dasar sepele tidak melakukan sesuatu yang menarik, tetapi menyediakan a
antarmuka kelas dasar yang berguna (Corrupt () dan Reset ()), diteruskan ke fungsi virtual itu
dapat disubklasifikasikan. Selanjutnya mari kita pertimbangkan apa yang kita sebut BasicErrorModel yang menjadi dasarnya
itu ns-2 Kelas ErrorModel (dalam ns-2/antrian/errmodel.{cc,h}).

Properti apa yang kita inginkan untuk dimiliki, dari perspektif antarmuka pengguna? Kami ingin
bagi pengguna untuk dapat dengan mudah menukar jenis ErrorModel yang digunakan dalam
NetDevice. Kami juga ingin kemampuan untuk mengatur parameter yang dapat dikonfigurasi.

Berikut adalah beberapa persyaratan sederhana yang akan kami pertimbangkan:

· Kemampuan untuk mengatur variabel acak yang mengatur kerugian (standarnya adalah UniformVariable)

· Kemampuan untuk mengatur unit (bit, byte, paket, waktu) perincian di mana kesalahan terjadi
terapan.

· Kemampuan untuk mengatur tingkat kesalahan (misalnya 10^-3) sesuai dengan unit di atas
perincian.

· Kemampuan untuk mengaktifkan / menonaktifkan (default diaktifkan)

Seterpercayaapakah Olymp Trade? Kesimpulan untuk Subkelas
Kami mendeklarasikan BasicErrorModel menjadi subclass dari ErrorModel sebagai berikut,:

kelas BasicErrorModel : ErrorModel publik
{
publik:
static TypeId GetTypeId (batal);
...
pribadi:
// Menerapkan fungsi virtual murni kelas dasar
virtual bool DoCorrupt (Ptr P);
virtual bool DoReset (batal);
...
}

dan konfigurasikan fungsi GetTypeId subkelas dengan menyetel string TypeId unik dan
menyetel Induk ke ErrorModel:

TypeId RateErrorModel::GetTypeId (batal)
{
statis TypeId tid = TypeId ("ns3::RateErrorModel")
.SetParent ()
.AddConstructor ()
...

Membangun Core Fungsi dan Satuan Tes
Tegas Macro
Writing Satuan Tes
Menambahkan a New Modul untuk ns-3
Ketika Anda telah membuat grup kelas, contoh, dan tes terkait, mereka bisa
digabungkan menjadi satu ns-3 modul sehingga mereka dapat digunakan dengan yang ada ns-3 modul
dan oleh peneliti lainnya.

Bab ini memandu Anda melalui langkah-langkah yang diperlukan untuk menambahkan modul baru ns-3.

Langkah 0 - Modul tata ruang
Semua modul dapat ditemukan di src direktori. Setiap modul dapat ditemukan di direktori
yang memiliki nama yang sama dengan modul. Misalnya, spektrum modul dapat ditemukan di sini:
src/spektrum. Kami akan mengutip dari spektrum modul untuk ilustrasi.

Modul prototipe memiliki struktur direktori berikut dan file yang diperlukan:

src /
nama-modul/
binding/
dokter/
contoh/
wscript.dll
pembantu/
model/
uji/
contoh-untuk-run.py
wscript.dll

Tidak semua direktori akan hadir di setiap modul.

Langkah 1 - membuat a Modul Kerangka
Program python disediakan di direktori sumber yang akan membuat kerangka baru
modul. Untuk keperluan diskusi ini, kami akan menganggap bahwa modul baru Anda telah dipanggil
modul baru. Dari src direktori, lakukan hal berikut untuk membuat modul baru:

$ ./create-module.py modul baru

Selanjutnya, cd ke modul baru; Anda akan menemukan tata letak direktori ini:

$ cd modul baru
$ l
doc contoh tes model helper wscript

Secara lebih rinci, buat-modul.py skrip akan membuat direktori serta inisial
kerangka wscript.dll, .h, Cc. dan . pertama file. Modul lengkap dengan file kerangka terlihat
seperti ini:

src /
modul-baru/
dokter/
modul-baru.pertama
contoh/
modul-baru-contoh.cc
wscript.dll
pembantu/
modul-baru-helper.cc
modul-baru-helper.h
model/
modul-baru.cc
modul-baru.h
uji/
modul-baru-test-suite.cc
wscript.dll

(Jika diperlukan binding/ direktori yang terdaftar di Langkah-0 akan dibuat secara otomatis selama
bangunan.)

Kami selanjutnya akan membahas cara menyesuaikan modul ini. Menginformasikan WAF tentang file yang
membuat modul Anda dilakukan dengan mengedit keduanya wscript.dll file. Kami akan berjalan melalui
langkah utama dalam bab ini.

Semua ns-3 modul tergantung pada inti modul dan biasanya pada modul lainnya. Ketergantungan ini
ditentukan dalam wscript.dll file (di tingkat atas modul, bukan yang terpisah wscript.dll
file di contoh direktori!). Di kerangka wscript.dll panggilan yang akan mendeklarasikan Anda
modul baru ke WAF akan terlihat seperti ini (sebelum diedit):

def membangun(bld):
modul = bld.create_ns3_module('modul-baru', ['inti'])

Mari kita asumsikan itu modul baru tergantung pada Internet, mobilitas, dan aodv modul. Setelah
mengeditnya wscript.dll File akan terlihat seperti:

def membangun(bld):
modul = bld.create_ns3_module('modul-baru', ['internet', 'mobilitas', 'aodv'])

Perhatikan bahwa hanya dependensi modul tingkat pertama yang harus dicantumkan, itulah sebabnya kami menghapusnya
inti; itu Internet modul pada gilirannya tergantung pada inti.

Modul Anda kemungkinan besar akan memiliki file sumber model. Kerangka awal (yang akan
kompilasi berhasil) dibuat di model/modul-baru.cc dan model/baru-modul.h.

Jika modul Anda akan memiliki file sumber pembantu, maka mereka akan masuk ke pembantu/
direktori; sekali lagi, kerangka awal dibuat di direktori itu.

Akhirnya, merupakan praktik yang baik untuk menulis tes dan contoh. Ini hampir pasti
diperlukan untuk modul baru untuk diterima menjadi resmi ns-3 pohon sumber. Sebuah tengkorak
test suite dan test case dibuat di uji/ direktori. Rangkaian uji kerangka akan
berisi konstruktor di bawah ini, yang mendeklarasikan pengujian unit baru bernama modul baru, Dengan
kasus uji tunggal yang terdiri dari kelas NewModuleTestCase1:

NewModuleTestSuite::NewModuleTestSuite ()
: TestSuite ("modul baru", UNIT)
{
AddTestCase (NewModuleTestCase1 baru);
}

Langkah 3 - Menyatakan sumber File
File header dan kode sumber publik untuk modul baru Anda harus ditentukan dalam
wscript.dll file dengan memodifikasinya dengan editor teks Anda.

Sebagai contoh, setelah mendeklarasikan spektrum modul, src/spektrum/wscript menentukan
file kode sumber dengan daftar berikut:

def membangun(bld):

modul = bld.create_ns3_module('spektrum', ['internet', 'propagasi', 'antena', 'aplikasi'])

modul.sumber = [
'model/spektrum-model.cc',
'model/spektrum-nilai.cc',
.
.
.
'model/microwave-oven-spectrum-value-helper.cc',
'pembantu/spektrum-pembantu.cc',
'helper/adhoc-aloha-noack-ideal-phy-helper.cc',
'helper/waveform-generator-helper.cc',
'helper/spectrum-analyzer-helper.cc',
]

Objek yang dihasilkan dari kompilasi sumber-sumber ini akan dirangkai menjadi pustaka tautan,
yang akan ditautkan ke program apa pun yang mengandalkan modul ini.

Tetapi bagaimana program semacam itu mempelajari API publik dari modul baru kami? Baca terus!

Langkah 4 - Menyatakan Publik Header File
File header yang mendefinisikan API publik model Anda dan pembantu juga harus
ditentukan dalam wscript.dll file.

Melanjutkan dengan spektrum ilustrasi model, file header publik ditentukan
dengan bait berikut. (Perhatikan bahwa argumen ke gedung fungsi memberitahu WAF untuk
pasang header modul ini dengan yang lain ns-3 tajuk):

tajuk = bld(fitur='ns3header')

headers.module = 'spektrum'

headers.sumber = [
'model/spektrum-model.h',
'model/spektrum-nilai.h',
.
.
.
'model/microwave-oven-spectrum-value-helper.h',
'pembantu/spektrum-pembantu.h',
'helper/adhoc-aloha-noack-ideal-phy-helper.h',
'helper/waveform-generator-helper.h',
'helper/spectrum-analyzer-helper.h',
]

Tajuk yang dipublikasikan dengan cara ini akan dapat diakses oleh pengguna model Anda dengan penyertaan
pernyataan seperti

#sertakan "ns3/spectrum-model.h"

Tajuk yang digunakan secara ketat secara internal dalam penerapan Anda tidak boleh disertakan di sini. Mereka
masih dapat diakses oleh implementasi Anda dengan menyertakan pernyataan seperti

#sertakan "implementasi-modul-saya.h"

Langkah 5 - Menyatakan Tes
Jika modul baru Anda memiliki pengujian, maka modul tersebut harus ditentukan dalam file wscript.dll file oleh
memodifikasinya dengan editor teks Anda.

spektrum tes model ditentukan dengan bait berikut:

module_test = bld.create_ns3_module_test_library('spektrum')

module_test.sumber = [
'test/spectrum-interference-test.cc',
'test/spectrum-value-test.cc',
]

Lihat Tes untuk informasi lebih lanjut tentang cara menulis test case.

Langkah 6 - Menyatakan contoh
Jika modul baru Anda memiliki contoh, maka itu harus ditentukan dalam file Anda contoh/skrip
mengajukan. (Tingkat atas kerangka wscript.dll rekursif akan termasuk contoh/skrip hanya jika
contoh diaktifkan pada waktu konfigurasi.)

spektrum model mendefinisikan contoh pertama di src/spektrum/contoh/wscript dengan

def membangun(bld):
obj = bld.create_ns3_program('adhoc-aloha-ideal-phy',
['spektrum', 'mobilitas'])
obj.source = 'adhoc-aloha-ideal-phy.cc'

Perhatikan bahwa argumen kedua untuk fungsi tersebut buat_ns3_program() adalah daftar modul
bahwa program yang dibuat bergantung pada; sekali lagi, jangan lupa sertakan modul baru in
Daftar. Ini praktik terbaik untuk mencantumkan hanya dependensi modul langsung, dan biarkan WAF
menyimpulkan pohon ketergantungan penuh.

Kadang-kadang, untuk kejelasan, Anda mungkin ingin membagi implementasi untuk contoh Anda di antara
beberapa file sumber. Dalam hal ini, sertakan saja file tersebut sebagai tambahan eksplisit
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 pemanggilan fungsi berikut. Perhatikan bahwa yang kedua
argumen untuk fungsi daftar_ns3_script() adalah daftar modul yang dimiliki Python
contoh tergantung pada:

bld.register_ns3_script('new-module-example.py', ['new-module'])

Langkah 7 - contoh Run as Tes
Selain menjalankan kode pengujian eksplisit, kerangka pengujian juga dapat diinstrumentasi
jalankan program contoh lengkap untuk mencoba menangkap regresi dalam contoh. Namun, tidak semuanya
contoh cocok untuk uji regresi. Berkas test/contoh-untuk-menjalankan.py mengontrol
pemanggilan contoh saat kerangka uji dijalankan.

spektrum contoh model dijalankan oleh tes.py ditentukan dalam
src/spectrum/test/examples-to-run.py menggunakan dua daftar berikut C++ dan Python
contoh:

# Daftar contoh C++ untuk dijalankan untuk memastikan bahwa mereka tetap ada
# dapat dibangun dan dijalankan dari waktu ke waktu. Setiap tuple dalam daftar berisi
#
# (nama_contoh, do_run, do_valgrind_run).
#
# Lihat test.py untuk informasi lebih lanjut.
cpp_contoh = [
("adhoc-aloha-ideal-phy", "Benar", "Benar"),
("adhoc-aloha-ideal-phy-with-microwave-oven", "Benar", "Benar"),
("adhoc-aloha-ideal-phy-matrix-propagation-loss-model", "Benar", "Benar"),
]

# Daftar contoh Python untuk dijalankan untuk memastikan bahwa mereka tetap ada
# dapat dijalankan dari waktu ke waktu. Setiap tuple dalam daftar berisi
#
# (nama_contoh, do_run).
#
# Lihat test.py untuk informasi lebih lanjut.
python_contoh = [
("sample-simulator.py", "Benar"),
]

Seperti yang ditunjukkan dalam komentar, setiap entri dalam daftar contoh C++ untuk dijalankan berisi
tupel (nama_contoh, lakukan_lari, lakukan_valgrind_run), Di mana

· contoh_nama adalah executable yang akan dijalankan,

· lakukan_lari adalah kondisi untuk menjalankan contoh, dan

· lakukan_valgrind_run adalah kondisi untuk menjalankan contoh di bawah valgrind. (Ini
diperlukan karena NSC menyebabkan instruksi ilegal macet dengan beberapa tes ketika mereka
dijalankan di bawah valgrind.)

Perhatikan bahwa kedua kondisi tersebut adalah pernyataan Python yang dapat diandalkan WAF konfigurasi
variabel. Misalnya,

("tcp-nsc-lfn", "NSC_ENABLED == Benar", "NSC_ENABLED == Salah"),

Setiap entri dalam daftar contoh Python untuk dijalankan berisi tuple (nama_contoh,
lakukan_lari), di mana, untuk contoh C++,

· contoh_nama adalah skrip Python yang akan dijalankan, dan

· lakukan_lari adalah kondisi untuk menjalankan contoh.

Sekali lagi, kondisinya adalah pernyataan Python yang dapat diandalkan WAF variabel konfigurasi.
Sebagai contoh,

("realtime-udp-echo.py", "ENABLE_REAL_TIME == Salah"),

Langkah 8 - Konfigurasi dan Membangun
Anda sekarang dapat mengonfigurasi, membangun, dan menguji modul Anda seperti biasa. Anda harus mengkonfigurasi ulang
proyek sebagai langkah awal sehingga WAF menyimpan informasi baru di cache Anda wscript.dll file, atau
jika tidak, modul baru Anda tidak akan disertakan dalam build.

$ ./waf konfigurasikan --enable-examples --enable-tests
$ ./waf membangun
$ ./test.py

Cari test suite modul baru Anda (dan program contoh, jika modul Anda memilikinya
diaktifkan) dalam output pengujian.

Langkah 9 - Ular sanca Bindings
Menambahkan binding Python ke modul Anda adalah opsional, dan langkahnya dikomentari oleh
bawaan di buat-modul.py Script.

# bld.ns3_python_bindings()

Jika Anda ingin menyertakan binding Python (diperlukan hanya jika Anda ingin menulis Python ns-3
program alih-alih program C++ ns-3), Anda harus menghapus komentar di atas dan menginstal
Sistem pemindaian API Python (dibahas di tempat lain dalam manual ini) dan pindai modul Anda ke
menghasilkan ikatan baru.

membuat Dokumentasi
ns-3 memasok dua jenis dokumentasi: bab gaya "panduan pengguna" ekspositori, dan
dokumentasi API kode sumber.

Bab "panduan pengguna" ditulis dengan tangan reStructuredText format (. pertama), yang mana
diproses oleh sistem dokumentasi Python Orang yg merahasiakan pendapatnya untuk menghasilkan halaman web dan file pdf.
Dokumentasi API dihasilkan dari kode sumber itu sendiri, menggunakan Doksigen, untuk menghasilkan
halaman web yang terhubung silang. Keduanya penting: bab Sphinx menjelaskan mengapa
dan ikhtisar penggunaan model; dokumentasi API menjelaskan bagaimana rincian.

Bab ini memberikan ikhtisar singkat tentang alat ini, menekankan penggunaan pilihan dan
kustomisasi untuk ns-3.

Untuk membangun semua dokumentasi standar:

$ ./waf dokumen

Untuk opsi yang lebih khusus, baca terus.

Mendokumentasikan dengan Orang yg merahasiakan pendapatnya
Kami menggunakan Orang yg merahasiakan pendapatnya untuk menghasilkan bab ekspositori yang menjelaskan desain dan penggunaan masing-masing
modul. Saat ini Anda sedang membaca Dokumentasi Bab. Itu Tampilan sumber link dalam
sidebar akan menampilkan sumber reStructuredText untuk bab ini.

Menambahkan New bab
Menambahkan bab baru membutuhkan tiga langkah (dijelaskan lebih detail di bawah):

1. Memilih Dimana? file dokumentasi akan aktif.

2. Link dari halaman yang ada ke dokumentasi baru.

3. Tambahkan file baru ke Makefile.

Dimana?
Dokumentasi untuk modul tertentu, foo, biasanya harus masuk src/foo/doc/. Sebagai contoh
src/foo/doc/foo.rst akan menjadi dokumen tingkat atas untuk modul. Itu
src/buat-module.py skrip akan membuat file ini untuk Anda.

Beberapa model memerlukan beberapa . pertama file, dan angka; ini semua harus masuk
src/foo/doc/ direktori. Dokumen sebenarnya dibuat oleh Sphinx Makefile. Untuk khususnya
dokumentasi yang terlibat, mungkin berguna untuk memiliki lokal Makefile dalam src/foo/doc/
direktori untuk menyederhanakan pembuatan dokumentasi untuk modul ini (Antena adalah sebuah contoh).
Menyiapkan ini tidak terlalu sulit, tetapi berada di luar cakupan bab ini.

Dalam beberapa kasus, dokumentasi mencakup beberapa model; itu jaringan bab adalah contohnya. Di dalam
kasus ini menambahkan . pertama file langsung ke doc/model/sumber/ mungkin tepat.

Link
Sphinx harus tahu dimana bab baru Anda akan muncul. Dalam kebanyakan kasus, model baru
bab akan muncul di Model buku. Untuk menambahkan bab Anda di sana, edit
doc/models/source/index.rst

.. toktree::
:kedalaman maksimum: 1

organisasi
animasi
antena
aodv
aplikasi
...

Tambahkan nama dokumen Anda (tanpa . pertama ekstensi) ke daftar ini. Harap simpan
Buat model bab dalam urutan abjad, untuk memudahkan pemindaian visual untuk bab tertentu.

Makefile
Anda juga harus menambahkan dokumen Anda ke yang sesuai Makefile, sehingga membuat tahu untuk memeriksanya
untuk pembaruan. Buku Model Makefile adalah doc/model/Makefile, Buku Manual Makefile adalah
doc/manual/Makefile.

# cantumkan semua file .pertama pustaka model yang perlu disalin ke $SOURCETEMP
SUMBER = \
sumber/conf.py \
sumber/_statis \
sumber/indeks.rst \
sumber/ganti.txt \
sumber/organisasi.rst \
...
$(SRC)/antena/doc/source/antena.rst \
...

Anda menambahkan Anda . pertama file ke SUMBER variabel. Untuk menambahkan angka, baca komentar di
Makefile untuk melihat variabel mana yang harus berisi file gambar Anda. Sekali lagi, tolong simpan ini
dalam urutan abjad.

Bangunan Orang yg merahasiakan pendapatnya Dokumen
Membuat dokumentasi Sphinx cukup sederhana. Untuk membangun semua Sphinx
dokumentasi:

$ ./waf sphinx

Untuk membuat dokumentasi Model saja:

$ make -C dokumen/model

Untuk melihat dokumentasi yang dihasilkan, arahkan browser Anda ke doc/models/build/html.

Seperti yang Anda lihat, Sphinx menggunakan Make untuk memandu prosesnya. Target default membangun semua
bentuk output yang diaktifkan, yang di ns-3 adalah multi-halaman html, halaman tunggal html tunggal, dan
pdf (getah). Untuk membuat html multi-halaman saja, Anda menambahkan html target:

$ make -C doc/model html

Ini dapat berguna untuk mengurangi waktu pembuatan (dan ukuran obrolan pembuatan) seperti Anda
sedang menulis bab Anda.

Sebelum melakukan dokumentasi Anda ke repo, harap periksa apakah itu dibangun tanpa
kesalahan atau peringatan. Proses build menghasilkan banyak output (kebanyakan obrolan normal
dari LaTeX), yang dapat mempersulit untuk melihat apakah ada peringatan Sphinx atau
kesalahan. Untuk menemukan peringatan dan kesalahan penting, buat saja html versi, lalu cari
log build untuk peringatan or kesalahan.

ns-3 Pokok-pokok
Sphinx dokumentasi dan tutorial cukup bagus. Kami tidak akan menduplikasi dasar-dasarnya
di sini, alih-alih berfokus pada penggunaan yang disukai untuk ns-3.

· Mulai dokumen dengan dua baris ini:

.. termasuk:: ganti.txt
.. sorot :: cpp

Baris pertama memungkinkan beberapa penggantian sederhana. Misalnya mengetik |ns3| merender sebagai
ns-3. Yang kedua menetapkan kode sumber default yang menyoroti bahasa secara eksplisit untuk
file, karena tebakan parser tidak selalu akurat. (Ini juga memungkinkan untuk mengatur
bahasa secara eksplisit untuk satu blok kode, lihat di bawah.)

· Bagian:

Sphinx cukup liberal dalam menandai judul bagian. Secara konvensi, kami lebih suka ini
hirarki:

.. hierarki tajuk:
------------- Bab
************* Bagian (#.#)
============= Ayat (#.#.#)
############# Sub-subbab

· Penyorotan Sintaks:

Untuk menggunakan penyorot sintaks default, cukup mulai blok kode sumber:

┌─ans──── tekstariran──── teks─ aciksach XNUMXirim "XNUMXX" "" XNUMXirim XNUMXirim XNUMXirim XNUMXirim "" XNUMXirim XNUMXirim XNUMXans XNUMXansansans XNUMX XNUMX Chollans XNUMX XNUMX XNUMX XNUMX XNUMX Chsans XNUMX Chsans XNUMXootoot Miss─ ─ "dengan ─ ilangan ───────────────────────────────┐
│Sumber Sphinx │ Keluaran yang Diberikan │
├─ans──── tekstariran──── tekstariran bing m haronggol uranding "" "" "" XNUMXirim XNUMXirim XNUMXansansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMXss pulangeseseseses XNUMX XNUMXya acbumANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANyap ───────────────────────────────┤
│ │ Itu Frobnitz diakses oleh: │
│ ``Frobnitz`` diakses oleh:: │ │
│ │ Foo::Frobnitz frob; │
│ Foo::Frobnitz frob; │ frob.Set (...); │
│ frob.Set (...); │ │
└─ans──── tekstariran──── tekstariran bing m haronggol uranding "" "" "" XNUMXirim XNUMXirim XNUMXansansansans XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMX XNUMXss pulangeseseseses XNUMX XNUMXya acbumANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANANyap ───────────────────────────────┘

Untuk menggunakan penyorot sintaks tertentu, misalnya, menampar perintah cangkang:

┌─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Chocanding "" "XNUMXirim XNUMXirim XNUMX Chollans XNUMX XNUMX XNUMX XNUMX XNUMX Chsans XNUMX Chsans XNUMX Chs Chs XNUMXX XNUMX Choc XNUMXX XNUMX Choll XNUMX Choll XNUMX Chs XNUMX Chs XNUMXX XNUMX Chack XNUMX Chsmoc olakkan ilangan uas tolasanasanasanasanaskan ───┐
│Sumber Sphinx │ Keluaran yang Diberikan │
├─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Chocanding "" "XNUMXirim XNUMXirim XNUMX Chollans XNUMX XNUMX XNUMX XNUMX XNUMX Chsans XNUMX Chsans XNUMX Chs Chs XNUMXX XNUMX Choc XNUMXX XNUMX Choll XNUMX Choll XNUMX Chs XNUMX Chs XNUMXX XNUMX Chack XNUMX Chsmoc olakkan ilangan uas tolasanasanasanasanaskan ───┤
│ │ │.
│ .. kode sumber:: bash │ $ ls │
│ │ │.
│ $ ls │ │
└─ans───── Chasan XNUMX Choll XNUMX Choll XNUMXX XNUMX Chocanding "" "XNUMXirim XNUMXirim XNUMX Chollans XNUMX XNUMX XNUMX XNUMX XNUMX Chsans XNUMX Chsans XNUMX Chs Chs XNUMXX XNUMX Choc XNUMXX XNUMX Choll XNUMX Choll XNUMX Chs XNUMX Chs XNUMXX XNUMX Chack XNUMX Chsmoc olakkan ilangan uas tolasanasanasanasanaskan ───┘

· Notasi Singkatan:

Singkatan ini didefinisikan:

┌────────────────────────┬───────────────┐
│Sumber Sphinx │ Keluaran yang Diberikan │
}
│ │. ns-3
│ |ns3| │ │
}
│ │. ns-2
│ |ns2| │ │
}
│ │ │.
│ |periksa| │ │
}
│ │. RFC 6282
│ :rfc:`6282` │ │
}

Mendokumentasikan dengan Doksigen
Kami menggunakan Doksigen untuk menghasilkan dapat dijelajahi dokumentasi API. Doxygen menyediakan sejumlah
fitur yang berguna:

· Tabel ringkasan semua anggota kelas.

· Grafik pewarisan dan kolaborasi untuk semua kelas.

· Tautan ke kode sumber yang mengimplementasikan setiap fungsi.

· Tautan ke setiap tempat anggota digunakan.

· Tautan ke setiap objek yang digunakan dalam mengimplementasikan suatu fungsi.

· Pengelompokan kelas terkait, seperti semua kelas yang terkait dengan protokol tertentu.

Selain itu, kami menggunakan TypeId sistem untuk menambah dokumentasi untuk setiap kelas

· Itu config jalur dimana objek tersebut dapat dicapai.

· Dokumentasi untuk apapun atribut, termasuk atribut didefinisikan dalam kelas induk.

· Dokumentasi untuk apapun Jejak sumber yang ditentukan oleh kelas.

Doxygen beroperasi dengan memindai kode sumber, mencari komentar yang ditandai secara khusus. Dia
juga membuat referensi silang, menunjukkan dimana setiap file, kelas, metode, dan variabel
bekas.

disukai Gaya
Gaya yang disukai untuk komentar Doxygen adalah gaya JavaDoc:

/ **
* Deskripsi singkat tentang kelas atau metode ini.
* Baris yang berdekatan menjadi satu paragraf.
*
* Deskripsi yang lebih panjang, dengan banyak detail.
*
* Baris kosong memisahkan paragraf.
*
* Jelaskan apa yang dilakukan kelas atau metode, menggunakan algoritma apa.
* Jelaskan unit argumen dan mengembalikan nilai.
*
* \note Catat batasan atau kesalahan apa pun.
*
* (Untuk fungsi dengan argumen atau nilai kembalian :)
* \param foo Frasa kata benda singkat yang menjelaskan argumen ini.
* \param bar Catatan Kasus kalimat, dan periode akhir.
* \return Frasa kata benda singkat yang menjelaskan nilai.
*
* \internal
*
* Anda juga dapat mendiskusikan detail implementasi internal.
* Memahami materi ini tidak harus menggunakan
* kelas atau metode.
*/
kelas Contoh

Dalam gaya ini blok komentar Doxygen dimulai dengan dua karakter `*': / **, dan mendahului
barang yang didokumentasikan.

Untuk barang-barang yang hanya membutuhkan deskripsi singkat, salah satu dari formulir singkat ini sesuai:

/** Implementasi destruktor. */
batal DoDispose ();

int m_hitung; //!< Hitungan ...

Perhatikan bentuk khusus komentar akhir baris, //!, menunjukkan bahwa itu mengacu pada
mendahului barang.

Beberapa hal yang perlu diperhatikan:

· Gunakan kapitalisasi kalimat, termasuk modal awal.

· Gunakan tanda baca, khususnya `.' di akhir kalimat atau frase.

· Itu \singkat tag tidak diperlukan; kalimat pertama akan digunakan sebagai brief
deskripsi.

Setiap kelas, metode, typedef, variabel anggota, argumen fungsi, dan nilai pengembalian harus
didokumentasikan di semua file kode sumber yang membentuk API formal dan implementasinya
ns-3, Seperti src/ /model/*, src/ /pembantu/* dan src/ / util / *.
Dokumentasi untuk barang-barang di src/ /tes/* dan src/ /contoh/* lebih disukai,
tetapi tidak diharuskan.

Berguna Fitur
· Anggota yang diwariskan akan secara otomatis mewarisi dokumen dari induknya, (tetapi dapat diganti
oleh dokumentasi lokal).

1. Dokumentasikan kelas dasar.

2. Di sub class tandai fungsi yang diwariskan dengan komentar biasa:

// Metode yang diwariskan
kekosongan virtual FooBar (batal);
int virtual BarFoo (baz ganda);

Perhatikan bahwa tanda tangan harus sama persis, jadi sertakan argumen formal (ruang kosong)

Ini tidak berfungsi untuk fungsi statis; melihat DapatkanTypeId, di bawah, sebagai contoh.

Bangunan Doksigen Dokumen
Membuat dokumentasi Doxygen cukup sederhana:

$ ./waf doksigen

Build ini menggunakan konfigurasi default, yang menghasilkan bagian dokumentasi untuk
semua item, bahkan jika mereka tidak memiliki blok dokumentasi komentar eksplisit. Ini memiliki
efek menekan peringatan untuk item yang tidak berdokumen, tetapi memastikan semuanya muncul
dalam output yang dihasilkan.

Saat menulis dokumentasi, seringkali lebih berguna untuk melihat item mana yang dihasilkan
peringatan, biasanya tentang dokumentasi yang hilang. Untuk melihat daftar peringatan lengkap, gunakan
doc/doxygen.warnings.report.sh naskah:

$ doc/doxygen.warnings.report.sh
Waf: Memasuki direktori `build'
...
Waf: Meninggalkan direktori `build'
'membangun' selesai dengan sukses (3m24.094s)

Membangun kembali dokumen doksigen dengan kesalahan penuh...Selesai.

Laporan peringatan Doksigen
----------------------------------------

(Semua hitungan adalah batas bawah.)

Peringatan berdasarkan modul/direktori:

Direktori Hitung
----- ----------------------------------
3844 src/lte/model
1718 src/wimax/model
1423 src/inti/model
....
138 parameter tidak berdokumen tambahan.
----------------------------------------
15765 total peringatan
126 direktori dengan peringatan

Peringatan menurut file (berdasarkan abjad)

Hitung File
----- ----------------------------------
17 dok/introspeksi-doxygen.h
15 contoh/routing/manet-routing-compare.cc
26 contoh/stat/wifi-contoh-aplikasi.h
....
----------------------------------------
967 file dengan peringatan

Peringatan berdasarkan file (numerik)

Hitung File
----- ----------------------------------
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 file dengan peringatan

Ringkasan Peringatan Doksigen
----------------------------------------
126 direktori
967 file
15765 peringatan

Skrip memodifikasi konfigurasi untuk menampilkan semua peringatan, dan untuk mempersingkat waktu proses.
Seperti yang Anda lihat, pada tulisan ini kita punya a banyak dari barang-barang yang tidak berdokumen. Laporan
merangkum peringatan berdasarkan modul src/*/*, dan berdasarkan file, dalam urutan abjad dan numerik.

Skrip memiliki beberapa opsi untuk mengurangi dan membuatnya lebih mudah dikelola. Untuk bantuan,
gunakan -h pilihan. Setelah menjalankannya sekali untuk melakukan build Doxygen dan menghasilkan penuh
log peringatan, Anda dapat memproses ulang file log dengan berbagai "filter", tanpa harus melakukannya
build Doxygen lengkap, sekali lagi menggunakan -s pilihan. Anda dapat mengecualikan peringatan dari
*/contoh/* file (-e pilihan), dan/atau */tes/* file (-t).

Mungkin opsi yang paling berguna saat menulis komentar dokumentasi adalah -m , yang
akan membatasi laporan hanya untuk pencocokan file src/ /*, dan ikuti laporan dengan
garis peringatan yang sebenarnya. Gabungkan dengan eth dan Anda dapat fokus pada peringatan yang ada
paling mendesak dalam satu modul:

$ doc/doxygen.warnings.report.sh -m mesh/helper
...
Ringkasan Peringatan Doksigen
----------------------------------------
1 direktori
3 file
149 peringatan

Peringatan yang Difilter
========================
src/mesh/helper/dot11s/dot11s-installer.h:72: peringatan: Anggota m_root (variabel) kelas ns3::Dot11sStack tidak didokumentasikan.
src/mesh/helper/dot11s/dot11s-installer.h:35: peringatan: kembalikan jenis anggota ns3::Dot11sStack::GetTypeId tidak didokumentasikan
src/mesh/helper/dot11s/dot11s-installer.h:56: peringatan: kembalikan jenis anggota ns3::Dot11sStack::InstallStack tidak didokumentasikan
src/mesh/helper/flame/lfame-installer.h:40: peringatan: Anggota GetTypeId() (fungsi) kelas ns3::FlameStack tidak didokumentasikan.
src/mesh/helper/flame/flame-installer.h:60: peringatan: tipe pengembalian anggota ns3::FlameStack::InstallStack tidak didokumentasikan
src/mesh/helper/mesh-helper.h:213: peringatan: Anggota m_nInterfaces (variabel) kelas ns3::MeshHelper tidak didokumentasikan.
src/mesh/helper/mesh-helper.h:214: peringatan: Anggota m_spreadChannelPolicy (variabel) kelas ns3::MeshHelper tidak didokumentasikan.
src/mesh/helper/mesh-helper.h:215: peringatan: Anggota m_stack (variabel) dari kelas ns3::MeshHelper tidak didokumentasikan.
src/mesh/helper/mesh-helper.h:216: peringatan: Anggota m_stackFactory (variabel) kelas ns3::MeshHelper tidak didokumentasikan.
src/mesh/helper/mesh-helper.h:209: peringatan: parameter anggota ns3::MeshHelper::CreateInterface tidak (semua) didokumentasikan
src/mesh/helper/mesh-helper.h:119: peringatan: parameter anggota ns3::MeshHelper::SetStandard tidak (semua) didokumentasikan

Sekarang tinggal memahami kodenya, dan menulis beberapa dokumen!

ns-3 Pokok-pokok
Adapun Sphinx, Doxygen docs dan referensi cukup bagus. Kami tidak akan menduplikasi
dasar-dasar di sini, alih-alih berfokus pada penggunaan yang disukai untuk ns-3.

· Gunakan Doksigen Modul untuk mengelompokkan item terkait.

Di header utama modul, buat grup Doxgyen:

/ **
* \defgroup protokol foo Foo.
*/

Tandai setiap kelas terkait sebagai milik grup:

/ **
* \inggroup
*
* Jenis paket Foo.
*/
kelas Foo

· Tahukah kamu typedef dapat memiliki argumen formal? Ini memungkinkan dokumentasi fungsi
tanda tangan penunjuk:

/ **
* Tanda tangan fungsi panggilan balik bar.
*
* \param ale Seukuran pint ale, dalam Imperial ounces.
*/
typedef batal (* BarCallback)(const int ale);

· Salin Atribut membantu string dari DapatkanTypeId metode untuk digunakan sebagai ringkasan
penjelasan anggota terkait.

· \bugid{298} akan membuat tautan ke bug 298 di Bugzilla kami.

· \pnama{foo} dalam deskripsi akan format foo sebagai \param foo parameter, membuatnya jelas
bahwa Anda mengacu pada argumen yang sebenarnya.

· \RFC{301} akan membuat tautan ke RFC 301.

· \intern harus digunakan hanya untuk memicu diskusi tentang detail implementasi, bukan untuk
tanda swasta fungsi (mereka sudah ditandai, sebagai swasta!)

· Jangan membuat kelas dengan nama yang sepele, seperti kelas A, bahkan di ruang uji. Ini
menyebabkan semua instance dari nama kelas literal `A' dirender sebagai tautan.

Seperti disebutkan di atas, fungsi statis tidak mewarisi dokumentasi dari fungsi yang sama
kelas induk. ns-3 menggunakan beberapa fungsi statis di mana-mana; yang disarankan
blok dokumentasi untuk kasus ini adalah:

· Konstruktor/destruktor default:

Kelasku (); //!< Konstruktor bawaan
~KelasSaya (); //!< Penghancur

· Dummy destructor dan DoDispose:

/** Penghancur dummy, lihat DoDispose. */
~KelasSaya ();

/** Implementasi destruktor */
kekosongan virtual DoDispose ();

· DapatkanTypeId:

/ **
* Daftarkan jenis ini.
* \return Objek TypeId.
*/
static TypeId GetTypeId (batal);

Mengaktifkan himpunan bagian of ns-3 Modul
Seperti kebanyakan proyek perangkat lunak, ns-3 semakin berkembang dalam hal jumlah modul,
baris kode, dan jejak memori. Namun, pengguna hanya dapat menggunakan beberapa modul tersebut
pada suatu waktu. Untuk alasan ini, pengguna mungkin ingin mengaktifkan secara eksplisit hanya sebagian dari
mungkin ns-3 modul yang sebenarnya mereka butuhkan untuk penelitian mereka.

Bab ini membahas cara mengaktifkan hanya ns-3 modul yang Anda minati
menggunakan.

Seterpercayaapakah Olymp Trade? Kesimpulan untuk aktif a bagian of ns-3's modul
Jika pustaka bersama sedang dibangun, mengaktifkan modul akan menyebabkan setidaknya satu
perpustakaan yang akan dibangun:

libns3-modulename.so

Jika modul memiliki pustaka pengujian dan pustaka pengujian sedang dibuat, maka

libns3-modulename-test.so

akan dibangun juga. Modul lain tempat modul bergantung dan pustaka pengujiannya
juga akan dibangun.

Secara default, semua modul sudah terpasang ns-3. Ada dua cara untuk mengaktifkan subset ini
modul:

1. Menggunakan opsi --enable-modules waf

2. Menggunakan ns-3 file konfigurasi

Aktifkan modul menggunakan waf --aktifkan-modul Option
Untuk mengaktifkan hanya modul inti dengan contoh dan tes, misalnya, coba perintah berikut:

$ ./waf bersih
$ ./waf konfigurasikan --enable-examples --enable-tests --enable-modules=inti
$ ./waf membangun
$ cd membangun/men-debug/
$ l

dan perpustakaan berikut harus ada:

binding libns3-core.so ns3 utilitas awal
contoh libns3-core-test.so sampel src

Perhatikan ./melambai membersihkan langkah ini dilakukan di sini hanya untuk memperjelas pustaka modul mana
telah dibangun. Anda tidak perlu melakukannya ./melambai membersihkan untuk mengaktifkan subset modul.

Menjalankan test.py hanya akan menyebabkan pengujian yang bergantung pada inti modul untuk dijalankan:

24 dari 24 tes lulus (24 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Ulangi langkah-langkah di atas untuk modul "jaringan" alih-alih modul "inti", dan
berikut ini akan dibangun, karena jaringan bergantung pada inti:

binding libns3-core.so libns3-network.so ns3 utilitas awal
contoh libns3-core-test.so libns3-network-test.so sampel src

Menjalankan test.py akan menyebabkan pengujian yang hanya bergantung pada modul inti dan jaringan
dijalankan:

31 dari 31 tes lulus (31 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Aktifkan modul menggunakan itu ns-3 konfigurasi fillet
File konfigurasi, .ns3rc, telah ditambahkan ns-3 yang memungkinkan pengguna untuk menentukan yang mana
modul harus disertakan dalam build.

Saat mengaktifkan subset dari ns-3 modul, aturan diutamakan adalah sebagai berikut:

1. string --enable-modules configure menimpa file .ns3rc apa pun

2. file .ns3rc di tingkat atas ns-3 direktori selanjutnya dikonsultasikan, jika ada

3. sistem mencari ~/.ns3rc jika dua di atas tidak ditentukan

Jika tidak ada di atas yang membatasi modul yang akan dibangun, semua modul yang diketahui waf akan
dibangun.

Versi file .ns3rc yang dipertahankan di ns-3 repositori kode sumber berada di
itu utilitas direktori. Alasan untuk ini adalah jika berada di direktori tingkat atas dari
repositori, itu akan rentan terhadap checkin yang tidak disengaja dari pengelola yang mengaktifkan
modul yang ingin mereka gunakan. Oleh karena itu, pengguna perlu menyalin .ns3rc secara manual dari
utilitas direktori ke tempat pilihan mereka (direktori tingkat atas atau direktori home mereka) ke
aktifkan konfigurasi build modular persisten.

Dengan asumsi bahwa Anda berada di tingkat atas ns-3 direktori, Anda bisa mendapatkan salinan .ns3rc
file yang ada di utilitas direktori sebagai berikut:

$cp utils/.ns3rc .

File .ns3rc sekarang seharusnya berada di level teratas Anda ns-3 direktori, dan itu berisi
sebagai berikut:

#! /usr/bin/env ular sanca

# Daftar modul yang akan diaktifkan saat ns-3 dijalankan.
# Modul yang bergantung pada modul yang terdaftar juga akan diaktifkan.
#
# Semua modul dapat diaktifkan dengan memilih 'all_modules'.
modules_enabled = ['semua_modul']

# Tetapkan ini sama dengan benar jika Anda ingin contoh dijalankan.
example_enabled = Salah

# Tetapkan ini sama dengan benar jika Anda ingin tes dijalankan.
tes_diaktifkan = Salah

Gunakan editor favorit Anda untuk memodifikasi file .ns3rc agar hanya mengaktifkan modul inti
contoh dan tes seperti ini:

#! /usr/bin/env ular sanca

# Daftar modul yang akan diaktifkan saat ns-3 dijalankan.
# Modul yang bergantung pada modul yang terdaftar juga akan diaktifkan.
#
# Semua modul dapat diaktifkan dengan memilih 'all_modules'.
modules_enabled = ['inti']

# Tetapkan ini sama dengan benar jika Anda ingin contoh dijalankan.
example_enabled = Benar

# Tetapkan ini sama dengan benar jika Anda ingin tes dijalankan.
tes_diaktifkan = Benar

Hanya modul inti yang akan diaktifkan sekarang jika Anda mencoba perintah ini:

$ ./waf bersih
$ ./waf mengkonfigurasi
$ ./waf membangun
$ cd membangun/men-debug/
$ l

dan perpustakaan berikut harus ada:

binding libns3-core.so ns3 utilitas awal
contoh libns3-core-test.so sampel src

Perhatikan ./melambai membersihkan langkah ini dilakukan di sini hanya untuk memperjelas pustaka modul mana
telah dibangun. Anda tidak perlu melakukannya ./melambai membersihkan untuk mengaktifkan subset modul.

Menjalankan test.py hanya akan menyebabkan pengujian yang bergantung pada inti modul untuk dijalankan:

24 dari 24 tes lulus (24 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Ulangi langkah-langkah di atas untuk modul "jaringan" alih-alih modul "inti", dan
berikut ini akan dibangun, karena jaringan bergantung pada inti:

binding libns3-core.so libns3-network.so ns3 utilitas awal
contoh libns3-core-test.so libns3-network-test.so sampel src

Menjalankan test.py akan menyebabkan pengujian yang hanya bergantung pada modul inti dan jaringan
dijalankan:

31 dari 31 tes lulus (31 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Mengaktifkan/menonaktifkan ns-3 Tes dan contoh
ns-3 distribusi mencakup banyak contoh dan tes yang digunakan untuk memvalidasi ns-3
sistem. Namun, pengguna mungkin tidak selalu menginginkan contoh dan pengujian ini dijalankan untuk mereka
pemasangan ns-3.

Bab ini membahas cara membangun ns-3 dengan atau tanpa contoh dan tesnya.

Seterpercayaapakah Olymp Trade? Kesimpulan untuk aktifkan / nonaktifkan contoh dan tes in ns-3
Ada 3 cara untuk mengaktifkan/menonaktifkan contoh dan pengujian ns-3:

1. Menggunakan build.py kapan ns-3 dibangun untuk pertama kalinya

2. Menggunakan waf sekali ns-3 telah dibangun

3. Menggunakan ns-3 file konfigurasi sekali ns-3 telah dibangun

Aktifkan / nonaktifkan contoh dan tes menggunakan build.py
Anda dapat menggunakan build.py untuk mengaktifkan/menonaktifkan contoh dan menguji kapan ns-3 dibangun untuk yang pertama
waktu.

Secara default, contoh dan pengujian tidak disertakan ns-3.

Dari direktori ns-3-allinone, Anda dapat membangun ns-3 tanpa contoh atau tes sederhana
dengan melakukan:

$ ./build.py

Menjalankan test.py di tingkat atas ns-3 direktori sekarang tidak akan menyebabkan contoh atau tes menjadi
menjalankan:

0 dari 0 tes lulus (0 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Jika Anda ingin membangun ns-3 dengan contoh dan tes, lalu lakukan hal berikut dari
direktori ns-3-allinon:

$ ./build.py --enable-examples --enable-tests

Menjalankan test.py di tingkat atas ns-3 direktori akan menyebabkan semua contoh dan tes
untuk dijalankan:

170 dari 170 tes lulus (170 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Aktifkan / nonaktifkan contoh dan tes menggunakan WAF
Anda dapat menggunakan waf untuk mengaktifkan/menonaktifkan contoh dan pengujian satu kali ns-3 telah dibangun.

Secara default, contoh dan pengujian tidak disertakan ns-3.

Dari tingkat atas ns-3 direktori, Anda dapat membangun ns-3 tanpa contoh atau tes sederhana
dengan melakukan:

$ ./waf mengkonfigurasi
$ ./waf membangun

Menjalankan test.py sekarang tidak akan menyebabkan tidak ada contoh atau pengujian yang dijalankan:

0 dari 0 tes lulus (0 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Jika Anda ingin membangun ns-3 dengan contoh dan tes, lalu lakukan hal berikut dari atas
tingkat ns-3 direktori:

$ ./waf konfigurasikan --enable-examples --enable-tests
$ ./waf membangun

Menjalankan test.py akan menyebabkan semua contoh dan pengujian dijalankan:

170 dari 170 tes lulus (170 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Aktifkan / nonaktifkan contoh dan tes menggunakan itu ns-3 konfigurasi fillet
File konfigurasi, .ns3rc, telah ditambahkan ns-3 yang memungkinkan pengguna untuk menentukan apakah
contoh dan tes harus dibangun atau tidak. Anda dapat menggunakan file ini untuk mengaktifkan/menonaktifkan
contoh dan tes sekali ns-3 telah dibangun.

Saat mengaktifkan penonaktifan contoh dan pengujian, aturan prioritasnya adalah sebagai berikut:

1. --enable-examples/--disable-examples mengkonfigurasi string mengesampingkan file .ns3rc apa pun

2. --enable-tests/--disable-tests mengkonfigurasi string mengesampingkan file .ns3rc apa pun

3. file .ns3rc di tingkat atas ns-3 direktori selanjutnya dikonsultasikan, jika ada

4. sistem mencari ~/.ns3rc jika file .ns3rc tidak ditemukan pada langkah sebelumnya

Jika tidak ada hal di atas, maka contoh dan pengujian tidak akan dibuat.

Versi file .ns3rc yang dipertahankan di ns-3 repositori kode sumber berada di
itu utilitas direktori. Alasan untuk ini adalah jika berada di direktori tingkat atas dari
repositori, itu akan rentan terhadap checkin yang tidak disengaja dari pengelola yang mengaktifkan
modul yang ingin mereka gunakan. Oleh karena itu, pengguna perlu menyalin .ns3rc secara manual dari
utilitas direktori ke tempat pilihan mereka (direktori tingkat atas atau direktori home mereka) ke
aktifkan pengaktifan contoh dan pengujian secara terus-menerus.

Dengan asumsi bahwa Anda berada di tingkat atas ns-3 direktori, Anda bisa mendapatkan salinan .ns3rc
file yang ada di utilitas direktori sebagai berikut:

$cp utils/.ns3rc .

File .ns3rc sekarang seharusnya berada di level teratas Anda ns-3 direktori, dan itu berisi
sebagai berikut:

#! /usr/bin/env ular sanca

# Daftar modul yang akan diaktifkan saat ns-3 dijalankan.
# Modul yang bergantung pada modul yang terdaftar juga akan diaktifkan.
#
# Semua modul dapat diaktifkan dengan memilih 'all_modules'.
modules_enabled = ['semua_modul']

# Tetapkan ini sama dengan benar jika Anda ingin contoh dijalankan.
example_enabled = Salah

# Tetapkan ini sama dengan benar jika Anda ingin tes dijalankan.
tes_diaktifkan = Salah

Dari tingkat atas ns-3 direktori, Anda dapat membangun ns-3 tanpa contoh atau tes sederhana
dengan melakukan:

$ ./waf mengkonfigurasi
$ ./waf membangun

Menjalankan test.py sekarang tidak akan menyebabkan tidak ada contoh atau pengujian yang dijalankan:

0 dari 0 tes lulus (0 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Jika Anda ingin membangun ns-3 dengan contoh dan tes, gunakan editor favorit Anda untuk berubah
nilai dalam file .ns3rc untuk file example_enabled dan test_enabled menjadi True:

#! /usr/bin/env ular sanca

# Daftar modul yang akan diaktifkan saat ns-3 dijalankan.
# Modul yang bergantung pada modul yang terdaftar juga akan diaktifkan.
#
# Semua modul dapat diaktifkan dengan memilih 'all_modules'.
modules_enabled = ['semua_modul']

# Tetapkan ini sama dengan benar jika Anda ingin contoh dijalankan.
example_enabled = Benar

# Tetapkan ini sama dengan benar jika Anda ingin tes dijalankan.
tes_diaktifkan = Benar

Dari tingkat atas ns-3 direktori, Anda dapat membangun ns-3 dengan contoh dan tes hanya dengan
perbuatan:

$ ./waf mengkonfigurasi
$ ./waf membangun

Menjalankan test.py akan menyebabkan semua contoh dan pengujian dijalankan:

170 dari 170 tes lulus (170 lulus, 0 dilewati, 0 gagal, 0 macet, 0 kesalahan valgrind)

Penyelesaian masalah
Bab ini memposting beberapa informasi tentang kemungkinan kesalahan umum dalam membangun atau menjalankan
ns-3 program.

Harap perhatikan bahwa wiki (http://www.nsnam.org/wiki/Troubleshooting) mungkin telah berkontribusi
barang.

Membangun kesalahan
Waktu jalan kesalahan
Terkadang, kesalahan dapat terjadi pada program setelah berhasil membangun. Ini adalah run-time
kesalahan, dan umumnya dapat terjadi saat memori rusak atau nilai penunjuk tiba-tiba
batal.

Berikut adalah contoh dari apa yang mungkin terjadi:

$ ./waf --jalankan tcp-point-to-point
Memasuki direktori '/home/tomh/ns-3-nsc/build'
Kompilasi selesai dengan sukses
Perintah ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] keluar dengan kode -11

Pesan kesalahan mengatakan bahwa program tidak berhasil dihentikan, tetapi tidak jelas
dari informasi ini apa yang mungkin salah. Untuk mempelajari lebih dekat, coba jalankan di bawah
itu gdb debugger:

$ ./waf --jalankan tcp-point-to-point --command-template="gdb %s"
Memasuki direktori '/home/tomh/ns-3-nsc/build'
Kompilasi selesai dengan sukses
GNU gdb Red Hat Linux (6.3.0.0-1.134.fc5rh)
Hak Cipta 2004 Free Software Foundation, Inc.
GDB adalah perangkat lunak gratis, tercakup dalam Lisensi Publik Umum GNU, dan Anda
selamat datang untuk mengubahnya dan/atau mendistribusikan salinannya dalam kondisi tertentu.
Ketik "show copying" untuk melihat kondisinya.
Sama sekali tidak ada garansi untuk GDB. Ketik "tampilkan garansi" untuk detailnya.
GDB ini dikonfigurasi sebagai "i386-redhat-linux-gnu"...Menggunakan host libthread_db
perpustakaan "/lib/libthread_db.so.1".

(gdb) jalankan
Memulai program: /home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point
Membaca simbol dari objek yang dibagikan, membaca dari memori target...selesai.
Sistem dimuat memasok DSO pada 0xf5c000

Program menerima sinyal SIGSEGV, Kesalahan segmentasi.
0x0804aa12 di main (argc=1, argv=0xbfdfefa4)
di ../examples/tcp-point-to-point.cc:136
136 Ptr localSocket = socketFactory->CreateSocket ();
(gdb) p soket lokal
$1 = {m_ptr = 0x3c5d65}
(gdb) p soketPabrik
$2 = {m_ptr = 0x0}
(gdb) keluar
Program sedang berjalan. Tetap keluar? (y atau n) y

Catat dulu cara program dipanggil-- berikan perintah untuk dijalankan sebagai argumen ke
templat perintah "gdb %s".

Ini memberi tahu kita bahwa ada upaya untuk melakukan dereferensi null pointer socketFactory.

Mari kita lihat baris 136 dari tcp-point-to-point, seperti yang disarankan gdb:

Ptr socketFactory = n2->GetObject (Tcp::iid);
Ptr localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();

Pelakunya di sini adalah nilai pengembalian GetObject tidak diperiksa dan mungkin
batal.

Terkadang Anda mungkin perlu menggunakan valgrind ingatan pemeriksa untuk kesalahan yang lebih halus. Lagi,
Anda meminta penggunaan valgrind dengan cara yang sama:

$ ./waf --jalankan tcp-point-to-point --command-template="valgrind %s"

SOURCE


Dokumen ini ditulis dalam reStructuredText untuk Orang yg merahasiakan pendapatnya dan dipertahankan di
dokumen/manual direktori kode sumber ns-3.

Gunakan ns-3-manual online menggunakan layanan onworks.net


Server & Workstation Gratis

Unduh aplikasi Windows & Linux

  • 1
    Manajer PAC
    Manajer PAC
    PAC adalah pengganti Perl/GTK untuk
    SecureCRT/Putty/dll (linux
    ssh/telnet/... gui)... Ini menyediakan GUI
    untuk mengonfigurasi koneksi: pengguna,
    kata sandi, aturan EXPECT...
    Unduh Manajer PAC
  • 2
    GeoServer
    GeoServer
    GeoServer adalah perangkat lunak sumber terbuka
    server yang ditulis dalam Java yang memungkinkan pengguna
    untuk berbagi dan mengedit data geospasial.
    Dirancang untuk interoperabilitas, itu
    menerbitkan da...
    Unduh GeoServer.dll
  • 3
    Kunang-kunang III
    Kunang-kunang III
    Keuangan pribadi sumber terbuka dan gratis
    Pengelola. Fitur Firefly III a
    sistem pembukuan berpasangan. Kamu bisa
    cepat masuk dan atur
    transaksi saya...
    Unduh Firefly III
  • 4
    Ekstensi Apache OpenOffice
    Ekstensi Apache OpenOffice
    Katalog resmi Apache
    ekstensi OpenOffice. Anda akan menemukan
    ekstensi mulai dari kamus hingga
    alat untuk mengimpor file PDF dan untuk menghubungkan
    dengan ekst...
    Unduh Ekstensi Apache OpenOffice
  • 5
    MantisBT
    MantisBT
    Mantis adalah web yang mudah digunakan
    bugtracker berbasis untuk membantu bug produk
    pelacakan. Ini membutuhkan PHP, MySQL dan a
    server web. Lihat demo dan host kami
    menawarkan...
    Unduh MantisBT
  • 6
    Utusan LAN
    Utusan LAN
    LAN Messenger adalah aplikasi obrolan p2p
    untuk komunikasi intranet dan tidak
    membutuhkan server. Berbagai berguna
    fitur yang didukung termasuk
    pemberitahuan...
    Unduh LAN Messenger
  • Lebih banyak lagi »

Perintah Linux

Ad