qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH V2 1/2] [SLIRP] Simple ARP table


From: Jan Kiszka
Subject: Re: [Qemu-devel] [PATCH V2 1/2] [SLIRP] Simple ARP table
Date: Sat, 30 Jul 2011 11:09:45 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666

On 2011-07-29 19:34, Jan Kiszka wrote:
> On 2011-07-29 18:25, Fabien Chouteau wrote:
>> This patch adds a simple ARP table in Slirp and also adds handling of
>> gratuitous ARP requests.
>>
>> Signed-off-by: Fabien Chouteau <address@hidden>
>> ---
>>  Makefile.objs     |    2 +-
>>  slirp/arp_table.c |   50 ++++++++++++++++++++++++++++++++++++++++++
>>  slirp/bootp.c     |   23 ++++++++++++------
>>  slirp/slirp.c     |   63 
>> +++++++++++++---------------------------------------
>>  slirp/slirp.h     |   50 +++++++++++++++++++++++++++++++++++++++--
>>  5 files changed, 129 insertions(+), 59 deletions(-)
>>  create mode 100644 slirp/arp_table.c
>>
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 6991a9f..0c10557 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -151,7 +151,7 @@ common-obj-y += qemu-timer.o qemu-timer-common.o
>>
>>  slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
>>  slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o 
>> tcp_output.o
>> -slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o
>> +slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
>>  common-obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
>>
>>  # xen backend driver support
>> diff --git a/slirp/arp_table.c b/slirp/arp_table.c
>> new file mode 100644
>> index 0000000..5d7404b
>> --- /dev/null
>> +++ b/slirp/arp_table.c
>> @@ -0,0 +1,50 @@
>> +#include "slirp.h"
>> +
>> +void arp_table_add(ArpTable *arptbl,
>> +                   int       ip_addr,
>> +                   uint8_t   ethaddr[ETH_ALEN])
> 
> I still prefer the condensed formatting, but that's a minor nit.
> 
>> +{
>> +    int i;
>> +
>> +    DEBUG_CALL("arp_table_add");
>> +    DEBUG_ARG("ip = 0x%x", ip_addr);
>> +    DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
>> +                ethaddr[0], ethaddr[1], ethaddr[2],
>> +                ethaddr[3], ethaddr[4], ethaddr[5]));
>> +
>> +    /* Search for an entry */
>> +    for (i = 0; i < ARP_TABLE_SIZE && arptbl->table[i].ar_sip != 0; i++) {
> 
> Missed that on round #1: Why treating 0.0.0.0 special? If ip_addr can be
> zero, the current logic will append every "update" of that address as a
> new entry.
> 
>> +        if (arptbl->table[i].ar_sip == ip_addr) {
>> +            /* Update the entry */
>> +            memcpy(arptbl->table[i].ar_sha, ethaddr, ETH_ALEN);
>> +            return;
>> +        }
>> +    }
>> +
>> +    /* No entry found, create a new one */
>> +    arptbl->table[arptbl->next_victim].ar_sip = ip_addr;
>> +    memcpy(arptbl->table[arptbl->next_victim].ar_sha,  ethaddr, ETH_ALEN);
>> +    arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE;
>> +}
>> +
>> +bool arp_table_search(ArpTable *arptbl,
>> +                      int       in_ip_addr,
>> +                      uint8_t   out_ethaddr[ETH_ALEN])
>> +{
>> +    int i;
>> +
>> +    DEBUG_CALL("arp_table_search");
>> +    DEBUG_ARG("ip = 0x%x", in_ip_addr);
>> +
>> +    for (i = 0; i < ARP_TABLE_SIZE; i++) {
>> +        if (arptbl->table[i].ar_sip == in_ip_addr) {
>> +            memcpy(out_ethaddr, arptbl->table[i].ar_sha,  ETH_ALEN);
>> +            DEBUG_ARGS((dfd, " found hw addr = 
>> %02x:%02x:%02x:%02x:%02x:%02x\n",
>> +                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
>> +                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
>> +            return 1;
>> +        }
>> +    }
>> +
>> +    return 0;
>> +}
>> diff --git a/slirp/bootp.c b/slirp/bootp.c
>> index 1eb2ed1..07cbb80 100644
>> --- a/slirp/bootp.c
>> +++ b/slirp/bootp.c
>> @@ -149,6 +149,7 @@ static void bootp_reply(Slirp *slirp, const struct 
>> bootp_t *bp)
>>      struct in_addr preq_addr;
>>      int dhcp_msg_type, val;
>>      uint8_t *q;
>> +    uint8_t client_ethaddr[ETH_ALEN];
>>
>>      /* extract exact DHCP msg type */
>>      dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
>> @@ -164,8 +165,9 @@ static void bootp_reply(Slirp *slirp, const struct 
>> bootp_t *bp)
>>      if (dhcp_msg_type != DHCPDISCOVER &&
>>          dhcp_msg_type != DHCPREQUEST)
>>          return;
>> -    /* XXX: this is a hack to get the client mac address */
>> -    memcpy(slirp->client_ethaddr, bp->bp_hwaddr, 6);
>> +
>> +    /* Get client's hardware address from bootp request */
>> +    memcpy(client_ethaddr, bp->bp_hwaddr, ETH_ALEN);
>>
>>      m = m_get(slirp);
>>      if (!m) {
>> @@ -178,25 +180,25 @@ static void bootp_reply(Slirp *slirp, const struct 
>> bootp_t *bp)
>>
>>      if (dhcp_msg_type == DHCPDISCOVER) {
>>          if (preq_addr.s_addr != htonl(0L)) {
>> -            bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
>> +            bc = request_addr(slirp, &preq_addr, client_ethaddr);
>>              if (bc) {
>>                  daddr.sin_addr = preq_addr;
>>              }
>>          }
>>          if (!bc) {
>>           new_addr:
>> -            bc = get_new_addr(slirp, &daddr.sin_addr, 
>> slirp->client_ethaddr);
>> +            bc = get_new_addr(slirp, &daddr.sin_addr, client_ethaddr);
>>              if (!bc) {
>>                  DPRINTF("no address left\n");
>>                  return;
>>              }
>>          }
>> -        memcpy(bc->macaddr, slirp->client_ethaddr, 6);
>> +        memcpy(bc->macaddr, client_ethaddr, ETH_ALEN);
>>      } else if (preq_addr.s_addr != htonl(0L)) {
>> -        bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
>> +        bc = request_addr(slirp, &preq_addr, client_ethaddr);
>>          if (bc) {
>>              daddr.sin_addr = preq_addr;
>> -            memcpy(bc->macaddr, slirp->client_ethaddr, 6);
>> +            memcpy(bc->macaddr, client_ethaddr, ETH_ALEN);
>>          } else {
>>              daddr.sin_addr.s_addr = 0;
>>          }
>> @@ -209,6 +211,11 @@ static void bootp_reply(Slirp *slirp, const struct 
>> bootp_t *bp)
>>          }
>>      }
>>
>> +    if (daddr.sin_addr.s_addr != 0) {
>> +        /* Update ARP table for this IP address */
>> +        arp_table_add(&slirp->arp_table, daddr.sin_addr.s_addr, 
>> client_ethaddr);
> 
> Here you prevent that arp_table_add is called with a zero IP, but not in
> arp_input below. Likely harmless, but at least inconsistent.
> 

Unfortunately, this patch also has a more sever issues: it breaks DHCP e.g.

Slirp's bootp sends out all replies, also acks and offers, as
broadcasts. Normal servers already use the clients IP address as
destination here.

Even if bootp is fixed, you still lack logic to deal with special
addresses in your arp table lookup. At least broadcasts need to be
handled, I think other multicasts aren't supported by slirp anyway.

Jan

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]