Networking doesn't work in FreeBSD pvm's on Opensolaris Dom0's When trying to do FreeBSD -> otherhost connections with ssh you recieve this error: Received disconnect from 192.168.1.14: 2: Bad packet length. When trying to connect from another host -> FreeBSD you recieve this error: Disconnecting: Bad packet length. It was suggested that this may have something to do with the fact that Opensolaris doesn't support scatter gather. The way it was explained to me was that domu's are supposed to check whether the dom0 supports scatter gather, but FreeBSD just assumes that it does. I'm going to be honest and say i have no idea what scatter gather is, whether or not this is true or how to fix the issue if it IS. What i DO know is that in hvm mode FreeBSD works, but we all know pvm mode is designed with performance in mind. How-To-Repeat: Install Opensolaris Install xVM xen Dom0 Install FreeBSD 8.0 hvm Download FreeBSD src build FreeBSD with xen kernel make the changes (/etc/fstab /etc/ttys) required to boot using pvm mode) boot FreeBSD 8.0 with xen kernel
Responsible Changed From-To: freebsd-bugs->freebsd-xen Over to maintainer(s).
the current FreeBSD frontend of the xn network driver does not check the ca= pabilities of the backend driver.=20 The following patch checks the backend features feature-sg (scatter/gather) and feature-gso-tcpv4 (segmentation offload) and sets the frontend driver capabilities accordingly.=20 There is still the problem with receive and transmit checksum offload. I have no idea how to figure out what the backend supports. So for opensolaris it seems necessary to disable checksum offload manually by ifconfig xn0 -txcsum -rxcsum Maybe it would make sense to change the default for checksum offload if the backend does not support feature-sg and/or feature-gso-tcpv4. --- netfront.c.orig 2009-10-25 02:10:29.000000000 +0100 +++ netfront.c 2010-02-28 18:08:20.000000000 +0100 @@ -236,6 +236,7 @@ u_int irq; u_int copying_receiver; u_int carrier; + u_int sg_allowed; =09 /* Receive-ring batched refills. */ #define RX_MIN_TARGET 32 @@ -1432,7 +1433,7 @@ */ for (m =3D m_head, nfrags =3D 0; m; m =3D m->m_next) nfrags++; - if (nfrags > MAX_SKB_FRAGS) { + if (nfrags > (sc->sg_allowed ? MAX_SKB_FRAGS : 1)) { m =3D m_defrag(m_head, M_DONTWAIT); if (!m) { m_freem(m_head); @@ -1788,6 +1789,35 @@ ifp->if_drv_flags &=3D ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); } =20 +static void xennet_set_features(device_t dev, struct netfront_info *np) +{ + struct ifnet *ifp; + int val; + + device_printf(dev, "backend features:"); + + if (xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev), "feature-s= g", NULL, "%d", &val) < 0) + val =3D 0; +=09 + np->sg_allowed =3D val; + + if (val) + printf(" feature-sg"); + + if (xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev), "feature-g= so-tcpv4", NULL, "%d", &val) < 0) + val =3D 0; + + if (val =3D=3D 0) { + ifp =3D np->xn_ifp; + ifp->if_capabilities &=3D ~(IFCAP_TSO4|IFCAP_LRO); + ifp->if_capenable &=3D ~(IFCAP_TSO4|IFCAP_LRO); + ifp->if_hwassist &=3D ~(CSUM_TSO); + } else + printf(" feature-gso-tcp4"); + + printf("\n"); +} + /* START of Xenolinux helper functions adapted to FreeBSD */ int network_connect(struct netfront_info *np) @@ -1820,6 +1850,8 @@ if (error)=20 return (error); =09 + xennet_set_features(np->xbdev, np); + /* Step 1: Reinitialise variables. */ netif_release_tx_bufs(np); Juergen Weiss |Universitaet Mainz, Zentrum fuer Datenverarbeitung, weiss@uni-mainz.de |55099 Mainz, Tel: +49(6131)39-26361, FAX: +49(6131)39-2= 6407
Dear colleagues, this is the correct patch resolving the problem: =3D=3D=3D --- sys/dev/xen/netfront/netfront.c.orig 2010-12-10 12:59:03.000000000 +000= 0 +++ sys/dev/xen/netfront/netfront.c 2010-12-10 12:31:01.000000000 +0000 @@ -258,6 +258,7 @@ u_int irq; u_int copying_receiver; u_int carrier; + u_int sg_allowed; =09 /* Receive-ring batched refills. */ #define RX_MIN_TARGET 32 @@ -1499,7 +1500,7 @@ * deal with nfrags > MAX_TX_REQ_FRAGS, which is a quirk of * the Linux network stack. */ - if (nfrags > MAX_TX_REQ_FRAGS) { + if (nfrags > (sc->sg_allowed? MAX_TX_REQ_FRAGS : 1)) { m =3D m_defrag(m_head, M_DONTWAIT); if (!m) { /* @@ -1878,6 +1879,37 @@ if_link_state_change(ifp, LINK_STATE_DOWN); } +static void +xennet_set_features(device_t dev, struct netfront_info *np) +{ + struct ifnet *ifp; + int val; + + device_printf(dev, "backend features:"); + + if (xs_scanf(XST_NIL, xenbus_get_otherend_path(np->xbdev), "feature-sg", NULL, "%d", &val) < 0) + val =3D 0; + + np->sg_allowed =3D val; + + if (val) + printf(" feature-sg"); + + if (xs_scanf(XST_NIL, xenbus_get_otherend_path(np->xbdev), "feature-gso-tcpv4", NULL, "%d", &val) < 0) + val =3D 0; + + if (val =3D=3D 0) { + ifp =3D np->xn_ifp; + ifp->if_capabilities &=3D ~(IFCAP_TSO4|IFCAP_LRO); + ifp->if_capenable &=3D ~(IFCAP_TSO4|IFCAP_LRO); + ifp->if_hwassist &=3D ~(CSUM_TSO); + xn_enable_lro =3D 0; + } else + printf(" feature-gso-tcp4"); + + printf("\n"); +} + /* START of Xenolinux helper functions adapted to FreeBSD */ int network_connect(struct netfront_info *np) @@ -1909,6 +1941,8 @@ if (error) return (error); =09 + xennet_set_features(np->xbdev, np); + /* Step 1: Reinitialise variables. */ netif_release_tx_bufs(np); =3D=3D=3D I've tested it on my system -- Solaris 11 Express 2010.11 + FreeBSD v8.2-BETA1 in paravirtualised mode. All is working as designed, I'm able at least to ssh into Guest and csup entire source tree. --=20 =C2=A0 =C2=A0 Yours =C2=A0 =C2=A0 =C2=A0 =C2=A0 Andrew Kolchoogin.
*** Bug 143398 has been marked as a duplicate of this bug. ***
AFAICT current netfront code correctly handles both "feature-sg" and "feature-gso-tcpv4", so I'm marking the bug as fixed.