mirror of https://github.com/xemu-project/xemu.git
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJV5yBwAAoJEJykq7OBq3PIbQ4IALIrAi3vHArU2eCA+YcaOeJZ ZvIh/ZaxcTKRA3zqt4WIC19Xz9kLC22l8bgwRVUcLr1i9rQaDLK0aLYRpNeHI2yO XccsJX0Pt6vKeyTB32WqCij85LnxfrEyCGJ8ToOArjV42Rd4pwHKRjyd/oUrdqGC ZI2SLugl3yBowjtdrcRrX7DK06Dk0Yr+xJgDkwkVQic1pRKUuAbnz8WehnI1R6FX N3GtToOEW8GaU63+Khu9hUHKPUc23eoTmLgNLyYgS3/6wGvafVHGgriKWGsiEofV A4SLmrxy7XOqFwwF1awnDLNjKkqfgz3S3lOOIaayis7Q6xENIkcH2cHUyTUUG0k= =s0AU -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging # gpg: Signature made Wed 02 Sep 2015 17:14:40 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/net-pull-request: ne2000: Drop ne2000_can_receive vmxnet3: Drop net_vmxnet3_info.can_receive rtl8139: Do not consume the packet during overflow in standard mode. rtl8139: Fix receive buffer overflow check rtl8139: use ldl/stl wrapper for unaligned 32-bit access rtl8139: use net/eth.h macros instead of custom macros rtl8139: remove duplicate net/eth.h definitions Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
654cd2c584
|
@ -44,7 +44,6 @@ typedef struct ISANE2000State {
|
|||
static NetClientInfo net_ne2000_isa_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = ne2000_can_receive,
|
||||
.receive = ne2000_receive,
|
||||
};
|
||||
|
||||
|
|
|
@ -165,15 +165,6 @@ static int ne2000_buffer_full(NE2000State *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ne2000_can_receive(NetClientState *nc)
|
||||
{
|
||||
NE2000State *s = qemu_get_nic_opaque(nc);
|
||||
|
||||
if (s->cmd & E8390_STOP)
|
||||
return 1;
|
||||
return !ne2000_buffer_full(s);
|
||||
}
|
||||
|
||||
#define MIN_BUF_SIZE 60
|
||||
|
||||
ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
|
||||
|
@ -705,7 +696,6 @@ void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size)
|
|||
static NetClientInfo net_ne2000_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = ne2000_can_receive,
|
||||
.receive = ne2000_receive,
|
||||
};
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ typedef struct NE2000State {
|
|||
void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size);
|
||||
extern const VMStateDescription vmstate_ne2000;
|
||||
void ne2000_reset(NE2000State *s);
|
||||
int ne2000_can_receive(NetClientState *nc);
|
||||
ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
|
||||
|
||||
#endif
|
||||
|
|
111
hw/net/rtl8139.c
111
hw/net/rtl8139.c
|
@ -56,6 +56,7 @@
|
|||
#include "sysemu/dma.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "net/net.h"
|
||||
#include "net/eth.h"
|
||||
#include "hw/loader.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/iov.h"
|
||||
|
@ -72,11 +73,8 @@
|
|||
#define MOD2(input, size) \
|
||||
( ( input ) & ( size - 1 ) )
|
||||
|
||||
#define ETHER_ADDR_LEN 6
|
||||
#define ETHER_TYPE_LEN 2
|
||||
#define ETH_HLEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
|
||||
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
|
||||
#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
|
||||
#define ETH_HLEN (ETH_ALEN * 2 + ETHER_TYPE_LEN)
|
||||
#define ETH_MTU 1500
|
||||
|
||||
#define VLAN_TCI_LEN 2
|
||||
|
@ -1016,8 +1014,8 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||
|
||||
/* write VLAN info to descriptor variables. */
|
||||
if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *)
|
||||
&buf[ETHER_ADDR_LEN * 2]) == ETH_P_8021Q) {
|
||||
dot1q_buf = &buf[ETHER_ADDR_LEN * 2];
|
||||
&buf[ETH_ALEN * 2]) == ETH_P_VLAN) {
|
||||
dot1q_buf = &buf[ETH_ALEN * 2];
|
||||
size -= VLAN_HLEN;
|
||||
/* if too small buffer, use the tailroom added duing expansion */
|
||||
if (size < MIN_BUF_SIZE) {
|
||||
|
@ -1058,10 +1056,10 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||
|
||||
/* receive/copy to target memory */
|
||||
if (dot1q_buf) {
|
||||
pci_dma_write(d, rx_addr, buf, 2 * ETHER_ADDR_LEN);
|
||||
pci_dma_write(d, rx_addr + 2 * ETHER_ADDR_LEN,
|
||||
buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN,
|
||||
size - 2 * ETHER_ADDR_LEN);
|
||||
pci_dma_write(d, rx_addr, buf, 2 * ETH_ALEN);
|
||||
pci_dma_write(d, rx_addr + 2 * ETH_ALEN,
|
||||
buf + 2 * ETH_ALEN + VLAN_HLEN,
|
||||
size - 2 * ETH_ALEN);
|
||||
} else {
|
||||
pci_dma_write(d, rx_addr, buf, size);
|
||||
}
|
||||
|
@ -1148,7 +1146,9 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||
|
||||
/* if receiver buffer is empty then avail == 0 */
|
||||
|
||||
if (avail != 0 && size + 8 >= avail)
|
||||
#define RX_ALIGN(x) (((x) + 3) & ~0x3)
|
||||
|
||||
if (avail != 0 && RX_ALIGN(size + 8) >= avail)
|
||||
{
|
||||
DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
|
||||
"read 0x%04x === available 0x%04x need 0x%04x\n",
|
||||
|
@ -1157,7 +1157,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||
s->IntrStatus |= RxOverflow;
|
||||
++s->RxMissed;
|
||||
rtl8139_update_irq(s);
|
||||
return size_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
packet_header |= RxStatusOK;
|
||||
|
@ -1176,7 +1176,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
|
|||
rtl8139_write_buffer(s, (uint8_t *)&val, 4);
|
||||
|
||||
/* correct buffer write pointer */
|
||||
s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize);
|
||||
s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);
|
||||
|
||||
/* now we can signal we have received something */
|
||||
|
||||
|
@ -1783,12 +1783,12 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
|
|||
return;
|
||||
}
|
||||
|
||||
if (dot1q_buf && size >= ETHER_ADDR_LEN * 2) {
|
||||
if (dot1q_buf && size >= ETH_ALEN * 2) {
|
||||
iov = (struct iovec[3]) {
|
||||
{ .iov_base = buf, .iov_len = ETHER_ADDR_LEN * 2 },
|
||||
{ .iov_base = buf, .iov_len = ETH_ALEN * 2 },
|
||||
{ .iov_base = (void *) dot1q_buf, .iov_len = VLAN_HLEN },
|
||||
{ .iov_base = buf + ETHER_ADDR_LEN * 2,
|
||||
.iov_len = size - ETHER_ADDR_LEN * 2 },
|
||||
{ .iov_base = buf + ETH_ALEN * 2,
|
||||
.iov_len = size - ETH_ALEN * 2 },
|
||||
};
|
||||
|
||||
memcpy(vlan_iov, iov, sizeof(vlan_iov));
|
||||
|
@ -1868,64 +1868,12 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
|
|||
}
|
||||
|
||||
/* structures and macros for task offloading */
|
||||
typedef struct ip_header
|
||||
{
|
||||
uint8_t ip_ver_len; /* version and header length */
|
||||
uint8_t ip_tos; /* type of service */
|
||||
uint16_t ip_len; /* total length */
|
||||
uint16_t ip_id; /* identification */
|
||||
uint16_t ip_off; /* fragment offset field */
|
||||
uint8_t ip_ttl; /* time to live */
|
||||
uint8_t ip_p; /* protocol */
|
||||
uint16_t ip_sum; /* checksum */
|
||||
uint32_t ip_src,ip_dst; /* source and dest address */
|
||||
} ip_header;
|
||||
|
||||
#define IP_HEADER_VERSION_4 4
|
||||
#define IP_HEADER_VERSION(ip) ((ip->ip_ver_len >> 4)&0xf)
|
||||
#define IP_HEADER_LENGTH(ip) (((ip->ip_ver_len)&0xf) << 2)
|
||||
|
||||
typedef struct tcp_header
|
||||
{
|
||||
uint16_t th_sport; /* source port */
|
||||
uint16_t th_dport; /* destination port */
|
||||
uint32_t th_seq; /* sequence number */
|
||||
uint32_t th_ack; /* acknowledgement number */
|
||||
uint16_t th_offset_flags; /* data offset, reserved 6 bits, TCP protocol flags */
|
||||
uint16_t th_win; /* window */
|
||||
uint16_t th_sum; /* checksum */
|
||||
uint16_t th_urp; /* urgent pointer */
|
||||
} tcp_header;
|
||||
|
||||
typedef struct udp_header
|
||||
{
|
||||
uint16_t uh_sport; /* source port */
|
||||
uint16_t uh_dport; /* destination port */
|
||||
uint16_t uh_ulen; /* udp length */
|
||||
uint16_t uh_sum; /* udp checksum */
|
||||
} udp_header;
|
||||
|
||||
typedef struct ip_pseudo_header
|
||||
{
|
||||
uint32_t ip_src;
|
||||
uint32_t ip_dst;
|
||||
uint8_t zeros;
|
||||
uint8_t ip_proto;
|
||||
uint16_t ip_payload;
|
||||
} ip_pseudo_header;
|
||||
|
||||
#define IP_PROTO_TCP 6
|
||||
#define IP_PROTO_UDP 17
|
||||
|
||||
#define TCP_HEADER_DATA_OFFSET(tcp) (((be16_to_cpu(tcp->th_offset_flags) >> 12)&0xf) << 2)
|
||||
#define TCP_FLAGS_ONLY(flags) ((flags)&0x3f)
|
||||
#define TCP_HEADER_FLAGS(tcp) TCP_FLAGS_ONLY(be16_to_cpu(tcp->th_offset_flags))
|
||||
|
||||
#define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off)))
|
||||
|
||||
#define TCP_FLAG_FIN 0x01
|
||||
#define TCP_FLAG_PUSH 0x08
|
||||
|
||||
/* produces ones' complement sum of data */
|
||||
static uint16_t ones_complement_sum(uint8_t *data, size_t len)
|
||||
{
|
||||
|
@ -2134,7 +2082,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||
bswap16(txdw1 & CP_TX_VLAN_TAG_MASK));
|
||||
|
||||
dot1q_buffer = (uint16_t *) dot1q_buffer_space;
|
||||
dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q);
|
||||
dot1q_buffer[0] = cpu_to_be16(ETH_P_VLAN);
|
||||
/* BE + le_to_cpu() + ~cpu_to_le()~ = BE */
|
||||
dot1q_buffer[1] = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK);
|
||||
} else {
|
||||
|
@ -2151,12 +2099,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||
DPRINTF("+++ C+ mode offloaded task checksum\n");
|
||||
|
||||
/* Large enough for Ethernet and IP headers? */
|
||||
if (saved_size < ETH_HLEN + sizeof(ip_header)) {
|
||||
if (saved_size < ETH_HLEN + sizeof(struct ip_header)) {
|
||||
goto skip_offload;
|
||||
}
|
||||
|
||||
/* ip packet header */
|
||||
ip_header *ip = NULL;
|
||||
struct ip_header *ip = NULL;
|
||||
int hlen = 0;
|
||||
uint8_t ip_protocol = 0;
|
||||
uint16_t ip_data_len = 0;
|
||||
|
@ -2172,11 +2120,15 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||
|
||||
DPRINTF("+++ C+ mode has IP packet\n");
|
||||
|
||||
/* not aligned */
|
||||
/* Note on memory alignment: eth_payload_data is 16-bit aligned
|
||||
* since saved_buffer is allocated with g_malloc() and ETH_HLEN is
|
||||
* even. 32-bit accesses must use ldl/stl wrappers to avoid
|
||||
* unaligned accesses.
|
||||
*/
|
||||
eth_payload_data = saved_buffer + ETH_HLEN;
|
||||
eth_payload_len = saved_size - ETH_HLEN;
|
||||
|
||||
ip = (ip_header*)eth_payload_data;
|
||||
ip = (struct ip_header*)eth_payload_data;
|
||||
|
||||
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
||||
DPRINTF("+++ C+ mode packet has bad IP version %d "
|
||||
|
@ -2185,8 +2137,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||
goto skip_offload;
|
||||
}
|
||||
|
||||
hlen = IP_HEADER_LENGTH(ip);
|
||||
if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
|
||||
hlen = IP_HDR_GET_LEN(ip);
|
||||
if (hlen < sizeof(struct ip_header) || hlen > eth_payload_len) {
|
||||
goto skip_offload;
|
||||
}
|
||||
|
||||
|
@ -2269,7 +2221,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||
}
|
||||
|
||||
DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
|
||||
be32_to_cpu(p_tcp_hdr->th_seq));
|
||||
ldl_be_p(&p_tcp_hdr->th_seq));
|
||||
|
||||
/* add 4 TCP pseudoheader fields */
|
||||
/* copy IP source and destination fields */
|
||||
|
@ -2287,7 +2239,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||
/* keep PUSH and FIN flags only for the last frame */
|
||||
if (!is_last_frame)
|
||||
{
|
||||
TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
|
||||
TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TH_PUSH | TH_FIN);
|
||||
}
|
||||
|
||||
/* recalculate TCP checksum */
|
||||
|
@ -2325,7 +2277,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|||
0, (uint8_t *) dot1q_buffer);
|
||||
|
||||
/* add transferred count to TCP sequence number */
|
||||
p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
|
||||
stl_be_p(&p_tcp_hdr->th_seq,
|
||||
chunk_size + ldl_be_p(&p_tcp_hdr->th_seq));
|
||||
++send_count;
|
||||
}
|
||||
|
||||
|
|
|
@ -1988,7 +1988,6 @@ static void vmxnet3_set_link_status(NetClientState *nc)
|
|||
static NetClientInfo net_vmxnet3_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||
.size = sizeof(NICState),
|
||||
.can_receive = vmxnet3_can_receive,
|
||||
.receive = vmxnet3_receive,
|
||||
.link_status_changed = vmxnet3_set_link_status,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue