Eu tenho dois contêineres linux conectados com um veth-pair. Na veth-interface de um container eu configuro o tc qdisc netem delay e envio o tráfego dele para o outro container. Se eu observar o tráfego em ambos os lados usando tcpdump/wireshark, pode-se ver que os carimbos de data e hora do mesmo pacote no remetente e no destinatário não diferem pelo atraso selecionado.
Eu queria entender mais detalhadamente em que ponto a libpcap coloca timestamps para sair do tráfego correspondente a tc qdisc. Procurei um esquema/imagem na Internet mas não encontrei. Eu encontrei este tópico ( wireshark packet capture point ) mas ele aconselha a introduzir uma indireção tendo mais um container/interface. Esta não é uma solução possível na minha situação. Existe alguma maneira de resolver o problema não introduzindo interfaces intermediárias adicionais (ou seja, não alterando a topologia) e apenas gravando na interface veth já fornecida, mas de forma que o atraso possa ser visto?
ATUALIZAR:
Fui muito rápido e me enganei. Nem minha solução presente abaixo (igual à primeira variante de solução da resposta de @AB), nem a solução com IFB de @AB (já verifiquei) resolvem meu problema. O problema está no estouro da fila de transmissão da interface a1-eth0
do remetente na topologia:
[a1-br0 ---3Gbps---a1-eth0]---100Mbps---r1---100Mbps---r2
Eu fui muito rápido e verifiquei apenas o atraso de 10ms no link entre o a1-eth0
roteador r1
. Hoje tentei aumentar o atraso: 100ms, 200ms e os resultados (por pacote de atraso e gráficos de taxa que recebo) começam a diferir para a topologia acima e para a topologia normal:
[a1-eth0]---100Mbps---r1---100Mbps---r2
Então não, certamente, para testes precisos não posso ter links extras: nem introduzidos pela ponte Linux, nem por este IFB, nem por qualquer outro sistema terceiro. Eu testo esquemas de controle de congestionamento. E eu quero fazer isso em uma topologia específica. E eu não posso alterar a topologia apenas por uma questão de plotagem - quero dizer, se ao mesmo tempo meus resultados / gráficos de taxa e atraso forem alterados.
ATUALIZAÇÃO 2:
Então parece que a solução foi encontrada, como pode ser visto abaixo (solução NFLOG).
ATUALIZAÇÃO 3:
Aqui são descritas algumas desvantagens da solução NFLOG (grandes cabeçalhos Link-Layer e checksums TCP errados para pacotes TCP de saída com carga útil zero) e proposta uma solução melhor com NFQUEUE que não tem nenhum destes problemas: Checksum TCP errado para pacotes de saída de comprimento zero (capturado com iptables) . No entanto, para minhas tarefas (teste de esquemas de controle de congestionamento) nem NFLOG, nem NFQUEUE são adequados. Como é explicado pelo mesmo link, a taxa de envio é limitada quando os pacotes são capturados do iptables do kernel (é assim que eu entendo). Então, quando você grava no remetente capturando da interface (ou seja, regularmente) você obtém 2 Gigabytes de despejo, enquanto se você grava no remetente capturando de iptables você obtém 1 Gigabyte de despejo. A grosso modo.
ATUALIZAÇÃO 4:
Finalmente, no meu projeto eu uso a solução de ponte Linux descrita em minha própria resposta abaixo.
De acordo com o fluxo de pacotes no Netfilter e no esquema geral de rede, o tcpdump captura ( AF_PACKET ) após a saída (qdisc) . Portanto, é normal que você não veja o atraso no tcpdump: o atraso já estava presente na captura inicial.
Você teria que capturá-lo um passo antes, então envolva um terceiro sistema:
S1: system1, executa o tcpdump na interface de saída
R: roteador (ou bridge, conforme sua conveniência, isso não muda nada), executa o qdisc netem
S2: system2, executa o tcpdump na interface de entrada
Isso significa 3 pilhas de rede envolvidas, sejam elas reais, vm, namespace de rede (incluindo ip netns , LXC, ...)
Opcionalmente, também é possível enganar e mover todas as configurações especiais no roteador (ou ponte) usando uma interface IFB com tráfego espelhado : permite por um truque (dedicado para este caso) inserir netem tipo de entrada posterior em vez de saída:
Há um exemplo básico de uso do IFB na página de manual tc mirred :
Basta usar netem em ifb0 em vez de sfq (e em namespace de rede não inicial,
ip link add name ifbX type ifb
funciona bem, sem modprobe).Isso ainda requer 3 pilhas de rede para um funcionamento adequado.
usando NFLOG
Após uma sugestão de JenyaKh, é possível capturar um pacote com tcpdump , antes da saída (antes de qdisc) e depois na saída (após qdisc): usando iptables (ou nftables ) para registrar pacotes completos na infraestrutura de log do netlink , e ainda lendo-os com tcpdump e novamente usando tcpdump na interface de saída. Isso requer apenas configurações em S1 (e não precisa mais de um roteador/ponte).
Então, com o iptables no S1, algo como:
Filtros específicos provavelmente devem ser adicionados para corresponder ao teste feito, porque o filtro tcpdump é limitado na interface nflog (o wireshark deve lidar melhor com isso).
Se a captura da resposta for necessária (aqui feita em um grupo diferente, exigindo assim um tcpdump adicional ):
Dependendo das necessidades, também é possível movê-los para raw/OUTPUT e raw/PREROUTING .
Com tcpdump :
Se um grupo diferente (= 2) foi usado para entrada:
Então, ao mesmo tempo, como de costume:
ATUALIZAR:
Então eu finalmente usei esta solução. Está presente na minha solução. Afinal, funcionou bem para mim.
Eu (o iniciador do tópico) resolvi meu problema usando a ponte Linux. Aqui [ https://www.linuxquestions.org/questions/linux-networking-3/transferring-all-traffic-through-an-extra-interface-4175656515 ] escrevi que consegui usar a ponte Linux, mas descartei a possibilidade: "Mas esta solução não atende às minhas necessidades, pois há um link Ethernet extra entre as interfaces h1-br0 e h1-eth0 na realidade. Eu preciso desse material para medições de desempenho, então não posso ter nenhum link Ethernet extra. bridge atrapalha minha topologia ao introduzir links extras."
Por que eu descartei a solução primeiro? Inicialmente, minha topologia é:
No link
r1---r2
tenho netem rate configurada para 100 Mbps, no linka1---r1
não tem limite de taxa. Como a fila de transmissão do roteadorr1
que o conecta ao roteadorr2
é de 1000 pacotes, tive o efeito de estouro de fila (alguns pacotes são descartados) ao enviar tráfego dea1
parar2
. E isso estava bem. É assim que acontece no mundo real com as filas do roteador transbordando em caso de engarrafamento.Agora eu faço toda essa pesquisa para adicionar limites de atraso e taxa
a1---r1
também. Então eu criei esta solução usando a ponte Linux. Mas eu pensei que esta solução não funcionaria. Abaixo você pode ver a nova topologia com ponte Linux:Portanto, meu problema com a solução era que eu esperava que o estouro da fila estivesse presente agora na fila de transmissão da interface
a1-eth0
. Ou seja, é da mesma forma que na figura anterior onde o estouro estava na interface der1
conectá-lo aor2
. Analogamente.E esse estouro eu não quero. Porque na topologia normal - sem usar a ponte Linux para fins de medição de atraso - não temos nenhum estouro de fila de transmissão de
a1-eth0
:Mas ontem eu criei a topologia com a ponte Linux (a 3ª topologia da desenhada acima) novamente e lancei o tráfego na topologia fluindo de
a1
parar2
. Verifiquei o backlog (número atual de pacotes em fila) da fila de transmissão dea1-eth0
chamar o comandotc -s qdisc show dev a1-eth0
em ciclo com intervalo de 500ms e o backlog da fila de transmissãoa1-br0
com o comando análogo.Isto é o que eu vi para
a1-eth0
, recebi as mensagens:Isto é o que eu vi para
a1-br0
, recebi as mensagens:Assim, pode-se ver que nenhum estouro acontece
a1-eth0
e, na realidade, não "parece"a1-br0
enviar nada, embora na realidade envie. Portanto, o link entrea1-bro
ea1-eth0
não é como aquele (o veth par link) entrea1
e roteadorr1
. Eu não sei por que é assim. É estranho porque verifiquei que posso, por exemplo, definir a configuração de atraso do netem ema1-br0
- por isso é como uma interface normal.De qualquer forma, verifiquei que a solução com a ponte atende todas as minhas necessidades. Eu ainda não explorei por que funciona (quero dizer, no sentido do que eu estava explicando acima - estouro de fila e etc.).
Aqui estão os comandos que eu executei no host
a1
para referência. Eu entendo que é difícil entendê-los completamente sem o contexto, no entanto. Mas, talvez, ajude alguém no futuro:A topologia com endereços IP, à qual apliquei os comandos, também está presente aqui: Pingar uma interface do roteador Linux por outra interface deste roteador . Segue a topologia: