710 likes | 871 Views
Curso de NS. Rainer R. P. Couto ( rainerpc@dcc.ufmg.br ). Sumário. Arquitetura do Software Hierarquia de Objetos Principais Classes em OTcl e C++ Escalonador Temporizadores – Timers Geração de números aleatórios. Arquitetura do software. Component e s de rede. TclCL. Escalonador
E N D
Curso de NS Rainer R. P. Couto (rainerpc@dcc.ufmg.br)
Sumário • Arquitetura do Software • Hierarquia de Objetos • Principais Classes em OTcl e C++ • Escalonador • Temporizadores – Timers • Geração de números aleatórios
Componentes de rede TclCL Escalonador de eventos OTcl Arquitetura do Software • Tcl • “script language” • Fracamente tipada • Configuração • C/C++ • “system language” • Fortemente tipada • “Core programming” • OTcl • Tcl orientado a objetos • TclCL (TclCLass) • Tcl com suporte a “object oriented split-level programming” Tcl C/C++ ns-2
Pure OTcl objects Pure C++ objects C++/OTcl split objects C++ OTcl ns Estrutura Interna • Arquitetura do NS • Orientado a objetos • Escrito em C++ • Interpretador Tcl como frontend • Arquitetura do NS • Duas hierarquias de objetos • Hierarquia C++ (compilada) • Hierarquia OTcl (interpretada) • Correspodência um para um pela perspectiva do usuário
Split-level programming • Por que duas linguagens? • C++: execução rápida / alteração complexa • Processamento de cada pacote, alteração de comportamento de objetos existentes em C++ (“dado”), estruturas e algotirmos complexos, código com alterações infreqüentes • OTcl: alteração simples / execução lenta • Configuração, setup, escalonamento de eventos periódicos e manipulação simples de objetos (“controle”), código com alterações freqüentes • Tclcl provê a forma de unir as duas linguagens • Compromisso entre composabilidade e velocidade • Aprendizado e correção de erros
1000 Visual Basic Tamanho do programa complexidade pequeno grande 100 Tcl/Perl Instructions/Statement 10 C/C++ OTcl Java C++ Assembly split objects C 1 Degree of Typing None Strong O Méritodo OTcl • Granularidade do código/script pode ser ajustada para compensar extensibilidade por performance. John Ousterhout. Scripting: Higher-level programming for the 21st century IEEE Computer, 1998.
Principais classes da programação C++/OTcl Raiz da hierarquia de objetos do ns-2 bind():realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObject command():realiza o “link” entre métodos chamados no OTcl e implementados em C++ TclClass Cria e inicializa TclObject’s Tcl Métodos C++ para acessar o interpretador Tcl TclCommand Comandos globais EmbeddedTcl Inicialização do script ns
Principais classes da programação C++/OTcl Raiz da hierarquia de objetos do ns-2 bind():realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObject command():realiza o “link” entre métodos chamados no OTcl e implementados em C++ TclClass Cria e inicializa TclObject’s Tcl Métodos C++ para acessar o interpretador Tcl TclCommand Comandos globais EmbeddedTcl Inicialização do script ns
TclObject: Hierarquia e Shadowing Hierarquia de classes C++ Hierarquia de classes OTcl TclObject TclObject Agent Agent TcpAgent Agent/TCP *tcp _o123 Agent/TCP OTcl Objeto shadow Objeto Agent/TCP C++
TclObject::bind() • “Une”variáveis membras de classes no C++ avariáveis no OTcl • Duas referências para um mesmo objeto • C++ TcpAgent::TcpAgent() { bind(“window_”, &wnd_); bind_bw(“taxa_", &taxa_); } • bind_time(), bind_bool(), bind_bw() • OTcl set tcp [new Agent/TCP] $tcp set window_ 200 $tcp set taxa_ 1.5Mb
Inicialização de variáveis do “bind” • Inicialização através de variáveis de classe do OTcl Agent/TCP set window_ 50 • Faça toda a inicialização de variáveis de “bind” em ~ns/tcl/lib/ns-default.tcl • Caso contrário, um aviso de alerta será mostrado quando o objeto “shadow” for criado
Implementação de variáveis de “bind” • Classe InstVar • Um objeto por variável de “bind” – caro! • InstVarInt, InstVarReal, ... • Criados por TclObject::bind() • Cria instância da variável na pilha OTcl • Habilita “trap” de escrita/leitura para variável OTcl • Conecta à variável C++ na ocorrência de “traps”
TclObject::command() • Implementa métodos do OTcl em C++ • “Trap point”: Método cmd{} em OTcl • Após chamado, cmd{} envia todos seus argumentos para TclObject::command()
TclObject::command() • OTcl set tcp [new Agent/TCP] $tcp advance 10 • C++ int TcpAgent::command(int argc, const char*const* argv) { if (argc == 3) { if (strcmp(argv[1], “advance”) == 0) { int newseq = atoi(argv[2]); …… return(TCL_OK); } } return (Agent::command(argc, argv); }
TclObject::command() OTcl space procedimento não existe $tcp send TclObject::unknown{} $tcp cmd send C++ space TcpAgent::command() implementa “send”? Sim Não Chama o método do pai: return Agent::command() Processa e retorna
TclObject: Criação e Remoção • Procedimentos globais: new{}, delete{} • Exemplo set tcp [new Agent/TCP] … delete $tcp
construtor Agent/TCP construtor pai (Agent) construtor TclObject chama cons_ trutor do pai cria objeto C++ completa inicialização completa inicialização cria objeto shadow OTcl Qual objeto C++ deve ser criado? – TclClass construtor pai (Agent) construtor AgentTCP construtor TclObject (C++) chama cons_ trutor do pai chama cons_ trutor do pai Não faz nada, retorna realiza binds e retorna realiza binds e retorna TclObject: Criação e Remoção chama cons_ trutor do pai OTcl C++
Principais classes da programação C++/OTcl Raiz da hierarquia de objetos do ns-2 bind():realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObject command():realiza o “link” entre métodos chamados no OTcl e implementados em C++ TclClass Cria e inicializa TclObject’s Tcl Métodos C++ para acessar o interpretador Tcl TclCommand Comandos globais EmbeddedTcl Inicialização do script ns
OTcl C++ TclObject TclObject NsObject ?? Agent Agent TcpAgent Agent/TCP TclClass • Static class TcpClass : public TclClass { • public: • TcpClass() : TclClass(“Agent/TCP”) {} • TclObject* create(int, const char*const*) { • return (new TcpAgent()); • } • } class_tcp;
TclClass: Mecanismo • Inicialização durante o “startup” da execução TcpClass::bind() TclClass::init() para cada TclClass definida estaticamente e.g. SplitObject::register{} Cria e registra Classe OTcl Agent/TCP Agent/TCP::create-shadow{} TclClass::create_shadow()
Principais classes da programação C++/OTcl Raiz da hierarquia de objetos do ns-2 bind():realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObject command():realiza o “link” entre métodos chamados no OTcl e implementados em C++ TclClass Cria e inicializa TclObject’s Tcl Métodos C++ para acessar o interpretador Tcl TclCommand Comandos globais EmbeddedTcl Inicialização do script ns
Classe Tcl • Classe que possui a referência para o interpretador Tcl • Uso • Chamar procedimentos em OTcl • Obter resultados de expressões em OTcl • Passar um resultado para o OTcl • Retornar um código de sucesso/falha para o Otcl • Armazenar e realizar procuras por referências a TclObjects
Obtendo uma referência para o interpretador • Uma única referência ao intepretador está declarado no arquivo Tcl.cc (dentro do diretório tclclXXX) como um membro estático da classe Tcl. Antes de acessar qualquer método do intepretador, devemos obter essa referência. • Comando Tcl& tcl = Tcl::instance();
Passandos comandos para o interpretador Tcl& tcl = Tcl::instance(); char wrk[128]; strcpy(wrk, "Simulator set NumberInterfaces_ 1"); tcl.eval(wrk); sprintf(tcl.buffer(), "Agent/SRM set requestFunction_ %s","Fixed"); tcl.eval(); tcl.evalc("puts stdout \”hello world\”"); tcl.evalf("%s request %d %d", name_, sender, msgid); • Tcl::eval(char *): passa string para o intepretador • Tcl::evalc(const char *): preserva o string de entrada • Tcl::eval(): supõe que o comando já está em tcl.buffer • Tcl::evalf(char *, par1, par2, ...): “printf like” • Exemplo:
Coletando resultados • Quanto o intepretador chama um comando em C++, espera-se um resultado na variável interna result. • Comando: tcl.resultf() • Similarmente, quando o C++ faz uma chamada a um método do interpretador, o resultado pode ser acessado através da mesma variável. • Comando: tcl.result()
Exemplo de métodos de Tcl Tcl& tcl = Tcl::instance(); if (argc == 2) { if (strcmp(argv[1], “now”) == 0) { tcl.resultf(“%g”, clock()); return TCL_OK; } tcl.error(“command not found”); return TCL_ERROR; } else if (argc == 3) { tcl.eval(argv[2]); clock_ = atof(tcl.result()); return TCL_OK; }
Funções de Hash da classe Tcl • O intepretador possui uma tabela hash com entradas para todos TclObjects criados durante a simulação. • void Tcl::enter(TclObject* o) • Utilizado para criar uma nova entrada para o novo TclObject • TclObject* Tcl::lookup(const char* name) • Utilizado para fazer uma procura por um TclObject
Principais classes da programação C++/OTcl Raiz da hierarquia de objetos do ns-2 bind():realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObject command():realiza o “link” entre métodos chamados no OTcl e implementados em C++ TclClass Cria e inicializa TclObject’s Tcl Métodos C++ para acessar o interpretador Tcl TclCommand Comandos globais EmbeddedTcl Inicialização do script ns
Class TclCommand • Implementação em C++ de comandosglobais em OTcl class RandomCommand : public TclCommand { public: RandomCommand() : TclCommand("ns-random") {} virtual int command(int argc, const char*const* argv); }; int RandomCommand::command(int argc, const char*const* argv) { Tcl& tcl = Tcl::instance(); if (argc == 1) { ... } } • Inicializar um novo objeto – new RandomCommand() – em misc.cc::init_misc
Principais classes da programação C++/OTcl Raiz da hierarquia de objetos do ns-2 bind():realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObject command():realiza o “link” entre métodos chamados no OTcl e implementados em C++ TclClass Cria e inicializa TclObject’s Tcl Métodos C++ para acessar o interpretador Tcl TclCommand Comandos globais EmbeddedTcl Inicialização do script ns
EmbeddedTcl • Carrega OTcl scripts durante a inicialização do ns • Carrega recursivamente ~ns/tcl/lib/ns-lib.tcl: source ns-autoconf.tcl source ns-address.tcl source ns-node.tcl ....... • Carrega tudo em um único vetor de caracteres em C++ • Executa esse string durante a inicialização
EmbeddedTcl • Como funciona • tcl2c++: provido pelo TclCL, converte tcl scripts em vetores estáticos de caracteres em C++ • Makefile.in: tclsh8.0 bin/tcl-expand.tcl tcl/lib/ns-lib.tcl | tcl2c++ et_ns_lib > gen/ns_tcl.cc
Resumo • TclObject • Classe raiz das hierarquias compilada (C++) e interpretada (OTcl) • Acesso transparente (chamadas de procedimento e acesso de variáveis) entre OTcl e C++ • TclClass • Mecanismo que torna possível TclObject • Tcl • Primitivas para acessar o interpretador Tcl
Utilizando-se o NS... • Criação do simulador • Escalonador de eventos • [Habilitação do tracing] • Criação da rede • Configuração do roteamento • ... set ns [new Simulator] # [Turn on tracing] # Create topology # Setup packet loss, link dynamics # Create routing agents # Create: # - multicast groups # - protocol agents # - application and/or setup traffic sources # Post-processing procs # Start simulation
Escalonador • O que é o escalonador? • Controlador de eventos dentro do simulador • Arquivos correspondentes: • tcl/lib/ns-lib.tcl (class Simulator) • common/scheduler(.h,.cc) (class Scheduler) • heap.h (class Heap)
Modelo do escalonador • Modela mundo como eventos • Simulador possui uma lista de eventos • Processo: pega o primeiro evento da lista, executa até estar completo • Cada evento acontece em um determinado instante do tempo virtual (tempo simulado), mas pode levar um tempo real arbitrátio • Implementação muito simples • uma thread de controle => não precisamos nos preocupar com condições de corrida ou “locking” (bem simples)
Escalonador de Eventos time_, uid_, next_, handler_ head_ -> handler_ -> handle() insert time_, uid_, next_, handler_ class Event { public: Event* next_; /* event list */ Handler* handler_; /* handler to call when event ready */ double time_; /* time at which event is ready */ scheduler_uid_t uid_; /* unique ID */ Event() : time_(0), uid_(0) {} }; class Handler { public: virtual void handle(Event* event) = 0; };
Modelo de filas simplificado: t=1 A coloca um pacote na fila da LAN t=1.01 LAN retira o pacote da fila e LAN e dispara um evento de recepção em B A B Modelo CSMA/CD detalhado: t=1.0 A envia pacote para NIC; NIC de A inicia “carrier sense” t=1.005 NIC de A conclui cs, inicia tx t=1.006 NIC de B começa a recepção do pacote t=1.01 NIC de B conclui recepção do pacote NIC de B passa pacote para agente/aplicação Modelo do escalonador Considere dois nodos em uma rede Ethernet
Criação do escalonador • Criação do simulador de eventos set ns [new Simulator] • Escalonamento de eventos $ns at <tempo> <evento> • <evento>: qualquer comando legítimo no ns/tcl • Ex: $ns at 5.0 “finish” • Início da execução do escalonador $ns run • Escalonador Calendar: default • Escalonador Real-time • Sincroniza com tempo real • Emulação de redes set ns_ [new Simulator] $ns_ use-scheduler Heap $ns_ at 300.5 “$self halt”
Simulador - métodos Simulator instproc use-scheduler type { $self instvar scheduler_ if [info exists scheduler_] { if { [$scheduler_info class] == "Scheduler/$type" } { return } else { delete $scheduler_ } } set scheduler_ [newScheduler/$type] $scheduler_now } Simulator instproc init args { $self instvar useasim_ ..._ set slinks_(0:0) 0 ... $self create_packetformat $self use-scheduler Calendar #$self use-scheduler List ... } Simulator instproc at args { $self instvar scheduler_ return [eval $scheduler_ at $args] } Simulator instproc run {} { ... return [$scheduler_ run] }
Escalonador - Tipos • ListScheduler • Lista simples O(N) • HeapScheduler • Baseado em um Heap O(logN) • CalendarScheduler • Baseado em Hash O(1) • SplayScheduler • RealTimerScheduler
Modos do escalonador Modo interativo arara:/ns->ns % set ns [new Simulator] _o3 % $ns at 1 “puts \“Hello World!\”” 1 % $ns at 1.5 “exit” 2 % $ns run Hello World! arara:/ns-> Modo batch: simple.tcl set ns [new Simulator] $ns at 1 “puts \“Hello World!\”” $ns at 1.5 “exit” $ns run arara:/ns->ns simple.tcl Hello World! arara:/ns->
Temporizadores – Timers • O que é um temporizador? • Um temporizador (timer) é um elemento que dispara um determinado evento e que pode ser programado • Usado principalmente em agentes, mas pode ser utilizado em outros objetos • Ex: retransmissão no agente TCP • Temporizadores podem ser implementados em C++ ou em OTcl. • São baseados em uma classe abstrata definida em timer-handler.h • Em OTcl um temporizador pode ser criado derivando a classe definida emtcl/mcast/timer.tcl.
Temporizadores – Funções e atributos • A classe abstrata TimerHandler contém os seguintes métodos públicos disponíveis: • void sched(double delay) • Escalona um temporizador para disparar em “delay” segundos • void resched(double delay) • Re-escalona o temporizador (similar ao sched, mas o temporizador pode estar pendente) • void cancel() • Cancela um temporizador pendente • int status() • Retorna o status do temporizador (TIMER_IDLE, TIMER_PENDING, ou TIMER_HANDLING)
Temporizadores – Funções e atributos • A classe abstrata TimerHandler contém os seguintes métodos protegidos disponíveis: • virtual void expire (Event* e) =0 • Este método deve ser preenchido com o código a ser executado no instante de disparo do evento • virtual void handle (Event* e) • Consome um evento; faz um chamada para expire()e atribui o valor adequado a status_ • int status_ • Variável que mantém o atual status do temporizador • Event event_ • Evento que deve ser consumido
Temporizadores – Funções e atributos • O método virtual expire() deve ser defindo na classe derivada da classe abstrata • Dois métodos privados “inline” são definidos: • inline void _sched(double delay) • {(void)Scheduler::instance().schedule(this, &event_, delay); } • inline void _cancel() • { (void)Scheduler::instance().cancel(&event_); } • Esses códigos utilizam diretamente métodos do escalonador.
Definindo um Temporizador class MyTimer : public TimerHandler { public: MyTimer(MyAgentClass *a) : TimerHandler() { a_ = a; } virtual double expire(Event *e); protected: MyAgentClass *a_; }; • Temporizadores criados em C++ não são diretamente acessíveis através do Otcl. • Geralmente um temporizador será uma classe amiga da classe agente onde se encontra ou expire() chamará um método público deste agente. double MyTimer::expire(Event *e) { // executa a função // Opção 1: // =\> não re-escalona o temporizador // Opção 2: // =\> re-escalona temporizador para // =\> disparar novamente em “delay” // =\> segundos }