1227652Sgrehan/*- 2253132Sbryanv * Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org> 3227652Sgrehan * All rights reserved. 4227652Sgrehan * 5227652Sgrehan * Redistribution and use in source and binary forms, with or without 6227652Sgrehan * modification, are permitted provided that the following conditions 7227652Sgrehan * are met: 8227652Sgrehan * 1. Redistributions of source code must retain the above copyright 9227652Sgrehan * notice unmodified, this list of conditions, and the following 10227652Sgrehan * disclaimer. 11227652Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 12227652Sgrehan * notice, this list of conditions and the following disclaimer in the 13227652Sgrehan * documentation and/or other materials provided with the distribution. 14227652Sgrehan * 15227652Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16227652Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17227652Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18227652Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19227652Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20227652Sgrehan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21227652Sgrehan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22227652Sgrehan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23227652Sgrehan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24227652Sgrehan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25227652Sgrehan * 26227652Sgrehan * $FreeBSD$ 27227652Sgrehan */ 28227652Sgrehan 29227652Sgrehan#ifndef _IF_VTNETVAR_H 30227652Sgrehan#define _IF_VTNETVAR_H 31227652Sgrehan 32265480Sbryanvstruct vtnet_softc; 33265480Sbryanv 34227652Sgrehanstruct vtnet_statistics { 35265480Sbryanv uint64_t mbuf_alloc_failed; 36227652Sgrehan 37265480Sbryanv uint64_t rx_frame_too_large; 38265480Sbryanv uint64_t rx_enq_replacement_failed; 39265480Sbryanv uint64_t rx_mergeable_failed; 40265480Sbryanv uint64_t rx_csum_bad_ethtype; 41265480Sbryanv uint64_t rx_csum_bad_ipproto; 42265480Sbryanv uint64_t rx_csum_bad_offset; 43265480Sbryanv uint64_t rx_csum_bad_proto; 44265480Sbryanv uint64_t tx_csum_bad_ethtype; 45265480Sbryanv uint64_t tx_tso_bad_ethtype; 46265480Sbryanv uint64_t tx_tso_not_tcp; 47265480Sbryanv uint64_t tx_defragged; 48265480Sbryanv uint64_t tx_defrag_failed; 49227652Sgrehan 50265480Sbryanv /* 51265480Sbryanv * These are accumulated from each Rx/Tx queue. 52265480Sbryanv */ 53265480Sbryanv uint64_t rx_csum_failed; 54265480Sbryanv uint64_t rx_csum_offloaded; 55265480Sbryanv uint64_t rx_task_rescheduled; 56265480Sbryanv uint64_t tx_csum_offloaded; 57265480Sbryanv uint64_t tx_tso_offloaded; 58265480Sbryanv uint64_t tx_task_rescheduled; 59227652Sgrehan}; 60227652Sgrehan 61265480Sbryanvstruct vtnet_rxq_stats { 62265480Sbryanv uint64_t vrxs_ipackets; /* if_ipackets */ 63265480Sbryanv uint64_t vrxs_ibytes; /* if_ibytes */ 64265480Sbryanv uint64_t vrxs_iqdrops; /* if_iqdrops */ 65265480Sbryanv uint64_t vrxs_ierrors; /* if_ierrors */ 66265480Sbryanv uint64_t vrxs_csum; 67265480Sbryanv uint64_t vrxs_csum_failed; 68265480Sbryanv uint64_t vrxs_rescheduled; 69265480Sbryanv}; 70265480Sbryanv 71265480Sbryanvstruct vtnet_rxq { 72265480Sbryanv struct mtx vtnrx_mtx; 73265480Sbryanv struct vtnet_softc *vtnrx_sc; 74265480Sbryanv struct virtqueue *vtnrx_vq; 75265480Sbryanv struct sglist *vtnrx_sg; 76265480Sbryanv int vtnrx_id; 77265480Sbryanv int vtnrx_process_limit; 78265480Sbryanv struct vtnet_rxq_stats vtnrx_stats; 79265480Sbryanv struct taskqueue *vtnrx_tq; 80265480Sbryanv struct task vtnrx_intrtask; 81265480Sbryanv char vtnrx_name[16]; 82265480Sbryanv} __aligned(CACHE_LINE_SIZE); 83265480Sbryanv 84265480Sbryanv#define VTNET_RXQ_LOCK(_rxq) mtx_lock(&(_rxq)->vtnrx_mtx) 85265480Sbryanv#define VTNET_RXQ_UNLOCK(_rxq) mtx_unlock(&(_rxq)->vtnrx_mtx) 86265480Sbryanv#define VTNET_RXQ_LOCK_ASSERT(_rxq) \ 87265480Sbryanv mtx_assert(&(_rxq)->vtnrx_mtx, MA_OWNED) 88265480Sbryanv#define VTNET_RXQ_LOCK_ASSERT_NOTOWNED(_rxq) \ 89265480Sbryanv mtx_assert(&(_rxq)->vtnrx_mtx, MA_NOTOWNED) 90265480Sbryanv 91265480Sbryanvstruct vtnet_txq_stats { 92265480Sbryanv uint64_t vtxs_opackets; /* if_opackets */ 93265480Sbryanv uint64_t vtxs_obytes; /* if_obytes */ 94265480Sbryanv uint64_t vtxs_omcasts; /* if_omcasts */ 95265480Sbryanv uint64_t vtxs_csum; 96265480Sbryanv uint64_t vtxs_tso; 97265480Sbryanv uint64_t vtxs_rescheduled; 98265480Sbryanv}; 99265480Sbryanv 100265480Sbryanvstruct vtnet_txq { 101265480Sbryanv struct mtx vtntx_mtx; 102265480Sbryanv struct vtnet_softc *vtntx_sc; 103265480Sbryanv struct virtqueue *vtntx_vq; 104265480Sbryanv struct sglist *vtntx_sg; 105265480Sbryanv#ifndef VTNET_LEGACY_TX 106265480Sbryanv struct buf_ring *vtntx_br; 107265480Sbryanv#endif 108265480Sbryanv int vtntx_id; 109265480Sbryanv int vtntx_watchdog; 110265480Sbryanv struct vtnet_txq_stats vtntx_stats; 111265480Sbryanv struct taskqueue *vtntx_tq; 112265480Sbryanv struct task vtntx_intrtask; 113265480Sbryanv#ifndef VTNET_LEGACY_TX 114265480Sbryanv struct task vtntx_defrtask; 115265480Sbryanv#endif 116265480Sbryanv char vtntx_name[16]; 117265480Sbryanv} __aligned(CACHE_LINE_SIZE); 118265480Sbryanv 119265480Sbryanv#define VTNET_TXQ_LOCK(_txq) mtx_lock(&(_txq)->vtntx_mtx) 120265480Sbryanv#define VTNET_TXQ_TRYLOCK(_txq) mtx_trylock(&(_txq)->vtntx_mtx) 121265480Sbryanv#define VTNET_TXQ_UNLOCK(_txq) mtx_unlock(&(_txq)->vtntx_mtx) 122265480Sbryanv#define VTNET_TXQ_LOCK_ASSERT(_txq) \ 123265480Sbryanv mtx_assert(&(_txq)->vtntx_mtx, MA_OWNED) 124265480Sbryanv#define VTNET_TXQ_LOCK_ASSERT_NOTOWNED(_txq) \ 125265480Sbryanv mtx_assert(&(_txq)->vtntx_mtx, MA_NOTOWNED) 126265480Sbryanv 127227652Sgrehanstruct vtnet_softc { 128227652Sgrehan device_t vtnet_dev; 129227652Sgrehan struct ifnet *vtnet_ifp; 130265480Sbryanv struct vtnet_rxq *vtnet_rxqs; 131265480Sbryanv struct vtnet_txq *vtnet_txqs; 132227652Sgrehan 133227652Sgrehan uint32_t vtnet_flags; 134265480Sbryanv#define VTNET_FLAG_SUSPENDED 0x0001 135265480Sbryanv#define VTNET_FLAG_MAC 0x0002 136227652Sgrehan#define VTNET_FLAG_CTRL_VQ 0x0004 137227652Sgrehan#define VTNET_FLAG_CTRL_RX 0x0008 138265480Sbryanv#define VTNET_FLAG_CTRL_MAC 0x0010 139265480Sbryanv#define VTNET_FLAG_VLAN_FILTER 0x0020 140265480Sbryanv#define VTNET_FLAG_TSO_ECN 0x0040 141265480Sbryanv#define VTNET_FLAG_MRG_RXBUFS 0x0080 142265480Sbryanv#define VTNET_FLAG_LRO_NOMRG 0x0100 143265480Sbryanv#define VTNET_FLAG_MULTIQ 0x0200 144265480Sbryanv#define VTNET_FLAG_EVENT_IDX 0x0400 145227652Sgrehan 146265480Sbryanv int vtnet_link_active; 147227652Sgrehan int vtnet_hdr_size; 148227652Sgrehan int vtnet_rx_process_limit; 149265480Sbryanv int vtnet_rx_nsegs; 150265480Sbryanv int vtnet_rx_nmbufs; 151265480Sbryanv int vtnet_rx_clsize; 152265480Sbryanv int vtnet_rx_new_clsize; 153265480Sbryanv int vtnet_tx_nsegs; 154227652Sgrehan int vtnet_if_flags; 155265480Sbryanv int vtnet_act_vq_pairs; 156265480Sbryanv int vtnet_max_vq_pairs; 157265480Sbryanv 158265480Sbryanv struct virtqueue *vtnet_ctrl_vq; 159265480Sbryanv struct vtnet_mac_filter *vtnet_mac_filter; 160265480Sbryanv uint32_t *vtnet_vlan_filter; 161265480Sbryanv 162227652Sgrehan uint64_t vtnet_features; 163227652Sgrehan struct vtnet_statistics vtnet_stats; 164227652Sgrehan struct callout vtnet_tick_ch; 165265480Sbryanv struct ifmedia vtnet_media; 166227652Sgrehan eventhandler_tag vtnet_vlan_attach; 167227652Sgrehan eventhandler_tag vtnet_vlan_detach; 168227652Sgrehan 169265480Sbryanv struct mtx vtnet_mtx; 170265480Sbryanv char vtnet_mtx_name[16]; 171227652Sgrehan char vtnet_hwaddr[ETHER_ADDR_LEN]; 172265480Sbryanv}; 173227652Sgrehan 174265480Sbryanv/* 175265480Sbryanv * Maximum number of queue pairs we will autoconfigure to. 176265480Sbryanv */ 177265480Sbryanv#define VTNET_MAX_QUEUE_PAIRS 8 178227652Sgrehan 179265480Sbryanv/* 180265480Sbryanv * Additional completed entries can appear in a virtqueue before we can 181265480Sbryanv * reenable interrupts. Number of times to retry before scheduling the 182265480Sbryanv * taskqueue to process the completed entries. 183265480Sbryanv */ 184265480Sbryanv#define VTNET_INTR_DISABLE_RETRIES 4 185227652Sgrehan 186227652Sgrehan/* 187265480Sbryanv * Fake the media type. The host does not provide us with any real media 188265480Sbryanv * information. 189265480Sbryanv */ 190265480Sbryanv#define VTNET_MEDIATYPE (IFM_ETHER | IFM_10G_T | IFM_FDX) 191265480Sbryanv 192265480Sbryanv/* 193265480Sbryanv * Number of words to allocate for the VLAN shadow table. There is one 194265480Sbryanv * bit for each VLAN. 195265480Sbryanv */ 196265480Sbryanv#define VTNET_VLAN_FILTER_NWORDS (4096 / 32) 197265480Sbryanv 198265480Sbryanv/* 199227652Sgrehan * When mergeable buffers are not negotiated, the vtnet_rx_header structure 200227652Sgrehan * below is placed at the beginning of the mbuf data. Use 4 bytes of pad to 201227652Sgrehan * both keep the VirtIO header and the data non-contiguous and to keep the 202227652Sgrehan * frame's payload 4 byte aligned. 203227652Sgrehan * 204227652Sgrehan * When mergeable buffers are negotiated, the host puts the VirtIO header in 205227652Sgrehan * the beginning of the first mbuf's data. 206227652Sgrehan */ 207227652Sgrehan#define VTNET_RX_HEADER_PAD 4 208227652Sgrehanstruct vtnet_rx_header { 209227652Sgrehan struct virtio_net_hdr vrh_hdr; 210227652Sgrehan char vrh_pad[VTNET_RX_HEADER_PAD]; 211227652Sgrehan} __packed; 212227652Sgrehan 213227652Sgrehan/* 214227652Sgrehan * For each outgoing frame, the vtnet_tx_header below is allocated from 215227652Sgrehan * the vtnet_tx_header_zone. 216227652Sgrehan */ 217227652Sgrehanstruct vtnet_tx_header { 218227652Sgrehan union { 219227652Sgrehan struct virtio_net_hdr hdr; 220227652Sgrehan struct virtio_net_hdr_mrg_rxbuf mhdr; 221227652Sgrehan } vth_uhdr; 222227652Sgrehan 223227652Sgrehan struct mbuf *vth_mbuf; 224227652Sgrehan}; 225227652Sgrehan 226227652Sgrehan/* 227227652Sgrehan * The VirtIO specification does not place a limit on the number of MAC 228227652Sgrehan * addresses the guest driver may request to be filtered. In practice, 229227652Sgrehan * the host is constrained by available resources. To simplify this driver, 230227652Sgrehan * impose a reasonably high limit of MAC addresses we will filter before 231227652Sgrehan * falling back to promiscuous or all-multicast modes. 232227652Sgrehan */ 233227652Sgrehan#define VTNET_MAX_MAC_ENTRIES 128 234227652Sgrehan 235227652Sgrehanstruct vtnet_mac_table { 236227652Sgrehan uint32_t nentries; 237227652Sgrehan uint8_t macs[VTNET_MAX_MAC_ENTRIES][ETHER_ADDR_LEN]; 238227652Sgrehan} __packed; 239227652Sgrehan 240227652Sgrehanstruct vtnet_mac_filter { 241227652Sgrehan struct vtnet_mac_table vmf_unicast; 242227652Sgrehan uint32_t vmf_pad; /* Make tables non-contiguous. */ 243227652Sgrehan struct vtnet_mac_table vmf_multicast; 244227652Sgrehan}; 245227652Sgrehan 246227652Sgrehan/* 247227652Sgrehan * The MAC filter table is malloc(9)'d when needed. Ensure it will 248227652Sgrehan * always fit in one segment. 249227652Sgrehan */ 250227652SgrehanCTASSERT(sizeof(struct vtnet_mac_filter) <= PAGE_SIZE); 251227652Sgrehan 252265480Sbryanv#define VTNET_TX_TIMEOUT 5 253227652Sgrehan#define VTNET_CSUM_OFFLOAD (CSUM_TCP | CSUM_UDP | CSUM_SCTP) 254265480Sbryanv#define VTNET_CSUM_OFFLOAD_IPV6 (CSUM_TCP_IPV6 | CSUM_UDP_IPV6 | CSUM_SCTP_IPV6) 255227652Sgrehan 256265480Sbryanv#define VTNET_CSUM_ALL_OFFLOAD \ 257265480Sbryanv (VTNET_CSUM_OFFLOAD | VTNET_CSUM_OFFLOAD_IPV6 | CSUM_TSO) 258265480Sbryanv 259227652Sgrehan/* Features desired/implemented by this driver. */ 260227652Sgrehan#define VTNET_FEATURES \ 261227652Sgrehan (VIRTIO_NET_F_MAC | \ 262227652Sgrehan VIRTIO_NET_F_STATUS | \ 263227652Sgrehan VIRTIO_NET_F_CTRL_VQ | \ 264227652Sgrehan VIRTIO_NET_F_CTRL_RX | \ 265265480Sbryanv VIRTIO_NET_F_CTRL_MAC_ADDR | \ 266227652Sgrehan VIRTIO_NET_F_CTRL_VLAN | \ 267227652Sgrehan VIRTIO_NET_F_CSUM | \ 268265480Sbryanv VIRTIO_NET_F_GSO | \ 269227652Sgrehan VIRTIO_NET_F_HOST_TSO4 | \ 270227652Sgrehan VIRTIO_NET_F_HOST_TSO6 | \ 271227652Sgrehan VIRTIO_NET_F_HOST_ECN | \ 272227652Sgrehan VIRTIO_NET_F_GUEST_CSUM | \ 273227652Sgrehan VIRTIO_NET_F_GUEST_TSO4 | \ 274227652Sgrehan VIRTIO_NET_F_GUEST_TSO6 | \ 275227652Sgrehan VIRTIO_NET_F_GUEST_ECN | \ 276227652Sgrehan VIRTIO_NET_F_MRG_RXBUF | \ 277265480Sbryanv VIRTIO_NET_F_MQ | \ 278265480Sbryanv VIRTIO_RING_F_EVENT_IDX | \ 279227652Sgrehan VIRTIO_RING_F_INDIRECT_DESC) 280227652Sgrehan 281227652Sgrehan/* 282265480Sbryanv * The VIRTIO_NET_F_HOST_TSO[46] features permit us to send the host 283265480Sbryanv * frames larger than 1514 bytes. 284265480Sbryanv */ 285265480Sbryanv#define VTNET_TSO_FEATURES (VIRTIO_NET_F_GSO | VIRTIO_NET_F_HOST_TSO4 | \ 286265480Sbryanv VIRTIO_NET_F_HOST_TSO6 | VIRTIO_NET_F_HOST_ECN) 287265480Sbryanv 288265480Sbryanv/* 289227652Sgrehan * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us 290227652Sgrehan * frames larger than 1514 bytes. We do not yet support software LRO 291227652Sgrehan * via tcp_lro_rx(). 292227652Sgrehan */ 293227652Sgrehan#define VTNET_LRO_FEATURES (VIRTIO_NET_F_GUEST_TSO4 | \ 294227652Sgrehan VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_ECN) 295227652Sgrehan 296227652Sgrehan#define VTNET_MAX_MTU 65536 297227652Sgrehan#define VTNET_MAX_RX_SIZE 65550 298227652Sgrehan 299227652Sgrehan/* 300227652Sgrehan * Used to preallocate the Vq indirect descriptors. The first segment 301265480Sbryanv * is reserved for the header, except for mergeable buffers since the 302265480Sbryanv * header is placed inline with the data. 303227652Sgrehan */ 304265480Sbryanv#define VTNET_MRG_RX_SEGS 1 305227652Sgrehan#define VTNET_MIN_RX_SEGS 2 306227652Sgrehan#define VTNET_MAX_RX_SEGS 34 307265480Sbryanv#define VTNET_MIN_TX_SEGS 4 308265480Sbryanv#define VTNET_MAX_TX_SEGS 64 309227652Sgrehan 310227652Sgrehan/* 311227652Sgrehan * Assert we can receive and transmit the maximum with regular 312227652Sgrehan * size clusters. 313227652Sgrehan */ 314227652SgrehanCTASSERT(((VTNET_MAX_RX_SEGS - 1) * MCLBYTES) >= VTNET_MAX_RX_SIZE); 315227652SgrehanCTASSERT(((VTNET_MAX_TX_SEGS - 1) * MCLBYTES) >= VTNET_MAX_MTU); 316227652Sgrehan 317227652Sgrehan/* 318265480Sbryanv * Number of slots in the Tx bufrings. This value matches most other 319265480Sbryanv * multiqueue drivers. 320265480Sbryanv */ 321265480Sbryanv#define VTNET_DEFAULT_BUFRING_SIZE 4096 322265480Sbryanv 323265480Sbryanv/* 324227652Sgrehan * Determine how many mbufs are in each receive buffer. For LRO without 325265480Sbryanv * mergeable buffers, we must allocate an mbuf chain large enough to 326227652Sgrehan * hold both the vtnet_rx_header and the maximum receivable data. 327227652Sgrehan */ 328265480Sbryanv#define VTNET_NEEDED_RX_MBUFS(_sc, _clsize) \ 329227652Sgrehan ((_sc)->vtnet_flags & VTNET_FLAG_LRO_NOMRG) == 0 ? 1 : \ 330227652Sgrehan howmany(sizeof(struct vtnet_rx_header) + VTNET_MAX_RX_SIZE, \ 331265480Sbryanv (_clsize)) 332227652Sgrehan 333265480Sbryanv#define VTNET_CORE_MTX(_sc) &(_sc)->vtnet_mtx 334265480Sbryanv#define VTNET_CORE_LOCK(_sc) mtx_lock(VTNET_CORE_MTX((_sc))) 335265480Sbryanv#define VTNET_CORE_UNLOCK(_sc) mtx_unlock(VTNET_CORE_MTX((_sc))) 336265480Sbryanv#define VTNET_CORE_LOCK_DESTROY(_sc) mtx_destroy(VTNET_CORE_MTX((_sc))) 337265480Sbryanv#define VTNET_CORE_LOCK_ASSERT(_sc) \ 338265480Sbryanv mtx_assert(VTNET_CORE_MTX((_sc)), MA_OWNED) 339265480Sbryanv#define VTNET_CORE_LOCK_ASSERT_NOTOWNED(_sc) \ 340265480Sbryanv mtx_assert(VTNET_CORE_MTX((_sc)), MA_NOTOWNED) 341227652Sgrehan 342265480Sbryanv#define VTNET_CORE_LOCK_INIT(_sc) do { \ 343227652Sgrehan snprintf((_sc)->vtnet_mtx_name, sizeof((_sc)->vtnet_mtx_name), \ 344227652Sgrehan "%s", device_get_nameunit((_sc)->vtnet_dev)); \ 345265480Sbryanv mtx_init(VTNET_CORE_MTX((_sc)), (_sc)->vtnet_mtx_name, \ 346227652Sgrehan "VTNET Core Lock", MTX_DEF); \ 347227652Sgrehan} while (0) 348227652Sgrehan 349227652Sgrehan#endif /* _IF_VTNETVAR_H */ 350