Skip to content

Commit

Permalink
lkl: Refactor net_enqueue
Browse files Browse the repository at this point in the history
This commit introduces some more descriptive names to the two queues
used by virtio_net, and wraps up some of the conditionals in net_enqueue
into functions so that it's a little more intention-revealing. As a
result, it's forced to pull the virtqueue struct definition into
virtio.h, but exposing more info is justified by keeping the virtio
structs closer together and allowing clearer code in virtio_net.

Signed-off-by: Patrick Collins <pscollins@google.com>
  • Loading branch information
pscollins committed Feb 23, 2016
1 parent 84ec4e0 commit 8f7a7c2
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 20 deletions.
12 changes: 0 additions & 12 deletions tools/lkl/lib/virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,6 @@
#define bad_driver(msg) do { } while (0)
#endif /* DEBUG */

struct virtio_queue {
uint32_t num_max;
uint32_t num;
uint32_t ready;

struct lkl_vring_desc *desc;
struct lkl_vring_avail *avail;
struct lkl_vring_used *used;
uint16_t last_avail_idx;
};


static inline uint16_t virtio_get_used_event(struct virtio_queue *q)
{
return q->avail->ring[q->num];
Expand Down
11 changes: 11 additions & 0 deletions tools/lkl/lib/virtio.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ struct virtio_dev_ops {
int (*enqueue)(struct virtio_dev *dev, struct virtio_req *req);
};

struct virtio_queue {
uint32_t num_max;
uint32_t num;
uint32_t ready;

struct lkl_vring_desc *desc;
struct lkl_vring_avail *avail;
struct lkl_vring_used *used;
uint16_t last_avail_idx;
};

struct virtio_dev {
uint32_t device_id;
uint32_t vendor_id;
Expand Down
45 changes: 37 additions & 8 deletions tools/lkl/lib/virtio_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@

#define BIT(x) (1ULL << x)

/* We always have 2 queues on a netdev: one for tx, one for rx. */
#define RX_QUEUE_IDX 0
#define TX_QUEUE_IDX 1
#define NUM_QUEUES (TX_QUEUE_IDX + 1)

#ifdef DEBUG
#define bad_request(s) do { \
lkl_printf("%s\n", s); \
panic(); \
} while (0)
#else
#define bad_request(s) lkl_printf("virtio_net: %s\n", s);
#endif /* DEBUG */


struct virtio_net_poll {
struct virtio_net_dev *dev;
struct lkl_sem_t *sem;
Expand All @@ -29,40 +44,54 @@ static int net_check_features(struct virtio_dev *dev)
return -LKL_EINVAL;
}

static inline int is_rx_queue(struct virtio_dev *dev, struct virtio_queue *queue)
{
return &dev->queue[RX_QUEUE_IDX] == queue;
}

static inline int is_tx_queue(struct virtio_dev *dev, struct virtio_queue *queue)
{
return &dev->queue[TX_QUEUE_IDX] == queue;
}

static int net_enqueue(struct virtio_dev *dev, struct virtio_req *req)
{
struct lkl_virtio_net_hdr_v1 *h;
struct lkl_virtio_net_hdr_v1 *header;
struct virtio_net_dev *net_dev;
int ret, len;
void *buf;

h = req->buf[0].addr;
header = req->buf[0].addr;
net_dev = container_of(dev, struct virtio_net_dev, dev);
len = req->buf[0].len - sizeof(*h);
len = req->buf[0].len - sizeof(*header);

buf = &h[1];
buf = &header[1];

if (!len && req->buf_count > 1) {
buf = req->buf[1].addr;
len = req->buf[1].len;
}

if (req->q != dev->queue) {
/* Pick which virtqueue to send the buffer(s) to */
if (is_tx_queue(dev, req->q)) {
ret = net_dev->ops->tx(net_dev->nd, buf, len);
if (ret < 0) {
lkl_host_ops.sem_up(net_dev->tx_poll.sem);
return -1;
}
} else {
h->num_buffers = 1;
} else if (is_rx_queue(dev, req->q)) {
header->num_buffers = 1;
ret = net_dev->ops->rx(net_dev->nd, buf, &len);
if (ret < 0) {
lkl_host_ops.sem_up(net_dev->rx_poll.sem);
return -1;
}
} else {
bad_request("tried to push on non-existent queue");
return -1;
}

virtio_req_complete(req, len + sizeof(*h));
virtio_req_complete(req, len + sizeof(*header));
return 0;
}

Expand Down

0 comments on commit 8f7a7c2

Please sign in to comment.