mirror of
https://github.com/apache/nuttx.git
synced 2026-10-03 04:07:55 +00:00
drivers/vhost: Add vhost-net, a device-role virtio network driver.
Implements the device end of virtio-net, so a peer running the stock virtio-net driver sees this side as a network card, and registers a netdev lowerhalf. Ring layout follows the peer's numbering: vq[0] is its RX queue, which we fill to transmit, and vq[1] its TX queue, which we harvest. No features are negotiated, so every frame carries the zeroed legacy virtio_net_hdr. Peer buffers are reached by raw 64-bit address through an arch-provided translation window -- the AM67 RAT, identity mapping elsewhere -- splitting copies that straddle it. Also gives DRIVERS_VHOST a prompt; it was promptless and so unselectable without a driver forcing it. Verified on t3-gem-o1 against an unmodified Linux virtio_net: eth0 registers, ifup brings it to RUNNING, and the peer pings it 5/5 at 0.27 ms and 60/60 with 0% loss. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
This commit is contained in:
parent
c77c981850
commit
fa935ecae1
8 changed files with 591 additions and 1 deletions
|
|
@ -88,6 +88,7 @@ config ARCH_CHIP_AM67
|
|||
select ARCH_CORTEXR5
|
||||
select ARCH_HAVE_LOWVECTORS
|
||||
select ARCH_HAVE_TICKLESS
|
||||
select ARCH_HAVE_VHOST_IOMAP
|
||||
select SCHED_HPWORK if RPTUN
|
||||
---help---
|
||||
TI AM67 family
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
#include "arm_internal.h"
|
||||
#include "am67_rat.h"
|
||||
#include <nuttx/vhost/vhost.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
@ -112,3 +113,19 @@ FAR void *am67_rat_map(uint64_t pa, FAR size_t *avail)
|
|||
|
||||
return (FAR void *)(AM67_RAT_WIN_BASE + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_vhost_iomap
|
||||
*
|
||||
* Description:
|
||||
* Arch hook used by the vhost drivers to reach peer buffers by 64-bit
|
||||
* physical address (see ARCH_HAVE_VHOST_IOMAP).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DRIVERS_VHOST
|
||||
FAR void *up_vhost_iomap(uint64_t pa, FAR size_t *avail)
|
||||
{
|
||||
return am67_rat_map(pa, avail);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ if(CONFIG_DRIVERS_VHOST_RNG)
|
|||
list(APPEND SRCS vhost-rng.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DRIVERS_VHOST_NET)
|
||||
list(APPEND SRCS vhost-net.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DRIVERS_VHOST_RPMSG)
|
||||
list(APPEND SRCS vhost-rpmsg.c)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -3,17 +3,47 @@
|
|||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config DRIVERS_VHOST
|
||||
config ARCH_HAVE_VHOST_IOMAP
|
||||
bool
|
||||
default n
|
||||
|
||||
config DRIVERS_VHOST
|
||||
bool "Virtual Host (device-role virtio) support"
|
||||
select OPENAMP
|
||||
select SCHED_WORKQUEUE
|
||||
default n
|
||||
---help---
|
||||
Framework for implementing the DEVICE side of virtio links
|
||||
(the peer's driver uses us as the device, e.g. a remoteproc
|
||||
master like Linux). rptun registers device-role vdevs from the
|
||||
resource table through this bus; without it such vdevs are
|
||||
rejected with -ENODEV.
|
||||
|
||||
config DRIVERS_VHOST_RNG
|
||||
bool "Virtual Host Rng Device Support"
|
||||
default n
|
||||
select DRIVERS_VHOST
|
||||
|
||||
config DRIVERS_VHOST_NET
|
||||
bool "Virtual Host Network Device Support"
|
||||
default n
|
||||
depends on NETDEVICES
|
||||
select DRIVERS_VHOST
|
||||
---help---
|
||||
Device-role virtio-net: expose this side as a network card to a
|
||||
peer processor running a standard virtio-net driver (e.g. Linux
|
||||
via remoteproc), providing a NuttX ethN interface.
|
||||
|
||||
config DRIVERS_VHOST_NET_MACADDR
|
||||
hex "vhost-net MAC address"
|
||||
default 0x025433000001
|
||||
depends on DRIVERS_VHOST_NET
|
||||
---help---
|
||||
No virtio-net features are negotiated on this link, so there is
|
||||
no MAC config space to read; this fixed, software-assigned,
|
||||
locally administered address is presented to the network stack
|
||||
instead.
|
||||
|
||||
config DRIVERS_VHOST_RPMSG
|
||||
bool "Virtual Host Rpmsg Device Support"
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ ifeq ($(CONFIG_DRIVERS_VHOST_RNG),y)
|
|||
CSRCS += vhost-rng.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DRIVERS_VHOST_NET),y)
|
||||
CSRCS += vhost-net.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DRIVERS_VHOST_RPMSG),y)
|
||||
CSRCS += vhost-rpmsg.c
|
||||
endif
|
||||
|
|
|
|||
495
drivers/vhost/vhost-net.c
Normal file
495
drivers/vhost/vhost-net.c
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/****************************************************************************
|
||||
* drivers/vhost/vhost-net.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Device-role virtio network driver ("vhost-net"): implements the DEVICE
|
||||
* end of a virtio-net link, so a peer processor running a stock virtio-net
|
||||
* DRIVER (e.g. Linux via remoteproc/rproc-virtio) sees this side as a
|
||||
* network card. Registers a NuttX netdev lowerhalf (ethN).
|
||||
*
|
||||
* Ring layout is fixed by the peer driver's point of view:
|
||||
* vq[0] = peer driver RX queue: the peer posts empty buffers; the
|
||||
* device side fills them to transmit toward the peer.
|
||||
* vq[1] = peer driver TX queue: the peer posts filled buffers; the
|
||||
* device side harvests them as its receive path.
|
||||
*
|
||||
* No virtio-net features are negotiated (the resource table advertises
|
||||
* none), so every packet is prefixed by the legacy 10-byte
|
||||
* struct virtio_net_hdr with all fields zero (gso_type NONE).
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/net/netdev_lowerhalf.h>
|
||||
#include <nuttx/vhost/vhost.h>
|
||||
|
||||
#include "vhost-net.h"
|
||||
|
||||
/* Peer buffers are referenced by 64-bit guest physical addresses that may
|
||||
* exceed the CPU's direct reach; arches that provide a translation window
|
||||
* implement up_vhost_iomap() (ARCH_HAVE_VHOST_IOMAP), others use the
|
||||
* identity mapping.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_VHOST_IOMAP
|
||||
# define vhost_net_map(pa, avl) up_vhost_iomap((pa), (avl))
|
||||
#else
|
||||
static inline FAR void *vhost_net_map(uint64_t pa, FAR size_t *avail)
|
||||
{
|
||||
if (avail != NULL)
|
||||
{
|
||||
*avail = SIZE_MAX;
|
||||
}
|
||||
|
||||
return (FAR void *)(uintptr_t)pa;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Queue indices (peer driver's numbering, see file header) */
|
||||
|
||||
#define VHOST_NET_PEER_RXQ 0 /* device-side transmit lane */
|
||||
#define VHOST_NET_PEER_TXQ 1 /* device-side receive lane */
|
||||
#define VHOST_NET_NUM 2
|
||||
|
||||
/* Legacy struct virtio_net_hdr (no VIRTIO_NET_F_MRG_RXBUF): flags(1) +
|
||||
* gso_type(1) + hdr_len(2) + gso_size(2) + csum_start(2) + csum_offset(2)
|
||||
*/
|
||||
|
||||
#define VHOST_NET_HDRSIZE 10
|
||||
|
||||
/* netpkt quota per direction and the longest peer descriptor chain we
|
||||
* accept on receive (Linux commonly splits header and payload).
|
||||
*/
|
||||
|
||||
#define VHOST_NET_NPKTS 8
|
||||
#define VHOST_NET_MAXCHAIN 8
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct vhost_net_priv_s
|
||||
{
|
||||
struct netdev_lowerhalf_s lower; /* Must be first for casts */
|
||||
FAR struct vhost_device *hdev;
|
||||
FAR struct virtqueue *txq; /* peer RX ring (filled here) */
|
||||
FAR struct virtqueue *rxq; /* peer TX ring (drained here) */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int vhost_net_ifup(FAR struct netdev_lowerhalf_s *dev);
|
||||
static int vhost_net_ifdown(FAR struct netdev_lowerhalf_s *dev);
|
||||
static int vhost_net_transmit(FAR struct netdev_lowerhalf_s *dev,
|
||||
FAR netpkt_t *pkt);
|
||||
static FAR netpkt_t *vhost_net_receive(FAR struct netdev_lowerhalf_s *dev);
|
||||
static int vhost_net_probe(FAR struct vhost_device *hdev);
|
||||
static void vhost_net_remove(FAR struct vhost_device *hdev);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct netdev_ops_s g_vhost_net_ops =
|
||||
{
|
||||
vhost_net_ifup,
|
||||
vhost_net_ifdown,
|
||||
vhost_net_transmit,
|
||||
vhost_net_receive,
|
||||
#ifdef CONFIG_NET_MCASTGROUP
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_NETDEV_IOCTL
|
||||
NULL,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct vhost_driver g_vhost_net_driver =
|
||||
{
|
||||
LIST_INITIAL_VALUE(g_vhost_net_driver.node), /* node */
|
||||
VIRTIO_ID_NETWORK, /* device id */
|
||||
vhost_net_probe, /* probe */
|
||||
vhost_net_remove, /* remove */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_net_rxready / vhost_net_txdone
|
||||
*
|
||||
* Description:
|
||||
* Virtqueue kick callbacks (transport notification context, thread
|
||||
* level). Notify the upper half that ring work is pending; the rings
|
||||
* are processed in transmit()/receive().
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void vhost_net_rxready(FAR struct virtqueue *vq)
|
||||
{
|
||||
FAR struct vhost_net_priv_s *priv = vq->vq_dev->priv;
|
||||
|
||||
netdev_lower_rxready(&priv->lower);
|
||||
}
|
||||
|
||||
static void vhost_net_txdone(FAR struct virtqueue *vq)
|
||||
{
|
||||
FAR struct vhost_net_priv_s *priv = vq->vq_dev->priv;
|
||||
|
||||
netdev_lower_txdone(&priv->lower);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_net_ifup / vhost_net_ifdown
|
||||
****************************************************************************/
|
||||
|
||||
static int vhost_net_ifup(FAR struct netdev_lowerhalf_s *dev)
|
||||
{
|
||||
netdev_lower_carrier_on(dev);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int vhost_net_ifdown(FAR struct netdev_lowerhalf_s *dev)
|
||||
{
|
||||
netdev_lower_carrier_off(dev);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_net_transmit
|
||||
*
|
||||
* Description:
|
||||
* Fill one peer-posted RX buffer with the frame and complete it.
|
||||
* Completion is synchronous: the netpkt is consumed and freed before
|
||||
* returning.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int vhost_net_transmit(FAR struct netdev_lowerhalf_s *dev,
|
||||
FAR netpkt_t *pkt)
|
||||
{
|
||||
FAR struct vhost_net_priv_s *priv = (FAR struct vhost_net_priv_s *)dev;
|
||||
struct vhost_buf_s vb[1];
|
||||
unsigned int len;
|
||||
unsigned int pos;
|
||||
size_t cnt;
|
||||
int head;
|
||||
|
||||
head = vhost_get_vq_buffers_pa(priv->txq, vb, nitems(vb), &cnt);
|
||||
if (head < 0)
|
||||
{
|
||||
/* Peer has not posted buffers (yet). Re-enable its notifications;
|
||||
* enable_cb reports buffers that arrived in the race window (their
|
||||
* kick was suppressed), so grab them now if so.
|
||||
*/
|
||||
|
||||
if (!virtqueue_enable_cb(priv->txq))
|
||||
{
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
head = vhost_get_vq_buffers_pa(priv->txq, vb, nitems(vb), &cnt);
|
||||
if (head < 0)
|
||||
{
|
||||
return -ENOBUFS;
|
||||
}
|
||||
}
|
||||
|
||||
len = netpkt_getdatalen(dev, pkt);
|
||||
if (len + VHOST_NET_HDRSIZE > vb[0].len)
|
||||
{
|
||||
/* Frame cannot fit the peer's buffer: complete it empty (drop) */
|
||||
|
||||
vhosterr("frame %u exceeds peer buffer %" PRIu32 ", dropped\n",
|
||||
len, vb[0].len);
|
||||
len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Serialize the zero header + frame into the peer buffer through
|
||||
* the translation window, honoring window-boundary splits.
|
||||
*/
|
||||
|
||||
for (pos = 0; pos < len + VHOST_NET_HDRSIZE; )
|
||||
{
|
||||
size_t avail;
|
||||
FAR uint8_t *dst = vhost_net_map(vb[0].addr + pos, &avail);
|
||||
unsigned int chunk = MIN(len + VHOST_NET_HDRSIZE - pos, avail);
|
||||
unsigned int hdrlen = 0;
|
||||
int ret = OK;
|
||||
|
||||
if (pos < VHOST_NET_HDRSIZE)
|
||||
{
|
||||
hdrlen = MIN(VHOST_NET_HDRSIZE - pos, chunk);
|
||||
memset(dst, 0, hdrlen);
|
||||
}
|
||||
|
||||
if (chunk > hdrlen)
|
||||
{
|
||||
ret = netpkt_copyout(dev, dst + hdrlen, pkt, chunk - hdrlen,
|
||||
pos + hdrlen - VHOST_NET_HDRSIZE);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
vhosterr("netpkt_copyout failed, ret=%d, dropped\n", ret);
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pos += chunk;
|
||||
}
|
||||
}
|
||||
|
||||
virtqueue_add_consumed_buffer(priv->txq, head,
|
||||
len ? len + VHOST_NET_HDRSIZE : 0);
|
||||
virtqueue_kick(priv->txq);
|
||||
|
||||
netpkt_free(dev, pkt, NETPKT_TX);
|
||||
netdev_lower_txdone(dev);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_net_receive
|
||||
*
|
||||
* Description:
|
||||
* Harvest one frame (possibly a descriptor chain) from the peer TX
|
||||
* ring, copy it into a fresh netpkt (stripping the virtio-net header)
|
||||
* and return the buffers to the peer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR netpkt_t *vhost_net_receive(FAR struct netdev_lowerhalf_s *dev)
|
||||
{
|
||||
FAR struct vhost_net_priv_s *priv = (FAR struct vhost_net_priv_s *)dev;
|
||||
struct vhost_buf_s vb[VHOST_NET_MAXCHAIN];
|
||||
FAR netpkt_t *pkt = NULL;
|
||||
unsigned int total = 0;
|
||||
unsigned int skip = VHOST_NET_HDRSIZE;
|
||||
int offset = 0;
|
||||
size_t cnt;
|
||||
size_t i;
|
||||
int head;
|
||||
|
||||
head = vhost_get_vq_buffers_pa(priv->rxq, vb, nitems(vb), &cnt);
|
||||
if (head < 0)
|
||||
{
|
||||
/* See vhost_net_transmit() for the enable_cb recheck rationale */
|
||||
|
||||
if (!virtqueue_enable_cb(priv->rxq))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
head = vhost_get_vq_buffers_pa(priv->rxq, vb, nitems(vb), &cnt);
|
||||
if (head < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
total += vb[i].len;
|
||||
}
|
||||
|
||||
if (total > skip)
|
||||
{
|
||||
pkt = netpkt_alloc(dev, NETPKT_RX);
|
||||
}
|
||||
|
||||
if (pkt != NULL &&
|
||||
netpkt_setdatalen(dev, pkt, total - skip) < total - skip)
|
||||
{
|
||||
vhosterr("rx dropped: cannot size netpkt to %u\n", total - skip);
|
||||
netpkt_free(dev, pkt, NETPKT_RX);
|
||||
pkt = NULL;
|
||||
}
|
||||
|
||||
if (pkt != NULL)
|
||||
{
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
uint64_t pa = vb[i].addr;
|
||||
uint32_t blen = vb[i].len;
|
||||
|
||||
if (skip > 0)
|
||||
{
|
||||
uint32_t skiplen = MIN(skip, blen);
|
||||
|
||||
pa += skiplen;
|
||||
blen -= skiplen;
|
||||
skip -= skiplen;
|
||||
}
|
||||
|
||||
/* Copy through the translation window, honoring
|
||||
* window-boundary splits.
|
||||
*/
|
||||
|
||||
while (blen > 0)
|
||||
{
|
||||
size_t avail;
|
||||
FAR const uint8_t *src = vhost_net_map(pa, &avail);
|
||||
uint32_t chunk = MIN(blen, avail);
|
||||
|
||||
if (netpkt_copyin(dev, pkt, src, chunk, offset) < 0)
|
||||
{
|
||||
vhosterr("netpkt_copyin failed, rx dropped\n");
|
||||
netpkt_free(dev, pkt, NETPKT_RX);
|
||||
pkt = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset += chunk;
|
||||
pa += chunk;
|
||||
blen -= chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vhosterr("rx dropped: total=%u (no netpkt)\n", total);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
/* Hand the buffers back to the peer either way */
|
||||
|
||||
virtqueue_add_consumed_buffer(priv->rxq, head, total);
|
||||
virtqueue_kick(priv->rxq);
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_net_probe
|
||||
****************************************************************************/
|
||||
|
||||
static int vhost_net_probe(FAR struct vhost_device *hdev)
|
||||
{
|
||||
FAR struct vhost_net_priv_s *priv;
|
||||
FAR const char *vqnames[VHOST_NET_NUM];
|
||||
vq_callback callbacks[VHOST_NET_NUM];
|
||||
FAR uint8_t *mac;
|
||||
int ret;
|
||||
|
||||
priv = kmm_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->hdev = hdev;
|
||||
hdev->priv = priv;
|
||||
|
||||
vqnames[VHOST_NET_PEER_RXQ] = "vhost_net_peer_rx";
|
||||
vqnames[VHOST_NET_PEER_TXQ] = "vhost_net_peer_tx";
|
||||
callbacks[VHOST_NET_PEER_RXQ] = vhost_net_txdone;
|
||||
callbacks[VHOST_NET_PEER_TXQ] = vhost_net_rxready;
|
||||
ret = vhost_create_virtqueues(hdev, 0, VHOST_NET_NUM, vqnames,
|
||||
callbacks, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
vhosterr("vhost_create_virtqueues failed, ret=%d\n", ret);
|
||||
goto err_with_priv;
|
||||
}
|
||||
|
||||
priv->txq = hdev->vrings_info[VHOST_NET_PEER_RXQ].vq;
|
||||
priv->rxq = hdev->vrings_info[VHOST_NET_PEER_TXQ].vq;
|
||||
|
||||
priv->lower.quota[NETPKT_RX] = VHOST_NET_NPKTS;
|
||||
priv->lower.quota[NETPKT_TX] = VHOST_NET_NPKTS;
|
||||
priv->lower.ops = &g_vhost_net_ops;
|
||||
|
||||
/* Software-assigned MAC (no MAC config space without negotiated
|
||||
* features); see CONFIG_DRIVERS_VHOST_NET_MACADDR.
|
||||
*/
|
||||
|
||||
mac = priv->lower.netdev.d_mac.ether.ether_addr_octet;
|
||||
mac[0] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 5)) & 0xff;
|
||||
mac[1] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 4)) & 0xff;
|
||||
mac[2] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 3)) & 0xff;
|
||||
mac[3] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 2)) & 0xff;
|
||||
mac[4] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 1)) & 0xff;
|
||||
mac[5] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 0)) & 0xff;
|
||||
|
||||
ret = netdev_lower_register(&priv->lower, NET_LL_ETHERNET);
|
||||
if (ret < 0)
|
||||
{
|
||||
vhosterr("netdev_lower_register failed, ret=%d\n", ret);
|
||||
goto err_with_vqs;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
err_with_vqs:
|
||||
vhost_delete_virtqueues(hdev);
|
||||
err_with_priv:
|
||||
kmm_free(priv);
|
||||
hdev->priv = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_net_remove
|
||||
****************************************************************************/
|
||||
|
||||
static void vhost_net_remove(FAR struct vhost_device *hdev)
|
||||
{
|
||||
FAR struct vhost_net_priv_s *priv = hdev->priv;
|
||||
|
||||
netdev_lower_unregister(&priv->lower);
|
||||
vhost_delete_virtqueues(hdev);
|
||||
kmm_free(priv);
|
||||
hdev->priv = NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_register_net_driver
|
||||
****************************************************************************/
|
||||
|
||||
int vhost_register_net_driver(void)
|
||||
{
|
||||
return vhost_register_driver(&g_vhost_net_driver);
|
||||
}
|
||||
28
drivers/vhost/vhost-net.h
Normal file
28
drivers/vhost/vhost-net.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/****************************************************************************
|
||||
* drivers/vhost/vhost-net.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_VHOST_VHOST_NET_H
|
||||
#define __DRIVERS_VHOST_VHOST_NET_H
|
||||
|
||||
int vhost_register_net_driver(void);
|
||||
|
||||
#endif /* __DRIVERS_VHOST_VHOST_NET_H */
|
||||
|
|
@ -109,6 +109,17 @@ int vhost_get_vq_buffers_pa(FAR struct virtqueue *vq,
|
|||
FAR struct vhost_buf_s *vb, size_t vbsize,
|
||||
FAR size_t *vbcnt);
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_VHOST_IOMAP
|
||||
/* Arch-provided: map a peer 64-bit physical address into CPU-reachable
|
||||
* memory. Returns the mapped VA; *avail (if non-NULL) receives the number
|
||||
* of contiguous bytes reachable from it. The mapping may be invalidated
|
||||
* by the next call (e.g. a sliding hardware window), so callers must
|
||||
* serialize use.
|
||||
*/
|
||||
|
||||
FAR void *up_vhost_iomap(uint64_t pa, FAR size_t *avail);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: vhost_register_drivers
|
||||
****************************************************************************/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue