Print this page
Use #pragma pack() per Hans
Hans review comments, but no pragma packed yet.
Add virtio net feature bit order string
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Code review changes


  38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41  */
  42 
  43 #include <sys/types.h>
  44 #include <sys/errno.h>
  45 #include <sys/param.h>
  46 #include <sys/stropts.h>
  47 #include <sys/stream.h>
  48 #include <sys/strsubr.h>
  49 #include <sys/kmem.h>
  50 #include <sys/conf.h>
  51 #include <sys/devops.h>
  52 #include <sys/ksynch.h>
  53 #include <sys/stat.h>
  54 #include <sys/modctl.h>
  55 #include <sys/debug.h>
  56 #include <sys/pci.h>
  57 #include <sys/ethernet.h>

  58 
  59 #define VLAN_TAGSZ 4
  60 
  61 #include <sys/dlpi.h>
  62 #include <sys/taskq.h>
  63 #include <sys/cyclic.h>
  64 
  65 #include <sys/pattr.h>
  66 #include <sys/strsun.h>
  67 
  68 #include <sys/random.h>
  69 #include <sys/sysmacros.h>
  70 #include <sys/stream.h>
  71 
  72 #include <sys/mac.h>
  73 #include <sys/mac_provider.h>
  74 #include <sys/mac_ether.h>
  75 
  76 #include "virtiovar.h"
  77 #include "virtioreg.h"
  78 
  79 #if !defined(__packed)
  80 #define __packed __attribute__((packed))
  81 #endif /* __packed */
  82 
  83 /* Configuration registers */
  84 #define VIRTIO_NET_CONFIG_MAC           0 /* 8bit x 6byte */
  85 #define VIRTIO_NET_CONFIG_STATUS        6 /* 16bit */
  86 
  87 /* Feature bits */
  88 #define VIRTIO_NET_F_CSUM       (1 << 0) /* Host handles pkts w/ partial csum */
  89 #define VIRTIO_NET_F_GUEST_CSUM (1 << 1) /* Guest handles pkts w/ part csum */
  90 #define VIRTIO_NET_F_MAC        (1 << 5) /* Host has given MAC address. */
  91 #define VIRTIO_NET_F_GSO        (1 << 6) /* Host handles pkts w/ any GSO type */
  92 #define VIRTIO_NET_F_GUEST_TSO4 (1 << 7) /* Guest can handle TSOv4 in. */
  93 #define VIRTIO_NET_F_GUEST_TSO6 (1 << 8) /* Guest can handle TSOv6 in. */
  94 #define VIRTIO_NET_F_GUEST_ECN  (1 << 9) /* Guest can handle TSO[6] w/ ECN in */
  95 #define VIRTIO_NET_F_GUEST_UFO  (1 << 10) /* Guest can handle UFO in. */
  96 #define VIRTIO_NET_F_HOST_TSO4  (1 << 11) /* Host can handle TSOv4 in. */
  97 #define VIRTIO_NET_F_HOST_TSO6  (1 << 12) /* Host can handle TSOv6 in. */
  98 #define VIRTIO_NET_F_HOST_ECN   (1 << 13) /* Host can handle TSO[6] w/ ECN in */
  99 #define VIRTIO_NET_F_HOST_UFO   (1 << 14) /* Host can handle UFO in. */
 100 #define VIRTIO_NET_F_MRG_RXBUF  (1 << 15) /* Host can merge receive buffers. */
 101 #define VIRTIO_NET_F_STATUS     (1 << 16) /* Config.status available */
 102 #define VIRTIO_NET_F_CTRL_VQ    (1 << 17) /* Control channel available */
 103 #define VIRTIO_NET_F_CTRL_RX    (1 << 18) /* Control channel RX mode support */
 104 #define VIRTIO_NET_F_CTRL_VLAN  (1 << 19) /* Control channel VLAN filtering */
 105 #define VIRTIO_NET_F_CTRL_RX_EXTRA (1 << 20) /* Extra RX mode control support */
 106 





















 107 /* Status */
 108 #define VIRTIO_NET_S_LINK_UP    1
 109 

 110 /* Packet header structure */
 111 struct virtio_net_hdr {
 112         uint8_t         flags;
 113         uint8_t         gso_type;
 114         uint16_t        hdr_len;
 115         uint16_t        gso_size;
 116         uint16_t        csum_start;
 117         uint16_t        csum_offset;
 118 };

 119 
 120 #define VIRTIO_NET_HDR_F_NEEDS_CSUM     1 /* flags */
 121 #define VIRTIO_NET_HDR_GSO_NONE         0 /* gso_type */
 122 #define VIRTIO_NET_HDR_GSO_TCPV4        1 /* gso_type */
 123 #define VIRTIO_NET_HDR_GSO_UDP          3 /* gso_type */
 124 #define VIRTIO_NET_HDR_GSO_TCPV6        4 /* gso_type */
 125 #define VIRTIO_NET_HDR_GSO_ECN          0x80 /* gso_type, |'ed */
 126 
 127 
 128 /* Control virtqueue */

 129 struct virtio_net_ctrl_cmd {
 130         uint8_t class;
 131         uint8_t command;
 132 } __packed;

 133 
 134 #define VIRTIO_NET_CTRL_RX              0
 135 #define VIRTIO_NET_CTRL_RX_PROMISC      0
 136 #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
 137 
 138 #define VIRTIO_NET_CTRL_MAC             1
 139 #define VIRTIO_NET_CTRL_MAC_TABLE_SET   0
 140 
 141 #define VIRTIO_NET_CTRL_VLAN            2
 142 #define VIRTIO_NET_CTRL_VLAN_ADD        0
 143 #define VIRTIO_NET_CTRL_VLAN_DEL        1
 144 

 145 struct virtio_net_ctrl_status {
 146         uint8_t ack;
 147 } __packed;
 148 
 149 struct virtio_net_ctrl_rx {
 150         uint8_t onoff;
 151 } __packed;
 152 
 153 struct virtio_net_ctrl_mac_tbl {
 154         uint32_t nentries;
 155         uint8_t macs[][ETHERADDRL];
 156 } __packed;
 157 
 158 struct virtio_net_ctrl_vlan {
 159         uint16_t id;
 160 } __packed;

 161 
 162 static int vioif_quiesce(dev_info_t *);
 163 static int vioif_attach(dev_info_t *, ddi_attach_cmd_t);
 164 static int vioif_detach(dev_info_t *, ddi_detach_cmd_t);
 165 
 166 DDI_DEFINE_STREAM_OPS(vioif_ops,
 167         nulldev,                /* identify */
 168         nulldev,                /* probe */
 169         vioif_attach,           /* attach */
 170         vioif_detach,           /* detach */
 171         nodev,                  /* reset */
 172         NULL,                   /* cb_ops */
 173         D_MP,                   /* bus_ops */
 174         NULL,                   /* power */
 175         vioif_quiesce           /* quiesce */
 176 );
 177 
 178 static char vioif_ident[] = "VirtIO ethernet driver";
 179 
 180 /* Standard Module linkage initialization for a Streams driver */


 827                         bcopy((char *)buf->rb_mapping.vbm_buf +
 828                             sizeof (struct virtio_net_hdr), mp->b_rptr, len);
 829                         mp->b_wptr = mp->b_rptr + len;
 830 
 831                 } else {
 832                         mp = desballoc((unsigned char *)
 833                             buf->rb_mapping.vbm_buf +
 834                             sizeof (struct virtio_net_hdr) +
 835                             VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn);
 836                         if (!mp) {
 837                                 sc->sc_norecvbuf++;
 838                                 sc->sc_ierrors++;
 839 
 840                                 virtio_free_chain(ve);
 841                                 break;
 842                         }
 843                         mp->b_wptr = mp->b_rptr + len;
 844 
 845                         atomic_inc_ulong(&sc->sc_rxloan);
 846                         /*
 847                          * Buffer loaned, we will have to allocte a new one
 848                          * for this slot.
 849                          */
 850                         sc->sc_rxbufs[ve->qe_index] = NULL;
 851                 }
 852 
 853                 /*
 854                  * virtio-net does not tell us if this packet is multicast
 855                  * or broadcast, so we have to check it.
 856                  */
 857                 if (mp->b_rptr[0] & 0x1) {
 858                         if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
 859                                 sc->sc_multircv++;
 860                         else
 861                                 sc->sc_brdcstrcv++;
 862                 }
 863 
 864                 sc->sc_rbytes += len;
 865                 sc->sc_ipackets++;
 866 
 867                 virtio_free_chain(ve);


1058                 msg_size += MBLKL(nmp);
1059 
1060         if (sc->sc_tx_tso4) {
1061                 mac_lso_get(mp, &lso_mss, &lso_flags);
1062                 lso_required = (lso_flags & HW_LSO);
1063         }
1064 
1065         ve = vq_alloc_entry(sc->sc_tx_vq);
1066 
1067         if (!ve) {
1068                 sc->sc_notxbuf++;
1069                 /* Out of free descriptors - try later. */
1070                 return (B_FALSE);
1071         }
1072         buf = &sc->sc_txbufs[ve->qe_index];
1073 
1074         /* Use the inline buffer of the first entry for the virtio_net_hdr. */
1075         (void) memset(buf->tb_inline_mapping.vbm_buf, 0,
1076             sizeof (struct virtio_net_hdr));
1077 
1078         /* LINTED E_BAD_PTR_CAST_ALIGN */
1079         net_header = (struct virtio_net_hdr *)
1080             buf->tb_inline_mapping.vbm_buf;
1081 
1082         mac_hcksum_get(mp, &csum_start, &csum_stuff, NULL,
1083             NULL, &csum_flags);
1084 
1085         /* They want us to do the TCP/UDP csum calculation. */
1086         if (csum_flags & HCK_PARTIALCKSUM) {
1087                 struct ether_header *eth_header;
1088                 int eth_hsize;
1089 
1090                 /* Did we ask for it? */
1091                 ASSERT(sc->sc_tx_csum);
1092 
1093                 /* We only asked for partial csum packets. */
1094                 ASSERT(!(csum_flags & HCK_IPV4_HDRCKSUM));
1095                 ASSERT(!(csum_flags & HCK_FULLCKSUM));
1096 
1097                 eth_header = (void *) mp->b_rptr;
1098                 if (eth_header->ether_type == htons(ETHERTYPE_VLAN)) {
1099                         eth_hsize = sizeof (struct ether_vlan_header);
1100                 } else {


1442         .mc_reserved    = NULL,         /* reserved */
1443         .mc_ioctl       = NULL,         /* mc_ioctl */
1444         .mc_getcapab    = vioif_getcapab,               /* mc_getcapab */
1445         .mc_open        = NULL,         /* mc_open */
1446         .mc_close       = NULL,         /* mc_close */
1447         .mc_setprop     = vioif_setprop,
1448         .mc_getprop     = vioif_getprop,
1449         .mc_propinfo    = vioif_propinfo,
1450 };
1451 
1452 static void
1453 vioif_show_features(struct vioif_softc *sc, const char *prefix,
1454     uint32_t features)
1455 {
1456         char buf[512];
1457         char *bufp = buf;
1458         char *bufend = buf + sizeof (buf);
1459 
1460         /* LINTED E_PTRDIFF_OVERFLOW */
1461         bufp += snprintf(bufp, bufend - bufp, prefix);
1462 
1463         /* LINTED E_PTRDIFF_OVERFLOW */
1464         bufp += virtio_show_features(features, bufp, bufend - bufp);
1465 
1466         /* LINTED E_PTRDIFF_OVERFLOW */
1467         bufp += snprintf(bufp, bufend - bufp, "Vioif ( ");
1468 
1469         if (features & VIRTIO_NET_F_CSUM)
1470                 /* LINTED E_PTRDIFF_OVERFLOW */
1471                 bufp += snprintf(bufp, bufend - bufp, "CSUM ");
1472         if (features & VIRTIO_NET_F_GUEST_CSUM)
1473                 /* LINTED E_PTRDIFF_OVERFLOW */
1474                 bufp += snprintf(bufp, bufend - bufp, "GUEST_CSUM ");
1475         if (features & VIRTIO_NET_F_MAC)
1476                 /* LINTED E_PTRDIFF_OVERFLOW */
1477                 bufp += snprintf(bufp, bufend - bufp, "MAC ");
1478         if (features & VIRTIO_NET_F_GSO)
1479                 /* LINTED E_PTRDIFF_OVERFLOW */
1480                 bufp += snprintf(bufp, bufend - bufp, "GSO ");
1481         if (features & VIRTIO_NET_F_GUEST_TSO4)
1482                 /* LINTED E_PTRDIFF_OVERFLOW */
1483                 bufp += snprintf(bufp, bufend - bufp, "GUEST_TSO4 ");
1484         if (features & VIRTIO_NET_F_GUEST_TSO6)
1485                 /* LINTED E_PTRDIFF_OVERFLOW */
1486                 bufp += snprintf(bufp, bufend - bufp, "GUEST_TSO6 ");
1487         if (features & VIRTIO_NET_F_GUEST_ECN)
1488                 /* LINTED E_PTRDIFF_OVERFLOW */
1489                 bufp += snprintf(bufp, bufend - bufp, "GUEST_ECN ");
1490         if (features & VIRTIO_NET_F_GUEST_UFO)
1491                 /* LINTED E_PTRDIFF_OVERFLOW */
1492                 bufp += snprintf(bufp, bufend - bufp, "GUEST_UFO ");
1493         if (features & VIRTIO_NET_F_HOST_TSO4)
1494                 /* LINTED E_PTRDIFF_OVERFLOW */
1495                 bufp += snprintf(bufp, bufend - bufp, "HOST_TSO4 ");
1496         if (features & VIRTIO_NET_F_HOST_TSO6)
1497                 /* LINTED E_PTRDIFF_OVERFLOW */
1498                 bufp += snprintf(bufp, bufend - bufp, "HOST_TSO6 ");
1499         if (features & VIRTIO_NET_F_HOST_ECN)
1500                 /* LINTED E_PTRDIFF_OVERFLOW */
1501                 bufp += snprintf(bufp, bufend - bufp, "HOST_ECN ");
1502         if (features & VIRTIO_NET_F_HOST_UFO)
1503                 /* LINTED E_PTRDIFF_OVERFLOW */
1504                 bufp += snprintf(bufp, bufend - bufp, "HOST_UFO ");
1505         if (features & VIRTIO_NET_F_MRG_RXBUF)
1506                 /* LINTED E_PTRDIFF_OVERFLOW */
1507                 bufp += snprintf(bufp, bufend - bufp, "MRG_RXBUF ");
1508         if (features & VIRTIO_NET_F_STATUS)
1509                 /* LINTED E_PTRDIFF_OVERFLOW */
1510                 bufp += snprintf(bufp, bufend - bufp, "STATUS ");
1511         if (features & VIRTIO_NET_F_CTRL_VQ)
1512                 /* LINTED E_PTRDIFF_OVERFLOW */
1513                 bufp += snprintf(bufp, bufend - bufp, "CTRL_VQ ");
1514         if (features & VIRTIO_NET_F_CTRL_RX)
1515                 /* LINTED E_PTRDIFF_OVERFLOW */
1516                 bufp += snprintf(bufp, bufend - bufp, "CTRL_RX ");
1517         if (features & VIRTIO_NET_F_CTRL_VLAN)
1518                 /* LINTED E_PTRDIFF_OVERFLOW */
1519                 bufp += snprintf(bufp, bufend - bufp, "CTRL_VLAN ");
1520         if (features & VIRTIO_NET_F_CTRL_RX_EXTRA)
1521                 /* LINTED E_PTRDIFF_OVERFLOW */
1522                 bufp += snprintf(bufp, bufend - bufp, "CTRL_RX_EXTRA ");
1523 
1524         /* LINTED E_PTRDIFF_OVERFLOW */
1525         bufp += snprintf(bufp, bufend - bufp, ")");
1526         *bufp = '\0';
1527 
1528         dev_err(sc->sc_dev, CE_NOTE, "%s", buf);



1529 }
1530 
1531 /*
1532  * Find out which features are supported by the device and
1533  * choose which ones we wish to use.
1534  */
1535 static int
1536 vioif_dev_features(struct vioif_softc *sc)
1537 {
1538         uint32_t host_features;
1539 
1540         host_features = virtio_negotiate_features(&sc->sc_virtio,
1541             VIRTIO_NET_F_CSUM |
1542             VIRTIO_NET_F_HOST_TSO4 |
1543             VIRTIO_NET_F_HOST_ECN |
1544             VIRTIO_NET_F_MAC |
1545             VIRTIO_NET_F_STATUS |
1546             VIRTIO_F_RING_INDIRECT_DESC |
1547             VIRTIO_F_NOTIFY_ON_EMPTY);
1548 


1687         }
1688 }
1689 
1690 static int
1691 vioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1692 {
1693         int ret, instance;
1694         struct vioif_softc *sc;
1695         struct virtio_softc *vsc;
1696         mac_register_t *macp;
1697         char cache_name[CACHE_NAME_SIZE];
1698 
1699         instance = ddi_get_instance(devinfo);
1700 
1701         switch (cmd) {
1702         case DDI_ATTACH:
1703                 break;
1704 
1705         case DDI_RESUME:
1706         case DDI_PM_RESUME:
1707                 /* not supported yet */
1708                 goto exit;
1709 
1710         default:
1711                 /* unrecognized command */
1712                 goto exit;
1713         }
1714 
1715         sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP);
1716         ddi_set_driver_private(devinfo, sc);
1717 
1718         vsc = &sc->sc_virtio;
1719 
1720         /* Duplicate for less typing */
1721         sc->sc_dev = devinfo;
1722         vsc->sc_dev = devinfo;
1723 
1724         /*
1725          * Initialize interrupt kstat.
1726          */
1727         sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller",
1728             KSTAT_TYPE_INTR, 1, 0);
1729         if (sc->sc_intrstat == NULL) {
1730                 dev_err(devinfo, CE_WARN, "kstat_create failed");
1731                 goto exit_intrstat;


1870 exit_map:
1871         kstat_delete(sc->sc_intrstat);
1872         kmem_free(sc, sizeof (struct vioif_softc));
1873 exit:
1874         return (DDI_FAILURE);
1875 }
1876 
1877 static int
1878 vioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1879 {
1880         struct vioif_softc *sc;
1881 
1882         if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1883                 return (DDI_FAILURE);
1884 
1885         switch (cmd) {
1886         case DDI_DETACH:
1887                 break;
1888 
1889         case DDI_PM_SUSPEND:
1890                 /* not supported yet */
1891                 return (DDI_FAILURE);
1892 
1893         default:
1894                 /* unrecognized command */
1895                 return (DDI_FAILURE);
1896         }
1897 
1898         if (sc->sc_rxloan) {
1899                 cmn_err(CE_NOTE, "Some rx buffers are still upstream, "
1900                     "Not detaching");
1901                 return (DDI_FAILURE);
1902         }
1903 
1904         virtio_stop_vq_intr(sc->sc_rx_vq);
1905         virtio_stop_vq_intr(sc->sc_tx_vq);
1906 
1907         virtio_release_ints(&sc->sc_virtio);
1908 
1909         if (mac_unregister(sc->sc_mac_handle)) {
1910                 return (DDI_FAILURE);
1911         }
1912 
1913         mac_free(sc->sc_macp);
1914 
1915         vioif_free_mems(sc);
1916         virtio_free_vq(sc->sc_rx_vq);
1917         virtio_free_vq(sc->sc_tx_vq);
1918 
1919         virtio_device_reset(&sc->sc_virtio);
1920 




  38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41  */
  42 
  43 #include <sys/types.h>
  44 #include <sys/errno.h>
  45 #include <sys/param.h>
  46 #include <sys/stropts.h>
  47 #include <sys/stream.h>
  48 #include <sys/strsubr.h>
  49 #include <sys/kmem.h>
  50 #include <sys/conf.h>
  51 #include <sys/devops.h>
  52 #include <sys/ksynch.h>
  53 #include <sys/stat.h>
  54 #include <sys/modctl.h>
  55 #include <sys/debug.h>
  56 #include <sys/pci.h>
  57 #include <sys/ethernet.h>
  58 #include <sys/vlan.h>
  59 


  60 #include <sys/dlpi.h>
  61 #include <sys/taskq.h>
  62 #include <sys/cyclic.h>
  63 
  64 #include <sys/pattr.h>
  65 #include <sys/strsun.h>
  66 
  67 #include <sys/random.h>
  68 #include <sys/sysmacros.h>
  69 #include <sys/stream.h>
  70 
  71 #include <sys/mac.h>
  72 #include <sys/mac_provider.h>
  73 #include <sys/mac_ether.h>
  74 
  75 #include "virtiovar.h"
  76 #include "virtioreg.h"
  77 




  78 /* Configuration registers */
  79 #define VIRTIO_NET_CONFIG_MAC           0 /* 8bit x 6byte */
  80 #define VIRTIO_NET_CONFIG_STATUS        6 /* 16bit */
  81 
  82 /* Feature bits */
  83 #define VIRTIO_NET_F_CSUM       (1 << 0) /* Host handles pkts w/ partial csum */
  84 #define VIRTIO_NET_F_GUEST_CSUM (1 << 1) /* Guest handles pkts w/ part csum */
  85 #define VIRTIO_NET_F_MAC        (1 << 5) /* Host has given MAC address. */
  86 #define VIRTIO_NET_F_GSO        (1 << 6) /* Host handles pkts w/ any GSO type */
  87 #define VIRTIO_NET_F_GUEST_TSO4 (1 << 7) /* Guest can handle TSOv4 in. */
  88 #define VIRTIO_NET_F_GUEST_TSO6 (1 << 8) /* Guest can handle TSOv6 in. */
  89 #define VIRTIO_NET_F_GUEST_ECN  (1 << 9) /* Guest can handle TSO[6] w/ ECN in */
  90 #define VIRTIO_NET_F_GUEST_UFO  (1 << 10) /* Guest can handle UFO in. */
  91 #define VIRTIO_NET_F_HOST_TSO4  (1 << 11) /* Host can handle TSOv4 in. */
  92 #define VIRTIO_NET_F_HOST_TSO6  (1 << 12) /* Host can handle TSOv6 in. */
  93 #define VIRTIO_NET_F_HOST_ECN   (1 << 13) /* Host can handle TSO[6] w/ ECN in */
  94 #define VIRTIO_NET_F_HOST_UFO   (1 << 14) /* Host can handle UFO in. */
  95 #define VIRTIO_NET_F_MRG_RXBUF  (1 << 15) /* Host can merge receive buffers. */
  96 #define VIRTIO_NET_F_STATUS     (1 << 16) /* Config.status available */
  97 #define VIRTIO_NET_F_CTRL_VQ    (1 << 17) /* Control channel available */
  98 #define VIRTIO_NET_F_CTRL_RX    (1 << 18) /* Control channel RX mode support */
  99 #define VIRTIO_NET_F_CTRL_VLAN  (1 << 19) /* Control channel VLAN filtering */
 100 #define VIRTIO_NET_F_CTRL_RX_EXTRA (1 << 20) /* Extra RX mode control support */
 101 
 102 #define VIRTIO_NET_FEATURE_BITS \
 103         "\020" \
 104         "\1CSUM" \
 105         "\2GUEST_CSUM" \
 106         "\6MAC" \
 107         "\7GSO" \
 108         "\10GUEST_TSO4" \
 109         "\11GUEST_TSO6" \
 110         "\12GUEST_ECN" \
 111         "\13GUEST_UFO" \
 112         "\14HOST_TSO4" \
 113         "\15HOST_TSO6" \
 114         "\16HOST_ECN" \
 115         "\17HOST_UFO" \
 116         "\20MRG_RXBUF" \
 117         "\21STATUS" \
 118         "\22CTRL_VQ" \
 119         "\23CTRL_RX" \
 120         "\24CTRL_VLAN" \
 121         "\25CTRL_RX_EXTRA"
 122 
 123 /* Status */
 124 #define VIRTIO_NET_S_LINK_UP    1
 125 
 126 #pragma pack(1)
 127 /* Packet header structure */
 128 struct virtio_net_hdr {
 129         uint8_t         flags;
 130         uint8_t         gso_type;
 131         uint16_t        hdr_len;
 132         uint16_t        gso_size;
 133         uint16_t        csum_start;
 134         uint16_t        csum_offset;
 135 };
 136 #pragma pack()
 137 
 138 #define VIRTIO_NET_HDR_F_NEEDS_CSUM     1 /* flags */
 139 #define VIRTIO_NET_HDR_GSO_NONE         0 /* gso_type */
 140 #define VIRTIO_NET_HDR_GSO_TCPV4        1 /* gso_type */
 141 #define VIRTIO_NET_HDR_GSO_UDP          3 /* gso_type */
 142 #define VIRTIO_NET_HDR_GSO_TCPV6        4 /* gso_type */
 143 #define VIRTIO_NET_HDR_GSO_ECN          0x80 /* gso_type, |'ed */
 144 
 145 
 146 /* Control virtqueue */
 147 #pragma pack(1)
 148 struct virtio_net_ctrl_cmd {
 149         uint8_t class;
 150         uint8_t command;
 151 };
 152 #pragma pack()
 153 
 154 #define VIRTIO_NET_CTRL_RX              0
 155 #define VIRTIO_NET_CTRL_RX_PROMISC      0
 156 #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
 157 
 158 #define VIRTIO_NET_CTRL_MAC             1
 159 #define VIRTIO_NET_CTRL_MAC_TABLE_SET   0
 160 
 161 #define VIRTIO_NET_CTRL_VLAN            2
 162 #define VIRTIO_NET_CTRL_VLAN_ADD        0
 163 #define VIRTIO_NET_CTRL_VLAN_DEL        1
 164 
 165 #pragma pack(1)
 166 struct virtio_net_ctrl_status {
 167         uint8_t ack;
 168 };
 169 
 170 struct virtio_net_ctrl_rx {
 171         uint8_t onoff;
 172 };
 173 
 174 struct virtio_net_ctrl_mac_tbl {
 175         uint32_t nentries;
 176         uint8_t macs[][ETHERADDRL];
 177 };
 178 
 179 struct virtio_net_ctrl_vlan {
 180         uint16_t id;
 181 };
 182 #pragma pack()
 183 
 184 static int vioif_quiesce(dev_info_t *);
 185 static int vioif_attach(dev_info_t *, ddi_attach_cmd_t);
 186 static int vioif_detach(dev_info_t *, ddi_detach_cmd_t);
 187 
 188 DDI_DEFINE_STREAM_OPS(vioif_ops,
 189         nulldev,                /* identify */
 190         nulldev,                /* probe */
 191         vioif_attach,           /* attach */
 192         vioif_detach,           /* detach */
 193         nodev,                  /* reset */
 194         NULL,                   /* cb_ops */
 195         D_MP,                   /* bus_ops */
 196         NULL,                   /* power */
 197         vioif_quiesce           /* quiesce */
 198 );
 199 
 200 static char vioif_ident[] = "VirtIO ethernet driver";
 201 
 202 /* Standard Module linkage initialization for a Streams driver */


 849                         bcopy((char *)buf->rb_mapping.vbm_buf +
 850                             sizeof (struct virtio_net_hdr), mp->b_rptr, len);
 851                         mp->b_wptr = mp->b_rptr + len;
 852 
 853                 } else {
 854                         mp = desballoc((unsigned char *)
 855                             buf->rb_mapping.vbm_buf +
 856                             sizeof (struct virtio_net_hdr) +
 857                             VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn);
 858                         if (!mp) {
 859                                 sc->sc_norecvbuf++;
 860                                 sc->sc_ierrors++;
 861 
 862                                 virtio_free_chain(ve);
 863                                 break;
 864                         }
 865                         mp->b_wptr = mp->b_rptr + len;
 866 
 867                         atomic_inc_ulong(&sc->sc_rxloan);
 868                         /*
 869                          * Buffer loaned, we will have to allocate a new one
 870                          * for this slot.
 871                          */
 872                         sc->sc_rxbufs[ve->qe_index] = NULL;
 873                 }
 874 
 875                 /*
 876                  * virtio-net does not tell us if this packet is multicast
 877                  * or broadcast, so we have to check it.
 878                  */
 879                 if (mp->b_rptr[0] & 0x1) {
 880                         if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
 881                                 sc->sc_multircv++;
 882                         else
 883                                 sc->sc_brdcstrcv++;
 884                 }
 885 
 886                 sc->sc_rbytes += len;
 887                 sc->sc_ipackets++;
 888 
 889                 virtio_free_chain(ve);


1080                 msg_size += MBLKL(nmp);
1081 
1082         if (sc->sc_tx_tso4) {
1083                 mac_lso_get(mp, &lso_mss, &lso_flags);
1084                 lso_required = (lso_flags & HW_LSO);
1085         }
1086 
1087         ve = vq_alloc_entry(sc->sc_tx_vq);
1088 
1089         if (!ve) {
1090                 sc->sc_notxbuf++;
1091                 /* Out of free descriptors - try later. */
1092                 return (B_FALSE);
1093         }
1094         buf = &sc->sc_txbufs[ve->qe_index];
1095 
1096         /* Use the inline buffer of the first entry for the virtio_net_hdr. */
1097         (void) memset(buf->tb_inline_mapping.vbm_buf, 0,
1098             sizeof (struct virtio_net_hdr));
1099 
1100         net_header = (struct virtio_net_hdr *)buf->tb_inline_mapping.vbm_buf;


1101 
1102         mac_hcksum_get(mp, &csum_start, &csum_stuff, NULL,
1103             NULL, &csum_flags);
1104 
1105         /* They want us to do the TCP/UDP csum calculation. */
1106         if (csum_flags & HCK_PARTIALCKSUM) {
1107                 struct ether_header *eth_header;
1108                 int eth_hsize;
1109 
1110                 /* Did we ask for it? */
1111                 ASSERT(sc->sc_tx_csum);
1112 
1113                 /* We only asked for partial csum packets. */
1114                 ASSERT(!(csum_flags & HCK_IPV4_HDRCKSUM));
1115                 ASSERT(!(csum_flags & HCK_FULLCKSUM));
1116 
1117                 eth_header = (void *) mp->b_rptr;
1118                 if (eth_header->ether_type == htons(ETHERTYPE_VLAN)) {
1119                         eth_hsize = sizeof (struct ether_vlan_header);
1120                 } else {


1462         .mc_reserved    = NULL,         /* reserved */
1463         .mc_ioctl       = NULL,         /* mc_ioctl */
1464         .mc_getcapab    = vioif_getcapab,               /* mc_getcapab */
1465         .mc_open        = NULL,         /* mc_open */
1466         .mc_close       = NULL,         /* mc_close */
1467         .mc_setprop     = vioif_setprop,
1468         .mc_getprop     = vioif_getprop,
1469         .mc_propinfo    = vioif_propinfo,
1470 };
1471 
1472 static void
1473 vioif_show_features(struct vioif_softc *sc, const char *prefix,
1474     uint32_t features)
1475 {
1476         char buf[512];
1477         char *bufp = buf;
1478         char *bufend = buf + sizeof (buf);
1479 
1480         /* LINTED E_PTRDIFF_OVERFLOW */
1481         bufp += snprintf(bufp, bufend - bufp, prefix);

1482         /* LINTED E_PTRDIFF_OVERFLOW */
1483         bufp += virtio_show_features(features, bufp, bufend - bufp);





























































1484         *bufp = '\0';
1485 
1486 
1487         /* Using '!' to only CE_NOTE this to the system log. */
1488         dev_err(sc->sc_dev, CE_NOTE, "!%s Vioif (%b)", buf, features,
1489             VIRTIO_NET_FEATURE_BITS);
1490 }
1491 
1492 /*
1493  * Find out which features are supported by the device and
1494  * choose which ones we wish to use.
1495  */
1496 static int
1497 vioif_dev_features(struct vioif_softc *sc)
1498 {
1499         uint32_t host_features;
1500 
1501         host_features = virtio_negotiate_features(&sc->sc_virtio,
1502             VIRTIO_NET_F_CSUM |
1503             VIRTIO_NET_F_HOST_TSO4 |
1504             VIRTIO_NET_F_HOST_ECN |
1505             VIRTIO_NET_F_MAC |
1506             VIRTIO_NET_F_STATUS |
1507             VIRTIO_F_RING_INDIRECT_DESC |
1508             VIRTIO_F_NOTIFY_ON_EMPTY);
1509 


1648         }
1649 }
1650 
1651 static int
1652 vioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1653 {
1654         int ret, instance;
1655         struct vioif_softc *sc;
1656         struct virtio_softc *vsc;
1657         mac_register_t *macp;
1658         char cache_name[CACHE_NAME_SIZE];
1659 
1660         instance = ddi_get_instance(devinfo);
1661 
1662         switch (cmd) {
1663         case DDI_ATTACH:
1664                 break;
1665 
1666         case DDI_RESUME:
1667         case DDI_PM_RESUME:
1668                 /* We do not support suspend/resume for vioif. */
1669                 goto exit;
1670 
1671         default:

1672                 goto exit;
1673         }
1674 
1675         sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP);
1676         ddi_set_driver_private(devinfo, sc);
1677 
1678         vsc = &sc->sc_virtio;
1679 
1680         /* Duplicate for less typing */
1681         sc->sc_dev = devinfo;
1682         vsc->sc_dev = devinfo;
1683 
1684         /*
1685          * Initialize interrupt kstat.
1686          */
1687         sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller",
1688             KSTAT_TYPE_INTR, 1, 0);
1689         if (sc->sc_intrstat == NULL) {
1690                 dev_err(devinfo, CE_WARN, "kstat_create failed");
1691                 goto exit_intrstat;


1830 exit_map:
1831         kstat_delete(sc->sc_intrstat);
1832         kmem_free(sc, sizeof (struct vioif_softc));
1833 exit:
1834         return (DDI_FAILURE);
1835 }
1836 
1837 static int
1838 vioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1839 {
1840         struct vioif_softc *sc;
1841 
1842         if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1843                 return (DDI_FAILURE);
1844 
1845         switch (cmd) {
1846         case DDI_DETACH:
1847                 break;
1848 
1849         case DDI_PM_SUSPEND:
1850                 /* We do not support suspend/resume for vioif. */
1851                 return (DDI_FAILURE);
1852 
1853         default:

1854                 return (DDI_FAILURE);
1855         }
1856 
1857         if (sc->sc_rxloan) {
1858                 dev_err(devinfo, CE_WARN, "!Some rx buffers are still upstream,"
1859                     " not detaching.");
1860                 return (DDI_FAILURE);
1861         }
1862 
1863         virtio_stop_vq_intr(sc->sc_rx_vq);
1864         virtio_stop_vq_intr(sc->sc_tx_vq);
1865 
1866         virtio_release_ints(&sc->sc_virtio);
1867 
1868         if (mac_unregister(sc->sc_mac_handle)) {
1869                 return (DDI_FAILURE);
1870         }
1871 
1872         mac_free(sc->sc_macp);
1873 
1874         vioif_free_mems(sc);
1875         virtio_free_vq(sc->sc_rx_vq);
1876         virtio_free_vq(sc->sc_tx_vq);
1877 
1878         virtio_device_reset(&sc->sc_virtio);
1879