]> Git Repo - qemu.git/blobdiff - hw/xen_nic.c
tcx: avoid structure holes spotted by pahole
[qemu.git] / hw / xen_nic.c
index 173e87a8ff4b5653d2e2206b02d6a05448b2727a..b28b15670b0ec4cf903179f23cc31b073c8cbb69 100644 (file)
@@ -13,8 +13,7 @@
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <stdio.h>
@@ -41,6 +40,8 @@
 
 #include "hw.h"
 #include "net.h"
+#include "net/checksum.h"
+#include "net/util.h"
 #include "qemu-char.h"
 #include "xen_backend.h"
 
@@ -56,7 +57,8 @@ struct XenNetDev {
     struct netif_rx_sring *rxs;
     netif_tx_back_ring_t  tx_ring;
     netif_rx_back_ring_t  rx_ring;
-    VLANClientState       *vs;
+    NICConf               conf;
+    NICState              *nic;
 };
 
 /* ------------------------------------------------------------- */
@@ -72,20 +74,23 @@ static void net_tx_response(struct XenNetDev *netdev, netif_tx_request_t *txp, i
     resp->status = st;
 
 #if 0
-    if (txp->flags & NETTXF_extra_info)
-       RING_GET_RESPONSE(&netdev->tx_ring, ++i)->status = NETIF_RSP_NULL;
+    if (txp->flags & NETTXF_extra_info) {
+        RING_GET_RESPONSE(&netdev->tx_ring, ++i)->status = NETIF_RSP_NULL;
+    }
 #endif
 
     netdev->tx_ring.rsp_prod_pvt = ++i;
     RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netdev->tx_ring, notify);
-    if (notify)
-       xen_be_send_notify(&netdev->xendev);
+    if (notify) {
+        xen_be_send_notify(&netdev->xendev);
+    }
 
     if (i == netdev->tx_ring.req_cons) {
-       int more_to_do;
-       RING_FINAL_CHECK_FOR_REQUESTS(&netdev->tx_ring, more_to_do);
-       if (more_to_do)
-           netdev->tx_work++;
+        int more_to_do;
+        RING_FINAL_CHECK_FOR_REQUESTS(&netdev->tx_ring, more_to_do);
+        if (more_to_do) {
+            netdev->tx_work++;
+        }
     }
 }
 
@@ -99,10 +104,11 @@ static void net_tx_error(struct XenNetDev *netdev, netif_tx_request_t *txp, RING
     RING_IDX cons = netdev->tx_ring.req_cons;
 
     do {
-       make_tx_response(netif, txp, NETIF_RSP_ERROR);
-       if (cons >= end)
-           break;
-       txp = RING_GET_REQUEST(&netdev->tx_ring, cons++);
+        make_tx_response(netif, txp, NETIF_RSP_ERROR);
+        if (cons >= end) {
+            break;
+        }
+        txp = RING_GET_REQUEST(&netdev->tx_ring, cons++);
     } while (1);
     netdev->tx_ring.req_cons = cons;
     netif_schedule_work(netif);
@@ -120,85 +126,88 @@ static void net_tx_packets(struct XenNetDev *netdev)
     void *tmpbuf = NULL;
 
     for (;;) {
-       rc = netdev->tx_ring.req_cons;
-       rp = netdev->tx_ring.sring->req_prod;
-       xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
+        rc = netdev->tx_ring.req_cons;
+        rp = netdev->tx_ring.sring->req_prod;
+        xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
 
-       while ((rc != rp)) {
-           if (RING_REQUEST_CONS_OVERFLOW(&netdev->tx_ring, rc))
-               break;
-           memcpy(&txreq, RING_GET_REQUEST(&netdev->tx_ring, rc), sizeof(txreq));
-           netdev->tx_ring.req_cons = ++rc;
+        while ((rc != rp)) {
+            if (RING_REQUEST_CONS_OVERFLOW(&netdev->tx_ring, rc)) {
+                break;
+            }
+            memcpy(&txreq, RING_GET_REQUEST(&netdev->tx_ring, rc), sizeof(txreq));
+            netdev->tx_ring.req_cons = ++rc;
 
 #if 1
-           /* should not happen in theory, we don't announce the *
-            * feature-{sg,gso,whatelse} flags in xenstore (yet?) */
-           if (txreq.flags & NETTXF_extra_info) {
-               xen_be_printf(&netdev->xendev, 0, "FIXME: extra info flag\n");
-               net_tx_error(netdev, &txreq, rc);
-               continue;
-           }
-           if (txreq.flags & NETTXF_more_data) {
-               xen_be_printf(&netdev->xendev, 0, "FIXME: more data flag\n");
-               net_tx_error(netdev, &txreq, rc);
-               continue;
-           }
+            /* should not happen in theory, we don't announce the *
+             * feature-{sg,gso,whatelse} flags in xenstore (yet?) */
+            if (txreq.flags & NETTXF_extra_info) {
+                xen_be_printf(&netdev->xendev, 0, "FIXME: extra info flag\n");
+                net_tx_error(netdev, &txreq, rc);
+                continue;
+            }
+            if (txreq.flags & NETTXF_more_data) {
+                xen_be_printf(&netdev->xendev, 0, "FIXME: more data flag\n");
+                net_tx_error(netdev, &txreq, rc);
+                continue;
+            }
 #endif
 
-           if (txreq.size < 14) {
-               xen_be_printf(&netdev->xendev, 0, "bad packet size: %d\n", txreq.size);
-               net_tx_error(netdev, &txreq, rc);
-               continue;
-           }
-
-           if ((txreq.offset + txreq.size) > XC_PAGE_SIZE) {
-               xen_be_printf(&netdev->xendev, 0, "error: page crossing\n");
-               net_tx_error(netdev, &txreq, rc);
-               continue;
-           }
-
-           xen_be_printf(&netdev->xendev, 3, "tx packet ref %d, off %d, len %d, flags 0x%x%s%s%s%s\n",
-                         txreq.gref, txreq.offset, txreq.size, txreq.flags,
-                         (txreq.flags & NETTXF_csum_blank)     ? " csum_blank"     : "",
-                         (txreq.flags & NETTXF_data_validated) ? " data_validated" : "",
-                         (txreq.flags & NETTXF_more_data)      ? " more_data"      : "",
-                         (txreq.flags & NETTXF_extra_info)     ? " extra_info"     : "");
-
-           page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                          netdev->xendev.dom,
-                                          txreq.gref, PROT_READ);
-           if (page == NULL) {
-               xen_be_printf(&netdev->xendev, 0, "error: tx gref dereference failed (%d)\n",
+            if (txreq.size < 14) {
+                xen_be_printf(&netdev->xendev, 0, "bad packet size: %d\n", txreq.size);
+                net_tx_error(netdev, &txreq, rc);
+                continue;
+            }
+
+            if ((txreq.offset + txreq.size) > XC_PAGE_SIZE) {
+                xen_be_printf(&netdev->xendev, 0, "error: page crossing\n");
+                net_tx_error(netdev, &txreq, rc);
+                continue;
+            }
+
+            xen_be_printf(&netdev->xendev, 3, "tx packet ref %d, off %d, len %d, flags 0x%x%s%s%s%s\n",
+                          txreq.gref, txreq.offset, txreq.size, txreq.flags,
+                          (txreq.flags & NETTXF_csum_blank)     ? " csum_blank"     : "",
+                          (txreq.flags & NETTXF_data_validated) ? " data_validated" : "",
+                          (txreq.flags & NETTXF_more_data)      ? " more_data"      : "",
+                          (txreq.flags & NETTXF_extra_info)     ? " extra_info"     : "");
+
+            page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
+                                           netdev->xendev.dom,
+                                           txreq.gref, PROT_READ);
+            if (page == NULL) {
+                xen_be_printf(&netdev->xendev, 0, "error: tx gref dereference failed (%d)\n",
                               txreq.gref);
-               net_tx_error(netdev, &txreq, rc);
-               continue;
-           }
-           if (txreq.flags & NETTXF_csum_blank) {
+                net_tx_error(netdev, &txreq, rc);
+                continue;
+            }
+            if (txreq.flags & NETTXF_csum_blank) {
                 /* have read-only mapping -> can't fill checksum in-place */
-                if (!tmpbuf)
-                    tmpbuf = qemu_malloc(XC_PAGE_SIZE);
+                if (!tmpbuf) {
+                    tmpbuf = g_malloc(XC_PAGE_SIZE);
+                }
                 memcpy(tmpbuf, page + txreq.offset, txreq.size);
-               net_checksum_calculate(tmpbuf, txreq.size);
-                qemu_send_packet(netdev->vs, tmpbuf, txreq.size);
+                net_checksum_calculate(tmpbuf, txreq.size);
+                qemu_send_packet(&netdev->nic->nc, tmpbuf, txreq.size);
             } else {
-                qemu_send_packet(netdev->vs, page + txreq.offset, txreq.size);
+                qemu_send_packet(&netdev->nic->nc, page + txreq.offset, txreq.size);
             }
-           xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
-           net_tx_response(netdev, &txreq, NETIF_RSP_OKAY);
-       }
-       if (!netdev->tx_work)
-           break;
-       netdev->tx_work = 0;
+            xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
+            net_tx_response(netdev, &txreq, NETIF_RSP_OKAY);
+        }
+        if (!netdev->tx_work) {
+            break;
+        }
+        netdev->tx_work = 0;
     }
-    qemu_free(tmpbuf);
+    g_free(tmpbuf);
 }
 
 /* ------------------------------------------------------------- */
 
 static void net_rx_response(struct XenNetDev *netdev,
-                           netif_rx_request_t *req, int8_t st,
-                           uint16_t offset, uint16_t size,
-                           uint16_t flags)
+                            netif_rx_request_t *req, int8_t st,
+                            uint16_t offset, uint16_t size,
+                            uint16_t flags)
 {
     RING_IDX i = netdev->rx_ring.rsp_prod_pvt;
     netif_rx_response_t *resp;
@@ -209,101 +218,121 @@ static void net_rx_response(struct XenNetDev *netdev,
     resp->flags      = flags;
     resp->id         = req->id;
     resp->status     = (int16_t)size;
-    if (st < 0)
-       resp->status = (int16_t)st;
+    if (st < 0) {
+        resp->status = (int16_t)st;
+    }
 
     xen_be_printf(&netdev->xendev, 3, "rx response: idx %d, status %d, flags 0x%x\n",
-                 i, resp->status, resp->flags);
+                  i, resp->status, resp->flags);
 
     netdev->rx_ring.rsp_prod_pvt = ++i;
     RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netdev->rx_ring, notify);
-    if (notify)
-       xen_be_send_notify(&netdev->xendev);
+    if (notify) {
+        xen_be_send_notify(&netdev->xendev);
+    }
 }
 
 #define NET_IP_ALIGN 2
 
-static int net_rx_ok(VLANClientState *vc)
+static int net_rx_ok(VLANClientState *nc)
 {
-    struct XenNetDev *netdev = vc->opaque;
+    struct XenNetDev *netdev = DO_UPCAST(NICState, nc, nc)->opaque;
     RING_IDX rc, rp;
 
-    if (netdev->xendev.be_state != XenbusStateConnected)
-       return 0;
+    if (netdev->xendev.be_state != XenbusStateConnected) {
+        return 0;
+    }
 
     rc = netdev->rx_ring.req_cons;
     rp = netdev->rx_ring.sring->req_prod;
     xen_rmb();
 
     if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
-       xen_be_printf(&netdev->xendev, 2, "%s: no rx buffers (%d/%d)\n",
-                     __FUNCTION__, rc, rp);
-       return 0;
+        xen_be_printf(&netdev->xendev, 2, "%s: no rx buffers (%d/%d)\n",
+                      __FUNCTION__, rc, rp);
+        return 0;
     }
     return 1;
 }
 
-static void net_rx_packet(VLANClientState *vc, const uint8_t *buf, size_t size)
+static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t size)
 {
-    struct XenNetDev *netdev = vc->opaque;
+    struct XenNetDev *netdev = DO_UPCAST(NICState, nc, nc)->opaque;
     netif_rx_request_t rxreq;
     RING_IDX rc, rp;
     void *page;
 
-    if (netdev->xendev.be_state != XenbusStateConnected)
-       return;
+    if (netdev->xendev.be_state != XenbusStateConnected) {
+        return -1;
+    }
 
     rc = netdev->rx_ring.req_cons;
     rp = netdev->rx_ring.sring->req_prod;
     xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
 
     if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
-       xen_be_printf(&netdev->xendev, 2, "no buffer, drop packet\n");
-       return;
+        xen_be_printf(&netdev->xendev, 2, "no buffer, drop packet\n");
+        return -1;
     }
     if (size > XC_PAGE_SIZE - NET_IP_ALIGN) {
-       xen_be_printf(&netdev->xendev, 0, "packet too big (%lu > %ld)",
-                     (unsigned long)size, XC_PAGE_SIZE - NET_IP_ALIGN);
-       return;
+        xen_be_printf(&netdev->xendev, 0, "packet too big (%lu > %ld)",
+                      (unsigned long)size, XC_PAGE_SIZE - NET_IP_ALIGN);
+        return -1;
     }
 
     memcpy(&rxreq, RING_GET_REQUEST(&netdev->rx_ring, rc), sizeof(rxreq));
     netdev->rx_ring.req_cons = ++rc;
 
     page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                  netdev->xendev.dom,
-                                  rxreq.gref, PROT_WRITE);
+                                   netdev->xendev.dom,
+                                   rxreq.gref, PROT_WRITE);
     if (page == NULL) {
-       xen_be_printf(&netdev->xendev, 0, "error: rx gref dereference failed (%d)\n",
+        xen_be_printf(&netdev->xendev, 0, "error: rx gref dereference failed (%d)\n",
                       rxreq.gref);
-       net_rx_response(netdev, &rxreq, NETIF_RSP_ERROR, 0, 0, 0);
-       return;
+        net_rx_response(netdev, &rxreq, NETIF_RSP_ERROR, 0, 0, 0);
+        return -1;
     }
     memcpy(page + NET_IP_ALIGN, buf, size);
     xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
     net_rx_response(netdev, &rxreq, NETIF_RSP_OKAY, NET_IP_ALIGN, size, 0);
+
+    return size;
 }
 
 /* ------------------------------------------------------------- */
 
+static NetClientInfo net_xen_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = net_rx_ok,
+    .receive = net_rx_packet,
+};
+
 static int net_init(struct XenDevice *xendev)
 {
     struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev);
-    VLANState *vlan;
 
     /* read xenstore entries */
-    if (netdev->mac == NULL)
-       netdev->mac = xenstore_read_be_str(&netdev->xendev, "mac");
+    if (netdev->mac == NULL) {
+        netdev->mac = xenstore_read_be_str(&netdev->xendev, "mac");
+    }
 
     /* do we have all we need? */
-    if (netdev->mac == NULL)
-       return -1;
-
-    vlan = qemu_find_vlan(netdev->xendev.dev);
-    netdev->vs = qemu_new_vlan_client(vlan, "xen", NULL,
-                                      net_rx_ok, net_rx_packet, NULL,
-                                      NULL, netdev);
-    snprintf(netdev->vs->info_str, sizeof(netdev->vs->info_str),
+    if (netdev->mac == NULL) {
+        return -1;
+    }
+
+    if (net_parse_macaddr(netdev->conf.macaddr.a, netdev->mac) < 0) {
+        return -1;
+    }
+
+    netdev->conf.vlan = qemu_find_vlan(netdev->xendev.dev, 1);
+    netdev->conf.peer = NULL;
+
+    netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf,
+                               "xen", NULL, netdev);
+
+    snprintf(netdev->nic->nc.info_str, sizeof(netdev->nic->nc.info_str),
              "nic: xenbus vif macaddr=%s", netdev->mac);
 
     /* fill info */
@@ -319,41 +348,48 @@ static int net_connect(struct XenDevice *xendev)
     int rx_copy;
 
     if (xenstore_read_fe_int(&netdev->xendev, "tx-ring-ref",
-                                  &netdev->tx_ring_ref) == -1)
-       return -1;
+                             &netdev->tx_ring_ref) == -1) {
+        return -1;
+    }
     if (xenstore_read_fe_int(&netdev->xendev, "rx-ring-ref",
-                                  &netdev->rx_ring_ref) == -1)
-       return 1;
+                             &netdev->rx_ring_ref) == -1) {
+        return 1;
+    }
     if (xenstore_read_fe_int(&netdev->xendev, "event-channel",
-                                  &netdev->xendev.remote_port) == -1)
-       return -1;
+                             &netdev->xendev.remote_port) == -1) {
+        return -1;
+    }
 
-    if (xenstore_read_fe_int(&netdev->xendev, "request-rx-copy", &rx_copy) == -1)
-       rx_copy = 0;
+    if (xenstore_read_fe_int(&netdev->xendev, "request-rx-copy", &rx_copy) == -1) {
+        rx_copy = 0;
+    }
     if (rx_copy == 0) {
-       xen_be_printf(&netdev->xendev, 0, "frontend doesn't support rx-copy.\n");
-       return -1;
+        xen_be_printf(&netdev->xendev, 0, "frontend doesn't support rx-copy.\n");
+        return -1;
     }
 
     netdev->txs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                         netdev->xendev.dom,
-                                         netdev->tx_ring_ref,
-                                         PROT_READ | PROT_WRITE);
+                                          netdev->xendev.dom,
+                                          netdev->tx_ring_ref,
+                                          PROT_READ | PROT_WRITE);
     netdev->rxs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                         netdev->xendev.dom,
-                                         netdev->rx_ring_ref,
-                                         PROT_READ | PROT_WRITE);
-    if (!netdev->txs || !netdev->rxs)
-       return -1;
+                                          netdev->xendev.dom,
+                                          netdev->rx_ring_ref,
+                                          PROT_READ | PROT_WRITE);
+    if (!netdev->txs || !netdev->rxs) {
+        return -1;
+    }
     BACK_RING_INIT(&netdev->tx_ring, netdev->txs, XC_PAGE_SIZE);
     BACK_RING_INIT(&netdev->rx_ring, netdev->rxs, XC_PAGE_SIZE);
 
     xen_be_bind_evtchn(&netdev->xendev);
 
     xen_be_printf(&netdev->xendev, 1, "ok: tx-ring-ref %d, rx-ring-ref %d, "
-                 "remote port %d, local port %d\n",
-                 netdev->tx_ring_ref, netdev->rx_ring_ref,
-                 netdev->xendev.remote_port, netdev->xendev.local_port);
+                  "remote port %d, local port %d\n",
+                  netdev->tx_ring_ref, netdev->rx_ring_ref,
+                  netdev->xendev.remote_port, netdev->xendev.local_port);
+
+    net_tx_packets(netdev);
     return 0;
 }
 
@@ -364,16 +400,16 @@ static void net_disconnect(struct XenDevice *xendev)
     xen_be_unbind_evtchn(&netdev->xendev);
 
     if (netdev->txs) {
-       xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
-       netdev->txs = NULL;
+        xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
+        netdev->txs = NULL;
     }
     if (netdev->rxs) {
-       xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
-       netdev->rxs = NULL;
+        xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
+        netdev->rxs = NULL;
     }
-    if (netdev->vs) {
-        qemu_del_vlan_client(netdev->vs);
-        netdev->vs = NULL;
+    if (netdev->nic) {
+        qemu_del_vlan_client(&netdev->nic->nc);
+        netdev->nic = NULL;
     }
 }
 
@@ -387,7 +423,7 @@ static int net_free(struct XenDevice *xendev)
 {
     struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev);
 
-    qemu_free(netdev->mac);
+    g_free(netdev->mac);
     return 0;
 }
 
This page took 0.045469 seconds and 4 git commands to generate.