diff --git a/src/libs/compat/freebsd_network/device.c b/src/libs/compat/freebsd_network/device.c index 7504d35cc0..142ba5bee0 100644 --- a/src/libs/compat/freebsd_network/device.c +++ b/src/libs/compat/freebsd_network/device.c @@ -25,7 +25,7 @@ spinlock __haiku_intr_spinlock; -struct net_stack_module_info *gStack; +struct net_buffer_module_info *gBufferModule; static struct list sRootDevices; static int sNextUnit; diff --git a/src/libs/compat/freebsd_network/device.h b/src/libs/compat/freebsd_network/device.h index 7b08131452..32631062ec 100644 --- a/src/libs/compat/freebsd_network/device.h +++ b/src/libs/compat/freebsd_network/device.h @@ -17,8 +17,6 @@ #include -#include - #include #include @@ -52,9 +50,8 @@ enum { }; -extern struct net_stack_module_info *gStack; +extern struct net_buffer_module_info *gBufferModule; extern pci_module_info *gPci; -extern struct pci_x86_module_info *gPCIx86; static inline void diff --git a/src/libs/compat/freebsd_network/device_hooks.c b/src/libs/compat/freebsd_network/device_hooks.c index 422fa0537b..b29c724627 100644 --- a/src/libs/compat/freebsd_network/device_hooks.c +++ b/src/libs/compat/freebsd_network/device_hooks.c @@ -13,6 +13,7 @@ #include #include +#include #include @@ -38,16 +39,11 @@ compat_open(const char *name, uint32 flags, void **cookie) if (i == MAX_DEVICES) return B_ERROR; - if (get_module(NET_STACK_MODULE_NAME, (module_info **)&gStack) != B_OK) - return B_ERROR; - ifp = gDevices[i]; if_printf(ifp, "compat_open(0x%" B_PRIx32 ")\n", flags); - if (atomic_or(&ifp->open_count, 1)) { - put_module(NET_STACK_MODULE_NAME); + if (atomic_or(&ifp->open_count, 1)) return B_BUSY; - } IFF_LOCKGIANT(ifp); @@ -107,24 +103,21 @@ compat_free(void *cookie) // TODO: empty out the send queue atomic_and(&ifp->open_count, 0); - put_module(NET_STACK_MODULE_NAME); return B_OK; } static status_t -compat_read(void *cookie, off_t position, void *buffer, size_t *numBytes) +compat_receive(void *cookie, net_buffer **_buffer) { struct ifnet *ifp = cookie; uint32 semFlags = B_CAN_INTERRUPT; status_t status; struct mbuf *mb; - size_t length = *numBytes; - //if_printf(ifp, "compat_read(%lld, %p, [%lu])\n", position, - // buffer, *numBytes); + //if_printf(ifp, "compat_receive(%p)\n", _buffer); - if (ifp->flags & DEVICE_CLOSED) + if ((ifp->flags & DEVICE_CLOSED) != 0) return B_INTERRUPTED; if (ifp->flags & DEVICE_NON_BLOCK) @@ -132,46 +125,46 @@ compat_read(void *cookie, off_t position, void *buffer, size_t *numBytes) do { status = acquire_sem_etc(ifp->receive_sem, 1, semFlags, 0); - if (ifp->flags & DEVICE_CLOSED) + if ((ifp->flags & DEVICE_CLOSED) != 0) return B_INTERRUPTED; - if (status == B_WOULD_BLOCK) { - *numBytes = 0; - return B_OK; - } else if (status < B_OK) + if (status != B_OK) return status; IF_DEQUEUE(&ifp->receive_queue, mb); } while (mb == NULL); - if (mb->m_pkthdr.len > length) { - if_printf(ifp, "error reading packet: too large! (%d > %" B_PRIuSIZE ")\n", - mb->m_pkthdr.len, length); + net_buffer *buffer = gBufferModule->create(0); + if (buffer == NULL) { m_freem(mb); - *numBytes = 0; - return E2BIG; + return B_NO_MEMORY; } - length = min_c(max_c((size_t)mb->m_pkthdr.len, 0), length); - - m_copydata(mb, 0, length, buffer); - *numBytes = length; + for (struct mbuf *m = mb; m != NULL; m = m->m_next) { + status = gBufferModule->append(buffer, mtod(m, void *), mb->m_len); + if (status != B_OK) + break; + } + if (status != B_OK) { + gBufferModule->free(buffer); + m_freem(mb); + return status; + } + *_buffer = buffer; m_freem(mb); return B_OK; } static status_t -compat_write(void *cookie, off_t position, const void *buffer, - size_t *numBytes) +compat_send(void *cookie, net_buffer *buffer) { struct ifnet *ifp = cookie; struct mbuf *mb; - int length = *numBytes; + int length = buffer->size; - //if_printf(ifp, "compat_write(%lld, %p, [%lu])\n", position, - // buffer, *numBytes); + //if_printf(ifp, "compat_send(%p, [%lu])\n", buffer, length); if (length <= MHLEN) { mb = m_gethdr(0, MT_DATA); @@ -185,16 +178,20 @@ compat_write(void *cookie, off_t position, const void *buffer, length = min_c(length, mb->m_ext.ext_size); } - // if we waited, check after if the ifp is still valid - + status_t status = gBufferModule->read(buffer, 0, mtod(mb, void *), length); + if (status != B_OK) + return status; mb->m_pkthdr.len = mb->m_len = length; - memcpy(mtod(mb, void *), buffer, mb->m_len); - *numBytes = length; + + if ((ifp->flags & DEVICE_CLOSED) != 0) + return B_INTERRUPTED; IFF_LOCKGIANT(ifp); int result = ifp->if_output(ifp, mb, NULL, NULL); IFF_UNLOCKGIANT(ifp); + if (result == 0) + gBufferModule->free(buffer); return result; } @@ -329,6 +326,20 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) } return B_OK; + case ETHER_SEND_NET_BUFFER: + if (arg == NULL || length == 0) + return B_BAD_DATA; + if (!IS_KERNEL_ADDRESS(arg)) + return B_BAD_ADDRESS; + return compat_send(cookie, (net_buffer*)arg); + + case ETHER_RECEIVE_NET_BUFFER: + if (arg == NULL || length == 0) + return B_BAD_DATA; + if (!IS_KERNEL_ADDRESS(arg)) + return B_BAD_ADDRESS; + return compat_receive(cookie, (net_buffer**)arg); + case SIOCSIFFLAGS: case SIOCSIFMEDIA: case SIOCSIFMTU: @@ -349,6 +360,6 @@ device_hooks gDeviceHooks = { compat_close, compat_free, compat_control, - compat_read, - compat_write, + NULL, + NULL, }; diff --git a/src/libs/compat/freebsd_network/mbuf.c b/src/libs/compat/freebsd_network/mbuf.c index 906feb9098..b252b264bb 100644 --- a/src/libs/compat/freebsd_network/mbuf.c +++ b/src/libs/compat/freebsd_network/mbuf.c @@ -11,6 +11,8 @@ #include #include +#include + #include #include #include @@ -311,6 +313,10 @@ m_free(struct mbuf* memoryBuffer) status_t init_mbufs() { + status_t status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule); + if (status != B_OK) + goto clean; + sMBufCache = create_object_cache("mbufs", MSIZE, 8, NULL, NULL, NULL); if (sMBufCache == NULL) goto clean; @@ -335,6 +341,7 @@ clean: delete_object_cache(sChunkCache); if (sMBufCache != NULL) delete_object_cache(sMBufCache); + put_module(NET_BUFFER_MODULE_NAME); return B_NO_MEMORY; }