2. Detalhes de Implementação

  1. Ambiente de Desenvolvimento de Programação

Netramet foi desenvolvido em um PC usando Borland Turbo C, Turbo Assembler e um ambiente de desenvolvimento interativo. Turbo Make foi utilizado para organizar o sistema, com arquivos MakeFile especificando como os vários componentes do sistema são criados.

Waterloo C forneceu uma boa implementação para PC do TCP/IP e foi usado para fornecer o transporte UDP para pacotes SNMP, Waterloo C tem uma interface com a Ethernet via driver de pacote CRYNWR.

Uma versão mais nova do CMU SNMP foi usado para a comunicação entre o Netramet e o Nemac. Ela foi portada para o PC, e estendida para suportar operações SET em caracteres e variáveis inteiras de 16 bits.

  1. Estruturas de Dados: Tabelas de Fluxos e de Regras

Endereços de hosts (adjacente, par e particularidades) e suas máscaras estão contidos em uma estrutura chamada Key. Um fluxo é uma estrutura larga que contém duas chaves, uma para o host origem e outras para o destino. Atributos gerais são armazenados como variáveis dentro do fluxo, e neste lugar existe um campo de ligação link para habilitar os fluxos a serem ligados juntos. Espaço para os fluxos são alocados dinamicamente de um pool de fluxos. A tabela de fluxos é implementada como um vetor de ponteiros para fluxos, um FlowIndex (índice de fluxos) é um índice nesse vetor.

As regras são implementadas em uma estrutura pequena. O espaço para uma tabela de regras é alocado como um bloco simples na memória.

A primeira vez que um fluxo é observado, um procedimento de contagem é executado. O medidor aloca espaço para o fluxo, assinala no FlowIndex (índice de fluxos) e o coloca em uma tabela de contagem (count table). As tabelas de contagem são implementadas como pequenas tabelas, o medidor mantém uma tabela de ponteiros para a tabela de contagem. Cada tabela de contagem possui 512 entradas de tabelas pequenas (2048 bytes). O usuário deve construir tabelas de regras que tenham algumas poucas contagens para possibilitar a minimização do overhead de memória.

  1. Gerenciamento da Memória do Medidor

Uma vez o fluxo criado, ele permanecerá indefinidamente, entretanto, o medidor não terá mais memória para novos fluxos. Para lidar com esse problema, Netramet usa o coletor de lixo incremental (incremental garbage collector).

Em intervalos regulares especificados pela variável GarbageCollectInterval o procedimento do coletor de lixo é invocado, ele procura na tabela de fluxos por fluxos que podem ser recuperados. Para controlar os recursos consumidos existe um número limite de fluxos em uso e ociosos que o coletor pode inspecionar. Estes são os parâmetros descritos no PC Statistics Display abordado a seguir.

Para decidir se o fluxo pode ser recuperado, o coletor de lixo considera quanto tempo ficou inativo (nenhum pacote em nenhuma direção) e quando seus dados foram coletados na última vez. Se foi coletado ao menos uma vez desde seu LasTime, ele deve ser recuperado. Este algoritmo é implementado usando uma variável chamada GarbageCollectTime, a qual normalmente contém o tempo de funcionamento (UpTime) do medidor no momento da ultima execução do coletor.

O fluxo não deve ser coletado quando o medidor esta sem espaço para rodar. Isto é prevenido por um processo de baixa prioridade em background que verifica a porcentagem de fluxo ativo e compara com a variável HighWaterMark. Se a porcentagem do fluxo ativo é maior que a maior capacidade, GarbageCollectTime é incrementado pelo valor corrente da variável InactivityTimeout. O efeito disso é que se o coletor falhar, o Netramet continuara a criar fluxos até que HighWaterMark seja excedido, então recorre para fluxos antigos para manter memória suficiente livre.

A MIB especifica o medidor que deve trocar para modo de uma tabela de regras "standby" se a percentagem de fluxos ativos for maior que HighWaterMark. A MIB também especifica que o medidor deve tomar alguma providencia quando a porcentagem do fluxo ativo ficar acima do FloodMark; Netramet troca para regra default neste caso. Os valores das variáveis de gerenciamento da memória mencionadas podem ser configuradas pelo NeMac - isto se torna possível para poder trabalhar melhor em quase todos os casos.

  1. Otimizando a tabela de regras

Regras são comumente testadas em seqüência até que uma comparação bem sucedida selecione um novo índice na tabela de regras. Testando um pacote contra uma lista longa de endereços sendo assim uma pesquisa seqüencial, que seria muito lenta. Para aperfeiçoar o desempenho das regras de teste, Netramet executa analises de fluxo de uma nova tabela de regras, procurando grupos de regras que testem o mesmo atributo usando a mesma máscara. Grupos que contém mais de quatro regras estão organizados em pequenas tabelas - estes podem efetivamente serem testados com pouco processamento e uma comparação individual.

Quando um pacote chega no medidor o seu atributo é copiado na próxima abertura disponível no buffer de entrada do medidor, preparando para posteriores comparações contra as regras. Se os pacotes do tipo par não puderem ser comparados com as regras, serão simplesmente descartados (antes do seu outro atributo ser copiado). Para implementar isto o medidor mantém uma tabela indicando qual pacote par foi testado pelas regras corrente, esta tabela pode ser exibida na tela do medidor a qualquer momento. Semelhantemente, se as regras correntes não requisitarem endereço adjacente, eles não serão copiados no buffer de entrada.

2.5 O Bloco externo do medidor

Bloco externo do Netramet é um laço individual no qual implementa quatro processamentos assíncronos. São estes, em ordem decrescente de prioridade:

  1. Comparação de regras

Quando um pacote chega ao medidor, duas chaves de estruturas de dados são construídas, uma para sua origem e outra para seu destino. Uma tentativa é feita para igualar o pacote contra as regras configuradas correntemente com as chaves na ordem origem para destino, se isto suceder corretamente o pacote é contado.

Se a comparação falhar, as chaves são trocadas e o pacote é testado junto as regras novamente. Se falhar neste momento, é descartada.

Uma terceira possibilidade é aquela em que o pacote combinou uma regra calculada, mas seu fluxo ainda não esta presente na tabela de cálculos. Desde que já tenha sido detectado trafegando em direção oposta, a comparação é remontada com as chaves invertidas. Se isto falhar, o fluxo é adicionado na tabela de cálculos com as chaves na ordem origem para destino.

Este algoritmo significa que você pode usar cálculos simétricos (ex.: cálculos tendo máscaras idênticas em ambas direções), se não cuidar a direção do fluxo. Alternativamente você pode escrever regras em uma ordem específica de origem para destino. Exemplos disto são descritos na seção Escrevendo Arquivos de Regras, mais adiante.

  1. SNMP: Buscando e Preparando Variáveis

O código para buscar e gravar variáveis SNMP foi retirado do pacote CMU sendo o arquivo snmpvars.c. Este código foi modificado para usar uma pesquisa binaria com objetivo de achar identificadores de objetos como requisitado, substituindo a pesquisa linear original.

Procedimentos simples para preparar caracteres, 16-bit inteiros e 32-bit variáveis longas são usados quando uma atividade que não seja especial é requerida. Ações especiais como atualização da GarbageCollectTime quando a variável LastCollectTime for setada, serão implementadas como procedimentos individuais.

2.8 Criação e Ativação de Tabelas

Uma exigência propriamente rara para a contabilização do medidor é a capacidade de suportar coletagens assíncronas de fluxos de dados de vários medidores simultaneamente. Isto é descrito na MIB pelas tabelas de Criação e Ativação, o qual fornece um coletor com janelas na tabela de fluxo, permitindo a ele inspecionar somente aqueles fluxos criados ou ativos desde um tempo especificado. Este tempo é passado para o medidor como um componente de um identificador de objeto; você pode ver como um parâmetro sendo passado para o procedimento GET o qual implementa a tabela de criação ou ativação.

Outro aspecto de ter múltiplos coletores é que um deles pode coletar estatísticas de desempenho. Uma possibilidade seria ter um medidor coletando fluxos de dados a cada 15 minutos, um segundo coletando fluxo a cada hora, e um terceiro coletando estatísticas de desempenho (mas não fluxo de dados) a cada minuto.

  1. Column Blobs: Recuperando Fluxo de Dados acumulados

Um elemento vital de um medidor de contabilização é que ele deve ter a possibilidade de recuperar fluxo de dados de maneira eficiente. SNMP pode ser ineficiente para este fim, visto que cada valor recuperado esta acompanhado pelos seus identificadores de objetos. Para recuperar um valor long (quatro bytes) pode requerer 12 ou mais bytes adicionais do identificador de objeto !

Netramet resolve este problema usando objetos SNMP discretos para passar muitos valores ao Nemac como uma unidade individual. A MIB define um objeto chamando Column Blob para fazer isto. Um Column Blob é um objeto SNMP tridimensional, as dimensões sendo uma ‘coluna’ de números, um valor LastTime e um FlowIndex. Nemac visualiza a tabela de fluxo como uma matriz composta de uma coluna para cada atributo de fluxo. Ele pode recuperar valores de um atributo em particular para todo fluxo ativo desde um tempo especificado, iniciando em uma determinada coluna da tabela de fluxo e chamando novamente column blob em seqüência descendo uma coluna.

Nemac usa esta idéia um pouco mais detalhadamente. O usuário especifica qual atributo deverá ser coletado usando uma declaração Format (Formato) no arquivo de regras. Nemac usa o Formato para decidir qual coluna é requisitada, então recupera column blobs para cada atributo iniciado na primeira linha da tabela de fluxo. O resultado do fluxo coletado é escrito no disco, então o processo é repetido na linha após a última linha coletada, e assim por diante.

O tamanho máximo para a column blob é definido para adaptar-se em um pacote SNMP de 500 bytes, o qual pode carregar de 50 até 60 valores de atributo (junto com seu número de fluxo). Como um exemplo, se nós desejamos coletar 10 atributos para 1000 fluxos, este requisitaria somente 10 x 20 = 200 pacotes SNMP. Para minimizar o carregamento da rede, Nemac para por 90 milisegundos após cada requisição SNMP.



Márcia G. Baltar