50#include <sys/kernel.h>
53#include <sys/module.h>
55#include <sys/socket.h>
56#include <sys/sockio.h>
57#include <sys/sysctl.h>
60#include <net/if_var.h>
61#include <net/if_arp.h>
62#include <net/ethernet.h>
64#include <net/if_media.h>
65#include <net/if_types.h>
67#include <netinet/in.h>
68#include <netinet/ip.h>
69#include <netinet/if_ether.h>
70#include <netinet/tcp.h>
71#include <netinet/ip_icmp.h>
72#include <netinet/udp.h>
73#include <machine/in_cksum.h>
77#include <vm/vm_extern.h>
78#include <vm/vm_kern.h>
80#include <machine/_inttypes.h>
82#include <xen/xen-os.h>
83#include <xen/hypervisor.h>
84#include <xen/xen_intr.h>
85#include <contrib/xen/io/netif.h>
86#include <xen/xenbus/xenbusvar.h>
97#define XNB_GSO_TCPV4 0
105#define DPRINTF(fmt, args...) \
106 printf("xnb(%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
108#define DPRINTF(fmt, args...) do {} while (0)
112#define GNTTAB_LEN (64)
115#define XNB_CSUM_FEATURES (CSUM_TCP | CSUM_UDP)
117#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
118#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
124#define RING_HAS_UNCONSUMED_REQUESTS_2(_r, cons) ({ \
125 unsigned int req = (_r)->sring->req_prod - cons; \
126 unsigned int rsp = RING_SIZE(_r) - \
127 (cons - (_r)->rsp_prod_pvt); \
128 req < rsp ? req : rsp; \
131#define virt_to_mfn(x) (vtophys(x) >> PAGE_SHIFT)
132#define virt_to_offset(x) ((x) & (PAGE_SIZE - 1))
145 int err,
const char *fmt, ...)
153static
int xnb_send(netif_rx_back_ring_t *
rxb, domid_t otherend,
155static
int xnb_recv(netif_tx_back_ring_t *
txb, domid_t otherend,
156 struct mbuf **mbufc, struct ifnet *ifnet,
159 const netif_tx_back_ring_t *tx_ring,
162 netif_tx_back_ring_t *ring,
int error);
167 const netif_tx_back_ring_t *
txb,
168 domid_t otherend_id);
173 RING_IDX start,
int space);
175 const struct mbuf *mbufc,
177 const netif_rx_back_ring_t *
rxb,
178 domid_t otherend_id);
181 netif_rx_back_ring_t *ring);
183static
int xnb_ioctl(struct ifnet*, u_long, caddr_t);
192#if defined(INET) || defined(INET6)
193static void xnb_add_mbuf_cksum(
struct mbuf *mbufc);
251 bzero(pxnb,
sizeof(*pxnb));
272 return (! pxnb->
error);
280 DPRINTF(
"Was passed a null pointer.\n");
283 DPRINTF(
"pkt address= %p\n", pkt);
299 DPRINTF(
"netif_tx_request index =%u\n", idx);
300 DPRINTF(
"netif_tx_request.gref =%u\n", txreq->gref);
301 DPRINTF(
"netif_tx_request.offset=%hu\n", txreq->offset);
302 DPRINTF(
"netif_tx_request.flags =%hu\n", txreq->flags);
303 DPRINTF(
"netif_tx_request.id =%hu\n", txreq->id);
304 DPRINTF(
"netif_tx_request.size =%hu\n", txreq->size);
405 uint8_t
mac[ETHER_ADDR_LEN];
516 printf(
"NULL grant table pointer\n");
520 if (entry->flags & GNTCOPY_dest_gref)
521 printf(
"gnttab dest ref=\t%u\n", entry->dest.u.ref);
523 printf(
"gnttab dest gmfn=\t%"PRI_xen_pfn
"\n",
525 printf(
"gnttab dest offset=\t%hu\n", entry->dest.offset);
526 printf(
"gnttab dest domid=\t%hu\n", entry->dest.domid);
527 if (entry->flags & GNTCOPY_source_gref)
528 printf(
"gnttab source ref=\t%u\n", entry->source.u.ref);
530 printf(
"gnttab source gmfn=\t%"PRI_xen_pfn
"\n",
531 entry->source.u.gmfn);
532 printf(
"gnttab source offset=\t%hu\n", entry->source.offset);
533 printf(
"gnttab source domid=\t%hu\n", entry->source.domid);
534 printf(
"gnttab len=\t%hu\n", entry->len);
535 printf(
"gnttab flags=\t%hu\n", entry->flags);
536 printf(
"gnttab status=\t%hd\n", entry->status);
542 static char results[720];
544 netif_rx_back_ring_t
const*
rxb =
546 netif_tx_back_ring_t
const*
txb =
553 return (SYSCTL_OUT(req, results, strnlen(results, 720)));
555 snprintf(results, 720,
564 "\t%16s %18d %18d\n",
566 "req_cons",
txb->req_cons,
rxb->req_cons,
567 "nr_ents",
txb->nr_ents,
rxb->nr_ents,
568 "rsp_prod_pvt",
txb->rsp_prod_pvt,
rxb->rsp_prod_pvt,
569 "sring",
txb->sring,
rxb->sring,
570 "sring->req_prod",
txb->sring->req_prod,
rxb->sring->req_prod,
571 "sring->req_event",
txb->sring->req_event,
rxb->sring->req_event,
572 "sring->rsp_prod",
txb->sring->rsp_prod,
rxb->sring->rsp_prod,
573 "sring->rsp_event",
txb->sring->rsp_event,
rxb->sring->rsp_event);
575 return (SYSCTL_OUT(req, results, strnlen(results, 720)));
586 printf(
"xnb_dump_mbuf:\n");
587 if (m->m_flags & M_PKTHDR) {
588 printf(
" flowid=%10d, csum_flags=%#8x, csum_data=%#8x, "
590 m->m_pkthdr.flowid, (
int)m->m_pkthdr.csum_flags,
591 m->m_pkthdr.csum_data, m->m_pkthdr.tso_segsz);
592 printf(
" rcvif=%16p, len=%19d\n",
593 m->m_pkthdr.rcvif, m->m_pkthdr.len);
595 printf(
" m_next=%16p, m_nextpk=%16p, m_data=%16p\n",
596 m->m_next, m->m_nextpkt, m->m_data);
597 printf(
" m_len=%17d, m_flags=%#15x, m_type=%18u\n",
598 m->m_len, m->m_flags, m->m_type);
601 d = mtod(m, uint8_t*);
605 for (i = 0; (i < 16) && (len > 0); i++, len--) {
606 printf(
"%02hhx ", *(d++));
642 int error __diagused;
661 if (xnb->
bridge != NULL) {
662 free(xnb->
bridge, M_XENSTORE);
672 error = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, gnts,
674 KASSERT(error == 0, (
"Grant table unmap op failed (%d)", error));
686 xnb->
flags &= ~XNBF_RING_CONNECTED;
703 struct gnttab_map_grant_ref gnt;
708 ring->
va = xnb->
kva + ring_type * PAGE_SIZE;
712 gnt.flags = GNTMAP_host_map;
716 error = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &gnt, 1);
718 panic(
"netback: Ring page grant table op failed (%d)", error);
720 if (gnt.status != 0) {
723 xenbus_dev_fatal(xnb->
dev, error,
724 "Ring shared page mapping failed. "
725 "Status %d.", gnt.status);
727 ring->
handle = gnt.handle;
732 (netif_tx_sring_t*)ring->
va,
736 (netif_rx_sring_t*)ring->
va,
739 xenbus_dev_fatal(xnb->
dev, error,
740 "Unknown ring type %d", ring_type);
774 error = xen_intr_bind_remote_port(xnb->
dev,
779 INTR_TYPE_NET | INTR_MPSAFE,
783 xenbus_dev_fatal(xnb->
dev, error,
"binding event channel");
844 const char *otherend_path;
845 const char *our_path;
847 unsigned int rx_copy, bridge_len;
848 uint8_t no_csum_offload;
850 otherend_path = xenbus_get_otherend_path(xnb->
dev);
851 our_path = xenbus_get_node(xnb->
dev);
855 "tx-ring-ref",
"%l" PRIu32,
857 "rx-ring-ref",
"%l" PRIu32,
859 "event-channel",
"%" PRIu32, &xnb->
evtchn,
862 xenbus_dev_fatal(xnb->
dev, err,
863 "Unable to retrieve ring information from "
864 "frontend %s. Unable to connect.",
870 err =
xs_scanf(XST_NIL, our_path,
"handle", NULL,
"%li", &xnb->
handle);
872 xenbus_dev_fatal(xnb->
dev, err,
873 "Error reading handle from frontend %s. "
874 "Unable to connect.", otherend_path);
881 err =
xs_read(XST_NIL, our_path,
"bridge", &bridge_len,
890 err =
xs_scanf(XST_NIL, otherend_path,
"request-rx-copy", NULL,
891 "%" PRIu32, &rx_copy);
897 xenbus_dev_fatal(xnb->
dev, err,
"reading %s/request-rx-copy",
912 if (
xs_scanf(XST_NIL, otherend_path,
"feature-sg", NULL,
913 "%hhu", &xnb->
can_sg) < 0)
917 if (
xs_scanf(XST_NIL, otherend_path,
"feature-gso-tcpv4", NULL,
918 "%hhu", &xnb->
gso) < 0)
921 if (
xs_scanf(XST_NIL, otherend_path,
"feature-gso-tcpv4-prefix", NULL,
925 if (
xs_scanf(XST_NIL, otherend_path,
"feature-no-csum-offload", NULL,
926 "%hhu", &no_csum_offload) < 0)
928 xnb->
ip_csum = (no_csum_offload == 0);
942 struct xs_transaction xst;
943 const char *our_path;
946 our_path = xenbus_get_node(xnb->
dev);
951 xenbus_dev_fatal(xnb->
dev, error,
952 "Error publishing backend info "
953 "(start transaction)");
957 error =
xs_printf(xst, our_path,
"feature-sg",
962 error =
xs_printf(xst, our_path,
"feature-gso-tcpv4",
967 error =
xs_printf(xst, our_path,
"feature-rx-copy",
972 error =
xs_printf(xst, our_path,
"feature-rx-flip",
978 if (error != 0 && error != EAGAIN) {
979 xenbus_dev_fatal(xnb->
dev, error,
"ending transaction");
983 }
while (error == EAGAIN);
999 if (xenbus_get_state(xnb->
dev) == XenbusStateConnected)
1005 xnb->
flags &= ~XNBF_SHUTDOWN;
1012 xenbus_dev_fatal(xnb->
dev, error,
1013 "Unable to allocate communication memory");
1028 xenbus_set_state(xnb->
dev, XenbusStateConnected);
1069 if (xenbus_get_state(xnb->
dev) < XenbusStateClosing)
1070 xenbus_set_state(xnb->
dev, XenbusStateClosing);
1073 xnb->
flags &= ~XNBF_IN_SHUTDOWN;
1096 va_copy(ap_hotplug, ap);
1098 "hotplug-error", fmt, ap_hotplug);
1101 "hotplug-status",
"error");
1103 xenbus_dev_vfatal(xnb->
dev, err, fmt, ap);
1106 (void)
xs_printf(XST_NIL, xenbus_get_node(xnb->
dev),
"online",
"0");
1121 if (!strcmp(xenbus_get_type(dev),
"vif")) {
1122 DPRINTF(
"Claiming device %d, %s\n", device_get_unit(dev),
1123 devclass_get_name(device_get_devclass(dev)));
1124 device_set_desc(dev,
"Backend Virtual Network Device");
1140 struct sysctl_ctx_list *sysctl_ctx = NULL;
1141 struct sysctl_oid *sysctl_tree = NULL;
1143 sysctl_ctx = device_get_sysctl_ctx(xnb->
dev);
1144 if (sysctl_ctx == NULL)
1147 sysctl_tree = device_get_sysctl_tree(xnb->
dev);
1148 if (sysctl_tree == NULL)
1152 SYSCTL_ADD_PROC(sysctl_ctx,
1153 SYSCTL_CHILDREN(sysctl_tree),
1155 "unit_test_results",
1156 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
1161 "Results of builtin unit tests");
1163 SYSCTL_ADD_PROC(sysctl_ctx,
1164 SYSCTL_CHILDREN(sysctl_tree),
1167 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
1172 "Xennet Back Rings");
1188 xnb = device_get_softc(
dev);
1189 mtx_init(&xnb->
sc_lock,
"xnb_softc",
"xen netback softc lock", MTX_DEF);
1190 mtx_init(&xnb->
tx_lock,
"xnb_tx",
"xen netback tx lock", MTX_DEF);
1191 mtx_init(&xnb->
rx_lock,
"xnb_rx",
"xen netback rx lock", MTX_DEF);
1196 ifmedia_add(&xnb->
sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
1197 ifmedia_set(&xnb->
sc_media, IFM_ETHER|IFM_MANUAL);
1209 bzero(&xnb->
mac[0],
sizeof(xnb->
mac));
1217 err =
xs_scanf(XST_NIL, xenbus_get_node(xnb->
dev),
"handle", NULL,
1221 snprintf(xnb->
if_name, IFNAMSIZ,
"xnb%" PRIu16
".%" PRIu32,
1227 ifp->if_softc = xnb;
1228 if_initname(
ifp, xnb->
if_name, IF_DUNIT_NONE);
1229 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1233 ifp->if_mtu = ETHERMTU;
1237 ifp->if_capabilities = IFCAP_HWCSUM;
1238 ifp->if_capenable = IFCAP_HWCSUM;
1240 ether_ifattach(
ifp, xnb->
mac);
1263 xenbus_dev_fatal(
dev, error,
"creating netdev");
1267 DPRINTF(
"Attaching to %s\n", xenbus_get_node(
dev));
1274 xnb = device_get_softc(
dev);
1287 "hotplug-status",
"connected");
1290 xenbus_get_node(xnb->
dev));
1301 "Publishing backend status for %s",
1302 xenbus_get_node(xnb->
dev));
1307 xenbus_set_state(
dev, XenbusStateInitWait);
1332 xnb = device_get_softc(
dev);
1387 xnb = device_get_softc(
dev);
1389 DPRINTF(
"frontend_state=%s, xnb_state=%s\n",
1390 xenbus_strstate(frontend_state),
1391 xenbus_strstate(xenbus_get_state(xnb->
dev)));
1393 switch (frontend_state) {
1394 case XenbusStateInitialising:
1395 case XenbusStateInitialised:
1397 case XenbusStateConnected:
1400 case XenbusStateClosing:
1401 case XenbusStateClosed:
1405 if (frontend_state == XenbusStateClosed)
1406 xenbus_set_state(xnb->
dev, XenbusStateClosed);
1409 xenbus_dev_fatal(xnb->
dev, EINVAL,
"saw state %d at frontend",
1429 netif_tx_back_ring_t *
txb;
1430 RING_IDX req_prod_local;
1439 req_prod_local =
txb->sring->req_prod;
1448 if (err || (mbufc == NULL))
1455 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(
txb,
notify);
1459 txb->sring->req_event =
txb->req_cons + 1;
1461 }
while (
txb->sring->req_prod != req_prod_local) ;
1492 uint16_t cdr_size = 0;
1498 netif_tx_request_t *tx = RING_GET_REQUEST(tx_ring, idx);
1499 pkt->
size = tx->size;
1500 pkt->
flags = tx->flags & ~NETTXF_more_data;
1501 more_data = tx->flags & NETTXF_more_data;
1508 if ((pkt->
flags & NETTXF_extra_info) &&
1510 netif_extra_info_t *ext =
1511 (netif_extra_info_t*) RING_GET_REQUEST(tx_ring, idx);
1512 pkt->
extra.type = ext->type;
1513 switch (pkt->
extra.type) {
1514 case XEN_NETIF_EXTRA_TYPE_GSO:
1515 pkt->
extra.u.gso = ext->u.gso;
1524 printf(
"xnb(%s:%d): Unknown extra info type %d."
1525 " Discarding packet\n",
1526 __func__, __LINE__, pkt->
extra.type);
1535 pkt->
extra.flags = ext->flags;
1536 if (ext->flags & XEN_NETIF_EXTRA_FLAG_MORE) {
1542 printf(
"xnb(%s:%d): Request sets "
1543 "XEN_NETIF_EXTRA_FLAG_MORE, but we can't handle "
1544 "that\n", __func__, __LINE__);
1558 netif_tx_request_t *tx = RING_GET_REQUEST(tx_ring, idx);
1560 cdr_size += tx->size;
1561 if (tx->flags & ~NETTXF_more_data) {
1563 printf(
"xnb(%s:%d): Request sets unknown flags %d "
1564 "after the 1st request in the packet.\n",
1565 __func__, __LINE__, tx->flags);
1570 more_data = tx->flags & NETTXF_more_data;
1575 if (more_data != 0) {
1610 netif_tx_request_t *tx;
1611 netif_tx_response_t *rsp;
1616 NETIF_RSP_ERROR : NETIF_RSP_OKAY;
1617 KASSERT((pkt->
list_len == 0) || (ring->rsp_prod_pvt == pkt->
car),
1618 (
"Cannot respond to ring requests out of order"));
1622 tx = RING_GET_REQUEST(ring, ring->rsp_prod_pvt);
1624 rsp = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt);
1626 rsp->status = status;
1627 ring->rsp_prod_pvt++;
1629 if (pkt->
flags & NETRXF_extra_info) {
1630 rsp = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt);
1631 rsp->status = NETIF_RSP_NULL;
1632 ring->rsp_prod_pvt++;
1636 for (i=0; i < pkt->
list_len - 1; i++) {
1638 tx = RING_GET_REQUEST(ring, ring->rsp_prod_pvt);
1640 rsp = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt);
1642 rsp->status = status;
1643 ring->rsp_prod_pvt++;
1665 m = m_getm(NULL, pkt->
size, M_NOWAIT, MT_DATA);
1668 m->m_pkthdr.rcvif =
ifp;
1669 if (pkt->
flags & NETTXF_data_validated) {
1675 m->m_pkthdr.csum_flags = (
1681 m->m_pkthdr.csum_data = 0xffff;
1702 domid_t otherend_id)
1705 struct mbuf *mbuf = mbufc;
1707 RING_IDX r_idx = pkt->
car;
1711 uint16_t size_remaining = pkt->
size;
1713 while (size_remaining > 0) {
1714 const netif_tx_request_t *txq = RING_GET_REQUEST(
txb, r_idx);
1715 const size_t mbuf_space = M_TRAILINGSPACE(mbuf) - m_ofs;
1716 const size_t req_size =
1718 const size_t pkt_space = req_size - r_ofs;
1723 const size_t space = MIN(pkt_space, mbuf_space);
1726 KASSERT(gnt_idx <
GNTTAB_LEN, (
"Grant table is too short"));
1728 gnttab[gnt_idx].source.u.ref = txq->gref;
1729 gnttab[gnt_idx].source.domid = otherend_id;
1730 gnttab[gnt_idx].source.offset = txq->offset + r_ofs;
1732 mtod(mbuf, vm_offset_t) + m_ofs);
1734 mtod(mbuf, vm_offset_t) + m_ofs);
1735 gnttab[gnt_idx].dest.domid = DOMID_SELF;
1736 gnttab[gnt_idx].len = space;
1737 gnttab[gnt_idx].flags = GNTCOPY_source_gref;
1742 size_remaining -= space;
1743 if (req_size - r_ofs <= 0) {
1746 r_idx = (r_idx == pkt->
car) ? pkt->
cdr : r_idx + 1;
1748 if (M_TRAILINGSPACE(mbuf) - m_ofs <= 0) {
1751 mbuf = mbuf->m_next;
1770 struct mbuf *mbuf = mbufc;
1772 size_t total_size = 0;
1774 for (i = 0; i < n_entries; i++) {
1775 KASSERT(
gnttab[i].status == GNTST_okay,
1776 (
"Some gnttab_copy entry had error status %hd\n",
1779 mbuf->m_len +=
gnttab[i].len;
1780 total_size +=
gnttab[i].len;
1781 if (M_TRAILINGSPACE(mbuf) <= 0) {
1782 mbuf = mbuf->m_next;
1785 mbufc->m_pkthdr.len = total_size;
1787#if defined(INET) || defined(INET6)
1788 xnb_add_mbuf_cksum(mbufc);
1807xnb_recv(netif_tx_back_ring_t *
txb, domid_t otherend,
struct mbuf **mbufc,
1817 if (num_consumed == 0)
1821 if_inc_counter(ifnet, IFCOUNTER_IPACKETS, 1);
1830 txb->req_cons += num_consumed;
1831 DPRINTF(
"xnb_intr: garbage packet, num_consumed=%d\n",
1833 if_inc_counter(ifnet, IFCOUNTER_IERRORS, 1);
1839 if (*mbufc == NULL) {
1845 DPRINTF(
"xnb_intr: Couldn't allocate mbufs, num_consumed=%d\n",
1847 if_inc_counter(ifnet, IFCOUNTER_IQDROPS, 1);
1854 int __unused hv_ret = HYPERVISOR_grant_table_op(GNTTABOP_copy,
1856 KASSERT(hv_ret == 0,
1857 (
"HYPERVISOR_grant_table_op returned %d\n", hv_ret));
1862 txb->req_cons += num_consumed;
1880 RING_IDX start,
int space)
1885 if ((mbufc == NULL) ||
1886 ( (mbufc->m_flags & M_PKTHDR) == 0) ||
1887 (mbufc->m_pkthdr.len == 0)) {
1895 pkt->
size = mbufc->m_pkthdr.len;
1899 if (mbufc->m_pkthdr.csum_flags & CSUM_TSO) {
1900 pkt->
flags |= NETRXF_extra_info;
1901 pkt->
extra.u.gso.size = mbufc->m_pkthdr.tso_segsz;
1902 pkt->
extra.u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
1903 pkt->
extra.u.gso.pad = 0;
1904 pkt->
extra.u.gso.features = 0;
1905 pkt->
extra.type = XEN_NETIF_EXTRA_TYPE_GSO;
1906 pkt->
extra.flags = 0;
1907 pkt->
cdr = start + 2;
1909 pkt->
cdr = start + 1;
1911 if (mbufc->m_pkthdr.csum_flags & (CSUM_TSO | CSUM_DELAY_DATA)) {
1913 (NETRXF_csum_blank | NETRXF_data_validated);
1925 pkt->
flags |= NETRXF_more_data;
1929 (pkt->
flags & NETRXF_extra_info ? 1 : 0);
1930 if (slots_required > space) {
1954 domid_t otherend_id)
1957 const struct mbuf *mbuf = mbufc;
1959 RING_IDX r_idx = pkt->
car;
1963 uint16_t size_remaining;
1967 while (size_remaining > 0) {
1968 const netif_rx_request_t *rxq = RING_GET_REQUEST(
rxb, r_idx);
1969 const size_t mbuf_space = mbuf->m_len - m_ofs;
1971 const size_t req_size = PAGE_SIZE;
1972 const size_t pkt_space = req_size - r_ofs;
1977 const size_t space = MIN(pkt_space, mbuf_space);
1980 KASSERT(gnt_idx <
GNTTAB_LEN, (
"Grant table is too short"));
1982 gnttab[gnt_idx].dest.u.ref = rxq->gref;
1983 gnttab[gnt_idx].dest.domid = otherend_id;
1984 gnttab[gnt_idx].dest.offset = r_ofs;
1986 mtod(mbuf, vm_offset_t) + m_ofs);
1988 mtod(mbuf, vm_offset_t) + m_ofs);
1989 gnttab[gnt_idx].source.domid = DOMID_SELF;
1990 gnttab[gnt_idx].len = space;
1991 gnttab[gnt_idx].flags = GNTCOPY_dest_gref;
1997 size_remaining -= space;
1998 if (req_size - r_ofs <= 0) {
2001 r_idx = (r_idx == pkt->
car) ? pkt->
cdr : r_idx + 1;
2003 if (mbuf->m_len - m_ofs <= 0) {
2006 mbuf = mbuf->m_next;
2028 int n_entries, netif_rx_back_ring_t *ring)
2038 int n_responses = 0;
2039 grant_ref_t last_gref = GRANT_REF_INVALID;
2042 KASSERT(
gnttab != NULL, (
"Received a null granttable copy"));
2054 for (gnt_idx = 0; gnt_idx < n_entries; gnt_idx++) {
2055 int16_t status =
gnttab[gnt_idx].status;
2056 if (status != GNTST_okay) {
2058 "Got error %d for hypervisor gnttab_copy status\n",
2063 if (
gnttab[gnt_idx].dest.u.ref != last_gref) {
2065 last_gref =
gnttab[gnt_idx].dest.u.ref;
2071 netif_rx_response_t *rsp;
2073 id = RING_GET_REQUEST(ring, ring->rsp_prod_pvt)->id;
2074 rsp = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt);
2076 rsp->status = NETIF_RSP_ERROR;
2080 const int has_extra = pkt->
flags & NETRXF_extra_info;
2084 for (i = 0; i < n_responses; i++) {
2085 netif_rx_request_t rxq;
2086 netif_rx_response_t *rsp;
2088 r_idx = ring->rsp_prod_pvt + i;
2093 rxq = *(RING_GET_REQUEST(ring, r_idx));
2094 rsp = RING_GET_RESPONSE(ring, r_idx);
2095 if (has_extra && (i == 1)) {
2096 netif_extra_info_t *ext =
2097 (netif_extra_info_t*)rsp;
2098 ext->type = XEN_NETIF_EXTRA_TYPE_GSO;
2100 ext->u.gso.size = pkt->
extra.u.gso.size;
2101 ext->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
2103 ext->u.gso.features = 0;
2106 rsp->status = GNTST_okay;
2109 if (i < pkt->list_len - 1)
2110 rsp->flags |= NETRXF_more_data;
2111 if ((i == 0) && has_extra)
2112 rsp->flags |= NETRXF_extra_info;
2114 (pkt->
flags & NETRXF_data_validated)) {
2115 rsp->flags |= NETRXF_data_validated;
2116 rsp->flags |= NETRXF_csum_blank;
2119 for (;
gnttab[gnt_idx].dest.u.ref == rxq.gref;
2121 rsp->status +=
gnttab[gnt_idx].len;
2127 ring->req_cons += n_responses;
2128 ring->rsp_prod_pvt += n_responses;
2132#if defined(INET) || defined(INET6)
2141xnb_add_mbuf_cksum(
struct mbuf *mbufc)
2143 struct ether_header *eh;
2145 uint16_t ether_type;
2147 eh = mtod(mbufc,
struct ether_header*);
2148 ether_type = ntohs(eh->ether_type);
2149 if (ether_type != ETHERTYPE_IP) {
2154 iph = (
struct ip*)(eh + 1);
2155 if (mbufc->m_pkthdr.csum_flags & CSUM_IP_VALID) {
2157 iph->ip_sum = in_cksum_hdr(iph);
2160 switch (iph->ip_p) {
2162 if (mbufc->m_pkthdr.csum_flags & CSUM_IP_VALID) {
2163 size_t tcplen = ntohs(iph->ip_len) -
sizeof(
struct ip);
2164 struct tcphdr *th = (
struct tcphdr*)(iph + 1);
2165 th->th_sum = in_pseudo(iph->ip_src.s_addr,
2166 iph->ip_dst.s_addr, htons(IPPROTO_TCP + tcplen));
2167 th->th_sum = in_cksum_skip(mbufc,
2168 sizeof(
struct ether_header) + ntohs(iph->ip_len),
2169 sizeof(
struct ether_header) + (iph->ip_hl << 2));
2173 if (mbufc->m_pkthdr.csum_flags & CSUM_IP_VALID) {
2174 size_t udplen = ntohs(iph->ip_len) -
sizeof(
struct ip);
2175 struct udphdr *uh = (
struct udphdr*)(iph + 1);
2176 uh->uh_sum = in_pseudo(iph->ip_src.s_addr,
2177 iph->ip_dst.s_addr, htons(IPPROTO_UDP + udplen));
2178 uh->uh_sum = in_cksum_skip(mbufc,
2179 sizeof(
struct ether_header) + ntohs(iph->ip_len),
2180 sizeof(
struct ether_header) + (iph->ip_hl << 2));
2194 mtx_assert(&xnb->
sc_lock, MA_OWNED);
2196 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
2197 if_link_state_change(
ifp, LINK_STATE_DOWN);
2204 struct ifreq *ifr = (
struct ifreq*) data;
2206 struct ifaddr *ifa = (
struct ifaddr*)data;
2213 if (
ifp->if_flags & IFF_UP) {
2216 if (
ifp->if_drv_flags & IFF_DRV_RUNNING) {
2229 if (ifa->ifa_addr->sa_family == AF_INET) {
2230 ifp->if_flags |= IFF_UP;
2231 if (!(
ifp->if_drv_flags & IFF_DRV_RUNNING)) {
2232 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING |
2234 if_link_state_change(
ifp,
2236 ifp->if_drv_flags |= IFF_DRV_RUNNING;
2237 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2238 if_link_state_change(
ifp,
2241 arp_ifinit(
ifp, ifa);
2246 error = ether_ioctl(
ifp, cmd, data);
2253 if (ifr->ifr_reqcap & IFCAP_TXCSUM) {
2254 ifp->if_capenable |= IFCAP_TXCSUM;
2257 ifp->if_capenable &= ~(IFCAP_TXCSUM);
2260 if ((ifr->ifr_reqcap & IFCAP_RXCSUM)) {
2261 ifp->if_capenable |= IFCAP_RXCSUM;
2263 ifp->if_capenable &= ~(IFCAP_RXCSUM);
2270 if (ifr->if_reqcap |= IFCAP_TSO4) {
2271 if (IFCAP_TXCSUM &
ifp->if_capenable) {
2272 printf(
"xnb: Xen netif requires that "
2273 "TXCSUM be enabled in order "
2277 ifp->if_capenable |= IFCAP_TSO4;
2278 ifp->if_hwassist |= CSUM_TSO;
2281 ifp->if_capenable &= ~(IFCAP_TSO4);
2282 ifp->if_hwassist &= ~(CSUM_TSO);
2284 if (ifr->ifreqcap |= IFCAP_LRO) {
2285 ifp->if_capenable |= IFCAP_LRO;
2287 ifp->if_capenable &= ~(IFCAP_LRO);
2293 ifp->if_mtu = ifr->ifr_mtu;
2294 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
2302 error = ifmedia_ioctl(
ifp, ifr, &xnb->
sc_media, cmd);
2305 error = ether_ioctl(
ifp, cmd, data);
2314 netif_rx_back_ring_t *
rxb;
2317 RING_IDX req_prod_local;
2319 xnb =
ifp->if_softc;
2326 int out_of_space = 0;
2328 req_prod_local =
rxb->sring->req_prod;
2333 IF_DEQUEUE(&
ifp->if_snd, mbufc);
2345 IF_PREPEND(&
ifp->if_snd, mbufc);
2356 if_inc_counter(
ifp, IFCOUNTER_OERRORS, 1);
2361 if_inc_counter(
ifp, IFCOUNTER_OPACKETS, 1);
2366 if (out_of_space != 0)
2370 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(
rxb,
notify);
2371 if ((
notify != 0) || (out_of_space != 0))
2373 rxb->sring->req_event = req_prod_local + 1;
2375 }
while (
rxb->sring->req_prod != req_prod_local) ;
2392xnb_send(netif_rx_back_ring_t *ring, domid_t otherend,
const struct mbuf *mbufc,
2396 int error, n_entries, n_reqs;
2399 space = ring->sring->req_prod - ring->req_cons;
2404 if (n_entries != 0) {
2405 int __unused hv_ret = HYPERVISOR_grant_table_op(GNTTABOP_copy,
2407 KASSERT(hv_ret == 0, (
"HYPERVISOR_grant_table_op returned %d\n",
2421 xnb =
ifp->if_softc;
2435 mtx_assert(&xnb->
sc_lock, MA_OWNED);
2437 if (
ifp->if_drv_flags & IFF_DRV_RUNNING)
2442 ifp->if_drv_flags |= IFF_DRV_RUNNING;
2443 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2444 if_link_state_change(
ifp, LINK_STATE_UP);
2474 ifmr->ifm_status = IFM_AVALID|IFM_ACTIVE;
2475 ifmr->ifm_active = IFM_ETHER|IFM_MANUAL;
2484 DEVMETHOD(device_shutdown, bus_generic_shutdown),
static void notify(struct notify_data *notify, vm_page_t page)
static int xnb_ring2pkt(struct xnb_pkt *pkt, const netif_tx_back_ring_t *tx_ring, RING_IDX start)
static int xnb_publish_backend_info(struct xnb_softc *xnb)
static void xnb_frontend_changed(device_t dev, XenbusState frontend_state)
struct gnttab_copy gnttab_copy_table[GNTTAB_LEN]
static void xnb_start_locked(struct ifnet *)
static int xnb_collect_xenstore_info(struct xnb_softc *xnb)
static void __unused xnb_dump_pkt(const struct xnb_pkt *pkt)
static void xnb_free_communication_mem(struct xnb_softc *xnb)
#define XNB_CSUM_FEATURES
static void xnb_pkt_validate(struct xnb_pkt *pxnb)
static void xnb_update_mbufc(struct mbuf *mbufc, const gnttab_copy_table gnttab, int n_entries)
static void xnb_ifinit(void *)
static void xnb_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
static void xnb_stop(struct xnb_softc *)
static int xnb_send(netif_rx_back_ring_t *rxb, domid_t otherend, const struct mbuf *mbufc, gnttab_copy_table gnttab)
static int xnb_resume(device_t dev)
static int xnb_alloc_communication_mem(struct xnb_softc *xnb)
static int xnb_unit_test_main(SYSCTL_HANDLER_ARGS)
static void xnb_intr(void *arg)
static int xnb_detach(device_t dev)
static int xnb_rxpkt2gnttab(const struct xnb_pkt *pkt, const struct mbuf *mbufc, gnttab_copy_table gnttab, const netif_rx_back_ring_t *rxb, domid_t otherend_id)
static int xnb_probe(device_t dev)
static void xnb_connect(struct xnb_softc *xnb)
static int xnb_dump_rings(SYSCTL_HANDLER_ARGS)
static void xnb_ifinit_locked(struct xnb_softc *)
static void xnb_dump_txreq(RING_IDX idx, const struct netif_tx_request *txreq)
static int xnb_txpkt2gnttab(const struct xnb_pkt *pkt, struct mbuf *mbufc, gnttab_copy_table gnttab, const netif_tx_back_ring_t *txb, domid_t otherend_id)
static int xnb_pkt_is_valid(const struct xnb_pkt *pxnb)
DRIVER_MODULE(xnb, xenbusb_back, xnb_driver, xnb_devclass, 0, 0)
static void __unused xnb_dump_mbuf(const struct mbuf *m)
static void __unused xnb_dump_gnttab_copy(const struct gnttab_copy *entry)
#define RING_HAS_UNCONSUMED_REQUESTS_2(_r, cons)
static device_method_t xnb_methods[]
static void xnb_pkt_initialize(struct xnb_pkt *pxnb)
static void xnb_attach_failed(struct xnb_softc *xnb, int err, const char *fmt,...) __printflike(3
static int xnb_recv(netif_tx_back_ring_t *txb, domid_t otherend, struct mbuf **mbufc, struct ifnet *ifnet, gnttab_copy_table gnttab)
static void xnb_txpkt2rsp(const struct xnb_pkt *pkt, netif_tx_back_ring_t *ring, int error)
static int xnb_mbufc2pkt(const struct mbuf *mbufc, struct xnb_pkt *pkt, RING_IDX start, int space)
static void xnb_setup_sysctl(struct xnb_softc *xnb)
static int xnb_connect_comms(struct xnb_softc *xnb)
static int xnb_connect_ring(struct xnb_softc *xnb, xnb_ring_type_t ring_type)
static int create_netdev(device_t dev)
static driver_t xnb_driver
#define virt_to_offset(x)
static int xnb_ifmedia_upd(struct ifnet *ifp)
static MALLOC_DEFINE(M_XENNETBACK, "xnb", "Xen Net Back Driver Data")
static struct mbuf * xnb_pkt2mbufc(const struct xnb_pkt *pkt, struct ifnet *ifp)
static void static int xnb_shutdown(struct xnb_softc *xnb)
static int xnb_attach(device_t dev)
static int xnb_rxpkt2rsp(const struct xnb_pkt *pkt, const gnttab_copy_table gnttab, int n_entries, netif_rx_back_ring_t *ring)
static void xnb_start(struct ifnet *)
static int xnb_suspend(device_t dev)
static int xnb_ioctl(struct ifnet *, u_long, caddr_t)
#define DPRINTF(fmt, args...)
static int xnb_disconnect(struct xnb_softc *xnb)
static void xnb_pkt_invalidate(struct xnb_pkt *pxnb)
Unit tests for the Xen netback driver.
Configuration data for a shared memory request ring used to communicate with the front-end client of ...
netif_tx_back_ring_t tx_ring
netif_rx_back_ring_t rx_ring
union xnb_ring_config::@0 back_ring
xen_intr_handle_t xen_intr_handle
struct xnb_ring_config ring_configs[XNB_NUM_RING_TYPES]
gnttab_copy_table rx_gnttab
struct resource * pseudo_phys_res
gnttab_copy_table tx_gnttab
domid_t otherend_id
Cached value of the front-end's domain id.
int abi
The netif protocol abi in effect.
uint8_t mac[ETHER_ADDR_LEN]
struct resource * xenmem_alloc(device_t dev, int *res_id, size_t size)
int xenmem_free(device_t dev, int res_id, struct resource *res)
int xs_printf(struct xs_transaction t, const char *dir, const char *node, const char *fmt,...)
int xs_transaction_start(struct xs_transaction *t)
int xs_read(struct xs_transaction t, const char *dir, const char *node, u_int *len, void **result)
int xs_transaction_end(struct xs_transaction t, int abort)
int xs_scanf(struct xs_transaction t, const char *dir, const char *node, int *scancountp, const char *fmt,...)
int xs_vprintf(struct xs_transaction t, const char *dir, const char *node, const char *fmt, va_list ap)
int xs_gather(struct xs_transaction t, const char *dir,...)