1c0ab888aSImre Vadász /*- 2c0ab888aSImre Vadász * Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org> 3c0ab888aSImre Vadász * All rights reserved. 4c0ab888aSImre Vadász * 5c0ab888aSImre Vadász * Redistribution and use in source and binary forms, with or without 6c0ab888aSImre Vadász * modification, are permitted provided that the following conditions 7c0ab888aSImre Vadász * are met: 8c0ab888aSImre Vadász * 1. Redistributions of source code must retain the above copyright 9c0ab888aSImre Vadász * notice unmodified, this list of conditions, and the following 10c0ab888aSImre Vadász * disclaimer. 11c0ab888aSImre Vadász * 2. Redistributions in binary form must reproduce the above copyright 12c0ab888aSImre Vadász * notice, this list of conditions and the following disclaimer in the 13c0ab888aSImre Vadász * documentation and/or other materials provided with the distribution. 14c0ab888aSImre Vadász * 15c0ab888aSImre Vadász * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16c0ab888aSImre Vadász * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17c0ab888aSImre Vadász * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18c0ab888aSImre Vadász * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19c0ab888aSImre Vadász * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20c0ab888aSImre Vadász * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21c0ab888aSImre Vadász * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22c0ab888aSImre Vadász * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23c0ab888aSImre Vadász * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24c0ab888aSImre Vadász * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25c0ab888aSImre Vadász */ 26c0ab888aSImre Vadász 27c0ab888aSImre Vadász #ifndef _IF_VTNETVAR_H 28c0ab888aSImre Vadász #define _IF_VTNETVAR_H 29c0ab888aSImre Vadász 30c0ab888aSImre Vadász struct vtnet_statistics { 31c0ab888aSImre Vadász uint64_t mbuf_alloc_failed; 32c0ab888aSImre Vadász 33c0ab888aSImre Vadász uint64_t rx_frame_too_large; 34c0ab888aSImre Vadász uint64_t rx_enq_replacement_failed; 35c0ab888aSImre Vadász uint64_t rx_mergeable_failed; 36c0ab888aSImre Vadász uint64_t rx_csum_bad_ethtype; 37c0ab888aSImre Vadász uint64_t rx_csum_bad_ipproto; 38c0ab888aSImre Vadász uint64_t rx_csum_bad_offset; 39c0ab888aSImre Vadász uint64_t rx_csum_failed; 40c0ab888aSImre Vadász uint64_t rx_csum_offloaded; 41c0ab888aSImre Vadász uint64_t rx_task_rescheduled; 42c0ab888aSImre Vadász 43c0ab888aSImre Vadász uint64_t tx_csum_offloaded; 44c0ab888aSImre Vadász uint64_t tx_tso_offloaded; 45c0ab888aSImre Vadász uint64_t tx_csum_bad_ethtype; 46c0ab888aSImre Vadász uint64_t tx_tso_bad_ethtype; 47c0ab888aSImre Vadász uint64_t tx_defragged; 48c0ab888aSImre Vadász uint64_t tx_defrag_failed; 49c0ab888aSImre Vadász uint64_t tx_task_rescheduled; 50c0ab888aSImre Vadász }; 51c0ab888aSImre Vadász 52*4bf21f5cSImre Vadász struct irqmap { 53*4bf21f5cSImre Vadász int irq; 54*4bf21f5cSImre Vadász driver_intr_t *handler; 55*4bf21f5cSImre Vadász }; 56*4bf21f5cSImre Vadász 57c0ab888aSImre Vadász struct vtnet_softc { 58c0ab888aSImre Vadász device_t vtnet_dev; 59c0ab888aSImre Vadász struct ifnet *vtnet_ifp; 60c0ab888aSImre Vadász struct lwkt_serialize vtnet_slz; 615bd18522SImre Vadász struct lwkt_serialize vtnet_rx_slz; 625bd18522SImre Vadász struct lwkt_serialize vtnet_tx_slz; 635bd18522SImre Vadász struct lwkt_serialize *serializes[3]; 64c0ab888aSImre Vadász 65c0ab888aSImre Vadász uint32_t vtnet_flags; 66c0ab888aSImre Vadász #define VTNET_FLAG_LINK 0x0001 67c0ab888aSImre Vadász #define VTNET_FLAG_SUSPENDED 0x0002 68c0ab888aSImre Vadász #define VTNET_FLAG_MAC 0x0004 69c0ab888aSImre Vadász #define VTNET_FLAG_CTRL_VQ 0x0008 70c0ab888aSImre Vadász #define VTNET_FLAG_CTRL_RX 0x0010 71c0ab888aSImre Vadász #define VTNET_FLAG_CTRL_MAC 0x0020 72c0ab888aSImre Vadász #define VTNET_FLAG_VLAN_FILTER 0x0040 73c0ab888aSImre Vadász #define VTNET_FLAG_TSO_ECN 0x0080 74c0ab888aSImre Vadász #define VTNET_FLAG_MRG_RXBUFS 0x0100 75c0ab888aSImre Vadász #define VTNET_FLAG_LRO_NOMRG 0x0200 76be3e3739SImre Vadász #define VTNET_FLAG_INDIRECT 0x0400 77c0ab888aSImre Vadász 78c0ab888aSImre Vadász struct virtqueue *vtnet_rx_vq; 79c0ab888aSImre Vadász struct virtqueue *vtnet_tx_vq; 80c0ab888aSImre Vadász struct virtqueue *vtnet_ctrl_vq; 81c0ab888aSImre Vadász 822f2405bbSImre Vadász /* controlq, rx, tx and config_change */ 832f2405bbSImre Vadász int vtnet_cpus[4]; 842f2405bbSImre Vadász int vtnet_nintr; 852f2405bbSImre Vadász 86*4bf21f5cSImre Vadász struct irqmap vtnet_irqmap[2]; 87*4bf21f5cSImre Vadász struct lwkt_serialize *vtnet_intr_slz[3]; 88*4bf21f5cSImre Vadász 89be3e3739SImre Vadász int vtnet_txhdrcount; 90c0ab888aSImre Vadász struct vtnet_tx_header *vtnet_txhdrarea; 91d8c85757SImre Vadász SLIST_HEAD(, vtnet_tx_header) 92d8c85757SImre Vadász vtnet_txhdr_free; 93c0ab888aSImre Vadász struct vtnet_mac_filter *vtnet_macfilter; 94c0ab888aSImre Vadász 95c0ab888aSImre Vadász int vtnet_hdr_size; 962c7152a8SImre Vadász int vtnet_tx_size; 97be3e3739SImre Vadász int vtnet_tx_nsegs; 98c0ab888aSImre Vadász int vtnet_rx_process_limit; 99be3e3739SImre Vadász int vtnet_rx_nsegs; 100c0ab888aSImre Vadász int vtnet_rx_mbuf_size; 101c0ab888aSImre Vadász int vtnet_rx_mbuf_count; 102c0ab888aSImre Vadász int vtnet_if_flags; 103f7e8a8e7SImre Vadász struct ifsubq_watchdog vtnet_tx_watchdog; 104c0ab888aSImre Vadász uint64_t vtnet_features; 105c0ab888aSImre Vadász 106c0ab888aSImre Vadász struct vtnet_statistics vtnet_stats; 107c0ab888aSImre Vadász 108c0ab888aSImre Vadász eventhandler_tag vtnet_vlan_attach; 109c0ab888aSImre Vadász eventhandler_tag vtnet_vlan_detach; 110c0ab888aSImre Vadász 111c0ab888aSImre Vadász struct ifmedia vtnet_media; 112c0ab888aSImre Vadász /* 113c0ab888aSImre Vadász * Fake media type; the host does not provide us with 114c0ab888aSImre Vadász * any real media information. 115c0ab888aSImre Vadász */ 116c0ab888aSImre Vadász #define VTNET_MEDIATYPE (IFM_ETHER | IFM_1000_T | IFM_FDX) 117c0ab888aSImre Vadász char vtnet_hwaddr[ETHER_ADDR_LEN]; 118c0ab888aSImre Vadász 119c0ab888aSImre Vadász /* 120c0ab888aSImre Vadász * During reset, the host's VLAN filtering table is lost. The 121c0ab888aSImre Vadász * array below is used to restore all the VLANs configured on 122c0ab888aSImre Vadász * this interface after a reset. 123c0ab888aSImre Vadász */ 124c0ab888aSImre Vadász #define VTNET_VLAN_SHADOW_SIZE (4096 / 32) 125c0ab888aSImre Vadász int vtnet_nvlans; 126c0ab888aSImre Vadász uint32_t vtnet_vlan_shadow[VTNET_VLAN_SHADOW_SIZE]; 127c0ab888aSImre Vadász }; 128c0ab888aSImre Vadász 129c0ab888aSImre Vadász /* 130c0ab888aSImre Vadász * When mergeable buffers are not negotiated, the vtnet_rx_header structure 1317d38e2d2SImre Vadász * below is placed at the beginning of the mbuf data. Use 2 bytes of pad to 132c0ab888aSImre Vadász * both keep the VirtIO header and the data non-contiguous and to keep the 133c0ab888aSImre Vadász * frame's payload 4 byte aligned. 134c0ab888aSImre Vadász * 135c0ab888aSImre Vadász * When mergeable buffers are negotiated, the host puts the VirtIO header in 136c0ab888aSImre Vadász * the beginning of the first mbuf's data. 137c0ab888aSImre Vadász */ 1387d38e2d2SImre Vadász #define VTNET_RX_HEADER_PAD 2 139c0ab888aSImre Vadász struct vtnet_rx_header { 140c0ab888aSImre Vadász struct virtio_net_hdr vrh_hdr; 141c0ab888aSImre Vadász char vrh_pad[VTNET_RX_HEADER_PAD]; 142c0ab888aSImre Vadász } __packed; 143c0ab888aSImre Vadász 144c0ab888aSImre Vadász /* 145c0ab888aSImre Vadász * For each outgoing frame, the vtnet_tx_header below is allocated from 146d8c85757SImre Vadász * a free-list. 147c0ab888aSImre Vadász */ 148c0ab888aSImre Vadász struct vtnet_tx_header { 149c0ab888aSImre Vadász union { 150c0ab888aSImre Vadász struct virtio_net_hdr hdr; 151c0ab888aSImre Vadász struct virtio_net_hdr_mrg_rxbuf mhdr; 152c0ab888aSImre Vadász } vth_uhdr; 153c0ab888aSImre Vadász 154c0ab888aSImre Vadász struct mbuf *vth_mbuf; 155d8c85757SImre Vadász SLIST_ENTRY(vtnet_tx_header) link; 156c0ab888aSImre Vadász }; 157c0ab888aSImre Vadász 158c0ab888aSImre Vadász /* 159c0ab888aSImre Vadász * The VirtIO specification does not place a limit on the number of MAC 160c0ab888aSImre Vadász * addresses the guest driver may request to be filtered. In practice, 161c0ab888aSImre Vadász * the host is constrained by available resources. To simplify this driver, 162c0ab888aSImre Vadász * impose a reasonably high limit of MAC addresses we will filter before 163c0ab888aSImre Vadász * falling back to promiscuous or all-multicast modes. 164c0ab888aSImre Vadász */ 165c0ab888aSImre Vadász #define VTNET_MAX_MAC_ENTRIES 128 166c0ab888aSImre Vadász 167c0ab888aSImre Vadász struct vtnet_mac_table { 168c0ab888aSImre Vadász uint32_t nentries; 169c0ab888aSImre Vadász uint8_t macs[VTNET_MAX_MAC_ENTRIES][ETHER_ADDR_LEN]; 170c0ab888aSImre Vadász } __packed; 171c0ab888aSImre Vadász 172c0ab888aSImre Vadász struct vtnet_mac_filter { 173c0ab888aSImre Vadász struct vtnet_mac_table vmf_unicast; 174c0ab888aSImre Vadász uint32_t vmf_pad; /* Make tables non-contiguous. */ 175c0ab888aSImre Vadász struct vtnet_mac_table vmf_multicast; 176c0ab888aSImre Vadász }; 177c0ab888aSImre Vadász 178c0ab888aSImre Vadász #define VTNET_WATCHDOG_TIMEOUT 5 179c0ab888aSImre Vadász #define VTNET_CSUM_OFFLOAD (CSUM_TCP | CSUM_UDP) 180c0ab888aSImre Vadász 181c0ab888aSImre Vadász /* Features desired/implemented by this driver. */ 182c0ab888aSImre Vadász #define VTNET_FEATURES \ 183c0ab888aSImre Vadász (VIRTIO_NET_F_MAC | \ 184c0ab888aSImre Vadász VIRTIO_NET_F_STATUS | \ 185c0ab888aSImre Vadász VIRTIO_NET_F_CTRL_VQ | \ 186c0ab888aSImre Vadász VIRTIO_NET_F_CTRL_RX | \ 187c0ab888aSImre Vadász VIRTIO_NET_F_CTRL_MAC_ADDR | \ 188c0ab888aSImre Vadász VIRTIO_NET_F_CTRL_VLAN | \ 189c0ab888aSImre Vadász VIRTIO_NET_F_CSUM | \ 190c0ab888aSImre Vadász VIRTIO_NET_F_HOST_TSO4 | \ 191c0ab888aSImre Vadász VIRTIO_NET_F_HOST_TSO6 | \ 192c0ab888aSImre Vadász VIRTIO_NET_F_HOST_ECN | \ 193c0ab888aSImre Vadász VIRTIO_NET_F_GUEST_CSUM | \ 194c0ab888aSImre Vadász VIRTIO_NET_F_GUEST_TSO4 | \ 195c0ab888aSImre Vadász VIRTIO_NET_F_GUEST_TSO6 | \ 196c0ab888aSImre Vadász VIRTIO_NET_F_GUEST_ECN | \ 197be3e3739SImre Vadász VIRTIO_NET_F_MRG_RXBUF | \ 198be3e3739SImre Vadász VIRTIO_RING_F_INDIRECT_DESC) 199c0ab888aSImre Vadász 200c0ab888aSImre Vadász /* 201c0ab888aSImre Vadász * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us 202c0ab888aSImre Vadász * frames larger than 1514 bytes. We do not yet support software LRO 203c0ab888aSImre Vadász * via tcp_lro_rx(). 204c0ab888aSImre Vadász */ 205c0ab888aSImre Vadász #define VTNET_LRO_FEATURES (VIRTIO_NET_F_GUEST_TSO4 | \ 206c0ab888aSImre Vadász VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_ECN) 207c0ab888aSImre Vadász 208c0ab888aSImre Vadász #define VTNET_MAX_MTU 65536 209c0ab888aSImre Vadász #define VTNET_MAX_RX_SIZE 65550 210c0ab888aSImre Vadász 211c0ab888aSImre Vadász /* 212c0ab888aSImre Vadász * Used to preallocate the Vq indirect descriptors. The first segment 213c0ab888aSImre Vadász * is reserved for the header. 214c0ab888aSImre Vadász */ 215be3e3739SImre Vadász #define VTNET_MRG_RX_SEGS 1 216c0ab888aSImre Vadász #define VTNET_MIN_RX_SEGS 2 217c0ab888aSImre Vadász #define VTNET_MAX_RX_SEGS 34 218be3e3739SImre Vadász #define VTNET_MIN_TX_SEGS 4 219be3e3739SImre Vadász #define VTNET_MAX_TX_SEGS 64 220c0ab888aSImre Vadász 221d07f5241SImre Vadász #if 0 /* Copied from FreeBSD's net/if.h at some time, but not usable. */ 222c0ab888aSImre Vadász #define IFCAP_LRO 0x00400 /* can do Large Receive Offload */ 223c0ab888aSImre Vadász #define IFCAP_VLAN_HWFILTER 0x10000 /* interface hw can filter vlan tag */ 224c0ab888aSImre Vadász #define IFCAP_VLAN_HWTSO 0x40000 /* can do IFCAP_TSO on VLANs */ 225d07f5241SImre Vadász #endif 226d07f5241SImre Vadász 227d07f5241SImre Vadász /* 228d07f5241SImre Vadász * This allows lots of code to at least build, even if it's never executed 229d07f5241SImre Vadász * at the moment. 230d07f5241SImre Vadász */ 231d07f5241SImre Vadász #ifndef IFCAP_VLAN_HWFILTER 232d07f5241SImre Vadász #define IFCAP_VLAN_HWFILTER 0 233d07f5241SImre Vadász #endif 234d07f5241SImre Vadász #ifndef IFCAP_VLAN_HWTSO 235d07f5241SImre Vadász #define IFCAP_VLAN_HWTSO 0 236d07f5241SImre Vadász #endif 237c0ab888aSImre Vadász 238c0ab888aSImre Vadász /* 239c0ab888aSImre Vadász * Assert we can receive and transmit the maximum with regular 240c0ab888aSImre Vadász * size clusters. 241c0ab888aSImre Vadász */ 242c0ab888aSImre Vadász CTASSERT(((VTNET_MAX_RX_SEGS - 1) * MCLBYTES) >= VTNET_MAX_RX_SIZE); 243c0ab888aSImre Vadász CTASSERT(((VTNET_MAX_TX_SEGS - 1) * MCLBYTES) >= VTNET_MAX_MTU); 244c0ab888aSImre Vadász 245c0ab888aSImre Vadász /* 246c0ab888aSImre Vadász * Determine how many mbufs are in each receive buffer. For LRO without 247c0ab888aSImre Vadász * mergeable buffers, we must allocate an mbuf chain large enough to 248c0ab888aSImre Vadász * hold both the vtnet_rx_header and the maximum receivable data. 249c0ab888aSImre Vadász */ 250c0ab888aSImre Vadász #define VTNET_NEEDED_RX_MBUFS(_sc) \ 251c0ab888aSImre Vadász ((_sc)->vtnet_flags & VTNET_FLAG_LRO_NOMRG) == 0 ? 1 : \ 252c0ab888aSImre Vadász howmany(sizeof(struct vtnet_rx_header) + VTNET_MAX_RX_SIZE, \ 253c0ab888aSImre Vadász (_sc)->vtnet_rx_mbuf_size) 254c0ab888aSImre Vadász 255c0ab888aSImre Vadász #endif /* _IF_VTNETVAR_H */ 256