Revision 1ab74cea

b/slirp/if.c
6 6
 */
7 7

  
8 8
#include <slirp.h>
9
#include "qemu-timer.h"
9 10

  
10 11
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
11 12

  
......
105 106
	ifs_init(ifm);
106 107
	insque(ifm, ifq);
107 108

  
109
        /* Expiration date = Now + 1 second */
110
        ifm->expiration_date = qemu_get_clock_ns(rt_clock) + 1000000000ULL;
111

  
108 112
diddit:
109 113
	slirp->if_queued++;
110 114

  
......
153 157
void
154 158
if_start(Slirp *slirp)
155 159
{
160
    int requeued = 0;
161
    uint64_t now;
162

  
156 163
	struct mbuf *ifm, *ifqt;
157 164

  
158 165
	DEBUG_CALL("if_start");
......
165 172
        if (!slirp_can_output(slirp->opaque))
166 173
            return;
167 174

  
175
        now = qemu_get_clock_ns(rt_clock);
176

  
168 177
	/*
169 178
	 * See which queue to get next packet from
170 179
	 * If there's something in the fastq, select it immediately
......
199 208
		   ifm->ifq_so->so_nqueued = 0;
200 209
	}
201 210

  
202
	/* Encapsulate the packet for sending */
203
        if_encap(slirp, (uint8_t *)ifm->m_data, ifm->m_len);
204

  
205
        m_free(ifm);
211
        if (ifm->expiration_date < now) {
212
            /* Expired */
213
            m_free(ifm);
214
        } else {
215
            /* Encapsulate the packet for sending */
216
            if (if_encap(slirp, ifm)) {
217
                m_free(ifm);
218
            } else {
219
                /* re-queue */
220
                insque(ifm, ifqt);
221
                requeued++;
222
            }
223
        }
206 224

  
207 225
	if (slirp->if_queued)
208 226
	   goto again;
227

  
228
        slirp->if_queued = requeued;
209 229
}
b/slirp/main.h
42 42
#define PROTO_PPP 0x2
43 43
#endif
44 44

  
45
void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len);
45
int if_encap(Slirp *slirp, struct mbuf *ifm);
46 46
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
b/slirp/mbuf.c
70 70
	m->m_len = 0;
71 71
        m->m_nextpkt = NULL;
72 72
        m->m_prevpkt = NULL;
73
        m->arp_requested = false;
74
        m->expiration_date = (uint64_t)-1;
73 75
end_error:
74 76
	DEBUG_ARG("m = %lx", (long )m);
75 77
	return m;
b/slirp/mbuf.h
86 86
		char	m_dat_[1]; /* ANSI don't like 0 sized arrays */
87 87
		char	*m_ext_;
88 88
	} M_dat;
89
    bool     arp_requested;
90
    uint64_t expiration_date;
89 91
};
90 92

  
91 93
#define m_next		m_hdr.mh_next
b/slirp/slirp.c
692 692
    }
693 693
}
694 694

  
695
/* output the IP packet to the ethernet device */
696
void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
695
/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
696
 * re-queued.
697
 */
698
int if_encap(Slirp *slirp, struct mbuf *ifm)
697 699
{
698 700
    uint8_t buf[1600];
699 701
    struct ethhdr *eh = (struct ethhdr *)buf;
700 702
    uint8_t ethaddr[ETH_ALEN];
701
    const struct ip *iph = (const struct ip *)ip_data;
703
    const struct ip *iph = (const struct ip *)ifm->m_data;
702 704

  
703
    if (ip_data_len + ETH_HLEN > sizeof(buf))
704
        return;
705
    if (ifm->m_len + ETH_HLEN > sizeof(buf)) {
706
        return 1;
707
    }
705 708

  
706 709
    if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
707 710
        uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
708 711
        struct ethhdr *reh = (struct ethhdr *)arp_req;
709 712
        struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
710 713

  
711
        /* If the client addr is not known, there is no point in
712
           sending the packet to it. Normally the sender should have
713
           done an ARP request to get its MAC address. Here we do it
714
           in place of sending the packet and we hope that the sender
715
           will retry sending its packet. */
716
        memset(reh->h_dest, 0xff, ETH_ALEN);
717
        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
718
        memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
719
        reh->h_proto = htons(ETH_P_ARP);
720
        rah->ar_hrd = htons(1);
721
        rah->ar_pro = htons(ETH_P_IP);
722
        rah->ar_hln = ETH_ALEN;
723
        rah->ar_pln = 4;
724
        rah->ar_op = htons(ARPOP_REQUEST);
725
        /* source hw addr */
726
        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
727
        memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
728
        /* source IP */
729
        rah->ar_sip = slirp->vhost_addr.s_addr;
730
        /* target hw addr (none) */
731
        memset(rah->ar_tha, 0, ETH_ALEN);
732
        /* target IP */
733
        rah->ar_tip = iph->ip_dst.s_addr;
734
        slirp->client_ipaddr = iph->ip_dst;
735
        slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
714
        if (!ifm->arp_requested) {
715
            /* If the client addr is not known, send an ARP request */
716
            memset(reh->h_dest, 0xff, ETH_ALEN);
717
            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
718
            memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
719
            reh->h_proto = htons(ETH_P_ARP);
720
            rah->ar_hrd = htons(1);
721
            rah->ar_pro = htons(ETH_P_IP);
722
            rah->ar_hln = ETH_ALEN;
723
            rah->ar_pln = 4;
724
            rah->ar_op = htons(ARPOP_REQUEST);
725

  
726
            /* source hw addr */
727
            memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
728
            memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
729

  
730
            /* source IP */
731
            rah->ar_sip = slirp->vhost_addr.s_addr;
732

  
733
            /* target hw addr (none) */
734
            memset(rah->ar_tha, 0, ETH_ALEN);
735

  
736
            /* target IP */
737
            rah->ar_tip = iph->ip_dst.s_addr;
738
            slirp->client_ipaddr = iph->ip_dst;
739
            slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
740
            ifm->arp_requested = true;
741
        }
742
        return 0;
736 743
    } else {
737 744
        memcpy(eh->h_dest, ethaddr, ETH_ALEN);
738 745
        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
739 746
        /* XXX: not correct */
740 747
        memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
741 748
        eh->h_proto = htons(ETH_P_IP);
742
        memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
743
        slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
749
        memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
750
        slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
751
        return 1;
744 752
    }
745 753
}
746 754

  

Also available in: Unified diff