qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: Benjamin Poirier <benjamin.poirier@gmail.com>
Cc: Blue Swirl <blauwirbel@gmail.com>,
	Jason Wang <jasowang@redhat.com>,
	qemu-devel@nongnu.org, "Michael S. Tsirkin" <mst@redhat.com>
Subject: [Qemu-devel] [PATCH v5 3/3] rtl8139: add vlan tag insertion
Date: Tue, 8 Mar 2011 14:44:05 +0800	[thread overview]
Message-ID: <19829.53301.857184.278363@gargle.gargle.HOWL> (raw)
In-Reply-To: <1299538414-22208-4-git-send-email-benjamin.poirier@gmail.com>

Benjamin Poirier writes:
 > Add support to the emulated hardware to insert vlan tags in packets
 > going from the guest to the network.
 > 
 > Signed-off-by: Benjamin Poirier <benjamin.poirier@gmail.com>
 > Cc: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
 > Cc: Jason Wang <jasowang@redhat.com>
 > Cc: Michael S. Tsirkin <mst@redhat.com>
 > Cc: Blue Swirl <blauwirbel@gmail.com>
 > ---
 >  hw/rtl8139.c |  107 ++++++++++++++++++++++++++++++++++++++++++---------------
 >  1 files changed, 79 insertions(+), 28 deletions(-)

Style issues were found through scripts/checkpatch.pl please have a look, and
better to meger all rx changes into previous patch. Other looks good.

 > 
 > diff --git a/hw/rtl8139.c b/hw/rtl8139.c
 > index 55a386e..265918a 100644
 > --- a/hw/rtl8139.c
 > +++ b/hw/rtl8139.c
 > @@ -819,11 +819,14 @@ static int rtl8139_can_receive(VLANClientState *nc)
 >      }
 >  }
 >  
 > -static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt)
 > +static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf,
 > +    size_t buf_size, int do_interrupt, const uint8_t *dot1q_buf)
 >  {
 >      RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque;
 > +    /* size_ is the total length of argument buffers */
 > +    int size_ = buf_size + (dot1q_buf ? VLAN_HLEN : 0);
 > +    /* size is the length of the buffer passed to the driver */
 >      int size = size_;
 > -    const uint8_t *dot1q_buf;
 >      const uint8_t *next_part;
 >      size_t next_part_size;
 >  
 > @@ -1005,10 +1008,13 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 >          /* next_part starts right after the vlan header (if any), at the
 >           * ethertype for the payload */
 >          next_part = &buf[ETHER_ADDR_LEN * 2];
 > -        if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *) next_part) ==
 > -            ETH_P_8021Q) {
 > -            dot1q_buf = next_part;
 > -            next_part += VLAN_HLEN;
 > +        if (s->CpCmd & CPlusRxVLAN && (dot1q_buf || be16_to_cpup((uint16_t *)
 > +                    next_part) == ETH_P_8021Q)) {
 > +            if (!dot1q_buf) {
 > +                /* the tag is in the buffer */
 > +                dot1q_buf = next_part;
 > +                next_part += VLAN_HLEN;
 > +            }
 >              size -= VLAN_HLEN;
 >  
 >              rxdw1 &= ~CP_RX_VLAN_TAG_MASK;
 > @@ -1020,9 +1026,8 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 >          } else {
 >              /* reset VLAN tag flag */
 >              rxdw1 &= ~CP_RX_TAVA;
 > -            dot1q_buf = NULL;
 >          }
 > -        next_part_size = buf + size_ - next_part;
 > +        next_part_size = buf + buf_size - next_part;
 >  
 >          /* if too small buffer, then expand it */
 >          if (size < MIN_BUF_SIZE) {
 > @@ -1147,10 +1152,18 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 >  
 >          /* if too small buffer, then expand it */
 >          if (size < MIN_BUF_SIZE) {
 > -            memcpy(buf1, buf, size);
 > +            if (dot1q_buf) {
 > +                memcpy(buf1, buf, 2 * ETHER_ADDR_LEN);
 > +                memcpy(buf1 + 2 * ETHER_ADDR_LEN, dot1q_buf, VLAN_HLEN);
 > +                memcpy(buf1 + 2 * ETHER_ADDR_LEN + VLAN_HLEN, buf + 2 *
 > +                    ETHER_ADDR_LEN, buf_size - 2 * ETHER_ADDR_LEN);
 > +            } else {
 > +                memcpy(buf1, buf, size);
 > +            }
 >              memset(buf1 + size, 0, MIN_BUF_SIZE - size);
 >              buf = buf1;
 >              size = MIN_BUF_SIZE;
 > +            dot1q_buf = NULL;
 >          }
 >  
 >          /* begin ring receiver mode */
 > @@ -1178,10 +1191,23 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 >  
 >          rtl8139_write_buffer(s, (uint8_t *)&val, 4);
 >  
 > -        rtl8139_write_buffer(s, buf, size);
 > +        /* receive/copy to target memory */
 > +        if (dot1q_buf) {
 > +            rtl8139_write_buffer(s, buf, 2 * ETHER_ADDR_LEN);
 > +            val = crc32(0, buf, 2 * ETHER_ADDR_LEN);
 > +            rtl8139_write_buffer(s, dot1q_buf, VLAN_HLEN);
 > +            val = crc32(val, dot1q_buf, VLAN_HLEN);
 > +            rtl8139_write_buffer(s, buf + 2 * ETHER_ADDR_LEN, buf_size - 2 *
 > +                ETHER_ADDR_LEN);
 > +            val = crc32(val, buf + 2 * ETHER_ADDR_LEN, buf_size - 2 *
 > +                ETHER_ADDR_LEN);
 > +        } else {
 > +            rtl8139_write_buffer(s, buf, size);
 > +            val = crc32(0, buf, size);
 > +        }
 >  
 >          /* write checksum */
 > -        val = cpu_to_le32(crc32(0, buf, size));
 > +        val = cpu_to_le32(val);
 >          rtl8139_write_buffer(s, (uint8_t *)&val, 4);
 >  
 >          /* correct buffer write pointer */
 > @@ -1205,7 +1231,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_
 >  
 >  static ssize_t rtl8139_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
 >  {
 > -    return rtl8139_do_receive(nc, buf, size, 1);
 > +    return rtl8139_do_receive(nc, buf, size, 1, NULL);
 >  }
 >  
 >  static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize)
 > @@ -1780,7 +1806,8 @@ static uint32_t rtl8139_RxConfig_read(RTL8139State *s)
 >      return ret;
 >  }
 >  
 > -static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int size, int do_interrupt)
 > +static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
 > +    int do_interrupt, const uint8_t *dot1q_buf)
 >  {
 >      if (!size)
 >      {
 > @@ -1791,11 +1818,22 @@ static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int size
 >      if (TxLoopBack == (s->TxConfig & TxLoopBack))
 >      {
 >          DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n"));
 > -        rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt);
 > +        rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt, dot1q_buf);
 >      }
 >      else
 >      {
 > -        qemu_send_packet(&s->nic->nc, buf, size);
 > +        if (dot1q_buf) {
 > +            struct iovec iov[] = {
 > +                { .iov_base = buf, .iov_len = ETHER_ADDR_LEN * 2 },
 > +                { .iov_base = (void *) dot1q_buf, .iov_len = VLAN_HLEN },
 > +                { .iov_base = buf + ETHER_ADDR_LEN * 2,
 > +                    .iov_len = size - ETHER_ADDR_LEN * 2 },
 > +            };
 > +
 > +            qemu_sendv_packet(&s->nic->nc, iov, ARRAY_SIZE(iov));
 > +        } else {
 > +            qemu_send_packet(&s->nic->nc, buf, size);
 > +        }
 >      }
 >  }
 >  
 > @@ -1829,7 +1867,7 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
 >      s->TxStatus[descriptor] |= TxHostOwns;
 >      s->TxStatus[descriptor] |= TxStatOK;
 >  
 > -    rtl8139_transfer_frame(s, txbuffer, txsize, 0);
 > +    rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL);
 >  
 >      DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor));
 >  
 > @@ -1956,7 +1994,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 >  
 >      cpu_physical_memory_read(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
 >      txdw0 = le32_to_cpu(val);
 > -    /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */
 >      cpu_physical_memory_read(cplus_tx_ring_desc+4,  (uint8_t *)&val, 4);
 >      txdw1 = le32_to_cpu(val);
 >      cpu_physical_memory_read(cplus_tx_ring_desc+8,  (uint8_t *)&val, 4);
 > @@ -1968,9 +2005,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 >             descriptor,
 >             txdw0, txdw1, txbufLO, txbufHI));
 >  
 > -    /* TODO: the following discard cast should clean clang analyzer output */
 > -    (void)txdw1;
 > -
 >  /* w0 ownership flag */
 >  #define CP_TX_OWN (1<<31)
 >  /* w0 end of ring flag */
 > @@ -1994,9 +2028,9 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 >  /* w0 bits 0...15 : buffer size */
 >  #define CP_TX_BUFFER_SIZE (1<<16)
 >  #define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1)
 > -/* w1 tag available flag */
 > -#define CP_RX_TAGC (1<<17)
 > -/* w1 bits 0...15 : VLAN tag */
 > +/* w1 add tag flag */
 > +#define CP_TX_TAGC (1<<17)
 > +/* w1 bits 0...15 : VLAN tag (big endian) */
 >  #define CP_TX_VLAN_TAG_MASK ((1<<16) - 1)
 >  /* w2 low  32bit of Rx buffer ptr */
 >  /* w3 high 32bit of Rx buffer ptr */
 > @@ -2096,13 +2130,13 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 >      /* update ring data */
 >      val = cpu_to_le32(txdw0);
 >      cpu_physical_memory_write(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
 > -    /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */
 > -//    val = cpu_to_le32(txdw1);
 > -//    cpu_physical_memory_write(cplus_tx_ring_desc+4,  &val, 4);
 >  
 >      /* Now decide if descriptor being processed is holding the last segment of packet */
 >      if (txdw0 & CP_TX_LS)
 >      {
 > +        uint8_t dot1q_buffer_space[VLAN_HLEN];
 > +        uint16_t *dot1q_buffer;
 > +
 >          DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor));
 >  
 >          /* can transfer fully assembled packet */
 > @@ -2111,6 +2145,21 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 >          int      saved_size    = s->cplus_txbuffer_offset;
 >          int      saved_buffer_len = s->cplus_txbuffer_len;
 >  
 > +        /* create vlan tag */
 > +        if (txdw1 & CP_TX_TAGC) {
 > +            /* the vlan tag is in BE byte order in the descriptor
 > +             * BE + le_to_cpu() + ~swap()~ = cpu */
 > +            DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : inserting vlan tag with "
 > +                    "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)));
 > +
 > +            dot1q_buffer = (uint16_t*) dot1q_buffer_space;
 > +            dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q);
 > +            /* BE + le_to_cpu() + ~cpu_to_le()~ = BE */
 > +            dot1q_buffer[1] = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK);
 > +        } else {
 > +            dot1q_buffer = NULL;
 > +        }
 > +
 >          /* reset the card space to protect from recursive call */
 >          s->cplus_txbuffer = NULL;
 >          s->cplus_txbuffer_offset = 0;
 > @@ -2264,7 +2313,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 >  
 >                          int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
 >                          DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
 > -                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0);
 > +                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
 > +                            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));
 > @@ -2337,7 +2387,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
 >  
 >          DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size));
 >  
 > -        rtl8139_transfer_frame(s, saved_buffer, saved_size, 1);
 > +        rtl8139_transfer_frame(s, saved_buffer, saved_size, 1,
 > +            (uint8_t *) dot1q_buffer);
 >  
 >          /* restore card space if there was no recursion and reset offset */
 >          if (!s->cplus_txbuffer)
 > -- 
 > 1.7.2.3
 > 
 > 

      reply	other threads:[~2011-03-08  6:50 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-07 22:53 [Qemu-devel] [PATCH v5] rtl8139: add vlan support Benjamin Poirier
2011-03-07 22:53 ` [Qemu-devel] [PATCH v5 1/3] rtl8139: cleanup FCS calculation Benjamin Poirier
2011-03-07 22:53 ` [Qemu-devel] [PATCH v5 2/3] rtl8139: add vlan tag extraction Benjamin Poirier
2011-03-08  3:44   ` Jason Wang
2011-03-07 22:53 ` [Qemu-devel] [PATCH v5 3/3] rtl8139: add vlan tag insertion Benjamin Poirier
2011-03-08  6:44   ` Jason Wang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=19829.53301.857184.278363@gargle.gargle.HOWL \
    --to=jasowang@redhat.com \
    --cc=benjamin.poirier@gmail.com \
    --cc=blauwirbel@gmail.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).