Hi Cédric, On 05/29/2018 03:28 AM, Cédric Le Goater wrote: > The ftgmac100 NIC supports VLAN tag insertion and the MAC engine also > has a control to remove VLAN tags from received packets. > > The VLAN control bits and VLAN tag information are contained in the > second word of the transmit and receive descriptors. The Insert VLAN > bit and the VLAN Tag available bit are only valid in the first segment > of the packet. > > Signed-off-by: Cédric Le Goater <c...@kaod.org> > --- > hw/net/ftgmac100.c | 32 +++++++++++++++++++++++++++++++- > 1 file changed, 31 insertions(+), 1 deletion(-) > > diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c > index 7598d08c9cb9..50af1222464a 100644 > --- a/hw/net/ftgmac100.c > +++ b/hw/net/ftgmac100.c > @@ -443,6 +443,24 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t > tx_ring, > break; > } > > + /* Check for VLAN */ > + if (bd.des0 & FTGMAC100_TXDES0_FTS && > + bd.des1 & FTGMAC100_TXDES1_INS_VLANTAG && > + be16_to_cpu(PKT_GET_ETH_HDR(ptr)->h_proto) != ETH_P_VLAN) { > + if (frame_size + len + 4 > sizeof(s->frame)) { > + qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d > bytes\n", > + __func__, len); > + s->isr |= FTGMAC100_INT_XPKT_LOST; > + len = sizeof(s->frame) - frame_size - 4; > + } > + memmove(ptr + 16, ptr + 12, len - 12); > + ptr[12] = 0x81; > + ptr[13] = 0x00;
stw_be_p(ptr + 12, ETH_P_VLAN); > + ptr[14] = (uint8_t) bd.des1 >> 8; > + ptr[15] = (uint8_t) bd.des1; stw_be_p(ptr + 12, bd.des1); > + len += 4; > + } > + > ptr += len; > frame_size += len; > if (bd.des0 & FTGMAC100_TXDES0_LTS) { > @@ -858,7 +876,19 @@ static ssize_t ftgmac100_receive(NetClientState *nc, > const uint8_t *buf, > buf_len += size - 4; > } > buf_addr = bd.des3; > - dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); > + if (first && proto == ETH_P_VLAN && buf_len >= 18) { > + bd.des1 = (buf[14] << 8) | buf[15] | > FTGMAC100_RXDES1_VLANTAG_AVAIL; bd.des1 = lduw_be_p(buf + 14) | FTGMAC100_RXDES1_VLANTAG_AVAIL; > + if (s->maccr & FTGMAC100_MACCR_RM_VLAN) { > + dma_memory_write(&address_space_memory, buf_addr, buf, 12); > + dma_memory_write(&address_space_memory, buf_addr + 12, buf + > 16, > + buf_len - 16); > + } else { > + dma_memory_write(&address_space_memory, buf_addr, buf, > buf_len); > + } > + } else { > + bd.des1 = 0; > + dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); > + } > buf += buf_len; > if (size < 4) { > dma_memory_write(&address_space_memory, buf_addr + buf_len, > With ldst API uses: Reviewed-by: Philippe Mathieu-Daudé <f4...@amsat.org>