English프랑스어스페인어

온웍스 파비콘

ns-3-manual - 클라우드에서의 온라인

Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터를 통해 OnWorks 무료 호스팅 제공업체에서 ns-3-manual을 실행하세요.

Ubuntu Online, Fedora Online, Windows 온라인 에뮬레이터 또는 MAC OS 온라인 에뮬레이터와 같은 여러 무료 온라인 워크스테이션 중 하나를 사용하여 OnWorks 무료 호스팅 제공업체에서 실행할 수 있는 ns-3-manual 명령입니다.

프로그램:

이름


ns-3-수동 - ns-3 수동

이것은 NS-3 Manual. ns-3 프로젝트에 대한 기본 문서는 XNUMX가지 형식으로 제공됩니다.
형태 :

· NS-3 독소: 시뮬레이터의 공개 API 문서

· 튜토리얼, 매뉴얼 (이 문서)및 모델 라이브러리 최근 공개 and
개발 나무

· NS-3 위키

내용


회사조직
이 장에서는 전반적인 내용을 설명합니다. NS-3 소프트웨어 조직 및 해당
이 매뉴얼의 구성.

NS-3 시뮬레이션 코어와 모델이 포함된 이산 이벤트 네트워크 시뮬레이터입니다.
C++로 구현되었습니다. NS-3 정적 또는 동적으로 라이브러리로 구축됩니다.
시뮬레이션 토폴로지를 정의하고 시작하는 C++ 기본 프로그램에 연결됩니다.
모의 실험 장치. NS-3 또한 거의 모든 API를 Python으로 내보내 Python 프로그램이 다음을 수행할 수 있도록 합니다.
"ns3" 모듈을 다음과 거의 같은 방식으로 가져옵니다. NS-3 라이브러리는 실행 파일로 연결됩니다
C ++에서.
[이미지] 소프트웨어 구성 NS-3.UNINDENT

소스 코드 NS-3 주로 조직되어 있다. SRC 디렉토리이며 설명될 수 있습니다.
의 다이어그램으로 소프트웨어 조직 of NS-3. 우리는 밑바닥부터 우리의 길을 갈 것이다
위로; 일반적으로 모듈은 그림에서 그 아래에 있는 모듈에만 종속됩니다.

먼저 시뮬레이터의 핵심을 설명합니다. 모든 구성 요소에 공통적으로 포함되는 구성 요소
프로토콜, 하드웨어, 환경 모델. 시뮬레이션 코어는 다음에서 구현됩니다.
소스/코어. 패킷은 네트워크 시뮬레이터의 기본 개체이며 다음으로 구현됩니다.
소스/네트워크. 이 두 가지 시뮬레이션 모듈은 그 자체로 다음을 구성하도록 고안되었습니다.
네트워크뿐만 아니라 다양한 종류의 네트워크에서 사용할 수 있는 일반 시뮬레이션 코어
인터넷 기반 네트워크. 위의 모듈은 NS-3 특정 네트워크에 독립적입니다.
이 설명서의 후속 부분에서 다루는 장치 모델.

상기 이외에 NS-3 핵심, 우리는 또한의 초기 부분에서 소개합니다.
매뉴얼, 핵심 C++ 기반 API를 보완하는 두 개의 다른 모듈. NS-3 프로그램은
모든 API에 직접 액세스하거나 소위 말하는 API를 사용할 수 있습니다. 도우미 API 제공하는
낮은 수준 API 호출의 편리한 래퍼 또는 캡슐화. 사실 그 NS-3 프로그램
두 개의 API(또는 이들의 조합)에 작성할 수 있다는 것은
모의 실험 장치. 또한 Python이 다음에서 어떻게 지원되는지 설명합니다. NS-3 특정 항목으로 넘어가기 전에
네트워크 시뮬레이션과 관련된 모델.

매뉴얼의 나머지 부분은 모델을 문서화하고 지원하는 데 중점을 둡니다.
능력. 다음 부분에서는 두 가지 기본 개체에 중점을 둡니다. NS-3다음 노드 and
NetDevice. 두 가지 특별한 NetDevice 유형은 네트워크 에뮬레이션 사용을 지원하도록 설계되었습니다.
경우와 에뮬레이션은 다음에 설명됩니다. 다음 장에서는 이에 대해 설명합니다.
인터넷 애플리케이션에서 사용되는 소켓 API를 포함한 인터넷 관련 모델. 그만큼
다음 장에서는 응용 프로그램을 다루고, 다음 장에서는 추가 지원에 대해 설명합니다.
애니메이터, 통계 등 시뮬레이션용.

프로젝트는 테스트 및 검증에 전념하는 별도의 매뉴얼을 유지 관리합니다. NS-3 암호
(참조 NS-3 지원 and 검증 조작).

랜덤 무작위 변수
NS-3 내장된 의사 난수 생성기(PRNG)가 포함되어 있습니다. 그것은 중요합니다
기능, 구성 및 사용법을 이해하기 위한 시뮬레이터의 진지한 사용자
이 PRNG의 내용을 확인하고 그것이 자신의 연구 용도에 충분한지 여부를 결정합니다.

빠른 살펴보기
NS-3 난수는 인스턴스를 통해 제공됩니다. ns3::RandomVariableStream.

· 기본적으로, NS-3 시뮬레이션은 고정 시드를 사용합니다. 무작위성이 있다면
시뮬레이션의 경우, 프로그램을 실행할 때마다 시드 및/또는
실행번호가 변경되었습니다.

· 안에 NS-3.3 그리고 더 일찍, NS-3 시뮬레이션은 기본적으로 무작위 시드를 사용했습니다. 이것은 a를 표시합니다
정책부터 바꿔야 NS-3.4.

· 안에 NS-3.14 그리고 더 일찍, NS-3 시뮬레이션에서는 다음과 같은 다른 래퍼 클래스를 사용했습니다.
ns3::랜덤변수. 현재 NS-3.15, 이 클래스는 다음으로 대체되었습니다.
ns3::RandomVariableStream; 기본 의사 난수 생성기는
바꾸었습니다.

· 여러 시뮬레이션 실행에서 무작위성을 얻으려면 시드를 설정해야 합니다.
다르게 실행하거나 실행 번호를 다르게 설정하십시오. 시드를 설정하려면 전화하세요.
ns3::RngSeedManager::SetSeed() 프로그램 시작시; 실행 번호를 설정하려면
같은 씨앗, 전화 ns3::RngSeedManager::SetRun() 프로그램 시작시; 보다
만들기 닥치는대로의 변수.

· 다음에서 사용되는 각 RandomVariableStream NS-3 가상 난수 생성기가 연결되어 있습니다.
그것으로; 모든 무작위 변수는 다음의 사용에 따라 고정 또는 무작위 시드를 사용합니다.
전역 시드(이전 글머리 기호);

· 동일한 시나리오를 다른 무작위로 여러 번 실행하려는 경우
숫자가 많은 경우 독립적인 복제를 수행하는 방법에 대한 섹션을 꼭 읽어보세요.
만들기 닥치는대로의 변수.

난수 기능에 대한 자세한 설명을 읽어보세요. NS-3.

배경
시뮬레이션에서는 많은 난수를 사용합니다. 한 연구에 따르면 대부분의 네트워크 시뮬레이션에서는
난수를 생성하는 데 CPU의 최대 50%를 소비합니다. 시뮬레이션 사용자는 다음과 같아야 합니다.
(의사) 난수의 품질과 사이의 독립성에 관심이 있습니다.
다양한 난수 스트림.

사용자는 다음과 같은 몇 가지 문제에 관심을 가져야 합니다.

· 난수 생성기의 시딩 및 시뮬레이션 결과가 다음과 같은지 여부
결정론적이든 아니든,

· 하나와 독립적인 다양한 난수 스트림을 얻는 방법
또 다른 그리고

· 스트림이 순환하는 데 걸리는 시간

여기서는 몇 가지 용어를 소개하겠습니다. RNG는 (의사) 무작위의 긴 시퀀스를 제공합니다.
숫자. 이 시퀀스의 길이를 주기 길이 or 기간, 그 후
RNG가 반복됩니다. 이 순서는 분리되어 있을 수 있습니다. 스트림. 에이
RNG의 스트림은 RNG 시퀀스의 연속적인 부분 집합 또는 블록입니다. 예를 들어,
RNG 기간은 길이 N이고 이 RNG에서 두 개의 스트림이 제공되고 첫 번째 스트림이 제공됩니다.
스트림은 첫 번째 N/2 값을 사용할 수 있고 두 번째 스트림은 두 번째 N/2 값을 생성할 수 있습니다.
가치. 여기서 중요한 속성은 두 스트림이 상관되지 않는다는 것입니다. 비슷하게,
각 스트림은 상관되지 않은 여러 스트림으로 분리될 수 있습니다. 서브스트림. 그만큼
기본 RNG는 매우 긴 숫자의 의사 난수 시퀀스를 생성하기를 바랍니다.
사이클 길이를 파악하고 이를 효율적인 방식으로 스트림과 서브스트림으로 분할합니다.

NS-3 동일한 기본 난수 생성기를 사용합니다. NS-2: MRG32k3a
Pierre L'Ecuyer의 발전기. 자세한 설명은 다음에서 확인할 수 있습니다.
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf. MRG32k3a 생성기
1.8x10^{19}개의 독립적인 난수 스트림을 제공하며, 각 스트림은 다음으로 구성됩니다.
2.3x10^{15} 서브스트림. 각 하위 스트림에는 마침표(, 난수의 수
겹치기 전) 7.6x10^{22}. 전체 생성기의 주기는 3.1x10^{57}입니다.

클래스 ns3::RandomVariableStream 이 기본 난수에 대한 공개 인터페이스입니다.
발전기. 사용자가 새로운 무작위 변수(예: ns3::UniformRandom변수,
ns3::지수임의변수등), 다음 중 하나를 사용하는 객체를 생성합니다.
난수 생성기의 고유하고 독립적인 스트림입니다. 그러므로 각 객체의
유형 ns3::RandomVariableStream 개념적으로 자체 "가상" RNG가 있습니다. 뿐만 아니라,
마다 ns3::RandomVariableStream 그려진 서브스트림 세트 중 하나를 사용하도록 구성할 수 있습니다.
메인 스트림에서.

대체 구현은 각 RandomVariable이 고유한 속성을 갖도록 허용하는 것입니다.
(다른 시드) RNG. 그러나 우리는 그 차이가 다음과 같다고 강력히 보장할 수는 없습니다.
그러한 경우 시퀀스는 상관되지 않습니다. 따라서 우리는 단일 RNG를 사용하는 것을 선호하고
그것으로부터의 스트림과 서브스트림.

만들기 닥치는대로의 변수
NS-3 기본 클래스의 다양한 무작위 변수 개체를 지원합니다.
무작위변수스트림. 이러한 개체는 다음에서 파생됩니다. ns3::객체 스마트하게 처리됩니다.
포인터.

이러한 객체를 생성하는 올바른 방법은 템플릿을 사용하는 것입니다. 객체 생성<> 방법,
예를 들면 :

포인트 x = 객체 생성 ();

그러면 다음과 같이 객체에 대한 메서드를 호출하여 값에 액세스할 수 있습니다.

myRandomNo = x->GetInteger();

대신 다음과 같은 작업을 수행하려고 하면:

myRandomNo =UniformRandomVariable().GetInteger();

구현이 다음 사항에 의존하기 때문에 프로그램에서 분할 오류가 발생합니다.
다음 경우에만 발생하는 일부 속성 구성 CreateObject 호출됩니다.

이제 이 장의 나머지 부분에서는 스트림의 속성에 대해 논의합니다.
그러한 객체로부터 생성된 의사 난수 및 그러한 객체의 시딩을 제어하는 ​​방법
사물.

시드 and 독립 복제
NS-3 시뮬레이션은 결정적 또는 무작위 결과를 생성하도록 구성될 수 있습니다. 만약
NS-3 시뮬레이션은 동일한 실행 번호를 가진 고정된 결정적 시드를 사용하도록 구성됩니다.
실행될 때마다 동일한 출력을 제공해야 합니다.

기본적으로, NS-3 시뮬레이션은 고정된 시드와 실행 번호를 사용합니다. 이 값은 다음 위치에 저장됩니다.
ns3::글로벌값 인스턴스: g_rng시드 and g_rng실행.

일반적인 사용 사례는 시뮬레이션을 일련의 독립적인 시도로 실행하는 것입니다.
다수의 독립적 실행에 대한 통계를 계산합니다. 사용자는
전역 시드를 적용하고 시뮬레이션을 다시 실행하거나 RNG의 하위 스트림 상태를 발전시킬 수 있습니다.
실행 번호를 증가시키는 것을 말합니다.

수업 ns3::RngSeedManager 시드 및 실행 횟수를 제어하는 ​​API를 제공합니다.
행동. 이 시딩 및 하위 스트림 상태 설정은 무작위 이전에 호출되어야 합니다.
변수가 생성됩니다. 예:

RngSeedManager::SetSeed (3); // 시드를 기본값 1에서 3으로 변경합니다.
RngSeedManager::SetRun (7); // 실행 번호를 기본값 1에서 7로 변경합니다.
// 이제 무작위 변수를 생성합니다.
포인트 x = 객체 생성 ();
포인트 y = 객체 생성 ();
...

새로운 시드를 설정하는 것과 하위 스트림 상태를 발전시키는 것 중 어느 것이 더 낫습니까? 없다
두 개의 무작위 시드에 의해 생성된 스트림이 겹치지 않도록 보장합니다. 유일한 방법은
두 스트림이 겹치지 않도록 보장하는 것은 다음에서 제공하는 하위 스트림 기능을 사용하는 것입니다.
RNG 구현. 따라서, 사용 전에, 서브스트림 능력 생산 여러
독립 실행 of 전에, 같은 시뮬레이션. 즉, 통계적으로 더 엄격할수록
여러 개의 독립적인 복제를 구성하는 방법은 고정된 시드를 사용하고 고급화하는 것입니다.
실행 번호. 이 구현은 최대 2.3x10^{15} 독립을 허용합니다.
서브스트림을 사용한 복제.

사용 편의성을 위해 시스템 내에서 시드 및 실행 횟수를 제어할 필요가 없습니다.
프로그램; 사용자는 NS_GLOBAL_VALUE 환경 변수는 다음과 같습니다.

$ NS_GLOBAL_VALUE="RngRun=3" ./waf --실행 프로그램 이름

이를 제어하는 ​​또 다른 방법은 명령줄 인수를 전달하는 것입니다. 왜냐하면 이것은 NS-3
GlobalValue 인스턴스에서는 다음과 같이 동일하게 수행됩니다.

$ ./waf --command-template="%s --RngRun=3" --프로그램 이름 실행

또는 waf 외부에서 직접 프로그램을 실행하는 경우:

$ ./빌드/최적화/스크래치/프로그램 이름 --RngRun=3

위의 명령줄 변형을 사용하면 쉘에서 다양한 실행을 쉽게 실행할 수 있습니다.
다른 RngRun 인덱스를 전달하면 됩니다.

클래스 무작위변수스트림
모든 확률 변수는 클래스에서 파생되어야 합니다. 무작위변수. 이 기본 클래스는
난수 생성기의 동작을 전역적으로 구성하는 몇 가지 방법입니다. 파생됨
클래스는 특정 분포에서 무작위 변량을 추출하기 위한 API를 제공합니다.
지원.

시뮬레이션에서 생성된 각 RandomVariableStream에는 새로운 생성기가 제공됩니다.
기본 PRNG의 RNGStream입니다. 이러한 방식으로 사용되는 L'Ecuyer 구현은
최대 1.8x10^19개의 무작위 변수를 허용합니다. 단일의 각 무작위 변수
복제는 겹치기 전에 최대 7.6x10^22개의 난수를 생성할 수 있습니다.

Base 수업 공개 API
다음은 클래스의 몇 가지 공개 메소드를 발췌한 것입니다. 무작위변수스트림 액세스하는
서브스트림의 다음 값입니다.

/ **
* \brief 기본 분포에서 임의의 double을 반환합니다.
* \return 부동 소수점 임의 값
*/
double GetValue (void) const;

/ **
* \brief 기본 분포에서 임의의 정수를 반환합니다.
* \return ::GetValue()의 정수형 캐스트
*/
uint32_t GetInteger (void) const;

위에서 시드 구성에 대해 이미 설명했습니다. 다른 무작위 변수
하위 클래스에는 추가 API가 있을 수 있습니다.

유형 of 무작위변수
다음 유형의 확률 변수가 제공되며, NS-3
Doxygen 또는 독서로 src/코어/모델/random-variable-stream.h. 사용자는 다음을 생성할 수도 있습니다.
클래스에서 파생된 자체 사용자 정의 무작위 변수 무작위변수스트림.

· 수업 균일무작위변수

· 수업 상수임의변수

· 수업 순차적임의변수

· 수업 지수임의변수

· 수업 파레토랜덤변수

· 수업 Weibull랜덤변수

· 수업 일반임의변수

· 수업 로그일반임의변수

· 수업 감마랜덤변수

· 수업 ErlangRandom변수

· 수업 삼각형임의변수

· 수업 ZipfRandom변수

· 수업 ZetaRandom변수

· 수업 결정적임의변수

· 수업 경험적 무작위변수

의미론 of 무작위변수스트림 사물
RandomVariableStream 객체는 다음에서 파생됩니다. ns3::객체 스마트 포인터에 의해 처리됩니다.

RandomVariableStream 인스턴스는 다음에서도 사용할 수 있습니다. NS-3 속성은 다음을 의미합니다.
값은 다음을 통해 설정할 수 있습니다. NS-3 속성 시스템. 예는 다음과 같습니다.
WifiNetDevice의 전파 모델:

유형 ID
RandomPropagationDelayModel::GetTypeId(무효)
{
static TypeId tid = TypeId ("ns3::RandomPropagationDelayModel")
.SetParent ()
.AddConstructor ()
.AddAttribute("변수",
"무작위 지연을 생성하는 무작위 변수입니다.",
StringValue("ns3::UniformRandomVariable"),
MakePointerAccessor(&RandomPropagationDelayModel::m_variable),
MakePointerChecker ())
;
정시 반환;
}

여기, NS-3 사용자는 이 지연 모델에 대한 기본 무작위 변수를 변경할 수 있습니다(이는
0에서 1 사이의 균일한 변수(UniformRandomVariable)를 속성 시스템을 통해 생성합니다.

사용 other PRNG
현재는 다른 기본 난수를 대체하는 기능이 지원되지 않습니다.
생성기(예: GNU Scientific Library 또는 Akaroa 패키지). 패치를 환영합니다.

환경 전에, 흐름 번호
기본 MRG32k3a 생성기는 2^64개의 독립적인 스트림을 제공합니다. ns-3에서는 다음과 같습니다.
새로운 RandomVariableStream 인스턴스로 첫 번째 스트림부터 순차적으로 할당됩니다.
GetValue()를 처음으로 호출합니다.

이러한 RandomVariableStream 개체가 기본 스트림에 할당되는 방식의 결과로,
할당은 시뮬레이션 구성의 교란에 민감합니다. 그만큼
결과적으로 시뮬레이션 구성의 어떤 측면이 변경되면 매핑이 변경됩니다.
스트림에 대한 RandomVariables는 변경될 수도 있고 변경되지 않을 수도 있습니다.

구체적인 예로, 라우팅 프로토콜 간의 비교 연구를 수행하는 사용자는 다음과 같습니다.
하나의 라우팅 프로토콜을 다른 라우팅 프로토콜로 변경하는 행위는
기본 이동성 패턴도 변경되었습니다.

ns-3.15부터 사용자가 다음을 수행할 수 있도록 일부 제어 기능이 사용자에게 제공되었습니다.
선택적으로 선택된 RandomVariableStream 객체의 할당을 기본으로 수정합니다.
스트림. 이것이 흐름 기본 클래스 RandomVariableStream의 일부인 속성.

이전의 기존 스트림 시퀀스를 분할하여 다음을 수행합니다.

<----------------------------------- ------------>
스트림 0 스트림 (2^64 - 1)

두 개의 동일한 크기 세트로:

<----------------------------------- ------------>
^^^ ^
| || |
스트림 0 스트림(2^63 - 1) 스트림 2^63 스트림(2^64 - 1)
<- 자동 할당 -----------><- 사용자 할당 ----->

처음 2^63개 스트림은 계속해서 자동으로 할당되고 마지막 2^63개 스트림은
2부터 시작하여 최대 63^1-XNUMX까지의 스트림 인덱스가 제공됩니다.

고정된 스트림 번호에 대한 스트림 할당은 선택 사항입니다. 인스턴스
스트림 값이 할당되지 않은 RandomVariableStream은 다음 항목에 할당됩니다.
자동 스트림 풀에서 하나.

RandomVariableStream을 특정 기본 스트림에 고정하려면 해당 스트림을 할당합니다. 흐름
음이 아닌 정수에 대한 속성(기본값 -1은 값이
자동으로 할당됨)

출판 your 결과
시뮬레이션 결과를 게시할 때 구성 정보의 핵심 부분은
항상 명시해야 할 것은 난수 생성기를 어떻게 사용했는지입니다.

· 어떤 씨앗을 사용했는지,

· 기본값이 아닌 경우 어떤 RNG를 사용했는지,

· 독립 실행은 어떻게 수행되었습니까?

· 대규모 시뮬레이션의 경우 순환하지 않았는지 어떻게 확인했나요?

충분한 정보를 포함하는 것은 결과를 출판하는 연구자의 의무입니다.
다른 사람들이 자신의 결과를 재현할 수 있도록 허용합니다. 연구자의 몫이기도 하다.
사용된 난수가 통계적으로 유효하다는 것을 스스로 확신하고 다음과 같이 진술하십시오.
왜 그런 자신감이 가정되는지 논문.

요약
시뮬레이션을 만들 때 수행해야 할 작업을 검토해 보겠습니다.

· 고정 시드 또는 무작위 시드를 사용하여 실행할지 결정합니다. 고정된 씨앗은
기본

· 해당되는 경우 독립적인 복제를 관리할 방법을 결정합니다.

· 다음과 같은 경우 주기 길이보다 더 많은 무작위 값을 그리는 것이 아니라는 점을 스스로 확신하십시오.
매우 긴 시뮬레이션을 실행 중이고

· 게시할 때 무작위 사용을 문서화하는 방법에 대한 위의 지침을 따르십시오.
숫자 생성기.

해시 기능
NS-3 범용 해시 함수에 대한 일반 인터페이스를 제공합니다. 가장 간단하게
사용법에 따라 해시 함수는 데이터 버퍼 또는 문자열의 32비트 또는 64비트 해시를 반환합니다.
기본 기본 해시 함수는 다음과 같습니다. 중얼 거림 3, 좋은 해시 함수를 가지고 있기 때문에 선택됨
속성을 제공하며 64비트 버전을 제공합니다. 존경하는 FNV1a 해시도 가능합니다.

대체 해시를 추가(또는 런타임에 제공)하는 간단한 메커니즘이 있습니다.
기능 구현.

Basic 용법
데이터 버퍼나 문자열의 해시 값을 얻는 가장 간단한 방법은 다음과 같습니다.

#include "ns3/hash.h"

네임스페이스 ns3 사용;

문자 * 버퍼 = ...
size_t buffer_size = ...

uint32_t buffer_hash = Hash32(버퍼, buffer_size);

표준::문자열 s;
uint32_t string_hash = Hash32(들);

64비트 해시 값에 대해 동등한 함수가 정의됩니다.

증분 해싱
어떤 상황에서는 마치 여러 버퍼의 해시를 계산하는 것이 유용합니다.
함께 합류하게 되었습니다. (예를 들어 패킷 스트림의 해시를 원할 수도 있지만 그렇지 않을 수도 있습니다.
모든 패킷의 내용이 결합된 단일 버퍼를 조립하고 싶습니다.)

이는 첫 번째 예와 거의 비슷합니다.

#include "ns3/hash.h"

네임스페이스 ns3 사용;

문자 * 버퍼;
size_t 버퍼_크기;

해셔 해셔; // 기본 해시 함수 사용

을 위한 ( )
{
버퍼 = get_next_buffer();
해셔(버퍼, buffer_size);
}
uint32_t Combined_hash = hasher.GetHash32 ();

기본적으로 해셔 증분 해싱을 활성화하기 위해 내부 상태를 유지합니다. 당신이 원한다면
재사용하다 해셔 객체(예: 기본이 아닌 해시로 구성되었기 때문에)
함수), 하지만 이전에 계산된 해시에 추가하고 싶지 않다면 다음을 수행해야 합니다. 맑은()
먼저:

hasher.clear().GetHash32(버퍼, buffer_size);

이는 버퍼를 해싱하기 전에 내부 상태를 다시 초기화합니다.

사용 an 대안투자 해시 함수
기본 해시 함수는 다음과 같습니다. 중얼 거림 3. FNV1a 또한 가능합니다. 해시를 지정하려면
함수를 명시적으로 사용하려면 다음 생성자를 사용하세요.

해셔 해셔 = 해셔(생성 () );

첨가 신제품 해시 함수 구현
해시 함수를 추가하려면 , 따라 해시-murmur3.h/.CC 무늬:

· 클래스 선언 생성(.h) 및 정의(.CC)에서 상속
해시::구현.

· 의 선언 해시.h (그 시점에서 해시-murmur3.h 포함되어 있습니다.

· 자신의 코드에서 인스턴스화 해셔 생성자를 통한 객체 해셔
(부분 ())

해시 함수가 단일 함수인 경우, 예: 해시, 생성할 필요도 없습니다.
HashImplementation에서 파생된 새 클래스:

해셔 해셔 =
해셔(생성 (&해시f) );

이를 컴파일하려면 해시 함수 포인터 서명 중 하나와 일치해야 합니다.

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

지우면 좋을거같음 . SM for 해시 기능
다른 해시 함수 구현 소스는 다음과 같습니다.

· 피터 칸코스키(Peter Kankowski): http://www.strchr.com

· 아라시 파토우: http://www.partow.net/programming/hashfunctions/index.html

· SM해셔: http://code.google.com/p/smhasher/

· 산메이스: http://www.sanmayce.com/Fastest_Hash/index.html

행사 and 모의 실험 장치
NS-3 이산 이벤트 네트워크 시뮬레이터입니다. 개념적으로 시뮬레이터는 다음을 추적합니다.
지정된 시뮬레이션 시간에 실행되도록 예약된 이벤트 수입니다. 직업
시뮬레이터는 순차적인 시간 순서로 이벤트를 실행하는 것입니다. 일단 완료되면
이벤트가 발생하면 시뮬레이터는 다음 이벤트로 이동합니다(또는 이벤트가 없으면 종료됩니다).
이벤트 큐에 더 많은 이벤트가 있습니다). 예를 들어 시뮬레이션 시간에 예정된 이벤트가 있는 경우
"100초"가 실행되고 "200초"까지 다음 이벤트가 예약되지 않습니다.
시뮬레이터는 즉시 100초에서 200초(시뮬레이션 시간 기준)로 점프합니다.
다음 이벤트를 실행합니다. 이것이 "이산 이벤트" 시뮬레이터의 의미입니다.

이 모든 일이 일어나려면 시뮬레이터에 몇 가지 사항이 필요합니다.

1. 이벤트가 저장되어 있는 이벤트 큐에 액세스할 수 있고 다음을 수행할 수 있는 시뮬레이터 객체
이벤트 실행 관리

2. 대기열에 이벤트를 삽입하고 제거하는 역할을 담당하는 스케줄러

3. 시뮬레이션 시간을 표현하는 방법

4. 이벤트 자체

매뉴얼의 이 장에서는 이러한 기본 개체(시뮬레이터, 스케줄러,
시간, 이벤트) 및 사용 방법을 설명합니다.

이벤트
be 완료

모의 실험 장치
Simulator 클래스는 이벤트 예약 기능에 액세스하기 위한 공개 진입점입니다. 한 번
시뮬레이션을 시작하기 위해 몇 가지 이벤트가 예약되어 있으면 사용자는 시뮬레이션을 시작할 수 있습니다.
시뮬레이터 메인 루프에 들어가서 실행하십시오(호출 시뮬레이터::실행). 일단 메인 루프
실행이 시작되면 예약된 모든 이벤트를 가장 오래된 이벤트부터 순차적으로 실행합니다.
이벤트 큐에 더 이상 이벤트가 남아 있지 않거나
Simulator::Stop이 호출되었습니다.

시뮬레이터 메인 루프에서 실행할 이벤트를 예약하기 위해 Simulator 클래스는 다음을 제공합니다.
Simulator::Schedule* 함수 계열.

1. 다양한 시그니처를 사용하여 이벤트 핸들러 처리하기

이러한 함수는 자동으로 처리하기 위해 C++ 템플릿으로 선언되고 구현됩니다.
현장에서 사용되는 다양한 C++ 이벤트 핸들러 시그니처. 예를 들어, 일정을 예약하려면
이벤트를 사용하여 앞으로 10초 동안 실행하고 C++ 메서드나 함수를 호출합니다.
특정 인수가 있는 경우 다음과 같이 작성할 수 있습니다.

무효 처리기(int arg0, int arg1)
{
std::cout << "인수 arg0=" << arg0 << "으로 호출된 핸들러 및
arg1=" << arg1 << std::endl;
}

시뮬레이터::일정((10), &핸들러, 10, 5);

그러면 다음이 출력됩니다.

인수 arg0=10 및 arg1=5로 호출된 핸들러

물론 이러한 C++ 템플릿은 C++의 멤버 메서드를 투명하게 처리할 수도 있습니다.
사물:

be 완전한: 회원 방법

배송 시 요청 사항:

· ns-3 Schedule 방법은 다음과 같은 경우에만 자동으로 기능과 방법을 인식합니다.
5개 미만의 인수를 사용합니다. 더 많은 주장을 뒷받침하기 위해 필요한 경우,
버그 신고.

· '완전히 바인딩된 펑터'라는 용어에 익숙한 독자라면
Simulator::Schedule 메소드는 그러한 객체를 자동으로 구성하는 방법입니다.

2. 일반적인 스케줄링 작업

시뮬레이터 API는 대부분의 이벤트를 매우 간단하게 예약할 수 있도록 설계되었습니다. 그것
이를 위한 세 가지 변형을 제공합니다(가장 일반적으로 사용되는 것부터 가장 덜 일반적으로 사용되는 것 순으로 정렬).

· 다음을 제공하여 향후 이벤트 일정을 예약할 수 있는 일정 방법
현재 시뮬레이션 시간과 대상 이벤트 만료 날짜 사이의 지연입니다.

· 현재 시뮬레이션에 대한 이벤트를 예약할 수 있는 ScheduleNow 방법
시간: 현재 이벤트 실행이 끝난 _후_ 실행되지만 이벤트 실행이 _전에_ 실행됩니다.
다음 이벤트의 시뮬레이션 시간이 변경됩니다.

· 시뮬레이터의 종료 프로세스를 연결할 수 있는 ScheduleDestroy 메서드
시뮬레이션 리소스 정리: 사용자가 호출할 때 모든 '파괴' 이벤트가 실행됩니다.
Simulator::Destroy 메소드.

3. 시뮬레이션 컨텍스트 유지

이벤트를 예약하는 기본 방법에는 포함 여부와 포함되지 않은 두 가지가 있습니다. 문맥. 이게 뭐야
평균?

시뮬레이터::일정(시간 const &time, MEM mem_ptr, OBJ obj);



시뮬레이터::ScheduleWithContext (uint32_t 컨텍스트, Time const &time, MEM mem_ptr, OBJ obj);

사소하지 않은 시뮬레이션 모델을 개발하거나 사용하는 데 시간과 노력을 투자하는 독자
단순하고 복잡한 시뮬레이션을 디버그하기 위한 ns-3 로깅 프레임워크의 가치를 알게 됩니다.
서로 같은. 이 로깅 프레임워크가 제공하는 중요한 기능 중 하나는
'현재' 실행 중인 이벤트와 관련된 네트워크 노드 ID를 자동으로 표시합니다.

현재 실행 중인 네트워크 노드의 노드 ID는 실제로 시뮬레이터에 의해 추적됩니다.
수업. 이는 다음을 반환하는 Simulator::GetContext 메서드를 사용하여 액세스할 수 있습니다.
'컨텍스트'(32비트 정수)는 현재 실행 중인 이벤트에 연결되어 저장됩니다. ~ 안에
드물지만 이벤트가 특정 네트워크 노드와 연결되지 않은 경우
'컨텍스트'는 0xffffffff로 설정됩니다.

각 이벤트에 컨텍스트를 연결하려면 Schedule 및 ScheduleNow 메서드를 자동으로 사용하세요.
현재 실행 중인 이벤트의 컨텍스트를 예정된 이벤트의 컨텍스트로 재사용합니다.
나중에 실행하기 위해.

어떤 경우에는 노드에서 노드로의 패킷 전송을 시뮬레이션할 때 가장 두드러집니다.
또 다른 하나는 수신 이벤트의 예상 컨텍스트가 다음과 같기 때문에 이 동작은 바람직하지 않습니다.
송신 노드가 아닌 수신 노드의 것입니다. 이 문제를 방지하려면 시뮬레이터
클래스는 특정 일정 메소드를 제공합니다: ScheduleWithContext
명시적으로 수신 이벤트와 연관된 수신 노드의 노드 ID입니다.

트리플 엑스: 암호

매우 드문 경우지만 개발자는 컨텍스트를 수정하거나 이해해야 할 수도 있습니다.
첫 번째 이벤트의 (노드 ID)는 관련 노드의 이벤트로 설정됩니다. 이것이 성취된다
NodeList 클래스에 의해: 새 노드가 생성될 때마다 NodeList 클래스는 다음을 사용합니다.
ScheduleWithContext는 이 노드에 대한 '초기화' 이벤트를 예약합니다. '초기화' 이벤트
따라서 노드 ID의 컨텍스트로 설정된 컨텍스트로 실행되며 일반적인 다양한 컨텍스트를 사용할 수 있습니다.
예약 방법. '초기화'를 전파하는 Node::Initialize 메소드를 호출합니다.
노드와 연결된 각 개체에 대해 DoInitialize 메서드를 호출하여 이벤트를 발생시킵니다. 그만큼
이러한 개체 중 일부에서 DoInitialize 메서드가 재정의되었습니다(특히 응용 프로그램에서
기본 클래스)는 일부 이벤트(주로 Application::StartApplication)를 예약합니다.
차례로 트래픽 생성 이벤트를 예약하고 이벤트를 예약합니다.
네트워크 수준 이벤트.

배송 시 요청 사항:

· 사용자는 다음을 호출하여 DoInitialize 메서드를 개체 전체에 전파할 때 주의해야 합니다.
멤버 개체에 대해 명시적으로 초기화

· 각 ScheduleWithContext 메소드와 연관된 컨텍스트 ID는 그 외에도 다른 용도로 사용됩니다.
로깅: ns-3의 실험적 분기에서 병렬 시뮬레이션을 수행하는 데 사용됩니다.
멀티스레딩을 사용하는 멀티코어 시스템.

Simulator::* 함수는 컨텍스트가 무엇인지 알지 못합니다.
ScheduleWithContext로 지정한 컨텍스트는 해당 컨텍스트가 있을 때 사용할 수 있습니다.
이벤트는 ::GetContext로 실행됩니다.

컨텍스트 값을 해석하는 것은 Simulator::* 위에 구현된 모델에 달려 있습니다.
ns-3에서 네트워크 모델은 컨텍스트를 노드의 노드 ID로 해석합니다.
이벤트를 발생시켰습니다. 이것이 바로 ScheduleWithContext를 호출하는 것이 중요한 이유입니다.
ns3::Channel은 노드 i에서 노드 j로 이벤트를 생성하고 있기 때문에 하위 클래스입니다.
노드 j에서 실행될 이벤트에 올바른 컨텍스트가 있는지 확인하려고 합니다.

Time
be 완료

스케줄러
be 완료

콜백
일부 신규 사용자는 NS-3 광범위하게 사용되는 프로그래밍 관용어에 익숙하지 않습니다.
코드 전반에 걸쳐: NS-3 콜백. 이 장에서는 다음과 같은 동기를 제공합니다.
콜백, 사용 방법 안내, 구현 세부정보 등을 확인할 수 있습니다.

콜백 자극
두 개의 시뮬레이션 모델 A와 B가 있고 이를 통과시키고 싶다고 가정해 보겠습니다.
시뮬레이션 중에 그들 사이의 정보. 그렇게 할 수 있는 한 가지 방법은
A와 B가 서로에 대해 명시적으로 알 수 있도록 하여 호출할 수 있도록 할 수 있습니다.
서로에 대한 방법:

클래스 A {
공공의:
void ReceiverInput ( // 매개변수 );
...
}

(다른 소스 파일에 있음:)

클래스 B {
공공의:
무효 DoSomething (공허);
...

비공개 :
A* a_instance; // A에 대한 포인터
}

무효화
B::DoSomething()
{
// a_instance에 무슨 일이 일어났는지 알립니다.
a_instance->ReceiveInput ( // 매개변수);
...
}

이것은 확실히 작동하지만 A와 B에 대한 종속성을 도입한다는 단점이 있습니다.
컴파일 타임에 상대방에 대해 알기 위해(이로 인해 독립성을 갖는 것이 더 어려워집니다)
시뮬레이터의 컴파일 단위) 일반화되지 않았습니다. 이후 사용 시나리오에서는
B는 완전히 다른 C 객체와 통신해야 하며, B의 소스 코드는 다음과 같아야 합니다.
추가하도록 변경되었습니다. c_인스턴스 기타 등등. 이것이 무차별적인 힘이라는 것을 쉽게 알 수 있습니다.
모델의 프로그래밍을 방해할 수 있는 의사소통 메커니즘입니다.

이는 어려운 문제가 있는 경우 객체가 서로에 대해 알 수 없다는 의미는 아닙니다.
그러나 종종 모델은 다음과 같은 경우 더 유연하게 만들어질 수 있습니다.
상호 작용은 컴파일 타임에 덜 제한됩니다.

이는 네트워크 시뮬레이션 연구에서 추상적인 문제가 아니라 오히려
연구자가 확장하거나 수정하려고 할 때 이전 시뮬레이터의 문제 원인
(연구에서 하기 쉬운 것처럼) 다양한 일을 하기 위한 시스템. 예를 들어,
TCP와 IP 사이에 IPsec 보안 프로토콜 하위 계층을 추가하려는 사용자:

------------ -----------
| TCP | | TCP |
------------ -----------
| 된다 -> |
----------- -----------
| IP | | IPsec |
----------- -----------
|
-----------
| IP |
-----------

시뮬레이터가 가정을 하고 코드에 하드 코딩된 경우 해당 IP는 항상 다음과 같이 말합니다.
위의 전송 프로토콜을 사용하면 사용자는 시스템을 해킹하여 정보를 얻어야 할 수도 있습니다.
원하는 상호 연결. 이는 분명히 일반적인 디자인을 위한 최적의 방법은 아닙니다.
모의 실험 장치.

콜백 배경
알림:
콜백 프로그래밍에 익숙한 독자는 이 튜토리얼 섹션을 건너뛸 수 있습니다.

위의 문제를 해결할 수 있는 기본 메커니즘은 다음과 같습니다. 콜백.
궁극적인 목표는 하나의 코드 조각이 함수(또는 C++의 메서드)를 호출할 수 있도록 하는 것입니다.
특정 모듈 간 종속성이 없습니다.

이는 궁극적으로 일종의 간접적인 방법이 필요하다는 것을 의미합니다.
함수를 변수로 호출합니다. 이 변수를 함수 포인터 변수라고 합니다.
함수와 함수 포인터 사이의 관계는 실제로 다르지 않습니다.
객체와 객체에 대한 포인터의 것입니다.

C에서 함수에 대한 포인터의 표준 예는
함수 반환 정수에 대한 포인터(PFI). 하나의 int 매개변수를 취하는 PFI의 경우, 이는
다음과 같이 선언될 수 있습니다:

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

여기서 얻는 것은 단순히 이름이 붙은 변수입니다. 피피 값 0으로 초기화됩니다.
이 포인터를 의미 있는 것으로 초기화하려면
일치하는 서명으로 기능합니다. 이 경우:

int MyFunction(int 인수) {}

이 대상이 있는 경우 다음과 같이 함수를 가리키도록 변수를 초기화할 수 있습니다.

pfi = 내기능;

그런 다음 보다 암시적인 호출 형식을 사용하여 MyFunction을 간접적으로 호출할 수 있습니다.

int 결과 = (*pfi) (1234);

이것은 함수 포인터를 역참조하는 것처럼 보이기 때문에 암시적입니다.
포인터를 역 참조하는 것처럼. 그러나 일반적으로 사람들은
컴파일러가 무슨 일이 일어나고 있는지 알고 있고 더 짧은 형식을 사용할 것이라는 사실:

정수 결과 = pfi(1234);

함수 포인터는 값 의미를 따르므로 다른 함수처럼 전달할 수 있습니다.
다른 가치. 일반적으로 비동기 인터페이스를 사용할 때 일부 엔터티를 전달합니다.
이와 같이 작업을 수행하는 함수에 전화 뒤로 그것을 당신에게 알리려고
완전한. 간접 참조를 따르고 제공된 함수를 실행하여 콜백합니다.

C++에서는 객체가 더 복잡해졌습니다. 위의 PFI와 비유하면 다음과 같습니다.
포인터 대신 int(PMI)를 반환하는 멤버 함수에 대한 포인터가 있습니다.
int(PFI)를 반환하는 함수입니다.

간접 참조를 제공하는 변수 선언은 약간 다르게 보입니다.

int (MyClass::*pmi) (int arg) = 0;

이는 이름이 지정된 변수를 선언합니다. 오후 이전 예제에서 이름이 지정된 변수를 선언한 것처럼
피피. 특정 클래스의 인스턴스 메서드를 호출하는 것이기 때문에 다음과 같이 해야 합니다.
클래스에서 해당 메서드를 선언합니다.

클래스 마이클래스 {
공공의:
int MyMethod(int 인수);
};

이 클래스 선언이 주어지면 해당 변수를 다음과 같이 초기화합니다.

pmi = &MyClass::MyMethod;

메소드를 구현하는 코드의 주소를 변수에 할당하여 완료합니다.
간접. 메소드를 호출하려면 코드에 바늘. 이 차례로,
참조할 MyClass 객체가 있어야 함을 의미합니다. 이에 대한 단순한 예는 다음과 같습니다.
간접적으로 메소드 호출(가상 함수를 생각해 보세요):

int (MyClass::*pmi) (int arg) = 0; // PMI 선언
pmi = &MyClass::MyMethod; // 구현 코드를 가리킨다.

MyClass myClass; // 클래스의 인스턴스가 필요합니다.
(myClass.*pmi) (1234); // 객체 ptr을 사용하여 메서드 호출

C 예제와 마찬가지로 다른 모듈에 대한 비동기 호출에서 이를 사용할 수 있습니다.
어느 것 전화 뒤로 메소드와 객체 포인터를 사용합니다. 간단한 확장
객체와 PMI 변수에 대한 포인터를 전달하는 것을 고려할 수 있습니다. 모듈
그냥 할 것입니다 :

(*objectPtr.*pmi)(1234);

원하는 객체에 대해 콜백을 실행합니다.

이때 누군가는 이렇게 물을 수도 있다. 뭐지 전에, 포인트? 호출된 모듈은 다음을 이해해야 합니다.
콜백을 적절하게 만들기 위해 호출 객체의 구체적인 유형입니다. 왜 안 돼
이것을 받아들이고 올바른 유형의 객체 포인터를 전달하고 수행하십시오. 객체->방법(1234) in
콜백 대신 코드? 이것이 바로 위에서 설명한 문제입니다. 무엇인가요
호출된 클래스에서 호출 함수를 완전히 분리하는 방법이 필요합니다. 이것
요구 사항은 다음의 개발로 이어졌습니다. 펑터.

펑터는 1960년대에 발명된 클로저라고 불리는 것의 파생물입니다. 그것은
기본적으로 어떤 상태를 포함하는 패키지화된 함수 호출일 뿐입니다.

펑터에는 상속을 통해 관련된 특정 부분과 일반 부분의 두 부분이 있습니다.
호출 코드(콜백을 실행하는 코드)는 일반 오버로드된 코드를 실행합니다.
연산자 () 콜백이 호출되도록 하는 일반 펑터입니다. 호출된 코드(
콜백하려는 코드)의 특수한 구현을 제공해야 합니다.
전에, 연산자 () 긴밀한 결합을 일으킨 클래스별 작업을 수행하는 클래스
위의 문제.

특정 펑터와 그 오버로드 연산자 () 생성된 후 호출된 코드
콜백을 실행할 모듈에 특수 코드를 제공합니다(호출
암호).

호출 코드는 일반 펑터를 매개변수로 사용하므로 암시적 캐스트가 수행됩니다.
함수 호출에서 특정 기능자를 일반 기능자로 변환합니다. 이는 다음을 의미합니다.
호출 모듈은 일반 펑터 유형을 이해하면 됩니다. 분리되어 있습니다
호출 코드에서 완전히.

특정 펑터를 만드는 데 필요한 정보는 객체 포인터와
메소드 주소에 대한 포인터.

일어나야 할 일의 본질은 시스템이
펑터:

주형
클래스 펑터
{
공공의:
가상 정수 연산자() (T arg) = 0;
};

호출자는 실제로 구현하기 위해 존재하는 펑터의 특정 부분을 정의합니다.
특정 운영자() 방법:

주형
특정Functor 클래스 : 공용 Functor
{
공공의:
특정 함수(T* p, int (T::*_pmi)(ARG arg))
{
m_p = p;
m_pmi = _pmi;
}

가상 정수 연산자() (ARG 인수)
{
(*m_p.*m_pmi)(arg);
}
비공개 :
int (T::*m_pmi)(ARG 인수);
T* m_p;
};

사용법의 예는 다음과 같습니다.

클래스 A
{
공공의:
A (int a0) : a (a0) {}
int 안녕하세요 (int b0)
{
std::cout << "안녕하세요 A님, a = " << a << " b0 = " << b0 << std::endl;
}
정수
};

int main ()
{
A a(10);
특정 함수 sf(&a, &A::안녕하세요);
sf(5);
}

알림:
이전 코드는 실제 ns-3 코드가 아닙니다. 에만 사용되는 단순한 예제 코드입니다.
관련된 개념을 설명하고 시스템을 더 잘 이해하는 데 도움이 됩니다. 하지 마라
이 코드는 ns-3 트리 어디에서나 찾을 수 있습니다.

위 클래스에는 두 개의 변수가 정의되어 있습니다. m_p 변수는
객체 포인터이고 m_pmi는 함수의 주소를 포함하는 변수입니다.
실행하다.

언제 운영자() 호출되면 다음과 함께 제공된 메소드를 호출합니다.
C++ PMI 구문을 사용하는 객체 포인터.

이를 사용하기 위해 일반 펑터를 사용하는 일부 모델 코드를 선언할 수 있습니다.
매개 변수 :

void LibraryFunction(펑터 펑터);

모델과 대화하는 코드는 특정 펑터를 구축하여 이를 전달합니다.
라이브러리함수:

MyClass myClass;
특정 함수 functor(&myclass, MyClass::MyMethod);

인셀덤 공식 판매점인 라이브러리함수 완료되면 다음을 사용하여 콜백을 실행합니다. 운영자() 일반에
functor가 전달되었으며 이 특별한 경우에는 정수 인수를 제공합니다.

무효화
LibraryFunction(펑터 펑터)
{
// 라이브러리 함수 실행
펑터(1234);
}

그것을주의해라 라이브러리함수 특정 유형의 클라이언트와 완전히 분리됩니다.
연결은 Functor 다형성을 통해 이루어집니다.

콜백 API NS-3 functor 메커니즘을 사용하여 객체 지향 콜백을 구현합니다.
C++ 템플릿을 기반으로 하는 이 콜백 API는 유형이 안전합니다. 즉, 정적 수행을 수행합니다.
호출자와 호출 수신자 사이에 적절한 서명 호환성을 적용하기 위한 유형 검사입니다. 그것은
따라서 기존 함수 포인터보다 사용하기에 유형이 더 안전하지만 구문은
처음에는 당당해 보인다. 이 섹션은 콜백 시스템을 안내하도록 설계되었습니다.
고객님께서 편안하게 사용하실 수 있도록 NS-3.

사용 전에, 콜백 API
콜백 API는 매우 간단하며 다음 두 가지 서비스만 제공합니다.

1. 콜백 유형 선언: 주어진 시그니처를 사용하여 콜백 유형을 선언하는 방법,
과,

2. 콜백 인스턴스화: 템플릿 생성 전달 콜백을 인스턴스화하는 방법
다른 C++ 클래스 멤버 메서드나 C++ 함수에 대한 호출을 전달할 수 있습니다.

이는 다음을 기반으로 한 예제를 살펴보면서 가장 잘 관찰할 수 있습니다. 샘플/main-callback.cc.

사용 전에, 콜백 API 정적 인 기능
함수를 고려해보세요:

정적 이중
CbOne(더블 a, 더블 b)
{
std::cout << "cbOne a=" << a << ", b=" << b << std::endl;
반환;
}

다음 기본 프로그램 조각도 고려하세요.

int main (int argc, char *argv[])
{
// 반환 유형: double
// 첫 번째 인수 유형: double
// 두 번째 인수 유형: double
콜백 하나;
}

이것은 C 스타일 콜백의 예입니다.
바늘. 함수 템플릿 콜백 본질적으로 변수 선언입니다.
함수에 대한 포인터를 포함합니다. 위의 예에서는 포인터를 명시적으로 표시했습니다.
정수를 반환하고 단일 정수를 매개변수로 취하는 함수에
콜백 템플릿 함수는 그것의 일반적인 버전입니다. 이는 유형을 선언하는 데 사용됩니다.
콜백의.

알림:
C++ 템플릿에 익숙하지 않은 독자는 상담할 수 있습니다.
http://www.cplusplus.com/doc/tutorial/templates/.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 콜백 템플릿에는 하나의 필수 인수가 필요합니다(함수의 반환 유형은
이 콜백에 할당됨) 및 최대 XNUMX개의 선택적 인수(각각 지정)
인수 유형(특정 콜백 함수에 XNUMX개 이상의 인수가 있는 경우,
그런 다음 콜백 구현을 확장하여 처리할 수 있습니다.)

따라서 위의 예에서는 "one"이라는 콜백을 선언했습니다.
함수 포인터를 보유하십시오. 보유할 함수의 서명이 반환되어야 합니다.
double이며 두 개의 double 인수를 지원해야 합니다. 다음과 같은 함수를 전달하려고 하면
서명이 선언된 콜백과 일치하지 않으면 컴파일 오류가 발생합니다. 또한 만약에
호환되지 않는 콜백을 콜백에 할당하려고 하면 컴파일은 성공하지만
런타임 NS_FATAL_ERROR가 발생합니다. 샘플 프로그램
src/core/examples/main-callback.cc 마지막에 이러한 두 가지 오류 사례를 모두 보여줍니다.
전에, 본관() 프로그램)

이제 이 콜백 인스턴스와 실제 대상 함수를 연결해야 합니다.
(CbOne). 위에서 CbOne에는 콜백과 동일한 함수 서명 유형이 있다는 점에 유의하세요.
이건 중요하다. 이러한 적절한 유형의 함수를 이 콜백에 전달할 수 있습니다.
이를 좀 더 자세히 살펴보겠습니다.

static double CbOne(더블 a, 더블 b) {}
^^
| | |
| | |
콜백 하나;

일치하는 서명이 있는 경우에만 함수를 콜백에 바인딩할 수 있습니다. 첫번째
템플릿 인수는 반환 유형이고 추가 템플릿 인수는 유형입니다.
함수 서명의 인수 중 하나입니다.

이제 콜백 "one"을 해당 서명과 일치하는 함수에 바인딩해 보겠습니다.

// cbOne 함수를 가리키는 콜백 인스턴스 구축
one = MakeCallback(&CbOne);

이 호출은 MakeCallback 본질적으로 특수한 펑터 중 하나를 만드는 것입니다.
위에 언급했듯이. 다음을 사용하여 선언된 변수 콜백 템플릿 기능은
일반 펑터의 역할을 하게 됩니다. 과제 = MakeCallback (&CbXNUMX) is
호출 수신자에게 알려진 특수 기능자를 일반 기능자로 변환하는 캐스트
발신자에게 알려졌습니다.

그런 다음 프로그램 후반부에 콜백이 필요한 경우 다음과 같이 사용할 수 있습니다.

NS_ASSERT(!one.IsNull());

// 콜백 인스턴스를 통해 cbOne 함수 호출
이중 retOne;
retOne = 10.0(20.0, XNUMX);

확인 IsNull() 콜백이 null이 아닌지 확인합니다. 즉, 함수가 있는지 확인합니다.
이 콜백 뒤에서 호출합니다. 그 다음에, 하나() 일반을 실행합니다 운영자() 그것은 정말로
특정 구현으로 인해 과부하가 발생했습니다. 운영자() 다음과 같은 결과를 반환합니다.
CbOne() 직접 전화를 걸었습니다.

사용 전에, 콜백 API 회원 기능
일반적으로 정적 함수를 호출하지 않고 대신 공개 멤버 함수를 호출합니다.
객체. 이 경우 MakeCallback 함수에 추가 인수가 필요합니다.
함수가 호출되어야 하는 객체를 시스템에 알려줍니다. 이 예를 고려해보세요.
또한 main-callback.cc에서:

클래스 MyCb {
공공의:
int CbTwo(더블 a) {
std::cout << "cbTwo a=" << a << std::endl; 호출
반환 -5;
}
};

정수 메인()
{
...
// 반환 유형: int
// 첫 번째 인수 유형: double
콜백 둘;
MyCb cb;
// MyCb::cbTwo를 가리키는 콜백 인스턴스 구축
two = MakeCallback(&MyCb::CbTwo, &cb);
...
}

여기서는 추가 객체 포인터를 MakeCallback<> 기능. 에서 회상
그 위의 배경 섹션 운영자() 멤버 구문에 대한 포인터를 사용합니다.
개체에서 실행됩니다.

가상 정수 연산자() (ARG 인수)
{
(*m_p.*m_pmi)(arg);
}

그래서 우리는 두 개의 변수를 제공해야 했습니다(m_p and m_pmi) 우리가 구체적인 것을 만들었을 때
펑터. 라인:

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

바로 그런 일을 합니다. 이 경우, 언제 () 호출됩니다:

int 결과 = 1.0(XNUMX);

결과적으로 CbXNUMX 가 가리키는 객체의 멤버 함수(메서드)
&cb.

건물 null로 콜백
콜백이 null일 수도 있습니다. 따라서 사용하기 전에 확인하는 것이 현명할 수 있습니다.
단순히 전달하는 것보다 더 나은 null 콜백을 위한 특별한 구성이 있습니다.
인수로 "0"; 그것은 MakeNullCallback<> 구성 :

XNUMX개 = MakeNullCallback ();
NS_ASSERT(two.IsNull());

null 콜백을 호출하는 것은 null 함수 포인터를 호출하는 것과 같습니다.
실행 시간.

경계 콜백
functor 개념에 대한 매우 유용한 확장은 Bound Callback의 확장입니다. 이전에는
클로저는 원래 나중을 위해 패키지된 함수 호출이었다고 언급되었습니다.
실행. 위의 모든 콜백 설명에는
나중에 사용할 수 있도록 매개변수를 패키지화합니다. 콜백 을 통해 호출됩니다 운영자().
모든 매개변수는 호출 함수에 의해 제공됩니다.

클라이언트 함수(콜백을 제공하는 함수)가 다음을 수행하도록 허용하려면 어떻게 해야 합니까?
일부 매개변수를 제공하시겠습니까? 알렉산드레스쿠 클라이언트가 다음을 수행하도록 허용하는 프로세스를 호출합니다.
매개변수 중 하나를 지정하십시오. "제본". 매개변수 중 하나 운영자() 있다
클라이언트에 의해 바인딩(고정)되었습니다.

우리의 pcap 추적 코드 중 일부는 이에 대한 좋은 예를 제공합니다. 하는 기능이 있습니다
패킷이 수신될 때마다 호출되어야 합니다. 이 함수는 다음과 같은 개체를 호출합니다.
실제로 패킷을 pcap 파일 형식으로 디스크에 씁니다. 이 중 하나의 서명
기능은 다음과 같습니다:

정적 무효 DefaultSink(Ptr 파일, PT 피);

static 키워드는 이것이 필요하지 않은 정적 함수임을 의미합니다. 포인터, 그래서
C 스타일 콜백을 사용하게 됩니다. 우리는 호출 코드가 다음 사항을 알아야 하는 것을 원하지 않습니다.
패킷 이외의 것. 호출 코드에서 원하는 것은 다음과 같은 호출입니다.

m_promiscSnifferTrace(m_currentPkt);

우리가 하고 싶은 일은 바인딩 전에, 포인트 파일 특정 콜백에
생성될 때 구현하고 준비합니다. 운영자() 콜백의
해당 매개변수를 무료로 제공하세요.

우리는 MakeBound콜백 이를 위한 템플릿 함수입니다. 똑같이 걸리네
매개변수를 MakeCallback 템플릿 함수일 뿐 아니라 매개변수도 사용합니다.
경계. 위 예의 경우:

MakeBoundCallback(&DefaultSink, 파일);

추가 경계를 추가하는 방법을 알고 있는 특정 콜백 구현을 생성합니다.
인수. 개념적으로 위에서 설명한 특정 기능을 하나 이상의 기능으로 확장합니다.
바인딩된 인수:

주형
특정Functor 클래스 : 공용 Functor
{
공공의:
특정Functor(T* p, int (T::*_pmi)(ARG arg), BOUND_ARGboundArg)
{
m_p = p;
m_pmi = pmi;
m_boundArg =boundArg;
}

가상 정수 연산자() (ARG 인수)
{
(*m_p.*m_pmi)(m_boundArg, arg);
}
비공개 :
무효 (T::*m_pmi)(ARG 인수);
T* m_p;
BOUND_ARG m_boundArg;
};

특정 functor가 생성되면 바인딩된 인수가
펑터/콜백 객체 자체. 때 운영자() 단일로 호출됩니다.
매개변수는 다음과 같습니다.

m_promiscSnifferTrace(m_currentPkt);

의 구현 운영자() 실제 함수 호출에 바인딩된 매개변수를 추가합니다.

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

두 개 또는 세 개의 인수를 바인딩하는 것도 가능합니다. 다음과 같은 기능이 있다고 가정해 보겠습니다.
서명:

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

다음과 같이 처음 두 인수를 바인딩하는 바인딩된 콜백을 만들 수 있습니다.

MakeBoundCallback(&NotifyEvent, a1, b1);

가정 a1 and b1 유형의 객체입니다 A and B 각기. 마찬가지로 XNUMX인용
인수 중 하나는 서명이 있는 기능을 갖습니다.

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

다음을 사용하여 세 가지 인수 바인딩을 완료했습니다.

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

다시 가정 a1, b1 and c1 유형의 객체입니다 A, B and C 각각.

이러한 종류의 바인딩은 시뮬레이션에서 객체 간에 정보를 교환하는 데 사용될 수 있습니다.
특히 바인딩된 콜백은 추적된 콜백으로 사용될 수 있습니다. 이에 대해서는 다음에서 설명합니다.
다음 섹션.

추적 된 콜백
자리 표시 자 일부

콜백 위치 in NS-3
콜백이 자주 사용되는 곳 NS-3? 다음은 좀 더 눈에 띄는 것들입니다.
일반 사용자:

· 소켓 API

· 레이어-2/레이어-3 API

· 추적 하위 시스템

· IP와 라우팅 하위 시스템 간의 API

실시 세부설명
위의 코드 조각은 단순하며 메커니즘을 설명하기 위해 설계되었습니다.
그 자체. 실제 콜백 코드는 상당히 복잡하고 템플릿 집약적이며
코드에 대한 깊은 이해는 필요하지 않습니다. 관심이 있는 경우 전문가 사용자는 다음을 찾을 수 있습니다.
다음은 유용합니다.

코드는 원래 다음에 설명된 기술을 기반으로 작성되었습니다.
http://www.codeproject.com/cpp/TTLFunction.asp. 이후에 다음과 같이 다시 작성되었습니다.
에 설명된 아키텍처 현대 C + + 디자인, 일반적인 프로그램 작성 and 디자인 패턴
적용된, 알렉산드레스쿠, 5, 일반화 펑터.

이 코드는 다음을 사용합니다.

· 기본 템플릿 매개변수를 사용하면 사용자가 다음 작업을 수행할 때 빈 매개변수를 지정하지 않아도 됩니다.
매개변수 수가 지원되는 최대 수보다 작습니다.

· pimpl 관용어: 콜백 클래스는 값으로 전달되고 핵심을 위임합니다.
pimpl 포인터에 대한 작업입니다.

· CallbackImpl FunctorCallbackImpl에서 파생된 두 개의 pimpl 구현을 사용할 수 있습니다.
MemPtrCallbackImpl은 멤버에 대한 포인터와 함께 사용할 수 있는 반면 모든 펑터 유형을 사용합니다.
기능.

· 콜백의 값 의미를 구현하기 위한 참조 목록 구현.

이 코드는 Alexandrescu 구현과 가장 크게 다릅니다.
콜백 인수의 유형을 지정하고 전달하려면 유형 목록을 사용하세요. 물론,
또한 복사 파괴 의미론을 사용하지 않고 참조 목록에 의존합니다.
autoPtr은 포인터를 유지합니다.

목적 모델
NS-3 기본적으로 C++ 개체 시스템입니다. 객체는 다음과 같이 선언되고 인스턴스화될 수 있습니다.
일반적으로 C++ 규칙에 따라. NS-3 또한 다음과 같이 전통적인 C++ 개체에 몇 가지 기능을 추가합니다.
더 나은 기능과 특징을 제공하기 위해 아래에 설명되어 있습니다. 이 매뉴얼 장은
독자에게 소개하려는 의도 NS-3 객체 모델.

이 섹션에서는 다음을 위한 C++ 클래스 디자인을 설명합니다. NS-3 사물. 간단히 말해서 여러 디자인
사용되는 패턴에는 고전적인 객체 지향 디자인(다형성 인터페이스 및
구현), 인터페이스와 구현의 분리, 비가상 공용
인터페이스 디자인 패턴, 객체 집합 기능, 참조 카운팅
메모리 관리. COM 또는 Bonobo와 같은 구성 요소 모델에 익숙한 사용자는
디자인 요소를 인식하고 NS-3 객체 집합 모델이지만 NS-3
디자인은 어느 쪽에도 엄격하게 따르지 않습니다.

객체 지향 행동
일반적으로 C++ 개체는 일반적인 개체 지향 기능(추상화,
캡슐화, 상속, 다형성)은 고전적인 객체지향의 일부입니다.
디자인. NS-3 객체는 이러한 속성을 사용합니다. 예를 들어:

수업 주소
{
공공의:
주소 ();
주소(uint8_t 유형, const uint8_t *버퍼, uint8_t len);
주소(const 주소 및 주소);
주소 &연산자 = (const 주소 &address);
...
비공개 :
uint8_t m_type;
uint8_t m_len;
...
};

목적 기지 수업
에는 세 가지 특수 기본 클래스가 사용됩니다. NS-3. 이러한 기본을 상속하는 클래스
클래스는 특별한 속성을 가진 객체를 인스턴스화할 수 있습니다. 이러한 기본 클래스는 다음과 같습니다.

· 수업 목적

· 수업 객체베이스

· 수업 SimpleRefCount

반드시 그럴 필요는 없습니다. NS-3 객체는 이 클래스에서 상속되지만, 객체는
특별한 속성. 클래스에서 파생된 클래스 목적 다음 속성을 얻습니다.

· NS NS-3 유형 및 속성 시스템(속성 참조)

· 객체 집합 시스템

· 스마트 포인터 참조 카운팅 시스템(클래스 Ptr)

클래스에서 파생된 클래스 객체베이스 위의 처음 두 속성을 가져오지만 가져오지 않음
스마트 포인터를 얻으세요. 클래스에서 파생된 클래스 SimpleRefCount:만 얻으세요
스마트 포인터 참조 카운팅 시스템.

실제로 수업을 목적 위 세 가지의 변형입니다. NS-3 개발자는
가장 흔하게 접하게 됩니다.

메모리 구축 and 수업 Ptr
C++ 프로그램의 메모리 관리는 복잡한 프로세스이며 종종 잘못 수행되거나
일관되지 않게. 우리는 다음과 같이 참조 카운팅 설계를 결정했습니다.

참조 카운트를 사용하는 모든 객체는 내부 참조 카운트를 유지하여 결정합니다.
객체가 안전하게 자신을 삭제할 수 있는 경우. 포인터를 얻을 때마다
인터페이스에서는 객체의 참조 횟수가 다음을 호출하여 증가합니다. 참조(). 그것은
명시적으로 포인터를 사용하는 사용자의 의무 참조 해제() 완료되면 포인터입니다. 언제
참조 횟수가 XNUMX으로 떨어지면 객체가 삭제됩니다.

· 클라이언트 코드가 객체 생성을 통해 객체 자체로부터 포인터를 얻으면,
또는 GetObject를 통해 참조 횟수를 늘릴 필요가 없습니다.

· 클라이언트 코드가 다른 소스에서 포인터를 얻을 때(예: 포인터 복사)
전화 참조() 참조 카운트를 증가시킵니다.

· 객체 포인터의 모든 사용자는 호출해야 합니다 참조 해제() 참조를 해제합니다.

전화에 대한 부담 참조 해제() 참조 카운팅을 사용하면 다소 안심됩니다.
아래에 설명된 스마트 포인터 클래스.

참조 계산되지 않은 객체를 명시적으로 할당하려는 하위 수준 API를 사용하는 사용자
힙에서는 new 연산자를 사용하여 이러한 객체를 삭제하는 일을 담당합니다.

참조 세는 스마트 한 포인터 (부분)
호출 참조() and 참조 해제() 항상 귀찮을 테니 NS-3 스마트함을 제공합니다
포인터 클래스 Ptr 와 유사한 부스트::intrusive_ptr. 이 스마트 포인터 클래스는 다음을 가정합니다.
기본 유형은 다음 쌍을 제공합니다. 참조 and 참조 해제 예상되는 방법
객체 인스턴스의 내부 참조 횟수를 늘리거나 줄입니다.

이 구현을 사용하면 스마트 포인터를 일반 포인터처럼 조작할 수 있습니다.
포인터: XNUMX과 비교하고, 다른 포인터와 비교하고, XNUMX을 할당할 수 있습니다.
그것 등등

다음을 사용하여 이 스마트 포인터에서 원시 포인터를 추출할 수 있습니다. GetPointer()
and 픽포인터() 방법.

새로 추가된 개체를 스마트 포인터에 저장하려면 다음을 사용하는 것이 좋습니다.
CreateObject 템플릿 함수는 객체를 생성하고 이를 스마트 포인터에 저장합니다.
메모리 누수를 방지하세요. 이 기능들은 정말 작은 편의 기능이고 그 목적은
단지 약간의 타이핑 시간을 절약하기 위한 것입니다.

CreateObject and 만들기
C++의 개체는 정적으로, 동적으로 또는 자동으로 생성될 수 있습니다. 이것은 사실이다
for NS-3 또한 시스템의 일부 개체에는 사용 가능한 추가 프레임워크가 있습니다.
특히, 참조 계산된 객체는 일반적으로 템플릿 생성 또는 생성을 사용하여 할당됩니다.
CreateObject 메서드는 다음과 같습니다.

클래스에서 파생된 객체의 경우 목적:

포인트 장치 = CreateObject ();

다음을 사용하여 그러한 객체를 생성하지 마십시오. 연산자 ; 사용하여 생성 객체 생성()
대신.

클래스에서 파생된 객체의 경우 SimpleRefCount또는 사용을 지원하는 기타 개체
스마트 포인터 클래스인 템플릿 도우미 기능을 사용할 수 있으며 사용을 권장합니다.

Ptr b = 생성 ();

이것은 단순히 참조 카운팅을 올바르게 처리하는 new 연산자를 둘러싼 래퍼입니다.
시스템.

요약하면 다음을 사용하십시오. 만들다 B가 객체는 아니지만 참조 계산만 사용하는 경우(예:
패킷) 및 사용 CreateObject B가 다음에서 파생된 경우 ns3::객체.

집합
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 객체 집합 시스템은 다음과 같은 인식에 의해 크게 동기 부여됩니다.
일반적인 사용 사례 NS-2 확장을 위해 상속과 다형성을 사용했습니다.
프로토콜 모델. 예를 들어 RenoTcpAgent와 같은 특수 버전의 TCP는 파생됩니다.
TcpAgent 클래스의 함수를 재정의합니다.

그러나, XNUMX가지 문제가 발생했습니다. NS-2 모델은 하향세이며 "약한 기반"입니다.
클래스." 다운캐스팅은 객체에 대한 기본 클래스 포인터를 사용하고
포인터를 명시적으로 캐스팅하는 데 사용되는 유형 정보를 찾기 위해 런타임에 쿼리
서브클래스 API를 사용할 수 있도록 서브클래스 포인터에 연결합니다. 약한 기본 클래스는
클래스가 효과적으로 재사용(파생)될 수 없을 때 발생하는 문제
필요한 기능이 부족하여 개발자가 기본 클래스를 수정해야 하고
기본 클래스 API 호출이 급증하며 그 중 일부는 의미상 맞지 않을 수 있습니다.
모든 하위 클래스에 적합합니다.

NS-3 이러한 문제를 피하기 위해 쿼리 인터페이스 디자인 패턴 버전을 사용하고 있습니다.
이 디자인은 다음 요소를 기반으로 합니다. 구성 요소 목적 모델 and GNOME 보노보 이기는하지만
교체 가능한 구성 요소의 전체 바이너리 수준 호환성은 지원되지 않으며
구문을 단순화하고 모델 개발자에게 미치는 영향을 단순화하려고 노력했습니다.


집합
노드 집계를 사용한 좋은 예입니다. NS-3. 파생되지 않았음을 참고하세요.
노드 클래스 NS-3 수업과 같은 인터넷노드. 대신 구성요소(프로토콜)는 다음과 같습니다.
노드로 집계됩니다. 일부 Ipv4 프로토콜이 노드에 추가되는 방법을 살펴보겠습니다.:

정적 공극
AddIpv4Stack(Ptr 마디)
{
포인트 ipv4 = 생성객체 ();
ipv4->SetNode(노드);
노드->AggregateObject(ipv4);
포인트 ipv4Impl = CreateObject ();
ipv4Impl->SetIpv4(ipv4);
노드->AggregateObject(ipv4Impl);
}

IPv4 프로토콜은 다음을 사용하여 생성됩니다. 객체 생성(). 그런 다음 집계됩니다.
노드에. 이러한 방식으로 Node 기본 클래스는 사용자가 허용하도록 편집할 필요가 없습니다.
Ipv4 인터페이스에 액세스하기 위한 기본 클래스 노드 포인터를 사용합니다. 사용자는 노드에 다음을 요청할 수 있습니다.
런타임 시 Ipv4 인터페이스에 대한 포인터입니다. 사용자가 노드에 요청하는 방법은
다음 하위 섹션.

동일한 유형의 개체를 두 개 이상 집계하는 것은 프로그래밍 오류입니다.
an ns3::객체. 따라서 예를 들어 집계는 모든 데이터를 저장하는 옵션이 아닙니다.
노드의 활성 소켓.

객체 가져오기
GetObject는 안전한 다운캐스팅을 달성하고 인터페이스를 허용하는 형식이 안전한 방법입니다.
물체에서 발견되었습니다.

노드 포인터를 고려하십시오 m_node 이는 다음을 구현한 Node 객체를 가리킵니다.
이전에는 IPv4가 여기에 집계되었습니다. 클라이언트 코드는 기본 경로를 구성하려고 합니다. 에게
그렇게 하려면 IP 전달에 대한 인터페이스가 있는 노드 내의 개체에 액세스해야 합니다.
구성. 다음을 수행합니다.

포인트 ipv4 = m_node->GetObject ();

실제로 노드에 집계된 Ipv4 개체가 없는 경우 메서드는 다음을 수행합니다.
null을 반환합니다. 따라서 그러한 함수의 반환 값을 확인하는 것이 좋습니다.
부르다. 성공하면 이제 사용자는 이전에 사용했던 Ipv4 개체에 대해 Ptr을 사용할 수 있습니다.
노드에 집계됩니다.

집계를 사용하는 방법의 또 다른 예는 선택적 모델을 객체에 추가하는 것입니다. 을 위한
예를 들어, 기존 Node 개체에는 "에너지 모델" 개체가 집계되어 있을 수 있습니다.
런타임(노드 클래스를 수정하고 다시 컴파일하지 않음) 기존 모델(예:
무선 네트워크 장치)는 나중에 에너지 모델에 대해 "GetObject"를 수행하고 적절하게 작동할 수 있습니다.
인터페이스가 기본 Node 객체에 내장되었거나 다음으로 집계된 경우
런타임에요. 그러나 다른 노드는 에너지 모델에 대해 아무것도 알 필요가 없습니다.

우리는 이 프로그래밍 모드에서 개발자가 수정할 필요성이 훨씬 줄어들기를 바랍니다.
기본 클래스.

목적 공장
일반적인 사용 사례는 유사하게 구성된 객체를 많이 만드는 것입니다. 반복적으로 할 수 있다
전화 객체 생성() 하지만 공장 디자인 패턴도 사용 중입니다. NS-3 시스템.
이는 "도우미" API에서 많이 사용됩니다.

클래스 객체공장 객체를 인스턴스화하고 속성을 구성하는 데 사용할 수 있습니다.
해당 개체:

void SetTypeId(TypeId tid);
void Set (std::string 이름, const AttributeValue &value);
포인트 생성 (무효) const;

첫 번째 방법을 사용하면 다음을 사용할 수 있습니다. NS-3 객체 유형을 지정하는 TypeId 시스템
만들어진. 두 번째는 생성될 객체에 대한 속성을 설정할 수 있게 해줍니다.
세 번째는 객체 자체를 생성할 수 있게 해줍니다.

예 :

ObjectFactory 팩토리;
// 이 팩토리가 FriisPropagationLossModel 유형의 객체를 생성하도록 만듭니다.
Factory.SetTypeId("ns3::FriisPropagationLossModel")
// 이 팩토리 객체가 속성의 기본값을 변경하도록 만듭니다.
// 이후에 생성된 객체
Factory.Set("SystemLoss", DoubleValue(2.0));
// 그러한 객체를 하나 생성합니다
포인트 객체 = 공장.생성();
Factory.Set("SystemLoss", DoubleValue(3.0));
// 다른 SystemLoss를 사용하여 다른 개체를 만듭니다.
포인트 객체 = 공장.생성();

다운캐스팅
여러 번 제기된 질문은 "만약 내가 어떤 객체에 대한 기본 클래스 포인터(Ptr)를 가지고 있다면
객체를 사용하고 파생 클래스 포인터를 원합니다. C++ 동적 캐스트를 통해 다운캐스트해야 할까요?
파생 포인터를 얻어야 할까요, 아니면 객체 집합 시스템을 사용해야 할까요? GetObject<> ()
서브클래스 API에 대한 인터페이스에 대한 Ptr을 찾으려면?"

이에 대한 대답은 많은 상황에서 두 기술이 모두 작동한다는 것입니다. NS-3 를 제공합니다
객체 동적 캐스팅 구문을 훨씬 더 사용자화하기 위한 템플릿 함수
친숙한:

주형
포인트
다이나믹캐스트(Ptr const&p)
{
반환 포인트 (동적_캐스트 (PeekPointer(p)));
}

DynamicCast는 프로그래머가 기본 유형 포인터를 갖고 있고
서브클래스 포인터. GetObject는 집계된 다양한 개체를 찾을 때 작동하지만
DynamicCast와 동일한 방식으로 하위 클래스와 함께 작동합니다. 확실하지 않은 경우 프로그래머는
모든 경우에 작동하므로 GetObject를 사용하십시오. 프로그래머가 클래스 계층 구조를 알고 있는 경우
고려 중인 객체에 대해서는 DynamicCast를 사용하는 것이 더 직접적입니다.

구성 and Attributes
In NS-3 시뮬레이션에는 구성에 대한 두 가지 주요 측면이 있습니다.

· 시뮬레이션 토폴로지 및 객체 연결 방법.

· 토폴로지에서 인스턴스화된 모델이 사용하는 값.

이 장에서는 위의 두 번째 항목에 초점을 맞춥니다. NS-3 are
에 의해 구성, 문서화 및 수정 가능 NS-3 사용자. 그만큼 NS-3 속성 시스템 역시
시뮬레이터에서 추적 및 통계가 수집되는 방식을 뒷받침합니다.

이 장에서는 값을 설정하거나 수정하는 다양한 방법에 대해 논의합니다.
에 의해 사용되는 NS-3 모델 객체. 특이성이 높아지는 순서대로 다음과 같습니다.

┌────────────────────────────────┬─────────────── ───────────────────┐
│방법 │ 범위 │
├────────────────────────────────┼─────────────── ───────────────────┤
│기본 속성 값 설정 │ 모든 인스턴스에 영향 │
│속성이 │ 클래스에 정의된 경우. │
유형 ID 가져오기 (). │ │
└────────────────────────────────┴─────────────── ───────────────────┘

CommandLine │ 향후 모든 인스턴스에 영향을 미칩니다. │
구성::기본값 설정() │ │
구성 저장소 │ │
├────────────────────────────────┼─────────────── ───────────────────┤
객체공장 │ 생성된 모든 인스턴스에 영향을 미칩니다 │
│ │ 공장과 함께. │
├────────────────────────────────┼─────────────── ───────────────────┤
XHelperSet속성 () │ │에 의해 생성된 모든 인스턴스에 영향을 미칩니다.
│ │ 도우미. │
├────────────────────────────────┼─────────────── ───────────────────┤
마이클래스::SetX () │ 이 특정 인스턴스를 변경합니다. │
객체::SetAttribute () │ 일반적으로 이것이 유일한 형식입니다 │
구성::설정() │ 변경 예정 │
│ │ 시뮬레이션 후 인스턴스 │
│ │ 실행 중입니다. │
└────────────────────────────────┴─────────────── ───────────────────┘

"특이성"이란 테이블의 이후 행에 있는 메서드가 설정된 값을 재정의한다는 의미입니다.
일반적으로 이전 방법보다 더 적은 수의 인스턴스에 영향을 미칩니다.

속성 값 시스템의 세부 사항을 살펴보기 전에 몇 가지를 검토하는 것이 도움이 될 것입니다.
클래스의 기본 속성 목적.

목적 살펴보기
NS-3 기본적으로 C++ 개체 기반 시스템입니다. 이는 새로운 C++ 클래스가
(유형)은 평소와 같이 선언, 정의 및 하위 클래스화될 수 있습니다.

많은 NS-3 개체는 다음에서 상속됩니다. 목적 기본 클래스. 이 개체에는 몇 가지 추가 기능이 있습니다.
시스템을 구성하고 메모리 관리를 개선하기 위해 활용하는 속성
우리 개체 중:

· 클래스 이름을 클래스에 대한 많은 메타정보에 연결하는 "메타데이터" 시스템
다음을 포함한 객체:

· 하위 클래스의 기본 클래스,

· 서브클래스의 접근 가능한 생성자 세트,

· 서브클래스의 "속성" 세트,

· 각 속성을 설정할 수 있는지 또는 읽기 전용인지 여부

· 각 속성에 허용되는 값 범위.

· 메모리 관리를 위한 참조 카운팅 스마트 포인터 구현.

NS-3 속성 시스템을 사용하는 객체는 다음 중 하나에서 파생됩니다. 목적 or 객체베이스. 가장
NS-3 우리가 논의할 객체는 다음에서 파생됩니다. 목적, 그러나 일부는 스마트 외부에 있습니다.
포인터 메모리 관리 프레임워크는 다음에서 파생됩니다. 객체베이스.

이러한 개체의 몇 가지 속성을 검토해 보겠습니다.

스마트 한 포인터
에서 소개된 바와 같이 NS-3 지도 시간, NS-3 객체는 다음에 의해 관리되는 메모리입니다. 참고
세는 스마트 한 포인터 이행, 수업 Ptr.

스마트 포인터는 다음과 같은 분야에서 광범위하게 사용됩니다. NS-3 참조 전달을 피하기 위한 API
메모리 누수를 일으킬 수 있는 힙 할당 개체입니다. 가장 기본적인 사용법(구문)의 경우 다음을 처리합니다.
일반 포인터와 같은 스마트 포인터:

포인트 nd = ...;
nd->CallSomeFunction();
// 등.

그렇다면 이 예제의 첫 번째 줄에서처럼 객체에 대한 스마트 포인터를 어떻게 얻을 수 있을까요?

CreateObject
위에서 메모리 관리 및 클래스 Ptr에서 논의한 것처럼 가장 낮은 수준의 API에서 객체는
유형의 목적 다음을 사용하여 인스턴스화되지 않습니다. 연산자 평소와 같이 대신 템플릿을 사용하여
함수 호출 CreateObject ().

이러한 객체를 생성하는 일반적인 방법은 다음과 같습니다.

포인트 nd = CreateObject ();

이는 기능적으로 다음과 동일하다고 생각할 수 있습니다.

WifiNetDevice* nd = 새로운 WifiNetDevice();

다음에서 파생된 개체 목적 다음을 사용하여 힙에 할당해야 합니다. CreateObject (). 그
에서 파생 객체베이스같은 NS-3 도우미 기능과 패킷 헤더 및 트레일러,
스택에 할당할 수 있습니다.

일부 스크립트에서는 다음 내용이 많이 표시되지 않을 수 있습니다. CreateObject () 코드를 호출합니다. 이것은
실제로 작업을 수행하는 도우미 개체가 있기 때문입니다. CreateObject () 통화
당신을 위해.

유형 ID
NS-3 클래스에서 파생된 클래스 목적 라는 메타데이터 클래스를 포함할 수 있습니다. 유형 ID
객체 집합 및 구성 요소에 사용하기 위해 클래스에 대한 메타 정보를 기록합니다.
관리자 시스템:

· 클래스를 식별하는 고유한 문자열입니다.

· 메타데이터 시스템 내 하위 클래스의 기본 클래스입니다.

· 하위 클래스의 액세스 가능한 생성자 세트.

· 클래스의 공개적으로 액세스 가능한 속성("속성") 목록입니다.

목적 요약
이러한 개념을 모두 종합하여 구체적인 예를 살펴보겠습니다. 노드.

공개 헤더 파일 node.h 정적을 포함하는 선언이 있습니다 유형 ID 가져오기 ()
함수 호출 :

클래스 노드 : 공용 객체
{
공공의:
정적 TypeId GetTypeId (void);
...

이는 다음에서 정의됩니다. node.cc 파일은 다음과 같습니다.

유형 ID
노드::GetTypeId(무효)
{
static TypeId tid = TypeId ("ns3::Node")
.SetParent ()
.AddConstructor ()
.AddAttribute("장치 목록",
"이 노드와 연결된 장치 목록입니다.",
객체벡터값(),
MakeObjectVectorAccessor(&Node::m_devices),
MakeObjectVectorChecker ())
.AddAttribute("응용 프로그램 목록",
"이 노드와 연결된 애플리케이션 목록입니다.",
객체벡터값(),
MakeObjectVectorAccessor(&Node::m_applications),
MakeObjectVectorChecker ())
.AddAttribute("ID",
"이 노드의 ID(고유 정수)입니다.",
TypeId::ATTR_GET, // 가져오기만 허용합니다.
단위값(0),
MakeUintegerAccessor(&Node::m_id),
MakeUintegerChecker ())
;
정시 반환;
}

고려하다 유형 IDNS-3 목적 런타임 유형의 확장된 형태인 클래스
정보(RTTI). C++ 언어에는 다음을 지원하기 위해 간단한 종류의 RTTI가 포함되어 있습니다.
동적_캐스트 and Typeid 연산자.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 부모 설정 () 위 정의의 call은 우리의 정의와 함께 사용됩니다.
상속 트리에서 안전한 업캐스트 및 다운캐스트를 허용하는 객체 집계 메커니즘
...동안 객체 가져오기 (). 또한 하위 클래스가 상위 클래스의 속성을 상속할 수도 있습니다.
클래스입니다.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 AddConstructor () 호출은 추상 개체 팩토리와 함께 사용됩니다.
사용자에게 C++ 객체를 알도록 강요하지 않고 C++ 객체를 구성할 수 있는 메커니즘
그녀가 만들고 있는 객체의 구체적인 클래스.

세 가지 호출 속성 추가 () 주어진 문자열을 강력한 형식의 값과 연관시킵니다.
클래스. 표시될 수 있는 도움말 문자열을 제공해야 합니다. 예를 들면 다음과 같습니다.
를 통해 명령줄 프로세서. 각 속성 액세스 메커니즘과 연관되어 있습니다.
객체의 기본 멤버 변수(예: MakeUintegerAccessor () 말하다
일반적인 속성 위의 노드 ID에 도달하는 방법을 코드화하세요). "체커"도 있습니다
최대값과 같은 범위 제한에 대해 값을 검증하는 데 사용되는 방법
최소 허용 값.

사용자가 노드를 생성하려고 할 때 일반적으로 다음과 같은 형식을 호출합니다. CreateObject (),:

포인트 n = 객체 생성 ();

또는 더 추상적으로 개체 팩토리를 사용하여 노드 심지어 없는 개체
구체적인 C++ 유형을 아는 것:

ObjectFactory 팩토리;
const std::string typeId = "ns3::Node'';
공장.SetTypeId(typeId);
포인트 노드 = 공장.생성 ();

이 두 가지 방법 모두 완전히 초기화된 속성을
결과 목적 인스턴스.

다음으로 속성(구성원 변수나 함수와 관련된 값)을 어떻게 사용하는지 논의합니다.
클래스)는 위의 클래스로 연결됩니다. 유형 ID.

Attributes
속성 시스템의 목표는 시스템의 내부 구성원 개체에 대한 액세스를 구성하는 것입니다.
시뮬레이션. 이 목표는 일반적으로 시뮬레이션에서 사용자가 잘라내고
기존 시뮬레이션 스크립트를 붙여넣거나 수정하거나 더 높은 수준의 시뮬레이션 구성을 사용합니다.
그러나 종종 특정 내부 변수를 연구하거나 추적하는 데 관심이 있습니다. 을 위한
예를 들어 다음과 같은 사용 사례:

· "I 필요 더듬다 전에, 패킷 on 전에, 무선 전화 인터페이스 on 전에, 먼저 ACCESS 가리키다."

· "I 필요 더듬다 전에, 가치 of 전에, TCP 충혈 (모든 시간 it 변경) on a
특별한 TCP 소켓."

· "I 필요 a 덤프 of 모든 했다 익숙한 in my 시뮬레이션."

마찬가지로 사용자는 시뮬레이션에서 내부 변수에 대한 세부적인 액세스를 원할 수도 있습니다.
특정 매개변수에 사용되는 초기 값을 전체적으로 변경하고 싶을 수도 있습니다.
이후에 생성된 개체입니다. 마지막으로 사용자는 어떤 변수를 설정할 수 있는지 알고 싶어할 수 있습니다.
시뮬레이션 구성에서 검색 가능합니다. 이것은 단지 직접적인 시뮬레이션만을 위한 것이 아닙니다.
명령줄에서의 상호작용; (미래의) 그래픽 사용자 인터페이스도 고려해보세요.
사용자가 노드를 마우스 오른쪽 버튼으로 클릭할 수 있는 기능을 제공하고 싶습니다.
캔버스에서 설정 가능한 계층적이고 조직화된 매개변수 목록을 확인하세요.
노드 및 해당 구성 구성원 개체, 각 항목에 대한 도움말 텍스트 및 기본값
매개 변수입니다.

정의 Attributes
우리는 사용자가 연결 없이 시스템 깊은 곳에 있는 값에 액세스할 수 있는 방법을 제공합니다.
시스템을 통해 접근자(포인터)를 탐색하고 포인터 체인을 따라 이동합니다. 다음을 고려해보세요.
수업 DropTailQueue 부호 없는 정수인 멤버 변수가 있는 경우 m_maxPackets;
이 멤버 변수는 대기열의 깊이를 제어합니다.

선언문을 보면 DropTailQueue, 다음을 볼 수 있습니다.

클래스 DropTailQueue : 공개 대기열 {
공공의:
정적 TypeId GetTypeId (void);
...

비공개 :
표준::큐 > m_패킷;
uint32_t m_maxPackets;
};

사용자가 m_maxPackets:

· 새로운 시스템이 나올 때마다 시스템의 기본값을 설정합니다. DropTailQueue 생성되고,
이 멤버는 해당 기본값으로 초기화됩니다.

· 이미 인스턴스화된 대기열에 값을 설정하거나 가져옵니다.

위 사항은 일반적으로 제공이 필요합니다. 세트 () and 돈을 받아가세요 () 기능 및 일부 유형의
전역 기본값.

. NS-3 속성 시스템, 이러한 값 정의 및 접근자 함수 등록
로 이동됩니다 유형 ID 수업; .:

NS_OBJECT_ENSURE_REGISTERED(DropTailQueue);

유형 ID
DropTailQueue::GetTypeId(무효)
{
정적 TypeId tid = TypeId ("ns3::DropTailQueue")
.SetParent ()
.AddConstructor ()
.AddAttribute("MaxPackets",
"이 DropTailQueue에서 허용하는 최대 패킷 수입니다.",
단위값(100),
MakeUintegerAccessor(&DropTailQueue::m_maxPackets),
MakeUintegerChecker ())
;

정시 반환;
}

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 속성 추가 () 방법은 다음을 위해 여러 가지 작업을 수행하는 것입니다. m_maxPackets 값 :

· (보통 비공개) 멤버 변수 바인딩 m_maxPackets 공개 문자열로
"맥스패킷".

· 기본값(100패킷)을 제공합니다.

· 값의 의미를 정의하는 도움말 텍스트를 제공합니다.

· 경계를 설정하는 데 사용할 수 있는 "검사기"(이 예에서는 사용되지 않음) 제공
허용되는 값 범위.

중요한 점은 이제 이 변수의 값과 기본값에 액세스할 수 있다는 것입니다.
다음과 같은 문자열을 기반으로 하는 속성 네임스페이스에서 "맥스패킷" and 유형 ID name
문자열. 다음 섹션에서는 사용자가 어떻게 작업을 수행할 수 있는지 보여주는 예제 스크립트를 제공합니다.
이 값을 조작하십시오.

속성의 초기화는 매크로에 의존합니다. NS_OBJECT_ENSURE_REGISTERED
(DropTailQueue) 부름을 받고 있다; 새 클래스 구현에서 이를 제외하면
속성이 올바르게 초기화되지 않습니다.

속성을 생성하는 방법은 설명했지만 속성에 액세스하는 방법은 아직 설명하지 않았습니다.
이러한 값을 관리합니다. 예를 들어, 전역.h 헤더 파일은 다음과 같습니다.
저장됨; 속성은 해당 클래스와 함께 저장됩니다. 자연스럽게 떠오르는 질문은 '어떻게'이다.
사용자가 모델의 모든 속성에 대해 쉽게 배울 수 있습니까?
이러한 속성에 액세스하거나 해당 값을 기록의 일부로 문서화합니다.
시뮬레이션?

유형에 대해 정의된 실제 속성에 대한 자세한 문서 및 전역 목록
정의된 모든 속성은 API 문서에서 확인할 수 있습니다. 나머지 부분에 대해서는
속성을 가져오고 설정하는 다양한 방법을 보여줄 문서입니다.
values.

환경 태만 마케팅은:
구성::기본값 설정 and CommandLine
사용자 스크립트가 특정 속성 값에 액세스하는 방법을 살펴보겠습니다. 우리는
사용 src/point-to-point/examples/main-attribute-value.cc 일러스트레이션을 위한 스크립트
일부 세부 사항이 제거되었습니다. 그만큼 본관 기능이 시작됩니다:

// 이것은 속성 시스템을 사용하는 방법에 대한 기본적인 예입니다.
// 기본 시스템에서 값을 설정하고 가져옵니다. 즉, 서명되지 않은
// 대기열에 있는 최대 패킷 수의 정수
//

INT
메인(int argc, char *argv[])
{

// 기본적으로 MaxPackets 속성의 값은 100패킷입니다.
// (이 기본값은 DropTailQueue::GetTypeId 함수에서 확인할 수 있습니다.)
//
// 여기서는 80패킷으로 설정했습니다. 두 가지 값 유형 중 하나를 사용할 수 있습니다.
// 문자열 기반 값 또는 Uinteger 값
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("80"));
// 아래 함수 호출은 중복됩니다.
Config::SetDefault("ns3::DropTailQueue::MaxPackets", UintegerValue (80));

// 사용자가 기본값 및 위의 사항을 재정의할 수 있도록 허용합니다.
// 명령줄 인수를 통해 런타임에 SetDefaults()
// 예를 들어 "--ns3::DropTailQueue::MaxPackets=80"을 통해
커맨드라인 cmd;
// 이는 명령줄에서 값을 설정하는 또 다른 방법을 제공합니다.
cmd.AddValue("maxPackets", "ns3::DropTailQueue::MaxPackets");
cmd.Parse(argc, argv);

위에서 주목해야 할 주요 사항은 구성::기본값 설정
(). 이것이 이후에 인스턴스화되는 모든 항목에 대해 기본값을 설정하는 방법입니다.
DropTailQueue에스. 우리는 두 가지 유형의 가치관 수업, 문자열 값
정수값 클래스를 사용하여 이름이 지정된 속성에 값을 할당할 수 있습니다.
"ns3::DropTailQueue::MaxPackets".

다음을 사용하여 속성을 조작하는 것도 가능합니다. CommandLine; 우리는 몇 가지 예를 보았습니다
튜토리얼 초반에. 특히 단축 인수를 추가하는 것은 간단합니다.
다음과 같은 이름 --maxPackets, 모델과 특히 관련된 속성의 경우
이 경우 "ns3::DropTailQueue::MaxPackets". 여기에는 다음과 같은 추가 기능이 있습니다.
속성에 대한 도움말 문자열은 스크립트 사용 메시지의 일부로 인쇄됩니다.
자세한 내용은을 참조하십시오 CommandLine API 문서.

이제 저수준 API를 사용하여 몇 가지 객체를 생성하겠습니다. 새로 생성된 대기열은
가지고 있지 않다 m_maxPackets 에 정의된 대로 100개 패킷으로 초기화됩니다.
DropTailQueue::GetTypeId () 기능이지만 위에서 수행한 작업으로 인해 80개의 패킷으로 제한됩니다.
기본값.:

포인트 n0 = 객체 생성 ();

포인트 net0 = CreateObject ();
n0->AddDevice(net0);

포인트 q = 객체 생성 ();
net0->AddQueue(q);

이 시점에서 우리는 단일 노드 (n0) 그리고 하나의 PointToPointNet장치
(net0) 그리고 다음을 추가했습니다. DropTailQueue (q)에 net0.

생성자, 도우미 and 객체공장
속성의 임의 조합을 도우미 및 하위 수준에서 설정하고 가져올 수 있습니다.
아피스; 생성자 자체에서:

포인트 피 =
CreateObjectWithAttributes
("MinX", DoubleValue (-100.0),
"MinY", DoubleValue(-100.0),
"DeltaX", DoubleValue(5.0),
"DeltaY", DoubleValue(20.0),
"GridWidth", UintegerValue (20),
"레이아웃 유형", StringValue("RowFirst"));

또는 다음과 같은 상위 수준 도우미 API에서:

이동성.SetPositionAllocator
("ns3::GridPositionAllocator",
"MinX", DoubleValue (-100.0),
"MinY", DoubleValue(-100.0),
"DeltaX", DoubleValue(5.0),
"DeltaY", DoubleValue(20.0),
"GridWidth", UintegerValue (20),
"레이아웃 유형", StringValue("RowFirst"));

여기서는 설명하지 않지만 객체공장 새로운 가치로
특정 속성에 대해. 다음에 의해 생성된 인스턴스 객체공장 그거 가질거야
생성 중에 설정된 속성. 이는 도우미 API 중 하나를 사용하는 것과 매우 유사합니다.
수업을 위해.

검토해 보면 클래스 인스턴스의 속성 값을 설정하는 방법에는 여러 가지가 있습니다. be
만든 in 전에, 미래:

· 구성::기본값 설정 ()

· 명령줄::값 추가 ()

· CreateObjectWithAttributes<> ()

· 다양한 도우미 API

하지만 이미 인스턴스를 생성했고 인스턴스의 값을 변경하려는 경우에는 어떻게 해야 할까요?
기인하다? 이 예에서는 어떻게 조작할 수 있나요? m_maxPackets 이미의 가치
인스턴스화 DropTailQueue? 이를 수행하는 다양한 방법이 있습니다.

변경하기 마케팅은:
스마트포인터
스마트 포인터(Ptr) 관련 네트워크 장치가 손에 있습니다. 현재
예를 들어, 그것은 net0 바늘.

값을 변경하는 한 가지 방법은 기본 큐에 대한 포인터에 액세스하여 해당 값을 수정하는 것입니다.
속성을 사용하지 않는 것입니다.

먼저, (기본 클래스)에 대한 포인터를 얻을 수 있다는 것을 관찰합니다. 를 통해 전에,
PointToPointNet장치 속성, 호출되는 위치 "Tx큐":

포인터값 tmp;
net0->GetAttribute("TxQueue", tmp);
포인트 txQueue = tmp.GetObject();

사용법 - 객체 가져오기 () 함수를 사용하여 안전한 다운캐스트를 수행할 수 있습니다. DropTailQueue어디로
"맥스패킷" 속성은 다음과 같습니다.

포인트 dtq = txQueue->GetObject ();
NS_ASSERT(dtq != 0);

다음으로 이 대기열의 속성 값을 가져올 수 있습니다. 래퍼를 도입했습니다
가치관 이러한 유형에 대한 Java 래퍼와 유사한 기본 데이터 유형에 대한 클래스
속성 시스템은 서로 다른 유형이 아닌 문자열로 직렬화된 값을 저장하기 때문입니다.
여기서 속성 값은 정수값돈을 받아가세요 () 이에 대한 방법
값은 (래핑되지 않음)을 생성합니다. uint32_t.:

UintegerValue 제한;
dtq->GetAttribute("MaxPackets", 제한);
NS_LOG_INFO ("1. dtq 제한: " ​​<< Limit.Get () << " 패킷");

위의 다운캐스트는 실제로 필요하지 않습니다. 우리는 속성을 얻을 수 있었습니다
직접적으로 가치를 평가하다 txQueue, 이는 목적:

txQueue->GetAttribute("MaxPackets", 제한);
NS_LOG_INFO ("2. txQueue 제한: " ​​<< Limit.Get () << " 패킷");

이제 다른 값(60패킷)으로 설정해 보겠습니다.

txQueue->SetAttribute("MaxPackets", UintegerValue (60));
txQueue->GetAttribute("MaxPackets", 제한);
NS_LOG_INFO ("3. txQueue 제한이 변경되었습니다: " << Limit.Get () << " 패킷");

구성 네임 스페이스 경로
속성을 얻는 또 다른 방법은 구성 네임스페이스를 사용하는 것입니다. 여기,
이 속성은 이 네임스페이스의 알려진 경로에 있습니다. 이 접근 방식은 다음과 같은 경우에 유용합니다.
기본 포인터에 대한 액세스 권한이 없으며 특정 포인터를 구성하려고 합니다.
단일 명령문이 포함된 속성:

구성::설정("/NodeList/0/DeviceList/0/TxQueue/MaxPackets",
UintegerValue (25));
txQueue->GetAttribute("MaxPackets", 제한);
NS_LOG_INFO("4. 네임스페이스를 통해 변경된 txQueue 제한: "
<< Limit.Get () << "패킷");

구성 경로는 종종 다음과 같은 형태를 갖습니다. ".../
이름>/ /.../ / " 특정 인스턴스를 인덱스로 참조하려면
컨테이너에 있는 개체입니다. 이 경우 첫 번째 컨테이너는 모든 항목의 목록입니다. 노드에스; 그만큼
두 번째 컨테이너는 모든 항목의 목록입니다. NetDevice선택한 것에 있어 노드. 마지막으로
구성 경로는 일반적으로 일련의 구성원 속성으로 끝납니다. 이 경우
"맥스패킷" 의 속성 "Tx큐" 선택된 것의 NetDevice.

모든 노드와 모든 네트워크 장치에 대해 이 값을 설정하기 위해 와일드카드를 사용할 수도 있습니다.
(이 간단한 예에서는 이전 예와 동일한 효과가 있습니다. 구성::설정 ()):

구성::설정("/NodeList/*/DeviceList/*/TxQueue/MaxPackets",
UintegerValue (15));
txQueue->GetAttribute("MaxPackets", 제한);
NS_LOG_INFO("5. 와일드카드 네임스페이스를 통해 변경된 txQueue 제한: "
<< Limit.Get () << "패킷");

목적 성함 예배
속성을 얻는 또 다른 방법은 객체 이름 서비스 기능을 사용하는 것입니다. 그만큼
객체 이름 서비스를 사용하면 구성 네임스페이스 아래에 항목을 추가할 수 있습니다.
"/이름/" 사용자 정의 이름 문자열이 있는 경로입니다. 이 접근 방식은 그렇지 않은 경우에 유용합니다.
기본 포인터에 액세스할 수 있고 필요한 포인터를 결정하기가 어렵습니다.
구체적인 구성 네임스페이스 경로.

이름::추가("서버", n0);
이름::추가("서버/eth0", net0);

...

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

여기에 경로 요소를 추가했습니다. "섬기는 사람" and "eth0" 아래 "/이름/" 네임스페이스, 그런 다음
결과 구성 경로를 사용하여 속성을 설정했습니다.

더 자세한 내용은 개체 이름을 참조하세요. NS-3 구성 네임스페이스.

실시 세부 정보
가치관 클래스
독자들은 다음 사항을 주목할 것이다. 유형값 클래스의 하위 클래스인 클래스 속성값 기지
수업. 이는 원시 클래스를 변환하는 데 사용되는 중간 클래스로 생각할 수 있습니다.
유형을 속성값속성 시스템에서 사용되는 s입니다. 이것을 기억하십시오
데이터베이스는 문자열로 직렬화된 다양한 유형의 개체를 보유하고 있습니다. 이 유형으로의 전환
중간 클래스(예: 정수값DoubleValue for
부동 소수점 숫자) 또는 를 통해 문자열. 유형을 다음으로 직접 암시적으로 변환
속성값 정말 실용적이지 않습니다. 따라서 위의 경우 사용자는 다음을 사용할 수 있습니다.
문자열 또는 값:

p->Set("cwnd", StringValue("100")); // 문자열 기반 설정자
p->Set("cwnd", IntegerValue (100)); // 정수 기반 설정자

시스템은 사용자가 새로운 AttributeValue를 선언하고 정의하는 데 도움이 되는 몇 가지 매크로를 제공합니다.
속성 시스템에 도입하려는 새로운 유형에 대한 서브클래스:

· ATTRIBUTE_HELPER_HEADER

· ATTRIBUTE_HELPER_CPP

자세한 내용은 이러한 구성에 대한 API 설명서를 참조하세요.

초기화 주문번호
시스템의 속성은 이 속성의 다른 속성 상태에 의존해서는 안 됩니다.
체계. 이는 속성 초기화 순서가 지정되지 않았거나
시스템에 의해 시행됩니다. 이에 대한 구체적인 예는 자동화된 구성에서 볼 수 있습니다.
같은 프로그램 구성 저장소. 주어진 모델은 속성을 정렬할 수 있지만
특정 순서로 초기화되면 다른 자동 구성자가 결정할 수 있습니다.
예를 들어 알파벳 순서로 속성을 변경하려면 독립적으로 수행해야 합니다.

이러한 비특정 순서로 인해 시스템의 어떤 속성도 종속성을 가질 수 없습니다.
다른 속성에 대해. 결과적으로 속성 설정자는 상태로 인해 절대 실패해서는 안 됩니다.
다른 속성의. 속성 설정자는 다른 속성 값을 다음과 같이 변경(설정)할 수 없습니다.
값을 변경한 결과입니다.

이는 매우 강력한 제한사항이며 속성을 설정해야 하는 경우도 있습니다.
올바른 작동을 위해 일관되게. 이를 위해 일관성 검사를 허용합니다.
언제 전에, 속성 is 익숙한 (cf. NS_ASSERT_MSG or NS_ABORT_MSG).

일반적으로 기본 클래스 멤버 변수에 값을 할당하는 속성 코드는
객체가 생성된 후에 실행됩니다. 하지만 할당된 값이 필요한 경우에는 어떻게 해야 할까요?
생성자 본문이 실행되기 전에
건설자? 예를 들어 수업에서 사용되는 방법이 있습니다. 구성 저장소: 부르다
ObjectBase::컨스트럭트셀프 () 다음과 같이 :

구성스토어::구성스토어 ()
{
ObjectBase::ConstructSelf(AttributeConstructionList ());
// 생성자를 계속 진행합니다.
}

객체와 객체에서 파생된 모든 클래스도 다음을 구현해야 한다는 점에 유의하세요. 인스턴스 유형 ID 가져오기
() 방법. 그렇지 않으면 ObjectBase::컨스트럭트셀프 () 읽을 수 없을 것이다
속성.

첨가 Attributes
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 시스템은 속성 시스템 아래에 여러 내부 값을 배치하지만
의심할 여지 없이 사용자는 우리가 놓친 것을 선택하거나 추가하기 위해 이것을 확장하기를 원할 것입니다.
시스템에 자신의 클래스를 추가합니다.

세 가지 일반적인 사용 사례가 있습니다.

· 아직 액세스할 수 없는 기존 클래스 데이터 멤버를 속성으로 액세스 가능하게 만듭니다.

· TypeId를 제공하여 일부 데이터 멤버를 속성으로 노출할 수 있는 새 클래스를 만듭니다.

· 만들기 속성값 새 클래스에 대한 하위 클래스를 생성하여 액세스할 수 있도록 합니다.
기인하다.

현존하는 회원 변하기 쉬운
이 변수를 고려하십시오. Tcp소켓:

uint32_t m_cWnd; // 혼잡 창

TCP로 작업하는 누군가가 해당 변수의 값을 얻거나 설정하기를 원한다고 가정합니다.
메타데이터 시스템을 사용합니다. 아직 제공되지 않은 경우 NS-3, 사용자는 선언할 수 있습니다
런타임 메타데이터 시스템에 다음 추가 사항( 유형ID 가져오기() 에 대한 정의
Tcp소켓):

.AddAttribute("혼잡 창",
"Tcp 정체 창(바이트)",
단위값(1),
MakeUintegerAccessor(&TcpSocket::m_cWnd),
MakeUintegerChecker ())

이제 포인터를 가진 사용자는 Tcp소켓 인스턴스는 다음과 같은 작업을 수행할 수 있습니다.
이러한 기능을 명시적으로 추가하지 않고도 값을 설정하고 가져옵니다.
또한 매개변수를 읽고 액세스할 수 있도록 허용하는 등의 액세스 제어를 적용할 수 있습니다.
작성되지 않았거나 허용 값에 ​​대한 경계 확인이 적용될 수 있습니다.

신제품 클래스 유형 ID
여기서는 새 클래스를 추가하려는 사용자에게 미치는 영향에 대해 논의합니다. NS-3. 무엇
속성을 보유하려면 추가 작업을 수행해야 합니까?

다음과 같은 새로운 클래스를 가정해 보겠습니다. ns3::마이모빌리티, 모빌리티 모델의 일종이다. 첫 번째,
클래스는 상위 클래스로부터 상속받아야 합니다. ns3::모빌리티모델. 에서 내 이동성 .h
헤더 파일:

네임스페이스 ns3 {

MyClass 클래스 : 공개 MobilityModel
{

이를 위해서는 다음 사항을 선언해야 합니다. 유형 ID 가져오기 () 기능. 이것은 한 줄짜리 공개 함수입니다.
선언:

공공의:
/ **
* 해당 유형을 등록하세요.
* \return 개체 TypeId입니다.
*/
정적 TypeId GetTypeId (void);

우리는 이미 유형 ID 정의는 다음과 같습니다. 내 이동성.cc
구현 파일:

NS_OBJECT_ENSURE_REGISTERED(마이모빌리티);

유형 ID
MyMobility::GetTypeId(무효)
{
static TypeId tid = TypeId ("ns3::MyMobility")
.SetParent ()
.SetGroupName ("이동성")
.AddConstructor ()
.AddAttribute("경계",
"순항할 지역의 경계.",
RectangleValue(직사각형(0.0, 0.0, 100.0, 100.0)),
MakeRectangleAccessor(&MyMobility::m_bounds),
MakeRectangleChecker ())
.AddAttribute("시간",
"이 지연 시간 동안 이동한 후 현재 방향과 속도를 변경하십시오.",
TimeValue(초(1.0)),
MakeTimeAccessor(&MyMobility::m_modeTime),
MakeTimeChecker ())
// 등(추가 매개변수).
;
정시 반환;
}

기존 클래스에서 하위 클래스를 만들고 싶지 않다면 헤더 파일에서 상속합니다.
ns3::객체, 객체 파일에서 상위 클래스를 다음으로 설정했습니다. ns3::객체
.SetParent ().

여기서 일반적인 실수는 다음과 같습니다.

· 전화하지 않음 NS_OBJECT_ENSURE_REGISTERED ()

· 전화하지 않음 부모 설정 () 메서드를 호출하거나 잘못된 유형으로 호출하는 경우가 있습니다.

· 전화하지 않음 AddConstructor () 메서드를 호출하거나 잘못된 유형으로 호출하는 경우가 있습니다.

· 이름에 오타가 발생했습니다. 유형 ID 생성자에서.

· 바깥쪽 C++ 클래스의 정규화된 C++ 유형 이름을 클래스의 이름으로 사용하지 않습니다.
유형 ID. 그 주 "ns3::" 필요합니다.

이러한 오류 중 어느 것도 감지할 수 없습니다. NS-3 코드베이스이므로 사용자는 확인하는 것이 좋습니다.
그들이 옳았는지 여러 번 조심스럽게 확인하십시오.

신제품 속성값 타입
시스템에 새로운 클래스를 작성하고 이를 원하는 사용자의 입장에서
속성으로 액세스할 수 있는 경우 주로 변환을 작성하는 문제가 있습니다.
문자열 및 속성 값. 이 중 대부분은 매크로화된 코드로 복사/붙여넣기가 가능합니다. 을 위한
예를 들어, 다음에 대한 클래스 선언을 고려하십시오. 구형 인간을 src/이동성/모델 예배 규칙서:

헤더 입양 부모로서의 귀하의 적합성을 결정하기 위해 미국 이민국에
/ **
* \2D 직사각형을 간략하게 설명합니다.
*/
클래스 직사각형
{
...

이중 xMin;
이중 xMax;
이중 yMin;
이중 yMax;
};

하나의 매크로 호출과 두 개의 연산자를 클래스 선언 아래에 추가해야 합니다.
Rectangle을 다음에서 사용할 수 있는 값으로 변환합니다. 속성 시스템 :

std::ostream &operator << (std::ostream &os, const 직사각형 &사각형);
std::istream &operator >> (std::istream &is, 직사각형 &사각형);

ATTRIBUTE_HELPER_HEADER(직사각형);

실시 입양 부모로서의 귀하의 적합성을 결정하기 위해 미국 이민국에
클래스 정의(.CC 파일) 코드는 다음과 같습니다.

ATTRIBUTE_HELPER_CPP(직사각형);

표준::ostream &
연산자 << (std::ostream &os, const 직사각형 &사각형)
{
os << 직사각형.xMin << "|" << 직사각형.xMax << "|" << 직사각형.yMin << "|"
<< 직사각형.yMax;
OS를 반환;
}
표준::istream &
연산자 >> (std::istream &is, 직사각형 &사각형)
{
문자 c1, c2, c3;
>> 직사각형.xMin >> c1 >> 직사각형.xMax >> c2 >> 직사각형.yMin >> c3
>> 직사각형.yMax;
if (c1 != '|' ||
c2 != '|' ||
c3 != '|')
{
is.setstate(std::ios_base::failbit);
}
반품은;
}

이러한 스트림 연산자는 단순히 Rectangle의 문자열 표현에서 변환됩니다.
("xMin|xMax|yMin|yMax")를 기본 Rectangle에 추가합니다. 모델러는 다음을 지정해야 합니다.
연산자와 새 클래스 인스턴스의 문자열 구문 표현.

구성 저장소
NS-3 속성은 ASCII 또는 XML 텍스트 파일에 저장되고
미래 시뮬레이션 실행. 이 기능은 다음과 같이 알려져 있습니다. NS-3 구성 저장소. 그만큼 구성 저장소 is
속성 값과 기본값에 대한 특수 데이터베이스.

별도로 관리되는 모듈이지만 src/config-store/ 디렉토리, 우리
에 대한 유일한 의존성 때문에 여기에 문서화하십시오. NS-3 핵심 모듈 및 속성.

우리는 다음의 예를 사용하여 이 시스템을 탐색할 수 있습니다.
src/config-store/examples/config-store-save.cc.

먼저, 모든 사용자는 구성 저장소 다음 진술을 포함해야 합니다.

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

다음으로 이 프로그램은 샘플 객체를 추가합니다. 구성예 시스템이 어떻게 확장되는지 보여주기 위해:

클래스 ConfigExample : 공용 객체
{
공공의:
정적 TypeId GetTypeId (void) {
정적 TypeId tid = TypeId ("ns3::A")
.SetParent ()
.AddAttribute("TestInt16", "도움말 텍스트",
정수값(-2),
MakeIntegerAccessor(&A::m_int16),
MakeIntegerChecker ())
;
정시 반환;
}
int16_t m_int16;
};

NS_OBJECT_ENSURE_REGISTERED(구성예제);

다음으로 Config 하위 시스템을 사용하여 몇 가지 방법으로 기본값을 재정의합니다.

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

포인트 a_obj = CreateObject ();
NS_ABORT_MSG_UNLESS(a_obj->m_int16 == -5,
"Config::SetDefault를 통해 ConfigExample의 정수 속성을 설정할 수 없습니다.");

포인트 a2_obj = CreateObject ();
a2_obj->SetAttribute("TestInt16", IntegerValue (-3));
정수값 iv;
a2_obj->GetAttribute("TestInt16", iv);
NS_ABORT_MSG_UNLESS(iv.Get() == -3,
"SetAttribute를 통해 ConfigExample의 정수 속성을 설정할 수 없습니다.");

생성된 객체 중 하나가 루팅되었는지 확인하려면 다음 명령문이 필요합니다.
구성 네임스페이스에서 객체 인스턴스로. 이는 일반적으로 다음과 같은 경우에 발생합니다.
개체를 ns3::노드 or ns3::채널 예를 들어, 하지만 여기서는 우리가 일하고 있기 때문에
핵심 수준에서는 새 루트 네임스페이스 개체를 만들어야 합니다.

구성::RegisterRootNamespaceObject(a2_obj);

쓰기
다음으로 구성 저장소를 출력하려고 합니다. 예제에서는 두 가지 방법으로 이를 수행하는 방법을 보여줍니다.
형식, XML 및 원시 텍스트. 실제로는 호출 직전에 이 단계를 수행해야 합니다.
시뮬레이터::실행 () 시뮬레이션을 실행하기 직전에 최종 구성을 저장합니다.

ConfigStore의 동작을 제어하는 ​​세 가지 속성이 있습니다. "방법",
"파일 이름""파일 형식". 모드(기본값 "없음") 여부를 구성합니다. NS-3 영상을
이전에 저장한 파일에서 구성 로드(지정 "모드=로드") 또는 파일에 저장
(지정하다 "모드=저장"). 파일 이름(기본값 "")는 ConfigStore가 읽어야 하는 위치입니다.
데이터를 쓰세요. FileFormat(기본값 "원문")는 ConfigStore 형식을 제어합니다.
일반 텍스트 또는 Xml("파일형식=Xml")

예제에서는 다음을 보여줍니다.

Config::SetDefault("ns3::ConfigStore::파일 이름", StringValue("output-attributes.xml"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("Xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("저장"));
구성저장outputConfig;
출력구성.구성기본값();
출력구성.구성속성();

// 구성 저장소를 txt 형식으로 출력합니다.
Config::SetDefault ("ns3::ConfigStore::파일 이름", StringValue ("output-attributes.txt"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("RawText"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("저장"));
ConfigStore 출력Config2;
outputConfig2.ConfigureDefaults();
outputConfig2.ConfigureAttributes();

시뮬레이터::실행();

시뮬레이터::파괴();

이 진술이 바로 앞에 배치되어 있음을 주목하십시오. 시뮬레이터::실행 () 성명서.
이 출력은 시뮬레이션을 시작하기 직전에 모든 값을 기록합니다(.
모든 구성이 완료된 후).

실행 후 다음을 열 수 있습니다. 출력속성.txt 파일을 보고 다음을 참조하세요.

기본 ns3::RealtimeSimulatorImpl::SynchronizationMode "BestEffort"
기본 ns3::RealtimeSimulatorImpl::HardLimit "+100000000.0ns"
기본 ns3::PcapFileWrapper::CaptureSize "65535"
기본 ns3::PacketSocket::RcvBufSize "131072"
기본 ns3::ErrorModel::IsEnabled "true"
기본 ns3::RateErrorModel::ErrorUnit "EU_BYTE"
기본 ns3::RateErrorModel::ErrorRate "0"
기본 ns3::RateErrorModel::RanVar "균일:0:1"
기본 ns3::DropTailQueue::모드 "패킷"
기본 ns3::DropTailQueue::MaxPackets "100"
기본 ns3::DropTailQueue::MaxBytes "6553500"
기본 ns3::Application::StartTime "+0.0ns"
기본 ns3::Application::StopTime "+0.0ns"
기본 ns3::ConfigStore::모드 "저장"
기본 ns3::ConfigStore::파일 이름 "output-attributes.txt"
기본 ns3::ConfigStore::FileFormat "RawText"
기본 ns3::ConfigExample::TestInt16 "-5"
전역 RngSeed "1"
글로벌 RngRun "1"
전역 SimulatorImplementationType "ns3::DefaultSimulatorImpl"
전역 SchedulerType "ns3::MapScheduler"
전역 체크섬 활성화됨 "false"
값 /$ns3::ConfigExample/TestInt16 "-3"

위에는 핵심 모듈 속성의 기본값이 모두 표시되어 있습니다.
그런 다음, NS-3 전역 값이 기록됩니다. 마지막으로,
대신에 구성예 구성 네임스페이스에 뿌리를 둔 이름이 표시됩니다. 안에
현실 NS-3 프로그램에는 더 많은 모델, 속성 및 기본값이 표시됩니다.

XML 버전도 존재합니다. 출력 속성.xml:




























이 파일은 시뮬레이션 스크립트 및 출력 데이터와 함께 보관될 수 있습니다.

읽기
다음으로 시뮬레이션 구성에 대해 논의합니다. 를 통해 저장된 입력 구성 파일. 있다
최종 시뮬레이션 구성 작성과 비교했을 때 몇 가지 주요 차이점이 있습니다.
먼저, 프로그램 시작 부분에 다음과 같은 명령문을 배치해야 합니다.
시뮬레이션 구성 명령문이 작성되므로 값이 등록되기 전에 등록됩니다.
객체 생성에 사용됨).

Config::SetDefault ("ns3::ConfigStore::파일 이름", StringValue ("input-defaults.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("로드"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("Xml"));
ConfigStore inputConfig;
inputConfig.ConfigureDefaults();

다음으로, 입력 구성 데이터의 로드는 속성 기본값(.
인스턴스가 아님) 값과 전역 값이 있습니다. 속성 인스턴스 값은 지원되지 않습니다.
시뮬레이션의 이 단계에서는 객체가 구성되기 전에
주변에 그러한 객체 인스턴스가 있습니다. (참고로 구성 저장소에 대한 향후 개선 사항은 변경될 수 있습니다.
이 행동).

둘째, 출력하는 동안 구성 저장소 state는 데이터베이스의 모든 것을 나열합니다.
입력 파일에는 재정의할 특정 값만 포함하면 됩니다. 그럼 활용방법 중 하나는
입력 파일 구성을 위한 이 클래스는
출력("저장") "방법" 위에서 설명한 대로 해당 구성 파일에서
변경하려는 요소를 선택하고 이러한 최소 요소를 새 구성 파일로 이동하세요.
그런 다음 후속 시뮬레이션 실행에서 안전하게 편집하고 로드할 수 있습니다.

구성 저장소 객체가 인스턴스화되고 해당 속성이 "파일 이름", "방법"
"파일 형식" 다음 중 하나를 설정해야 합니다. 를 통해 명령줄 또는 를 통해 프로그램 진술.

읽기 쓰기 예시
좀 더 복잡한 예로, 다음과 같은 구성으로 읽고 싶다고 가정해 보겠습니다.
기본값은 다음과 같은 입력 파일에서 발생합니다. 입력-defaults.xml, 그리고 그 결과를 쓰세요.
라는 별도의 파일에 속성을 부여합니다. 출력 속성.xml.:

#include "ns3/config-store-module.h"
...
정수 메인(...)
{

Config::SetDefault ("ns3::ConfigStore::파일 이름", StringValue ("input-defaults.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("로드"));
Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("Xml"));
ConfigStore inputConfig;
inputConfig.ConfigureDefaults();

//
// 사용자가 기본값과 위의 Bind()를 재정의할 수 있도록 허용합니다.
// 런타임, 명령줄 인수를 통해
//
커맨드라인 cmd;
cmd.Parse(argc, argv);

// 토폴로지 설정
...

// Simulator::Run에 진입하기 직전에 호출합니다()
Config::SetDefault("ns3::ConfigStore::파일 이름", StringValue("output-attributes.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("저장"));
구성저장outputConfig;
출력구성.구성속성();
시뮬레이터::실행();
}

구성 저장소 GUI
ConfigStore에는 GTK 기반 프런트 엔드가 있습니다. 이를 통해 사용자는 GUI를 사용하여 다음 작업을 수행할 수 있습니다.
변수에 접근하고 변경합니다. 이 기능의 스크린샷은 다음에서 확인할 수 있습니다. |ns3|
살펴보기 표시.

이 기능을 사용하려면 다음을 설치해야 합니다. libgtk and libgtk-dev; 우분투의 예
설치 명령은 다음과 같습니다

$ sudo apt-get 설치 libgtk2.0-0 libgtk2.0-dev

구성 여부를 확인하려면 단계의 출력을 확인하세요.

$ ./waf 구성 --enable-examples --enable-tests

---- NS-3 옵션 기능 요약:
Python 바인딩: 사용
Python API 스캐닝 지원: 활성화됨
NS-3 클릭 통합: 활성화됨
GtkConfigStore: 활성화되지 않음('gtk+-2.0 >= 2.12' 라이브러리를 찾을 수 없음)

위의 예에서는 활성화되지 않았으므로 적합한 버전이 나올 때까지 사용할 수 없습니다.
설치 및:

$ ./waf 구성 --enable-examples --enable-tests
$ ./와프

재방송이다.

GTK 기반이 아닌 버전과 사용법은 거의 동일하지만 구성 저장소
관련된 속성:

// Simulator::Run에 진입하기 직전에 호출합니다()
GtkConfigStore 구성;
config.ConfigureDefaults();
config.ConfigureAttributes();

이제 스크립트를 실행하면 GUI가 팝업되어 다음 메뉴를 열 수 있습니다.
다른 노드/객체에 대한 속성을 지정한 다음 시뮬레이션 실행을 시작합니다.
완료되었습니다.

미래
몇 가지 가능한 개선 사항이 있습니다.

· 파일 시작 시 날짜 및 시간과 함께 고유한 버전 번호를 저장합니다.

· 어딘가에 rng 초기 시드를 저장하십시오.

· 각 RandomVariable이 자체 초기 시드를 직렬화하고 나중에 다시 읽도록 만듭니다.

목적 이름
자리 표시 자

로깅
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 로깅 기능을 사용하여 시뮬레이션 진행 상황을 모니터링하거나 디버그할 수 있습니다.
프로그램들. 로깅 출력은 다음의 프로그램 문으로 활성화할 수 있습니다. 본관() 프로그램 또는
사용하여 NS_LOG 환경 변수.

로깅 문은 최적화된 빌드로 컴파일되지 않습니다. NS-3. 로깅을 사용하려면 다음 중 하나를 수행하세요.
(기본) 디버그 빌드를 빌드해야 합니다. NS-3.

프로젝트는 로깅 출력이 계속해서 동일하게 유지되는지 여부를 보장하지 않습니다.
시간. 사용자는 로깅 위에 시뮬레이션 출력 프레임워크를 구축하지 않도록 주의를 받습니다.
출력과 출력이 활성화되는 방식은 시간이 지남에 따라 변경될 수 있습니다.

살펴보기
NS-3 로깅 문은 일반적으로 다음과 같은 다양한 프로그램 실행 이벤트를 기록하는 데 사용됩니다.
시뮬레이션 이벤트의 발생이나 특정 기능의 사용 등.

예를 들어, 이 코드 조각은 Ipv4L3프로토콜::IsDestinationAddress():

if (주소 == iaddr.GetBroadcast ())
{
NS_LOG_LOGIC("For me(인터페이스 브로드캐스트 주소)");
true를 반환;
}

로깅이 활성화된 경우 Ipv4L3프로토콜 심각도의 구성 요소 논리 or
위(로그 심각도에 대해서는 아래 참조) 명령문이 인쇄됩니다. 그렇지 않으면 그것은
억제됩니다.

사용 산출
사용자가 일반적으로 로그 출력을 제어하는 ​​방법에는 두 가지가 있습니다. 첫 번째는
NS_LOG 환경 변수; 예:

$ NS_LOG="*" ./waf --먼저 실행

을 실행합니다 먼저 모든 로깅 출력이 포함된 튜토리얼 프로그램. (구체적인 내용은 NS_LOG
형식은 아래에서 설명하겠습니다.)

개별 구성요소를 선택하여 이를 더욱 세부적으로 만들 수 있습니다.

$ NS_LOG="Ipv4L3Protocol" ./waf --먼저 실행

접두사 옵션을 사용하여 출력을 더욱 맞춤화할 수 있습니다.

로깅을 활성화하는 두 번째 방법은 다음과 같이 프로그램에서 명시적인 명령문을 사용하는 것입니다.
전에, 먼저 튜토리얼 프로그램:

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

(그 의미 LOG_LEVEL_INFO, 기타 가능한 값에 대해서는 아래에서 설명합니다.)

NS_LOG 통사론
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS_LOG 환경 변수에는 로그 구성 요소 및 옵션 목록이 포함되어 있습니다. 통나무
구성 요소는 ':' 문자로 구분됩니다.

$NS_LOG=" : ..."

각 로그 구성 요소에 대한 옵션은 각 로그 구성 요소 뒤에 플래그로 제공됩니다.

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

옵션은 해당 구성 요소의 심각도와 수준, 그리고 선택 사항인지 여부를 제어합니다.
시뮬레이션 시간, 시뮬레이션 노드, 기능과 같은 정보가 포함되어야 합니다.
이름, 상징적 심각도.

로그 구성 요소들
일반적으로 로그 구성 요소는 단일 소스 코드를 나타냅니다. .CC 파일을 포함하며
전체 파일.

일부 도우미에는 모듈의 모든 구성 요소에 대한 로깅을 활성화하는 특별한 방법이 있습니다.
서로 다른 컴파일 단위에 걸쳐 있지만 논리적으로 함께 그룹화되어 있습니다. NS-3
와이파이 코드:

WifiHelper 와이파이헬퍼;
wifiHelper.EnableLogComponents();

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS_LOG 로그 구성 요소 와일드카드 '*'는 모든 구성 요소를 활성화합니다.

어떤 로그 구성 요소가 정의되어 있는지 확인하려면 다음 중 하나를 수행하면 됩니다.

$ NS_LOG="인쇄 목록" ./waf --run ...

$ NS_LOG="foo" # 로그 구성 요소와 일치하지 않는 토큰

첫 번째 양식은 모든 로그 구성 요소에 대한 이름과 활성화된 플래그를 인쇄합니다.
연결됨; 그걸로 시도해봐 스크래치 시뮬레이터. 두 번째 양식은 등록된 모든 로그를 인쇄합니다.
그런 다음 오류와 함께 종료됩니다.

심각도 and 레벨 옵션
개별 메시지는 단일 "심각도 클래스"에 속합니다.
메시지. 위의 예에서, NS_LOG_LOGIC(..) 에서 메시지를 생성합니다. 로그_로직
심각도 등급.

다음 심각도 클래스는 다음과 같이 정의됩니다. 열거 형 상수 :

┌───────────────┬──────────────────────────────── ─┐
│심각도 등급 │ 의미 │
├───────────────┼──────────────────────────────── ─┤
로그_없음 │ 기본값, 로깅 없음 │
├───────────────┼──────────────────────────────── ─┤
로그_오류 │ 심각한 오류 메시지만 │
├───────────────┼──────────────────────────────── ─┤
로그_경고 │ 경고 메시지 │
├───────────────┼──────────────────────────────── ─┤
로그_디버그 │ 디버깅에 사용 │
├───────────────┼──────────────────────────────── ─┤
로그_정보 │ 정보 │
├───────────────┼──────────────────────────────── ─┤
로그_함수 │ 함수 추적 │
├───────────────┼──────────────────────────────── ─┤
로그_로직 │ 제어 흐름 추적 │
│ │ 기능 │
└───────────────┴──────────────────────────────── ─┘

일반적으로 특정 심각도 클래스의 메시지를 보고 싶어합니다. and 더 높은. 이것은
포괄적인 로깅 "수준" 정의:

┌───────────────────┬──────────────────────────── ─────┐
│레벨 │ 의미 │
├───────────────────┼──────────────────────────── ─────┤
로그_레벨_오류 │ 만 로그_오류 심각도 등급 │
│ │ 메시지. │
├───────────────────┼──────────────────────────── ─────┤
LOG_LEVEL_WARN로그_경고 이상. │
├───────────────────┼──────────────────────────── ─────┤
LOG_LEVEL_DEBUG로그_디버그 이상. │
├───────────────────┼──────────────────────────── ─────┤
LOG_LEVEL_INFO로그_정보 이상. │
├───────────────────┼──────────────────────────── ─────┤
LOG_LEVEL_FUNCTION로그_함수 이상. │
├───────────────────┼──────────────────────────── ─────┤
LOG_LEVEL_LOGIC로그_로직 이상. │
├───────────────────┼──────────────────────────── ─────┤
LOG_LEVEL_ALL │ 모든 심각도 등급. │
├───────────────────┼──────────────────────────── ─────┤
LOG_ALL │ 동의어 LOG_LEVEL_ALL
└───────────────────┴──────────────────────────── ─────┘

심각도 등급 및 수준 옵션은 NS_LOG 환경 변수
다음 토큰:

┌─────────┬────────────────┐
│클래스 │ 레벨 │
├─────────┼────────────────┤
오류레벨 오류
├─────────┼────────────────┤
경고레벨_경고
├─────────┼────────────────┤
디버그레벨_디버그
├─────────┼────────────────┤
정보level_info
├─────────┼────────────────┤
기능레벨_기능
├─────────┼────────────────┤
논리레벨로직
├─────────┼────────────────┤
│ │ level_all
│ │ 모든
│ │ *
└─────────┴────────────────┘

심각도 클래스 토큰을 사용하면 해당 심각도의 로그 메시지만 활성화됩니다. 예를 들어,
NS_LOG="*=경고" 심각도가 있는 메시지를 출력하지 않습니다. 오류. NS_LOG="*=level_debug" 의지
심각도 수준의 메시지 출력 디버그 이상.

심각도 클래스와 수준은 `|' 운영자:
NS_LOG="*=level_warn|논리" 심각도 수준에서 메시지를 출력합니다. 오류, 경고 and 논리.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS_LOG 심각도 수준 와일드카드 '*' 및 모든 의 동의어입니다 level_all.

방금 언급된 로그 구성 요소의 경우 NS_LOG

$NS_LOG=" :..."

기본 심각도는 LOG_LEVEL_ALL.

접두사 옵션
다양한 접두사는 메시지가 어디서, 언제, 어디서 시작되었는지 식별하는 데 도움이 될 수 있습니다.
심각성.

사용 가능한 접두사 옵션(예: 열거 형 상수)는

┌─────────────────┬────────────────────────────── ───┐
│접두사 기호 │ 의미 │
├─────────────────┼────────────────────────────── ───┤
LOG_PREFIX_FUNC │ 부름의 이름 앞에 붙임 │
│ │ 기능. │
├─────────────────┼────────────────────────────── ───┤
LOG_PREFIX_TIME │ 시뮬레이션 시간을 앞에 붙입니다. │
├─────────────────┼────────────────────────────── ───┤
LOG_PREFIX_NODE │ 노드 ID 접두사를 붙입니다. │
├─────────────────┼────────────────────────────── ───┤
LOG_PREFIX_LEVEL │ 심각도 수준 앞에 붙습니다. │
├─────────────────┼────────────────────────────── ───┤
LOG_PREFIX_ALL │ 모든 접두사를 활성화합니다. │
└─────────────────┴────────────────────────────── ───┘

접두사 옵션은 아래에 간략하게 설명되어 있습니다.

옵션은 NS_LOG 다음 토큰에 의한 환경 변수:

┌─────────────┬───────────┐
│토큰 │ 대체 │
├─────────────┼───────────┤
접두사_펑크펑크
├─────────────┼───────────┤
접두사_시간시간
└─────────────┴───────────┘

접두사_노드노드
├─────────────┼───────────┤
접두사_수준수평
├─────────────┼───────────┤
접두어_모두모든
│ │ *
└─────────────┴───────────┘

방금 언급된 로그 구성 요소의 경우 NS_LOG

$NS_LOG=" :..."

기본 접두사 옵션은 다음과 같습니다. LOG_PREFIX_ALL.

심각도 접두사
메시지의 심각도 클래스는 옵션에 포함될 수 있습니다. 접두사_수준 or 수평.
예를 들어, 이 값은 NS_LOG 모든 로그 구성 요소(`*') 및 모든 로그 구성 요소에 대한 로깅을 활성화합니다.
심각도 등급(=모두), 메시지 앞에 심각도 클래스(|접두사_수준).

$ NS_LOG="*=all|prefix_level" ./waf --run 스크래치 시뮬레이터
스크래치 시뮬레이터
[오류] 오류 메시지
[WARN] 경고 메시지
[디버그] 디버그 메시지
[INFO] 정보 메시지
[FUNC] 기능 메시지
[LOGIC] 로직 메시지

Time 접두사
시뮬레이션 시간은 옵션에 포함될 수 있습니다. 접두사_시간 or 시간. 이것은 인쇄
시뮬레이션 시간(초)입니다.

노드 접두사
시뮬레이션 노드 ID는 옵션에 포함될 수 있습니다. 접두사_노드 or 노드.

함수 접두사
호출 함수의 이름은 옵션에 포함될 수 있습니다. 접두사_펑크 or 펑크.

NS_LOG 와일드 카드
로그 구성요소 와일드카드 `*'는 모든 구성요소를 활성화합니다. 모든 구성 요소를 한 번에 활성화하려면
특정 심각도 수준 사용 *=.

심각도 수준 옵션 와일드카드 `*'는 모든. 이 작업은 어떤 작업보다 먼저 발생해야 합니다.
`|' 옵션을 구분하는 문자. 모든 심각도 클래스를 활성화하려면 다음을 사용하십시오. =*,
or =*|.

옵션 와일드카드 `*' 또는 토큰 모든 모든 접두사 옵션을 활성화하지만 반드시 발생해야 함 시간 내에 a
`|' 성격. 특정 심각도 클래스 또는 수준과 모든 접두사를 활성화하려면 다음을 사용하십시오.
= |*.

결합된 옵션 와일드카드 ** 모든 심각도와 모든 접두사를 활성화합니다. 예를 들어,
=**.

우버 와일드카드 *** 모든 로그 구성 요소에 대해 모든 심각도와 모든 접두사를 활성화합니다.
다음은 모두 동일합니다.

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

주의 사항: 사소한 것조차도 스크래치 시뮬레이터 46K 라인 이상의 출력을 생성합니다.
NS_LOG="***"!

방법 더하다 로깅 your 암호
코드에 로깅을 추가하는 것은 매우 간단합니다.

1. NS_LOG_COMPONENT_DEFINE (...); 매크로 내부 네임 스페이스 ns3.
고유한 문자열 식별자를 만듭니다(일반적으로 파일 및/또는 클래스 이름을 기반으로 함).
파일 내에 정의됨) 다음과 같은 매크로 호출로 등록합니다.

네임스페이스 ns3 {

NS_LOG_COMPONENT_DEFINE("Ipv4L3프로토콜");
...

이 레지스터 Ipv4L3프로토콜 로그 구성 요소로.

(매크로는 내부 또는 외부에 포함될 수 있도록 주의 깊게 작성되었습니다.
네임 스페이스 ns3, 사용법은 코드베이스에 따라 다르지만 원래 의도는 다음과 같습니다.
이것을 등록하다 외부 네임스페이스의 ns3 파일 전역 범위에서.)

2. 함수 및 함수 본문에 로깅 문(매크로 호출)을 추가합니다.

로깅 매크로
로깅 매크로 및 관련 심각도 수준은 다음과 같습니다.

┌───────────────┬───────────────────────┐
│심각도 등급 │ 매크로 │
├───────────────┼───────────────────────┤
로그_없음 │ (필요 없음) │
├───────────────┼───────────────────────┤
로그_오류NS_LOG_ERROR (...);
├───────────────┼───────────────────────┤
로그_경고NS_LOG_WARN (...);
├───────────────┼───────────────────────┤
로그_디버그NS_LOG_DEBUG (...);
├───────────────┼───────────────────────┤
로그_정보NS_LOG_INFO (...);
├───────────────┼───────────────────────┤
로그_함수NS_LOG_FUNCTION (...);
├───────────────┼───────────────────────┤
로그_로직NS_LOG_LOGIC (...);
└───────────────┴───────────────────────┘

매크로는 출력 스트리머 역할을 하므로 무엇이든 보낼 수 있습니다. 표준::컷, 합류했다
by << 연산자는 허용됩니다:

void MyClass::Check(int 값, char * 항목)
{
NS_LOG_FUNCTION(이 << 인수 << 항목);
if (인수 > 10)
{
NS_LOG_ERROR("잘못된 값이 발견되었습니다" << 값 <
" 확인하는 동안 " << 이름 << "!");
}
...
}

참고 NS_LOG_FUNCTION `를 자동으로 삽입합니다.,'(쉼표-공백) 사이 구분 기호
각각의 주장. 이는 함수 인수의 로깅을 단순화합니다. 그냥 연결해
그들과 함께 << 위의 예에서와 같이.

무조건 로깅
편의상, NS_LOG_UNCOND (...); 매크로는 항상 인수를 기록합니다.
관련 로그 구성 요소는 어떤 심각도에서도 활성화되지 않습니다. 이 매크로는 어떤 것도 사용하지 않습니다
접두사 옵션 중 로깅은 디버그 빌드에서만 활성화됩니다. 이 매크로
최적화된 빌드에서는 출력을 생성하지 않습니다.

가이드 라인
· 모든 수업 방법을 다음과 같이 시작하세요. NS_LOG_FUNCTION (이 << 인수...); 이를 통해 쉽게
함수 호출 추적.

· 예외: 연산자나 명시적인 복사 생성자를 기록하지 마십시오.
무한 재귀 및 스택 오버플로.

· 인수가 없는 메서드의 경우 동일한 형식을 사용합니다. NS_LOG_FUNCTION (이것);

· 정적 함수의 경우:

· 인수 사용 NS_LOG_FUNCTION (...); 정상적으로.

· 인수 없이 사용 NS_LOG_FUNCTION_NOARGS ();

· 사용하다 NS_LOG_ERROR 시뮬레이션을 무효화할 수 있는 심각한 오류 조건의 경우
실행.

· 사용하다 NS_LOG_WARN 수정 가능한 비정상적인 조건의 경우. 힌트 좀 주세요
문제의 성격과 해결 방법에 대해 설명합니다.

· NS_LOG_DEBUG 일반적으로 다음에서 사용됩니다. ad 모델의 실행을 이해하는 방법.

· 사용하다 NS_LOG_INFO 크기와 같은 실행에 대한 추가 정보를 보려면
추가/제거할 때 데이터 구조.

· 사용하다 NS_LOG_LOGIC 함수 내의 중요한 논리 분기를 추적합니다.

· 로깅 변경으로 인해 코드가 손상되지 않는지 테스트하십시오. 다음을 사용하여 몇 가지 예제 프로그램을 실행하세요.
모든 로그 구성 요소가 켜져 있습니다(예: NS_LOG="***").

트레이싱
추적 하위 시스템은 이해해야 할 가장 중요한 메커니즘 중 하나입니다. NS-3. 에
대부분의 경우, NS-3 사용자는 새롭고 향상된 네트워킹에 대한 훌륭한 아이디어를 갖게 될 것입니다.
특징. 이 아이디어가 작동하는지 확인하기 위해 연구원은 다음을 변경합니다.
기존 시스템을 수집한 다음 실험을 실행하여 새로운 기능이 어떻게 작동하는지 확인합니다.
기능의 동작을 포착하는 통계입니다.

즉, 시뮬레이션 실행의 전체 요점은 추가 작업을 위한 출력을 생성하는 것입니다.
공부하다. ~ 안에 NS-3, 연구자가 이를 수행할 수 있게 해주는 하위 시스템은 추적입니다.
서브 시스템.

트레이싱 자극
프로그램에서 정보를 얻는 방법에는 여러 가지가 있습니다. 가장 직관적인 방법은
다음과 같이 정보를 표준 출력으로 직접 인쇄하려면

#포함
...
정수 메인()
{
...
std::cout << "x의 값은 " << x << std::endl;
...
}

이는 소규모 환경에서 실행 가능하지만 시뮬레이션이 점점 더 많아짐에 따라
복잡해지면 점점 더 많은 인쇄물과 구문 분석 및 수행 작업이 발생하게 됩니다.
출력에 대한 계산이 점점 더 어려워지기 시작합니다.

고려해야 할 또 다른 점은 새로운 재미있는 정보가 필요할 때마다 소프트웨어 코어가
편집하고 다른 인쇄물을 도입해야 합니다. 모든 것을 제어할 수 있는 표준화된 방법은 없습니다.
이 출력의 양은 한계 없이 증가하는 경향이 있습니다. 결국,
단순히 이 정보를 출력하는 데 필요한 대역폭이 실행 시간을 제한하기 시작합니다.
시뮬레이션의. 출력 파일은 엄청난 크기로 커지고 이를 구문 분석하는 것은
문제가 발생했습니다.

NS-3 로깅을 위한 간단한 메커니즘을 제공하고 다음을 통해 출력에 대한 일부 제어를 제공합니다.
로그 구성 요소들, 그러나 제어 수준은 전혀 세밀하지 않습니다. 로깅
모듈은 비교적 무딘 도구입니다.

핵심 시스템에 접근할 수 있는 시설을 갖추는 것이 바람직합니다.
핵심 시스템을 변경하고 다시 컴파일하지 않고도 필요한 정보를 얻을 수 있습니다. 심지어
관심 항목이 변경되거나 변경될 때 사용자에게 알려주는 시스템이 더 좋습니다.
흥미로운 사건이 일어났습니다.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 추적 시스템은 이러한 라인을 따라 작동하도록 설계되었으며 다음과 잘 통합됩니다.
상대적으로 간단한 사용 시나리오를 허용하는 Attribute 및 Config 하위 항목입니다.

살펴보기
추적 하위 시스템은 다음에 크게 의존합니다. NS-3 콜백 및 속성 메커니즘. 너
시도하기 전에 설명서의 해당 섹션을 읽고 이해해야 합니다.
추적 시스템을 이해합니다.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 추적 시스템은 독립적인 추적 소스 및
싱크 추적; 소스를 싱크에 연결하는 균일한 메커니즘과 함께 제공됩니다.

추적 소스는 시뮬레이션에서 발생하는 이벤트에 신호를 보내고 다음을 제공할 수 있는 엔터티입니다.
흥미로운 기본 데이터에 액세스할 수 있습니다. 예를 들어 추적 소스는
패킷은 네트 장치에 의해 수신되고 패킷 내용에 대한 액세스를 제공합니다.
관심 추적 싱크. 추적 소스는 관심 있는 상태가 언제 표시될 수도 있습니다.
변화는 모델에서 일어난다. 예를 들어, TCP 모델의 혼잡 창은 소수입니다.
추적 소스 후보입니다.

추적 소스는 그 자체로는 유용하지 않습니다. 다른 코드 조각에 연결되어야 합니다.
소스에서 제공하는 정보로 실제로 유용한 작업을 수행합니다. 그만큼
추적 정보를 사용하는 엔터티를 추적 싱크라고 합니다. 추적 소스는
이벤트 생성자와 추적 싱크는 소비자입니다.

이러한 명시적인 구분을 통해 많은 수의 추적 소스를 분산시킬 수 있습니다.
모델 작성자가 유용하다고 생각하는 장소에 시스템을 적용합니다. 사용자가 연결하지 않는 한
싱크를 이러한 소스 중 하나로 추적하면 아무것도 출력되지 않습니다. 이 배열은 상대적으로
복잡하지 않은 사용자는 새로운 유형의 싱크를 기존 추적 소스에 연결하지 않고
시뮬레이터의 코어 또는 모델을 편집하고 다시 컴파일해야 합니다.

추적 소스에서 생성된 추적 이벤트의 소비자는 XNUMX명 이상일 수 있습니다. 하나는 수
추적 소스를 일종의 지점 대 다중 지점 정보 링크로 생각하십시오.

이 개념적 지점 대 다중 지점 링크에 대한 "전송 프로토콜"은 NS-3 콜백.

콜백 기능은 두 개의 모듈을 허용하는 방법이라는 것을 콜백 섹션에서 상기하십시오.
호출을 분리하는 동시에 함수 호출을 통해 통신하는 시스템
호출된 클래스의 함수를 완전히 호출합니다. 이는 위에서 설명한 것과 동일한 요구 사항입니다.
추적 시스템의 경우.

기본적으로 추적 소스 is 여러 함수가 등록될 수 있는 콜백입니다.
추적 싱크가 추적 이벤트 수신에 관심을 표시하면
추적 소스가 보유한 콜백 목록입니다. 흥미로운 사건이 발생하면 추적
소스가 호출합니다. 운영자() XNUMX개 이상의 매개변수를 제공합니다. 이것은 소스에게 다음과 같이 지시합니다.
각각을 차례로 호출하는 콜백 목록을 살펴보세요. 이런 식으로 매개변수(들)
이는 단지 함수일 뿐인 추적 싱크로 전달됩니다.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 가장 간단한 예시
우리가 말한 내용을 강화하기 위해 간단한 예를 살펴보는 것이 유용할 것입니다.:

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

#포함

네임스페이스 ns3 사용;

가장 먼저 해야 할 일은 필요한 파일을 포함시키는 것입니다. 위에서 언급한 것처럼 추적 시스템은
객체 및 속성 시스템을 많이 사용합니다. 처음 두 개에는
해당 시스템에 대한 선언. 파일, 추적 값.h 필수를 가져옵니다
값 의미 체계를 따르는 데이터 추적을 위한 선언입니다.

일반적으로 값 의미론은 단지 객체를 전달할 수 있다는 것을 의미합니다.
주소. 가치 의미론을 사용하려면 다음과 같은 객체가 있어야 합니다.
연관된 복사 생성자와 할당 연산자를 사용할 수 있습니다. 우리는 요구 사항을 확장합니다
POD(Plain-Old-Data) 유형에 대해 사전 정의된 연산자 세트에 대해 이야기합니다.
연산자=, 연산자++, 연산자--, 연산자+, 연산자== 등

이것이 의미하는 바는 다음을 사용하여 객체에 대한 변경 사항을 추적할 수 있다는 것입니다.
그 연산자.:

클래스 MyObject : 공용 객체
{
공공의:
정적 TypeId GetTypeId(무효)
{
정적 TypeId tid = TypeId("MyObject")
.SetParent(객체::GetTypeId())
.AddConstructor ()
.AddTraceSource("MyInteger",
"추적할 정수 값입니다.",
MakeTraceSourceAccessor(&MyObject::m_myInt))
;
정시 반환;
}

내객체() {}
추적된 값 m_myInt;
};

추적 시스템이 속성과 통합되고 속성이 개체와 함께 작동하므로
이 있어야합니다 NS-3 목적 추적 소스가 살기 위해. 두 가지 중요한 라인은
코드는 .AddTraceSource 그리고 추적된 값 선언.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 .AddTraceSource 추적 소스를 연결하는 데 사용되는 "후크"를 제공합니다.
외부 세계. 그만큼 추적된 값 선언은 오버로드되는 인프라를 제공합니다.
위에서 언급한 연산자를 사용하고 콜백 프로세스를 구동합니다.:

무효화
IntTrace(Int oldValue, Int newValue)
{
std::cout << "추적된 " << oldValue << "에서 " << newValue << std::endl;
}

이것이 추적 싱크의 정의입니다. 콜백 함수에 직접적으로 대응됩니다.
이 함수는 연산자 중 하나가 호출될 때마다 호출됩니다. 추적된 값 is
실행.:

INT
메인(int argc, char *argv[])
{
포인트 myObject = CreateObject ();

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

myObject->m_myInt = 1234;
}

이 코드 조각에서 가장 먼저 해야 할 일은 개체를 만드는 것입니다.
추적 소스가 살아있습니다.

다음 단계는 TraceConnectWithoutContext, 추적 간의 연결을 형성합니다.
소스 및 추적 싱크. 주목하세요 MakeCallback 템플릿 기능. 에서 회상
제공을 담당하는 특수 펑터를 생성하는 콜백 섹션
오버로드 운영자() 콜백을 "실행"하는 데 사용됩니다. 오버로드된 연산자(++, -- 등)
이것을 사용할 것이다 운영자() 실제로 콜백을 호출합니다. 그만큼 TraceConnectWithoutContext,
추적에 할당된 속성의 이름을 제공하는 문자열 매개변수를 사용합니다.
원천. 아직은 중요하지 않기 때문에 지금은 컨텍스트에 대한 부분을 무시하겠습니다.

마지막으로 다음 줄은 다음과 같습니다.

myObject->m_myInt = 1234;

~을 호출하는 것으로 해석되어야 한다. operator = 멤버 변수에 m_myInt
매개변수로 전달된 정수 1234. 이 연산자는 다음과 같이 정의됩니다.
추적된 값) void를 반환하고 두 개의 정수 값을 다음과 같이 사용하는 콜백을 실행합니다.
매개변수 - 문제의 정수에 대한 이전 값과 새 값. 그것은 바로
우리가 제공한 콜백 함수의 함수 서명 -- 인트레이스.

요약하면 추적 소스는 본질적으로 콜백 목록을 보유하는 변수입니다. ㅏ
트레이스 싱크는 콜백의 대상으로 사용되는 함수입니다. 속성 및 개체 유형
정보 시스템은 추적 소스를 추적 싱크에 연결하는 방법을 제공하는 데 사용됩니다. 그만큼
추적 소스를 "적중"하는 행위는 추적 소스에서 연산자를 실행하는 것입니다.
콜백. 그 결과 추적 싱크 콜백이 소스에 관심을 등록하게 됩니다.
소스에서 제공하는 매개변수를 사용하여 호출됩니다.

사용 전에, 구성 서브 시스템 연결하기 더듬다 지우면 좋을거같음 . SM
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 TraceConnectWithoutContext 위의 간단한 예에 표시된 호출은 실제로 매우
시스템에서는 거의 사용되지 않습니다. 보다 일반적으로, 구성 하위 시스템은 선택을 허용하는 데 사용됩니다.
호출되는 것을 사용하여 시스템의 추적 소스 설정 통로.

예를 들어, 시스템에서 다음과 같은 것을 찾을 수 있습니다.
예제/tcp-large-transfer.cc):

void CwndTracer(uint32_t oldval, uint32_t newval) {}

...

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

이것은 매우 친숙해 보일 것입니다. 차이점을 제외하면 앞의 예와 동일합니다.
클래스의 정적 멤버 함수 구성 에 대한 메서드 대신 호출되고 있습니다. 목적;
그리고 대신에 속성 이름, 경로를 제공하고 있습니다.

가장 먼저 해야 할 일은 경로를 거꾸로 읽는 것입니다. 경로의 마지막 세그먼트는 다음과 같아야 합니다.
an 속성목적. 실제로, 만약 당신이 목적 그것은
"혼잡 창" 속성 편리하다(전화해 그 물체), 다음과 같이 작성할 수 있습니다.
이전 예:

void CwndTracer(uint32_t oldval, uint32_t newval) {}

...

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

코드는 다음과 같습니다. 구성::ConnectWithoutContext 바로 그런 일을 합니다. 이것
함수는 다음의 체인을 나타내는 경로를 취합니다. 목적 포인터를 가리키고 포인터가 나올 때까지 따라갑니다.
경로의 끝에 도달하고 마지막 세그먼트를 다음과 같이 해석합니다. 속성 마지막에
물체. 어떤 일이 일어나는지 살펴보겠습니다.

경로의 선행 "/" 문자는 소위 네임스페이스를 나타냅니다. 중 하나
구성 시스템에 미리 정의된 네임스페이스는 "NodeList"입니다.
시뮬레이션의 노드. 목록의 항목은 목록의 색인으로 참조됩니다.
"/NodeList/0"은 시뮬레이션으로 생성된 노드 목록의 XNUMX번째 노드를 나타냅니다.
이 노드는 실제로 Ptr 의 하위 클래스도 마찬가지입니다. ns3::객체.

객체 모델 섹션에 설명된 대로, NS-3 개체 집계 모델을 지원합니다. 그만큼
다음 경로 세그먼트는 다음을 나타내는 "$" 문자로 시작됩니다. 객체 가져오기 전화는 다음과 같아야합니다
다음에 오는 유형을 찾아보았습니다. 노드가 초기화될 때
인터넷스택헬퍼 여러 인터페이스가 노드에 집계됩니다. 이들 중 하나는
TCP 레벨 XNUMX 프로토콜. 이 프로토콜 객체의 런타임 유형은 다음과 같습니다. ns3::TcpL4Protocol''.
인셀덤 공식 판매점인 전에, ``GetObject 실행되면 이 유형의 객체에 대한 포인터를 반환합니다.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 TcpL4프로토콜 클래스는 "SocketList"라는 속성을 정의합니다.
소켓. 각 소켓은 실제로 ns3::객체 자체적으로 Attributes. 의 항목
소켓 목록은 NodeList에서와 마찬가지로 인덱스로 참조되므로 "SocketList/0"
NodeList의 XNUMX번째 노드에 있는 소켓 목록의 XNUMX번째 소켓을 나타냅니다.
시뮬레이션에서 생성된 첫 번째 노드입니다.

이 소켓의 유형은 다음과 같습니다. ns3::TcpSocketImpl 속성을 정의합니다
"CongestionWindow"라고 불리는 추적된 값. 그만큼
구성::ConnectWithoutContext 이제 다음을 수행합니다.

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

추적 간의 연결을 만드는 "SocketList/0"의 개체 포인터를 사용합니다.
콜백에 대한 소켓에 정의된 소스 - CwndTracer.

이제 설정이 변경될 때마다 추적된 값 혼잡함을 표현하는
TCP 소켓의 창에 등록된 콜백이 실행되고 함수
CwndTracer TCP 정체의 이전 값과 새 값을 인쇄하는 작업이 호출됩니다.
창.

사용 전에, 트레이싱 API
추적 시스템과의 상호작용에는 세 가지 수준이 있습니다.

· 초보 사용자는 추적에 참여하는 개체를 쉽게 제어할 수 있습니다.

· 중급 사용자는 추적 시스템을 확장하여 생성된 출력 형식을 수정할 수 있습니다.
또는 핵심을 수정하지 않고 기존 추적 소스를 다른 방식으로 사용합니다.
모의 실험 장치;

· 고급 사용자는 시뮬레이터 코어를 수정하여 새로운 추적 소스 및 싱크를 추가할 수 있습니다.

사용 더듬다 도우미
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 추적 도우미는 다양한 구성 및 선택을 위한 풍부한 환경을 제공합니다.
이벤트를 추적하여 파일에 기록합니다. 이전 섹션에서는 주로 "건물
토폴로지"에서 우리는 사용하도록 설계된 여러 종류의 추적 도우미 메서드를 보았습니다.
다른 (장치) 도우미 내부.

아마도 다음과 같은 변형 중 일부를 본 것을 기억할 것입니다.

pointToPoint.EnablePcapAll("초");
pointToPoint.EnablePcap("초", p2pNodes.Get(0)->GetId(), 0);
csma.EnablePcap("제0", csmaDevices.Get(XNUMX), true);
pointToPoint.EnableAsciiAll(ascii.CreateFileStream("myfirst.tr"));

그러나 분명하지 않은 것은 모든 분야에 일관된 모델이 있다는 것입니다.
시스템에서 찾은 추적 관련 메서드입니다. 이제 잠시 시간을 내어 살펴보겠습니다.
"큰 그림"에서.

현재 추적 도우미의 두 가지 기본 사용 사례가 있습니다. NS-3: 장치 도우미
그리고 프로토콜 도우미. 장치 도우미는 어떤 추적을 지정해야 하는지 문제를 살펴봅니다.
노드, 장치 쌍을 통해 활성화됩니다. 예를 들어, 다음과 같이 pcap을 지정할 수 있습니다.
특정 노드의 특정 장치에서 추적을 활성화해야 합니다. 이는 다음과 같습니다.
NS-3 장치 개념 모델 및 다양한 장치의 개념 모델
도우미. 이에 따라 자연스럽게 생성된 파일은
- - 명명 규칙.

프로토콜 도우미는 다음을 통해 활성화해야 하는 추적을 지정하는 문제를 살펴봅니다.
프로토콜과 인터페이스 쌍. 이는 다음과 같습니다. NS-3 프로토콜 스택 개념 모델,
인터넷 스택 도우미의 개념적 모델도 있습니다. 당연히 추적 파일은
다음을 따라야 한다 - - 명명 규칙.

따라서 추적 도우미는 자연스럽게 XNUMX차원 분류 체계에 속하게 됩니다. 있다
네 가지 클래스가 모두 동일하게 행동하는 것을 방해하는 미묘한 점들이 있지만 우리는 그렇게 하기 위해 노력합니다.
가능한 한 모두 유사하게 작동하도록 하십시오. 그리고 가능할 때마다 다음과 같은 유사점이 있습니다.
모든 클래스의 모든 메소드.

┌────────────────┬──────┬───────┐
│ │ pcap │ ascii │
├────────────────┼──────┼───────┤
│장치 도우미 │ │ │
├────────────────┼──────┼───────┤
│프로토콜 도우미 │ │ │
└────────────────┴──────┴───────┘

라는 접근 방식을 사용합니다. 믹스 인 도우미 클래스에 추적 기능을 추가합니다. ㅏ
믹스 인 하위 클래스에 상속된 기능을 제공하는 클래스입니다.
mixin에서 상속하는 것은 전문화의 한 형태로 간주되지 않지만 실제로는
기능을 수집합니다.

이 네 가지 사례 모두와 각각의 사례를 간단히 살펴보겠습니다. 믹스 인.

피캡 트레이싱 장치 도우미
이러한 도우미의 목표는 일관된 pcap 추적 기능을 쉽게 추가할 수 있도록 하는 것입니다.
NS-3 장치. 우리는 pcap 추적의 다양한 유형이 모두 동일하게 작동하기를 원합니다.
모든 장치이므로 이러한 헬퍼의 메서드는 장치 헬퍼에 의해 상속됩니다. 구경하다
at src/네트워크/helper/trace-helper.h 보면서 토론을 따라가고 싶다면
실제 코드.

클래스 PcapHelperForDevice 하는 믹스 인 사용하기 위한 높은 수준의 기능을 제공합니다.
pcap 추적 NS-3 장치. 모든 장치는 단일 가상 메서드를 구현해야 합니다.
이 클래스에서 상속되었습니다.:

가상 무효 EnablePcapInternal(std::string 접두사, Ptr nd, bool promiscuous) = 0;

이 방법의 시그니처는 현재 상황에 대한 장치 중심적 관점을 반영합니다.
수준. 클래스에서 상속된 모든 공개 메소드 PcapUserHelperForDevice 로 줄이다
이 단일 장치 종속 구현 방법을 호출합니다. 예를 들어, 가장 낮은 수준
pcap 방법:

void EnablePcap(std::string 접두사, Ptr nd, bool promiscuous = false, boolexplicitFilename = false);

다음의 장치 구현을 호출합니다. Pcap내부 활성화 곧장. 기타 모든 공개 PCAP
추적 방법은 이 구현을 기반으로 구축되어 추가 사용자 수준을 제공합니다.
기능. 이것이 사용자에게 의미하는 바는 시스템의 모든 장치 도우미가
모든 pcap 추적 방법을 사용할 수 있어야 합니다. 이 방법은 모두 동일하게 작동합니다.
기기가 구현하는 경우 여러 기기에 걸쳐 Pcap내부 활성화 바르게.

피캡 트레이싱 장치 돕는 사람 행동 양식
void EnablePcap(std::string 접두사, Ptr 그리고,
bool promiscuous = false, boolexplicitFilename = false);
무효 EnablePcap(std::string 접두사, std::string ndName,
bool promiscuous = false, boolexplicitFilename = false);
void EnablePcap(std::string 접두사, NetDeviceContainer d,
bool 무차별 = 거짓);
void EnablePcap(std::string 접두사, NodeContainer n,
bool 무차별 = 거짓);
void EnablePcap(std::string 접두사, uint32_t nodeid, uint32_t deviceid,
bool 무차별 = 거짓);
void EnablePcapAll (std::string 접두사, bool promiscuous = false);

위에 표시된 각 메소드에는 다음과 같은 기본 매개변수가 있습니다. 난잡한
기본값은 false입니다. 이 매개변수는 추적이 수집되어서는 안 됨을 나타냅니다.
무차별 모드. 장치에서 본 모든 트래픽을 추적에 포함시키려는 경우
(그리고 장치가 무차별 모드를 지원하는 경우) 다음 중 하나에 실제 매개변수를 추가하기만 하면 됩니다.
위에서 호출합니다. 예를 들어,:

Ptr 차;
...
helper.EnablePcap("접두사", nd, true);

무차별 모드 캡처를 활성화합니다. NetDevice 에 의해 지정된 nd.

처음 두 메서드에는 다음과 같은 기본 매개 변수도 포함됩니다. 명시적 파일 이름 그럴거야.
아래에서 논의됩니다.

수업을 위해 Doxygen을 정독하는 것이 좋습니다 PcapHelperForDevice 세부 사항을 찾으려면
이러한 방법 중; 하지만 요약하자면 ...

다음을 제공하여 특정 노드/네트 장치 쌍에서 pcap 추적을 활성화할 수 있습니다.
포인트Pcap 활성화 방법. 그만큼 Ptr net 장치 이후로 암시적입니다.
정확히 하나에 속해야 합니다. 노드. 예를 들어,:

Ptr 차;
...
helper.EnablePcap("접두사", nd);

다음을 제공하여 특정 노드/네트 장치 쌍에서 pcap 추적을 활성화할 수 있습니다.
표준::문자열 객체 이름 서비스 문자열을 Pcap 활성화 방법. 그만큼
포인트 이름 문자열에서 조회됩니다. 다시 말하지만, 이후로 암시적입니다.
명명된 넷 장치는 정확히 하나의 장치에 속해야 합니다. 노드. 예를 들어,:

이름::추가("서버" ...);
이름::추가("서버/eth0" ...);
...
helper.EnablePcap ("접두사", "서버/ath0");

다음을 제공하여 노드/네트 장치 쌍 모음에서 pcap 추적을 활성화할 수 있습니다.
NetDevice컨테이너. 각각 NetDevice 컨테이너에서 유형이 확인됩니다. 각각
적절한 유형의 장치(장치 도우미가 관리하는 것과 동일한 유형), 추적은
활성화되었습니다. 다시 말하지만, 발견된 네트 장치는 정확히 다음에 속해야 하므로 암시적입니다.
노드. 예를 들어,:

NetDeviceContainer d = ...;
...
helper.EnablePcap("접두사", d);

다음을 제공하여 노드/네트 장치 쌍 모음에서 pcap 추적을 활성화할 수 있습니다.
노드컨테이너. 각각 노드 인간을 노드컨테이너 붙어있어 NetDevices 반복됩니다.
각각 NetDevice 컨테이너의 각 노드에 연결된 경우 해당 장치의 유형은 다음과 같습니다.
확인. 적절한 유형의 각 장치에 대해(장치에서 관리하는 것과 동일한 유형
도우미), 추적이 활성화됩니다.:

NodeContainern;
...
helper.EnablePcap("접두사", n);

명시적인 정보뿐만 아니라 노드 ID와 장치 ID를 기반으로 pcap 추적을 활성화할 수 있습니다.
Ptr. 마다 노드 시스템에는 정수 노드 ID가 있고 각 장치는 노드에 연결되어 있습니다.
정수 장치 ID가 있습니다.:

helper.EnablePcap("접두사", 21, 1);

마지막으로 다음과 같은 유형으로 시스템의 모든 장치에 대해 pcap 추적을 활성화할 수 있습니다.
장치 도우미에 의해 관리됩니다.:

helper.EnablePcapAll("접두사");

피캡 트레이싱 장치 돕는 사람 파일 이름 선택
위의 방법 설명에 내포된 것은 다음과 같은 방법으로 완전한 파일 이름을 구성하는 것입니다.
구현 방법. 관례적으로 pcap은 다음에서 추적합니다. NS-3 시스템은 다음과 같은 형태입니다.
- 아이디>- 아이디>.pcap

앞서 언급했듯이 시스템의 모든 노드에는 시스템 할당 노드 ID가 있습니다. 그리고
모든 장치에는 노드와 관련된 인터페이스 인덱스(장치 ID라고도 함)가 있습니다.
그러면 기본적으로 첫 번째 항목에서 추적을 활성화한 결과로 생성된 pcap 추적 파일이 생성됩니다.
접두사 "prefix"를 사용하는 노드 21의 장치는 접두사-21-1.pcap.

항상 사용할 수 있습니다 NS-3 이것을 더 명확하게 하기 위해 객체 이름 서비스. 예를 들어,
개체 이름 서비스를 사용하여 "server"라는 이름을 노드 21에 할당하면 결과 pcap이 생성됩니다.
추적 파일 이름은 자동으로 다음과 같이 됩니다. 접두사-서버-1.pcap 또한
장치에 "eth0"이라는 이름을 지정하면 pcap 파일 이름이 자동으로 이를 선택하여
라는 접두사-서버-eth0.pcap.

마지막으로 위에 표시된 두 가지 방법은 다음과 같습니다.

void EnablePcap(std::string 접두사, Ptr nd, bool promiscuous = false, boolexplicitFilename = false);
void EnablePcap(std::string 접두사, std::string ndName, bool promiscuous = false, boollicitFilename = false);

라는 기본 매개변수가 있습니다. 명시적 파일 이름. true로 설정하면 이 매개변수는
자동 파일 이름 완성 메커니즘을 비활성화하고 명시적인 파일 이름을 생성할 수 있습니다.
파일 이름. 이 옵션은 컴퓨터에서 pcap 추적을 활성화하는 방법에서만 사용할 수 있습니다.
단일 장치.

예를 들어 장치 도우미가 단일 무차별 pcap을 생성하도록 준비하려면
특정 이름의 캡처 파일(내-pcap-file.pcap) 특정 장치에서 다음을 수행할 수 있습니다.

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

처음으로 참된 매개변수는 무차별 모드 추적을 활성화하고 두 번째 매개변수는 도우미에게 알려줍니다.
해석하다 접두사 매개변수를 완전한 파일 이름으로 사용합니다.

아스키 트레이싱 장치 도우미
ASCII 추적 도우미의 동작 믹스 인 pcap 버전과 실질적으로 유사합니다.
살펴 src/네트워크/helper/trace-helper.h 토론을 팔로우하고 싶다면
실제 코드를 보면서.

클래스 AsciiTraceHelperForDevice ASCII 사용을 위한 고급 기능을 추가합니다.
장치 도우미 클래스를 추적합니다. pcap의 경우와 마찬가지로 모든 장치는 다음을 구현해야 합니다.
ASCII 추적에서 상속된 단일 가상 메서드 믹스 인.:

가상 무효 EnableAsciiInternal(Ptr 스트림, std::문자열 접두사, Ptr nd) = 0;

이 방법의 시그니처는 현재 상황에 대한 장치 중심적 관점을 반영합니다.
수준; 또한 도우미가 공유 출력 스트림에 쓸 수 있다는 사실도 있습니다. 모든
클래스에서 상속된 공개 ASCII 추적 관련 메서드 AsciiTraceHelperForDevice
이 단일 장치 종속 구현 방법을 호출하는 것으로 줄입니다. 예를 들어,
가장 낮은 수준의 ASCII 추적 방법:

void EnableAscii(std::string 접두사, Ptr 차);
무효 EnableAscii(Ptr 스트림, PTR 차);

다음의 장치 구현을 호출합니다. Ascii내부 활성화 직접,
유효한 접두사 또는 스트림. 다른 모든 공개 ASCII 추적 방법은 이를 기반으로 구축됩니다.
추가 사용자 수준 기능을 제공하는 하위 수준 기능입니다. 이것이 무엇을 의미하는가?
사용자는 시스템의 모든 장치 도우미가 모든 ASCII 추적 방법을 갖게 된다는 것입니다.
사용 가능; 이러한 방법은 장치가 다음과 같은 경우 모든 장치에서 동일한 방식으로 작동합니다.
구현 EnablAscii내부 바르게.

아스키 트레이싱 장치 돕는 사람 행동 양식
void EnableAscii(std::string 접두사, Ptr 차);
무효 EnableAscii(Ptr 스트림, PTR 차);

void EnableAscii(std::string 접두사, std::string ndName);
무효 EnableAscii(Ptr 스트림, std::string ndName);

무효 EnableAscii(std::문자열 접두사, NetDeviceContainer d);
무효 EnableAscii(Ptr 스트림, NetDeviceContainer d);

void EnableAscii(std::string 접두사, NodeContainer n);
무효 EnableAscii(Ptr 스트림, NodeContainer n);

void EnableAscii(std::string 접두사, uint32_t nodeid, uint32_t deviceid);
무효 EnableAscii(Ptr 스트림, uint32_t nodeid, uint32_t deviceid);

무효 EnableAsciiAll(std::문자열 접두사);
무효 EnableAsciiAll(Ptr 개울);

수업을 위해 Doxygen을 정독하는 것이 좋습니다 TraceHelperForDevice 를 찾는 방법
이러한 방법의 세부사항; 하지만 요약하자면 ...

pcap에 비해 ASCII 추적에 사용할 수 있는 방법이 두 배나 많습니다.
트레이싱. 이는 pcap 스타일 모델 외에도 각 항목의 추적이 이루어지기 때문입니다.
고유한 노드/장치 쌍이 고유한 파일에 기록되므로 추적하는 모델을 지원합니다.
많은 노드/장치 쌍에 대한 정보가 공통 파일에 기록됩니다. 이는
- - 파일 이름 생성 메커니즘은 다음 메커니즘으로 대체됩니다.
공통 파일을 참조하십시오. 모든 API 메소드를 허용하기 위해 API 메소드 수가 두 배로 늘어났습니다.
조합.

pcap 추적과 마찬가지로 특정 노드/네트 장치 쌍에서 ASCII 추적을 활성화할 수 있습니다.
제공함으로써 포인트Ascii 활성화 방법. 그만큼 Ptr 이후로 암시적이다
네트 장치는 정확히 하나의 장치에 속해야 합니다. 노드. 예를 들어,:

Ptr 차;
...
helper.EnableAscii("접두사", nd);

이 경우 추적 컨텍스트는 ASCII 추적 파일에 기록되지 않습니다.
불필요한. 시스템은 다음과 동일한 규칙을 사용하여 생성할 파일 이름을 선택합니다.
파일에 ".tr"이라는 접미사가 붙는다는 점을 제외하고는 pcap 섹션에 설명되어 있습니다.
".pcap".

둘 이상의 네트워크 장치에서 ASCII 추적을 활성화하고 모든 추적을 전송하려는 경우
단일 파일을 참조하려면 객체를 사용하여 단일 파일을 참조하면 됩니다.

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

이 경우 추적 컨텍스트는 필수이므로 ASCII 추적 파일에 기록됩니다.
두 장치에서 추적을 명확하게 합니다. 사용자가 완전히
파일 이름을 지정하는 경우 일관성을 위해 문자열에 ".tr"이 포함되어야 합니다.

다음을 제공하여 특정 노드/네트 장치 쌍에서 ASCII 추적을 활성화할 수 있습니다.
표준::문자열 객체 이름 서비스 문자열을 Pcap 활성화 방법. 그만큼
포인트 이름 문자열에서 조회됩니다. 다시 말하지만, 이후로 암시적입니다.
명명된 넷 장치는 정확히 하나의 장치에 속해야 합니다. 노드. 예를 들어,:

이름::추가("클라이언트" ...);
이름::추가("클라이언트/eth0" ...);
이름::추가("서버" ...);
이름::추가("서버/eth0" ...);
...
helper.EnableAscii("접두사", "클라이언트/eth0");
helper.EnableAscii("접두사", "서버/eth0");

그러면 다음과 같은 두 개의 파일이 생성됩니다. 접두사-클라이언트-eth0.tr and 접두사-서버-eth0.tr
각 추적 파일의 각 장치에 대한 추적입니다. 모든 EnableAscii 이후
함수가 스트림 래퍼를 사용하도록 오버로드되는 경우 해당 형식도 사용할 수 있습니다.

이름::추가("클라이언트" ...);
이름::추가("클라이언트/eth0" ...);
이름::추가("서버" ...);
이름::추가("서버/eth0" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAscii(스트림, "클라이언트/eth0");
helper.EnableAscii(스트림, "서버/eth0");

이렇게 하면 다음과 같은 단일 추적 파일이 생성됩니다. 추적 파일 이름.tr 모두 포함하는
두 장치에 대한 추적 이벤트. 이벤트는 추적 컨텍스트에 의해 명확해집니다.
문자열.

다음을 제공하여 노드/네트 장치 쌍 모음에서 ASCII 추적을 활성화할 수 있습니다.
NetDevice컨테이너. 각각 NetDevice 컨테이너에서 유형이 확인됩니다. 각각
적절한 유형의 장치(장치 도우미가 관리하는 것과 동일한 유형), 추적은
활성화되었습니다. 다시 말하지만, 발견된 네트 장치는 정확히 다음에 속해야 하므로 암시적입니다.
노드. 예를 들어,:

NetDeviceContainer d = ...;
...
helper.EnableAscii("접두사", d);

이로 인해 다수의 ASCII 추적 파일이 생성되며 각 파일은 다음과 같습니다.
그만큼 - - .tr 규칙. 모든 흔적을 하나로 결합
단일 파일은 위의 예와 유사하게 수행됩니다.

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

다음을 제공하여 노드/네트 장치 쌍 모음에서 ASCII 추적을 활성화할 수 있습니다.
노드컨테이너. 각각 노드 인간을 노드컨테이너 붙어있어 NetDevices 반복됩니다.
각각 NetDevice 컨테이너의 각 노드에 연결된 경우 해당 장치의 유형은 다음과 같습니다.
확인. 적절한 유형의 각 장치에 대해(장치에서 관리하는 것과 동일한 유형
도우미), 추적이 활성화됩니다.:

NodeContainern;
...
helper.EnableAscii ("접두사", n);

이로 인해 다수의 ASCII 추적 파일이 생성되며 각 파일은 다음과 같습니다.
그만큼 - - .tr 규칙. 모든 흔적을 하나로 결합
단일 파일은 위의 예와 유사하게 수행됩니다.

명시적인 정보뿐만 아니라 노드 ID와 장치 ID를 기반으로 pcap 추적을 활성화할 수 있습니다.
Ptr. 마다 노드 시스템에는 정수 노드 ID가 있고 각 장치는 노드에 연결되어 있습니다.
정수 장치 ID가 있습니다.:

helper.EnableAscii("접두사", 21, 1);

물론, 위와 같이 추적을 단일 파일로 결합할 수 있습니다.

마지막으로 다음과 같은 유형으로 시스템의 모든 장치에 대해 pcap 추적을 활성화할 수 있습니다.
장치 도우미에 의해 관리됩니다.:

helper.EnableAsciiAll("접두사");

이로 인해 여러 개의 ASCII 추적 파일이 생성됩니다(모든 장치당 하나씩).
도우미가 관리하는 유형의 시스템입니다. 이 모든 파일은 다음을 따릅니다.
- - .tr 규칙. 모든 추적을 하나의 추적으로 결합
파일은 위의 예와 유사하게 수행됩니다.

아스키 트레이싱 장치 돕는 사람 파일 이름 선택
위의 접두사 스타일 메서드 설명에 암시된 것은 완전한 구성입니다.
구현 방법에 따른 파일 이름. 관례적으로 ASCII는 NS-3 시스템은
형태의 - 아이디>- 아이디>.tr.

앞서 언급했듯이 시스템의 모든 노드에는 시스템 할당 노드 ID가 있습니다. 그리고
모든 장치에는 노드와 관련된 인터페이스 인덱스(장치 ID라고도 함)가 있습니다.
그러면 기본적으로 첫 번째 추적을 활성화한 결과로 생성된 ASCII 추적 파일이 생성됩니다.
접두사 "prefix"를 사용하는 노드 21의 장치는 다음과 같습니다. 접두사-21-1.tr.

항상 사용할 수 있습니다 NS-3 이것을 더 명확하게 하기 위해 객체 이름 서비스. 예를 들어,
개체 이름 서비스를 사용하여 "server"라는 이름을 노드 21에 할당하면 결과는 다음과 같습니다.
ASCII 추적 파일 이름은 자동으로 다음과 같이 됩니다. 접두사-서버-1.tr 그리고 당신이 또한 할당한다면
장치에 "eth0"이라는 이름을 추가하면 ASCII 추적 파일 이름이 자동으로 이를 선택합니다.
그리고 부름을 받다 접두사-서버-eth0.tr.

피캡 트레이싱 프로토콜 도우미
이들의 목표 믹스 인 일관된 pcap 추적 기능을 쉽게 추가할 수 있도록 하는 것입니다.
프로토콜. 우리는 pcap 추적의 다양한 유형이 모두 동일하게 작동하기를 원합니다.
프로토콜이므로 이러한 도우미의 메서드는 스택 도우미에 의해 상속됩니다. 보세요
src/네트워크/helper/trace-helper.h 보면서 토론을 따라가고 싶다면
실제 코드.

이 섹션에서는 프로토콜에 적용되는 방법을 설명합니다. IPv4. 에
유사한 프로토콜로 추적을 지정하려면 적절한 유형으로 대체하면 됩니다. 예를 들어,
~을 사용하다 포인트 대신에 포인트 전화 PcapIpv6 활성화 대신 PcapIpv4 활성화.

클래스 PcapHelperForIpv4 pcap 추적을 사용하기 위한 높은 수준의 기능을 제공합니다.
인간을 IPv4 규약. 이러한 메서드를 활성화하는 각 프로토콜 도우미는 단일 메서드를 구현해야 합니다.
이 클래스에서 상속된 가상 메서드입니다. 별도의 구현이 있을 예정입니다.
IPv6, 예를 들어 메서드 이름과 서명에만 차이가 있습니다.
클래스를 명확하게 하려면 다른 메소드 이름이 필요합니다. IPv4IPv6 둘 다
클래스에서 파생됨 목적및 동일한 서명을 공유하는 메서드.:

가상 무효 EnablePcapIpv4Internal(std::string 접두사, Ptr ipv4, uint4_t 인터페이스) = 32;

이 메소드의 서명은 프로토콜과 인터페이스 중심 관점을 반영합니다.
이 수준의 상황입니다. 클래스에서 상속된 모든 공개 메소드 PcapHelperForIpv4
이 단일 장치 종속 구현 방법을 호출하는 것으로 줄입니다. 예를 들어,
가장 낮은 수준의 pcap 방법:

void EnablePcapIpv4(std::string 접두사, Ptr ipv4, uint4_t 인터페이스);

다음의 장치 구현을 호출합니다. PcapIpv4내부 활성화 곧장. 기타 모든 공개
pcap 추적 방법은 이 구현을 기반으로 구축되어 추가 사용자 수준을 제공합니다.
기능. 이것이 사용자에게 의미하는 바는 시스템의 모든 프로토콜 도우미가
모든 pcap 추적 방법을 사용할 수 있어야 합니다. 이 방법은 모두 동일하게 작동합니다.
도우미가 구현하는 경우 프로토콜 전반에 걸쳐 PcapIpv4내부 활성화 바르게.

피캡 트레이싱 프로토콜 돕는 사람 행동 양식
이러한 방법은 다음과 일대일로 대응되도록 설계되었습니다. 노드- 그리고
NetDevice- 장치 버전의 중심 버전입니다. 대신에 노드 and NetDevice
제약 조건, 우리는 프로토콜 및 인터페이스 제약 조건을 사용합니다.

장치 버전과 마찬가지로 XNUMX가지 방법이 있습니다.

void EnablePcapIpv4(std::string 접두사, Ptr ipv4, uint4_t 인터페이스);
void EnablePcapIpv4(std::string 접두사, std::string ipv4Name, uint32_t 인터페이스);
void EnablePcapIpv4(std::string 접두사, Ipv4InterfaceContainer c);
void EnablePcapIpv4(std::string 접두사, NodeContainer n);
void EnablePcapIpv4(std::string 접두사, uint32_t nodeid, uint32_t 인터페이스);
void EnablePcapIpv4All (std::string 접두사);

수업을 위해 Doxygen을 정독하는 것이 좋습니다 PcapHelperForIpv4 세부 사항을 찾으려면
이러한 방법 중; 하지만 요약하자면 ...

다음을 제공하여 특정 프로토콜/인터페이스 쌍에서 pcap 추적을 활성화할 수 있습니다.
포인트 and 인터페이스Pcap 활성화 방법. 예를 들어,:

포인트 ipv4 = 노드->GetObject ();
...
helper.EnablePcapIpv4("접두사", ipv4, 0);

다음을 제공하여 특정 노드/네트 장치 쌍에서 pcap 추적을 활성화할 수 있습니다.
표준::문자열 객체 이름 서비스 문자열을 Pcap 활성화 방법. 그만큼
포인트 이름 문자열에서 조회됩니다. 예를 들어,:

이름::추가("serverIPv4" ...);
...
helper.EnablePcapIpv4("접두사", "serverIpv4", 1);

다음을 제공하여 프로토콜/인터페이스 쌍 모음에서 pcap 추적을 활성화할 수 있습니다.
IPv4인터페이스 컨테이너. 각각 IPv4 / 컨테이너의 인터페이스 쌍 프로토콜 유형
확인됩니다. 적절한 유형(에 의해 관리되는 것과 동일한 유형)의 각 프로토콜에 대해
장치 도우미), 해당 인터페이스에 대한 추적이 활성화됩니다. 예를 들어,:

NodeContainer 노드;
...
NetDeviceContainer 장치 = deviceHelper.Install(노드);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer 인터페이스 = ipv4.Assign(장치);
...
helper.EnablePcapIpv4("접두사", 인터페이스);

다음을 제공하여 프로토콜/인터페이스 쌍 모음에서 pcap 추적을 활성화할 수 있습니다.
노드컨테이너. 각각 노드 인간을 노드컨테이너 적절한 프로토콜을 찾았습니다. 을 위한
각 프로토콜의 인터페이스가 열거되고 결과에 대한 추적이 활성화됩니다.
한 쌍. 예를 들어,:

NodeContainern;
...
helper.EnablePcapIpv4("접두사", n);

노드 ID와 인터페이스를 기반으로 pcap 추적을 활성화할 수도 있습니다. 이 경우,
node-id는 다음으로 변환됩니다. Ptr 그리고 적절한 프로토콜은
마디. 결과 프로토콜과 인터페이스는 결과 추적을 지정하는 데 사용됩니다.
원천.:

helper.EnablePcapIpv4("접두사", 21, 1);

마지막으로 시스템의 모든 인터페이스에 대해 pcap 추적을 활성화할 수 있습니다.
프로토콜은 장치 도우미가 관리하는 것과 동일한 유형입니다.:

helper.EnablePcapIpv4All("접두사");

피캡 트레이싱 프로토콜 돕는 사람 파일 이름 선택
위의 모든 메소드 설명에는 완전한 메소드 구성이 암시되어 있습니다.
구현 방법에 따른 파일 이름. 관례적으로, 다음 장치에 대해 수행된 pcap 추적은
전에, NS-3 시스템은 다음과 같은 형태입니다. - 아이디>- 아이디>.pcap. 의 경우
프로토콜 추적에서는 프로토콜과 프로토콜 사이에 일대일 대응이 있습니다. 노드. 이것은
왜냐하면 프로토콜 사물 로 집계됩니다. 노드 사물. 글로벌 프로토콜이 없기 때문에
시스템에서 id를 사용하면 파일 이름 지정에 해당 노드 ID를 사용합니다. 그러므로
자동으로 선택된 추적 파일 이름에서 파일 이름 충돌 가능성. 이를 위해
따라서 프로토콜 추적에 대한 파일 이름 규칙이 변경되었습니다.

앞서 언급했듯이 시스템의 모든 노드에는 시스템이 할당한 노드 ID가 있습니다.
프로토콜 인스턴스와 노드 인스턴스 사이에는 일대일 대응이 있으므로
우리는 노드 ID를 사용합니다. 각 인터페이스에는 해당 프로토콜과 관련된 인터페이스 ID가 있습니다. 우리는 사용
대회 " -N -나 추적 파일 이름 지정을 위한 .pcap"
프로토콜 도우미.

따라서 기본적으로 pcap 추적 파일은 추적 활성화 결과로 생성됩니다.
접두사 "prefix"를 사용하는 노드 1의 Ipv4 프로토콜 인터페이스 21은 다음과 같습니다.
"접두사-n21-i1.pcap".

항상 사용할 수 있습니다 NS-3 이것을 더 명확하게 하기 위해 객체 이름 서비스. 예를 들어,
개체 이름 서비스를 사용하여 "serverIpv4"라는 이름을 Ptr에 할당합니다. 노드에서
21, 결과 pcap 추적 파일 이름은 자동으로 다음과 같습니다.
"prefix-nserverIpv4-i1.pcap".

아스키 트레이싱 프로토콜 도우미
ASCII 추적 도우미의 동작은 pcap의 경우와 실질적으로 유사합니다. 받아
보고 src/네트워크/helper/trace-helper.h 동안 토론을 따르고 싶다면
실제 코드를 보면

이 섹션에서는 프로토콜에 적용되는 방법을 설명합니다. IPv4. 에
유사한 프로토콜로 추적을 지정하려면 적절한 유형으로 대체하면 됩니다. 예를 들어,
~을 사용하다 포인트 대신에 포인트 전화 AsciiIpv6 활성화 대신
AsciiIpv4 활성화.

클래스 AsciiTraceHelperForIpv4 ASCII 사용을 위한 고급 기능을 추가합니다.
프로토콜 도우미를 추적합니다. 이러한 메서드를 활성화하는 각 프로토콜은 다음을 구현해야 합니다.
이 클래스에서 상속된 단일 가상 메서드:

가상 무효 EnableAsciiIpv4Internal(Ptr 스트림, std::string 접두사,
포인트 ipv4, uint4_t 인터페이스) = 32;

이 메소드의 서명은 프로토콜 및 인터페이스 중심의 관점을 반영합니다.
이 수준의 상황; 또한 헬퍼가 공유된
출력 스트림. 클래스에서 상속된 모든 공개 메소드
PcapAndAsciiTraceHelperForIpv4 이 단일 장치 종속 호출로 줄입니다.
구현 방법. 예를 들어, 가장 낮은 수준의 ASCII 추적 방법은 다음과 같습니다.

void EnableAsciiIpv4(std::string 접두사, Ptr ipv4, uint4_t 인터페이스);
무효 EnableAsciiIpv4(Ptr 스트림, PTR ipv4, uint4_t 인터페이스);

다음의 장치 구현을 호출합니다. AsciiIpv4내부 활성화 직접 제공하거나
접두사 또는 스트림. 다른 모든 공개 ASCII 추적 방법은 이를 기반으로 구축됩니다.
추가 사용자 수준 기능을 제공하는 하위 수준 기능입니다. 이것이 무엇을 의미하는가?
사용자는 시스템의 모든 장치 도우미가 모든 ASCII 추적 방법을 갖게 된다는 것입니다.
사용 가능; 이러한 방법은 다음과 같은 경우 프로토콜 전체에서 모두 동일한 방식으로 작동합니다.
프로토콜 구현 EnablAsciiIpv4내부 바르게.

아스키 트레이싱 장치 돕는 사람 행동 양식
void EnableAsciiIpv4(std::string 접두사, Ptr ipv4, uint4_t 인터페이스);
무효 EnableAsciiIpv4(Ptr 스트림, PTR ipv4, uint4_t 인터페이스);

void EnableAsciiIpv4(std::string 접두사, std::string ipv4Name, uint32_t 인터페이스);
무효 EnableAsciiIpv4(Ptr 스트림, std::string ipv4Name, uint32_t 인터페이스);

void EnableAsciiIpv4(std::string 접두사, Ipv4InterfaceContainer c);
무효 EnableAsciiIpv4(Ptr 스트림, Ipv4InterfaceContainer c);

void EnableAsciiIpv4(std::string 접두사, NodeContainer n);
무효 EnableAsciiIpv4(Ptr 스트림, NodeContainer n);

void EnableAsciiIpv4(std::string 접두사, uint32_t nodeid, uint32_t deviceid);
무효 EnableAsciiIpv4(Ptr 스트림, uint32_t nodeid, uint32_t 인터페이스);

void EnableAsciiIpv4All(std::string 접두사);
무효화 EnableAsciiIpv4All(Ptr 개울);

수업을 위해 Doxygen을 정독하는 것이 좋습니다 PcapAndAsciiHelperForIpv4 를 찾는 방법
이러한 방법의 세부사항; 하지만 요약하자면 ...

pcap에 비해 ASCII 추적에 사용할 수 있는 방법이 두 배나 많습니다.
트레이싱. 이는 pcap 스타일 모델 외에도 각 항목의 추적이 이루어지기 때문입니다.
고유한 프로토콜/인터페이스 쌍이 고유한 파일에 기록되면 다음과 같은 모델을 지원합니다.
많은 프로토콜/인터페이스 쌍에 대한 추적 정보가 공통 파일에 기록됩니다. 이것
의미하는 것은 -N - 파일 이름 생성 메커니즘이 대체되었습니다.
공통 파일을 참조하는 메커니즘을 통해; API 메서드 수가 두 배로 늘어납니다.
모든 조합을 허용합니다.

pcap 추적과 마찬가지로 특정 프로토콜/인터페이스에서 ASCII 추적을 활성화할 수 있습니다.
제공하여 쌍 포인트인터페이스Ascii 활성화 방법. 예를 들어,:

Ptr IPv4;
...
helper.EnableAsciiIpv4("접두사", ipv4, 1);

이 경우 추적 컨텍스트는 ASCII 추적 파일에 기록되지 않습니다.
불필요한. 시스템은 다음과 동일한 규칙을 사용하여 생성할 파일 이름을 선택합니다.
파일에 ".tr"이라는 접미사가 붙는다는 점을 제외하고는 pcap 섹션에 설명되어 있습니다.
".pcap".

둘 이상의 인터페이스에서 ASCII 추적을 활성화하고 모든 추적을
단일 파일인 경우 개체를 사용하여 단일 파일을 참조하면 그렇게 할 수도 있습니다. 우리
위의 "cwnd" 예제에는 이미 이와 유사한 내용이 있습니다.

Ptr 프로토콜4 = node1->GetObject ();
Ptr 프로토콜4 = node2->GetObject ();
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAsciiIpv4(스트림, 프로토콜1, 1);
helper.EnableAsciiIpv4(스트림, 프로토콜2, 1);

이 경우 추적 컨텍스트는 필수이므로 ASCII 추적 파일에 기록됩니다.
두 인터페이스의 추적을 명확하게 합니다. 사용자가 완전히
파일 이름을 지정하는 경우 일관성을 위해 문자열에 ".tr"이 포함되어야 합니다.

다음을 제공하여 특정 프로토콜에서 ASCII 추적을 활성화할 수 있습니다. 표준::문자열
객체 이름 서비스 문자열을 Pcap 활성화 방법. 그만큼 포인트 is
이름 문자열에서 찾아보았습니다. 그만큼 결과 파일 이름에는 암시적입니다.
프로토콜 인스턴스와 노드 사이에는 일대일 대응이 있습니다. 예를 들면 다음과 같습니다.

이름::추가("node1Ipv4" ...);
이름::추가("node2Ipv4" ...);
...
helper.EnableAsciiIpv4("접두사", "node1Ipv4", 1);
helper.EnableAsciiIpv4("접두사", "node2Ipv4", 1);

그러면 "prefix-nnode1Ipv4-i1.tr"이라는 두 개의 파일이 생성되고
해당 추적 파일의 각 인터페이스에 대한 추적이 포함된 "prefix-nnode2Ipv4-i1.tr"입니다.
모든 EnableAscii 함수는 스트림 래퍼를 사용하도록 오버로드되므로 다음을 수행할 수 있습니다.
해당 형식도 사용하십시오.

이름::추가("node1Ipv4" ...);
이름::추가("node2Ipv4" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAsciiIpv4(스트림, "node1Ipv4", 1);
helper.EnableAsciiIpv4(스트림, "node2Ipv4", 1);

그러면 다음을 모두 포함하는 "trace-file-name.tr"이라는 단일 추적 파일이 생성됩니다.
두 인터페이스 모두에 대한 추적 이벤트. 이벤트는 추적 컨텍스트에 의해 명확해집니다.
문자열.

다음을 제공하여 프로토콜/인터페이스 쌍 모음에 대해 ASCII 추적을 활성화할 수 있습니다.
IPv4인터페이스 컨테이너. 적절한 유형의 각 프로토콜에 대해(관리되는 것과 동일한 유형
장치 도우미에 의해) 해당 인터페이스에 대한 추적이 활성화됩니다. 다시 말하지만,
각 프로토콜과 프로토콜 사이에는 일대일 대응이 있기 때문에 암시적입니다.
그 노드. 예를 들어,:

NodeContainer 노드;
...
NetDeviceContainer 장치 = deviceHelper.Install(노드);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer 인터페이스 = ipv4.Assign(장치);
...
...
helper.EnableAsciiIpv4("접두사", 인터페이스);

이로 인해 다수의 ASCII 추적 파일이 생성되며 각 파일은 다음과 같습니다.
그만큼 -N -나 .tr 규칙. 모든 흔적을 하나로 결합
단일 파일은 위의 예와 유사하게 수행됩니다.

NodeContainer 노드;
...
NetDeviceContainer 장치 = deviceHelper.Install(노드);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer 인터페이스 = ipv4.Assign(장치);
...
Ptr stream = asciiTraceHelper.CreateFileStream("trace-file-name.tr");
...
helper.EnableAsciiIpv4(스트림, 인터페이스);

다음을 제공하여 프로토콜/인터페이스 쌍 모음에 대해 ASCII 추적을 활성화할 수 있습니다.
노드컨테이너. 각각 노드 인간을 노드컨테이너 적절한 프로토콜을 찾았습니다. 을 위한
각 프로토콜의 인터페이스가 열거되고 결과에 대한 추적이 활성화됩니다.
한 쌍. 예를 들어,:

NodeContainern;
...
helper.EnableAsciiIpv4("접두사", n);

이로 인해 다수의 ASCII 추적 파일이 생성되며 각 파일은 다음과 같습니다.
그만큼 - - .tr 규칙. 모든 흔적을 하나로 결합
단일 파일은 위의 예와 유사하게 수행됩니다.

노드 ID와 장치 ID를 기반으로 pcap 추적을 활성화할 수도 있습니다. 이 경우,
node-id는 다음으로 변환됩니다. Ptr 그리고 적절한 프로토콜은
마디. 결과 프로토콜과 인터페이스는 결과 추적을 지정하는 데 사용됩니다.
원천.:

helper.EnableAsciiIpv4 ("접두사", 21, 1);

물론, 위와 같이 추적을 단일 파일로 결합할 수 있습니다.

마지막으로 시스템의 모든 인터페이스에 대해 ASCII 추적을 활성화할 수 있습니다.
프로토콜은 장치 도우미가 관리하는 것과 동일한 유형입니다.:

helper.EnableAsciiIpv4All("접두사");

이로 인해 모든 인터페이스마다 하나씩 여러 ASCII 추적 파일이 생성됩니다.
헬퍼가 관리하는 유형의 프로토콜과 관련된 시스템에서. 이 모든 파일
따라갈 것이다 -N -나
단일 파일로의 작업은 위의 예와 유사하게 수행됩니다.

아스키 트레이싱 장치 돕는 사람 파일 이름 선택
위의 접두사 스타일 메서드 설명에 암시된 것은 완전한 구성입니다.
구현 방법에 따른 파일 이름. 관례적으로 ASCII는 NS-3 시스템은
" 형식의 - - .tr."

앞서 언급했듯이 시스템의 모든 노드에는 시스템이 할당한 노드 ID가 있습니다.
프로토콜과 노드 사이에 일대일 대응이 있기 때문에 node-id에 사용합니다.
프로토콜 ID를 식별합니다. 특정 프로토콜의 모든 인터페이스에는
해당 프로토콜과 관련된 인터페이스 인덱스(단순히 인터페이스라고도 함)입니다. 기본적으로,
그런 다음 첫 번째 장치에서 추적을 활성화한 결과로 생성된 ASCII 추적 파일
접두사 "prefix"를 사용하는 노드 21은 "prefix-n21-i1.tr"이 됩니다. 접두사를 사용하여
노드당 여러 프로토콜을 명확하게 합니다.

항상 사용할 수 있습니다 NS-3 이것을 더 명확하게 하기 위해 객체 이름 서비스. 예를 들어,
객체 이름 서비스를 사용하여 노드의 프로토콜에 "serverIpv4"라는 이름을 할당합니다.
21, 인터페이스 XNUMX도 지정하면 결과 ASCII 추적 파일 이름이 자동으로 지정됩니다.
"prefix-nserverIpv4-1.tr"이 됩니다.

트레이싱 이행 세부설명
Data 수집
이 장에서는 다음을 제공하는 ns-3 데이터 수집 프레임워크(DCF)에 대해 설명합니다.
시뮬레이터에서 모델에 의해 생성된 데이터를 얻고 온라인으로 수행하는 기능
축소 및 데이터 처리, 원시 또는 변환된 데이터를 다양한 출력으로 마샬링
형식.

프레임워크는 현재 외부에 의존하지 않는 독립형 ns-3 실행을 지원합니다.
프로그램 실행 제어. DCF에서 제공하는 객체는 다음에 연결될 수 있습니다. NS-3 더듬다
데이터 처리를 가능하게 하는 소스.

클래스의 소스 코드는 디렉토리에 있습니다. 소스/통계.

이 장은 다음과 같이 구성되어 있습니다. 먼저, 아키텍처 개요는 다음과 같습니다.
제시. 다음으로 이러한 클래스에 대한 도우미가 제공됩니다. 이 초기 치료
많은 사용 사례에 대해 데이터 수집 프레임워크의 기본 사용을 허용해야 합니다. 사용자
현재 도우미의 범위를 벗어나는 출력을 생성하려는 경우 또는 생성하려는 경우
자신의 데이터 수집 객체에 대해서는 이 장의 나머지 부분을 읽어야 합니다.
모든 기본 DCF 객체 유형에 대해 자세히 설명하고 낮은 수준의 코딩을 제공합니다.
예.

디자인
DCF는 세 가지 기본 클래스로 구성됩니다.

· 탐침 시뮬레이션 데이터의 출력을 계측하고 제어하는 ​​메커니즘입니다.
흥미로운 이벤트를 모니터링하는 데 사용됩니다. 하나 이상의 형태로 출력을 생성합니다. NS-3
추적 소스. 프로브 개체는 하나 이상의 추적에 연결됩니다. 싱크 (
수집가), 온라인으로 샘플을 처리하고 출력을 준비합니다.

· 수집가 하나 이상의 프로브 개체에서 생성된 데이터를 사용합니다. 수행합니다
정규화, 축소 및 계산과 같은 데이터 변환
기본 통계. Collector 개체는 직접 출력되는 데이터를 생성하지 않습니다.
ns-3 실행; 대신 데이터 다운스트림을 다른 유형의 객체로 출력합니다.
애그리 게이터 (aggregator), 해당 기능을 수행합니다. 일반적으로 수집기는 데이터를 다음 형식으로 출력합니다.
추적 소스의 형태도 가능하므로 수집기를 직렬로 연결할 수 있습니다.

· 애그리 게이터 (aggregator) 프로브 및 수집기 네트워크에 의해 수집된 데이터의 종점입니다.
Aggregator의 주요 책임은 데이터와 해당 데이터를 정리하는 것입니다.
메타데이터를 일반 텍스트 파일, 스프레드시트 파일과 같은 다양한 출력 형식으로 변환
데이터베이스.

이 세 클래스 모두 동적으로 스스로 켜거나 끄는 기능을 제공합니다.
시뮬레이션 내내.

모든 독립형 NS-3 DCF를 사용하는 시뮬레이션 실행은 일반적으로 하나 이상의
위의 세 클래스 각각의 인스턴스입니다.
[이미지] 데이터 수집 프레임워크 개요.UNINDENT

데이터 처리의 전반적인 흐름은 다음과 같습니다. Data 수집 뼈대 개요.
왼쪽에는 달리기 NS-3 시뮬레이션이 그려져 있습니다. 운영하는 과정에서
시뮬레이션을 통해 데이터는 추적 소스나 기타 수단을 통해 모델에서 사용할 수 있게 됩니다.
다이어그램은 프로브가 이러한 추적 소스에 연결되어 데이터를 수신할 수 있음을 보여줍니다.
비동기적으로 또는 프로브가 데이터를 폴링할 수 있습니다. 그런 다음 데이터는 수집기 개체로 전달됩니다.
데이터를 변환하는 것입니다. 마지막으로 집계자는 다음의 출력에 연결될 수 있습니다.
수집기, 플롯, 파일 또는 데이터베이스를 생성합니다.
[이미지] 데이터 수집 프레임워크 집계.UNINDENT

위 그림의 변형이 제공됩니다. Data 수집 뼈대 집합.
이 두 번째 그림은 DCF 개체가 다음과 같은 방식으로 함께 연결될 수 있음을 보여줍니다.
다운스트림 객체는 여러 업스트림 객체로부터 입력을 받습니다. 그림
여러 프로브가 단일 프로브에 공급되는 출력을 생성할 수 있음을 개념적으로 보여줍니다.
수집기; 예를 들어, 두 카운터의 비율을 출력하는 컬렉터는
일반적으로 별도의 프로브에서 각 카운터 데이터를 수집합니다. 여러 수집가도 가능
(이름에서 알 수 있듯이) 다수의 데이터를 수집할 수 있는 단일 수집기에 공급됩니다.
단일 플롯, 파일 또는 데이터베이스에 포함할 스트림입니다.

Data 수집 도우미
데이터 수집 프레임워크의 완전한 유연성은 상호 연결을 통해 제공됩니다.
프로브, 수집기 및 수집기. 이러한 모든 상호 연결을 수행하면
사용자 프로그램의 많은 구성 명령문. 사용 편의성을 위해 가장 일반적인 몇 가지
작업은 도우미 함수로 결합되고 캡슐화될 수 있습니다. 또한 일부
관련된 진술 NS-3 추적 소스에는 Python 바인딩이 없습니다.
바인딩.

Data 수집 도우미 살펴보기
이 섹션에서는 다음을 위해 생성된 일부 도우미 클래스에 대한 개요를 제공합니다.
일부 일반적인 사용 사례에 대한 데이터 수집 프레임워크 구성을 쉽게 합니다. 그만큼
도우미를 사용하면 사용자는 C++ 또는 몇 가지 명령문만으로 일반적인 작업을 수행할 수 있습니다.
파이썬 프로그램. 그러나 이러한 사용 편의성은 훨씬 더 적은 비용으로 발생합니다.
낮은 수준 구성이 제공할 수 있는 유연성과 명시적인 코딩 필요성
도우미에 새로운 프로브 유형을 지원합니다(아래 설명된 문제를 해결하기 위해).

현재 도우미에 중점을 두는 것은 데이터를 정리하는 것입니다. NS-3 소스를 추적하다
높은 수준의 출력 사용자 정의나 통계가 없는 gnuplot 플롯 또는 텍스트 파일
처리(초기). 또한 사용 가능한 프로브 유형에 따라 사용이 제한됩니다.
NS-3. 이 문서의 뒷부분에서는 새 항목을 만드는 방법에 대해 자세히 설명합니다.
프로브 유형 및 프로브, 수집기, 수집기 연결에 대한 세부 정보
맞춤식 배열로.

현재까지 두 가지 데이터 수집 도우미가 구현되었습니다.

· Gnuplot도우미

· 파일헬퍼

Gnuplot도우미
GnuplotHelper는 gnuplot을 만드는 데 사용되는 출력 파일을 생성하기 위한 도우미 클래스입니다. 그만큼
전반적인 목표는 사용자가 내보낸 데이터에서 신속하게 플롯을 만들 수 있는 기능을 제공하는 것입니다.
in NS-3 추적 소스. 기본적으로 최소한의 데이터 변환이 수행됩니다.
목표는 다음과 같이 최소한의 (기본) 구성 명령문을 사용하여 플롯을 생성하는 것입니다.
수.

Gnuplot도우미 살펴보기
GnuplotHelper는 시뮬레이션이 끝나면 3개의 다른 파일을 생성합니다.

· 공백으로 구분된 gnuplot 데이터 파일

· gnuplot 제어 파일

· gnuplot을 생성하는 쉘 스크립트

플롯을 생성하는 데 필요한 두 가지 구성 명령문이 있습니다. 첫번째
명령문은 플롯(파일 이름, 제목, 범례 및 출력 유형을 구성합니다. 여기서 출력은
지정되지 않은 경우 유형은 기본적으로 PNG로 설정됨):

void ConfigurePlot(const std::string &outputFileNameWithoutExtension,
const 표준::문자열 &제목,
const std::string &xLegend,
const std::string &yLegend,
const std::string &terminalType = ".png");

두 번째 문은 관심 있는 추적 소스를 연결합니다.

void PlotProbe(const std::string &typeId,
const std::string &경로,
const std::string &probeTraceSource,
const std::string &제목);

인수는 다음과 같습니다.

· typeId: NS-3 프로브의 TypeId

· 경로: 경로 NS-3 하나 이상의 추적 소스에 대한 구성 네임스페이스

·probeTraceSource: 프로브(그 자체가 추적 소스)의 출력을 표시해야 합니다.

· 제목: 데이터세트와 연결할 제목(gnuplot 범례에 있음)

위 PlotProbe의 변형은 제어하는 ​​다섯 번째 선택적 인수를 지정하는 것입니다.
플롯에서 키(범례)가 배치되는 위치입니다.

완전히 작동된 예제( 일곱번째.cc)은 아래와 같습니다.

// gnuplot 도우미를 만듭니다.
GnuplotHelper 플롯헬퍼;

// 플롯을 구성합니다.
// 플롯을 구성합니다. 첫 번째 인수는 파일 이름 접두사입니다.
// 생성된 출력 파일의 경우. 두 번째, 세 번째, 네 번째
// 인수는 각각 플롯 제목, x축, y축 레이블입니다.
plotHelper.ConfigurePlot("XNUMX번째 패킷 바이트 수",
"패킷 바이트 수 대 시간",
"시간(초)",
"패킷 바이트 수",
"png");

// 프로브 유형, 추적 소스 경로(구성 네임스페이스에서) 및
// 출력 추적 소스("OutputBytes")를 조사하여 플롯합니다. 네 번째 주장
// 플롯의 데이터 시리즈 레이블 이름을 지정합니다. 마지막
// 인수는 키가 배치되어야 하는 위치를 지정하여 플롯의 형식을 지정합니다.
plotHelper.PlotProbe(프로브 유형,
추적 경로,
"출력바이트",
"패킷 바이트 수",
GnuplotAggregator::KEY_BELOW);

이 예에서 프로브 유형 and 추적 경로 다음과 같습니다(IPv4의 경우).

프로브 유형 = "ns3::Ipv4PacketProbe";
TracePath = "/NodeList/*/$ns3::Ipv4L3Protocol/Tx";

프로브 유형은 이 도우미가 작동하는 데 필요한 핵심 매개변수입니다. 이 TypeId를 등록해야 합니다.
시스템에 있으며 프로브 추적 싱크의 서명은 추적의 서명과 일치해야 합니다.
소스에 연결되어 있습니다. 다양한 데이터 유형에 대해 프로브 유형이 사전 정의되어 있습니다.
에 해당하는 NS-3 추적된 값 및 다음과 같은 몇 가지 다른 추적 소스 서명의 경우
'Tx' 추적 소스 ns3::Ipv4L3프로토콜 클래스입니다.

지정된 추적 소스 경로에는 와일드카드가 포함될 수 있습니다. 이 경우 여러
데이터 세트는 하나의 플롯에 표시됩니다. 일치하는 각 경로마다 하나씩.

생성되는 기본 출력은 다음 세 가지 파일입니다.

일곱 번째-패킷-바이트-count.dat
일곱 번째 패킷 바이트 수.plt
일곱 번째-패킷-바이트-count.sh

이 시점에서 사용자는 추가 사용자 정의를 위해 .plt 파일을 직접 편집하거나
그냥 gnuplot을 통해 실행해 보세요. 달리기 sh 일곱 번째-패킷-바이트-count.sh 단순히 줄거리를 실행
아래와 같이 gnuplot을 통해.
[이미지] 일곱번째.cc 예제로 생성된 2-D Gnuplot 예제..UNINDENT

핵심 요소(범례, 제목, 범례 배치, xlabel, ylabel,
및 데이터 경로)는 모두 플롯에 배치됩니다. 두 경기가 있었기 때문에
구성 경로가 제공되면 두 개의 데이터 시리즈가 표시됩니다.

· 패킷 바이트 수-0은 /NodeList/0/$ns3::Ipv4L3Protocol/Tx에 해당합니다.

· 패킷 바이트 수-1은 /NodeList/1/$ns3::Ipv4L3Protocol/Tx에 해당합니다.

Gnuplot도우미 플롯 구성
GnuplotHelper의 구성플롯() 기능을 사용하여 플롯을 구성할 수 있습니다.

다음과 같은 프로토타입이 있습니다.

void ConfigurePlot(const std::string &outputFileNameWithoutExtension,
const 표준::문자열 &제목,
const std::string &xLegend,
const std::string &yLegend,
const std::string &terminalType = ".png");

여기에는 다음과 같은 인수가 있습니다.

┌───────────────────────────────┬───────────────── ─────────────────┐
│인수 │ 설명 │
├───────────────────────────────┼───────────────── ─────────────────┤
│outputFileNameWithoutExtension │ gnuplot 관련 파일 이름 │
│ │ 확장자 없이 씁니다. │
├───────────────────────────────┼───────────────── ─────────────────┤
│title │ │에 사용할 플롯 제목 문자열
│ │ 이 줄거리. │
├───────────────────────────────┼───────────────── ─────────────────┤
│xLegend │ x 가로 범례 │
│ │ 축. │
├───────────────────────────────┼───────────────── ─────────────────┤
│yLegend │ y 수직에 대한 범례 │
│ │ 축. │
└───────────────────────────────┴───────────────── ─────────────────┘

│terminalType │ │에 대한 터미널 유형 설정 문자열
│ │ 출력. 기본 터미널 │
│ │ 유형은 "png"입니다. │
└───────────────────────────────┴───────────────── ─────────────────┘

GnuplotHelper의 구성플롯() 함수는 이에 대한 플롯 관련 매개변수를 구성합니다.
gnuplot 도우미는 공백으로 구분된 gnuplot 데이터 파일을 생성합니다.
outputFileNameWithoutExtension + ".dat", 이름이 지정된 gnuplot 제어 파일
outputFileNameWithoutExtension + ".plt" 및 이름이 지정된 gnuplot을 생성하는 쉘 스크립트
outputFileNameWithoutExtension + ".sh".

이 기능을 사용하는 방법의 예는 다음에서 볼 수 있습니다. 일곱번째.cc 위에서 설명한 코드
여기서는 다음과 같이 사용되었습니다.

plotHelper.ConfigurePlot("XNUMX번째 패킷 바이트 수",
"패킷 바이트 수 대 시간",
"시간(초)",
"패킷 바이트 수",
"png");

Gnuplot도우미 플롯프로브
GnuplotHelper의 플롯프로브() 함수를 사용하여 프로브에서 생성된 값을 플롯할 수 있습니다.

다음과 같은 프로토타입이 있습니다.

void PlotProbe(const std::string &typeId,
const std::string &경로,
const std::string &probeTraceSource,
const 표준::문자열 &제목,
enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE);

여기에는 다음과 같은 인수가 있습니다.

┌─────────────────┬────────────────────────────── ───┐
│인수 │ 설명 │
├─────────────────┼────────────────────────────── ───┤
│typeId │ 프로브의 유형 ID │
│ │ 이 도우미가 생성했습니다. │
├─────────────────┼────────────────────────────── ───┤
│path │ 추적에 액세스하기 위한 구성 경로 │
│ │ 출처. │
├─────────────────┼────────────────────────────── ───┤
│probeTraceSource │ 프로브 추적 소스 │
│ │ 접속. │
├─────────────────┼────────────────────────────── ───┤
│title │ │에 연결될 제목
│ │ 이 데이터세트 │
├─────────────────┼────────────────────────────── ───┤
│keyLocation │ │에 있는 키의 위치
│ │ 플롯. 기본 위치는 │입니다.
│ │ 내부. │
└─────────────────┴────────────────────────────── ───┘

GnuplotHelper의 플롯프로브() 함수는 다음을 연결하여 생성된 데이터 세트를 플롯합니다. NS-3
도우미가 만든 프로브를 사용하여 소스를 추적한 다음
프로브TraceSource. 데이터 세트는 제공된 제목을 가지며 다음으로 구성됩니다.
각 타임스탬프에 'newValue'가 있습니다.

와일드카드가 있기 때문에 구성 경로에 시스템 내 일치 항목이 두 개 이상 있는 경우
각 일치 항목에 대해 하나의 데이터세트가 표시됩니다. 데이터 세트 제목에는
구성 경로의 각 와일드카드에 대해 일치하는 문자를 공백으로 구분합니다. 을 위한
예를 들어, 제안된 데이터세트 제목이 "bytes" 문자열이고 와일드카드가 두 개 있는 경우
경로에서 "bytes-0 0" 또는 "bytes-12 9"와 같은 데이터 세트 제목은 다음과 같이 가능합니다.
플롯된 데이터세트의 레이블입니다.

이 기능을 사용하는 방법의 예는 다음에서 볼 수 있습니다. 일곱번째.cc 위에서 설명한 코드
다음과 같이 변수 대체와 함께 사용되었습니다.

plotHelper.PlotProbe("ns3::Ipv4PacketProbe",
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
"출력바이트",
"패킷 바이트 수",
GnuplotAggregator::KEY_BELOW);

기타
지플롯 돕는 사람 예시
좀 더 간단한 예는 다음과 같습니다. 일곱번째.cc 예는 다음에서 찾을 수 있습니다.
src/stats/examples/gnuplot-helper-example.cc. 다음 2D gnuplot은 다음을 사용하여 생성되었습니다.
예.
[이미지] gnuplot-helper-example.cc로 생성된 2D Gnuplot 예제..UNINDENT

이 예에는 다음과 같이 카운터를 증가시키는 Emitter 객체가 있습니다.
포아송 프로세스를 수행한 다음 카운터 값을 추적 소스로 내보냅니다.

포인트 이미터 = CreateObject ();
이름::추가("/이름/이미터", 이미터);

아래 사용된 경로에는 와일드카드가 없으므로 데이터 스트림은 1개만 사용되었습니다.
줄거리에 그려져 있습니다. 플롯의 이 단일 데이터 스트림은 단순히 "Emitter Count"라는 레이블이 지정되어 있습니다.
추가 접미사가 없으면 경로에 와일드카드가 있는지 확인할 수 있습니다.

// gnuplot 도우미를 만듭니다.
GnuplotHelper 플롯헬퍼;

// 플롯을 구성합니다.
plotHelper.ConfigurePlot("gnuplot-helper-예제",
"이미터 수 대 시간",
"시간(초)",
"이미터 수",
"png");

// 프로브에서 생성된 값을 플롯합니다. 우리가 제공하는 길
// 추적 소스를 명확하게 하는 데 도움이 됩니다.
plotHelper.PlotProbe("ns3::Uinteger32Probe",
"/이름/이미터/카운터",
"산출",
"이미터 수",
GnuplotAggregator::KEY_INSIDE);

파일헬퍼
FileHelper는 데이터 값을 파일에 저장하는 데 사용되는 도우미 클래스입니다. 전반적인 목표는
사용자가 내보낸 데이터에서 서식 있는 텍스트 파일을 빠르게 만들 수 있는 기능을 제공합니다.
in NS-3 추적 소스. 기본적으로 최소한의 데이터 변환이 수행됩니다.
목표는 다음과 같은 최소한의 (기본) 구성 명령문을 사용하여 파일을 생성하는 것입니다.
수.

파일헬퍼 살펴보기
FileHelper는 시뮬레이션이 끝나면 하나 이상의 텍스트 파일을 생성합니다.

FileHelper는 4가지 유형의 텍스트 파일을 생성할 수 있습니다.

· 포맷됨

· 공백으로 구분됨(기본값)

· 쉼표로 구분

· 탭 분리

형식화된 파일은 C 스타일 형식 문자열과 sprintf() 함수를 사용하여 파일을 인쇄합니다.
기록 중인 파일의 값입니다.

다음과 같은 텍스트 파일에는 2개의 형식화된 값 열이 있습니다.
일곱 번째-패킷-바이트-카운트-0.txt 에 추가된 더 많은 새로운 코드를 사용하여 생성되었습니다.
실물 NS-3 튜토리얼 예제의 코드입니다. 이 파일의 처음 10줄만 표시됩니다.
간략하게 설명하자면 여기입니다.

시간(초) = 1.000e+00 패킷 바이트 수 = 40
시간(초) = 1.004e+00 패킷 바이트 수 = 40
시간(초) = 1.004e+00 패킷 바이트 수 = 576
시간(초) = 1.009e+00 패킷 바이트 수 = 576
시간(초) = 1.009e+00 패킷 바이트 수 = 576
시간(초) = 1.015e+00 패킷 바이트 수 = 512
시간(초) = 1.017e+00 패킷 바이트 수 = 576
시간(초) = 1.017e+00 패킷 바이트 수 = 544
시간(초) = 1.025e+00 패킷 바이트 수 = 576
시간(초) = 1.025e+00 패킷 바이트 수 = 544

...

2개의 형식화된 값 열이 있는 다음과 같은 다른 텍스트 파일
일곱 번째-패킷-바이트-카운트-1.txt 또한 다음에 추가된 것과 동일한 새 코드를 사용하여 생성되었습니다.
원래 NS-3 튜토리얼 예제의 코드입니다. 이 파일의 처음 10줄만 표시됩니다.
간략하게 설명하자면 여기입니다.

시간(초) = 1.002e+00 패킷 바이트 수 = 40
시간(초) = 1.007e+00 패킷 바이트 수 = 40
시간(초) = 1.013e+00 패킷 바이트 수 = 40
시간(초) = 1.020e+00 패킷 바이트 수 = 40
시간(초) = 1.028e+00 패킷 바이트 수 = 40
시간(초) = 1.036e+00 패킷 바이트 수 = 40
시간(초) = 1.045e+00 패킷 바이트 수 = 40
시간(초) = 1.053e+00 패킷 바이트 수 = 40
시간(초) = 1.061e+00 패킷 바이트 수 = 40
시간(초) = 1.069e+00 패킷 바이트 수 = 40

...

두 개의 텍스트 파일을 생성하기 위해 추가된 새 코드는 다음과 같습니다. 에 대한 자세한 내용
이 API는 이후 섹션에서 다루겠습니다.

경로에 와일드카드와 일치하는 항목이 2개 있었기 때문에 2개의 별도 텍스트 파일이 생성되었습니다.
만들어졌습니다. "seventh-packet-byte-count-0.txt"라는 이름의 첫 번째 텍스트 파일은,
"*"가 "0"으로 대체된 와일드카드 일치에 해당합니다. 두 번째 텍스트 파일,
"seventh-packet-byte-count-1.txt"라는 이름은 다음과 같은 와일드카드 일치에 해당합니다.
"*"는 "1"로 대체됩니다. 또한 다음 함수 호출에 유의하세요. 쓰기프로브() 줄 것이다
와일드카드가 포함된 경로와 일치하는 항목이 없으면 오류 메시지가 나타납니다.

// 파일 도우미를 만듭니다.
FileHelper fileHelper;

// 쓸 파일을 구성합니다.
fileHelper.ConfigureFile("XNUMX번째-패킷-바이트-카운트",
FileAggregator::포맷됨);

// 이 형식화된 출력 파일에 대한 레이블을 설정합니다.
fileHelper.Set2dFormat("시간(초) = %.3e\t패킷 바이트 수 = %.0f");

// 프로브에서 생성된 값을 씁니다.
fileHelper.WriteProbe("ns3::Ipv4PacketProbe",
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
"출력바이트");

파일헬퍼 파일 구성
FileHelper의 구성파일() 기능을 사용하여 텍스트 파일을 구성할 수 있습니다.

다음과 같은 프로토타입이 있습니다.

무효 구성파일(const std::string &outputFileNameWithoutExtension,
enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED);

여기에는 다음과 같은 인수가 있습니다.

┌───────────────────────────────┬───────────────── ─────────────────┐
│인수 │ 설명 │
├───────────────────────────────┼───────────────── ─────────────────┤
│outputFileNameWithoutExtension │ 쓸 출력 파일 이름 │
│ │ 확장자가 없습니다. │
├───────────────────────────────┼───────────────── ─────────────────┤
│fileType │ 쓸 파일 유형입니다. │
│ │ 기본 파일 유형은 공백입니다. │
│ │ 분리되었습니다. │
└───────────────────────────────┴───────────────── ─────────────────┘

FileHelper의 구성파일() 함수는 텍스트 파일 관련 매개변수를 구성합니다.
파일 도우미를 사용하면 outputFileNameWithoutExtension이라는 파일을 생성하고
와일드카드 일치에서 가능한 추가 정보와 다음과 같이 인쇄된 값이 있는 ".txt"
fileType으로 지정됩니다. 기본 파일 형식은 공백으로 구분됩니다.

이 기능을 사용하는 방법의 예는 다음에서 볼 수 있습니다. 일곱번째.cc 위에서 설명한 코드
여기서는 다음과 같이 사용되었습니다.

fileHelper.ConfigureFile("XNUMX번째-패킷-바이트-카운트",
FileAggregator::포맷됨);

파일헬퍼 WriteProbe
FileHelper의 쓰기프로브() 함수를 사용하여 프로브에서 생성된 값을 쓸 수 있습니다.
텍스트 파일.

다음과 같은 프로토타입이 있습니다.

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

여기에는 다음과 같은 인수가 있습니다.

┌─────────────────┬────────────────────────────── ───┐
│인수 │ 설명 │
├─────────────────┼────────────────────────────── ───┤
│typeId │ 프로브의 유형 ID는 │입니다.
│ │ 생성되었습니다. │
├─────────────────┼────────────────────────────── ───┤
│path │ 추적에 액세스하기 위한 구성 경로 │
│ │ 출처. │
├─────────────────┼────────────────────────────── ───┤
│probeTraceSource │ 프로브 추적 소스 │
│ │ 접속. │
└─────────────────┴────────────────────────────── ───┘

FileHelper의 쓰기프로브() 함수는 다음을 연결하여 생성된 출력 텍스트 파일을 생성합니다.
도우미가 만든 프로브를 사용하여 ns-3 추적 소스를 만든 다음
프로브TraceSource. 출력 파일 이름에는 멤버 변수에 저장된 텍스트가 있습니다.
m_outputFileNameWithoutExtension과 ".txt"는 각각 'newValue'로 구성됩니다.
타임 스탬프.

와일드카드가 있기 때문에 구성 경로에 시스템 내 일치 항목이 두 개 이상 있는 경우
각 일치 항목에 대해 하나의 출력 파일이 생성됩니다. 출력 파일 이름에는
m_outputFileNameWithoutExtension의 텍스트와 각 항목에 대해 일치하는 문자
대시로 구분된 구성 경로의 와일드카드와 ".txt". 예를 들어, 값이
m_outputFileNameWithoutExtension에는 "packet-byte-count"라는 문자열이 있으며 두 개가 있습니다.
경로에 와일드카드를 추가한 다음 "packet-byte-count-0-0.txt"와 같은 파일 이름을 출력하거나
생성될 파일의 ​​이름으로 "packet-byte-count-12-9.txt"가 가능합니다.

이 기능을 사용하는 방법의 예는 다음에서 볼 수 있습니다. 일곱번째.cc 위에서 설명한 코드
여기서는 다음과 같이 사용되었습니다.

fileHelper.WriteProbe("ns3::Ipv4PacketProbe",
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
"출력바이트");

기타
입양 부모로서의 귀하의 적합성을 결정하기 위해 미국 이민국에 돕는 사람 예시
좀 더 간단한 예는 다음과 같습니다. 일곱번째.cc 예는 다음에서 찾을 수 있습니다.
src/stats/examples/file-helper-example.cc. 이 예에서는 FileHelper만 사용합니다.

다음과 같은 텍스트 파일에는 2개의 형식화된 값 열이 있습니다. 파일-도우미-example.txt
예제를 사용하여 만들어졌습니다. 여기에는 이 파일의 처음 10줄만 표시됩니다.
짧음.

시간(초) = 0.203 개수 = 1
시간(초) = 0.702 개수 = 2
시간(초) = 1.404 개수 = 3
시간(초) = 2.368 개수 = 4
시간(초) = 3.364 개수 = 5
시간(초) = 3.579 개수 = 6
시간(초) = 5.873 개수 = 7
시간(초) = 6.410 개수 = 8
시간(초) = 6.472 개수 = 9
...

이 예에는 다음과 같이 카운터를 증가시키는 Emitter 객체가 있습니다.
포아송 프로세스를 수행한 다음 카운터 값을 추적 소스로 내보냅니다.

포인트 이미터 = CreateObject ();
이름::추가("/이름/이미터", 이미터);

아래 사용된 경로에는 와일드카드가 없으므로 텍스트 파일이 1개만 표시됩니다.
만들어진. 이 단일 텍스트 파일은 추가 항목 없이 단순히 "file-helper-example.txt"라는 이름으로 지정됩니다.
경로에 와일드카드가 있는지 확인할 수 있는 접미사입니다.

// 파일 도우미를 만듭니다.
FileHelper fileHelper;

// 쓸 파일을 구성합니다.
fileHelper.ConfigureFile("파일-도우미-예제",
FileAggregator::포맷됨);

// 이 형식화된 출력 파일에 대한 레이블을 설정합니다.
fileHelper.Set2dFormat("시간(초) = %.3e\tCount = %.0f");

// 프로브에서 생성된 값을 씁니다. 우리가 가는 길
// 추적 소스를 명확하게 하는 데 도움이 됩니다.
fileHelper.WriteProbe("ns3::Uinteger32Probe",
"/이름/이미터/카운터",
"산출");

범위 and 제한 사항
현재 이러한 프로브만 구현되어 GnuplotHelper에 연결되어 있으며
FileHelper에:

· 부울 프로브

· 더블프로브

· Uinteger8Probe

· Uinteger16Probe

· Uinteger32Probe

· 타임프로브

· 패킷프로브

· ApplicationPacketProbe

· Ipv4PacketProbe

따라서 이러한 프로브는 다음에서 사용할 수 있는 유일한 TypeId입니다. 플롯프로브() and
쓰기프로브().

다음 몇 섹션에서는 기본 개체 유형(프로브, 수집기,
및 Aggregator)에 대해 더 자세히 설명하고 다음을 사용하여 어떻게 함께 연결할 수 있는지 보여줍니다.
하위 수준 API.

프로브
이 섹션에서는 Probe 클래스가 제공하는 기능에 대해 자세히 설명합니다. NS-3
시뮬레이션을 통해 이를 프로그램에서 코딩하는 방법에 대한 예제를 제공합니다. 이 섹션의 목적은 다음과 같습니다.
시뮬레이션 개발에 관심이 있는 사용자 NS-3 도구 및 데이터 사용
Probe 클래스가 포함된 컬렉션 프레임워크는 다음을 사용하여 데이터 출력을 생성합니다.
그들의 시뮬레이션 결과.

탐침 살펴보기
프로브 객체는 값이 있는 시뮬레이션의 변수에 연결되어야 합니다.
실험 전반에 걸쳐 사용자와 관련이 있습니다. 프로브는 무엇을 기록할지 기록합니다.
시뮬레이션 전반에 걸쳐 변수가 가정한 값을 입력하고 해당 데이터를 다른 변수에 전달합니다.
데이터 수집 프레임워크의 회원입니다. 이 섹션의 범위를 벗어나는 동안
프로브가 출력을 생성한 후 어떤 일이 발생하는지 논의하면 다음과 같이 말하는 것으로 충분합니다.
시뮬레이션이 끝나면 사용자는 어떤 값이 있었는지에 대한 자세한 정보를 갖게 됩니다.
시뮬레이션 중에 탐색되는 변수 내부에 저장됩니다.

일반적으로 프로브는 NS-3 추적 소스. 이런 식으로, 언제든지
추적 소스가 새 값을 내보내면 프로브는 값을 사용하고 다운스트림으로 내보냅니다.
자체 추적 소스를 통해 다른 개체로).

프로브는 추적 소스에 대한 일종의 필터로 생각할 수 있습니다. 주된 이유는
추적 소스에 직접 연결하는 대신 프로브에 연결하는 방법은 다음과 같습니다.

· 시뮬레이션 중에 다음 호출을 통해 프로브를 동적으로 켜고 끌 수 있습니다. 할 수 있게 하다()
and 장애를 입히다(). 예를 들어, 데이터 출력이 도중에 꺼질 수 있습니다.
시뮬레이션 준비 단계.

· 프로브는 데이터에 대한 작업을 수행하여 더 복잡한 데이터에서 값을 추출할 수 있습니다.
구조; 예를 들어, 수신된 ns3::Packet에서 패킷 크기 값을 출력합니다.

· 프로브는 ns3::Config 네임스페이스에 이름을 등록합니다(다음을 사용). 이름::추가 ()) 그래서 다른
객체는 이를 참조할 수 있습니다.

· 프로브는 이름으로 프로브를 조작할 수 있는 정적 방법을 제공합니다.
ns2measure에서 수행되는 작업 [Cic06]

Stat::put ("my_metric", ID, 샘플);

위의 ns3measure 코드에 해당하는 ns-2은 다음과 같습니다.

DoubleProbe::SetValueByPath("/path/to/probe", 샘플);

창조
Probe 기본 클래스 개체는 추상 기반이므로 생성할 수 없습니다.
즉, 구현되지 않은 순수 가상 함수가 있습니다. 의 대상
Probe 클래스의 하위 클래스인 DoubleProbe 유형이 여기에 생성되어 표시됩니다.
무엇을 해야 하는지.

스마트 포인터 클래스(Ptr)를 사용하여 동적 메모리에 DoubleProbe를 선언합니다. ). 에게
스마트 포인터를 사용하여 동적 메모리에 DoubleProbe를 생성하려면
NS-3 방법 객체 생성():

포인트 myprobe = CreateObject ();

위 선언은 해당 속성의 기본값을 사용하여 DoubleProbe를 생성합니다.
DoubleProbe 클래스에는 네 가지 특성이 있습니다. 기본 클래스 객체의 두 개
DataCollectionObject 및 Probe 기본 클래스의 두 개:

· "이름"(DataCollectionObject), StringValue

· "Enabled"(DataCollectionObject), BooleanValue

· TimeValue인 "Start"(프로브)

· "중지"(프로브), TimeValue

다음 방법을 사용하여 객체 생성 시 이러한 속성을 설정할 수 있습니다.

포인트 myprobe = CreateObjectWithAttributes (
"이름", StringValue("myprobe"),
"활성화됨", BooleanValue(false),
"시작", TimeValue(초(100.0)),
"중지", TimeValue(초(1000.0)));

시작 및 중지는 프로브의 작업 간격을 결정하는 시간 변수입니다. 그만큼
프로브는 시뮬레이션의 현재 시간이 해당 시간 내에 있는 경우에만 데이터를 출력합니다.
간격. 중지에 대한 특수 시간 값 0초는 이 속성을 비활성화합니다(예:
전체 시뮬레이션 동안 프로브를 켜두십시오). 활성화는 프로브를 켜거나 켜는 플래그입니다.
끄고 프로브가 데이터를 내보내려면 true로 설정해야 합니다. 이름은 개체의 이름입니다.
DCF 프레임워크에서.

가져 오기 and 내보내기 데이터
NS-3 추적 소스는 강력한 유형이므로 프로브를 추적에 연결하는 메커니즘은 다음과 같습니다.
소스 및 데이터 내보내기는 해당 하위 클래스에 속합니다. 예를 들어, 기본값
배포 NS-3 추적에 연결하도록 설계된 DoubleProbe 클래스를 제공합니다.
이중 값을 내보내는 소스입니다. 다음으로 DoubleProbe의 작동을 자세히 설명하겠습니다.
그런 다음 사용자가 다른 프로브 클래스를 정의하는 방법에 대해 논의합니다.

더블프로브 살펴보기
DoubleProbe는 이중 값에 연결됩니다. NS-3 추적 소스 자체를 내보냅니다.
다른 이중 값 NS-3 추적 소스.

다음 코드는 src/stats/examples/double-probe-example.cc, 기본을 보여줍니다
DoubleProbe를 시뮬레이션으로 연결하여 카운터를 프로빙하는 작업
이미터 객체(Emitter 클래스)에 의해 내보냅니다.

포인트 이미터 = CreateObject ();
이름::추가("/이름/이미터", 이미터);
...

포인트 프로브1 = CreateObject ();

// 프로브를 이미터의 카운터에 연결합니다.
bool 연결됨 = 프로브1->ConnectByObject("카운터", 이미터);

다음 코드는 동일한 이미터 객체에서 내보낸 동일한 Counter를 검색합니다. 이것
그러나 DoubleProbe는 구성 네임스페이스의 경로를 사용하여
연결. 이미터는 이후 구성 네임스페이스에 자체적으로 등록되었습니다.
그것은 창조되었다; 그렇지 않으면 ConnectByPath가 작동하지 않습니다.

포인트 프로브2 = CreateObject ();

// 여기서는 반환 값이 확인되지 않음을 참고하세요.
프로브2->ConnectByPath("/이름/이미터/카운터");

아래 표시된 다음 DoubleProbe는 해당 경로를 사용하여 값이 설정됩니다.
구성 네임스페이스. 이번에는 DoubleProbe가
생성된 후의 구성 네임스페이스입니다.

포인트 프로브3 = CreateObject ();
프로브3->SetName("StaticallyAccessedProbe");

// 구성 데이터베이스에 추가해야 합니다.
이름::추가("/이름/프로브", 프로브3->GetName(), 프로브3);

이제 이미터의 Count() 함수는 이 DoubleProbe의 값을 다음과 같이 설정할 수 있습니다.
다음과 같습니다 :

무효화
이미터::카운트(void)
{
...
m_counter += 1.0;
DoubleProbe::SetValueByPath("/Names/StaticallyAccessedProbe", m_counter);
...
}

위의 예는 프로브를 호출하는 코드가 명시적인 값을 가질 필요가 없는 방법을 보여줍니다.
프로브를 참조하지만 Config 네임스페이스를 통해 값 설정을 지정할 수 있습니다.
이는 기능면에서 유사합니다. 상태::넣기 ns2measure 논문에서 소개된 방법
[Cic06], 사용자가 다음과 같은 Probe 문을 임시로 삽입할 수 있습니다. printf
기존 내 NS-3 모델. 여기서 DoubleProbe를 사용하려면
이와 같은 예에는 두 가지가 필요했습니다.

1. 통계 모듈 헤더 파일이 예제 .cc 파일에 포함되었습니다.

2. 예제는 wscript 파일의 stats 모듈에 종속되도록 만들어졌습니다.

다른 프로브를 다른 위치에 추가하려면 유사한 작업을 수행해야 합니다. NS-3
코드베이스.

DoubleProbe의 값은 DoubleProbe::SetValue() 함수를 사용하여 설정할 수도 있습니다.
DoubleProbe의 값은 함수를 사용하여 얻을 수 있습니다.
DoubleProbe::GetValue().

DoubleProbe는 "출력" 추적 소스에서 이중 값을 내보냅니다. 다운스트림 객체
다음과 같이 추적 싱크(NotifyViaProbe)를 여기에 연결할 수 있습니다.

연결 = 프로브1->TraceConnect("출력", 프로브1->GetName(), MakeCallback(&NotifyViaProbe));

기타 프로브
DoubleProbe 외에도 다음 프로브도 사용할 수 있습니다.

· Uinteger8Probe는 NS-3 uint8_t를 내보내는 추적 소스입니다.

· Uinteger16Probe는 NS-3 uint16_t를 내보내는 추적 소스입니다.

· Uinteger32Probe는 NS-3 uint32_t를 내보내는 추적 소스입니다.

· PacketProbe는 NS-3 패킷을 내보내는 추적 소스입니다.

· ApplicationPacketProbe는 NS-3 패킷과 소켓을 내보내는 추적 소스
주소.

· Ipv4PacketProbe는 NS-3 패킷, IPv4 객체를 내보내는 추적 소스
인터페이스.

만들기 탐침 유형
새 프로브 유형을 생성하려면 다음 단계를 수행해야 합니다.

· 새 Probe 클래스가 Probe 기본 클래스에서 파생되었는지 확인하십시오.

· 새 Probe 클래스가 상속하는 순수 가상 함수가
프로브 기본 클래스가 구현됩니다.

· 유형이 가장 가까운 추적 소스를 사용하는 기존 프로브 클래스를 찾습니다.
프로브가 사용할 추적 소스 유형입니다.

· 기존 Probe 클래스의 헤더 파일(.h)과 구현 파일(.cc)을 두 개로 복사합니다.
새 프로브와 일치하는 이름을 가진 새 파일.

· 복사된 파일의 유형, 인수 및 변수를 적절한 것으로 대체하십시오.
프로브에 입력하세요.

· 코드를 컴파일하고 원하는 대로 작동하도록 필요한 수정을 가합니다.
처럼.


여기서는 두 가지 예를 자세히 설명합니다.

· 이중 프로브 예

· IPv4 패킷 플롯 예

탐침 예시
이중 프로브 예는 이전에 논의되었습니다. 예제 프로그램을 찾을 수 있습니다
in src/stats/examples/double-probe-example.cc. 이 프로그램에서 일어나는 일을 요약하자면,
포아송 프로세스에 따라 증가하는 카운터를 내보내는 이미터가 있습니다.
특히 데이터를 내보내는 두 가지 방법이 표시됩니다.

1. 하나의 프로브에 연결된 추적 변수를 통해:

추적된 값 m_counter; // 일반적으로 이는 정수 유형입니다.

2. 값이 두 번째 프로브에 게시되는 카운터를 통해 이름으로 참조됩니다.
구성 시스템:

무효화
이미터::카운트(void)
{
NS_LOG_FUNCTION(이것);
NS_LOG_DEBUG("계산 중" << Simulator::Now ().GetSeconds ());
m_counter += 1.0;
DoubleProbe::SetValueByPath("/Names/StaticallyAccessedProbe", m_counter);
Simulator::Schedule(초(m_var->GetValue ()), &Emitter::Count, this);
}

프로브를 좀 더 자세히 살펴보겠습니다. 프로브는 여러 값으로 값을 받을 수 있습니다.
방법 :

1. 프로브가 트레이스 소스에 직접 액세스하고 트레이스 싱크를 여기에 연결함으로써

2. 프로브가 구성 네임스페이스를 통해 추적 소스에 액세스하고
싱크대를 추적해 보세요

3. 프로브의 호출 코드를 명시적으로 호출하여 값 설정() 방법

4. 호출 코드를 명시적으로 호출하여 값별 경로 설정
("/경로/통과/구성/네임스페이스", ~)

처음 두 가지 기술이 가장 일반적일 것으로 예상됩니다. 또한 예에서는
일반적으로 수행되는 것처럼 일반 콜백 함수의 후킹이 표시됩니다. NS-3. 이
콜백 함수는 프로브 개체와 연결되어 있지 않습니다. 아래에서는 이 사례를 0)이라고 부르겠습니다.

// 이는 원시 함수를 추적 소스에 연결하는 것을 테스트하는 함수입니다.
무효화
NotifyViaTraceSource(std::string 컨텍스트, double oldVal, double newVal)
{
NS_LOG_DEBUG("컨텍스트: " << 컨텍스트 << " old " << oldVal << " new " << newVal);
}

먼저 이미터를 설정해야 합니다:

포인트 이미터 = CreateObject ();
이름::추가("/이름/이미터", 이미터);

// Emitter 객체는 ns-3 노드와 연결되어 있지 않으므로
// 자동으로 시작되지 않으므로 직접 수행해야 합니다.
시뮬레이터::일정(초(0.0), &Emitter::시작, 이미터);

아래 표시된 대로 다양한 DoubleProbe가 이 예에서 이미터와 상호 작용합니다.

사례 0):

// 아래는 프로브가 없는 일반적인 기능을 보여줍니다.
// (싱크 함수를 추적 소스에 연결)
//
연결됨 = 이미터->TraceConnect("카운터", "샘플 컨텍스트", MakeCallback(&NotifyViaTraceSource));
NS_ASSERT_MSG(연결됨, "트레이스 소스가 연결되지 않음");

사례 1):

//
// Probe1은 Emitter 추적 소스 개체에 직접 연결됩니다.
//

// 프로브1은 이미터 추적 소스에 연결됩니다.
포인트 프로브1 = CreateObject ();
// 프로브의 이름은 추적에서 컨텍스트로 사용될 수 있습니다.
프로브1->SetName("ObjectProbe");

// 프로브를 이미터의 카운터에 연결합니다.
연결 = 프로브1->ConnectByObject("카운터", 이미터);
NS_ASSERT_MSG(연결됨, "추적 소스가 프로브1에 연결되지 않음");

사례 2):

//
// Probe2는 다음과 같은 방법으로 Emitter 추적 소스 개체에 연결됩니다.
// Config 데이터베이스의 경로 이름으로 액세스
//

// 또 다른 유사한 프로브를 생성합니다. 이는 구성 경로를 통해 연결됩니다.
포인트 프로브2 = CreateObject ();
프로브2->SetName("PathProbe");

// 여기서는 반환 값이 확인되지 않음을 참고하세요.
프로브2->ConnectByPath("/이름/이미터/카운터");

사례 4)(이 예에서는 사례 3이 표시되지 않음):

//
// Probe3은 이미터에 의해 직접 호출됩니다.
// 정적 메서드 SetValueByPath().
//
포인트 프로브3 = CreateObject ();
프로브3->SetName("StaticallyAccessedProbe");
// 구성 데이터베이스에 추가해야 합니다.
이름::추가("/이름/프로브", 프로브3->GetName(), 프로브3);

마지막으로 예제에서는 프로브를 연결하여 출력을 생성하는 방법을 보여줍니다.

// 프로브 자체가 출력을 생성해야 합니다. 우리가 제공하는 컨텍스트
// 이 프로브(이 경우 프로브 이름)에 추가하면 명확하게 하는 데 도움이 됩니다.
// 추적 소스
연결됨 = 프로브3->TraceConnect("출력",
"/이름/프로브/StaticallyAccessedProbe/출력",
MakeCallback(&NotifyViaProbe));
NS_ASSERT_MSG(연결됨, "트레이스 소스가 ..probe3 출력에 연결되지 않았습니다.");

다음 콜백은 설명을 위해 이 예제의 프로브에 연결됩니다.
일반적으로 프로브는 Collector 개체에 연결됩니다.

// 프로브 출력에 대한 연결을 테스트하는 함수입니다.
무효화
NotifyViaProbe(std::string 컨텍스트, double oldVal, double newVal)
{
NS_LOG_DEBUG("컨텍스트: " << 컨텍스트 << " old " << oldVal << " new " << newVal);
}

IPv4 패킷 음모 예시
IPv4 패킷 도표 예는 다음의 five.cc 예를 기반으로 합니다. NS-3 지도 시간. 그것
에 있습니다 src/stats/examples/ipv4-packet-plot-example.cc.

노드 0 노드 1
+----------------+ +----------------+
| NS-3 TCP | | NS-3 TCP |
+----------------+ +----------------+
| 10.1.1.1 | | 10.1.1.2 |
+----------------+ +----------------+
| 지점 간 | | 지점 간 |
+----------------+ +----------------+
| |
+---------+

프로브가 다음에서 값을 풀 수도 있음을 보여주므로 프로브만 살펴보겠습니다.
구조(이 경우 패킷)를 추적하고 해당 값을 추적 소스 출력으로 보고합니다.
단순히 동일한 유형의 데이터를 전달하는 것보다

이 예제의 다른 측면은 문서의 뒷부분에서 설명하겠습니다.
내보낸 두 가지 유형의 데이터는 패킷 자체(산출) 및
패킷의 바이트 수(출력바이트).

유형 ID
Ipv4PacketProbe::GetTypeId()
{
static TypeId tid = TypeId ("ns3::Ipv4PacketProbe")
.SetParent ()
.AddConstructor ()
.AddTraceSource("출력",
"패킷과 이 프로브의 출력 역할을 하는 IPv4 개체 및 인터페이스",
MakeTraceSourceAccessor(&Ipv4PacketProbe::m_output))
.AddTraceSource("출력바이트",
"패킷의 바이트 수",
MakeTraceSourceAccessor(&Ipv4PacketProbe::m_outputBytes))
;
정시 반환;
}

프로브의 추적 싱크가 패킷을 받으면 프로브가 활성화된 경우 출력됩니다.
그 패킷 산출 추적 소스이지만 바이트 수도 출력됩니다.
출력바이트 추적 소스.

무효화
Ipv4PacketProbe::TraceSink(Ptr 패킷, Ptr ipv4, uint4_t 인터페이스)
{
NS_LOG_FUNCTION(이 << 패킷 << ipv4 << 인터페이스);
if (IsEnabled ())
{
m_packet = 패킷;
m_ipv4 = IPv4;
m_interface = 인터페이스;
m_output(패킷, ipv4, 인터페이스);

uint32_t packetSizeNew = 패킷->GetSize ();
m_outputBytes(m_packetSizeOld, packetSizeNew);
m_packetSizeOld = 패킷 크기 신규;
}
}

참고자료
[Cic06]
Claudio Cicconetti, Enzo Mingozzi, Giovanni Stea, "통합 프레임워크
ns2를 통한 효과적인 데이터 수집 및 통계 분석 활성화, 워크숍
ns-2(WNS2), 이탈리아 피사, 2006년 XNUMX월.

수집가
이 섹션은 Collector가 제공하는 기능을 자세히 설명하는 자리 표시자입니다.
수업을 NS-3 시뮬레이션을 통해 이를 프로그램에서 코딩하는 방법에 대한 예제를 제공합니다.

참고 : ns-3.18 현재 Collector는 아직 개발 중이며 아직 일부로 제공되지 않습니다.
프레임워크의.

어 그리 게이터
이 섹션에서는 Aggregator 클래스가 제공하는 기능을 자세히 설명합니다. NS-3
시뮬레이션. 이 섹션은 다음을 사용한 시뮬레이션 개발에 관심이 있는 사용자를 위한 것입니다.
NS-3 도구 및 데이터 수집 프레임워크 사용 중 Aggregator 클래스는
시뮬레이션 결과로 데이터 출력을 생성하는 부분입니다.

애그리 게이터 (aggregator) 살펴보기
Aggregator 개체는 다음을 수행하기 위해 하나 이상의 추적 소스에 연결되어야 합니다.
입력을 받습니다. Aggregator는 네트워크가 수집한 데이터의 종점입니다.
시뮬레이션 중 프로브 및 수집기. 이를 수집하는 것이 Aggregator의 임무입니다.
값을 저장하고 이를 일반 텍스트 파일과 같은 최종 출력 형식으로 변환합니다.
스프레드시트 파일, 플롯 또는 데이터베이스.

일반적으로 수집기는 하나 이상의 수집기에 연결됩니다. 이런 식으로 언제든지
수집기의 추적 소스는 새 값을 내보내고 수집기는 값을 처리하여
데이터 값이 이후에 상주하게 될 최종 출력 형식에 사용될 수 있다는 것입니다.
시뮬레이션.

Aggregator에 대해서는 다음 사항에 유의하세요.

· 집계자는 다음 호출을 통해 시뮬레이션 중에 동적으로 켜고 끌 수 있습니다.
할 수 있게 하다() and 장애를 입히다(). 예를 들어, 데이터 집계는 다음 동안 꺼질 수 있습니다.
시뮬레이션 준비 단계. 이는 해당 값이 최종 단계에 포함되지 않음을 의미합니다.
출력 매체.

· 집계자는 콜백을 통해 수집기로부터 데이터를 받습니다. Collector가 연결된 경우
수집자에게 TraceConnect를 호출하여 수집자의 추적을 설정합니다.
콜백으로서의 싱크 메소드.

현재까지 두 개의 Aggregator가 구현되었습니다.

· GnuplotAggregator

· 파일 수집기

Gnuplot 애그리게이터
GnuplotAggregator는 gnuplot을 만드는 데 사용되는 출력 파일을 생성합니다.

GnuplotAggregator는 시뮬레이션이 끝나면 3개의 서로 다른 파일을 생성합니다.

· 공백으로 구분된 gnuplot 데이터 파일

· gnuplot 제어 파일

· gnuplot을 생성하는 쉘 스크립트

창조
여기서는 수행해야 할 작업을 보여주기 위해 GnuplotAggregator 유형의 개체가 생성됩니다.

스마트 포인터 클래스를 사용하여 동적 메모리에 GnuplotAggregator를 선언합니다.
(부분 ). 스마트 포인터를 사용하여 동적 메모리에 GnuplotAggregator를 만들려면 다음 중 하나를 수행하세요.
전화해야 해 NS-3 방법 객체 생성(). 다음 코드는
src/stats/examples/gnuplot-aggregator-example.cc 이를 수행하는 방법을 보여줍니다.

string fileNameWithoutExtension = "gnuplot-aggregator";

// 수집기를 생성합니다.
포인트 수집자 =
CreateObject (파일 이름WithoutExtension);

생성자의 첫 번째 인수인 fileNameWithoutExtension은
확장자 없이 작성하려면 gnuplot 관련 파일을 사용하세요. 이 GnuplotAggregator는
"gnuplot-aggregator.dat"라는 이름의 공백으로 구분된 gnuplot 데이터 파일, gnuplot 제어 파일
"gnuplot-aggregator.plt"라는 이름과 +라는 이름의 gnuplot을 생성하는 쉘 스크립트
"gnuplot-aggregator.sh".

생성된 gnuplot의 키는 4개의 다른 위치에 있을 수 있습니다.

· 열쇠 없음

· 플롯 내부의 키(기본값)

· 플롯 위의 키

· 플롯 아래의 키

다음 gnuplot 키 위치 열거형 값은 키 위치를 지정하는 데 허용됩니다.

열거형 키 위치 {
NO_KEY,
KEY_INSIDE,
KEY_ABOVE,
KEY_BELOW
};

기본 위치인 내부가 아닌 아래 키를 원할 경우
다음을 수행할 수 있습니다.

수집기->SetKeyLocation(GnuplotAggregator::KEY_BELOW);


여기서 한 가지 예를 자세히 설명합니다.

· Gnuplot 수집기 예

지플롯 애그리 게이터 (aggregator) 예시
GnuplotAggregator를 실행하는 예는 다음에서 찾을 수 있습니다.
src/stats/examples/gnuplot-aggregator-example.cc.

다음 2D gnuplot은 예제를 사용하여 생성되었습니다.
[이미지] gnuplot-aggregator-example.cc로 생성된 2D Gnuplot 예시..UNINDENT

예제의 이 코드는 논의된 대로 GnuplotAggregator를 구성하는 방법을 보여줍니다.
위.

무효 Create2dPlot()
{
네임 스페이스를 사용하여 표준;

string fileNameWithoutExtension = "gnuplot-aggregator";
stringplotTitle = "Gnuplot Aggregator 플롯";
stringplotXAxisHeading = "시간(초)";
stringplotYAxisHeading = "이중 값";
stringplotDatasetLabel = "데이터 값";
stringdatasetContext = "데이터 세트/컨텍스트/문자열";

// 수집기를 생성합니다.
포인트 수집자 =
CreateObject (파일 이름WithoutExtension);

2D 데이터 세트를 포함하여 다양한 GnuplotAggregator 속성이 설정됩니다.
음모를 꾸몄다.

// 수집자의 속성을 설정합니다.
수집기->SetTerminal("png");
수집자->SetTitle(plotTitle);
aggregator->SetLegend(plotXAxisHeading,plotYAxisHeading);

// 수집기에 데이터 세트를 추가합니다.
aggregator->Add2dDataset(datasetContext,plotDatasetLabel);

// 수집기가 켜져 있어야 합니다.
수집자->활성화();

다음으로 2차원 값이 계산되고 각 값이 개별적으로
GnuplotAggregator를 사용하여 쓰기2d() 기능.

두 배의 시간;
이중 값;

// 2D 데이터세트를 생성합니다.
for (시간 = -5.0; 시간 <= +5.0; 시간 += 1.0)
{
// 2차원 곡선 계산
//
// 2
// 값 = 시간 .
//
값 = 시간 * 시간;

// 이 점을 플롯에 추가합니다.
aggregator->Write2d(datasetContext, 시간, 값);
}

// 수집기에 대한 데이터 로깅을 비활성화합니다.
수집자->비활성화();
}

파일 수집기
FileAggregator는 받은 값을 파일로 보냅니다.

FileAggregator는 4가지 유형의 파일을 생성할 수 있습니다.

· 포맷됨

· 공백으로 구분됨(기본값)

· 쉼표로 구분

· 탭 분리

형식화된 파일은 C 스타일 형식 문자열과 sprintf() 함수를 사용하여 파일을 인쇄합니다.
기록 중인 파일의 값입니다.

창조
수행해야 할 작업을 보여주기 위해 FileAggregator 유형의 개체가 여기에 생성됩니다.

스마트 포인터 클래스(Ptr)를 사용하여 동적 메모리에 FileAggregator를 선언합니다. ).
스마트 포인터를 사용하여 동적 메모리에 FileAggregator를 생성하려면 다음을 호출하면 됩니다.
전에, NS-3 메소드 CreateObject. 다음 코드는
src/stats/examples/file-aggregator-example.cc 이를 수행하는 방법을 보여줍니다.

string fileName = "file-aggregator-formatted-values.txt";

// 형식화된 값을 갖는 수집기를 만듭니다.
포인트 수집자 =
CreateObject (파일 이름, FileAggregator::FORMATTED);

생성자의 첫 번째 인수인 filename은 작성할 파일의 이름입니다. 그만큼
두 번째 인수인 fileType은 작성할 파일 유형입니다. 이 FileAggregator는
"file-aggregator-formatted-values.txt"라는 이름의 파일에 해당 값이 지정된 대로 인쇄됩니다.
fileType, 즉 이 경우 형식이 지정됩니다.

다음 파일 유형 열거형 값이 허용됩니다.

열거형 파일 유형 {
포맷됨,
SPACE_SEPARATED,
쉼표_분리됨,
TAB_SEPARATED
};


여기서 한 가지 예를 자세히 설명합니다.

· 파일 수집기 예

입양 부모로서의 귀하의 적합성을 결정하기 위해 미국 이민국에 애그리 게이터 (aggregator) 예시
FileAggregator를 실행하는 예는 다음에서 찾을 수 있습니다.
src/stats/examples/file-aggregator-example.cc.

쉼표로 구분된 2개의 값 열이 있는 다음 텍스트 파일은 다음을 사용하여 생성되었습니다.
예.

-5,25
-4,16
-3,9
-2,4
-1,1
0,0
1,1
2,4
3,9
4,16
5,25

예제의 이 코드는 논의된 대로 FileAggregator를 구성하는 방법을 보여줍니다.
위.

무효 CreateCommaSeparatedFile()
{
네임 스페이스를 사용하여 표준;

string fileName = "file-aggregator-comma-separated.txt";
stringdatasetContext = "데이터 세트/컨텍스트/문자열";

// 수집기를 생성합니다.
포인트 수집자 =
CreateObject (파일 이름, FileAggregator::COMMA_SEPARATED);

FileAggregator 속성이 설정되었습니다.

// 수집기가 켜져 있어야 합니다.
수집자->활성화();

다음으로 2차원 값이 계산되고 각 값이 개별적으로
FileAggregator를 사용하여 쓰기2d() 기능.

두 배의 시간;
이중 값;

// 2D 데이터세트를 생성합니다.
for (시간 = -5.0; 시간 <= +5.0; 시간 += 1.0)
{
// 2차원 곡선 계산
//
// 2
// 값 = 시간 .
//
값 = 시간 * 시간;

// 이 점을 플롯에 추가합니다.
aggregator->Write2d(datasetContext, 시간, 값);
}

// 수집기에 대한 데이터 로깅을 비활성화합니다.
수집자->비활성화();
}

2개의 형식화된 값 열이 포함된 다음 텍스트 파일도 다음을 사용하여 생성되었습니다.
예.

시간 = -5.000e+00 값 = 25
시간 = -4.000e+00 값 = 16
시간 = -3.000e+00 값 = 9
시간 = -2.000e+00 값 = 4
시간 = -1.000e+00 값 = 1
시간 = 0.000e+00 값 = 0
시간 = 1.000e+00 값 = 1
시간 = 2.000e+00 값 = 4
시간 = 3.000e+00 값 = 9
시간 = 4.000e+00 값 = 16
시간 = 5.000e+00 값 = 25

예제의 이 코드는 논의된 대로 FileAggregator를 구성하는 방법을 보여줍니다.
위.

무효 CreateFormattedFile()
{
네임 스페이스를 사용하여 표준;

string fileName = "file-aggregator-formatted-values.txt";
stringdatasetContext = "데이터 세트/컨텍스트/문자열";

// 형식화된 값을 갖는 수집기를 만듭니다.
포인트 수집자 =
CreateObject (파일 이름, FileAggregator::FORMATTED);

사용할 C 스타일 형식 문자열을 포함하여 FileAggregator 속성이 설정됩니다.

// 값의 형식을 설정합니다.
aggregator->Set2dFormat ("시간 = %.3e\t값 = %.0f");

// 수집기가 켜져 있어야 합니다.
수집자->활성화();

다음으로 2차원 값이 계산되고 각 값이 개별적으로
FileAggregator를 사용하여 쓰기2d() 기능.

두 배의 시간;
이중 값;

// 2D 데이터세트를 생성합니다.
for (시간 = -5.0; 시간 <= +5.0; 시간 += 1.0)
{
// 2차원 곡선 계산
//
// 2
// 값 = 시간 .
//
값 = 시간 * 시간;

// 이 점을 플롯에 추가합니다.
aggregator->Write2d(datasetContext, 시간, 값);
}

// 수집기에 대한 데이터 로깅을 비활성화합니다.
수집자->비활성화();
}

어댑터
이 섹션에서는 Adapter 클래스가 제공하는 기능을 자세히 설명합니다. NS-3
시뮬레이션. 이 섹션은 다음을 사용한 시뮬레이션 개발에 관심이 있는 사용자를 위한 것입니다.
NS-3 도구 및 Adapter 클래스가 포함된 데이터 수집 프레임워크 사용
시뮬레이션 결과로 데이터 출력을 생성합니다.

참고: '어댑터'라는 용어는 '어댑터'로 표기될 수도 있습니다. 우리는 맞춤법 정렬을 선택했습니다
C++ 표준을 사용합니다.

어댑터 살펴보기
어댑터는 다양한 유형의 DCF 개체를 연결하는 데 사용됩니다.

현재까지 하나의 어댑터가 구현되었습니다.

· TimeSeriesAdaptor

Time 연속 어댑터
TimeSeriesAdaptor를 사용하면 프로브를 별도의 연결 없이 수집기에 직접 연결할 수 있습니다.
그 사이의 수집가.

구현된 DCF 도우미는 모두 TimeSeriesAdaptor를 활용하여 프로브를 수행합니다.
다른 유형의 값을 변환하고 현재 시간과 두 값을 모두 변환하여 출력합니다.
두 배로.

TimeSeriesAdaptor 클래스의 역할은 원시 값을 취하는 어댑터의 역할입니다.
다양한 유형의 데이터를 조사하고 두 개의 double 값으로 구성된 튜플을 출력합니다. 첫 번째는
타임스탬프는 다른 해상도(예: 초, 밀리초 등)로 설정될 수 있습니다.
미래이지만 현재는 Seconds로 하드코딩되어 있습니다. 두 번째는 A의 변환이다.
double 값이 아닌 값을 double 값으로 변경합니다(정밀도가 손실될 수 있음).

범위/제한
이 섹션에서는 데이터 수집 프레임워크의 범위와 제한 사항에 대해 설명합니다.

현재 DCF에서는 다음 프로브만 구현되었습니다.

· 부울 프로브

· 더블프로브

· Uinteger8Probe

· Uinteger16Probe

· Uinteger32Probe

· 타임프로브

· 패킷프로브

· ApplicationPacketProbe

· Ipv4PacketProbe

현재 DCF에서는 수집기를 사용할 수 없지만 BasicStatsCollector는 아래에 있습니다.
개발.

현재 DCF에서는 다음 Aggregator만 구현되었습니다.

· GnuplotAggregator

· 파일 수집기

현재 DCF에서는 이 어댑터만 구현되었습니다.

시계열 어댑터.

미래 작업
이 섹션에서는 데이터 수집 프레임워크에서 수행될 향후 작업에 대해 설명합니다.

아직 수행해야 할 작업은 다음과 같습니다.

· 더 많은 추적 소스를 연결합니다. NS-3 시뮬레이터에서 더 많은 값을 얻는 코드입니다.

· 현재보다 더 많은 유형의 프로브를 구현합니다.

· 단일 현재 2D 수집기인 BasicStatsCollector 이상의 기능을 구현합니다.

· 더 많은 집계자를 구현합니다.

· 단순한 어댑터 이상의 것을 구현합니다.

통계적인 뼈대
이 장에서는 시뮬레이션 데이터 수집 및 통계 프레임워크에 대한 작업을 간략하게 설명합니다.
NS-3.

통계 프레임워크의 소스 코드는 디렉토리에 있습니다. 소스/통계.

목표
이 노력의 주요 목표는 다음과 같습니다.

· 분석을 위한 데이터 및 통계를 기록, 계산, 제시하는 기능 제공
네트워크 시뮬레이션.

· 광범위한 추적 로그를 생성할 필요성을 줄여 시뮬레이션 성능을 향상시킵니다.
데이터를 수집하라는 명령입니다.

· 온라인 통계를 통해 시뮬레이션 제어 활성화(예: 시뮬레이션 종료 또는
반복되는 시련.

파생된 하위 목표 및 기타 대상 기능은 다음과 같습니다.

· 기본 계측 프레임워크로 기존 ns-3 추적 시스템과 통합
내부 시뮬레이션 엔진(예: 네트워크 스택, 넷 장치 및 채널).

· 사용자가 추적을 사용하지 않고도 통계 프레임워크를 활용할 수 있도록 지원
시스템.

· 사용자가 여러 번의 시도를 통해 데이터를 생성, 집계 및 분석할 수 있도록 지원합니다.

· 사용자 생성 계측 지원(예: 특정 애플리케이션 이벤트 및
측정합니다.

· 패키지를 사용하지 않을 때 메모리 및 CPU 오버헤드가 낮습니다.

· 기존 분석 및 출력 도구를 최대한 활용합니다. 프레임워크는 다음과 같습니다.
몇 가지 기본 통계를 제공하지만 데이터를 수집하고 만드는 데 중점을 둡니다.
기존 도구에서 조작이 가능합니다.

· 독립적인 복제 배포에 대한 최종 지원은 중요하지만 포함되지 않습니다.
첫 번째 기능 라운드에서.

살펴보기
통계 프레임워크에는 다음 기능이 포함되어 있습니다.

· 핵심 프레임워크와 두 개의 기본 데이터 수집기: 카운터, 최소/최대/평균/총계
관찰자.

· 시간과 패킷을 쉽게 사용할 수 있는 확장 기능입니다.

· 다음 형식의 일반 텍스트 출력 옴넷++.

· 데이터베이스 출력을 사용하여 SQLite는, 독립형 경량 고성능 SQL 엔진입니다.

· 실행을 설명하고 작업하기 위한 필수 개방형 메타데이터입니다.

· NS-3의 특성을 조사하는 개념적 실험을 기반으로 한 예
기본 Ad Hoc WiFi 성능. 여기에는 다음이 포함됩니다.

· 노드 간의 거리가 매개변수화된 XNUMX노드 Ad Hoc WiFi 네트워크 구성
떨어져서.

· 동작이 약간 다른 UDP 트래픽 소스 및 싱크 애플리케이션
재고 클래스보다 측정 후크.

· 기존 추적 신호를 통해 NS-3 코어에서 데이터 수집, 특히
WiFi MAC 개체가 전송하고 수신하는 프레임입니다.

· 새로운 추적 신호를 통계에 연결하여 맞춤형 애플리케이션 계측
프레임워크뿐만 아니라 직접 업데이트를 통해서도 가능합니다. 총 패킷에 대한 정보가 기록됩니다.
전송 및 수신, 전송된 바이트 및 종단 간 지연.

· 종단 간 지연을 추적하기 위해 패킷 태그를 사용하는 예입니다.

· 다양한 실험을 여러 번 시도하는 간단한 제어 스크립트
거리를 측정하고 결과 데이터베이스를 쿼리하여 GNUPlot을 사용하여 그래프를 생성합니다.

할 것
우선순위가 높은 항목은 다음과 같습니다.

· 온라인 통계 코드 포함(예: 메모리 효율적인 신뢰 구간).

· 실행 종료를 위한 데이터 수집기의 규정, 즉 임계값 또는
자신감이 충족되었습니다.

· 시간이 지남에 따라 샘플을 기록하고 다양한 형식으로 출력하기 위한 데이터 수집기입니다.

· 일부 값을 정기적으로 폴링하기 위해 간단한 순환 이벤트 글루를 작성하는 방법을 보여줍니다.

이들 각각은 현재 프레임워크에 통합하기가 간단하다는 것이 입증되어야 합니다.

Approach
프레임워크는 다음 핵심 원칙을 기반으로 합니다.

· 하나의 실험은 하나의 시뮬레이션 프로그램 인스턴스로 수행됩니다.
병렬 또는 직렬.

· 제어 스크립트는 필요에 따라 매개변수를 변경하면서 시뮬레이션 인스턴스를 실행합니다.

· 외부 스크립트를 사용하여 플롯팅 및 분석을 위해 데이터를 수집하고 저장합니다.
기존 도구.

· ns-3 코어 내 조치는 통계 프레임워크를 기존에 연결하여 수행됩니다.
추적 신호.

· 추적 신호 또는 프레임워크의 직접 조작을 사용하여 사용자 정의를 계측할 수 있습니다.
시뮬레이션 코드.

프레임워크의 기본 구성 요소와 상호 작용은 다음과 같습니다.
다음 그림. [영상]

예시
이번 섹션에서는 프레임워크에서 실험을 구성하는 과정을 살펴보고,
분석을 위한 데이터(그래프)를 생성하고 이에 따라 구조와 API를 시연합니다.
그 길.

문제
''ns-3의 WiFi NetDevices의 (시뮬레이션된) 성능은 무엇입니까(기본값 사용)
설정)? 시뮬레이션에서 무선 노드가 얼마나 멀리 떨어져 있을 수 있습니까?
안정적으로 의사소통을 할 수 있나요?''

· 가설: 실생활 성능에 대한 지식을 바탕으로 노드들이 통신해야 함
최소한 100m 이상 떨어져 있어야 합니다. 200m이상의 통신은 안됩니다
실현 가능 한.

시뮬레이션 상황에서 흔히 발생하는 질문은 아니지만 이는 중요한 속성입니다.
시뮬레이션 개발자는 이에 대한 기본적인 이해를 가지고 있어야 합니다. 그것은 또한 일반적인
라이브 하드웨어에 대한 연구.

시뮬레이션 프로그램
이 실험을 구현하기 위해 가장 먼저 해야 할 일은 시뮬레이션을 개발하는 것입니다.
프로그램. 이 예제의 코드는 다음에서 찾을 수 있습니다. 예제/통계/wifi-example-sim.cc.
다음과 같은 주요 단계를 수행합니다.

· 다음을 사용하여 매개변수 선언 및 명령줄 구문 분석 ns3::명령줄.

이중 거리 = 50.0;
문자열 형식("OMNet++");
문자열 실험("wifi-distance-test");
문자열 전략("wifi-default");
문자열 runID;

커맨드라인 cmd;
cmd.AddValue("distance", "노드를 배치하기 위한 거리(미터 단위).", distance);
cmd.AddValue("format", "데이터 출력에 사용할 형식입니다.", format);
cmd.AddValue("실험", "실험 식별자.", 실험);
cmd.AddValue("strategy", "전략 식별자.", strategy);
cmd.AddValue("run", "실행 식별자.", runID);
cmd.Parse(argc, argv);

· 다음을 사용하여 노드 및 네트워크 스택 생성 ns3::노드컨테이너, ns3::WiFiHelper
ns3::InternetStackHelper.

NodeContainer 노드;
노드.생성(2);

Wi-FiHelper Wi-Fi;
wifi.SetMac("ns3::AdhocWifiMac");
wifi.SetPhy("ns3::WifiPhy");
NetDeviceContainer nodeDevices = wifi.Install(nodes);

InternetStackHelper 인터넷;
인터넷.설치(노드);
Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase("192.168.0.0", "255.255.255.0");
ipAddrs.Assign(nodeDevices);

· 다음을 사용하여 노드 위치 지정 ns3::모빌리티헬퍼. 기본적으로 노드에는 정적
이동성이 있어 움직이지 않지만, 주어진 거리만큼 떨어져 있어야 합니다. 있다
이를 수행하는 여러 가지 방법; 여기서는 다음을 사용하여 수행됩니다. ns3::ListPositionAllocator, 그리는
주어진 목록의 위치.

이동성도우미 이동성;
포인트 positionAlloc =
CreateObject ();
positionAlloc->Add(벡터(0.0, 0.0, 0.0));
positionAlloc->Add(Vector(0.0, 거리, 0.0));
이동성.SetPositionAllocator(positionAlloc);
이동성.설치(노드);

· 트래픽 생성기와 트래픽 싱크를 설치합니다. 주식 어플리케이션 될 수
사용되었지만 예제에는 사용자 정의 개체가 포함되어 있습니다. src/test/test02-apps.(cc|h). 이들
주어진 간격으로 일정한 수의 패킷을 생성하는 간단한 동작을 가집니다.
각각 하나만 있기 때문에 수동으로 설치됩니다. 더 큰 세트의 경우
ns3::ApplicationHelper 수업을 사용할 수 있습니다. 주석 처리된 구성::설정 라인 변경
이 예에서는 기본적으로 브로드캐스트로 설정된 패킷의 대상입니다. 참고하세요
일반적으로 WiFi는 다음과 같은 이유로 브로드캐스트 및 유니캐스트 프레임의 성능이 다를 수 있습니다.
다양한 속도 제어 및 MAC 재전송 정책.

포인트 appSource = NodeList::GetNode(0);
포인트 발신자 = CreateObject ();
appSource->AddApplication(발신자);
보낸 사람->시작((삼));

포인트 appSink = NodeList::GetNode(1);
포인트 수신자 = CreateObject ();
appSink->AddApplication(수신자);
수신기->시작((삼));

// Config::Set("/NodeList/*/ApplicationList/*/$Sender/Destination",
// Ipv4AddressValue("192.168.0.2"));

· 수집할 데이터 및 통계를 구성합니다. 기본적인 패러다임은
ns3::데이터수집기 이 특정 실행에 대한 정보를 보유하기 위해 객체가 생성됩니다.
실제로 데이터를 생성하기 위해 어떤 관찰자와 계산기가 부착되어 있는지. 중요한 것은,
실행 정보에는 '실험', '전략', '입력'에 대한 레이블이 포함됩니다.
''달리다''. 이는 나중에 여러 시험에서 데이터를 식별하고 쉽게 그룹화하는 데 사용됩니다.

· 실험은 이 임상시험이 속해 있는 연구입니다. 여기 Wi-Fi가 있습니다.
성능과 거리.

· 전략은 이 시험에서 검사되는 코드 또는 매개변수입니다. 이 예에서는
수정되었지만 확실한 확장은 다른 WiFi 비트를 조사하는 것입니다.
각각 다른 전략이 될 것입니다.

· 입력은 이 시도에 주어진 특정 문제입니다. 여기는 단순히
두 노드 사이의 거리.

· runID는 정보가 태그된 이 시험에 대한 고유 식별자입니다.
추후 분석에서 식별을 위해. 실행 ID가 제공되지 않으면 예제 프로그램은 다음을 수행합니다.
현재 시간을 사용하는 (약한) 실행 ID입니다.

이 네 가지 메타데이터가 필요하지만 더 많은 것이 필요할 수도 있습니다. 추가될 수 있음
을 사용하여 기록에 ns3::DataCollector::메타데이터 추가() 방법.

DataCollector 데이터;
data.DescribeRun(실험, 전략, 입력, 실행 ID);
data.AddMetadata("작성자", "tjkopena");

실제 관찰과 계산은 다음과 같이 수행됩니다. ns3::데이터계산기 개체, 그중
여러 가지 유형이 존재합니다. 이는 다음에 첨부된 시뮬레이션 프로그램에 의해 생성됩니다.
보고 또는 샘플링 코드를 등록한 다음 ns3::데이터수집기 그래서 그들은 그럴 것이다
나중에 출력에 대해 쿼리됩니다. 쉬운 관찰 메커니즘 중 하나는 기존의 것을 사용하는 것입니다.
예를 들어 소스를 변경하지 않고 ns-3 코어의 개체를 계측하기 위한 추적 소스
암호. 여기서 카운터는 Wi-Fi MAC 계층의 추적 신호에 직접 연결됩니다.
대상 노드.

포인트 totalRx = CreateObject ();
totalRx->SetKey("wifi-rx-frames");
Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Rx",
MakeCallback(&PacketCounterCalculator::FrameUpdate, totalRx));
data.AddDataCalculator(totalRx);

계산기를 직접 조작할 수도 있습니다. 이 예에서는 카운터가 생성되고
패킷이 수신되면 업데이트되도록 트래픽 싱크 애플리케이션에 전달됩니다.

포인트 > appRx = CreateObject >();
appRx->SetKey("수신기-rx-패킷");
수신기->SetCounter(appRx);
data.AddDataCalculator(appRx);

개수를 늘리기 위해 싱크의 패킷 처리 코드는 다음 중 하나를 호출합니다.
계산기의 업데이트 방법.

m_calc->업데이트();

이 프로그램에는 기본 요소와 두 가지 요소를 모두 사용하는 몇 가지 다른 예제도 포함되어 있습니다.
다음과 같은 계산기 ns3::카운터계산기 패킷을 관찰하는 데 적합한 것
타임스. ~ 안에 src/test/test02-apps.(cc|h) 또한 사용하는 간단한 사용자 정의 태그를 생성합니다.
생성된 패킷의 종단 간 지연을 추적하고 결과를
ns3::TimeMinMaxAvgTotal계산기 데이터 계산기.

· 일단 구성되면 매우 간단하게 시뮬레이션을 실행합니다.

시뮬레이터::실행();

· 다음 중 하나를 생성합니다. 옴넷++ or SQLite는 명령줄 인수에 따라 출력됩니다. 에게
이것을 해라 ns3::데이터출력인터페이스 객체가 생성되고 구성됩니다. 특정 유형
이것에 따라 출력 형식이 결정됩니다. 그런 다음 이 객체에는
ns3::데이터수집기 출력을 생성하기 위해 조사하는 개체입니다.

포인트 산출;
if (형식 == "OMNet++") {
NS_LOG_INFO("OMNet++ 형식의 데이터 출력을 생성 중입니다.");
출력 = CreateObject ();
} 다른 {
# ifdef STAT_USE_DB
NS_LOG_INFO("SQLite 형식의 데이터 출력을 생성합니다.");
출력 = CreateObject ();
#엔디프
}

출력->출력(데이터);

· 시뮬레이션에 사용된 모든 메모리를 해제합니다. 이건 메인의 마지막 부분에 나와야 해
예를 들어 함수를 사용합니다.

시뮬레이터::파괴();

로깅
예제 프로그램, 애플리케이션, 통계 프레임워크가 수행하는 작업을 자세히 보려면 ​​다음을 설정하세요.
전에, NS_LOG 적절하게 가변합니다. 다음은 모든 것의 풍부한 출력을 제공합니다.
세.

$ 내보내기 NS_LOG=WiFiDistanceExperiment:WiFiDistanceApps

이로 인해 시뮬레이션 속도가 엄청나게 느려집니다.

견본 산출
테스트 프로그램을 컴파일하고 간단히 실행하면 추가됩니다. 옴넷++ 다음과 같은 형식화된 출력
다음은 data.sca.

run-1212239121을 실행하세요.

attr 실험 "wifi-distance-test"
속성 전략 "wifi-default"
속성 입력 "50"
속성 설명 ""

attr "author" "tjkopena"

스칼라 wifi-tx-프레임 수 30
스칼라 wifi-rx-프레임 수 30
스칼라 sender-tx-packets 개수 30
스칼라 수신기-rx-패킷 수 30
스칼라 tx-pkt-size 개수 30
스칼라 tx-pkt-size 총 1920
스칼라 tx-pkt-크기 평균 64
스칼라 tx-pkt-size 최대 64
스칼라 tx-pkt-size 최소 64
스칼라 지연 횟수 30
스칼라 지연 총 5884980ns
스칼라 지연 평균 196166ns
스칼라 지연 최대 196166ns
스칼라 지연 최소 196166ns

Control 스크립트
다양한 입력(거리)에서 데이터 수집을 자동화하기 위해 간단한 Bash
스크립트는 일련의 시뮬레이션을 실행하는 데 사용됩니다. 다음에서 찾을 수 있습니다.
예제/stats/wifi-example-db.sh. 스크립트는 다음에서 실행되도록 되어 있습니다. 예/통계/
디렉토리.

스크립트는 일련의 거리를 통해 실행되어 결과를 SQLite는
데이터 베이스. 예상되는 결과를 더 잘 파악하기 위해 각 거리에서 XNUMX번의 시도가 수행됩니다.
성능. 전체 실험은 낮은 수준에서 실행되는 데 수십 초 밖에 걸리지 않습니다.
시뮬레이션 중에는 출력이 없고 트래픽도 거의 발생하지 않기 때문입니다.

#!/ 빈 / SH

거리="25 50 75 100 125 145 147 150 152 155 157 160 162 165 167 170 172 175 177 180"
평가판="1 2 3 4 5"

에코 WiFi 실험 예

if [ -e 데이터.db ]
그때
echo Kill data.db?
ANS 읽기
if [ "$ANS" = "예" -o "$ANS" = "y" ]
그때
echo 데이터베이스 삭제 중
rm 데이터.db
fi
fi

$TRIALS 평가판용
do
거리($DISTANCES)
do
에코 평가판 $trial, 거리 $distance
./bin/test02 --format=db --distance=$distance --run=run-$distance-$trial



분석 and 결론
모든 시도가 수행되면 스크립트는 다음을 통해 간단한 SQL 쿼리를 실행합니다.
데이터베이스를 사용하여 SQLite는 명령줄 프로그램. 쿼리는 평균 패킷 손실을 다음과 같이 계산합니다.
각 거리와 관련된 각 시도 세트. 다른 점을 고려하지 않습니다.
하지만 몇 가지 간단한 확장을 위해 정보가 데이터베이스에 존재합니다.
그렇게 하세요. 수집된 데이터는 그래프 작성을 위해 GNUPlot으로 전달됩니다.

CMD="선택 exp.input,avg(100-((rx.value*100)/tx.value)) \
Singletons rx, Singletons tx, Experiments exp에서 \
여기서 rx.run = tx.run AND \
rx.run = exp.run AND \
rx.name='수신기-rx-패킷' AND \
tx.name='sender-tx-packets' \
exp.input으로 그룹화 \
ABS(exp.input) ASC로 주문;"

sqlite3 -noheader data.db "$CMD" > wifi-default.data
sed -i "s/|/ /" wifi-default.data
gnuplot wifi-example.gnuplot

GNUPlot 스크립트는 다음 위치에 있습니다. 예제/통계/wifi-example.gnuplot 단순히 출력을 정의합니다
형식과 그래프의 일부 기본 형식을 지정합니다.

터미널 포스트스크립트 초상화 강화 lw 2 "Helvetica" 14 설정

크기를 1.0, 0.66으로 설정

#------------------------------------------------- ------
"wifi-default.eps"를 설정하세요.
#set title "거리에 따른 패킷 손실"
set xlabel "거리(m) --- 포인트당 5회 시도의 평균"
xrange 설정 [0:200]
set ylabel "% 패킷 손실"
범위 설정 [0:110]

줄 제목이 "WiFi Defaults"인 "wifi-default.data" 플롯

종료 결과
결과 그래프는 기본 WiFi 모델의 성능이 다음과 같다는 증거를 제공하지 않습니다.
필연적으로 비합리적이며 최소한 토큰에 대한 충실도에 약간의 자신감을 부여합니다.
현실. 더 중요한 것은 이 간단한 조사가 처음부터 끝까지 진행되었다는 것입니다.
통계 프레임워크를 사용합니다. 성공! [영상]

실시간
NS-3 테스트베드 및 가상 머신 환경에 통합되도록 설계되었습니다. 에게
실제 네트워크 스택과 통합하고 패킷을 방출/소비하는 실시간 스케줄러는
하드웨어 시계로 시뮬레이션 시계를 잠그려면 필요합니다. 우리는 여기서 설명합니다
이것의 구성 요소는 RealTime 스케줄러입니다.

실시간 스케줄러의 목적은 시뮬레이션 시계의 진행을 유발하는 것입니다.
일부 외부 시간 기반에 대해 동기적으로 발생합니다. 존재하지 않고
외부 시간 기반(벽시계), 시뮬레이션 시간은 시뮬레이션된 시간에서 즉시 점프합니다.
다음 시간.

행동
실시간이 아닌 스케줄러를 사용하는 경우(기본값은 NS-3), 시뮬레이터는
다음 예정된 이벤트까지의 시뮬레이션 시간. 이벤트 실행 중 시뮬레이션 시간은
겨울 왕국. 실시간 스케줄러의 동작은 다음의 관점에서 비슷합니다.
시뮬레이션 모델(즉, 이벤트 실행 중에 시뮬레이션 시간이 고정됨)
이벤트가 발생하면 시뮬레이터는 시뮬레이션 시계를 기계와 일치시키려고 시도합니다.
시계.

이벤트 실행이 완료되고 스케줄러가 다음 이벤트로 이동하면
스케줄러는 다음 이벤트 실행 시간을 머신 시계와 비교합니다. 만약 다음
이벤트가 미래 시간으로 예정되어 있으면 시뮬레이터는 해당 실시간 시간에 도달할 때까지 절전 모드로 전환됩니다.
그리고 다음 이벤트를 실행합니다.

시뮬레이션 이벤트 실행에 내재된 처리로 인해 다음과 같은 일이 발생할 수 있습니다.
시뮬레이터가 실시간을 따라갈 수 없다는 것입니다. 그러한 경우에는 사용자의 몫입니다.
무엇을 해야할지 구성. 두 가지가있다 NS-3 행동을 지배하는 속성. 그만큼
첫 번째는 ns3::RealTimeSimulatorImpl::SynchronizationMode. XNUMX개의 항목이 가능합니다.
이 속성은 최고의 노력 (기본값) 또는 하드리미트. "BestEffort" 모드에서는
시뮬레이터는 이벤트가 도달할 때까지 이벤트를 실행하여 실시간을 따라잡으려고 노력합니다.
다음 이벤트가 (실시간) 미래에 있는 지점입니다. 그렇지 않으면 시뮬레이션이 종료됩니다. ~ 안에
그러면 BestEffort 모드에서는 시뮬레이션이 다른 모드보다 더 많은 시간을 소모할 수 있습니다.
벽시계 시간. 다른 옵션 "HardLimit"은 다음과 같은 경우 시뮬레이션이 중단되도록 합니다.
허용 한도가 초과되었습니다. 이 속성은 ns3::RealTimeSimulatorImpl::HardLimit
기본값은 0.1초입니다.

다른 작동 모드는 시뮬레이션된 시간이 다음과 같은 모드입니다. 지원 행사 중 얼어붙은
실행. 이 실시간 시뮬레이션 모드는 구현되었지만 NS-3 나무
쓸모가 있을지 의문이 들기 때문이다. 사용자가 실시간에 관심이 있는 경우
이벤트 실행 중에 시뮬레이션 시간이 멈추지 않는 시뮬레이터(즉, 매
~에게 전화 해 시뮬레이터::지금() 현재 벽시계 시간을 반환합니다.
이벤트가 실행되기 시작했습니다.), ns-developers 메일링 리스트에 문의하세요.

용법
실시간 시뮬레이터의 사용법은 스크립팅 관점에서 보면 간단합니다.
사용자는 속성만 설정하면 됩니다. 시뮬레이터 구현 유형 실시간으로
다음과 같은 시뮬레이터:

GlobalValue::Bind("시뮬레이터 구현 유형",
StringValue("ns3::RealtimeSimulatorImpl"));

에 스크립트가 있습니다 예제/realtime/realtime-udp-echo.cc 여기에는 방법에 대한 예가 있습니다.
실시간 동작을 구성합니다. 노력하다:

$ ./waf --실시간 UDP 에코 실행

시뮬레이터가 최선의 노력으로 작동할지 아니면 엄격한 제한 정책 방식으로 작동할지 여부가 결정됩니다.
이전 섹션에서 설명한 속성을 사용합니다.

실시
구현은 다음 파일에 포함되어 있습니다.

· src/core/model/realtime-simulator-impl.{cc,h}

· src/코어/모델/벽시계-동기화 장치.{cc,h}

실시간 스케줄러를 생성하려면 첫 번째 근사값을 생성하고 싶습니다.
시뮬레이션 시간이 점프하여 실시간을 소모합니다. 우리는 다음의 조합을 사용하여 이를 수행할 것을 제안합니다.
잠자고 바빠서 기다립니다. Sleep-wait는 호출 프로세스(스레드)가
일정 시간 동안 프로세서. 정해진 시간이 지나도
나노초 해상도로 실제로는 OS별 세분성으로 변환됩니다. ~ 안에
Linux에서는 세분성을 Jiffy라고 합니다. 일반적으로 이 해상도로는 충분하지 않습니다.
우리의 필요 사항(대략 XNUMX밀리초)을 줄여서 잠시 잠을 잡니다.
더 적은 수의 Jiffies. 그런 다음 지정된 횟수만큼 프로세스가 활성화됩니다.
Jiffies가 통과했습니다. 현재로서는 기다릴 수 있는 잔여 시간이 있습니다. 이번은
일반적으로 최소 수면 시간보다 작으므로 남은 수면 시간을 바쁘게 기다립니다.
시간. 이는 스레드가
원하는 시간이 왔다. 수면 대기와 바쁜 대기를 결합한 후 경과된 실시간
(벽)시계는 다음 이벤트의 시뮬레이션 시간과 시뮬레이션 시간과 일치해야 합니다.
수입.

도우미
위의 장에서는 다양한 내용을 소개했습니다. NS-3 스마트와 같은 프로그래밍 개념
참조 계산된 메모리 관리, 속성, 네임스페이스, 콜백 등을 위한 포인터
이 하위 수준 API에서 작업하는 사용자는 상호 연결할 수 있습니다. NS-3 미세한 입자를 가진 물체.
그러나 저수준 API를 사용하여 완전히 작성된 시뮬레이션 프로그램은 상당히 길 수 있습니다.
그리고 코딩하기 지루하다. 이러한 이유로 별도의 소위 "도우미 API"가 오버레이되었습니다.
핵심에 NS-3 API. 만약 당신이 NS-3 튜토리얼, 당신은 이미 익숙할 것입니다
헬퍼 API를 사용하는 이유는 일반적으로 신규 사용자에게 가장 먼저 소개되는 API이기 때문입니다.
이 장에서는 도우미 API의 설계 철학을 소개하고 이를 다음과 대조합니다.
저수준 API. 헤비유저가 된다면 NS-3, 당신은 아마도 앞뒤로 움직일 것입니다
동일한 프로그램에서도 이러한 API 간에 가능합니다.

도우미 API에는 몇 가지 목표가 있습니다.

1. 나머지 src / 도우미 API에 대한 종속성이 없습니다. 무엇이든 할 수 있는 일
도우미 API는 하위 수준 API에서도 코딩할 수 있습니다.

2. 컨테이너 : 시뮬레이션에서는 그룹에 대해 여러 가지 동일한 작업을 수행해야 하는 경우가 많습니다.
개체의. 헬퍼 API는 유사한 객체의 컨테이너를 많이 사용합니다.
유사하거나 동일한 작업을 수행할 수 있습니다.

3. 도우미 API는 일반적이지 않습니다. 코드 재사용을 극대화하려고 노력하지 않습니다. 그래서,
코드 재사용을 달성하는 다형성 및 템플릿과 같은 프로그래밍 구성은
널리 퍼져 있지는 않습니다. 예를 들어 별도의 CsmaNetDevice 도우미와
PointToPointNetDevice 도우미이지만 공통 NetDevice 기반에서 파생되지 않습니다.
클래스입니다.

4. 도우미 API는 일반적으로 스택 할당(대 힙 할당) 개체와 함께 작동합니다. 을 위한
일부 프로그램, NS-3 사용자는 낮은 수준의 객체 생성 또는
Ptr 처리; 객체 컨테이너와 스택 할당 도우미를 사용하여 작업할 수 있습니다.
그것들을 조작하는 것입니다.

도우미 API는 실제로 만들기에 관한 모든 것입니다. NS-3 프로그램을 작성하고 읽기가 더 쉽습니다.
저수준 인터페이스의 힘을 빼앗아갑니다. 이 장의 나머지 부분에서는 다음과 같은 내용을 제공합니다.
도우미 API의 프로그래밍 규칙 예입니다.

유튜브 영상을 만드는 것은 플롯 사용 전에, 지플롯 클래스
다음을 사용하여 플롯을 만드는 두 가지 일반적인 방법이 있습니다. NS-3 그리고 gnuplot (‐
http://www.gnuplot.info):

1. 다음을 사용하여 gnuplot 제어 파일을 생성합니다. NS-3의 Gnuplot 클래스입니다.

2. 생성된 값을 사용하여 gnuplot 데이터 파일을 생성합니다. NS-3.

이 섹션은 방법 1에 관한 것입니다. 즉, 다음을 사용하여 플롯을 만드는 방법에 관한 것입니다. NS-3의 Gnuplot
수업. 방법 2에 관심이 있다면 아래의 "실제 예" 하위 섹션을 참조하세요.
"추적"섹션 NS-3 튜토리얼.

만들기 플롯 사용 전에, 지플롯 클래스
다음을 사용하여 플롯을 생성하려면 다음 단계를 수행해야 합니다. NS-3의 Gnuplot 클래스:

1. Gnuplot 클래스와 해당 기능을 사용하도록 코드를 수정합니다.

2. 코드를 실행하여 gnuplot 제어 파일을 생성합니다.

3. gnuplot 제어 파일 이름으로 gnuplot을 호출합니다.

4. 즐겨 사용하는 그래픽 뷰어에서 생성된 그래픽 파일을 봅니다.

1단계에 대한 자세한 내용은 아래에 설명된 예제 플롯의 코드를 참조하세요.

An 예시 프로그램 사용 전에, 지플롯 클래스
다음을 사용하는 예제 프로그램 NS-3의 Gnuplot 클래스는 여기에서 찾을 수 있습니다:

src/stats/examples/gnuplot-example.cc

이 예제를 실행하려면 다음을 수행하십시오.

$ ./waf 쉘
$ cd 빌드/디버그/src/통계/예제
$ ./gnuplot 예

그러면 예제가 있는 디렉터리에 다음과 같은 gnuplot 제어 파일이 생성됩니다.
위치:

플롯-2d.plt
플롯-2d-with-error-bars.plt
플롯-3d.plt

이러한 gnuplot 제어 파일을 처리하려면 다음을 수행하십시오.

$ gnuplot 플롯-2d.plt
$ gnuplot 플롯-2d-with-error-bars.plt
$ gnuplot 플롯-3d.plt

그러면 예제가 있는 디렉터리에 다음 그래픽 파일이 생성됩니다.
위치:

플롯-2d.png
플롯-2D-오류-바.png
플롯-3d.png

즐겨 사용하는 그래픽 뷰어에서 이러한 그래픽 파일을 볼 수 있습니다. 김프가 있다면
예를 들어 컴퓨터에 설치된 경우 다음과 같이 할 수 있습니다.

$ 김프 플롯-2d.png
$ gimp 플롯-2d-with-error-bars.png
$ 김프 플롯-3d.png

An 예시 2차원 음모
다음 2차원 플롯
[이미지]

gnuplot-example.cc의 다음 코드를 사용하여 생성되었습니다.

네임 스페이스를 사용하여 표준;

string fileNameWithNoExtension = "plot-2d";
문자열 그래픽파일 이름 = fileNameWithNoExtension + ".png";
stringplotFileName = fileNameWithNoExtension + ".plt";
stringplotTitle = "2차원 플롯";
string dataTitle = "2차원 데이터";

// 플롯을 인스턴스화하고 제목을 설정합니다.
Gnuplot 플롯(graphicsFileName);
플롯.SetTitle(plotTitle);

// 플롯 파일이 생성될 그래픽 파일을 만듭니다.
// Gnuplot과 함께 사용되며 PNG 파일입니다.
플롯.SetTerminal("png");

// 각 축의 라벨을 설정합니다.
plot.SetLegend("X 값", "Y 값");

// x축의 범위를 설정합니다.
줄거리.AppendExtra("xrange 설정 [-6:+6]");

// 데이터세트를 인스턴스화하고 제목을 설정한 다음 포인트를
// 연결선을 따라 그려집니다.
Gnuplot2dDataset 데이터세트;
데이터세트.SetTitle(dataTitle);
데이터 세트.SetStyle(Gnuplot2dDataset::LINES_POINTS);

더블엑스;
이중 y;

// 2D 데이터세트를 생성합니다.
(x = -5.0; x <= +5.0; x += 1.0)
{
// 2차원 곡선 계산
//
// 2
// y = x .
//
y = x * x;

// 이 점을 추가합니다.
데이터세트.추가(x, y);
}

// 플롯에 데이터세트를 추가합니다.
플롯.AddDataset(데이터세트);

// 플롯 파일을 엽니다.
ofstream 플롯파일(plotFileName.c_str());

// 플롯 파일을 작성합니다.
플롯.GenerateOutput(plotFile);

// 플롯 파일을 닫습니다.
플롯파일.닫기();

An 예시 2차원 음모 오류
x 및 y 방향의 오차 막대가 있는 다음 2차원 플롯
[이미지]

gnuplot-example.cc의 다음 코드를 사용하여 생성되었습니다.

네임 스페이스를 사용하여 표준;

string fileNameWithNoExtension = "plot-2d-with-error-bars";
문자열 그래픽파일 이름 = fileNameWithNoExtension + ".png";
stringplotFileName = fileNameWithNoExtension + ".plt";
stringplotTitle = "오차 막대가 있는 2차원 플롯";
string dataTitle = "오차 막대가 있는 2차원 데이터";

// 플롯을 인스턴스화하고 제목을 설정합니다.
Gnuplot 플롯(graphicsFileName);
플롯.SetTitle(plotTitle);

// 플롯 파일이 생성될 그래픽 파일을 만듭니다.
// Gnuplot과 함께 사용되며 PNG 파일입니다.
플롯.SetTerminal("png");

// 각 축의 라벨을 설정합니다.
plot.SetLegend("X 값", "Y 값");

// x축의 범위를 설정합니다.
줄거리.AppendExtra("xrange 설정 [-6:+6]");

// 데이터세트를 인스턴스화하고 제목을 설정한 다음 포인트를
// 연결선 없이 그려졌습니다.
Gnuplot2dDataset 데이터세트;
데이터세트.SetTitle(dataTitle);
데이터 세트.SetStyle(Gnuplot2dDataset::POINTS);

// 데이터세트의 x 방향과 y 방향 모두에 오류 막대가 있도록 만듭니다.
데이터세트.SetErrorBars(Gnuplot2dDataset::XY);

더블엑스;
이중 xErrorDelta;
이중 y;
이중 yErrorDelta;

// 2D 데이터세트를 생성합니다.
(x = -5.0; x <= +5.0; x += 1.0)
{
// 2차원 곡선 계산
//
// 2
// y = x .
//
y = x * x;

// x 방향의 불확실성을 일정하게 만들고
// y 방향의 불확실성은
// y의 값.
xErrorDelta = 0.25;
yErrorDelta = 0.1 * y;

// x와 y 모두에 불확실성이 있는 이 점을 추가합니다.
// 방향.
데이터세트.추가(x, y, xErrorDelta, yErrorDelta);
}

// 플롯에 데이터세트를 추가합니다.
플롯.AddDataset(데이터세트);

// 플롯 파일을 엽니다.
ofstream 플롯파일(plotFileName.c_str());

// 플롯 파일을 작성합니다.
플롯.GenerateOutput(plotFile);

// 플롯 파일을 닫습니다.
플롯파일.닫기();

An 예시 3차원 음모
다음 3차원 플롯
[이미지]

gnuplot-example.cc의 다음 코드를 사용하여 생성되었습니다.

네임 스페이스를 사용하여 표준;

string fileNameWithNoExtension = "plot-3d";
문자열 그래픽파일 이름 = fileNameWithNoExtension + ".png";
stringplotFileName = fileNameWithNoExtension + ".plt";
stringplotTitle = "3차원 플롯";
string dataTitle = "3차원 데이터";

// 플롯을 인스턴스화하고 제목을 설정합니다.
Gnuplot 플롯(graphicsFileName);
플롯.SetTitle(plotTitle);

// 플롯 파일이 생성될 그래픽 파일을 만듭니다.
// Gnuplot과 함께 사용되며 PNG 파일입니다.
플롯.SetTerminal("png");

// x축을 중심으로 플롯을 30도 회전한 다음
// 새로운 z축을 기준으로 120도를 그립니다.
줄거리.AppendExtra("보기 30, 120, 1.0, 1.0 설정");

// z축의 영점이 x축과 y축 평면에 있도록 만듭니다.
줄거리.AppendExtra("틱레벨 0 설정");

// 각 축의 라벨을 설정합니다.
plot.AppendExtra("xlabel 'X 값' 설정");
줄거리.AppendExtra("ylabel 'Y 값' 설정");
plot.AppendExtra("zlabel 'Z 값' 설정");

// x축과 y축의 범위를 설정합니다.
줄거리.AppendExtra("xrange 설정 [-5:+5]");
줄거리.AppendExtra("yrange 설정 [-5:+5]");

// 데이터세트를 인스턴스화하고 제목을 설정한 다음 포인트를
// 선으로 연결됩니다.
Gnuplot3dDataset 데이터세트;
데이터세트.SetTitle(dataTitle);
데이터 세트.SetStyle("라인 포함");

더블엑스;
이중 y;
더블 z;

// 3D 데이터세트를 생성합니다.
(x = -5.0; x <= +5.0; x += 1.0)
{
(y = -5.0; y <= +5.0; y += 1.0)
{
// 3차원 표면 계산
//
// 2 2
// z = x * y .
//
z = x * x * y * y;

// 이 점을 추가합니다.
데이터 세트.추가(x, y, z);
}

// 각 x 값의 데이터 끝에는 빈 줄이 필요합니다.
// 3D 표면 그리드가 작동할 지점입니다.
데이터세트.AddEmptyLine();
}

// 플롯에 데이터세트를 추가합니다.
플롯.AddDataset(데이터세트);

// 플롯 파일을 엽니다.
ofstream 플롯파일(plotFileName.c_str());

// 플롯 파일을 작성합니다.
플롯.GenerateOutput(plotFile);

// 플롯 파일을 닫습니다.
플롯파일.닫기();

사용 Python 달리기 NS-3
Python 바인딩을 사용하면 C++ 코드를 NS-3 Python에서 호출됩니다.

이 장에서는 실행할 수 있는 Python 스크립트를 만드는 방법을 보여줍니다. NS-3 또한
C++용 Python 바인딩을 만드는 프로세스 NS-3 기준 치수.

개요
Python 바인딩의 목표 NS-3 두 배입니다 :

1. 프로그래머가 Python으로 완전한 시뮬레이션 스크립트를 작성할 수 있도록 허용합니다(-
http://www.python.org);

2. 새로운 모델의 프로토타입을 제작합니다(예: 라우팅 프로토콜).

당분간 바인딩의 주요 초점은 첫 번째 목표이지만 두 번째 목표는 다음과 같습니다.
목표도 결국 지원될 것입니다. Python 바인딩 NS-3 개발 중이다.
PyBindGen이라는 새로운 도구를 사용하여(http://code.google.com/p/pybindgen).

An 예시 Python 스크립트 실행 NS-3
다음은 Python으로 작성되고 실행되는 몇 가지 예제 코드입니다. NS-3, 라고 쓰여 있다
C++에서. 이 Python 예제는 다음에서 찾을 수 있습니다. 예제/튜토리얼/first.py:

ns.applications 가져오기
ns.core 가져오기
ns.internet 가져오기
ns.network 가져오기
ns.point_to_point 가져오기

ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO)
ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO)

노드 = ns.network.NodeContainer()
노드.생성(2)

pointToPoint = ns.point_to_point.PointToPointHelper()
pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps"))
pointToPoint.SetChannelAttribute("지연", ns.core.StringValue("2ms"))

장치 = pointToPoint.Install(노드)

스택 = ns.internet.InternetStackHelper()
스택.설치(노드)

주소 = ns.internet.Ipv4AddressHelper()
address.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0"))

인터페이스 = 주소.할당(장치);

에코서버 = ns.applications.UdpEchoServerHelper(9)

serverApps = echoServer.설치(노드.가져오기(1))
serverApps.Start(ns.core.Seconds(1.0))
serverApps.Stop(ns.core.Seconds(10.0))

echoClient = ns.applications.UdpEchoClientHelper(인터페이스.GetAddress(1), 9)
echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(1))
echoClient.SetAttribute("간격", ns.core.TimeValue(ns.core.Seconds (1.0)))
echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(1024))

clientApps = echoClient.설치(노드.가져오기(0))
clientApps.Start(ns.core.Seconds(2.0))
clientApps.Stop(ns.core.Seconds(10.0))

ns.core.Simulator.Run()
ns.core.Simulator.Destroy()

달리는 Python 스크립트
waf에는 ns3를 찾기 위해 Python 경로를 자동으로 업데이트하는 몇 가지 옵션이 포함되어 있습니다.
기준 치수. 예제 프로그램을 실행하려면 waf를 사용하여 이를 처리하는 두 가지 방법이 있습니다. 하나
waf 쉘을 실행하는 것입니다. 예:

$ ./waf --쉘
$ 파이썬 예제/무선/mixed-wireless.py

다른 하나는 --pyrun 옵션을 사용하여 waf하는 것입니다.

$ ./waf --pyrun 예제/무선/mixed-wireless.py

C 디버거에서 Python 스크립트를 실행하려면 다음 안내를 따르세요.

$ ./waf --쉘
$ gdb --args python 예제/무선/mixed-wireless.py

호출하는 Python 스크립트를 실행하려면 NS-3 그 경로는 다음과 같습니다.
/path/to/your/example/my-script.py다음을 수행하십시오.

$ ./waf --쉘
$ 파이썬 /path/to/your/example/my-script.py

주의 사항
Python 바인딩 NS-3 작업이 진행 중이며 일부 제한사항이 알려져 있습니다.
개발자. 이러한 제한 사항 중 일부(전부는 아님)가 여기에 나열되어 있습니다.

불완전한 적용 범위
우선, Python에서는 API가 100% 지원되지 않는다는 점을 명심하세요. 일부
이유는 다음과 같습니다:

1. 일부 API에는 포인터가 포함되어 있어 어떤 종류의 메모리인지 알아야 합니다.
의미 전달(누가 어떤 메모리를 소유하는지). 그러한 지식은 기능의 일부가 아닙니다.
서명이 있으며 문서화되거나 문서화되지 않은 경우도 있습니다. 주석은
해당 기능을 바인딩하는 데 필요합니다.

2. 때때로 아직 알려지지 않은 특이한 기본 데이터 유형이나 C++ 구조가 사용됩니다.
PyBindGen에서 지원됩니다.

3. GCC-XML은 인스턴스화되지 않는 한 템플릿 기반 클래스를 보고하지 않습니다.

충분한 시간, 인내심, 전문 지식이 제공된다면 누락된 API의 대부분을 래핑할 수 있습니다.
버그 보고서가 제출되면 포장될 가능성이 높습니다. 그러나 버그 보고서를 제출하지 마십시오.
"바인딩이 불완전하다"고 말하는 이유는 100% 완성할 수 있는 인력이 없기 때문입니다.
바인딩.

매출 상승 생성자
매출 상승 생성자 PyBindGen에서는 아직 완전히 지원되지 않으며 항상 다음과 같이 작동합니다.
API를 Python으로 변환할 때 명시적인 생성자. 예를 들어 C++에서는 다음을 수행할 수 있습니다.
이:

Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase("192.168.0.0", "255.255.255.0");
ipAddrs.Assign(backboneDevices);

Python에서는 당분간 다음을 수행해야 합니다.

IPAddrs = ns3.Ipv4AddressHelper()
ipAddrs.SetBase(ns3.Ipv4Address("192.168.0.0"), ns3.Ipv4Mask("255.255.255.0"))
ipAddrs.Assign(백본장치)

CommandLine
명령줄::추가값() Python에서는 Python에서와 다르게 작동합니다. NS-3. 파이썬에서는
첫 번째 매개변수는 명령줄 옵션 이름을 나타내는 문자열입니다. 옵션이 있을 때
설정되면 옵션 이름과 동일한 이름의 속성이 명령줄()
물체. 예:

NUM_NODES_SIDE_DEFAULT = 3

cmd = ns3.CommandLine()

cmd.NumNodesSide = 없음
cmd.AddValue("NumNodesSide", "그리드 측 노드 수(총 노드 수는 이 숫자의 제곱이 됩니다)")

cmd.Parse(argv)

[...]

cmd.NumNodesSide가 None인 경우:
num_nodes_side = NUM_NODES_SIDE_DEFAULT
그밖에:
num_nodes_side = int(cmd.NumNodesSide)

트레이싱
콜백 기반 추적은 아직 Python에 대해 제대로 지원되지 않습니다. NS-3 API는 다음을 수행해야 합니다.
이를 지원하기 위해 제공됩니다.

Pcap 파일 쓰기는 일반 API를 통해 지원됩니다.

Ascii 추적이 지원됩니다. NS-3.4 Python으로 변환된 일반 C++ API를 통해.
그러나 ASCII 추적에서는 ASCII로 전달하기 위해 ostream 객체를 생성해야 합니다.
추적 방법. Python에서는 C++ std::ofstream이 최소한으로 래핑되었습니다.
이것. 예를 들어:

ascii = ns3.ofstream("wifi-ap.tr") # 파일 생성
ns3.YansWifiPhyHelper.EnableAsciiAll(ascii)
ns3.시뮬레이터.실행()
ns3.Simulator.Destroy()
ascii.close() # 파일을 닫습니다.

한 가지 주의할 점은 파일 객체가 가비지 수집되는 것을 허용해서는 안 된다는 것입니다. NS-3
아직도 사용하고 있습니다. 즉, 위의 'ascii' 변수는 허용되어서는 안 됩니다.
범위를 벗어나면 프로그램이 중단됩니다.

Cygwin에서 한정
Python 바인딩은 Cygwin에서 작동하지 않습니다. 이는 gccxml 버그 때문입니다.

cygwin 내에서 API 정의를 다시 스캔하면 문제를 해결할 수 있습니다.
환경(./waf --python-scan). 그러나 가장 가능성 있는 해결책은 아마도 다음과 같습니다.
CygWin에서 Python 바인딩을 비활성화합니다.

Windows에서 Python 바인딩에 정말로 관심이 있다면 mingw 및 기본을 사용하여 빌드해 보세요.
대신 파이썬. 또는 Python 바인딩 없이 빌드하려면 다음에서 Python 바인딩을 비활성화하세요.
구성 단계:

$ ./waf 구성 --disable-python

Python 바인딩
현재 Python 바인딩에는 두 가지 종류가 있습니다. NS-3:

1. 모놀리식 바인딩에는 모든 모듈에 대한 API 정의가 포함되어 있으며 다음에서 찾을 수 있습니다.
단일 디렉토리, 바인딩/파이썬.

2. 모듈형 바인딩에는 단일 모듈에 대한 API 정의가 포함되어 있으며 각 모듈에서 찾을 수 있습니다.
모듈의 바인딩 디렉토리.

Python 바인딩 워크 플로우
Python 바인딩이 처리되는 프로세스는 다음과 같습니다.

1. 개발자는 주기적으로 GCC-XML(http://www.gccxml.org) 기반 API 스캐닝
스캔한 API 정의를 다음과 같이 저장하는 스크립트 바인딩/python/ns3_module_*.py 파일
또는 각 모듈의 Python 파일로 바인딩 예배 규칙서. 이 파일은 다음 위치에 보관됩니다.
메인 버전 관리 NS-3 저장소;

2. 다른 개발자는 저장소를 복제하고 이미 스캔한 API 정의를 사용합니다.

3. 구성 시 NS-3, pybindgen이 아직 다운로드되지 않은 경우 자동으로 다운로드됩니다.
설치되었습니다. 출시된 NS-3 tarball은 pybindgen의 복사본을 제공합니다.

Python 바인딩 컴파일에 문제가 발생하고 이를 무시하고 싶은 경우
C++로 넘어가면 다음을 사용하여 Python을 비활성화할 수 있습니다.

$ ./waf --비활성화-파이썬

명령 for 처리 신제품 파일 or 변경 API의의
그래서 당신은 기존을 변경하고 있습니다 NS-3 API와 Python 바인딩이 더 이상 컴파일되지 않습니까? 하다
절망하지 말고 바인딩을 다시 스캔하여 변경 사항을 반영하는 새 바인딩을 만들 수 있습니다.
부터 NS-3 API.

모놀리식 바인딩을 사용하는지 아니면 모듈식 바인딩을 사용하는지에 따라 아래 설명을 참조하세요.
Python 바인딩을 다시 검색하는 방법을 알아보세요.

단단히 짜여 하나로 되어 있는 Python 바인딩
스캐닝 전에, 단단히 짜여 하나로 되어 있는 Python 바인딩
모놀리식 Python 바인딩을 스캔하려면 다음을 수행합니다.

$ ./waf --python-scan

회사조직 of 전에, 단단히 짜여 하나로 되어 있는 Python 바인딩
모놀리식 Python API 정의는 다음과 같이 구성됩니다. 각각 NS-3 모듈
, 파일 바인딩/python/ns3_module_ .py API를 설명합니다. 그 각각
파일에는 3가지 최상위 기능이 있습니다:

1. def 레지스터_유형(기준 치수)(): 이 함수는 새로운 유형을 등록하는 일을 담당합니다(예:
해당 모듈에 정의된 C++ 클래스, 열거형)

2. def 레지스터_방법(기준 치수)(): 이 함수는 각 클래스에 대해 호출됩니다. , 또 다른
함수 Register_methods_Ns3 (기준 치수). 후자의 함수는 메소드를 추가합니다.
각 클래스에 대한 정의;

3. def 레지스터_함수(기준 치수)(): 이 함수는 레지스터 NS-3 에 속하는 기능
그 모듈.

모듈 Python 바인딩
살펴보기
ns 3.11부터 모듈식 바인딩이 이전 모놀리식 바인딩과 병행하여 추가되고 있습니다.
바인딩.

새로운 Python 바인딩은 이전의 'ns3' 대신 'ns' 네임스페이스에 생성됩니다.
바인딩. 예:

ns.network 가져오기 노드에서
n1 = 노드()

모듈식 Python 바인딩 사용:

1. 각각에 대해 별도의 Python 확장 모듈이 하나씩 있습니다. NS-3 기준 치수;

2. API 정의(apidef) 검색은 ns-모듈 단위로 수행됩니다.

3. 각 모듈의 apidefs 파일은 모듈의 '바인딩' 하위 디렉터리에 저장됩니다.
예배 규칙서;

스캐닝 전에, 모듈 Python 바인딩
예를 들어 핵심 모듈에 대한 모듈식 Python 바인딩을 스캔하려면 다음을 수행합니다.

$ ./waf --apiscan=코어

모든 모듈에 대한 모듈식 Python 바인딩을 스캔하려면 다음을 수행하세요.

$ ./waf --apiscan=모두

만들기 a 신제품 모듈
새 모듈을 추가하는 경우 Python 바인딩은 계속 컴파일되지만 컴파일되지는 않습니다.
새 모듈을 덮습니다.

새 모듈을 다루려면 바인딩/python/ns3_module_ .py 파일
이전 섹션에서 설명한 것과 유사하게 변수에 등록합니다.
로컬_모듈() in 바인딩/python/ns3modulegen.py

첨가 모듈 바인딩 A 현존하는 모듈
기존 바인딩에 모듈식 바인딩에 대한 지원을 추가하려면 NS-3 모듈에 다음을 추가하기만 하면 됩니다.
wscript build() 함수에 다음 줄을 추가합니다.

bld.ns3_python_bounds()

회사조직 of 전에, 모듈 Python 바인딩
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 소스/ /바인딩 디렉토리에는 다음 파일이 포함될 수 있으며 그 중 일부는
선택 과목:

· callbacks_list.py: 스캔한 파일이므로 만지지 마세요. 다음 목록이 포함되어 있습니다.
스캔된 헤더에서 콜백<...> 템플릿 인스턴스가 발견되었습니다.

· modulegen__gcc_LP64.py: 스캔한 파일이므로 만지지 마세요. 스캔된 API 정의
GCC의 경우 LP64 아키텍처(64비트)

· modulegen__gcc_ILP32.py: 스캔한 파일이므로 만지지 마세요. 스캔된 API 정의
GCC의 경우 ILP32 아키텍처(32비트)

· modulegen_customizations.py: 선택적으로 이 파일을 추가하여 사용자 정의할 수 있습니다.
pybindgen 코드 생성

· 스캔 헤더.h: 선택적으로 이 파일을 추가하여 스캔할 헤더 파일을 사용자 정의할 수 있습니다.
모듈의 경우. 기본적으로 이 파일은 ns3/ 대신 검사됩니다. -모듈.h.
일반적으로 첫 번째 문은 #include "ns3/ -module.h" 및 기타
템플릿 인스턴스화를 강제하는 것;

· module_helpers.cc: Python에 연결하기 위해 이와 같은 추가 파일을 추가할 수 있습니다.
확장 모듈이지만 wscript에 등록되어야 합니다. 보다
이를 수행하는 방법에 대한 예는 src/core/wscript입니다.

· .py: 이 파일이 존재하면 ns3의 "프론트엔드" Python 모듈이 됩니다.
모듈, 확장 모듈(.so 파일)은 _가 됩니다. .그래서 대신 .그래서.
그만큼 .py 파일은 모듈에서 모든 기호를 가져와야 합니다. (이게 더
생각보다 까다롭습니다. 예를 보려면 src/core/bounds/core.py를 참조하세요.) 그런 다음 추가할 수 있습니다.
몇 가지 추가 순수 Python 정의.

더 보기 정보 for 개발자
개발자이고 이에 대한 추가 정보가 필요한 경우 NS-3의 Python 바인딩에 대해서는 다음을 참조하세요.
Python 바인딩 위키 페이지.

테스트
살펴보기
이 문서는 테스트 및 검증에 관한 것입니다. NS-3 소프트웨어.

이 문서는

· 용어 및 소프트웨어 테스팅에 대한 배경(2장);

· ns-3 테스트 프레임워크에 대한 설명(3장)

· 모델 개발자 또는 새로운 모델 기여자를 위한 테스트 작성 방법 가이드(장
4);

간단히 말해서 처음 세 장은 NS 개발자와 기여자가 읽어야 할 내용입니다.
테스트 코드와 검증된 프로그램을 기여하는 방법과 나머지 부분을 이해해야 합니다.
문서의 일부는 사람들이 선택한 모델의 어떤 측면에 대해 보고할 수 있는 공간을 제공합니다.
검증되었습니다.

배경
5월 be 건너 뛴 by 독자들 익숙한 전에, 기초 of 소프트웨어 테스트.

결함 없는 소프트웨어를 작성하는 것은 어려운 일입니다. 에는 많은 차원이 있습니다.
문제가 있으며 서로 다른 용어가 무엇을 의미하는지에 대해 많은 혼란이 있습니다.
다른 맥락. 우리는 약간의 시간을 들여 다음 항목을 검토하는 것이 가치 있다고 판단했습니다.
주제를 정하고 몇 가지 용어를 정의합니다.

소프트웨어 테스팅은 다음과 같이 프로그램을 실행하는 프로세스로 느슨하게 정의될 수 있습니다.
오류를 찾아내려는 의도. 소프트웨어 테스팅에 관한 토론에 들어가면
사람이 할 수 있는 다양한 사고방식이 있다는 것이 곧 명백해집니다.
주제에 접근하세요.

예를 들어 프로세스를 다음과 같은 광범위한 기능 범주로 나눌 수 있습니다.
'정확성 테스트', '성능 테스트', '강건성 테스트', '보안'
테스트.'' 문제를 보는 또 다른 방법은 수명 주기를 기준으로 하는 것입니다. '요구 사항 테스트'
'설계 테스트', '인수 테스트', '유지보수 테스트' 또 다른 관점
테스트된 시스템의 범위에 따릅니다. 이 경우 '단위 테스트'라고 말할 수 있습니다.
'컴포넌트 테스트', '통합 테스트', '시스템 테스트' 이러한 용어는 다음과 같습니다.
또한 어떤 방식으로든 표준화되지 않았으므로 '유지 관리 테스트' 및 '회귀'
테스트''는 같은 의미로 들릴 수 있습니다. 또한 이러한 용어는 종종 잘못 사용됩니다.

소프트웨어 테스팅에는 다양한 철학적 접근 방식이 있습니다. 을 위한
예를 들어 일부 조직에서는 실제로 구현하기 전에 테스트 프로그램 작성을 옹호합니다.
원하는 소프트웨어를 선택하여 '테스트 중심 개발'을 실현합니다. 일부 조직에서는 이를 옹호합니다.
가능한 한 빨리 고객 관점에서 테스트하고,
민첩한 개발 프로세스: '조기 테스트하고 자주 테스트'. 이는 때때로 호출됩니다.
'애자일 테스팅'. 모든 테스트에 대해 적어도 하나의 접근 방식이 있는 것 같습니다.
개발 방법론.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 프로젝트는 이러한 프로세스 중 하나를 옹호하는 사업에 속하지 않지만
프로젝트 전체에는 테스트 프로세스를 알리는 데 도움이 되는 요구 사항이 있습니다.

모든 주요 소프트웨어 제품과 마찬가지로 NS-3 반드시 갖춰야 할 여러 가지 특성을 가지고 있습니다.
성공할 제품. 테스트 관점에서 볼 때 이러한 특성 중 일부는
다루는 것은 NS-3 '올바른', '견고한', '성능이 뛰어난'' 그리고
''유지보수 가능'' 이상적으로는 이러한 각 차원에 대한 측정항목이 있어야 합니다.
제품이 기대에 부응하지 못하는 경우를 확인하기 위해 테스트를 통해 확인/
요구 사항.

단정
테스트의 본질적인 목적은 소프트웨어의 일부가 작동하는지 확인하는 것입니다.
''맞습니다.'' NS-3 이는 우리가 무언가를 시뮬레이션하면 시뮬레이션이 다음과 같아야 함을 의미합니다.
일부 물리적 개체나 프로세스를 지정된 정확도로 충실하게 표현하고
정도.

정확성을 볼 수 있는 두 가지 관점이 있다는 것이 밝혀졌습니다.
특정 모델이 해당 사양에 따라 구현되었는지 확인하는 것은
일반적으로 호출 확인. 모형이 적합하다고 판단하는 과정
그 의도된 용도는 일반적으로 확인.

검증 and 확인
컴퓨터 모델은 어떤 것의 수학적 또는 논리적 표현입니다. 그것은 할 수 있다
차량, 코끼리를 나타냅니다(참조: 데이비드 하렐의 이야기 about 모델링 an 코끼리 at
SIMU도구 2009또는 네트워킹 카드. 모델은 글로벌 프로세스와 같은 프로세스를 나타낼 수도 있습니다.
온난화, 고속도로 교통 흐름 또는 네트워킹 프로토콜 사양. 모델은 다음과 같습니다.
논리적 프로세스 사양을 완전히 충실하게 표현하지만
반드시 물리적 객체나 프로세스를 완전히 시뮬레이션할 수는 없습니다. 대부분의 경우,
계산적으로 시뮬레이션을 수행하기 위해 모델에 여러 가지 단순화가 수행됩니다.
다루기 쉬운.

모든 모델에는 목표 체계 시뮬레이션을 시도하고 있다는 것입니다. 첫 번째 단계
시뮬레이션 모델을 만드는 것은 이 대상 시스템과 세부 수준을 식별하고
시뮬레이션이 재현하고자 하는 정확도. 논리적 프로세스의 경우,
대상 시스템은 'RFC 793에 정의된 TCP'로 식별될 수 있습니다. 이 경우
아마도 RFC를 완전하고 충실하게 재현하는 모델을 만드는 것이 바람직할 것입니다.
793. 물리적 프로세스의 경우 이는 불가능합니다. 예를 들어, 당신이
무선 네트워킹 카드를 시뮬레이션하고 싶을 경우, 필요한 것을 결정할 수 있습니다.
802.11 사양의 정확한 MAC 수준 구현과 [...] 그다지 느리지 않은
802.11a 사양의 PHY 레벨 모델입니다.''

이 작업이 완료되면 대상 시스템의 추상 모델을 개발할 수 있습니다. 이것은
일반적으로 복잡성과 리소스 요구 사항 간의 균형을 관리하는 연습입니다.
그리고 정확성. 추상적인 모델을 개발하는 과정이 호출되었습니다. 모델
자격 문헌에서. TCP 프로토콜의 경우 이 프로세스는 다음과 같은 결과를 가져옵니다.
완전히 구현될 개체, 상호 작용 및 동작 모음을 위한 디자인
RFC 793 NS-3. 무선 카드의 경우 이 프로세스로 인해 여러 가지 결과가 발생합니다.
물리적 계층을 시뮬레이션하고 네트워크 장치를 설계할 수 있는 절충안
원하는 개체, 상호 작용 및 동작과 함께 ns-3용 채널을 제공합니다.

이 추상 모델은 다음으로 개발됩니다. NS-3 추상을 구현하는 모델
컴퓨터 프로그램으로 모델을 만듭니다. 구현이 동의하도록 하는 프로세스
추상 모델이 호출됩니다. 모델 확인 문헌에서.

지금까지의 프로세스는 개방형 루프입니다. 남은 것은 주어진 ns-3이 다음과 같이 결정되는 것입니다.
모델은 어떤 현실과 어느 정도 연관되어 있습니다. 즉, 모델은 현실을 정확하게 표현한다는 것입니다.
논리적 프로세스이든 물리적 개체이든 실제 시스템입니다.

시뮬레이션 모델을 사용하여 실제 시스템이 어떻게 진행되는지 예측하려는 경우
행동하려면 결과를 믿을 만한 어떤 이유가 있어야 합니다. 즉, 믿을 수 있습니까?
모델로부터의 추론은 실제 시스템에 대한 정확한 예측으로 변환됩니다.
ns-3 모델 동작이 원하는 대상 시스템과 일치하도록 하는 프로세스
모델 검증 프로세스에 의해 정의된 동작을 이라고 합니다. 모델 확인 인간을
문학. TCP 구현의 경우 다음의 동작을 비교할 수 있습니다.
모델을 검증하기 위해 ns-3 TCP 모델을 일부 참조 구현에 적용하십시오. ~ 안에
무선 물리 계층 시뮬레이션의 경우 다음의 동작을 비교할 수 있습니다.
통제된 환경에서 모델을 실제 하드웨어와 동일하게 만들고,

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 테스트 환경은 모델 검증과 검증을 모두 허용하는 도구를 제공합니다.
테스트하고 검증 결과 공개를 장려합니다.

견고성
견고성은 스트레스나 환경 변화를 견딜 수 있는 품질입니다.
입력이나 계산 등을 처리할 수 있다면 시스템이나 설계는 '견고'합니다.
기능 손실을 최소화하면서 변경됩니다.

이러한 종류의 테스트는 일반적으로 특정 초점을 두고 수행됩니다. 예를 들어, 다음과 같은 시스템
전체가 다양한 시스템 구성에서 실행될 수 있음을 보여줍니다.
많은 환경에서 올바르게 수행됩니다.

시스템은 또한 다음과 같은 생성으로 인해 용량에 가깝거나 그 이상으로 작동함으로써 스트레스를 받을 수 있습니다.
또는 다양한 종류의 자원 고갈을 시뮬레이션합니다. 이런 종류의 테스트를 테스트라고 합니다.
''스트레스 테스트.''

시스템과 그 구성 요소는 소위 '클린 테스트'에 노출될 수 있습니다.
긍정적인 결과 - 즉 시스템이 큰 변화에 반응하여 올바르게 작동한다는 것입니다.
예상 구성의 변형.

시스템과 그 구성 요소는 입력을 제공하는 '더티 테스트'에 노출될 수도 있습니다.
예상 범위를 벗어났습니다. 예를 들어, 모듈이 XNUMX으로 끝나는 문자열을 예상하는 경우
정수 표현, 더티 테스트는 종료되지 않은 무작위 문자열을 제공할 수 있습니다.
예상치 못한 입력으로 인해 시스템이 충돌하지 않는지 확인하기 위해 문자를 사용합니다.
안타깝게도 이러한 '더러운' 입력을 감지하고 예방 조치를 취하여
시스템이 치명적으로 실패하지 않으면 엄청난 양의 개발 오버헤드가 필요할 수 있습니다.
개발 시간을 단축하기 위해 프로젝트 초기에 다음과 같은 결정을 내렸습니다.
매개변수 검증 및 오류 처리 양을 최소화합니다. NS-3 코드베이스. 을 위한
이런 이유로 우리는 더티 테스트에 많은 시간을 소비하지 않습니다.
우리가 내린 디자인 결정의 결과.

우리는 그것을 보여주고 싶습니다. NS-3 소프트웨어는 일부 조건에서 작동합니다. 우리
이 범위를 조금 좁히려면 몇 가지 정의를 빌려보세요. 그만큼 도메인 of 적용 가능성 is
모델이 테스트된 일련의 규정된 조건을 다음과 비교합니다.
가능한 한 현실에 부합하고, 사용하기에 적합하다고 판단됩니다. 그만큼 범위 of 는 Teledyne LeCroy 오실로스코프 및 LSA-XNUMX 시리즈 임베디드 신호 분석기가
적용 영역 내에서 컴퓨터화된 모델과 현실 사이의 일치.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 테스트 환경은 테스트를 설정하고 실행할 수 있는 도구를 제공합니다.
여러 시스템(buildbot)에 걸쳐 환경을 구축하고 정리를 장려하는 클래스를 제공합니다.
예상되는 '적용 영역'에 걸쳐 시스템 작동을 검증하기 위한 테스트
그리고 ''정확도 범위''입니다.

성능
좋아요, 'performant'는 실제 영어 단어가 아닙니다. 그러나 그것은 매우 간결한 신조어이다.
그것은 우리가 원하는 것을 설명하는 데 자주 사용됩니다. NS-3 될 것: 충분히 강력하고 빠르다
일을 끝내십시오.

이것은 실제로 소프트웨어 성능 테스트의 광범위한 주제에 관한 것입니다. 핵심 중 하나
수행되는 작업은 두 시스템을 비교하여 어느 시스템이 더 나은 성능을 발휘하는지 찾는 것입니다(참조
벤치마크). 이는 예를 들어 다음을 입증하는 데 사용됩니다. NS-3 기본적인 종류를 수행할 수 있습니다.
최소한 경쟁 도구만큼 빠른 속도로 시뮬레이션하거나
성능이 좋지 않은 시스템.

. NS-3 테스트 프레임워크를 통해 다양한 종류의 테스트 타이밍을 지원합니다.

유지 보수성
소프트웨어 제품은 유지 관리가 가능해야 합니다. 이것은 다시 말하지만 매우 광범위한 진술입니다.
테스트 프레임워크는 작업에 도움이 될 수 있습니다. 모델이 개발되고 검증되면
검증되면 전체 시스템에 대해 일련의 테스트를 반복적으로 실행하여 다음을 보장할 수 있습니다.
평생 동안 유효하고 검증된 상태로 유지됩니다.

시스템이 변경된 후 기능이 의도한 대로 작동하지 않는 경우
통합된 경우 일반적으로 a라고 합니다. 되돌아옴. 원래 회귀라는 용어는
이전에 수정된 버그가 다시 나타나도록 만든 변경 사항을 의미하지만 해당 용어는
기존 기능을 손상시키는 모든 종류의 변경을 설명하도록 진화했습니다. 많이있다
실제로 발생할 수 있는 회귀 유형.

A 지방의 되돌아옴 변경 사항이 변경된 구성 요소에 직접 영향을 미치는 것입니다. 을 위한
예를 들어, 메모리를 할당하고 해제하기 위해 구성 요소가 수정되었지만 오래된 포인터가 있는 경우
사용하면 구성 요소 자체가 실패합니다.

A 되돌아옴 하나의 구성 요소를 변경하면 기능이 중단되는 것입니다.
또 다른 구성 요소. 이는 묵시적이지만 인식할 수 없는 위반을 반영합니다.
구성 요소 간의 계약.

An 가면 되돌아옴 이전에 존재했던 버그가 발생하는 상황을 만드는 것입니다.
영향을 미치지 않던 정보가 갑자기 시스템에 노출됩니다. 이것은 운동만큼 간단할 수도 있다
처음으로 코드 경로를 작성했습니다.

A 성능 되돌아옴 시스템의 성능 요구 사항을 유발하는 것입니다.
침해당하다. 예를 들어, 반복될 수 있는 낮은 수준의 기능에서 일부 작업을 수행하는 경우
여러 번 갑자기 특정 관점에서 시스템을 사용할 수 없게 될 수 있습니다.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 테스트 프레임워크는 검증 및 검증에 사용되는 프로세스를 자동화하는 도구를 제공합니다.
가능한 회귀를 신속하게 식별하는 데 도움이 되도록 야간 테스트 스위트에서 코드를 확인하십시오.

지원 뼈대
ns-3은 시뮬레이션 코어 엔진, 모델 세트, 예제 프로그램 및 테스트로 구성됩니다.
시간이 지남에 따라 새로운 기여자가 모델, 테스트 및 예제를 제공합니다. Python 테스트 프로그램
test.py 테스트 실행 관리자 역할을 합니다. test.py 테스트 코드와 예제를 실행할 수 있습니다.
회귀를 찾고, 결과를 다양한 형태로 출력하고, 코드를 관리할 수 있습니다.
적용 범위 분석 도구. 그 위에 우리는 레이어 빌드봇 자동화된 빌드
다양한 시스템에서 테스트 프레임워크를 실행하여 견고성 테스트를 수행하는 로봇
다양한 구성 옵션이 있습니다.

빌드봇
ns-3 테스트의 최고 수준에는 빌드봇(빌드 로봇)이 있습니다. 당신이있는 경우
이 시스템이 익숙하지 않은 경우 http://djmitche.github.com/buildbot/docs/0.7.11/.
이것은 다음을 허용하는 오픈 소스 자동화 시스템입니다. NS-3 각각 재구축 및 테스트 예정
시간이 지나면 뭔가 바뀌었어요. 다양한 시스템에서 빌드봇을 실행함으로써 우리는
그것을 보장할 수 있다 NS-3 지원되는 모든 시스템에서 올바르게 빌드되고 실행됩니다.

사용자(및 개발자)는 일반적으로 다음 외에는 빌드봇 시스템과 상호 작용하지 않습니다.
테스트 결과에 관한 메시지를 읽어보세요. 다음 중 하나에서 오류가 감지된 경우
자동화된 빌드 및 테스트 작업을 수행하면 빌드봇이 ns 개발자
메일링 리스트. 이 이메일은 다음과 같습니다.

이메일에 표시된 전체 세부정보 URL에서 키워드를 검색할 수 있습니다. 실패한 and
를 선택합니다 표준 해당 단계에 대한 링크를 클릭하면 실패 이유를 확인할 수 있습니다.

오류가 없으면 빌드봇은 조용히 작업을 수행하며 시스템은 다음과 같은 작업을 수행합니다.
모든 것이 제대로 되었는지 확인하기 위해 매일 주기를 구축하고 테스트합니다.

Test.py
빌드봇은 Python 프로그램을 사용합니다. test.py, 모든 실행을 담당합니다.
테스트하고 결과 보고서를 사람이 읽을 수 있는 형식으로 수집합니다. 이 프로그램은
사용자와 개발자도 사용할 수 있습니다.

test.py 사용자가 테스트의 수와 종류를 지정할 수 있다는 점에서 매우 유연합니다.
달리다; 그리고 생성할 출력의 양과 종류도 마찬가지입니다.

실행하기 전에 test.py, 다음을 수행하여 ns3의 예제와 테스트가 구축되었는지 확인하세요.
다음과 같은

$ ./waf 구성 --enable-examples --enable-tests
$ ./와프

기본적으로, test.py 사용 가능한 모든 테스트를 실행하고 상태를 매우 간결하게 보고합니다.
형태. 명령 실행

$ ./test.py

여러 가지 결과가 발생합니다 PASS, 실패, 추락 or 버킷 종류에 따른 표시
실행된 테스트와 해당 표시 이름입니다.

Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리 입력 중
Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리를 종료합니다.
'빌드'가 성공적으로 완료되었습니다(0.939초).
실패: TestSuite ns3-wifi-전파-손실-모델
통과: TestSuite 개체 이름 서비스
통과: TestSuite pcap-file-object
통과: TestSuite ns3-tcp-cwnd
...
통과: TestSuite ns3-tcp-상호 운용성
PASS: csma-broadcast 예시
PASS: csma-멀티캐스트 예시

이 모드는 자신의 상태를 확인하려는 사용자가 사용하도록 고안되었습니다.
배포가 올바르게 작동하고 있는지 확인하려는 개발자가
그들이 변경한 사항으로 인해 회귀가 발생했습니다.

동작을 제어하는 ​​데 사용할 수 있는 다양한 옵션이 있습니다. test.py. 당신이 달리면
test.py --도움 다음과 같은 명령 요약이 표시됩니다.

사용법: test.py [옵션]

옵션 :
-h, --help 이 도움말 메시지를 표시하고 종료
-b BUILDPATH, --buildpath=BUILDPATH
ns-3이 빌드된 경로를 지정합니다(기본값은
현재 변형의 빌드 디렉터리)
-c 종류, --constrain=종류
테스트 종류에 따라 테스트 실행기를 제한합니다.
-e 예, --example=예
실행할 단일 예제를 지정합니다(상대 경로는 없음).
필요)
-g, --grind valgrind를 사용하여 테스트 스위트와 예제를 실행합니다.
-k, --kinds 사용 가능한 테스트 종류를 인쇄합니다.
-l, --list 알려진 테스트 목록을 인쇄합니다.
-m, --multiple 테스트 스위트 및 테스트의 여러 실패를 보고합니다.
가지 경우
-n, --nowaf 테스트를 시작하기 전에 waf를 실행하지 않습니다.
-p PYEXAMPLE, --pyexample=PYEXAMPLE
실행할 단일 Python 예제를 지정합니다(상대적 사용).
경로)
-r, --retain 모든 임시 파일을 유지합니다(일반적으로
삭제됨)
-s 테스트 스위트, --suite=테스트 스위트
실행할 단일 테스트 스위트 지정
-t 텍스트-파일, --text=텍스트-파일
TEXT-FILE.txt에 자세한 테스트 결과를 기록합니다.
-v, --verbose 진행 상황 및 정보 메시지 인쇄
-w HTML-파일, --web=HTML-FILE, --html=HTML-FILE
HTML-FILE.html에 자세한 테스트 결과를 기록합니다.
-x XML-FILE, --xml=XML-FILE
자세한 테스트 결과를 XML-FILE.xml에 기록

선택적 출력 스타일을 지정하면 해당 스타일에 대한 자세한 설명을 생성할 수 있습니다.
테스트 및 상태. 사용 가능한 스타일은 다음과 같습니다. 본문 and HTML. 빌드봇은 HTML을 선택합니다.
다음을 사용하여 야간 빌드에 대한 HTML 테스트 보고서를 생성하는 옵션

$ ./test.py --html=nightly.html

이 경우 'nightly.html''이라는 이름의 HTML 파일이 예쁜 요약과 함께 생성됩니다.
테스트가 완료되었습니다. 관심 있는 사용자는 '사람이 읽을 수 있는' 형식을 사용할 수 있습니다.
세부.

$ ./test.py --text=results.txt

위의 예에서 테스트 스위트는 NS-3 무선 장치 전파 손실
모델이 실패했습니다. 기본적으로 추가 정보는 제공되지 않습니다.

실패를 더 자세히 조사하기 위해, test.py 단일 테스트 스위트를 지정할 수 있습니다.
명령 실행

$ ./test.py --suite=ns3-wifi-전파-손실-모델

또는 동등하게

$ ./test.py -s ns3-wifi-전파-손실-모델

그 결과 단일 테스트 스위트가 실행됩니다.

실패: TestSuite ns3-wifi-전파-손실-모델

실패에 대한 자세한 정보를 찾으려면 출력 종류를 지정해야 합니다.
원하는. 예를 들어, 대부분의 사람들은 아마도 다음과 같은 텍스트 파일에 관심을 가질 것입니다.

$ ./test.py --suite=ns3-wifi-propagation-loss-models --text=results.txt

그러면 해당 단일 테스트 모음이 테스트 상태가 기록된 상태로 실행됩니다.
파일 ''results.txt''.

해당 파일에서 다음과 유사한 내용을 찾아야 합니다.

실패: 테스트 스위트 ''ns3-wifi-propagation-loss-models''(실제 0.02 사용자 0.01 시스템 0.00)
PASS: 테스트 케이스 "Check...Friis...model..."(실제 0.01 사용자 0.00 시스템 0.00)
FAIL: 테스트 케이스 "Check...Log Distance...model"(실제 0.01 사용자 0.01 시스템 0.00)
세부:
메시지: 예상치 못한 SNR 값을 얻었습니다.
조건: [실제로 실패한 것에 대한 긴 설명]
실제: 176.395년
한도: 176.407 +- 0.0005
파일: ../src/test/ns3wifi/propagation-loss-models-test-suite.cc
라인 : 360

테스트 스위트는 두 개의 테스트 케이스로 구성되어 있습니다. 첫 번째 테스트 케이스는 다음을 확인했습니다.
Friis 전파 손실 모델이 통과되었습니다. 두 번째 테스트 사례가 로그 확인에 실패했습니다.
거리 전파 모델. 이 경우 176.395의 SNR이 발견되었으며 테스트는
소수점 세 자리까지 올바른 값은 176.407이 될 것으로 예상됩니다. 구현한 파일
실패한 테스트와 실패를 유발한 코드 줄이 나열됩니다.

원하는 경우 다음을 사용하여 HTML 파일을 쉽게 작성할 수도 있습니다. --html option
상술 한 바와 같이.

일반적으로 사용자는 다운로드 후 모든 테스트를 적어도 한 번 실행합니다. NS-3 보장하기 위해
해당 환경이 올바르게 구축되었으며 올바른 결과를 생성하고 있습니다.
테스트 스위트에 따르면. 개발자는 일반적으로 이전과 이전에 테스트 스위트를 실행합니다.
회귀를 도입하지 않았는지 확인하기 위해 변경한 후
변화. 이 경우 개발자는 모든 테스트를 실행하지 않고 하위 집합만 실행하기를 원할 수 있습니다. 을 위한
예를 들어, 개발자는 만드는 동안 주기적으로 단위 테스트만 실행하기를 원할 수 있습니다.
저장소로 변경됩니다. 이 경우, test.py 유형을 제한하도록 지시할 수 있습니다.
특정 테스트 클래스에 대해 실행되는 테스트입니다. 다음 명령의 결과는 다음과 같습니다.
실행 중인 단위 테스트:

$ ./test.py --constrain=단위

마찬가지로 다음 명령을 실행하면 예제 연기 테스트만 실행됩니다.

$ ./test.py --constrain=단위

법적 종류의 제약 조건에 대한 빠른 목록을 보려면 해당 제약 조건을 나열하도록 요청할 수 있습니다.
다음 명령

$ ./test.py --종류

다음 목록이 표시됩니다.

Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리 입력 중
Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리를 종료합니다.
'빌드'가 성공적으로 완료되었습니다(0.939초)Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉터리를 입력하는 중입니다.
bvt: 빌드 확인 테스트(빌드가 성공적으로 완료되었는지 확인)
core: 모든 TestSuite 기반 테스트 실행(예제 제외)
예: 예(예제 프로그램이 성공적으로 실행되는지 확인하기 위해)
성능: 성능 테스트(시스템이 예상만큼 빠른지 확인)
시스템: 시스템 테스트(모듈 통합을 확인하기 위해 모듈에 걸쳐 있음)
단위: 단위 테스트(기본 기능을 확인하기 위한 모듈 내)

이러한 종류의 테스트는 모두 다음을 사용하여 제약 조건으로 제공될 수 있습니다. --강제 옵션을 선택합니다.

사용 가능한 모든 테스트 도구 모음의 빠른 목록을 보려면 해당 도구 모음을 요청할 수 있습니다.
나열되어 있습니다. 다음 명령은

$ ./test.py --목록

다음과 비슷하게 테스트 스위트 목록이 표시됩니다.

Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리 입력 중
Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리를 종료합니다.
'빌드'가 성공적으로 완료되었습니다(0.939초).
막대 그래프
ns3-wifi-간섭
ns3-tcp-cwnd
ns3-tcp-상호 운용성
견본
장치 메쉬 불꽃
장치-메쉬-dot11s
장치 메시
...
객체 이름 서비스
콜백
속성
설정
글로벌 가치
명령 줄
기본 난수
대상

나열된 제품군 중 하나를 사용하여 자체적으로 실행되도록 선택할 수 있습니다. --모음곡 옵션으로
위에 표시된.

테스트 스위트와 마찬가지로 다음을 사용하여 단일 C++ 예제 프로그램을 실행할 수 있습니다. --예시
옵션. 예제의 상대 경로는 포함될 필요가 없으며
C++ 예제용으로 빌드된 실행 파일에는 확장이 없습니다. 입장

$ ./test.py --example=udp-echo

그 결과 단일 예제가 실행됩니다.

PASS: 예제 예제/udp/udp-echo

다음을 사용하여 ns-3이 빌드된 디렉토리를 지정할 수 있습니다. --buildpath 옵션으로
다음과 같습니다.

$ ./test.py --buildpath=/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build/debug --example=wifi-simple-adhoc

다음을 사용하여 단일 Python 예제 프로그램을 실행할 수 있습니다. --pyexample 옵션. 참고
예제에 대한 상대 경로가 포함되어야 하며 Python 예제에는 상대 경로가 필요합니다.
확장. 입장

$ ./test.py --pyexample=examples/tutorial/first.py

그 결과 단일 예제가 실행됩니다.

통과: 예제 example/tutorial/first.py

Python 예제는 빌드되지 않으므로 ns-3이 있는 디렉터리를 지정할 필요가 없습니다.
그들을 운영하기 위해 만들어졌습니다.

일반적으로 예제 프로그램을 실행하면 많은 양의 추적 파일 데이터가 작성됩니다.
이는 일반적으로 배포판의 기본 디렉터리에 저장됩니다(예:
/홈/사용자/ns-3-dev). 언제 test.py 예제를 실행하면 정말 전혀 걱정하지 않습니다.
추적 파일로. 단지 예제를 빌드하고 실행할 수 있는지 확인하고 싶을 뿐입니다.
오류 없이. 이 경우이기 때문에 추적 파일은
/tmp/unchecked-추적 예배 규칙서. 위의 예제를 실행하면 다음을 찾을 수 있습니다.
관련된 UDP-echo.tr and udp-에코-n-1.pcap 거기에 파일.

사용 가능한 예제 목록은 다음의 ''examples'' 디렉토리 내용에 따라 정의됩니다.
배포. 다음을 사용하여 실행할 예제를 선택하면 --예시 선택권,
test.py 예제가 구성되었는지 여부를 결정하려고 시도하지 않습니다.
그냥 실행을 시도하고 시도 결과를 보고합니다.

인셀덤 공식 판매점인 test.py 실행되면 기본적으로 먼저 시스템이 완전히 작동되었는지 확인합니다.
세워짐. 이것을 선택하면 패배할 수 있습니다. --nowaf 옵션을 선택합니다.

$ ./test.py --목록 --nowaf

다음과 유사하게 현재 구축된 테스트 모음 목록이 표시됩니다.

ns3-wifi-전파-손실-모델
ns3-tcp-cwnd
ns3-tcp-상호 운용성
pcap-파일-객체
객체 이름 서비스
난수 생성기

가 없다는 점에 유의하세요. 와프 메시지를 작성합니다.

test.py 또한 valgrind에서 테스트 스위트 및 예제 실행을 지원합니다. 발그린드는
Linux 실행 파일 디버깅 및 프로파일링을 위한 유연한 프로그램입니다. 기본적으로 valgrind는 실행됩니다.
다음을 포함하여 다양한 메모리 검사 기능을 수행하는 memcheck라는 도구
초기화되지 않은 메모리에 대한 액세스 감지, 할당된 메모리의 오용(이중 해제,
해제 후 액세스 등) 및 메모리 누수를 감지합니다. 이는 다음을 사용하여 선택할 수 있습니다.
--갈기 옵션을 선택합니다.

$ ./test.py --그라인드

실행되면서, test.py 간접적으로 실행되는 프로그램은 많은 수의
임시 파일. 일반적으로 이러한 파일의 내용은 흥미롭지 않지만 일부에서는
경우에는 이러한 파일을 보는 것이 (디버깅 목적으로) 유용할 수 있습니다. test.py 를 제공합니다
--유지하다 실행 후 이러한 임시 파일이 유지되도록 하는 옵션은 다음과 같습니다.
완전한. 파일은 다음과 같은 디렉터리에 저장됩니다. testpy 출력 하위 디렉토리 아래
현재의 협정 세계시(그리니치 표준시라고도 함)에 따라 명명되었습니다.
시간).

$ ./test.py --유지

마지막으로, test.py 를 제공합니다 --말 수가 많은 많은 양의 정보를 인쇄하는 옵션
그 진행 상황에 대해. 이것이 없으면 매우 유용할 것으로 예상되지 않습니다.
오류. 이 경우 표준 출력 및 표준 오류에 액세스할 수 있습니다.
테스트 스위트 및 예제를 실행하여 보고됩니다. 다음과 같은 방법으로 verbose를 선택합니다.

$ ./test.py --상세 정보

이러한 옵션은 모두 혼합 및 일치될 수 있습니다. 예를 들어 모든 ns-3 코어를 실행하려면
HTML 출력 파일을 생성하는 동안 장황한 모드로 Valgrind에서 테스트 스위트를 테스트합니다.
할것이다:

$ ./test.py --verbose --grind --constrain=core --html=results.html

테스트분류
위에서 언급했듯이 테스트는 다음과 같이 광범위하게 정의된 여러 분류로 그룹화됩니다.
사용자가 선택적으로 테스트를 실행하여 필요한 다양한 종류의 테스트를 처리할 수 있도록 허용
수행 할.

· 빌드 검증 테스트

· 단위 테스트

· 시스템 테스트

· 예시

· 성능 ​​테스트

빌드검증테스트
이는 배포판과 함께 구축되어 사용되는 비교적 간단한 테스트입니다.
빌드가 제대로 작동하는지 확인합니다. 현재 단위 테스트는
테스트하고 ns-3 모듈에 내장된 코드의 소스 파일 그리고 너무 딱 맞아
BVT에 대한 설명 BVT는 ns-3 코드에 내장된 동일한 소스 코드에 있습니다.
현재 테스트는 이러한 종류의 테스트의 예입니다.

단위 테스트
단위 테스트는 코드 조각이
광고된 대로 단독으로 작동합니다. 이런 종류의 테스트를 할 이유가 전혀 없습니다.
ns-3 모듈에 내장되어 있습니다. 예를 들어, 유닛이 객체를 테스트한다는 것이 밝혀졌습니다.
이름 서비스는 객체 이름 서비스 코드 자체와 크기가 거의 같습니다. 단위 테스트
ns-3 코드에 내장되지 않은 단일 기능을 확인하는 테스트입니다.
그러나 테스트하는 코드와 동일한 디렉토리에 있습니다. 이러한 테스트가 가능합니다.
모듈에서 여러 구현 파일의 통합도 확인하십시오. 파일
src/core/test/names-test-suite.cc는 이러한 종류의 테스트의 예입니다. 파일
src/network/test/pcap-file-test-suite.cc는 알려진 좋은 pcap을 사용하는 또 다른 예입니다.
파일을 테스트 벡터 파일로 저장합니다. 이 파일은 src/network 디렉터리에 로컬로 저장됩니다.

테스트
시스템 테스트는 시스템에 둘 이상의 모듈을 포함하는 테스트입니다. 우리는 많은 것을 가지고 있습니다
이러한 종류의 테스트는 현재 회귀 프레임워크에서 실행되지만 일반적으로
과부하된 예. 우리는 디렉토리에 이러한 종류의 테스트를 위한 새로운 장소를 제공합니다.
소스/테스트. src/test/ns3tcp/ns3-interop-test-suite.cc 파일은 이러한 종류의 예입니다.
테스트의. NSC TCP를 사용하여 ns-3 TCP 구현을 테스트합니다. 시험을 보는 경우가 많습니다
이러한 종류의 테스트에 필요한 벡터는 다음 디렉토리에 저장됩니다.
테스트 생활. 예를 들어, ns3tcp-interop-response-Vectors.pcap은 다음으로 구성된 파일입니다.
테스트 중인 ns-3 TCP의 예상 응답으로 사용되는 TCP 헤더 수
'알려진 좋은' 구현으로 사용되는 NSC TCP에 의해 생성된 자극에 대한 것입니다.


예제는 프레임워크에서 테스트되어 예제가 빌드되고 실행되는지 확인합니다. 아무것도 아니다
확인되었으며 현재 pcap 파일이 방금 기록되었습니다. / TMP 폐기됩니다. 만약에
예제가 실행되면(충돌하지 않음) 이 연기 테스트를 통과합니다.

퍼포먼스 테스트
성능 테스트는 시스템의 특정 부분을 실행하고 결정하는 테스트입니다.
테스트가 합리적인 시간 내에 완료되었는지 여부.

달리는 테스트
테스트는 일반적으로 높은 수준을 사용하여 실행됩니다. test.py 프로그램. 목록을 얻으려면
사용 가능한 명령줄 옵션, 실행 test.py --도움

테스트 프로그램 test.py 테스트와 추가된 예제를 모두 실행합니다.
확인할 목록입니다. 테스트와 예제의 차이점은 다음과 같습니다. 테스트
일반적으로 특정 시뮬레이션 출력이나 이벤트가 예상 동작과 일치하는지 확인합니다.
대조적으로, 예제의 출력은 확인되지 않고, 테스트 프로그램은 단지 결과만 확인합니다.
예제 프로그램의 종료 상태를 확인하여 오류 없이 실행되는지 확인합니다.

간단히 말해서, 모든 테스트를 실행하려면 먼저 구성 단계에서 테스트를 구성해야 하며,
또한 (선택적으로) 예시를 확인해야 하는 경우 예시를 확인하세요.

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

그런 다음 ns-3을 빌드하고 빌드된 후 다음을 실행하세요. test.py. test.py -h 숫자가 표시됩니다
test.py의 동작을 수정하는 구성 옵션입니다.

프로그램 test.py C++ 테스트 및 예제를 위해 다음과 같은 하위 수준 C++ 프로그램을 호출합니다.
테스트 러너 실제로 테스트를 실행해보겠습니다. 아래에서 논의된 바와 같이, 이는 테스트 러너 될 수 있습니다
테스트를 디버깅하는 유용한 방법입니다.

디버깅 테스트
테스트 프로그램 디버깅은 낮은 수준의 테스트 실행기를 실행하는 것이 가장 좋습니다.
프로그램. 테스트 실행기는 일반 Python 코드를 다음 코드로 연결하는 다리입니다. NS-3 암호. 그것은
C++로 작성되었으며 자동 테스트 검색 프로세스를 사용합니다. NS-3 찾기 위한 코드와
다양한 테스트를 모두 실행할 수 있습니다.

주된 이유 test.py 디버깅에 적합하지 않다는 것은 허용되지 않는다는 것입니다.
로깅은 다음을 사용하여 활성화됩니다. NS_LOG test.py가 실행될 때의 환경 변수입니다. 이것
테스트 실행기 실행 파일에는 제한이 적용되지 않습니다. 그러므로 로깅을 보고 싶다면
테스트 결과를 얻으려면 테스트 실행기를 직접 사용하여 실행해야 합니다.

테스트 실행기를 실행하려면 다른 ns-3 실행 파일처럼 실행합니다.
waf. 사용 가능한 옵션 목록을 얻으려면 다음을 입력하세요.

$ ./waf --run "테스트 실행기 --help"

다음과 같은 내용이 표시됩니다.

Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리 입력 중
Waf: `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' 디렉토리를 종료합니다.
'빌드'가 성공적으로 완료되었습니다(0.353초).
--assert: 오류가 감지되면 segfault(assert와 같은)에 테스트를 지시합니다.
--basedir=dir: 기본 디렉터리(src를 찾을 위치)를 ''dir''로 설정합니다.
--tempdir=dir: 임시 디렉터리(데이터 파일을 찾을 위치)를 ''dir''로 설정합니다.
--constrain=test-type: ''test-type'' 유형의 테스트 스위트로 검사를 제한합니다.
--help: 이 메시지를 인쇄하세요.
--kinds: 사용 가능한 모든 테스트 종류를 나열합니다.
--list: 모든 테스트 스위트 나열(선택적으로 테스트 유형에 따라 제한됨)
--out=file-name: 테스트 상태 출력 파일을 ''file-name''으로 설정합니다.
--suite=suite-name: ''suite-name''이라는 테스트 모음을 실행합니다.
--verbose: 실행 테스트 모음에서 메시지를 켭니다.

다음과 같은 경우 익숙할 수 있는 여러 가지 항목이 있습니다.
바라 보았다 test.py. 테스트 실행기는 단순한 인터페이스이므로 이는 예상된 결과입니다.
사이에 test.py and NS-3. 여기에는 예제 관련 명령이 누락되어 있음을 알 수 있습니다.
그 이유는 예제가 실제로 그렇지 않기 때문입니다. NS-3 테스트. test.py 마치 마치 그런 것처럼 실행
통합된 테스트 환경을 제시하기 위해 노력했지만 실제로는 완전히 다르며 그렇지 않습니다.
여기에서 찾을 수 있습니다.

여기에 표시되지만 test.py에는 표시되지 않는 첫 번째 새 옵션은 --주장하다 선택권. 이
옵션은 다음과 같은 디버거에서 실행될 때 테스트 사례를 디버깅할 때 유용합니다. gdb. 언제
이 옵션을 선택하면 기본 테스트 사례에 다음과 같은 경우 분할 위반이 발생하도록 지시합니다.
오류가 감지되었습니다. 이는 프로그램 실행을 중지시키는 좋은 부작용이 있습니다.
(디버거에 침입) 오류가 감지되면. gdb를 사용하는 경우 다음을 사용할 수 있습니다.
이 옵션은 다음과 같습니다.

$ ./waf 쉘
$ cd 빌드/디버그/유틸리티
$ gdb 테스트 실행기
$ 실행 --suite=글로벌 값 --assert

전역 값 테스트 모음에서 오류가 발견되면 segfault가 생성됩니다.
(소스 수준) 디버거는 다음에서 중지됩니다. NS_TEST_ASSERT_MSG 그 것을 감지한
오류.

여기에 나타나는 또 다른 새로운 옵션은 --basedir 옵션. 일부는
테스트에서는 소스 디렉터리를 참조해야 할 수도 있습니다. NS-3 지역을 찾기 위한 배포
따라서 테스트를 실행하려면 항상 기본 디렉터리가 필요합니다.

test.py에서 테스트를 실행하면 Python 프로그램은 다음에 대한 basedir 옵션을 제공합니다.
너. 다음을 사용하여 테스트 실행기에서 직접 테스트 중 하나를 실행하려면 waf, 당신은해야합니다
기본 디렉터리와 함께 실행할 테스트 모음을 지정합니다. 그래서 쉘을 사용할 수 있습니다
그리고 다음을 수행하십시오:

$ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object"

''뒤로'' 따옴표를 참고하세요. pwd 명령.

디버거에서 테스트 스위트를 실행하는 경우 기억하기가 매우 어려울 수 있습니다.
배포 기본 디렉터리의 절대 경로를 지속적으로 입력합니다. 때문에
만약 당신이 basedir을 생략한다면, 테스트 실행자는 당신을 위해 하나를 알아내려고 노력할 것입니다. 그것
현재 작업 디렉토리에서 시작하여 디렉토리 트리를 탐색하여
이름이 지정된 파일이 있는 디렉터리 파일 버전 and 특허. 하나를 찾으면 다음과 같이 가정합니다.
기반이어야 하며 이를 제공해야 합니다.

Test 출력
많은 테스트 스위트는 테스트 과정에서 임시 파일(예: pcap 파일)을 작성해야 합니다.
테스트를 실행 중입니다. 그런 다음 테스트에는 쓸 임시 디렉터리가 필요합니다. 파이썬
테스트 유틸리티(test.py)는 임시 파일을 자동으로 제공하지만 독립 실행형으로 실행하는 경우
이 임시 디렉터리를 제공해야 합니다. basedir의 경우와 마찬가지로 다음과 같이 할 수 있습니다.
지속적으로 제공해야 하는 번거로움 --tempdir, 그래서 테스트 실행자는 하나를 알아낼 것입니다
당신이 하나를 제공하지 않으면 당신을 위해 아웃됩니다. 먼저 이름이 지정된 환경 변수를 찾습니다. TMP
and TEMP 그리고 그것을 사용합니다. 둘 다 아니라면 TMP ...도 아니다 TEMP 정의되어 선택됩니다. / TMP. 코드
그런 다음 디렉토리를 생성한 항목(ns-3)을 나타내는 식별자와 시간을 추가합니다.
(hh.mm.ss) 뒤에 큰 난수가 나옵니다. 테스트 실행기는 해당 디렉토리를 생성합니다.
임시 디렉토리로 사용할 이름입니다. 임시 파일은 다음 디렉터리로 이동합니다.
다음과 같이 이름이 지정됩니다.

/tmp/ns-3.10.25.37.61537845

시간은 힌트로 제공되어 비교적 쉽게 내용을 재구성할 수 있습니다.
돌아가서 해당 디렉토리에 있는 파일을 확인해야 하는 경우 디렉토리가 사용되었습니다.
디렉토리.

또 다른 출력 클래스는 다음과 비교하기 위해 생성되는 pcap 추적과 같은 테스트 출력입니다.
참조 출력. 테스트 프로그램은 일반적으로 테스트 스위트를 모두 삭제한 후 이를 삭제합니다.
달리다. 테스트 출력 삭제를 비활성화하려면 다음을 실행하십시오. test.py "보유" 옵션을 사용하면:

$ ./test.py -r

테스트 출력은 다음에서 찾을 수 있습니다. testpy-출력/ 디렉토리.

통계 보고서 of test 실패
테스트 실행기를 사용하여 테스트 스위트를 실행하면 기본적으로 테스트가 자동으로 실행됩니다.
테스트가 통과되었음을 알 수 있는 유일한 표시는 부재 메시지
waf 프로그램이 XNUMX 종료 코드가 아닌 다른 것을 반환했다고 말합니다. 얻으려면
테스트의 일부 출력을 사용하려면 테스트가 수행할 출력 파일을 지정해야 합니다.
다음을 사용하여 XML 상태를 작성합니다. --밖 옵션. 해석을 잘 하셔야 합니다
결과는 테스트 스위트가 추가 결과를 이 파일에 저장합니다. 노력하다,

$ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object --out=myfile.xml"

파일을 보시면 myfile.xml 다음과 같은 내용이 표시되어야 합니다.


pcap-파일-객체

PcapFile::Open with ''w'' 모드가 작동하는지 확인하세요.
통과하다
실제 0.00 사용자 0.00 시스템 0.00


PcapFile::Open with ''r'' 모드가 작동하는지 확인하세요.
통과하다
실제 0.00 사용자 0.00 시스템 0.00


PcapFile::Open with ''a'' 모드가 작동하는지 확인하세요.
통과하다
실제 0.00 사용자 0.00 시스템 0.00


PcapFileHeader가 올바르게 관리되는지 확인하세요.
통과하다
실제 0.00 사용자 0.00 시스템 0.00


PcapRecordHeader가 올바르게 관리되는지 확인하세요.
통과하다
실제 0.00 사용자 0.00 시스템 0.00


PcapFile이 알려진 양호한 PCAP 파일을 읽을 수 있는지 확인하십시오.
통과하다
실제 0.00 사용자 0.00 시스템 0.00

통과하다
실제 0.00 사용자 0.00 시스템 0.00


XML에 익숙하다면 이는 매우 자명할 것입니다. 그것은 또한
테스트 스위트는 출력이 마스터에 추가되도록 설계되었으므로 완전한 XML 파일
에 설명된 XML 상태 파일 test.py 안내

디버깅 test 스위트 실패
다음과 같은 테스트 충돌을 디버그하려면

충돌: TestSuite ns3-wifi-간섭

다음과 같이 gdb를 통해 기본 테스트 실행기 프로그램에 액세스한 다음
실행할 "--basedir=`pwd`" 인수(필요에 따라 다른 인수를 전달할 수도 있지만,
basedir은 필요한 최소값입니다):

$ ./waf --command-template="gdb %s" --run "테스트 실행기"
Waf: `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build' 디렉토리 입력 중
Waf: `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build' 디렉토리를 종료합니다.
'빌드'가 성공적으로 완료되었습니다(0.380초).
GNU gdb 6.8-데비안
Copyright (C) 2008 자유 소프트웨어 재단, Inc.
L cense GPLv3+: GNU GPL 버전 3 이상http://gnu.org/licenses/gpl.html>
이것은 자유 소프트웨어입니다. 자유롭게 변경하고 재배포할 수 있습니다.
법이 허용하는 한도 내에서는 보증이 제공되지 않습니다. "복사 표시"를 입력하세요.
자세한 내용은 '보증 표시'를 참조하세요.
이 GDB는 "x86_64-linux-gnu"로 구성되었습니다...
(gdb) r --basedir=`비밀번호`
프로그램 시작: <..>/build/debug/utils/test-runner --basedir=`pwd`
[libthread_db를 사용한 스레드 디버깅 활성화]
어설션이 실패했습니다. 파일=../src/core/model/type-id.cc, line=138, cond="uid <= m_information.size () && uid != 0"
...

다음은 valgrind를 사용하여 다음과 같은 메모리 문제를 디버깅하는 방법에 대한 또 다른 예입니다.

VALGR: TestSuite 장치-mesh-dot11s-회귀

$ ./waf --command-template="valgrind %s --basedir=`pwd` --suite=devices-mesh-dot11s-regression" --run test-runner

클래스 테스트러너
전용 테스트 프로그램을 실행하는 실행 파일은 TestRunner 클래스를 사용합니다. 이 수업
자동 테스트 등록 및 목록뿐만 아니라 실행 방법도 제공합니다.
개별 테스트. 개별 테스트 스위트는 C++ 전역 생성자를 사용하여 자신을 추가합니다.
테스트 실행기가 관리하는 테스트 스위트 모음입니다. 테스트 실행기는 다음을 나열하는 데 사용됩니다.
사용 가능한 모든 테스트를 확인하고 실행할 테스트를 선택합니다. 아주 간단한 수업이에요
테스트 스위트를 제공하거나 추가 및 가져오기 위한 세 가지 정적 메소드를 제공합니다.
테스트 모음. 수업은 doxygen을 참조하세요. ns3::테스트러너 를 참조하세요

Test 스위트
All NS-3 테스트는 테스트 스위트(Test Suites)와 테스트 케이스(Test Case)로 분류됩니다. 테스트 스위트는
특정 종류의 기능을 완전히 실행하는 테스트 케이스 모음입니다. 처럼
위에서 설명한 대로 테스트 스위트는 다음과 같이 분류될 수 있습니다.

· 빌드 검증 테스트

· 단위 테스트

· 시스템 테스트

· 예시

· 성능 ​​테스트

이 분류는 TestSuite 클래스에서 내보내집니다. 이 수업은 매우 간단합니다.
이 유형을 내보내고 테스트 사례를 축적하는 장소로만 존재합니다. 사용자로부터
관점에서 시스템에 새로운 TestSuite를 생성하려면 새로운 TestSuite를 정의하기만 하면 됩니다.
클래스를 상속받은 클래스 테스트스위트 그리고 이 두 가지 임무를 수행합니다.

다음 코드는 다음에서 실행할 수 있는 새 클래스를 정의합니다. test.py '단위' 테스트로
표시 이름으로 내 테스트 도구 모음 이름.

MySuite 클래스 : 공개 TestSuite
{
공공의:
MyTestSuite();
};

MyTestSuite::MyTestSuite()
: TestSuite("my-test-suite-name", UNIT)
{
AddTestCase(새로운 MyTestCase);
}

MyTestSuite myTestSuite;

기본 클래스는 좋은 서비스가 되기 위해 필요한 모든 등록 및 보고를 처리합니다.
테스트 프레임워크의 시민.

Test 케이스
개별 테스트는 TestCase 클래스를 사용하여 생성됩니다. 테스트 사용을 위한 일반적인 모델
케이스에는 "기능당 하나의 테스트 케이스"와 "메서드당 하나의 테스트 케이스"가 포함됩니다. 혼합물
이러한 모델을 사용할 수 있습니다.

시스템에서 새로운 테스트 케이스를 생성하기 위해 해야 할 일은
테스트 케이스 기본 클래스, 생성자를 재정의하여 테스트 케이스에 이름을 지정하고 재정의합니다.
전에, 도런 테스트를 실행하는 방법.

클래스 MyTestCase : 공개 TestCase
{
MyTestCase();
가상 무효 DoRun(void);
};

MyTestCase::MyTestCase ()
: TestCase ("일부 기능을 확인하세요")
{
}

무효화
MyTestCase::DoRun(무효)
{
NS_TEST_ASSERT_MSG_EQ(true, true, "일부 실패 메시지");
}

유틸리티
테스트의 일부인 다양한 종류의 유틸리티가 많이 있습니다.
뼈대. 예에는 테스트 벡터를 저장하는 데 유용한 일반화된 pcap 파일이 포함됩니다. ㅏ
테스트 실행 중 테스트 벡터를 일시적으로 저장하는 데 유용한 일반 컨테이너입니다. 그리고
검증 및 검증 테스트 결과를 기반으로 프레젠테이션을 생성하는 도구입니다.

이러한 유틸리티는 여기에 문서화되어 있지 않습니다. 예를 들어 TCP 테스트 방법을 참조하세요.
발견 된 소스/테스트/ns3tcp/ pcap 파일과 참조 출력을 사용하십시오.

방법 쓰다 테스트
ns-3 프로젝트의 주요 목표는 사용자가 유효성을 향상하고
결과의 신뢰성. 유효한 모델을 얻기 위해서는 많은 요소가 필요하며,
시뮬레이션 및 테스트가 주요 구성 요소입니다. 모델이나 예시를 제공하는 경우
ns-3의 경우 테스트 코드를 제공하라는 요청을 받을 수 있습니다. 귀하가 기여한 모델이 사용됩니다
다른 사람들에 의해 수년 동안
모델이 맞습니다. 모델에 대해 작성하는 테스트 코드는 향후 발생할 수 있는 문제를 방지하는 데 도움이 됩니다.
출력의 회귀를 확인하고 향후 사용자가 검증을 이해하는 데 도움이 될 것입니다.
모델의 적용 범위.

모델 구현의 정확성을 확인하는 방법에는 여러 가지가 있습니다. 이에
섹션에서는 새로운 글을 작성하는 데 지침으로 사용할 수 있는 몇 가지 일반적인 사례를 다루기를 바랍니다.
테스트.

견본 테스트스위트 골격
처음부터 시작할 때(즉, 기존 TestSuite에 TestCase를 추가하지 않음)
모든 사항을 미리 결정해야 합니다.

· 테스트 스위트의 이름은 무엇입니까?

· 테스트 유형은 무엇입니까(빌드 검증 테스트, 단위 테스트, 시스템 테스트 또는
성능 검사)

· 테스트 코드가 존재할 위치(기존 ns-3 모듈 또는 별도로
src/test/디렉토리). 해당 디렉토리의 wscript 파일을 편집해야 합니다.
새 파일인 경우 새 코드를 컴파일하십시오.

라는 프로그램 src/create-module.py 좋은 출발점입니다. 이 프로그램은
다음과 같이 호출됩니다. 생성-module.py 라우터 라는 가상의 새 모듈에 대해 라우터. 일단
이렇게 하면 라우터 디렉토리 및 테스트/router-test-suite.cc 테스트 스위트.
이 파일은 초기 테스트의 시작점이 될 수 있습니다. 이것은 작동하는 테스트 스위트입니다.
수행되는 실제 테스트는 사소하지만. 모듈의 테스트에 복사하세요.
디렉토리에 대해 해당 파일에서 "Router"를 전역적으로 대체합니다.
테스트하려는 모델에 좀 더 설명적인 내용을 편집할 수도 있습니다.
테스트 케이스 이름.

또한 이 테스트를 컴파일하려면 wscript에 블록을 추가해야 합니다.

module_test.source = [
'테스트/라우터-테스트-스위트.cc',
]

실제로 유용한 작업을 수행하기 전에 다음을 실행해 보는 것이 도움이 될 수 있습니다.
해골. ns-3이 "--enable-tests" 옵션으로 구성되었는지 확인하세요.
새 테스트 스위트가 다음과 같이 "라우터"라고 가정해 보겠습니다.

RouterTestSuite::RouterTestSuite()
: TestSuite("라우터", UNIT)

다음 명령을 시도하십시오.

$ ./test.py -s 라우터

아래와 같은 출력이 생성되어야 합니다.

통과: TestSuite 라우터
테스트 1개 중 1개 통과(1개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

실제 예제는 src/lte/test/test-lte-antenna.cc를 참조하세요.

Test 매크로
예상되는 테스트 프로그램 출력을 확인하는 데 사용할 수 있는 매크로가 많이 있습니다.
산출. 이러한 매크로는 다음에 정의되어 있습니다. src/코어/모델/test.h.

사용되는 주요 매크로 세트는 다음과 같습니다.

NS_TEST_ASSERT_MSG_EQ(실제, 한계, 메시지)
NS_TEST_ASSERT_MSG_NE(실제, 한계, 메시지)
NS_TEST_ASSERT_MSG_LT(실제, 한계, 메시지)
NS_TEST_ASSERT_MSG_GT(실제, 한계, 메시지)
NS_TEST_ASSERT_MSG_EQ_TOL(실제, 한계, 톨, 메시지)

첫 번째 인수 실제 테스트 중인 값, 두 번째 값 제한 예상이다
값(또는 테스트할 값) 및 마지막 인수 메시지 오류 메시지는 다음과 같습니다.
테스트가 실패하면 인쇄하십시오.

위의 처음 XNUMX개 매크로는 동등성, 불평등, 미만 또는 초과를 테스트합니다.
각기. 위의 다섯 번째 매크로는 동일성을 테스트하지만 특정 허용 범위 내에 있습니다.
이 변형은 부동 소수점 숫자가 한계와 동일한지 테스트할 때 유용합니다.
반올림 오류로 인한 테스트 실패를 피하려는 경우.

마지막으로 키워드가 위의 변형인 경우가 있습니다. 주장하다 다음으로 대체됩니다. 배고 있다.
이러한 변형은 반환값을 반환하는 메서드(특히 콜백)에 사용하도록 특별히 설계되었습니다.
무효의. 테스트 프로그램에서 사용하는 콜백용으로 예약하세요. 그렇지 않으면 사용
전에, 주장하다 변종.

방법 더하다 an 프로그램 전에, test 스위트
예제를 성공적으로 컴파일하고 실행하여 완료하는 "스모크 테스트"를 수행할 수 있습니다.
메모리 누수)를 사용하여 example-to-run.py 모듈의 테스트 디렉터리에 있는 스크립트입니다.
간단히 말해, 테스트 디렉터리에 이 파일의 인스턴스를 포함하면 다음과 같은 결과가 발생할 수 있습니다.
나열된 예제를 실행하는 테스트 실행기입니다. 일반적으로 다음 사항을 확인하는 것이 가장 좋습니다.
테스트를 방해하지 않도록 실행 시간이 상당히 짧은 예제를 선택하십시오. 보다
의 예 src/lte/테스트/ 디렉토리.

지원 for 부울 결과
지원 결과 언제 무작위성 is 참여
지원 출력 데이터 반대 a 알려진 분포
제공 사소하지 않은 입력 벡터 of 데이터
저장 and 참조 사소하지 않은 출력 데이터
프리젠 테이션 your 출력 test 데이터
고객 지원
만들기 a NS-3 모델
이 장에서는 디자인 프로세스를 안내합니다. NS-3 모델. 많은 연구 사례에서,
사용자는 단순히 기존 모델을 적용하는 데 만족하지 않고 확장을 원할 수 있습니다.
새로운 방식으로 시뮬레이터의 핵심을 구현합니다. 우리는 ErrorModel을
간편한 설치 NS-3 이 문제에 어떻게 접근할 수 있는지에 대한 동기 부여적인 예로서 링크
설계 및 구현을 진행합니다.

알림:
문서

여기서 우리는 새로운 모델과 새로운 모듈을 만드는 과정과 그 중 일부에 초점을 맞췄습니다.
관련된 디자인 선택. 명확성을 위해 논의를 연기합니다. 역학
모델과 소스 코드를 문서화하는 것 문서 장.

디자인 Approach
어떻게 작동하기를 원하는지 고려하십시오. 어떻게 해야 합니까? 다음 사항에 대해 생각해 보십시오.

· 기능성 : 어떤 기능을 갖추어야 합니까? 속성 또는 구성은 무엇입니까?
사용자에게 노출되나요?

· 재사용 성: 다른 사람들이 내 디자인을 얼마나 재사용할 수 있어야 합니까? 다음 코드를 재사용할 수 있나요?
NS-2 시작하려면? 사용자는 모델을 다른 모델과 어떻게 통합합니까?
시뮬레이션?

· 종속성: 새 코드에 대한 외부 종속성 도입을 줄이는 방법
(더 모듈화하기 위해) 가능한 한 많이? 예를 들어, 어떤 것을 피해야 할까요?
IPv4에서도 사용하려면 IPv6에 의존해야 합니까? 의존성을 피해야 할까요?
IP에서는 전혀요?

주저하지 마시고 연락주세요 ns-3-사용자 or ns 개발자 질문이 있으면 목록을 작성하세요.
특히, 새 모델의 공개 API에 대해 생각하고 요청하는 것이 중요합니다.
피드백. 또한 관심이 있는 경우 다른 사람에게 귀하의 작업을 알리는 데 도움이 됩니다.
협력자.

예: 오류모델
오류 모델이 존재합니다. NS-2. 이는 패킷이 상태 저장 객체로 전달되도록 허용합니다.
무작위 변수를 기반으로 패킷이 손상되었는지 여부를 결정합니다. 발신자는 다음을 수행할 수 있습니다.
그런 다음 패킷을 어떻게 처리할지 결정합니다(삭제 등).

오류 모델의 주요 API는 패킷을 전달하는 함수이며, 반환 값은
이 함수는 호출자에게 손상이 발생했는지 알려주는 부울입니다. 메모
오류 모델에 따라 패킷 데이터 버퍼가 손상될 수도 있고 손상되지 않을 수도 있습니다.
이 함수를 "IsCorrupt()"라고 부르겠습니다.

지금까지 우리의 디자인에는 다음이 포함되었습니다.

클래스 오류 모델
{
공공의:
/ **
* \패킷이 오류/손상된 것으로 간주되는 경우 true를 반환합니다.
* \param pkt 오류 모델을 적용할 패킷
*/
bool IsCorrupt(Ptr pkt);
};

const 포인터를 전달하지 않으므로 함수가
IsCorrupt()가 true를 반환하는 경우 패킷입니다. 모든 오류 모델이 실제로 패킷을 수정하는 것은 아닙니다.
패킷 데이터 버퍼가 손상되었는지 여부를 문서화해야 합니다.

우리는 또한 다음과 같은 특수 버전을 원할 수도 있습니다. NS-2, 그래서 비록 그렇지는 않지만
다형성을 위한 유일한 디자인 선택으로, 기본 클래스를 하위 클래스로 분류한다고 가정합니다.
RateErrorModel, ListErrorModel 등과 같은 특수 클래스에 대한 ErrorModel
에서 이루어집니다 NS-2.

이 시점에서 "IsCorrupt()를 가상 메서드로 만드는 것은 어떨까요?"라고 생각할 수도 있습니다. 그건
하나의 접근 방식; 다른 하나는 공개 비가상 기능을 간접적으로 만드는 것입니다.
개인 가상 함수(C++에서는 비가상 인터페이스 관용구로 알려져 있으며
채택 NS-3 ErrorModel 클래스).

다음으로, 이 장치는 IP나 다른 프로토콜에 종속되어야 합니까? 우리는 원하지 않는다
인터넷 프로토콜에 대한 종속성을 생성하려면(오류 모델은 다음에 적용 가능해야 함)
인터넷 프로토콜이 아닌 경우에도 마찬가지), 나중에 이를 염두에 두겠습니다.

또 다른 고려 사항은 개체가 이 오류 모델을 포함하는 방법입니다. 우리는 퍼팅을 구상합니다
예를 들어 특정 NetDevice 구현의 명시적 설정자:

/ **
* 수신 ErrorModel을 PointToPointNetDevice에 연결합니다.
*
* PointToPointNetDevice는 선택적으로 ErrorModel을 포함할 수 있습니다.
* 패킷 수신 체인.
*
* @ErrorModel 참조
* @param em ErrorModel에 대한 Ptr입니다.
*/
void PointToPointNetDevice::SetReceiveErrorModel(Ptr 여자 이름);

다시 말하지만, 이것이 우리가 가진 유일한 선택은 아닙니다(오류 모델은 여러 가지로 집계될 수 있음).
다른 개체), 그러나 이는 사용자가 강제로
NetDevice 수준에서 성공적인 패킷 전송에 대한 오류입니다.

몇 가지 생각하고 기존 내용을 살펴본 후 NS-2 코드, 여기에 기본의 샘플 API가 있습니다.
초기 검토를 위해 게시될 수 있는 클래스 및 첫 번째 하위 클래스:

클래스 오류 모델
{
공공의:
오류모델();
가상 ~ErrorModel();
bool IsCorrupt(Ptr pkt);
무효 재설정(void);
무효 활성화(void);
무효 비활성화 (무효);
bool IsEnabled (void) const;
비공개 :
가상 bool DoCorrupt(Ptr pkt) = 0;
가상 무효 DoReset(void) = 0;
};

열거형 ErrorUnit
{
EU_BIT,
EU_BYTE,
EU_PKT
};

// 기본 패킷에 따라 오류가 발생한 패킷을 결정합니다.
// 확률변수 분포, 오류율, 비율의 단위.
클래스 RateErrorModel : 공개 ErrorModel
{
공공의:
RateErrorModel();
가상 ~RateErrorModel();
enum ErrorUnit GetUnit (void) const;
void SetUnit(enum ErrorUnit error_unit);
double GetRate (void) const;
무효 SetRate(이중 속도);
void SetRandomVariable(const RandomVariable &ranvar);
비공개 :
가상 bool DoCorrupt(Ptr pkt);
가상 무효 DoReset(무효);
};

발판
구현을 시작할 준비가 되었다고 가정해 보겠습니다. 당신은 꽤 명확한 그림을 가지고 있습니다
당신이 만들고 싶은 것이 무엇인지, 그리고 당신은 초기 검토나 제안을 요청했을 수도 있습니다.
목록. 다음 단계(구현)에 접근하는 한 가지 방법은 스캐폴딩을 만들고
디자인이 성숙해지면 세부 사항을 채우십시오.

이 섹션에서는 스캐폴딩을 정의하기 위해 고려해야 할 여러 단계를 안내합니다.
모델이 결국 구현하게 될 비기능적 뼈대입니다. 보통은 좋은데
이러한 세부 사항이 마지막에 통합되기를 기다리지 말고 대신에 연결하는 연습을 하십시오.
모델의 뼈대를 초기에 시스템에 추가한 다음 나중에 API를 사용하여 기능을 추가하고
통합이 맞는 것 같습니다.

아래 프레젠테이션에서 모델에 대한 몇 가지 사항을 수정하고 싶을 것입니다.
왜냐하면 오류 모델을 그대로 따르면 생성한 코드가 오류 모델과 충돌하기 때문입니다.
기존 오류 모델. 아래는 ErrorModel이 어떻게 구축되었는지에 대한 개요입니다.
다른 모델에 적응할 수 있습니다.

검토 전에, NS-3 코딩 스타일 문서
이 시점에서 잠시 멈추고 다음 내용을 읽어 보십시오. NS-3 코딩 스타일 문서, 특히
코드를 프로젝트에 다시 기여할 것을 고려하고 있다면. 코딩 스타일
문서가 기본 프로젝트 페이지와 연결되어 있습니다. NS-3 코딩 스타일.

결정하다 어디에 in 전에, 출처 나무 전에, 모델 되었어야 살다
의 모든 NS-3 모델 소스 코드는 디렉토리에 있습니다 src /. 당신은 어느 것을 선택해야합니다
그것이 상주하는 하위 디렉토리입니다. 일종의 새로운 모델 코드라면 이를 넣는 것이 합리적입니다.
src / 특히 빌드와 쉽게 통합할 수 있도록 디렉토리를 어딘가에 둡니다.
시스템.

오류 모델의 경우 패킷 클래스와 관련성이 높으므로 의미가 있습니다.
이것을 구현하려면 소스/네트워크/ 모듈 NS-3 패킷이 구현됩니다.

waf and 스크립트
NS-3 를 사용하여 와프 시스템을 구축합니다. 당신은 새로운 것을 통합하고 싶을 것입니다 NS-3 와프를 사용한다
시스템을 구축합니다. 새로운 소스 파일을 이 시스템에 통합하고 싶을 것입니다. 이것
에 파일을 추가해야 합니다. 스크립트 각 디렉토리에 있는 파일입니다.

빈 파일 error-model.h 및 error-model.cc로 시작하여 이를
소스/네트워크/wscript. 실제로는 .cc 파일을 나머지 파일에 추가하기만 하면 됩니다.
소스 파일과 .h 파일을 헤더 파일 목록에 추가합니다.

이제 최상위 디렉토리로 팝업하여 "./test.py"를 입력하세요. 넌 깨지 말았어야 했어
이 작업으로 무엇이든.

포함 근위 연대
다음으로 몇 가지를 추가해 보겠습니다. 교도관 헤더 파일에:

#ifndef ERROR_MODEL_H
#ERROR_MODEL_H 정의
...
#endif

네임 스페이스 ns3
NS-3 를 사용하여 NS-3 네임 스페이스 해당 기호를 다른 네임스페이스로부터 격리합니다. 일반적으로
사용자는 다음에 NS-3 cc 및 h 파일 모두에 네임스페이스 블록이 있습니다.:

네임스페이스 ns3 {
...
}

이 시점에서 우리는 새 클래스 정의를 시작할 수 있는 몇 가지 뼈대 파일을 갖게 되었습니다.
헤더 파일은 다음과 같습니다.

#ifndef ERROR_MODEL_H
#ERROR_MODEL_H 정의

네임스페이스 ns3 {

} // 네임스페이스 ns3
#endif

동안 오류 모델.cc 파일은 다음과 같습니다.

#include "error-model.h"

네임스페이스 ns3 {

} // 네임스페이스 ns3

이러한 파일에는 실제로 내용이 없으므로 컴파일해야 합니다. 이제 준비가 되었습니다.
수업 추가를 시작합니다.

처음의 실시
이 시점에서 우리는 여전히 일부 비계를 작업 중이지만 다음을 정의하기 시작할 수 있습니다.
나중에 추가할 기능이 있는 클래스입니다.

상속 전에, 목적 수업?
이는 중요한 설계 단계입니다. 수업을 사용할지 여부 목적 새로운 기본 클래스로
수업.

장에 설명된 대로 NS-3 객체 모델, 클래스에서 상속되는 클래스
목적 특별한 속성을 얻습니다:

· NS NS-3 유형 및 속성 시스템(속성 참조)

· 객체 집합 시스템

· 스마트 포인터 참조 카운팅 시스템(클래스 Ptr)

클래스에서 파생된 클래스 객체베이스} 위의 처음 두 속성을 가져오지만 가져오지는 않습니다.
스마트 포인터를 얻으세요. 클래스에서 파생된 클래스 RefCountBase 스마트 포인터만 가져오기
참조 카운팅 시스템.

실제로 수업을 목적 위 세 가지의 변형입니다. NS-3 개발자는
가장 흔하게 접하게 됩니다.

우리의 경우에는 속성 시스템을 활용하고 인스턴스를 전달하겠습니다.
이 물체의 NS-3 공개 API이므로 클래스 목적 우리에게 적합합니다.

처음의 클래스
진행하는 한 가지 방법은 최소한의 기능을 정의하는 것부터 시작하여 해당 기능이 작동하는지 확인하는 것입니다.
엮다. Object 클래스에서 파생될 때 구현하는 데 필요한 모든 것이 무엇인지 검토해 보겠습니다.

#ifndef ERROR_MODEL_H
#ERROR_MODEL_H 정의

#include "ns3/object.h"

네임스페이스 ns3 {

클래스 ErrorModel : 공용 객체
{
공공의:
정적 TypeId GetTypeId (void);

오류모델();
가상 ~ErrorModel();
};

클래스 RateErrorModel : 공개 ErrorModel
{
공공의:
정적 TypeId GetTypeId (void);

RateErrorModel();
가상 ~RateErrorModel();
};
#endif

여기서 주목해야 할 몇 가지 사항이 있습니다. 우리는 다음을 포함해야 합니다 객체.h. 협약 NS-3 만약
헤더 파일은 동일한 디렉터리에 함께 위치하므로 경로 없이 포함될 수 있습니다.
접두사. 따라서 ErrorModel을 구현한다면 소스/코어/모델 디렉토리, 우리
그냥 "라고 말할 수도 있었어#포함 "객체.h"". 하지만 우리는 소스/네트워크/모델, 그래서 우리는
"로 포함시키세요.#포함 "ns3/객체.h"". 또한 이는 네임스페이스 외부에 있다는 점에 유의하세요.
선언.

둘째, 각 클래스는 다음과 같은 정적 공개 멤버 함수를 구현해야 합니다. 유형 ID 가져오기 (무효의).

셋째, 생성자와 소멸자를 구현하는 것이 좋습니다.
컴파일러는 이를 생성하고 소멸자를 가상으로 만듭니다. C++에서는 다음 복사본도 참고하세요.
할당 연산자와 복사 생성자는 정의되지 않은 경우 자동 생성되므로
이를 원하지 않으면 이를 비공개 멤버로 구현해야 합니다. 이런 측면은
C++는 Scott Meyers의 Effective C++ 책에서 논의됩니다. 항목 45.

이제 .cc 파일에서 해당하는 골격 구현 코드를 살펴보겠습니다.:

#include "error-model.h"

네임스페이스 ns3 {

NS_OBJECT_ENSURE_REGISTERED(오류모델);

TypeId ErrorModel::GetTypeId(무효)
{
static TypeId tid = TypeId ("ns3::ErrorModel")
.SetParent ()
;
정시 반환;
}

오류모델::오류모델 ()
{
}

오류모델::~오류모델()
{
}

NS_OBJECT_ENSURE_REGISTERED(RateErrorModel);

TypeId RateErrorModel::GetTypeId(무효)
{
static TypeId tid = TypeId ("ns3::RateErrorModel")
.SetParent ()
.AddConstructor ()
;
정시 반환;
}

RateErrorModel::RateErrorModel ()
{
}

RateErrorModel::~RateErrorModel ()
{
}

무엇인가 유형 ID 가져오기 (무효의) 기능? 이 함수는 몇 가지 작업을 수행합니다. 그것은
TypeId 시스템에 고유한 문자열을 추가합니다. 이는 개체의 계층 구조를 설정합니다.
속성 시스템(경유 부모 설정). 또한 다음을 통해 특정 객체를 생성할 수 있다고 선언합니다.
객체 생성 프레임워크(AddConstructor).

매크로 NS_OBJECT_ENSURE_REGISTERED (수업 이름) 또한 매 수업마다 한 번씩 필요합니다.
새로운 GetTypeId 메서드를 정의하고 클래스를 실제로 등록합니다.
체계. 객체 모델 장에서는 이에 대해 더 자세히 설명합니다.

포함 외부 파일
로깅 고객 지원
여기 쓰다 a 비트 about 첨가 |ns3| 로깅 매크로. 주의 사항 LOG_COMPONENT_DEFINE is
외부 전에, 네임 스페이스 ns3

건설자, 함수 프로토 타입
변수 (기본 가치, 속성)
Test 프로그램 1
목적 뼈대
첨가 a 견본 스크립트
이 시점에서 위에서 정의한 기본 스캐폴딩을 가져와서 추가해 볼 수 있습니다.
시스템에. 이제 이 단계를 수행하면 배관 작업 시 더 간단한 모델을 사용할 수 있습니다.
시스템에 추가하고 설계 또는 API 수정이 필요한지 여부도 밝힐 수 있습니다.
만들어진. 이 작업이 완료되면 우리는
ErrorModel 자체.

추가 Basic 고객 지원 in 전에, 클래스
/* 지점간-net-device.h */
클래스 오류모델;

/ **
* 수신 패킷 이벤트에 대한 오류 모델
*/
포인트 m_receiveErrorModel;

추가 접근 자
무효화
PointToPointNetDevice::SetReceiveErrorModel(Ptr 여자 이름)
{
NS_LOG_FUNCTION (this << em);
m_receiveErrorModel = em;
}

.AddAttribute("ReceiveErrorModel",
"패킷 손실을 시뮬레이션하는 데 사용되는 수신기 오류 모델",
포인터값(),
MakePointerAccessor(&PointToPointNetDevice::m_receiveErrorModel),
MakePointerChecker ())

리드 으로 전에,
void PointToPointNetDevice::수신(Ptr 패킷)
{
NS_LOG_FUNCTION(이 << 패킷);
uint16_t 프로토콜 = 0;

if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (패킷) )
{
//
// 오류 모델이 있고 그것이 손실 시간임을 나타내는 경우
// 손상된 패킷입니다. 이 패킷을 전달하지 말고 그대로 두십시오.
//
m_dropTrace(패킷);
}
그렇지 않으면
{
//
// 수신 추적 후크를 누르고 지점간 프로토콜 헤더를 제거합니다.
// 그리고 이 패킷을 프로토콜 스택 위로 전달합니다.
//
m_rxTrace(패킷);
ProcessHeader(패킷, 프로토콜);
m_rxCallback(이, 패킷, 프로토콜, GetRemote());
if (!m_promiscCallback.IsNull ())
{ m_promiscCallback(이, 패킷, 프로토콜, GetRemote(),
GetAddress(), NetDevice::PACKET_HOST);
}
}
}

만들기 null로 기능성화장품유무 스크립트
/* 단순 오류-모델.cc */

// 오류 모델
// 노드 3의 NetDevice에 오류 모델을 추가하고 싶습니다.
// 채널과 노드를 통해 NetDevice에 대한 핸들을 얻을 수 있습니다.
// 포인터
포인트 nd3 = PointToPointTopology::GetNetDevice
(n3, 채널2);
포인트 em = 생성 ();
nd3->SetReceiveErrorModel(em);

불량배
ErrorModel::DoCorrupt(패킷 및 p)
{
NS_LOG_FUNCTION;
NS_LOG_UNCOND("손상되었습니다!");
false를 반환;
}

이 시점에서 우리는 수신 모듈에 간단한 ErrorModel을 연결하여 프로그램을 실행할 수 있습니다.
PointToPointNetDevice의 경로입니다. "Corrupt!"라는 문자열이 출력됩니다. 각 패킷마다
노드 n3에서 수신되었습니다. 다음으로 오류 모델로 돌아가서 다음을 수행하는 하위 클래스를 추가합니다.
더 흥미로운 오류 모델링.

추가 a 아강
간단한 기본 클래스 ErrorModel은 흥미로운 작업을 수행하지 않지만 다음을 제공합니다.
유용한 기본 클래스 인터페이스(Corrupt() 및 Reset())는 가상 함수로 전달됩니다.
하위 분류될 수 있습니다. 다음으로 BasicErrorModel을 기반으로 하는 것을 고려해 보겠습니다.
전에, NS-2 ErrorModel 클래스( ns-2/대기열/errmodel.{cc,h}).

사용자 인터페이스 관점에서 우리는 이것이 어떤 속성을 갖기를 원합니까? 우리는 원한다
사용자가 사용된 ErrorModel 유형을 간단하게 교체할 수 있도록 하기 위해
NetDevice. 또한 구성 가능한 매개변수를 설정하는 기능도 원합니다.

우리가 고려할 몇 가지 간단한 요구 사항은 다음과 같습니다.

· 손실을 제어하는 ​​무작위 변수를 설정하는 기능(기본값은 균일변수)

· 오류가 발생하는 단위(비트, 바이트, 패킷, 시간)를 설정하는 기능
적용된.

· 위 단위에 해당하는 오류율(예: 10^-3)을 설정하는 기능
세분성.

· 활성화/비활성화 기능(기본값은 활성화됨)

방법 아강
BasicErrorModel을 다음과 같이 ErrorModel의 하위 클래스로 선언합니다.

클래스 BasicErrorModel : 공개 ErrorModel
{
공공의:
정적 TypeId GetTypeId (void);
...
비공개 :
// 기본 클래스 순수 가상 함수 구현
가상 bool DoCorrupt(Ptr 피);
가상 bool DoReset (무효);
...
}

고유한 TypeId 문자열을 설정하여 하위 클래스 GetTypeId 함수를 구성하고
부모를 ErrorModel로 설정:

TypeId RateErrorModel::GetTypeId(무효)
{
static TypeId tid = TypeId ("ns3::RateErrorModel")
.SetParent ()
.AddConstructor ()
...

짓다 핵심 기능 and 단위 테스트
주장하다 매크로
쓰기 단위 테스트
첨가 a 신제품 모듈 NS-3
관련 클래스, 예제 및 테스트 그룹을 생성하면 다음과 같은 작업을 수행할 수 있습니다.
하나로 합쳐진 NS-3 기존 모듈과 함께 사용할 수 있도록 NS-3 모듈
그리고 다른 연구자들에 의해.

이 장에서는 새 모듈을 추가하는 데 필요한 단계를 안내합니다. NS-3.

단계 0 - 모듈 레이아웃
모든 모듈은 다음에서 찾을 수 있습니다. SRC 예배 규칙서. 각 모듈은 디렉토리에서 찾을 수 있습니다.
모듈과 이름이 같습니다. 예를 들어, 스펙트럼 모듈은 여기에서 찾을 수 있습니다:
소스/스펙트럼. 우리는 다음의 내용을 인용할 것입니다. 스펙트럼 설명을 위한 모듈입니다.

프로토타입 모듈에는 다음과 같은 디렉터리 구조와 필수 파일이 있습니다.

src /
모듈 이름/
바인딩/
문서/
예/
스크립트
돕는 사람/
모델/
테스트/
example-to-run.py
스크립트

모든 디렉토리가 각 모듈에 존재하는 것은 아닙니다.

단계 1 - 만들기 a 모듈 해골
새로운 소스 디렉토리에 대한 뼈대를 생성하는 Python 프로그램이 소스 디렉토리에 제공됩니다.
기준 치수. 이 논의의 목적을 위해 우리는 새 모듈이 호출된다고 가정합니다.
새 모듈. 에서 SRC 디렉터리에서 다음을 수행하여 새 모듈을 만듭니다.

$ ./create-module.py 새 모듈

다음으로, cd 으로 새 모듈; 다음 디렉토리 레이아웃을 찾을 수 있습니다.

$ cd 새 모듈
$ls
문서 예제 도우미 모델 테스트 wscript

더 자세히 말하면, 생성-module.py 스크립트는 디렉토리와 초기 디렉토리를 생성합니다.
골격 스크립트, .h, .CC and .첫 번째 파일. 뼈대 파일이 포함된 전체 모듈은 다음과 같습니다.
이렇게 :

src /
새 모듈/
문서/
새로운 모듈.rst
예/
새-모듈-example.cc
스크립트
돕는 사람/
새로운 모듈 helper.cc
새로운 모듈-helper.h
모델/
새로운 모듈.cc
새로운 모듈.h
테스트/
새로운 모듈-테스트-suite.cc
스크립트

(필요한 경우 바인딩/ 다음에 나열된 디렉토리 Step-0 동안 자동으로 생성됩니다.
빌드.)

다음으로 이 모듈을 사용자 정의하는 방법을 살펴보겠습니다. 유익한 waf 파일에 대해
두 가지를 편집하여 모듈을 구성합니다. 스크립트 파일. 우리는
이 장의 주요 단계.

All NS-3 모듈은 다음에 따라 달라집니다. core 모듈과 일반적으로 다른 모듈에 있습니다. 이 의존성
에 지정되어 있습니다. 스크립트 파일(별도의 파일이 아닌 모듈의 최상위 수준에 있음) 스크립트
에 파일을 예배 규칙서!). 해골에서 스크립트 당신을 선언할 전화
새 모듈 waf 다음과 같이 표시됩니다(편집 전).

def 빌드(bld):
모듈 = bld.create_ns3_module('새 모듈', ['코어'])

가정해보자 새 모듈 에 따라 인터넷, 유동성aodv 모듈. 후에
그것을 편집 스크립트 파일은 다음과 같아야합니다.

def 빌드(bld):
모듈 = bld.create_ns3_module('새 모듈', ['인터넷', '이동성', 'aodv'])

첫 번째 수준 모듈 종속성만 나열되어야 하므로 제거했습니다.
core; 인터넷 모듈은 다음에 따라 달라집니다. core.

모듈에는 모델 소스 파일이 있을 가능성이 높습니다. 초기 뼈대(
성공적으로 컴파일)에 생성됩니다. 모델/new-module.cc and 모델/new-module.h.

모듈에 헬퍼 소스 파일이 있으면 다음으로 이동합니다. 돕는 사람/
예배 규칙서; 다시 말하지만 초기 스켈레톤은 해당 디렉토리에 생성됩니다.

마지막으로 테스트와 예제를 작성하는 것이 좋습니다. 이것들은 거의 틀림없이
새 모듈이 공식에 승인되기 위해 필요합니다. NS-3 소스 트리. 해골
테스트 스위트와 테스트 케이스는 테스트/ 예배 규칙서. 스켈레톤 테스트 스위트는
이름이 지정된 새 단위 테스트를 선언하는 아래 생성자를 포함합니다. 새 모듈,와
클래스로 구성된 단일 테스트 케이스 새로운모듈TestCase1:

NewModuleTestSuite::NewModuleTestSuite()
: TestSuite("새 모듈", UNIT)
{
AddTestCase(새로운 NewModuleTestCase1);
}

단계 3 - 선언 출처 파일
새 모듈의 공개 헤더 및 소스 코드 파일은
스크립트 텍스트 편집기로 수정하여 파일을 만듭니다.

예를 들어 선언 후 스펙트럼 모듈, src/스펙트럼/wscript 지정합니다
다음 목록이 있는 소스 코드 파일:

def 빌드(bld):

모듈 = bld.create_ns3_module('스펙트럼', ['인터넷', '전파', '안테나', '응용 프로그램'])

모듈.소스 = [
'모델/스펙트럼-model.cc',
'모델/스펙트럼-값.cc',
.
.
.
'model/microwave-oven-spectrum-value-helper.cc',
'helper/spectrum-helper.cc',
'helper/adhoc-aloha-noack-ideal-phy-helper.cc',
'도우미/파형 생성기-helper.cc',
'도우미/스펙트럼-분석기-helper.cc',
]

이러한 소스를 컴파일한 결과 개체는 링크 라이브러리로 어셈블됩니다.
이 모듈에 의존하는 모든 프로그램에 연결됩니다.

그러나 그러한 프로그램은 새 모듈의 공개 API를 어떻게 학습합니까? 읽어!

단계 4 - 선언 공공 영역 헤더 파일
모델 및 도우미의 공개 API를 정의하는 헤더 파일도 다음과 같아야 합니다.
에 지정된 스크립트 파일.

계속 스펙트럼 모델 일러스트레이션, 공개 헤더 파일이 지정됨
다음 스탠자와 함께. (에 대한 인수에 유의하십시오. 빌딩 기능이 알려줍니다 waf
이 모듈의 헤더를 다른 모듈과 함께 설치 NS-3 헤더):

헤더 = bld(기능='ns3header')

headers.module = '스펙트럼'

헤더.소스 = [
'모델/스펙트럼-모델.h',
'모델/스펙트럼-값.h',
.
.
.
'모델/전자레인지-스펙트럼-값-helper.h',
'도우미/스펙트럼-helper.h',
'helper/adhoc-aloha-noack-ideal-phy-helper.h',
'도우미/파형 생성기-helper.h',
'도우미/스펙트럼-분석기-helper.h',
]

이 방법으로 공개된 헤더는 포함을 통해 모델 사용자가 액세스할 수 있습니다.
다음과 같은 진술

#include "ns3/spectrum-model.h"

구현에서 내부적으로 엄격하게 사용되는 헤더는 여기에 포함되지 않아야 합니다. 그들
다음과 같은 include 문을 통해 여전히 구현에 액세스할 수 있습니다.

#include "my-module-implementation.h"

단계 5 - 선언 테스트
새 모듈에 테스트가 있는 경우에는 스크립트 파일
텍스트 편집기로 수정하십시오.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 스펙트럼 모델 테스트는 다음 스탠자로 지정됩니다.

module_test = bld.create_ns3_module_test_library('스펙트럼')

module_test.source = [
'테스트/스펙트럼-간섭-테스트.cc',
'테스트/스펙트럼-값-테스트.cc',
]

테스트 테스트 케이스 작성 방법에 대한 자세한 내용은

단계 6 - 선언
새 모듈에 예제가 있는 경우에는 예제/wscript
파일. (스켈레톤 최상위 레벨 스크립트 재귀적으로 포함 예제/wscript 오직
예제는 구성 시 활성화되었습니다.)

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 스펙트럼 모델은 첫 번째 예를 정의합니다. src/스펙트럼/예제/wscript

def 빌드(bld):
obj = bld.create_ns3_program('adhoc-aloha-ideal-phy',
['스펙트럼', '이동성'])
obj.source = 'adhoc-aloha-ideal-phy.cc'

함수에 대한 두 번째 인수는 create_ns3_program() 모듈 목록입니다
생성되는 프로그램이 의존하는 것; 다시 말하지만, 포함하는 것을 잊지 마세요 새 모듈 in
목록. 직접 모듈 종속성만 나열하고 waf
전체 종속성 트리를 추론합니다.

경우에 따라 명확성을 위해 예제에 대한 구현을
여러 소스 파일. 이 경우 해당 파일을 추가적인 명시적 파일로 포함하면 됩니다.
예제 소스:

obj = bld.create_ns3_program('새 모듈 예', [새 모듈])
obj.source = ['new-module-example.cc', 'new-module-example-part.cc']

Python 예제는 다음 함수 호출을 사용하여 지정됩니다. 두 번째
함수에 대한 인수 Register_ns3_script() 파이썬이 실행하는 모듈의 목록입니다.
예는 다음에 따라 다릅니다.

bld.register_ns3_script('new-module-example.py', ['new-module'])

단계 7 - 달리기 as 테스트
명시적인 테스트 코드를 실행하는 것 외에도 테스트 프레임워크를 계측하여 다음을 수행할 수도 있습니다.
전체 예제 프로그램을 실행하여 예제에서 회귀를 포착하려고 합니다. 그러나, 전부는 아니다
예제는 회귀 테스트에 적합합니다. 파일 테스트/examples-to-run.py 제어
테스트 프레임워크가 실행될 때 예제 호출.

이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 스펙트럼 에 의해 실행되는 모델 예제 test.py 에 지정되어 있습니다
src/spectrum/test/examples-to-run.py C++ 및 Python의 다음 두 목록을 사용하여
예 :

# 남아 있는지 확인하기 위해 실행할 C++ 예제 목록
# 시간이 지남에 따라 빌드 가능하고 실행 가능합니다. 목록의 각 튜플에는
#
# (example_name, do_run, do_valgrind_run).
#
# 자세한 내용은 test.py를 참조하세요.
cpp_예제 = [
("adhoc-aloha-ideal-phy", "참", "참"),
("adhoc-aloha-ideal-phy-with-microwave-oven", "True", "True"),
("adhoc-aloha-ideal-phy-matrix-propagation-loss-model", "True", "True"),
]

# 남아 있는지 확인하기 위해 실행할 Python 예제 목록
# 시간이 지남에 따라 실행할 수 있습니다. 목록의 각 튜플에는
#
# (예제_이름, do_run).
#
# 자세한 내용은 test.py를 참조하세요.
python_examples = [
("sample-simulator.py", "참"),
]

주석에 표시된 대로 실행할 C++ 예제 목록의 각 항목에는 다음이 포함됩니다.
튜플 (예_이름, do_run, do_valgrind_run)어디로

· example_name 실행할 실행 파일입니다.

· do_run 예제를 실행하기 위한 조건이고,

· do_valgrind_run valgrind에서 예제를 실행하기 위한 조건입니다. (이것
NSC가 일부 테스트에서 불법 명령 충돌을 일으키기 때문에 필요합니다.
valgrind에서 실행됩니다.)

두 조건은 다음에 의존할 수 있는 Python 문입니다. waf 구성
변수. 예를 들어,

("tcp-nsc-lfn", "NSC_ENABLED == 참", "NSC_ENABLED == 거짓"),

실행할 Python 예제 목록의 각 항목에는 튜플이 포함되어 있습니다. (예_이름,
do_run), 여기서 C++ 예제의 경우,

· example_name 실행할 Python 스크립트입니다.

· do_run 예제를 실행할 조건입니다.

다시 말하지만, 조건은 다음에 의존할 수 있는 Python 문입니다. waf 구성 변수.
예를 들어,

("realtime-udp-echo.py", "ENABLE_REAL_TIME == False"),

단계 8 - 구성 and 짓다
이제 정상적으로 모듈을 구성, 빌드 및 테스트할 수 있습니다. 다음을 다시 구성해야 합니다.
첫 번째 단계로 계획하여 waf 새 정보를 캐시에 저장합니다. 스크립트 파일 또는
그렇지 않으면 새 모듈이 빌드에 포함되지 않습니다.

$ ./waf 구성 --enable-examples --enable-tests
$ ./waf 빌드
$ ./test.py

새 모듈의 테스트 모음(및 모듈에 있는 경우 예제 프로그램)을 찾으세요.
활성화) 테스트 출력에서.

단계 9 - Python 바인딩
모듈에 Python 바인딩을 추가하는 것은 선택 사항이며 단계는 다음에 의해 주석 처리됩니다.
기본 생성-module.py 스크립트.

# bld.ns3_python_bounds()

Python 바인딩을 포함하려는 경우(Python ns-3을 작성하려는 경우에만 필요함)
프로그램 대신 C++ ns-3 프로그램) 위의 주석을 제거하고 다음을 설치해야 합니다.
Python API 스캐닝 시스템(이 매뉴얼의 다른 부분에서 다룸) 및 모듈을 스캔하여
새 바인딩을 생성합니다.

만들기 문서
NS-3 두 종류의 문서를 제공합니다: 설명적인 "사용자 가이드" 스타일 장
소스 코드 API 설명서.

"사용자 가이드" 챕터는 reStructuredText 형식 (.첫 번째), 즉
Python 문서 시스템에 의해 처리됨 스핑크스 웹 페이지 및 PDF 파일을 생성합니다.
API 문서는 다음을 사용하여 소스 코드 자체에서 생성됩니다. 독소, 생성
상호 연결된 웹 페이지. 이 두 가지 모두 중요합니다. 스핑크스 장에서는 다음을 설명합니다. why
모델 사용 개요; API 설명서는 방법 세부.

이 장에서는 이러한 도구에 대한 간략한 개요를 제공하며 선호하는 사용법과
에 대한 사용자 정의 NS-3.

모든 표준 문서를 작성하려면 다음을 수행하십시오.

$ ./waf 문서

보다 전문적인 옵션에 대해서는 계속 읽으십시오.

문서화 스핑크스
우리는 사용 스핑크스 각각의 설계 및 사용법을 설명하는 설명 장을 생성합니다.
기준 치수. 지금 당신이 읽고 있는 문서 장. 그만큼 출처 에 링크
사이드바에 이 장의 reStructuredText 소스가 표시됩니다.

첨가 신제품
새 챕터를 추가하려면 세 단계를 거쳐야 합니다(자세한 내용은 아래에서 설명).

1. 고르다 어디서? 문서 파일이 살아 있을 것입니다.

2. (링크) 기존 페이지에서 새 문서로.

3. 새 파일을 Makefile.

어디서?
특정 모듈에 대한 문서, , 일반적으로 들어가야 합니다. 소스/푸/문서/. 예를 들어
src/foo/doc/foo.rst 모듈의 최상위 문서가 됩니다. 그만큼
src/create-module.py 스크립트가 이 파일을 생성합니다.

일부 모델에는 여러 가지가 필요합니다. .첫 번째 파일 및 그림; 이것들은 모두
소스/푸/문서/ 예배 규칙서. 문서는 실제로 Sphinx Makefile에 의해 빌드됩니다. 특히
포함된 문서를 가지고 있는 것이 도움이 될 수 있습니다. Makefile 인간을 소스/푸/문서/
이 모듈에 대한 문서 작성을 단순화하기 위한 디렉토리(안테나 예)입니다.
이를 설정하는 것은 특별히 어렵지는 않지만 이 장의 범위를 벗어납니다.

어떤 경우에는 문서가 여러 모델에 걸쳐 있습니다. 그만큼 네트워크 장이 예시입니다. ~ 안에
추가하는 이러한 경우 .첫 번째 파일을 직접 문서/모델/소스/ 적절할 수도 있습니다.

(링크)
스핑크스는 알아야 해 어디에 새 장이 나타나야 합니다. 대부분의 경우 새 모델
장이 에 나타나야 합니다. 모델 책. 거기에 챕터를 추가하려면 편집하십시오.
문서/모델/소스/index.rst

.. 톡트리::
:최대 깊이: 1

조직
생기
안테나
aodv
어플리케이션
...

문서 이름을 추가합니다( .첫 번째 확장자)를 이 목록에 추가합니다. 보관하십시오
특정 챕터를 쉽게 시각적으로 스캔할 수 있도록 알파벳 순서로 챕터를 모델링합니다.

Makefile
또한 문서를 적절한 위치에 추가해야 합니다. Makefile그래서 확인 확인할 줄 안다
업데이트를 위해. 모델 책 Makefile은 문서/모델/Makefile, 설명서 책 Makefile은
문서/매뉴얼/메이크파일.

# $SOURCETEMP에 복사해야 하는 모든 모델 라이브러리 .rst 파일을 나열합니다.
소스 = \
소스/conf.py \
소스/_정적 \
소스/index.rst \
소스/바꾸기.txt \
소스/조직.rst \
...
$(SRC)/antenna/doc/source/antenna.rst \
...

당신은 당신의 .첫 번째 파일에 SOURCES 변하기 쉬운. 그림을 추가하려면 다음의 주석을 읽으십시오.
Makefile 이미지 파일을 포함해야 하는 변수를 확인합니다. 다시 말하지만 이것들을 지켜주세요
알파벳 순서로.

건물 스핑크스 기술 문서
Sphinx 문서 작성은 매우 간단합니다. 모든 스핑크스를 구축하려면
선적 서류 비치:

$ ./waf 스핑크스

모델 문서만 작성하려면 다음을 수행하십시오.

$ make -C 문서/모델

생성된 문서를 보려면 브라우저에서 다음을 가리킵니다. 문서/모델/빌드/html.

보시다시피 Sphinx는 Make를 사용하여 프로세스를 안내합니다. 기본 대상은 모두 빌드합니다.
활성화된 출력 형식 NS-3 다중 페이지 HTML, 단일 페이지 단일 HTML
pdf(유액). 다중 페이지 html만 빌드하려면 다음을 추가합니다. HTML 표적:

$ make -C 문서/모델 html

이렇게 하면 빌드 시간(및 빌드 대화의 크기)을 줄이는 데 도움이 될 수 있습니다.
당신의 장을 쓰고 있습니다.

문서를 리포지토리에 커밋하기 전에 다음 없이 빌드되는지 확인하십시오.
오류 또는 경고. 빌드 프로세스는 많은 출력을 생성합니다(주로 일반적인 대화).
LaTeX에서), 이로 인해 Sphinx 경고가 있는지 확인하기 어려울 수 있습니다.
오류. 중요한 경고와 오류를 찾으려면 HTML 버전을 선택한 다음 검색
빌드 로그 경고 or 오류.

NS-3 세부 사항
스핑크스 선적 서류 비치 and 지도 시간 꽤 좋습니다. 우리는 기본을 복제하지 않습니다
대신에 선호하는 용도에 초점을 맞춥니다. NS-3.

· 다음 두 줄로 문서를 시작합니다.

.. 포함:: replace.txt
.. 하이라이트:: cpp

첫 번째 라인은 몇 가지 간단한 교체를 가능하게 합니다. 예를 들어, 타이핑 |ns3| 로 렌더링
NS-3. 두 번째는 기본 소스 코드 강조 표시 언어를 명시적으로 설정합니다.
파서 추측이 항상 정확한 것은 아니기 때문입니다. (설정도 가능합니다.
단일 코드 블록에 대한 명시적인 언어는 아래를 참조하세요.)

· 섹션:

Sphinx는 섹션 제목 표시에 대해 매우 자유롭습니다. 관습적으로 우리는 이것을 선호합니다
계층:

.. 표제 계층 구조:
------------- 장
************* 부분 (#.#)
============= 하위 섹션(#.#.#)
############# 하위 하위 섹션

· 구문 강조:

기본 구문 강조 표시를 사용하려면 소스 코드 블록을 시작하기만 하면 됩니다.

┌────────────────────────────────────────────┬── ───────────────────────────────┐
│스핑크스 소스 │ 렌더링된 출력 │
├────────────────────────────────────────────┼── ───────────────────────────────┤
│ │ 프로브니츠 액세스: │
│ ``Frobnitz`` 액세스: │ │
│ │ 푸::프로브니츠 프롭; │
│ 푸::프로브니츠 프롭; │ frob.Set(...); │
│ frob.Set (...); │ │
└────────────────────────────────────────────┴── ───────────────────────────────┘

예를 들어 특정 구문 강조 표시를 사용하려면 세게 때리다 쉘 명령:

┌───────────────────────────────┬─────────────── ───┐
│스핑크스 소스 │ 렌더링된 출력 │
├────────────────────────────────┼─────────────── ───┤
│ │ │
│ .. 소스 코드:: bash │ $ ls │
│ │ │
│ $ ls │ │
└───────────────────────────────┴─────────────── ───┘

· 속기 표기법:

이러한 약어는 다음과 같이 정의됩니다.

┌────────────────────────┬─────────────────┐
│스핑크스 소스 │ 렌더링된 출력 │
├────────────────────────┼─────────────────┤
│ │ NS-3
│ |ns3| │ │
├────────────────────────┼─────────────────┤
│ │ NS-2
│ |ns2| │ │
├────────────────────────┼─────────────────┤
│ │ │
│ |체크| │ │
├────────────────────────┼─────────────────┤
│ │ RFC 6282
│ :rfc:`6282` │ │
└────────────────────────┴─────────────────┘

문서화 독소
우리는 사용 독소 생성하는 탐색 가능한 API 설명서. Doxygen은 여러 가지를 제공합니다.
유용한 기능:

· 모든 학급 구성원의 요약표.

· 모든 클래스에 대한 상속 및 협업 그래프.

· 각 기능을 구현하는 소스 코드에 대한 링크입니다.

· 회원이 사용되는 모든 장소에 대한 링크.

· 기능 구현에 사용되는 모든 개체에 대한 링크.

· 특정 프로토콜과 관련된 모든 클래스와 같은 관련 클래스의 그룹화.

또한, 우리는 유형 ID 모든 클래스의 문서에 추가하는 시스템

· 구성 그러한 객체에 도달할 수 있는 경로.

· 모든 문서 Attributes를 포함한 Attributes 부모 클래스에 정의되어 있습니다.

· 모든 문서 더듬다 클래스에 의해 정의된 소스.

Doxygen은 특별히 표시된 주석을 찾아 소스 코드를 스캔하여 작동합니다. 그것
또한 상호 참조를 생성하여 다음을 나타냅니다. 어디에 각 파일, 클래스, 메소드 및 변수는
익숙한.

선호 스타일
Doxygen 주석에 선호되는 스타일은 JavaDoc 스타일입니다.

/ **
* 이 클래스 또는 메소드에 대한 간략한 설명.
* 인접한 줄은 하나의 단락이 됩니다.
*
* 많은 세부 사항과 함께 더 긴 설명.
*
* 빈 줄은 단락을 구분합니다.
*
* 어떤 알고리즘을 사용하여 클래스 또는 메소드가 무엇을 하는지 설명하십시오.
* 인수 및 반환 값의 단위를 설명하십시오.
*
* \note 제한 사항이나 문제가 있는지 확인하십시오.
*
* (인수가 있거나 값을 반환하는 함수의 경우:)
* \param foo 이 인수를 설명하는 간단한 명사구.
* \param bar 참고 문장 케이스 및 종료 기간.
* \return 값을 설명하는 간단한 명사구.
*
* \내부
*
* 내부 구현 세부 사항에 대해서도 논의할 수 있습니다.
* 이 자료를 이해하는 것은 사용에 필요하지 않아야 합니다.
* 클래스 또는 메소드.
*/
클래스 예

이 스타일에서 Doxygen 주석 블록은 두 개의 `*' 문자로 시작합니다. / **, 그리고 앞에
문서화되는 항목.

간단한 설명만 필요한 항목의 경우 다음 짧은 형식 중 하나가 적합합니다.

/** 소멸자 구현. */
무효 DoDispose();

int m_count; //!< 개수 ...

줄 끝 주석의 특수 형식에 유의하십시오. //!, 다음을 참조함을 나타냅니다.
선행 목.

참고할 몇 가지 항목:

· 초기 대문자를 포함하여 문장의 경우를 사용합니다.

· 구두점, 특히 문장이나 구문의 끝에 `.'를 사용하십시오.

· \짧은 태그가 필요하지 않습니다. 첫 번째 문장이 요약으로 사용됩니다.
기술.

모든 클래스, 메소드, typedef, 멤버 변수, 함수 인수 및 반환 값은
공식 API 및 구현을 구성하는 모든 소스 코드 파일에 문서화되어야 합니다.
NS-3같은 소스/ /모델/*, 소스/ /돕는 사람/* and 소스/ /utils/*.
항목에 대한 문서 소스/ /시험/* and 소스/ /예제/* 바람직하다,
하지만 필수는 아닙니다.

유능한 기능
· 상속된 구성원은 자동으로 부모로부터 문서를 상속받게 됩니다(교체 가능).
현지 문서에 따라).

1. 기본 클래스를 문서화합니다.

2. 하위 클래스 마크 상속 함수에서 일반 주석으로:

// 상속된 메서드
가상 무효 FooBar(무효);
virtual int BarFoo(더블 baz);

서명이 정확히 일치해야 하므로 공식 인수를 포함하십시오. (무효의)

정적 함수에는 작동하지 않습니다. 보다 유형 ID 가져오기, 아래의 예를 참조하세요.

건물 독소 기술 문서
Doxygen 문서 작성은 매우 간단합니다.

$ ./waf 독시젠

이것은 다음 문서 섹션을 생성하는 기본 구성을 사용하여 빌드됩니다.
모든 명시적인 주석 문서 블록이 없더라도 항목입니다. 이것은
문서화되지 않은 항목에 대한 경고를 억제하는 효과가 있지만 모든 항목이 표시되도록 합니다.
생성된 출력에서.

문서를 작성할 때 어떤 항목이 생성되는지 확인하는 것이 종종 더 유용합니다.
일반적으로 문서 누락에 대한 경고입니다. 전체 경고 목록을 보려면
문서/doxygen.warnings.report.sh 스크립트:

$ doc/doxygen.warnings.report.sh
Waf: 'build' 디렉터리를 입력하는 중입니다.
...
Waf: `build' 디렉토리를 떠납니다.
'build'가 성공적으로 완료되었습니다(3m24.094s).

전체 오류가 있는 doxygen 문서 재구축...완료.

Doxygen 경고 보고서
----------------------------------------

(모든 카운트는 하한입니다.)

모듈/디렉토리별 경고:

카운트 디렉토리
----- ---------------------
3844 src/lte/모델
1718 src/wimax/모델
1423 소스/코어/모델
....
138개의 문서화되지 않은 추가 매개변수.
----------------------------------------
15765 총 경고
경고가 있는 126개의 디렉토리

파일별 경고(알파벳순)

카운트 파일
----- ---------------------
17 문서/introspected-doxygen.h
15개의 예/routing/manet-routing-compare.cc
26개의 예시/통계/wifi-example-apps.h
....
----------------------------------------
경고가 있는 파일 967개

파일별 경고(숫자)

카운트 파일
----- ---------------------
374 src/lte/모델/lte-asn1-header.h
280 src/lte/모델/lte-rrc-sap.h
262 src/lte/모델/lte-rrc-header.h
....
----------------------------------------
경고가 있는 파일 967개

Doxygen 경고 요약
----------------------------------------
126개의 디렉토리
967 파일
경고 15765개

스크립트는 모든 경고를 표시하고 실행 시간을 단축하도록 구성을 수정합니다.
보시다시피 이 글에서 우리는 a 많은 문서화되지 않은 항목. 보고서
모듈별 경고 요약 소스/*/*, 및 파일별로 알파벳순 및 숫자순입니다.

스크립트에는 작업을 줄이고 관리하기 쉽게 만드는 몇 가지 옵션이 있습니다. 도와주기 위해,
사용 -h 옵션. 한 번 실행하여 Doxygen 빌드를 수행하고 전체
경고 로그를 사용하면 다음을 수행할 필요 없이 다양한 "필터"를 사용하여 로그 파일을 다시 처리할 수 있습니다.
전체 Doxygen 빌드를 다시 사용하여 -s 옵션. 에서 경고를 제외할 수 있습니다.
*/예제/* 파일(-e 옵션) 및/또는 */시험/* 파일(-t).

아마도 문서 주석을 작성할 때 가장 유용한 옵션은 -m , 그
일치하는 파일로만 보고서를 제한합니다. 소스/ /*, 그리고 다음과 같이 보고서를 따르세요.
실제 경고 라인. 결합 ETH 경고에 집중할 수 있습니다.
단일 모듈에서 가장 긴급:

$ doc/doxygen.warnings.report.sh -m 메쉬/도우미
...
Doxygen 경고 요약
----------------------------------------
1개의 디렉토리
3 파일
경고 149개

필터링된 경고
==========================
src/mesh/helper/dot11s/dot11s-installer.h:72: 경고: ns3::Dot11sStack 클래스의 멤버 m_root(변수)가 문서화되지 않았습니다.
src/mesh/helper/dot11s/dot11s-installer.h:35: 경고: 멤버 ns3::Dot11sStack::GetTypeId의 반환 유형이 문서화되지 않았습니다.
src/mesh/helper/dot11s/dot11s-installer.h:56: 경고: 멤버 ns3::Dot11sStack::InstallStack의 반환 유형이 문서화되지 않았습니다.
src/mesh/helper/flame/lfame-installer.h:40: 경고: ns3::FlameStack 클래스의 멤버 GetTypeId()(함수)가 문서화되지 않았습니다.
src/mesh/helper/flame/flame-installer.h:60: 경고: 멤버 ns3::FlameStack::InstallStack의 반환 유형이 문서화되지 않았습니다.
src/mesh/helper/mesh-helper.h:213: 경고: ns3::MeshHelper 클래스의 멤버 m_nInterfaces(변수)가 문서화되지 않았습니다.
src/mesh/helper/mesh-helper.h:214: 경고: ns3::MeshHelper 클래스의 m_spreadChannelPolicy(변수) 멤버가 문서화되지 않았습니다.
src/mesh/helper/mesh-helper.h:215: 경고: ns3::MeshHelper 클래스의 m_stack(변수) 멤버가 문서화되지 않았습니다.
src/mesh/helper/mesh-helper.h:216: 경고: ns3::MeshHelper 클래스의 m_stackFactory(변수) 멤버가 문서화되지 않았습니다.
src/mesh/helper/mesh-helper.h:209: 경고: 멤버 ns3::MeshHelper::CreateInterface의 매개변수가 (모두) 문서화되지 않았습니다.
src/mesh/helper/mesh-helper.h:119: 경고: 멤버 ns3::MeshHelper::SetStandard의 매개변수가 (모두) 문서화되지 않았습니다.

이제 코드를 이해하고 문서를 작성하기만 하면 됩니다!

NS-3 세부 사항
스핑크스의 경우 Doxygen 문서 and 참고 꽤 좋습니다. 우리는 복제하지 않습니다
여기에서 기본 사항에 대한 기본 사용법에 중점을 둡니다. NS-3.

· Doxygen을 사용하세요 모듈 관련 항목을 그룹화합니다.

모듈의 기본 헤더에서 Doxgyen 그룹을 만듭니다.

/ **
* \defgroup foo Foo 프로토콜.
*/

연결된 각 클래스를 그룹에 속하는 것으로 표시:

/ **
* \ingroup 푸
*
* Foo 패킷 유형.
*/
클래스 푸

· 알고 계셨나요? 형식 정의 공식적인 주장을 할 수 있나요? 이를 통해 기능을 문서화할 수 있습니다.
포인터 서명:

/ **
* 바 콜백 함수 서명.
*
* \param ale 영국식 온스 단위의 에일 파인트 크기.
*/
typedef void (* BarCallback)(const int ale);

· 복사 속성 도움말 문자열 유형 ID 가져오기 요약으로 사용하는 방법
관련 구성원에 대한 설명.

· \bugid{298} Bugzilla에서 버그 298에 대한 링크를 생성합니다.

· \p이름{foo} 설명에서 형식을 지정합니다. 매개변수 매개변수, 명확하게 하기
실제 주장을 언급하고 있습니다.

· \RFC{301} RFC 301에 대한 링크를 생성합니다.

· \내부 구현 세부 사항에 대한 논의를 시작하는 데에만 사용해야 하며
사설 기능(이미 다음과 같이 표시되어 있습니다. 사설!)

· 다음과 같은 사소한 이름으로 클래스를 만들지 마십시오. 수업 A, 테스트 스위트에서도. 이것들
클래스 이름 리터럴 `A'의 모든 인스턴스가 링크로 렌더링되도록 합니다.

위에서 언급했듯이 정적 함수는 동일한 함수의 문서를 상속하지 않습니다.
부모 클래스. NS-3 몇 가지 정적 함수를 어디서나 사용합니다. 제안된
이러한 경우에 대한 문서 블록은 다음과 같습니다.

· 기본 생성자/소멸자:

내 수업 (); //!< 기본 생성자
~MyClass(); //!< 소멸자

· 더미 소멸자 및 DoDispose:

/** 더미 소멸자, DoDispose를 참조하십시오. */
~MyClass();

/** 소멸자 구현 */
가상 무효 DoDispose();

· GetTypeId:

/ **
* 해당 유형을 등록하세요.
* \return 개체 TypeId입니다.
*/
정적 TypeId GetTypeId (void);

사용 부분집합 of NS-3 모듈
대부분의 소프트웨어 프로젝트와 마찬가지로 NS-3 모듈 수 측면에서 점점 더 커지고 있습니다.
코드 라인 및 메모리 풋프린트. 그러나 사용자는 이러한 모듈 중 일부만 사용할 수 있습니다.
한 번에. 이러한 이유로 사용자는
가능한 NS-3 연구에 실제로 필요한 모듈입니다.

이 장에서는 NS-3 intersted in 모듈
사용.

방법 가능 a 서브 세트 of NS-3's 모듈
공유 라이브러리가 구축되는 경우 모듈을 활성화하면 적어도 하나의
빌드할 라이브러리:

libns3-모듈 이름.so

모듈에 테스트 라이브러리가 있고 테스트 라이브러리가 빌드되는 경우

libns3-모듈 이름-test.so

도 지어질 것입니다. 모듈이 의존하는 다른 모듈과 해당 테스트 라이브러리
도 건설될 것입니다.

기본적으로 모든 모듈은 내장되어 있습니다. NS-3. 이러한 하위 집합을 활성화하는 방법에는 두 가지가 있습니다.
모듈 :

1. waf의 --enable-modules 옵션 사용

2. 사용 NS-3 구성 파일

사용 모듈 사용 와프의 --활성화 모듈 option
예를 들어 예제 및 테스트가 포함된 핵심 모듈만 활성화하려면 다음 명령을 시도하십시오.

$ ./waf 청소
$ ./waf 구성 --enable-examples --enable-tests --enable-modules=core
$ ./waf 빌드
$ cd 빌드/디버그/
$ls

다음 라이브러리가 있어야 합니다.

바인딩 libns3-core.so ns3 스크래치 유틸리티
예 libns3-core-test.so 샘플 src

참고 사항 ./와프 황어 무리 여기서는 어떤 모듈 라이브러리를 더 명확하게 하기 위해 단계를 수행합니다.
지어졌습니다. 당신은 할 필요가 없습니다 ./와프 황어 무리 모듈의 하위 집합을 활성화하기 위해.

test.py를 실행하면 모듈 코어에 의존하는 테스트만 실행됩니다.

테스트 24개 중 24개 통과(24개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

"코어" 모듈 대신 "네트워크" 모듈에 대해 위의 단계를 반복하고
네트워크가 코어에 의존하기 때문에 다음이 구축됩니다.

바인딩 libns3-core.so libns3-network.so ns3 스크래치 유틸리티
예 libns3-core-test.so libns3-network-test.so 샘플 src

test.py를 실행하면 코어 및 네트워크 모듈에만 의존하는 테스트가
실행될:

테스트 31개 중 31개 통과(31개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

사용 모듈 사용 전에, NS-3 구성 파일
구성 파일 .ns3rc가 다음에 추가되었습니다. NS-3 사용자가
모듈은 빌드에 포함됩니다.

하위 집합을 활성화하는 경우 NS-3 모듈에서 우선 순위 규칙은 다음과 같습니다.

1. --enable-modules 구성 문자열은 모든 .ns3rc 파일을 재정의합니다.

2. 최상위 수준의 .ns3rc 파일 NS-3 디렉터리가 다음으로 참조됩니다(있는 경우).

3. 시스템에서 검색 ~/.ns3rc 위의 두 가지가 지정되지 않은 경우

위의 어느 것도 구축할 모듈을 제한하지 않으면 WAF가 알고 있는 모든 모듈은
건설되다.

.ns3rc 파일의 유지 관리 버전은 NS-3 소스 코드 저장소는 다음 위치에 있습니다.
전에, 유틸리티 예배 규칙서. 그 이유는 파일이 최상위 디렉터리에 있는 경우입니다.
리포지토리를 활성화하는 관리자로부터 실수로 체크인하는 경향이 있습니다.
사용하려는 모듈. 따라서 사용자는 .ns3rc를 수동으로 복사해야 합니다.
유틸리티 디렉토리를 원하는 위치(최상위 디렉토리 또는 홈 디렉토리)로 이동하여
지속적인 모듈식 빌드 구성을 활성화합니다.

당신이 최상위 레벨에 있다고 가정하면 NS-3 디렉토리에서 .ns3rc의 사본을 얻을 수 있습니다.
에 있는 파일 유틸리티 디렉토리는 다음과 같습니다.

$cp utils/.ns3rc .

이제 .ns3rc 파일이 최상위 수준에 있어야 합니다. NS-3 디렉토리에 다음이 포함되어 있습니다.
다음 :

#! /usr/빈/환경 파이썬

# ns-3이 실행될 때 활성화될 모듈 목록입니다.
# 나열된 모듈에 의존하는 모듈도 활성화됩니다.
#
# 'all_modules'를 선택하면 모든 모듈을 활성화할 수 있습니다.
modules_enabled = ['all_modules']

# 예제를 실행하려면 이것을 true로 설정하십시오.
examples_enabled = 거짓

# 테스트를 실행하려면 이 값을 true로 설정합니다.
테스트_활성화 = 거짓

즐겨 사용하는 편집기를 사용하여 .ns3rc 파일을 수정하여
다음과 같은 예제 및 테스트:

#! /usr/빈/환경 파이썬

# ns-3이 실행될 때 활성화될 모듈 목록입니다.
# 나열된 모듈에 의존하는 모듈도 활성화됩니다.
#
# 'all_modules'를 선택하면 모든 모듈을 활성화할 수 있습니다.
modules_enabled = ['코어']

# 예제를 실행하려면 이것을 true로 설정하십시오.
example_enabled = 참

# 테스트를 실행하려면 이 값을 true로 설정합니다.
tests_enabled = 참

다음 명령을 시도하면 이제 코어 모듈만 활성화됩니다.

$ ./waf 청소
$ ./waf 구성
$ ./waf 빌드
$ cd 빌드/디버그/
$ls

다음 라이브러리가 있어야 합니다.

바인딩 libns3-core.so ns3 스크래치 유틸리티
예 libns3-core-test.so 샘플 src

참고 사항 ./와프 황어 무리 여기서는 어떤 모듈 라이브러리를 더 명확하게 하기 위해 단계를 수행합니다.
지어졌습니다. 당신은 할 필요가 없습니다 ./와프 황어 무리 모듈의 하위 집합을 활성화하기 위해.

test.py를 실행하면 모듈 코어에 의존하는 테스트만 실행됩니다.

테스트 24개 중 24개 통과(24개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

"코어" 모듈 대신 "네트워크" 모듈에 대해 위의 단계를 반복하고
네트워크가 코어에 의존하기 때문에 다음이 구축됩니다.

바인딩 libns3-core.so libns3-network.so ns3 스크래치 유틸리티
예 libns3-core-test.so libns3-network-test.so 샘플 src

test.py를 실행하면 코어 및 네트워크 모듈에만 의존하는 테스트가
실행될:

테스트 31개 중 31개 통과(31개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

활성화/비활성화 NS-3 테스트 and
이 어플리케이션에는 XNUMXµm 및 XNUMXµm 파장에서 최대 XNUMXW의 평균 출력을 제공하는 NS-3 배포에는 유효성을 검사하는 데 사용되는 많은 예제와 테스트가 포함됩니다. NS-3
체계. 그러나 사용자는 이러한 예제와 테스트가 항상 실행되는 것을 원하지 않을 수 있습니다.
설치 NS-3.

이 장에서는 빌드 방법에 대해 설명합니다. NS-3 예제와 테스트가 있든 없든.

방법 켜기 끄기 and 테스트 in NS-3
에서 예제 및 테스트를 활성화/비활성화하는 3가지 방법이 있습니다. NS-3:

1. build.py를 사용할 때 NS-3 처음으로 지어진다

2. waf를 한 번만 사용하기 NS-3 지어졌다

3. 사용 NS-3 구성 파일을 한 번 NS-3 지어졌다

켜기 끄기 and 테스트 사용 build.py
다음과 같은 경우 build.py를 사용하여 예제 및 테스트를 활성화/비활성화할 수 있습니다. NS-3 처음으로 지어진
시간.

기본적으로 예제와 테스트는 내장되어 있지 않습니다. NS-3.

ns-3-allinone 디렉토리에서 다음을 빌드할 수 있습니다. NS-3 예제나 테스트 없이 간단하게
다음을 수행하여 :

$ ./build.py

최상위 수준에서 test.py 실행 NS-3 디렉토리는 이제 예제나 테스트를 수행하지 않습니다.
운영:

테스트 0개 중 0개 통과(0개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

빌드를 원하시면 NS-3 예제와 테스트를 사용하여 다음을 수행하십시오.
ns-3-allinone 디렉토리:

$ ./build.py --enable-examples --enable-tests

최상위 수준에서 test.py 실행 NS-3 디렉토리는 모든 예제와 테스트를 유발합니다.
실행하려면 :

테스트 170개 중 170개 통과(170개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

켜기 끄기 and 테스트 사용 waf
waf를 사용하여 예제 및 테스트를 한 번 활성화/비활성화할 수 있습니다. NS-3 구축되었습니다.

기본적으로 예제와 테스트는 내장되어 있지 않습니다. NS-3.

최상위 수준에서 NS-3 디렉토리에서 빌드할 수 있습니다. NS-3 예제나 테스트 없이 간단하게
다음을 수행하여 :

$ ./waf 구성
$ ./waf 빌드

이제 test.py를 실행하면 예제나 테스트가 실행되지 않습니다.

테스트 0개 중 0개 통과(0개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

빌드를 원하시면 NS-3 예제와 테스트를 통해 위에서부터 다음을 수행하세요.
수평 NS-3 예배 규칙서:

$ ./waf 구성 --enable-examples --enable-tests
$ ./waf 빌드

test.py를 실행하면 모든 예제와 테스트가 실행됩니다.

테스트 170개 중 170개 통과(170개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

켜기 끄기 and 테스트 사용 전에, NS-3 구성 파일
구성 파일 .ns3rc가 다음에 추가되었습니다. NS-3 사용자가 다음을 지정할 수 있도록 합니다.
예제와 테스트를 빌드해야 합니다. 이 파일을 사용하여 활성화/비활성화할 수 있습니다.
예제와 테스트를 한 번 NS-3 구축되었습니다.

비활성화 예제 및 테스트를 활성화할 때 우선 순위 규칙은 다음과 같습니다.

1. --enable-examples/--disable-examples 구성 문자열은 모든 .ns3rc 파일을 재정의합니다.

2. --enable-tests/--disable-tests 구성 문자열은 모든 .ns3rc 파일을 재정의합니다.

3. 최상위 수준의 .ns3rc 파일 NS-3 디렉터리가 다음으로 참조됩니다(있는 경우).

4. 시스템에서 검색 ~/.ns3rc 이전 단계에서 .ns3rc 파일을 찾지 못한 경우

위의 항목 중 어느 것도 존재하지 않으면 예제와 테스트가 구축되지 않습니다.

.ns3rc 파일의 유지 관리 버전은 NS-3 소스 코드 저장소는 다음 위치에 있습니다.
전에, 유틸리티 예배 규칙서. 그 이유는 파일이 최상위 디렉터리에 있는 경우입니다.
리포지토리를 활성화하는 관리자로부터 실수로 체크인하는 경향이 있습니다.
사용하려는 모듈. 따라서 사용자는 .ns3rc를 수동으로 복사해야 합니다.
유틸리티 디렉토리를 원하는 위치(최상위 디렉토리 또는 홈 디렉토리)로 이동하여
예제 및 테스트를 지속적으로 활성화합니다.

당신이 최상위 레벨에 있다고 가정하면 NS-3 디렉토리에서 .ns3rc의 사본을 얻을 수 있습니다.
에 있는 파일 유틸리티 디렉토리는 다음과 같습니다.

$cp utils/.ns3rc .

이제 .ns3rc 파일이 최상위 수준에 있어야 합니다. NS-3 디렉토리에 다음이 포함되어 있습니다.
다음 :

#! /usr/빈/환경 파이썬

# ns-3이 실행될 때 활성화될 모듈 목록입니다.
# 나열된 모듈에 의존하는 모듈도 활성화됩니다.
#
# 'all_modules'를 선택하면 모든 모듈을 활성화할 수 있습니다.
modules_enabled = ['all_modules']

# 예제를 실행하려면 이것을 true로 설정하십시오.
examples_enabled = 거짓

# 테스트를 실행하려면 이 값을 true로 설정합니다.
테스트_활성화 = 거짓

최상위 수준에서 NS-3 디렉토리에서 빌드할 수 있습니다. NS-3 예제나 테스트 없이 간단하게
다음을 수행하여 :

$ ./waf 구성
$ ./waf 빌드

이제 test.py를 실행하면 예제나 테스트가 실행되지 않습니다.

테스트 0개 중 0개 통과(0개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

빌드를 원하시면 NS-3 예제와 테스트를 통해 좋아하는 편집기를 사용하여 변경
examples_enabled 및 tests_enabled 파일에 대한 .ns3rc 파일의 값이 True여야 합니다.

#! /usr/빈/환경 파이썬

# ns-3이 실행될 때 활성화될 모듈 목록입니다.
# 나열된 모듈에 의존하는 모듈도 활성화됩니다.
#
# 'all_modules'를 선택하면 모든 모듈을 활성화할 수 있습니다.
modules_enabled = ['all_modules']

# 예제를 실행하려면 이것을 true로 설정하십시오.
example_enabled = 참

# 테스트를 실행하려면 이 값을 true로 설정합니다.
tests_enabled = 참

최상위 수준에서 NS-3 디렉토리에서 빌드할 수 있습니다. NS-3 간단하게 예제와 테스트로
하기:

$ ./waf 구성
$ ./waf 빌드

test.py를 실행하면 모든 예제와 테스트가 실행됩니다.

테스트 170개 중 170개 통과(170개 통과, 0개 건너뛰기, 0개 실패, 0개 충돌, 0개 valgrind 오류)

문제해결
이 장에서는 빌드 또는 실행 시 발생할 수 있는 일반적인 오류에 대한 정보를 게시합니다.
NS-3 프로그램.

위키(http://www.nsnam.org/wiki/Troubleshooting) 기여했을 수 있습니다
항목.

짓다 오류
실행 시간 오류
경우에 따라 성공적으로 빌드한 후 프로그램에 오류가 발생할 수 있습니다. 이들은 런타임
오류가 발생하며 일반적으로 메모리가 손상되거나 포인터 값이 예기치 않게 변경될 때 발생할 수 있습니다.
없는.

발생할 수 있는 상황의 예는 다음과 같습니다.

$ ./waf --tcp-point-to-point 실행
디렉토리 '/home/tomh/ns-3-nsc/build' 입력 중
컴파일이 성공적으로 끝났습니다
['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] 명령이 코드 -11로 종료됨

오류 메시지는 프로그램이 성공적으로 종료되지 않았다고 말하지만 명확하지 않습니다.
이 정보에서 무엇이 잘못되었을 수 있습니다. 더 자세히 조사하려면 아래에서 실행해 보십시오.
전에, gdb 디버거:

$ ./waf --run tcp-point-to-point --command-template="gdb %s"
디렉토리 '/home/tomh/ns-3-nsc/build' 입력 중
컴파일이 성공적으로 끝났습니다
GNU gdb 레드햇 리눅스(6.3.0.0-1.134.fc5rh)
저작권 2004 자유 소프트웨어 재단, Inc.
GDB는 GNU General Public License가 적용되는 무료 소프트웨어이며 귀하는
특정 조건 하에서 이를 변경하거나 사본을 배포하는 것을 환영합니다.
조건을 보려면 "show copying"을 입력하세요.
GDB에 대한 보증은 전혀 없습니다. 자세한 내용은 "보증 표시"를 입력하십시오.
이 GDB는 "i386-redhat-linux-gnu"로 구성되었습니다...호스트 libthread_db 사용
라이브러리 "/lib/libthread_db.so.1".

(gdb) 실행
시작 프로그램: /home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point
대상 메모리에서 읽은 공유 개체에서 기호 읽기...완료.
로드된 시스템은 0xf5c000에서 DSO를 제공했습니다.

프로그램 수신 신호 SIGSEGV, 분할 오류.
메인의 0x0804aa12(argc=1, argv=0xbfdfefa4)
../examples/tcp-point-to-point.cc:136에서
136포인트 localSocket = socketFactory->CreateSocket();
(gdb) p 로컬 소켓
$1 = {m_ptr = 0x3c5d65}
(gdb) p 소켓팩토리
$2 = {m_ptr = 0x0}
(gdb) 종료
프로그램이 실행 중입니다. 그래도 종료하시겠습니까? (y 또는 n) y

먼저 프로그램이 호출된 방식에 주목하십시오.
명령 템플릿 "gdb %s".

이는 널 포인터 소켓Factory를 역참조하려는 시도가 있었음을 알려줍니다.

gdb가 제안한 대로 tcp-point-to-point의 136번째 줄을 살펴보겠습니다.

Ptr socketFactory = n2->GetObject (Tcp::iid);
Ptr localSocket = socketFactory->CreateSocket();
localSocket->바인드();

여기서 범인은 GetObject의 반환 값이 확인되지 않고 다음과 같을 수 있다는 것입니다.
없는.

때로는 다음을 사용해야 할 수도 있습니다. Valgrind 기억 체커 더 미묘한 오류에 대해서는. 다시,
유사하게 valgrind 사용을 호출합니다.

$ ./waf --run tcp-point-to-point --command-template="valgrind %s"

SOURCE


이 문서는 reStructuredText for 스핑크스 그리고 에서 유지됩니다
문서/매뉴얼 ns-3의 소스 코드 디렉토리.

onworks.net 서비스를 사용하여 온라인에서 ns-3-manual 사용


무료 서버 및 워크스테이션

Windows 및 Linux 앱 다운로드

  • 1
    팩 매니저
    팩 매니저
    PAC는 다음을 위한 Perl/GTK 대체품입니다.
    SecureCRT/퍼티/등(리눅스
    ssh/telnet/... gui)... GUI를 제공합니다.
    연결 구성: 사용자,
    비밀번호, EXPECT 규칙...
    PAC 관리자 다운로드
  • 2
    GeoServer
    GeoServer
    GeoServer는 오픈 소스 소프트웨어입니다.
    사용자를 허용하는 Java로 작성된 서버
    지리 공간 데이터를 공유하고 편집합니다.
    상호 운용성을 위해 설계되었으며,
    출판 다...
    GeoServer 다운로드
  • 3
    반딧불 III
    반딧불 III
    무료 오픈 소스 개인 금융
    관리자. Firefly III는
    복식 부기 시스템. 당신은 할 수 있습니다
    신속하게 입력하고 구성
    거래 나...
    Firefly III 다운로드
  • 4
    아파치 오픈오피스 확장
    아파치 오픈오피스 확장
    Apache의 공식 카탈로그
    오픈오피스 확장. 당신은 찾을 수 있습니다
    사전에서 확장까지
    PDF 파일을 가져오고 연결하는 도구
    내선으로...
    Apache OpenOffice 확장 다운로드
  • 5
    맨티스BT
    맨티스BT
    Mantis는 쉽게 배포할 수 있는 웹
    제품 버그를 지원하는 기반 버그 추적기
    추적. PHP, MySQL 및
    웹 서버. 데모를 확인하고 호스팅
    제안...
    맨티스BT 다운로드
  • 6
    LAN 메신저
    LAN 메신저
    LAN Messenger는 p2p 채팅 응용 프로그램입니다.
    인트라넷 통신용이며
    서버가 필요합니다. 다양한 핸디
    다음과 같은 기능이 지원됩니다.
    알림...
    LAN 메신저 다운로드
  • 더»

Linux 명령

  • 1
    계속
    계속
    abidw - ELF의 ABI 직렬화
    파일 abidw는 ELF에서 공유 라이브러리를 읽습니다.
    형식을 지정하고 XML 표현을 내보냅니다.
    ABI를 표준 출력으로. 그만큼
    방출 ...
    abidw 실행
  • 2
    아빌린트
    아빌린트
    abilint - abigail ABI 유효성 검사
    표현 abilint는 네이티브를 구문 분석합니다.
    내보낸 ABI의 XML 표현
    by abidw. XML을 구문 분석한 후
    표현...
    실행 빌린트
  • 3
    코어센드msg
    코어센드msg
    coresendmsg - CORE API 메시지 보내기
    코어 데몬 데몬으로 ...
    coresendmsg 실행
  • 4
    core_server
    core_server
    core_server - 기본 서버
    SpamBayes. 설명: 현재 서비스 중
    웹 인터페이스만. 연결
    다양한 프로토콜에 대한 리스너는 미정입니다.
    이건 ...
    core_server 실행
  • 5
    fwflash
    fwflash
    fwflash - 이미지 파일을 플래시하는 프로그램
    연결된 NXT 장치에...
    fwflash 실행
  • 6
    fwts 수집
    fwts 수집
    fwts-collect - fwts에 대한 로그 수집
    버그 보고. ...
    fwts-collect를 실행하세요
  • 더»

Ad