-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJeg0JmAAoJEO8Ells5jWIRriwIAIJP3RSeSZpipxXoI8aIVOHv mkteuLqJpid0+wwpmT+YAv6PpniJ76Rwrc54VsOKBURG/baJAoGR5ozsu+dS/pF5 VW9rFarR6FyRcLJWA/I4q3C9rhzcNwhoA2l0Jwy0sXQFYegsptb2Qc+Mr+Fw1hGZ mnIB7g4wXZc0NuGY+SAuQdlS0HvIgf8Lbv8z1i0vO2h1ADTFIjhrrnbsZ2//Nttu YwFh4IZJzirZ7VqRbfqo0fK6yElAA3EI6VjkPospuxOT6XcNp4ODEMMfeEl2qSa/ TSVCnCXBXaoX8HPdVfdb3zK4GA11wITDkF+uv9Nx0/AUYJSsOgMkqItHoQr24uQ= =Kh21 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging # gpg: Signature made Tue 31 Mar 2020 14:15:18 BST # gpg: using RSA key EF04965B398D6211 # gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" [marginal] # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211 * remotes/jasowang/tags/net-pull-request: qtest: add tulip test case hw/net/allwinner-sun8i-emac.c: Fix REG_ADDR_HIGH/LOW reads net: tulip: check frame size and r/w data length net/colo-compare.c: Expose "expired_scan_cycle" to users net/colo-compare.c: Expose "compare_timeout" to users hw/net/can: Make CanBusClientInfo::can_receive() return a boolean hw/net: Make NetCanReceive() return a boolean hw/net/rtl8139: Update coding style to make checkpatch.pl happy hw/net/rtl8139: Simplify if/else statement hw/net/smc91c111: Let smc91c111_can_receive() return a boolean hw/net/e1000e_core: Let e1000e_can_receive() return a boolean Fixed integer overflow in e1000e hw/net/i82596.c: Avoid reading off end of buffer in i82596_receive() hw/net/i82596: Correct command bitmask (CID 1419392) Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
17083d6d1e
@ -395,7 +395,7 @@ static void allwinner_sun8i_emac_flush_desc(FrameDescriptor *desc,
|
|||||||
cpu_physical_memory_write(phys_addr, desc, sizeof(*desc));
|
cpu_physical_memory_write(phys_addr, desc, sizeof(*desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int allwinner_sun8i_emac_can_receive(NetClientState *nc)
|
static bool allwinner_sun8i_emac_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
|
AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
|
||||||
FrameDescriptor desc;
|
FrameDescriptor desc;
|
||||||
@ -611,10 +611,10 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
|
|||||||
value = s->mii_data;
|
value = s->mii_data;
|
||||||
break;
|
break;
|
||||||
case REG_ADDR_HIGH: /* MAC Address High */
|
case REG_ADDR_HIGH: /* MAC Address High */
|
||||||
value = *(((uint32_t *) (s->conf.macaddr.a)) + 1);
|
value = lduw_le_p(s->conf.macaddr.a + 4);
|
||||||
break;
|
break;
|
||||||
case REG_ADDR_LOW: /* MAC Address Low */
|
case REG_ADDR_LOW: /* MAC Address Low */
|
||||||
value = *(uint32_t *) (s->conf.macaddr.a);
|
value = ldl_le_p(s->conf.macaddr.a);
|
||||||
break;
|
break;
|
||||||
case REG_TX_DMA_STA: /* Transmit DMA Status */
|
case REG_TX_DMA_STA: /* Transmit DMA Status */
|
||||||
break;
|
break;
|
||||||
@ -728,14 +728,10 @@ static void allwinner_sun8i_emac_write(void *opaque, hwaddr offset,
|
|||||||
s->mii_data = value;
|
s->mii_data = value;
|
||||||
break;
|
break;
|
||||||
case REG_ADDR_HIGH: /* MAC Address High */
|
case REG_ADDR_HIGH: /* MAC Address High */
|
||||||
s->conf.macaddr.a[4] = (value & 0xff);
|
stw_le_p(s->conf.macaddr.a + 4, value);
|
||||||
s->conf.macaddr.a[5] = (value & 0xff00) >> 8;
|
|
||||||
break;
|
break;
|
||||||
case REG_ADDR_LOW: /* MAC Address Low */
|
case REG_ADDR_LOW: /* MAC Address Low */
|
||||||
s->conf.macaddr.a[0] = (value & 0xff);
|
stl_le_p(s->conf.macaddr.a, value);
|
||||||
s->conf.macaddr.a[1] = (value & 0xff00) >> 8;
|
|
||||||
s->conf.macaddr.a[2] = (value & 0xff0000) >> 16;
|
|
||||||
s->conf.macaddr.a[3] = (value & 0xff000000) >> 24;
|
|
||||||
break;
|
break;
|
||||||
case REG_TX_DMA_STA: /* Transmit DMA Status */
|
case REG_TX_DMA_STA: /* Transmit DMA Status */
|
||||||
case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
|
case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
|
||||||
|
@ -178,7 +178,7 @@ static uint32_t fifo8_pop_word(Fifo8 *fifo)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aw_emac_can_receive(NetClientState *nc)
|
static bool aw_emac_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
AwEmacState *s = qemu_get_nic_opaque(nc);
|
AwEmacState *s = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ static void phy_update_link(CadenceGEMState *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gem_can_receive(NetClientState *nc)
|
static bool gem_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
CadenceGEMState *s;
|
CadenceGEMState *s;
|
||||||
int i;
|
int i;
|
||||||
@ -518,7 +518,7 @@ static int gem_can_receive(NetClientState *nc)
|
|||||||
s->can_rx_state = 1;
|
s->can_rx_state = 1;
|
||||||
DB_PRINT("can't receive - no enable\n");
|
DB_PRINT("can't receive - no enable\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < s->num_priority_queues; i++) {
|
for (i = 0; i < s->num_priority_queues; i++) {
|
||||||
@ -532,14 +532,14 @@ static int gem_can_receive(NetClientState *nc)
|
|||||||
s->can_rx_state = 2;
|
s->can_rx_state = 2;
|
||||||
DB_PRINT("can't receive - all the buffer descriptors are busy\n");
|
DB_PRINT("can't receive - all the buffer descriptors are busy\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->can_rx_state != 0) {
|
if (s->can_rx_state != 0) {
|
||||||
s->can_rx_state = 0;
|
s->can_rx_state = 0;
|
||||||
DB_PRINT("can receive\n");
|
DB_PRINT("can receive\n");
|
||||||
}
|
}
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -733,21 +733,21 @@ uint64_t can_sja_mem_read(CanSJA1000State *s, hwaddr addr, unsigned size)
|
|||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int can_sja_can_receive(CanBusClientState *client)
|
bool can_sja_can_receive(CanBusClientState *client)
|
||||||
{
|
{
|
||||||
CanSJA1000State *s = container_of(client, CanSJA1000State, bus_client);
|
CanSJA1000State *s = container_of(client, CanSJA1000State, bus_client);
|
||||||
|
|
||||||
if (s->clock & 0x80) { /* PeliCAN Mode */
|
if (s->clock & 0x80) { /* PeliCAN Mode */
|
||||||
if (s->mode & 0x01) { /* reset mode. */
|
if (s->mode & 0x01) { /* reset mode. */
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
} else { /* BasicCAN mode */
|
} else { /* BasicCAN mode */
|
||||||
if (s->control & 0x01) {
|
if (s->control & 0x01) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* always return 1, when operation mode */
|
return true; /* always return true, when operation mode */
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t can_sja_receive(CanBusClientState *client, const qemu_can_frame *frames,
|
ssize_t can_sja_receive(CanBusClientState *client, const qemu_can_frame *frames,
|
||||||
|
@ -137,7 +137,7 @@ void can_sja_disconnect(CanSJA1000State *s);
|
|||||||
|
|
||||||
int can_sja_init(CanSJA1000State *s, qemu_irq irq);
|
int can_sja_init(CanSJA1000State *s, qemu_irq irq);
|
||||||
|
|
||||||
int can_sja_can_receive(CanBusClientState *client);
|
bool can_sja_can_receive(CanBusClientState *client);
|
||||||
|
|
||||||
ssize_t can_sja_receive(CanBusClientState *client,
|
ssize_t can_sja_receive(CanBusClientState *client,
|
||||||
const qemu_can_frame *frames, size_t frames_cnt);
|
const qemu_can_frame *frames, size_t frames_cnt);
|
||||||
|
@ -414,7 +414,7 @@ static void dp8393x_do_stop_timer(dp8393xState *s)
|
|||||||
dp8393x_update_wt_regs(s);
|
dp8393x_update_wt_regs(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dp8393x_can_receive(NetClientState *nc);
|
static bool dp8393x_can_receive(NetClientState *nc);
|
||||||
|
|
||||||
static void dp8393x_do_receiver_enable(dp8393xState *s)
|
static void dp8393x_do_receiver_enable(dp8393xState *s)
|
||||||
{
|
{
|
||||||
@ -718,13 +718,11 @@ static void dp8393x_watchdog(void *opaque)
|
|||||||
dp8393x_update_irq(s);
|
dp8393x_update_irq(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dp8393x_can_receive(NetClientState *nc)
|
static bool dp8393x_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
dp8393xState *s = qemu_get_nic_opaque(nc);
|
dp8393xState *s = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
if (!(s->regs[SONIC_CR] & SONIC_CR_RXEN))
|
return !!(s->regs[SONIC_CR] & SONIC_CR_RXEN);
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf,
|
static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf,
|
||||||
|
@ -845,7 +845,7 @@ static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
|
|||||||
return total_size <= bufs * s->rxbuf_size;
|
return total_size <= bufs * s->rxbuf_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static bool
|
||||||
e1000_can_receive(NetClientState *nc)
|
e1000_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
E1000State *s = qemu_get_nic_opaque(nc);
|
E1000State *s = qemu_get_nic_opaque(nc);
|
||||||
|
@ -199,7 +199,7 @@ static const MemoryRegionOps io_ops = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static bool
|
||||||
e1000e_nc_can_receive(NetClientState *nc)
|
e1000e_nc_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
E1000EState *s = qemu_get_nic_opaque(nc);
|
E1000EState *s = qemu_get_nic_opaque(nc);
|
||||||
@ -328,7 +328,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr)
|
|||||||
s->nic = qemu_new_nic(&net_e1000e_info, &s->conf,
|
s->nic = qemu_new_nic(&net_e1000e_info, &s->conf,
|
||||||
object_get_typename(OBJECT(s)), dev->id, s);
|
object_get_typename(OBJECT(s)), dev->id, s);
|
||||||
|
|
||||||
s->core.max_queue_num = s->conf.peers.queues - 1;
|
s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0;
|
||||||
|
|
||||||
trace_e1000e_mac_set_permanent(MAC_ARG(macaddr));
|
trace_e1000e_mac_set_permanent(MAC_ARG(macaddr));
|
||||||
memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac));
|
memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac));
|
||||||
|
@ -967,7 +967,7 @@ e1000e_start_recv(E1000ECore *core)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
bool
|
||||||
e1000e_can_receive(E1000ECore *core)
|
e1000e_can_receive(E1000ECore *core)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -143,7 +143,7 @@ e1000e_core_set_link_status(E1000ECore *core);
|
|||||||
void
|
void
|
||||||
e1000e_core_pci_uninit(E1000ECore *core);
|
e1000e_core_pci_uninit(E1000ECore *core);
|
||||||
|
|
||||||
int
|
bool
|
||||||
e1000e_can_receive(E1000ECore *core);
|
e1000e_can_receive(E1000ECore *core);
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
|
@ -562,18 +562,18 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
|
|||||||
ftgmac100_update_irq(s);
|
ftgmac100_update_irq(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ftgmac100_can_receive(NetClientState *nc)
|
static bool ftgmac100_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
|
FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
|
||||||
FTGMAC100Desc bd;
|
FTGMAC100Desc bd;
|
||||||
|
|
||||||
if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN))
|
if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN))
|
||||||
!= (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) {
|
!= (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ftgmac100_read_bd(&bd, s->rx_descriptor)) {
|
if (ftgmac100_read_bd(&bd, s->rx_descriptor)) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
return !(bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY);
|
return !(bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#define SCB_STATUS_CNA 0x2000 /* CU left active state */
|
#define SCB_STATUS_CNA 0x2000 /* CU left active state */
|
||||||
#define SCB_STATUS_RNR 0x1000 /* RU left active state */
|
#define SCB_STATUS_RNR 0x1000 /* RU left active state */
|
||||||
|
|
||||||
|
#define SCB_COMMAND_ACK_MASK \
|
||||||
|
(SCB_STATUS_CX | SCB_STATUS_FR | SCB_STATUS_CNA | SCB_STATUS_RNR)
|
||||||
|
|
||||||
#define CU_IDLE 0
|
#define CU_IDLE 0
|
||||||
#define CU_SUSPENDED 1
|
#define CU_SUSPENDED 1
|
||||||
#define CU_ACTIVE 2
|
#define CU_ACTIVE 2
|
||||||
@ -348,14 +351,7 @@ static void examine_scb(I82596State *s)
|
|||||||
/* and clear the scb command word */
|
/* and clear the scb command word */
|
||||||
set_uint16(s->scb + 2, 0);
|
set_uint16(s->scb + 2, 0);
|
||||||
|
|
||||||
if (command & BIT(31)) /* ACK-CX */
|
s->scb_status &= ~(command & SCB_COMMAND_ACK_MASK);
|
||||||
s->scb_status &= ~SCB_STATUS_CX;
|
|
||||||
if (command & BIT(30)) /*ACK-FR */
|
|
||||||
s->scb_status &= ~SCB_STATUS_FR;
|
|
||||||
if (command & BIT(29)) /*ACK-CNA */
|
|
||||||
s->scb_status &= ~SCB_STATUS_CNA;
|
|
||||||
if (command & BIT(28)) /*ACK-RNR */
|
|
||||||
s->scb_status &= ~SCB_STATUS_RNR;
|
|
||||||
|
|
||||||
switch (cuc) {
|
switch (cuc) {
|
||||||
case 0: /* no change */
|
case 0: /* no change */
|
||||||
@ -474,23 +470,23 @@ void i82596_h_reset(void *opaque)
|
|||||||
i82596_s_reset(s);
|
i82596_s_reset(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i82596_can_receive(NetClientState *nc)
|
bool i82596_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
I82596State *s = qemu_get_nic_opaque(nc);
|
I82596State *s = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
if (s->rx_status == RX_SUSPENDED) {
|
if (s->rx_status == RX_SUSPENDED) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->lnkst) {
|
if (!s->lnkst) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (USE_TIMER && !timer_pending(s->flush_queue_timer)) {
|
if (USE_TIMER && !timer_pending(s->flush_queue_timer)) {
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_BUF_SIZE 60
|
#define MIN_BUF_SIZE 60
|
||||||
@ -501,7 +497,8 @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz)
|
|||||||
uint32_t rfd_p;
|
uint32_t rfd_p;
|
||||||
uint32_t rbd;
|
uint32_t rbd;
|
||||||
uint16_t is_broadcast = 0;
|
uint16_t is_broadcast = 0;
|
||||||
size_t len = sz;
|
size_t len = sz; /* length of data for guest (including CRC) */
|
||||||
|
size_t bufsz = sz; /* length of data in buf */
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
uint8_t *crc_ptr;
|
uint8_t *crc_ptr;
|
||||||
uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN];
|
uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN];
|
||||||
@ -595,6 +592,7 @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz)
|
|||||||
if (len < MIN_BUF_SIZE) {
|
if (len < MIN_BUF_SIZE) {
|
||||||
len = MIN_BUF_SIZE;
|
len = MIN_BUF_SIZE;
|
||||||
}
|
}
|
||||||
|
bufsz = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the ethernet checksum (4 bytes) */
|
/* Calculate the ethernet checksum (4 bytes) */
|
||||||
@ -627,6 +625,7 @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz)
|
|||||||
while (len) {
|
while (len) {
|
||||||
uint16_t buffer_size, num;
|
uint16_t buffer_size, num;
|
||||||
uint32_t rba;
|
uint32_t rba;
|
||||||
|
size_t bufcount, crccount;
|
||||||
|
|
||||||
/* printf("Receive: rbd is %08x\n", rbd); */
|
/* printf("Receive: rbd is %08x\n", rbd); */
|
||||||
buffer_size = get_uint16(rbd + 12);
|
buffer_size = get_uint16(rbd + 12);
|
||||||
@ -639,14 +638,37 @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz)
|
|||||||
}
|
}
|
||||||
rba = get_uint32(rbd + 8);
|
rba = get_uint32(rbd + 8);
|
||||||
/* printf("rba is 0x%x\n", rba); */
|
/* printf("rba is 0x%x\n", rba); */
|
||||||
|
/*
|
||||||
|
* Calculate how many bytes we want from buf[] and how many
|
||||||
|
* from the CRC.
|
||||||
|
*/
|
||||||
|
if ((len - num) >= 4) {
|
||||||
|
/* The whole guest buffer, we haven't hit the CRC yet */
|
||||||
|
bufcount = num;
|
||||||
|
} else {
|
||||||
|
/* All that's left of buf[] */
|
||||||
|
bufcount = len - 4;
|
||||||
|
}
|
||||||
|
crccount = num - bufcount;
|
||||||
|
|
||||||
|
if (bufcount > 0) {
|
||||||
|
/* Still some of the actual data buffer to transfer */
|
||||||
|
assert(bufsz >= bufcount);
|
||||||
|
bufsz -= bufcount;
|
||||||
address_space_write(&address_space_memory, rba,
|
address_space_write(&address_space_memory, rba,
|
||||||
MEMTXATTRS_UNSPECIFIED, buf, num);
|
MEMTXATTRS_UNSPECIFIED, buf, bufcount);
|
||||||
rba += num;
|
rba += bufcount;
|
||||||
buf += num;
|
buf += bufcount;
|
||||||
len -= num;
|
len -= bufcount;
|
||||||
if (len == 0) { /* copy crc */
|
}
|
||||||
address_space_write(&address_space_memory, rba - 4,
|
|
||||||
MEMTXATTRS_UNSPECIFIED, crc_ptr, 4);
|
/* Write as much of the CRC as fits */
|
||||||
|
if (crccount > 0) {
|
||||||
|
address_space_write(&address_space_memory, rba,
|
||||||
|
MEMTXATTRS_UNSPECIFIED, crc_ptr, crccount);
|
||||||
|
rba += crccount;
|
||||||
|
crc_ptr += crccount;
|
||||||
|
len -= crccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
num |= 0x4000; /* set F BIT */
|
num |= 0x4000; /* set F BIT */
|
||||||
|
@ -48,7 +48,7 @@ void i82596_ioport_writel(void *opaque, uint32_t addr, uint32_t val);
|
|||||||
uint32_t i82596_ioport_readl(void *opaque, uint32_t addr);
|
uint32_t i82596_ioport_readl(void *opaque, uint32_t addr);
|
||||||
uint32_t i82596_bcr_readw(I82596State *s, uint32_t rap);
|
uint32_t i82596_bcr_readw(I82596State *s, uint32_t rap);
|
||||||
ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
|
ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
|
||||||
int i82596_can_receive(NetClientState *nc);
|
bool i82596_can_receive(NetClientState *nc);
|
||||||
void i82596_set_link_status(NetClientState *nc);
|
void i82596_set_link_status(NetClientState *nc);
|
||||||
void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info);
|
void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info);
|
||||||
extern const VMStateDescription vmstate_i82596;
|
extern const VMStateDescription vmstate_i82596;
|
||||||
|
@ -1049,7 +1049,7 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
imx_eth_update(s);
|
imx_eth_update(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx_eth_can_receive(NetClientState *nc)
|
static bool imx_eth_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
|
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
|
||||||
|
|
||||||
|
@ -349,12 +349,11 @@ static void open_eth_reset(void *opaque)
|
|||||||
open_eth_set_link_status(qemu_get_queue(s->nic));
|
open_eth_set_link_status(qemu_get_queue(s->nic));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_eth_can_receive(NetClientState *nc)
|
static bool open_eth_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
OpenEthState *s = qemu_get_nic_opaque(nc);
|
OpenEthState *s = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
return GET_REGBIT(s, MODER, RXEN) &&
|
return GET_REGBIT(s, MODER, RXEN) && (s->regs[TX_BD_NUM] < 0x80);
|
||||||
(s->regs[TX_BD_NUM] < 0x80);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t open_eth_receive(NetClientState *nc,
|
static ssize_t open_eth_receive(NetClientState *nc,
|
||||||
|
@ -793,26 +793,28 @@ static bool rtl8139_cp_rx_valid(RTL8139State *s)
|
|||||||
return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0);
|
return !(s->RxRingAddrLO == 0 && s->RxRingAddrHI == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl8139_can_receive(NetClientState *nc)
|
static bool rtl8139_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
RTL8139State *s = qemu_get_nic_opaque(nc);
|
RTL8139State *s = qemu_get_nic_opaque(nc);
|
||||||
int avail;
|
int avail;
|
||||||
|
|
||||||
/* Receive (drop) packets if card is disabled. */
|
/* Receive (drop) packets if card is disabled. */
|
||||||
if (!s->clock_enabled)
|
if (!s->clock_enabled) {
|
||||||
return 1;
|
return true;
|
||||||
if (!rtl8139_receiver_enabled(s))
|
}
|
||||||
return 1;
|
if (!rtl8139_receiver_enabled(s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) {
|
if (rtl8139_cp_receiver_enabled(s) && rtl8139_cp_rx_valid(s)) {
|
||||||
/* ??? Flow control not implemented in c+ mode.
|
/* ??? Flow control not implemented in c+ mode.
|
||||||
This is a hack to work around slirp deficiencies anyway. */
|
This is a hack to work around slirp deficiencies anyway. */
|
||||||
return 1;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr,
|
avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr,
|
||||||
s->RxBufferSize);
|
s->RxBufferSize);
|
||||||
return (avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow));
|
return avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt)
|
static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt)
|
||||||
|
@ -130,16 +130,16 @@ static void smc91c111_update(smc91c111_state *s)
|
|||||||
qemu_set_irq(s->irq, level);
|
qemu_set_irq(s->irq, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smc91c111_can_receive(smc91c111_state *s)
|
static bool smc91c111_can_receive(smc91c111_state *s)
|
||||||
{
|
{
|
||||||
if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) {
|
if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) {
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
if (s->allocated == (1 << NUM_PACKETS) - 1 ||
|
if (s->allocated == (1 << NUM_PACKETS) - 1 ||
|
||||||
s->rx_fifo_len == NUM_PACKETS) {
|
s->rx_fifo_len == NUM_PACKETS) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void smc91c111_flush_queued_packets(smc91c111_state *s)
|
static inline void smc91c111_flush_queued_packets(smc91c111_state *s)
|
||||||
@ -667,7 +667,7 @@ static void smc91c111_writefn(void *opaque, hwaddr addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smc91c111_can_receive_nc(NetClientState *nc)
|
static bool smc91c111_can_receive_nc(NetClientState *nc)
|
||||||
{
|
{
|
||||||
smc91c111_state *s = qemu_get_nic_opaque(nc);
|
smc91c111_state *s = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
|
@ -110,11 +110,11 @@ typedef struct SpaprVioVlan {
|
|||||||
RxBufPool *rx_pool[RX_MAX_POOLS]; /* Receive buffer descriptor pools */
|
RxBufPool *rx_pool[RX_MAX_POOLS]; /* Receive buffer descriptor pools */
|
||||||
} SpaprVioVlan;
|
} SpaprVioVlan;
|
||||||
|
|
||||||
static int spapr_vlan_can_receive(NetClientState *nc)
|
static bool spapr_vlan_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
SpaprVioVlan *dev = qemu_get_nic_opaque(nc);
|
SpaprVioVlan *dev = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
return (dev->isopen && dev->rx_bufs > 0);
|
return dev->isopen && dev->rx_bufs > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -433,7 +433,7 @@ static bool sungem_rx_full(SunGEMState *s, uint32_t kick, uint32_t done)
|
|||||||
return kick == ((done + 1) & s->rx_mask);
|
return kick == ((done + 1) & s->rx_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sungem_can_receive(NetClientState *nc)
|
static bool sungem_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
SunGEMState *s = qemu_get_nic_opaque(nc);
|
SunGEMState *s = qemu_get_nic_opaque(nc);
|
||||||
uint32_t kick, done, rxdma_cfg, rxmac_cfg;
|
uint32_t kick, done, rxdma_cfg, rxmac_cfg;
|
||||||
@ -445,11 +445,11 @@ static int sungem_can_receive(NetClientState *nc)
|
|||||||
/* If MAC disabled, can't receive */
|
/* If MAC disabled, can't receive */
|
||||||
if ((rxmac_cfg & MAC_RXCFG_ENAB) == 0) {
|
if ((rxmac_cfg & MAC_RXCFG_ENAB) == 0) {
|
||||||
trace_sungem_rx_mac_disabled();
|
trace_sungem_rx_mac_disabled();
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
if ((rxdma_cfg & RXDMA_CFG_ENABLE) == 0) {
|
if ((rxdma_cfg & RXDMA_CFG_ENABLE) == 0) {
|
||||||
trace_sungem_rx_txdma_disabled();
|
trace_sungem_rx_txdma_disabled();
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check RX availability */
|
/* Check RX availability */
|
||||||
|
@ -657,11 +657,11 @@ static void sunhme_transmit(SunHMEState *s)
|
|||||||
sunhme_update_irq(s);
|
sunhme_update_irq(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sunhme_can_receive(NetClientState *nc)
|
static bool sunhme_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
SunHMEState *s = qemu_get_nic_opaque(nc);
|
SunHMEState *s = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
return s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE;
|
return !!(s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sunhme_link_status_changed(NetClientState *nc)
|
static void sunhme_link_status_changed(NetClientState *nc)
|
||||||
|
@ -170,6 +170,10 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
|
|||||||
} else {
|
} else {
|
||||||
len = s->rx_frame_len;
|
len = s->rx_frame_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame +
|
pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame +
|
||||||
(s->rx_frame_size - s->rx_frame_len), len);
|
(s->rx_frame_size - s->rx_frame_len), len);
|
||||||
s->rx_frame_len -= len;
|
s->rx_frame_len -= len;
|
||||||
@ -181,6 +185,10 @@ static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc)
|
|||||||
} else {
|
} else {
|
||||||
len = s->rx_frame_len;
|
len = s->rx_frame_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->rx_frame_len + len > sizeof(s->rx_frame)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame +
|
pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame +
|
||||||
(s->rx_frame_size - s->rx_frame_len), len);
|
(s->rx_frame_size - s->rx_frame_len), len);
|
||||||
s->rx_frame_len -= len;
|
s->rx_frame_len -= len;
|
||||||
@ -227,7 +235,8 @@ static ssize_t tulip_receive(TULIPState *s, const uint8_t *buf, size_t size)
|
|||||||
|
|
||||||
trace_tulip_receive(buf, size);
|
trace_tulip_receive(buf, size);
|
||||||
|
|
||||||
if (size < 14 || size > 2048 || s->rx_frame_len || tulip_rx_stopped(s)) {
|
if (size < 14 || size > sizeof(s->rx_frame) - 4
|
||||||
|
|| s->rx_frame_len || tulip_rx_stopped(s)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +284,6 @@ static ssize_t tulip_receive_nc(NetClientState *nc,
|
|||||||
return tulip_receive(qemu_get_nic_opaque(nc), buf, size);
|
return tulip_receive(qemu_get_nic_opaque(nc), buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static NetClientInfo net_tulip_info = {
|
static NetClientInfo net_tulip_info = {
|
||||||
.type = NET_CLIENT_DRIVER_NIC,
|
.type = NET_CLIENT_DRIVER_NIC,
|
||||||
.size = sizeof(NICState),
|
.size = sizeof(NICState),
|
||||||
@ -558,7 +566,7 @@ static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc)
|
|||||||
if ((s->csr[6] >> CSR6_OM_SHIFT) & CSR6_OM_MASK) {
|
if ((s->csr[6] >> CSR6_OM_SHIFT) & CSR6_OM_MASK) {
|
||||||
/* Internal or external Loopback */
|
/* Internal or external Loopback */
|
||||||
tulip_receive(s, s->tx_frame, s->tx_frame_len);
|
tulip_receive(s, s->tx_frame, s->tx_frame_len);
|
||||||
} else {
|
} else if (s->tx_frame_len <= sizeof(s->tx_frame)) {
|
||||||
qemu_send_packet(qemu_get_queue(s->nic),
|
qemu_send_packet(qemu_get_queue(s->nic),
|
||||||
s->tx_frame, s->tx_frame_len);
|
s->tx_frame, s->tx_frame_len);
|
||||||
}
|
}
|
||||||
@ -570,23 +578,31 @@ static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
|
static int tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc)
|
||||||
{
|
{
|
||||||
int len1 = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK;
|
int len1 = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK;
|
||||||
int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK;
|
int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK;
|
||||||
|
|
||||||
|
if (s->tx_frame_len + len1 > sizeof(s->tx_frame)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (len1) {
|
if (len1) {
|
||||||
pci_dma_read(&s->dev, desc->buf_addr1,
|
pci_dma_read(&s->dev, desc->buf_addr1,
|
||||||
s->tx_frame + s->tx_frame_len, len1);
|
s->tx_frame + s->tx_frame_len, len1);
|
||||||
s->tx_frame_len += len1;
|
s->tx_frame_len += len1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->tx_frame_len + len2 > sizeof(s->tx_frame)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (len2) {
|
if (len2) {
|
||||||
pci_dma_read(&s->dev, desc->buf_addr2,
|
pci_dma_read(&s->dev, desc->buf_addr2,
|
||||||
s->tx_frame + s->tx_frame_len, len2);
|
s->tx_frame + s->tx_frame_len, len2);
|
||||||
s->tx_frame_len += len2;
|
s->tx_frame_len += len2;
|
||||||
}
|
}
|
||||||
desc->status = (len1 + len2) ? 0 : 0x7fffffff;
|
desc->status = (len1 + len2) ? 0 : 0x7fffffff;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n)
|
static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n)
|
||||||
@ -651,13 +667,15 @@ static uint32_t tulip_ts(TULIPState *s)
|
|||||||
|
|
||||||
static void tulip_xmit_list_update(TULIPState *s)
|
static void tulip_xmit_list_update(TULIPState *s)
|
||||||
{
|
{
|
||||||
|
#define TULIP_DESC_MAX 128
|
||||||
|
uint8_t i = 0;
|
||||||
struct tulip_descriptor desc;
|
struct tulip_descriptor desc;
|
||||||
|
|
||||||
if (tulip_ts(s) != CSR5_TS_SUSPENDED) {
|
if (tulip_ts(s) != CSR5_TS_SUSPENDED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (i = 0; i < TULIP_DESC_MAX; i++) {
|
||||||
tulip_desc_read(s, s->current_tx_desc, &desc);
|
tulip_desc_read(s, s->current_tx_desc, &desc);
|
||||||
tulip_dump_tx_descriptor(s, &desc);
|
tulip_dump_tx_descriptor(s, &desc);
|
||||||
|
|
||||||
@ -675,12 +693,12 @@ static void tulip_xmit_list_update(TULIPState *s)
|
|||||||
s->tx_frame_len = 0;
|
s->tx_frame_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tulip_copy_tx_buffers(s, &desc);
|
if (!tulip_copy_tx_buffers(s, &desc)) {
|
||||||
|
|
||||||
if (desc.control & TDES1_LS) {
|
if (desc.control & TDES1_LS) {
|
||||||
tulip_tx(s, &desc);
|
tulip_tx(s, &desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tulip_desc_write(s, s->current_tx_desc, &desc);
|
tulip_desc_write(s, s->current_tx_desc, &desc);
|
||||||
tulip_next_tx_descriptor(s, &desc);
|
tulip_next_tx_descriptor(s, &desc);
|
||||||
}
|
}
|
||||||
|
@ -1234,26 +1234,26 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index));
|
qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_net_can_receive(NetClientState *nc)
|
static bool virtio_net_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
VirtIONet *n = qemu_get_nic_opaque(nc);
|
VirtIONet *n = qemu_get_nic_opaque(nc);
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||||
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
|
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
|
||||||
|
|
||||||
if (!vdev->vm_running) {
|
if (!vdev->vm_running) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nc->queue_index >= n->curr_queues) {
|
if (nc->queue_index >= n->curr_queues) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!virtio_queue_ready(q->rx_vq) ||
|
if (!virtio_queue_ready(q->rx_vq) ||
|
||||||
!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize)
|
static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize)
|
||||||
|
@ -175,7 +175,7 @@ static const MemoryRegionOps eth_ops = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int eth_can_rx(NetClientState *nc)
|
static bool eth_can_rx(NetClientState *nc)
|
||||||
{
|
{
|
||||||
struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
|
struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
|
||||||
unsigned int rxbase = s->rxbuf * (0x800 / 4);
|
unsigned int rxbase = s->rxbuf * (0x800 / 4);
|
||||||
|
@ -83,7 +83,7 @@ typedef struct CanBusClientState CanBusClientState;
|
|||||||
typedef struct CanBusState CanBusState;
|
typedef struct CanBusState CanBusState;
|
||||||
|
|
||||||
typedef struct CanBusClientInfo {
|
typedef struct CanBusClientInfo {
|
||||||
int (*can_receive)(CanBusClientState *);
|
bool (*can_receive)(CanBusClientState *);
|
||||||
ssize_t (*receive)(CanBusClientState *,
|
ssize_t (*receive)(CanBusClientState *,
|
||||||
const struct qemu_can_frame *frames, size_t frames_cnt);
|
const struct qemu_can_frame *frames, size_t frames_cnt);
|
||||||
} CanBusClientInfo;
|
} CanBusClientInfo;
|
||||||
|
@ -42,7 +42,7 @@ typedef struct NICConf {
|
|||||||
/* Net clients */
|
/* Net clients */
|
||||||
|
|
||||||
typedef void (NetPoll)(NetClientState *, bool enable);
|
typedef void (NetPoll)(NetClientState *, bool enable);
|
||||||
typedef int (NetCanReceive)(NetClientState *);
|
typedef bool (NetCanReceive)(NetClientState *);
|
||||||
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
|
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
|
||||||
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
|
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
|
||||||
typedef void (NetCleanup) (NetClientState *);
|
typedef void (NetCleanup) (NetClientState *);
|
||||||
|
@ -110,9 +110,9 @@ static void can_host_socketcan_read(void *opaque)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int can_host_socketcan_can_receive(CanBusClientState *client)
|
static bool can_host_socketcan_can_receive(CanBusClientState *client)
|
||||||
{
|
{
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t can_host_socketcan_receive(CanBusClientState *client,
|
static ssize_t can_host_socketcan_receive(CanBusClientState *client,
|
||||||
|
@ -48,8 +48,8 @@ static NotifierList colo_compare_notifiers =
|
|||||||
#define COLO_COMPARE_FREE_PRIMARY 0x01
|
#define COLO_COMPARE_FREE_PRIMARY 0x01
|
||||||
#define COLO_COMPARE_FREE_SECONDARY 0x02
|
#define COLO_COMPARE_FREE_SECONDARY 0x02
|
||||||
|
|
||||||
/* TODO: Should be configurable */
|
|
||||||
#define REGULAR_PACKET_CHECK_MS 3000
|
#define REGULAR_PACKET_CHECK_MS 3000
|
||||||
|
#define DEFAULT_TIME_OUT_MS 3000
|
||||||
|
|
||||||
static QemuMutex event_mtx;
|
static QemuMutex event_mtx;
|
||||||
static QemuCond event_complete_cond;
|
static QemuCond event_complete_cond;
|
||||||
@ -92,6 +92,8 @@ typedef struct CompareState {
|
|||||||
SocketReadState sec_rs;
|
SocketReadState sec_rs;
|
||||||
SocketReadState notify_rs;
|
SocketReadState notify_rs;
|
||||||
bool vnet_hdr;
|
bool vnet_hdr;
|
||||||
|
uint32_t compare_timeout;
|
||||||
|
uint32_t expired_scan_cycle;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Record the connection that through the NIC
|
* Record the connection that through the NIC
|
||||||
@ -607,10 +609,9 @@ static int colo_old_packet_check_one_conn(Connection *conn,
|
|||||||
CompareState *s)
|
CompareState *s)
|
||||||
{
|
{
|
||||||
GList *result = NULL;
|
GList *result = NULL;
|
||||||
int64_t check_time = REGULAR_PACKET_CHECK_MS;
|
|
||||||
|
|
||||||
result = g_queue_find_custom(&conn->primary_list,
|
result = g_queue_find_custom(&conn->primary_list,
|
||||||
&check_time,
|
&s->compare_timeout,
|
||||||
(GCompareFunc)colo_old_packet_check_one);
|
(GCompareFunc)colo_old_packet_check_one);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
@ -822,7 +823,7 @@ static void check_old_packet_regular(void *opaque)
|
|||||||
/* if have old packet we will notify checkpoint */
|
/* if have old packet we will notify checkpoint */
|
||||||
colo_old_packet_check(s);
|
colo_old_packet_check(s);
|
||||||
timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
||||||
REGULAR_PACKET_CHECK_MS);
|
s->expired_scan_cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public API, Used for COLO frame to notify compare event */
|
/* Public API, Used for COLO frame to notify compare event */
|
||||||
@ -852,7 +853,7 @@ static void colo_compare_timer_init(CompareState *s)
|
|||||||
SCALE_MS, check_old_packet_regular,
|
SCALE_MS, check_old_packet_regular,
|
||||||
s);
|
s);
|
||||||
timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
timer_mod(s->packet_check_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
|
||||||
REGULAR_PACKET_CHECK_MS);
|
s->expired_scan_cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void colo_compare_timer_del(CompareState *s)
|
static void colo_compare_timer_del(CompareState *s)
|
||||||
@ -984,6 +985,72 @@ static void compare_set_notify_dev(Object *obj, const char *value, Error **errp)
|
|||||||
s->notify_dev = g_strdup(value);
|
s->notify_dev = g_strdup(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void compare_get_timeout(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
CompareState *s = COLO_COMPARE(obj);
|
||||||
|
uint32_t value = s->compare_timeout;
|
||||||
|
|
||||||
|
visit_type_uint32(v, name, &value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare_set_timeout(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
CompareState *s = COLO_COMPARE(obj);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
visit_type_uint32(v, name, &value, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
error_setg(&local_err, "Property '%s.%s' requires a positive value",
|
||||||
|
object_get_typename(obj), name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
s->compare_timeout = value;
|
||||||
|
|
||||||
|
out:
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare_get_expired_scan_cycle(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
CompareState *s = COLO_COMPARE(obj);
|
||||||
|
uint32_t value = s->expired_scan_cycle;
|
||||||
|
|
||||||
|
visit_type_uint32(v, name, &value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare_set_expired_scan_cycle(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
CompareState *s = COLO_COMPARE(obj);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
visit_type_uint32(v, name, &value, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
error_setg(&local_err, "Property '%s.%s' requires a positive value",
|
||||||
|
object_get_typename(obj), name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
s->expired_scan_cycle = value;
|
||||||
|
|
||||||
|
out:
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
}
|
||||||
|
|
||||||
static void compare_pri_rs_finalize(SocketReadState *pri_rs)
|
static void compare_pri_rs_finalize(SocketReadState *pri_rs)
|
||||||
{
|
{
|
||||||
CompareState *s = container_of(pri_rs, CompareState, pri_rs);
|
CompareState *s = container_of(pri_rs, CompareState, pri_rs);
|
||||||
@ -1090,6 +1157,16 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!s->compare_timeout) {
|
||||||
|
/* Set default value to 3000 MS */
|
||||||
|
s->compare_timeout = DEFAULT_TIME_OUT_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->expired_scan_cycle) {
|
||||||
|
/* Set default value to 3000 MS */
|
||||||
|
s->expired_scan_cycle = REGULAR_PACKET_CHECK_MS;
|
||||||
|
}
|
||||||
|
|
||||||
if (find_and_check_chardev(&chr, s->pri_indev, errp) ||
|
if (find_and_check_chardev(&chr, s->pri_indev, errp) ||
|
||||||
!qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) {
|
!qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) {
|
||||||
return;
|
return;
|
||||||
@ -1185,6 +1262,14 @@ static void colo_compare_init(Object *obj)
|
|||||||
compare_get_notify_dev, compare_set_notify_dev,
|
compare_get_notify_dev, compare_set_notify_dev,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
object_property_add(obj, "compare_timeout", "uint32",
|
||||||
|
compare_get_timeout,
|
||||||
|
compare_set_timeout, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
object_property_add(obj, "expired_scan_cycle", "uint32",
|
||||||
|
compare_get_expired_scan_cycle,
|
||||||
|
compare_set_expired_scan_cycle, NULL, NULL, NULL);
|
||||||
|
|
||||||
s->vnet_hdr = false;
|
s->vnet_hdr = false;
|
||||||
object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
|
object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
|
||||||
compare_set_vnet_hdr, NULL);
|
compare_set_vnet_hdr, NULL);
|
||||||
|
@ -74,7 +74,7 @@ static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
|
|||||||
* the filter can still accept packets until its internal queue is full.
|
* the filter can still accept packets until its internal queue is full.
|
||||||
* For example:
|
* For example:
|
||||||
* For some reason, receiver could not receive more packets
|
* For some reason, receiver could not receive more packets
|
||||||
* (.can_receive() returns zero). Without a filter, at most one packet
|
* (.can_receive() returns false). Without a filter, at most one packet
|
||||||
* will be queued in incoming queue and sender's poll will be disabled
|
* will be queued in incoming queue and sender's poll will be disabled
|
||||||
* unit its sent_cb() was called. With a filter, it will keep receiving
|
* unit its sent_cb() was called. With a filter, it will keep receiving
|
||||||
* the packets without caring about the receiver. This is suboptimal.
|
* the packets without caring about the receiver. This is suboptimal.
|
||||||
|
@ -90,7 +90,7 @@ static NetHub *net_hub_new(int id)
|
|||||||
return hub;
|
return hub;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int net_hub_port_can_receive(NetClientState *nc)
|
static bool net_hub_port_can_receive(NetClientState *nc)
|
||||||
{
|
{
|
||||||
NetHubPort *port;
|
NetHubPort *port;
|
||||||
NetHubPort *src_port = DO_UPCAST(NetHubPort, nc, nc);
|
NetHubPort *src_port = DO_UPCAST(NetHubPort, nc, nc);
|
||||||
@ -102,11 +102,11 @@ static int net_hub_port_can_receive(NetClientState *nc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (qemu_can_send_packet(&port->nc)) {
|
if (qemu_can_send_packet(&port->nc)) {
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t net_hub_port_receive(NetClientState *nc,
|
static ssize_t net_hub_port_receive(NetClientState *nc,
|
||||||
|
@ -4615,7 +4615,7 @@ SRST
|
|||||||
stored. The file format is libpcap, so it can be analyzed with
|
stored. The file format is libpcap, so it can be analyzed with
|
||||||
tools such as tcpdump or Wireshark.
|
tools such as tcpdump or Wireshark.
|
||||||
|
|
||||||
``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id]``
|
``-object colo-compare,id=id,primary_in=chardevid,secondary_in=chardevid,outdev=chardevid,iothread=id[,vnet_hdr_support][,notify_dev=id][,compare_timeout=@var{ms}][,expired_scan_cycle=@var{ms}``
|
||||||
Colo-compare gets packet from primary\_inchardevid and
|
Colo-compare gets packet from primary\_inchardevid and
|
||||||
secondary\_inchardevid, than compare primary packet with
|
secondary\_inchardevid, than compare primary packet with
|
||||||
secondary packet. If the packets are same, we will output
|
secondary packet. If the packets are same, we will output
|
||||||
@ -4624,8 +4624,12 @@ SRST
|
|||||||
outdevchardevid. In order to improve efficiency, we need to put
|
outdevchardevid. In order to improve efficiency, we need to put
|
||||||
the task of comparison in another thread. If it has the
|
the task of comparison in another thread. If it has the
|
||||||
vnet\_hdr\_support flag, colo compare will send/recv packet with
|
vnet\_hdr\_support flag, colo compare will send/recv packet with
|
||||||
vnet\_hdr\_len. If you want to use Xen COLO, will need the
|
vnet\_hdr\_len. Then compare\_timeout=@var{ms} determines the
|
||||||
notify\_dev to notify Xen colo-frame to do checkpoint.
|
maximum delay colo-compare wait for the packet.
|
||||||
|
The expired\_scan\_cycle=@var{ms} to set the period of scanning
|
||||||
|
expired primary node network packets.
|
||||||
|
If you want to use Xen COLO, will need the notify\_dev to
|
||||||
|
notify Xen colo-frame to do checkpoint.
|
||||||
|
|
||||||
we must use it with the help of filter-mirror and
|
we must use it with the help of filter-mirror and
|
||||||
filter-redirector.
|
filter-redirector.
|
||||||
|
@ -217,6 +217,7 @@ qos-test-obj-y += tests/qtest/es1370-test.o
|
|||||||
qos-test-obj-y += tests/qtest/ipoctal232-test.o
|
qos-test-obj-y += tests/qtest/ipoctal232-test.o
|
||||||
qos-test-obj-y += tests/qtest/megasas-test.o
|
qos-test-obj-y += tests/qtest/megasas-test.o
|
||||||
qos-test-obj-y += tests/qtest/ne2000-test.o
|
qos-test-obj-y += tests/qtest/ne2000-test.o
|
||||||
|
qos-test-obj-y += tests/qtest/tulip-test.o
|
||||||
qos-test-obj-y += tests/qtest/nvme-test.o
|
qos-test-obj-y += tests/qtest/nvme-test.o
|
||||||
qos-test-obj-y += tests/qtest/pca9552-test.o
|
qos-test-obj-y += tests/qtest/pca9552-test.o
|
||||||
qos-test-obj-y += tests/qtest/pci-test.o
|
qos-test-obj-y += tests/qtest/pci-test.o
|
||||||
|
91
tests/qtest/tulip-test.c
Normal file
91
tests/qtest/tulip-test.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* QTest testcase for DEC/Intel Tulip 21143
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Li Qiang <liq3ea@gmail.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "libqtest.h"
|
||||||
|
#include "qemu/module.h"
|
||||||
|
#include "libqos/qgraph.h"
|
||||||
|
#include "libqos/pci.h"
|
||||||
|
#include "qemu/bitops.h"
|
||||||
|
#include "hw/net/tulip.h"
|
||||||
|
|
||||||
|
typedef struct QTulip_pci QTulip_pci;
|
||||||
|
|
||||||
|
struct QTulip_pci {
|
||||||
|
QOSGraphObject obj;
|
||||||
|
QPCIDevice dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *tulip_pci_get_driver(void *obj, const char *interface)
|
||||||
|
{
|
||||||
|
QTulip_pci *tulip_pci = obj;
|
||||||
|
|
||||||
|
if (!g_strcmp0(interface, "pci-device")) {
|
||||||
|
return &tulip_pci->dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s not present in tulip_pci\n", interface);
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *tulip_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
|
||||||
|
{
|
||||||
|
QTulip_pci *tulip_pci = g_new0(QTulip_pci, 1);
|
||||||
|
QPCIBus *bus = pci_bus;
|
||||||
|
|
||||||
|
qpci_device_init(&tulip_pci->dev, bus, addr);
|
||||||
|
tulip_pci->obj.get_driver = tulip_pci_get_driver;
|
||||||
|
|
||||||
|
return &tulip_pci->obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tulip_large_tx(void *obj, void *data, QGuestAllocator *alloc)
|
||||||
|
{
|
||||||
|
QTulip_pci *tulip_pci = obj;
|
||||||
|
QPCIDevice *dev = &tulip_pci->dev;
|
||||||
|
QPCIBar bar;
|
||||||
|
struct tulip_descriptor context;
|
||||||
|
char guest_data[4096];
|
||||||
|
uint64_t context_pa;
|
||||||
|
uint64_t guest_pa;
|
||||||
|
|
||||||
|
qpci_device_enable(dev);
|
||||||
|
bar = qpci_iomap(dev, 0, NULL);
|
||||||
|
context_pa = guest_alloc(alloc, sizeof(context));
|
||||||
|
guest_pa = guest_alloc(alloc, 4096);
|
||||||
|
memset(guest_data, 'A', sizeof(guest_data));
|
||||||
|
context.status = TDES0_OWN;
|
||||||
|
context.control = TDES1_BUF2_SIZE_MASK << TDES1_BUF2_SIZE_SHIFT |
|
||||||
|
TDES1_BUF1_SIZE_MASK << TDES1_BUF1_SIZE_SHIFT;
|
||||||
|
context.buf_addr2 = guest_pa;
|
||||||
|
context.buf_addr1 = guest_pa;
|
||||||
|
|
||||||
|
qtest_memwrite(dev->bus->qts, context_pa, &context, sizeof(context));
|
||||||
|
qtest_memwrite(dev->bus->qts, guest_pa, guest_data, sizeof(guest_data));
|
||||||
|
qpci_io_writel(dev, bar, 0x20, context_pa);
|
||||||
|
qpci_io_writel(dev, bar, 0x30, CSR6_ST);
|
||||||
|
guest_free(alloc, context_pa);
|
||||||
|
guest_free(alloc, guest_pa);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tulip_register_nodes(void)
|
||||||
|
{
|
||||||
|
QOSGraphEdgeOptions opts = {
|
||||||
|
.extra_device_opts = "addr=04.0",
|
||||||
|
};
|
||||||
|
add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) });
|
||||||
|
|
||||||
|
qos_node_create_driver("tulip", tulip_pci_create);
|
||||||
|
qos_node_consumes("tulip", "pci-bus", &opts);
|
||||||
|
qos_node_produces("tulip", "pci-device");
|
||||||
|
|
||||||
|
qos_add_test("tulip_large_tx", "tulip", tulip_large_tx, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
libqos_init(tulip_register_nodes);
|
Loading…
x
Reference in New Issue
Block a user