Como arp_process() responde ao dispositivo certo?

Como arp_process() responde ao dispositivo certo?

Olhando para o código-fonte do Kernel, vejo que, ao processar a solicitação ARP, a solicitação net_deviceé recuperada diretamente do skbe, em seguida, parece que a resposta é enviada para esse dispositivo (arp.c#L679):

static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
{
     struct net_device *dev = skb->dev;
     ...
     arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
           sip, dev, tip, sha,
           dev->dev_addr, sha,
           reply_dst);
}

Mas se o pacote passou pela ponte, então skbseu dispositivo foi obtidosubstituído por dispositivo de ponte:

static int br_pass_frame_up(struct sk_buff *skb)
{
    ...
    skb->dev = brdev;
    ...
}

Não deveria, de alguma forma, recuperar o dispositivo original e enviar a resposta para lá?

Responder1

Se o quadro chegou de uma porta bridge, isso significa que agora há umentrada nova da ponte fdbdizendo para usar esta mesma porta de ponte ao enviar um quadro para este endereço MAC: uma resposta será enviada para a mesma porta de ponte de onde a consulta chegou.

Portanto, do ponto de vista da camada ARP, o pacote foi recebido na interface da ponte e a resposta também foi enviada de volta na interface da ponte.

Quando a resposta atinge a camada inferior: bridge, esse é o código da ponte que faz uma pesquisa em seu banco de dados de encaminhamento (também conhecido comoFIB) e escolhe como porta da ponte de saída a porta da ponte de entrada anterior em vez de inundar a resposta para todas as suas portas (já que existe uma entrada tão recente a ser encontrada):

br_device.c:

netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
...
  } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) {
      br_forward(dst->dst, skb, false, true);
  } else {
      br_flood(br, skb, BR_PKT_UNICAST, false, true);

Fazendo o oposto de antes, a interface da ponte do dispositivo do skb é substituída pela porta da ponte:

br_forward.c:

static void __br_forward(const struct net_bridge_port *to,
           struct sk_buff *skb, bool local_orig)
{
...
      skb->dev = to->dev;
...

informação relacionada