620 likes | 810 Views
NS Tutorial. PMIPv6 Implementation in NS HyonYoung Choi (commani@gmail.com). 목차. NS 기초 PMIPv6 Implementation. NS 기초. Tcl 와 C++ 의 연관관계. Tcl Object 와 C++ Object 의 매핑 일반적으로 Tcl Object 당 C++ Object 가 존재 TclClass 가 Tcl 에서 C++ object 를 만들 수 있도록 해줌
E N D
NS Tutorial PMIPv6 Implementation in NS HyonYoung Choi (commani@gmail.com)
목차 • NS 기초 • PMIPv6 Implementation
Tcl와 C++의 연관관계 • Tcl Object와 C++ Object의 매핑 • 일반적으로 Tcl Object당 C++ Object가 존재 • TclClass가 Tcl에서 C++ object를만들 수 있도록 해줌 • TclClass의 생성자 인수가 Tcl에서 사용가능한 Object 이름 set mag [new Agent/PMIPv6/MAG] static class MAGAgentClass : public TclClass { public: MAGAgentClass() : TclClass("Agent/PMIPv6/MAG") {} TclObject* create(int, const char*const*) { return (new MAGAgent()); } } class_magagent; class MAGAgent : public PMIPv6Agent { public: MAGAgent(); …… };
NS의 함수(1/4) • 함수의 정의 • Tcl: instproc를 사용하여 정의 • C++: TclObject class의 command 함수 overriding후 if-else-if로 string match Classifier/Addr/PMIPv6Dest instproc install {dst target} { $self instvar classifier_ $classifier_ install $dst $target } int MAGAgent::command(int argc, const char*const* argv) { if(argc==3) { if(strcmp(argv[1], "new-mn") == 0) { …… return TCL_OK; } else if(strcmp(argv[1], "set-lmaa") == 0) { …… return (PMIPv6Agent::command(argc, argv)); }
NS의 함수(2/4) • Tcl 함수와 C++ 함수의 장단점
NS의 함수(3/4) • Tcl 함수와 C++ 함수의 상호접근 • 함수 호출의 우선순위: Tcl > C++ • Tcl의 함수에서 찾은 뒤 없으면 C++의 command 함수 호출 • Tcl과 C++에 같은 이름의 함수가 있는 경우 • Tcl의 함수 호출: 일반적인 함수 호출 • C++의 함수 호출: 함수이름 앞에 “cmd”를 추가 Classifier/Addr/PMIPv6Dest instproc clear { dst } { $self instvar classifier_ $classifier_ clear $dst } Classifier/Addr/PMIPv6Dest instproc clear-by-dest { addr } { $self cmd clear $addr }
NS의 함수(4/4) • Tcl 함수와 C++ 함수의 상호접근 (cont’d) • C++에서 Tcl 함수 호출 • Tcl::eval, Tcl::evalf 함수 사용 • C++에서 Tcl 함수의 결과값 얻기 • Tcl::result 함수 사용 • C++ 함수에서 Tcl로 결과값 반환(return) • Tcl::resultf 함수 사용 Tcl& tcl = Tcl::instance(); tcl.evalf("%s setup-route %ld %ld", name(), bule->mn_prefix(), bule->lmaa()); tcl.evalf ("%s getRXThresh",netif_->name()); RXThreshold_ = atof (tcl.result()); if (strcmp(argv[1], "ifq") == 0) { tcl.resultf("%s", ifq_->name()); return (TCL_OK); }
새로운 packet type 만들기(1/4) • 1. Packet 헤더 작성 • offset_, offset(), access(Packet *p) 작성 (필수) • HDR_XXX define 작성 (옵션) • offset_이 static이므로 C++소스 파일에 선언 #define HDR_PMIPv6((p) ((struct hdr_pmipv6*)(p)->access(hdr_pmipv6::offset_)) struct hdr_pmipv6 { ……(패킷 헤더의 필드들) static int offset_; inline static int& offset() { return offset_; } inline static hdr_pmipv6* access(Packet* p) { return (hdr_pmipv6*) p->access(offset_); } }; int hdr_pmipv6::offset_;
새로운 packet type 만들기(2/4) • 2. PacketHeaderClass 작성 • Packet Manager용 class 작성 • 3. ns-packet.tcl 수정 (ns-2.29/tcl/lib/) • PacketHeaderClass 생성자의 이름과 일치해야 함 static class PMIPv6HeaderClass : public PacketHeaderClass { public: PMIPv6HeaderClass() : PacketHeaderClass("PacketHeader/PMIPv6", sizeof(hdr_pmipv6)) { bind_offset(&hdr_pmipv6::offset_); } } class_pmipv6hdr; foreach prot { …… PMIPv6 } { add-packet-header $prot }
새로운 packet type 만들기(3/4) • 4. packet.h 수정 (ns-2.29/common/) • enum packet_t의 PT_NTYPE 전에 넣음 • name_ 작성: trace에 표시되는 패킷 type enum packet_t { …… //PMIP6: type PT_PBU, PT_PBACK, PT_NTYPE // This MUST be the LAST one }; p_info() { …… name_[PT_PBU]="pbu"; name_[PT_PBACK]="pba"; name_[PT_NTYPE]= "undefined"; }
새로운 packet type 만들기(4/4) • 패킷 생성 • allockpkt 함수 사용 • hdr_cmn 정보 반드시 채울 것 • size: 실제 전송되는 총 패킷 크기 • ptype: packet type Packet *p = allocpkt(); hdr_cmn *hdrc = HDR_CMN(p); hdr_ip *iph = HDR_IP(p); hdr_pmipv6 *h = HDR_PMIPv6(p); hdrc->size() = IPv6_HEADER_SIZE; hdrc->ptype() = PT_PBU; hdrc->size() += PBU_SIZE; iph->saddr() = proxy_coa; iph->sport() = port(); ……
List 관리 – Tcl (1/2) • 배열로 처리 (index에 문자도 가능) • 중복처리를 쉽게 할 수 있음 • 간단한 형태만 가능 • 1. List 추가 • 덮어 쓰는 경우는 바로 추가 • 이미 존재하면 에러인 경우는 이미 있는지 검사 • info exists 사용 Node instproclistadd {index value} { $self instvar List_ if { ! [info exists List_($index)] || $List_($index)==“”} { set List_($index) $value } }
List 관리 – Tcl (2/2) • 2. List 제거 • 존재 하는 경우 “”로 만들거나 unset Node instproc listdel {index} { $self instvar List_ if { [info exists List_($index)] && $List_($index)!=“”} { set List_($index) “” unset List_($index) } }
List 관리 - C++ (1/2) • List 관련매크로 활용 • 1. LIST_HEAD 정의 • 데이터 클래스와 그에 연결되는 head 정의 • 2. 리스트 각 entry 내용 정의 • insert_entry. next_entry, remove_entry, link 정의 class BULEntry; LIST_HEAD(bulEntry, BULEntry); class BULEntry { …… public: inline void insert_entry(struct bulEntry *head) { LIST_INSERT_HEAD(head, this, link); } BULEntry* next_entry(void) const { return link.le_next; } inline void remove_entry() { LIST_REMOVE(this, link); } protected: LIST_ENTRY(BULEntry) link; };
List 관리 - C++ (2/2) • 3. List 사용 • List 변수 정의 • List에 추가 • List에서 찾기 class MAGAgent : public PMIPv6Agent { …… struct bulEntry bul_list_; void MAGAgent::process_new_mn(int32_t mn_id) { …… bule->insert_entry(&bul_list_); BULEntry *MAGAgent::find_bule(int32_t mn_id) { for(BULEntry *bule=bul_list_.lh_first; bule; bule=bule->next_entry()) { if(bule->mn_id() == mn_id) return bule; } return NULL; }
Timer 관리 - Tcl • ns simulator의 at 함수 활용 • 1. timeout시 실행될 함수 정의 • 2. Timer 시작과중단 Node instproc record {} { set ns [Simulator instance] …….. } Node instproc start { mnaddr } { $self instvar RTimer_ set ns [Simulator instance] set now [$ns now] if {![info exists RTimer_($mnaddr)] || $RTimer_($mnaddr) == ""} { $ns at [expr $now + 1.0] “$self record” } } Node instproc stop { mnaddr } { $self instvar RTimer_ set ns [Simulator instance] if {[info exists RTimer_($mnaddr)] && $RTimer_($mnaddr) != ""} { $ns cancel $RTimer_($mnaddr) set Rtimer_($mnaddr) “” } }
Timer 관리 – C++ (1/2) • TimerHandler를 사용하여 구현 • 1. TimerHandler를상속한 클래스 정의 • 생성자에 호출할 정보를 넣도록 작성 • expire 함수를 반드시 overriding class BindingTimer : public TimerHandler { public: BindingTimer(PMIPv6Agent *pagent, void *data): TimerHandler() { pagent_ = pagent; data_ = data; } protected: PMIPv6Agent *pagent_; void *data_; void expire(Event *); };
Timer 관리 – C++ (2/2) • 2. expire 함수 정의 • Timer를 설정해 놓으면 지정된 시간 이후 호출되는 함수 • 생성자로 받은 정보를 사용해 원하는 작업 수행 • 3. timer 시작과 중단 하기 • resched 함수와 cancel 함수 사용 void BindingTimer::expire(Event *) { pagent_->BindingTimeout(data_); } bule->BULTimer_.resched(1.0); bule->BULTimer_.cancel ();
PMIPv6 Objects (1/2) • PacketHeader/PMIPv6 (struct hdr_pmipv6) • PBU, PBACK 패킷을 위한 헤더 • PacketHeader/IP6Encap (struct hdr_ip6encap) • IPv6-in-IPv6 패킷을 위한 헤더 • Agent/PMIPv6 (class PMIPv6Agent) • LMA와 MAG의 상위 클래스 • Agent/PMIPv6/LMA (class LMAAgent) • LMA Agent • Agent/PMIPv6/MAG (class MAGAgent) • MAG Agent
PMIPv6 Objects (2/2) • PMIPv6Encapsulator (class PMIPv6Encapsulator) • IPv6-in-IPv6 Encapsulator • Classifier/Addr/PMIPv6Src (class PMIPv6Src) • Source address based routing • Classifier/Addr/PMIPv6Dest (class PMIPv6Dest) • Destination address routing • Classifier/Addr/PMIPv6Decapsulator (class PMIPv6Decapsulator) • IPv6-in-IPv6 Decapsulator
General Initialization • Hierarchical routing • MN 패킷이 LMA로 routing 되도록 하기 위함 • Wireless configuration # set up for hierarchical routing (needed for routing over a basestation) $ns node-config -addressType hierarchical AddrParams set domain_num_ 5 ;# domain number AddrParams set cluster_num_ {1 1 1 1 1} AddrParams set nodes_num_ {1 2 1 1 1} # Parameter for wireless nodes set opt(chan) Channel/WirelessChannel ;# channel type set opt(prop) Propagation/TwoRayGround ;# radio-propagation model set opt(netif) Phy/WirelessPhy ;# network interface type set opt(mac) Mac/802_11 ;# MAC type set opt(ifq) Queue/DropTail/PriQueue ;# interface queue type set opt(ll) LL ;# link layer type set opt(ant) Antenna/OmniAntenna ;# antenna model set opt(ifqlen) 50 ;# max packet in ifq set opt(adhocRouting) DSDV ;# routing protocol
PMIPv6 Initialization (1/8) • LMA • LMA Node 생성 후 install-lma 함수 호출 • 주의사항: duplex-link 호출 전에 install-lma 호출 set lma [$ns node 1.0.0] #attach Agent/PMIPv6/LMA to the LMA set lma_pm [$lma install-lma] #BE CAREFUL!. PMIPv6 agent must be installed before connecting link(duplex-link) $ns duplex-link $lma $router 100Mb $opt(dfLinkDelay) DropTail
PMIPv6 Initialization (2/8) • LMA (cont’d) • install-lma 함수
PMIPv6 Initialization (3/8) • install-lma 함수 Node instproc install-lma {} { $self instvar classifier_ decap_ dmux_ agents_ $self instvar pmip6_agent_ $self instvardst_classifier_ old_classifier_ #attach pmip6 agent set lma [new Agent/PMIPv6/LMA] $self attach $lma [$lma set default_port_] set pmip6_agent_ $lma #attach dest classifier set old_classifier_ $classifier_ set dst_classifier_ [new Classifier/Addr/PMIPv6Dest] $dst_classifier_ set mask_ 0xffffffff $dst_classifier_ set shift_ 0 $dst_classifier_ defaulttarget $old_classifier_
PMIPv6 Initialization (4/8) • install-lma 함수 (cont’d) set nodetype [[Simulator instance] get-nodetype] $self insert-entry [$self get-module $nodetype] $dst_classifier_ $dst_classifier_ install-by-dest 0 $old_classifier_ #attach decapsulator set decap_ [new Classifier/Addr/PMIPv6Decapsulator] $decap_ set mask_ 0xffffffff $decap_ set shift_ 0 $decap_ defaulttarget $dst_classifier_ lappend $agents_ $decap_ $dmux_ install [Simulator set PMIPv6_TUNNEL_PORT] $decap_ return $lma }
PMIPv6 Initialization (5/8) • MAG • NIST settings: bssid, channel, beacon 설정 • install-mag 호출 • set-lmaa 호출: LMA Address 지정 • 802.11 MAC에 trigger를 위한 설정 set mag1 [$ns node 3.0.0] $mag1 random-motion 0 $mag1 set X_ 100.0 $mag1 set Y_ 200.0 $mag1 set Z_ 0.0 #NIST settings set mag1_mac [$mag1 getMac 0] set mag1_addr [$mag1_mac id] $mag1_mac bss_id $mag1_addr $mag1_mac set-channel 1 $mag1_mac enable-beacon #install PMIPv6/MAG agent to the MAG1 set mag1_pm [$mag1 install-mag] set lmaa [$lma node-addr] $mag1_pm set-lmaa [AddrParams addr2id $lmaa] #setup 802.11 MAC to support MN ATTACH Event $mag1_mac set use_pmip6_ext_ 1 $mag1_mac pmip6-agent $mag1_pm $ns duplex-link $mag1 $router 100Mb $opt(dfLinkDelay) DropTail
PMIPv6 Initialization (6/8) • MAG (cont’d)
PMIPv6 Initialization (7/8) • install-mag 함수 Node instproc install-mag {} { $self instvar classifier_ dmux_ agents_ ll_ $self instvar pmip6_agent_ $self instvar src_classifier_ old_classifier_ $self instvar decap_ set mag [new Agent/PMIPv6/MAG] $self attach $mag [$mag set default_port_] set pmip6_agent_ $mag #attach src classifier set old_classifier_ $classifier_ set src_classifier_ [new Classifier/Addr/PMIPv6Src] $src_classifier_ set mask_ 0xffffffff $src_classifier_ set shift_ 0 $src_classifier_ defaulttarget $old_classifier_
PMIPv6 Initialization (8/8) • install-mag 함수 (cont’d) set nodetype [[Simulator instance] get-nodetype] $self insert-entry [$self get-module $nodetype] $src_classifier_ $src_classifier_ install-by-src 0 $old_classifier_ #attach decap_ set decap_ [new Classifier/Addr/PMIPv6Decapsulator] $decap_ set mask_ 0xffffffff $decap_ set shift_ 0 lappend $agents_ $decap_ $dmux_ install [Simulator set PMIPv6_TUNNEL_PORT] $decap_ # LL points previous hier_classifier as up-target # we should change this to our classifier if {[info exists ll_(0)] && $ll_(0) != ""} { $ll_(0) up-target $src_classifier_ } return $mag }
Binding Update Process (1/3) • Sending PBU PMIPv6Agent Mac802_11 MAGAgent new-mn/TCL command() process_new_mn() -find_bule send_pbu() create_pbu() send()
Binding Update Process (2/3) • Receiving PBU/Sending PBACK PMIPv6Agent LMAAgent recv() process_packet() process_pbu() -find_bce() setup_route() setup-route/TCL -get-pmip6-encap/TCL send_pback() create_pback() send()
Binding Update Process (3/3) • Receiving PBACK PMIPv6Agent MAGAgent recv() process_packet() process_pback() -find_bule() setup_route() bule_state: BUL_S_SETUP setup-route/TCL -get-pmip6-encap/TCL clear_route() bule_state: BUL_S_DELETE clear-route/TCL
Data Process (1/2) • LMA MAG PMIPv6Decapsulator PMIPv6Dest PMIPv6Encapsulator recv() classify() recv() target_->recv() recv() find() link->recv()
Data Process (2/2) • MAG LMA PMIPv6Decapsulator PMIPv6Src PMIPv6Encapsulator recv() classify() recv() target_->recv() recv() find() link->recv()
802.11 MAC Operation (1/5) • 802.11 MAC에서 Layer 2 Trigger 발생 PMIPv6Agent Mac802_11 MAGAgent new-mn/TCL command() process_new_mn() -find_bule send_pbu() create_pbu() send()
802.11 MAC Operation (2/5) • 802.11 MAC 수정 • class Mac802_11 (ns-2.29/mac/mac-802_11.h) • use_pmip6_ext_: PMIPv6용 L2 trigger 사용 • pmip6_agent_: L2 trigger를 전달할 PMIPv6 agent • pmip6-agent 함수 추가 class Mac802_11 : public Mac { …… //PMIPv6 int use_pmip6_ext_; Agent* pmip6_agent_; //End PMIPv6 int Mac802_11::command(int argc, const char*const* argv) { …… else if (strcmp(argv[1], "pmip6-agent") == 0) { if(use_pmip6_ext_==0) return TCL_ERROR; pmip6_agent_ = (Agent *)TclObject::lookup(argv[2]); return TCL_OK; }
802.11 MAC Operation (3/5) • 802.11 MAC 수정 (cont’d) • 802.11 MAC에서 AP address 적용 버그 수정 • Link 가 끊어졌을 때 자동으로 스캔하도록 수정 inline int Mac802_11::hdr_dst(char* hdr, int dst ) { …… //PMIPv6 if(dst != bss_id_) STORE4BYTE(&bss_id_, (dh->dh_3a)); //end PMIPv6 void Mac802_11::link_disconnect (link_down_reason_t reason) { …… //PMIPv6 if(!mih_) { //If disconnected, it automatically starts scanning Tcl& tcl = Tcl::instance(); tcl.evalf ("%s autoscan", name()); } //PMIPv6 end
802.11 MAC Operation (4/5) • 802.11 MAC 수정 (cont’d) • AP를 발견하면 바로 연결되도록 수정 void Mac802_11::nextScan () { …… //PMIPv6 if(!mih_) { BSSDescription *n; n=scan_status_.resp->bssDesc_head.lh_first; //store structure scan bssid/channel Vincent Gauthier channelIDAfterScan_[n->bss_id()] = n->channel(); link_connect(n->bss_id()); } //PMIPv6 end
802.11 MAC Operation (5/5) • Layer 2 Trigger 발생 • AssocRes 메시지가 도착하면 시작 • PMIPv6 agent의 new-mn 함수 호출 void Mac802_11::recvACK(Packet *p) { …… //PMIPv6 if(use_pmip6_ext_) { if(pmip6_agent_) { Tcl& tcl = Tcl::instance(); tcl.evalf("%s new-mn %d", pmip6_agent_->name(), n->id()); } } //end PMIPv6
MAG Operation #1 (1/5) • MAG에서 L2 Trigger 처리 후 PBU 전송 PMIPv6Agent Mac802_11 MAGAgent new-mn/TCL command() process_new_mn() -find_bule send_pbu() create_pbu() send()
MAG Operation #1 (1/4) • new-mn 함수 이후 process_new_mn 호출 • process_new_mn 함수 • Binding Update List 처리 • BUL entry (bule) • PBU retransmission timer • 마지막 PBU 저장 (pktPBU_) int MAGAgent::command(int argc, const char*const* argv) { …… else if(argc==3) { if(strcmp(argv[1], "new-mn") == 0) { uint32_t id; id = atoi(argv[2]); process_new_mn(id); return TCL_OK; }
MAG Operation #1 (2/4) • process_new_mn 함수 (cont’d) void MAGAgent::process_new_mn(int32_t mn_id) { BULEntry *bule; bule = find_bule(mn_id); if(!bule) { bule = create_bule(mn_id); bule->lmaa() = lma_addr_; bule->proxy_coa() = addr(); bule->lifetime() = binding_lifetime_; bule->insert_entry(&bul_list_); } else { bule->BULTimer_.cancel(); if(bule->pktPBU_) { Packet::free(bule->pktPBU_); bule->pktPBU_ = 0; } } bule->set_state(BUL_S_SETUP); bule->retry_count_ = 0; send_pbu(bule); }
MAG Operation #1 (3/4) • send_pbu 함수 • PMIPv6Agent의 create_pbu 함수로 PBU 생성 • bule에 생성된 PBU를 저장하고 복사본 전송 • Retransmission timer 설정 void MAGAgent::send_pbu(BULEntry *bule) { if(!bule->pktPBU_) { bule->pktPBU_ = create_pbu(bule->lmaa(), bule->mn_id(), bule->lifetime(), bule->proxy_coa()); } send(bule->pktPBU_->copy(), 0); //FIXME: adjust retransmit timeout (Random backoff??) bule->BULTimer_.resched(1.0); }
MAG Operation #1 (4/4) • create_pbu 함수 Packet *PMIPv6Agent::create_pbu( int32_t dst, int32_t mn_id, uint32_t lifetime, int32_t proxy_coa) { Packet *p = allocpkt(); hdr_cmn *hdrc = HDR_CMN(p); hdr_ip *iph = HDR_IP(p); hdr_pmipv6 *h = HDR_PMIPv6(p); hdrc->size() = IPv6_HEADER_SIZE; hdrc->ptype() = PT_PBU; hdrc->size() += PBU_SIZE; iph->saddr() = proxy_coa; iph->sport() = port(); iph->daddr() = dst; iph->dport() = port(); h->H() = 1; h->A() = 1; h->P() = 1; h->type() = PBU; h->seqno() = 0; h->lifetime() = lifetime; h->mn_id() = mn_id; h->coa() = proxy_coa; h->haddr() = -1; h->status() = 0; return p; }
LMA Operation (1/7) • Receiving PBU/Sending PBACK PMIPv6Agent LMAAgent recv() process_packet() process_pbu() -find_bce() setup_route() setup-route/TCL -get-pmip6-encap/TCL send_pback() create_pback() send()
LMA Operation (2/7) • PMIPv6Agent의 recv 함수 • PBU의 IP헤더 dest port에 따라 recv함수 호출됨 void PMIPv6Agent::recv(Packet* p, Handler *) { hdr_cmn *hdrc = HDR_CMN(p); intptype; ptype = hdrc->ptype(); if((ptype==PT_PBU && strcmp(node_info_, "LMA")==0) || (ptype==PT_PBACK && strcmp(node_info_, "MAG")==0)) { process_packet(p); } else { fprintf(stderr, "%s received packet with wrong type %d\n", node_info_, ptype); Packet::free(p); } }
LMA Operation (3/7) • process_packet 함수 • virtual이며, LMAAgent와 MAGAgent에서 override함 • process_pbu 함수 호출 • process_pbu 함수 • Binding cache 찾기, lifetime처리 • Lifetime에 따라 Routing 설정 • PBACK 보내기 void LMAAgent::process_packet(Packet *p) { hdr_cmn *ch = HDR_CMN(p); if(ch->ptype() == PT_PBU) { process_pbu(p); } Packet::free(p); }