summaryrefslogtreecommitdiffstats
path: root/include/hw/virtio/virtio-net.h
blob: 96c68d4a927cf42185dfda1424246ce9fb14e837 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * Virtio Network Device
 *
 * Copyright IBM, Corp. 2007
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
 */

#ifndef QEMU_VIRTIO_NET_H
#define QEMU_VIRTIO_NET_H

#include "qemu/units.h"
#include "standard-headers/linux/virtio_net.h"
#include "hw/virtio/virtio.h"
#include "net/announce.h"
#include "qemu/option_int.h"

#define TYPE_VIRTIO_NET "virtio-net-device"
#define VIRTIO_NET(obj) \
        OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET)

#define TX_TIMER_INTERVAL 150000 /* 150 us */

/* Limit the number of packets that can be sent via a single flush
 * of the TX queue.  This gives us a guaranteed exit condition and
 * ensures fairness in the io path.  256 conveniently matches the
 * length of the TX queue and shows a good balance of performance
 * and latency. */
#define TX_BURST 256

typedef struct virtio_net_conf
{
    uint32_t txtimer;
    int32_t txburst;
    char *tx;
    uint16_t rx_queue_size;
    uint16_t tx_queue_size;
    uint16_t mtu;
    int32_t speed;
    char *duplex_str;
    uint8_t duplex;
    char *primary_id_str;
} virtio_net_conf;

/* Coalesced packets type & status */
typedef enum {
    RSC_COALESCE,           /* Data been coalesced */
    RSC_FINAL,              /* Will terminate current connection */
    RSC_NO_MATCH,           /* No matched in the buffer pool */
    RSC_BYPASS,             /* Packet to be bypass, not tcp, tcp ctrl, etc */
    RSC_CANDIDATE                /* Data want to be coalesced */
} CoalesceStatus;

typedef struct VirtioNetRscStat {
    uint32_t received;
    uint32_t coalesced;
    uint32_t over_size;
    uint32_t cache;
    uint32_t empty_cache;
    uint32_t no_match_cache;
    uint32_t win_update;
    uint32_t no_match;
    uint32_t tcp_syn;
    uint32_t tcp_ctrl_drain;
    uint32_t dup_ack;
    uint32_t dup_ack1;
    uint32_t dup_ack2;
    uint32_t pure_ack;
    uint32_t ack_out_of_win;
    uint32_t data_out_of_win;
    uint32_t data_out_of_order;
    uint32_t data_after_pure_ack;
    uint32_t bypass_not_tcp;
    uint32_t tcp_option;
    uint32_t tcp_all_opt;
    uint32_t ip_frag;
    uint32_t ip_ecn;
    uint32_t ip_hacked;
    uint32_t ip_option;
    uint32_t purge_failed;
    uint32_t drain_failed;
    uint32_t final_failed;
    int64_t  timer;
} VirtioNetRscStat;

/* Rsc unit general info used to checking if can coalescing */
typedef struct VirtioNetRscUnit {
    void *ip;   /* ip header */
    uint16_t *ip_plen;      /* data len pointer in ip header field */
    struct tcp_header *tcp; /* tcp header */
    uint16_t tcp_hdrlen;    /* tcp header len */
    uint16_t payload;       /* pure payload without virtio/eth/ip/tcp */
} VirtioNetRscUnit;

/* Coalesced segment */
typedef struct VirtioNetRscSeg {
    QTAILQ_ENTRY(VirtioNetRscSeg) next;
    void *buf;
    size_t size;
    uint16_t packets;
    uint16_t dup_ack;
    bool is_coalesced;      /* need recal ipv4 header checksum, mark here */
    VirtioNetRscUnit unit;
    NetClientState *nc;
} VirtioNetRscSeg;

typedef struct VirtIONet VirtIONet;

/* Chain is divided by protocol(ipv4/v6) and NetClientInfo */
typedef struct VirtioNetRscChain {
    QTAILQ_ENTRY(VirtioNetRscChain) next;
    VirtIONet *n;                            /* VirtIONet */
    uint16_t proto;
    uint8_t  gso_type;
    uint16_t max_payload;
    QEMUTimer *drain_timer;
    QTAILQ_HEAD(, VirtioNetRscSeg) buffers;
    VirtioNetRscStat stat;
} VirtioNetRscChain;

/* Maximum packet size we can receive from tap device: header + 64k */
#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 * KiB))

typedef struct VirtIONetQueue {
    VirtQueue *rx_vq;
    VirtQueue *tx_vq;
    QEMUTimer *tx_timer;
    QEMUBH *tx_bh;
    uint32_t tx_waiting;
    struct {
        VirtQueueElement *elem;
    } async_tx;
    struct VirtIONet *n;
} VirtIONetQueue;

struct VirtIONet {
    VirtIODevice parent_obj;
    uint8_t mac[ETH_ALEN];
    uint16_t status;
    VirtIONetQueue *vqs;
    VirtQueue *ctrl_vq;
    NICState *nic;
    /* RSC Chains - temporary storage of coalesced data,
       all these data are lost in case of migration */
    QTAILQ_HEAD(, VirtioNetRscChain) rsc_chains;
    uint32_t tx_timeout;
    int32_t tx_burst;
    uint32_t has_vnet_hdr;
    size_t host_hdr_len;
    size_t guest_hdr_len;
    uint64_t host_features;
    uint32_t rsc_timeout;
    uint8_t rsc4_enabled;
    uint8_t rsc6_enabled;
    uint8_t has_ufo;
    uint32_t mergeable_rx_bufs;
    uint8_t promisc;
    uint8_t allmulti;
    uint8_t alluni;
    uint8_t nomulti;
    uint8_t nouni;
    uint8_t nobcast;
    uint8_t vhost_started;
    struct {
        uint32_t in_use;
        uint32_t first_multi;
        uint8_t multi_overflow;
        uint8_t uni_overflow;
        uint8_t *macs;
    } mac_table;
    uint32_t *vlans;
    virtio_net_conf net_conf;
    NICConf nic_conf;
    DeviceState *qdev;
    int multiqueue;
    uint16_t max_queues;
    uint16_t curr_queues;
    size_t config_size;
    char *netclient_name;
    char *netclient_type;
    uint64_t curr_guest_offloads;
    /* used on saved state restore phase to preserve the curr_guest_offloads */
    uint64_t saved_guest_offloads;
    AnnounceTimer announce_timer;
    bool needs_vnet_hdr_swap;
    bool mtu_bypass_backend;
    QemuOpts *primary_device_opts;
    QDict *primary_device_dict;
    DeviceState *primary_dev;
    BusState *primary_bus;
    char *primary_device_id;
    char *standby_id;
    bool primary_should_be_hidden;
    bool failover;
    DeviceListener primary_listener;
    Notifier migration_state;
};

void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
                                   const char *type);

#endif