Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/e1k/e1k.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -67,4 +67,6 @@
 #define E1000_RECEIVE_ADDRESS  16
 
+/** Maximum sending packet size */
+#define E1000_MAX_SEND_FRAME_SIZE  2048
 /** Maximum receiving packet size */
 #define E1000_MAX_RECEIVE_PACKET_SIZE  2048
@@ -125,6 +127,8 @@
 	void *tx_ring_virt;
 	
-	/** Packets in tx ring  */
-	packet_t **tx_ring_packets;
+	/** Ring of TX frames, physical address */
+	void **tx_frame_phys;
+	/** Ring of TX frames, virtual address */
+	void **tx_frame_virt;
 	
 	/** Physical rx ring address */
@@ -223,5 +227,5 @@
 static int e1000_on_activating(nic_t *);
 static int e1000_on_stopping(nic_t *);
-static void e1000_write_packet(nic_t *, packet_t *);
+static void e1000_send_frame(nic_t *, void *, size_t);
 
 /** Commands to deal with interrupt
@@ -1126,10 +1130,4 @@
 	    (e1000->tx_ring_virt + offset * sizeof(e1000_tx_descriptor_t));
 	
-	if (tx_descriptor->length) {
-		packet_t *old_packet = *(e1000->tx_ring_packets + offset);
-		if (old_packet)
-			nic_release_packet(nic, old_packet);
-	}
-	
 	tx_descriptor->phys_addr = 0;
 	tx_descriptor->length = 0;
@@ -1522,5 +1520,12 @@
 static int e1000_initialize_tx_structure(e1000_t *e1000)
 {
+	size_t i;
+	
 	fibril_mutex_lock(&e1000->tx_lock);
+	
+	e1000->tx_ring_phys = NULL;
+	e1000->tx_ring_virt = NULL;
+	e1000->tx_frame_phys = NULL;
+	e1000->tx_frame_virt = NULL;
 	
 	int rc = dmamem_map_anonymous(
@@ -1529,8 +1534,24 @@
 	    &e1000->tx_ring_virt);
 	if (rc != EOK)
-		return rc;
+		goto error;
 	
 	bzero(e1000->tx_ring_virt,
 	    E1000_TX_PACKETS_COUNT * sizeof(e1000_tx_descriptor_t));
+	
+	e1000->tx_frame_phys = calloc(E1000_TX_PACKETS_COUNT, sizeof(void *));
+	e1000->tx_frame_virt = calloc(E1000_TX_PACKETS_COUNT, sizeof(void *));
+
+	if (e1000->tx_frame_phys == NULL || e1000->tx_frame_virt == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+	
+	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+		rc = dmamem_map_anonymous(
+		    E1000_MAX_SEND_FRAME_SIZE, AS_AREA_READ | AS_AREA_WRITE,
+		    0, &e1000->tx_frame_phys[i], &e1000->tx_frame_virt[i]);
+		if (rc != EOK)
+			goto error;
+	}
 	
 	E1000_REG_WRITE(e1000, E1000_TDBAH,
@@ -1539,12 +1560,36 @@
 	    (uint32_t) PTR_TO_U64(e1000->tx_ring_phys));
 	
-	e1000->tx_ring_packets =
-	    malloc(E1000_TX_PACKETS_COUNT * sizeof(packet_t *));
-	// FIXME: Check return value
-	
 	e1000_initialize_tx_registers(e1000);
 	
 	fibril_mutex_unlock(&e1000->tx_lock);
 	return EOK;
+	
+error:
+	if (e1000->tx_ring_virt != NULL) {
+		dmamem_unmap_anonymous(e1000->tx_ring_virt);
+		e1000->tx_ring_virt = NULL;
+	}
+	
+	if (e1000->tx_frame_phys != NULL && e1000->tx_frame_virt != NULL) {
+		for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+			if (e1000->tx_frame_virt[i] != NULL) {
+				dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
+				e1000->tx_frame_virt[i] = NULL;
+				e1000->tx_frame_phys[i] = NULL;
+			}
+		}
+	}
+	
+	if (e1000->tx_frame_phys != NULL) {
+		free(e1000->tx_frame_phys);
+		e1000->tx_frame_phys = NULL;
+	}
+	
+	if (e1000->tx_frame_virt != NULL) {
+		free(e1000->tx_frame_virt);
+		e1000->tx_frame_phys = NULL;
+	}
+	
+	return rc;
 }
 
@@ -1556,5 +1601,21 @@
 static void e1000_uninitialize_tx_structure(e1000_t *e1000)
 {
-	free(e1000->tx_ring_packets);
+	size_t i;
+	
+	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+		dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
+		e1000->tx_frame_virt[i] = NULL;
+		e1000->tx_frame_phys[i] = NULL;
+	}
+	
+	if (e1000->tx_frame_phys != NULL) {
+		free(e1000->tx_frame_phys);
+		e1000->tx_frame_phys = NULL;
+	}
+	
+	if (e1000->tx_frame_virt != NULL) {
+		free(e1000->tx_frame_virt);
+		e1000->tx_frame_phys = NULL;
+	}
 	dmamem_unmap_anonymous(e1000->tx_ring_virt);
 }
@@ -1771,5 +1832,5 @@
 	
 	nic_set_specific(nic, e1000);
-	nic_set_write_packet_handler(nic, e1000_write_packet);
+	nic_set_send_frame_handler(nic, e1000_send_frame);
 	nic_set_state_change_handlers(nic, e1000_on_activating,
 	    e1000_on_down, e1000_on_stopping);
@@ -2190,8 +2251,9 @@
 }
 
-/** Send packet
+/** Send frame
  *
  * @param nic    NIC driver data structure
- * @param packet Packet to send
+ * @param data   Frame data
+ * @param size   Frame size in bytes
  *
  * @return EOK if succeed
@@ -2199,5 +2261,5 @@
  *
  */
-static void e1000_write_packet(nic_t *nic, packet_t *packet)
+static void e1000_send_frame(nic_t *nic, void *data, size_t size)
 {
 	assert(nic);
@@ -2217,13 +2279,6 @@
 	
 	/* Descriptor done */
-	if (tx_descriptor_addr->status & TXDESCRIPTOR_STATUS_DD) {
+	if (tx_descriptor_addr->status & TXDESCRIPTOR_STATUS_DD)
 		descriptor_available = true;
-		packet_t *old_packet = *(e1000->tx_ring_packets + tdt);
-		if (old_packet) {
-			size_t old_packet_size = packet_get_data_length(old_packet);
-			nic_dma_unlock_packet(old_packet, old_packet_size);
-			nic_release_packet(nic, old_packet);
-		}
-	}
 	
 	if (!descriptor_available) {
@@ -2233,18 +2288,8 @@
 	}
 	
-	size_t packet_size = packet_get_data_length(packet);
-	
-	void *phys;
-	int rc = nic_dma_lock_packet(packet, packet_size, &phys);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&e1000->tx_lock);
-		return;
-	}
-	
-	*(e1000->tx_ring_packets + tdt) = packet;
-	
-	tx_descriptor_addr->phys_addr =
-	    PTR_TO_U64(phys + packet->data_start);
-	tx_descriptor_addr->length = packet_size;
+	memcpy(e1000->tx_frame_virt[tdt], data, size);
+	
+	tx_descriptor_addr->phys_addr = PTR_TO_U64(e1000->tx_frame_phys[tdt]);
+	tx_descriptor_addr->length = size;
 	
 	/*
Index: uspace/drv/nic/lo/lo.c
===================================================================
--- uspace/drv/nic/lo/lo.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/lo/lo.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -59,7 +59,18 @@
 };
 
-static void lo_write_packet(nic_t *nic_data, packet_t *packet)
+static void lo_send_frame(nic_t *nic_data, void *data, size_t size)
 {
-	nic_report_send_ok(nic_data, 1, packet_get_data_length(packet));
+	packet_t *packet;
+	int rc;
+
+	packet = nic_alloc_packet(nic_data, size);
+	if (packet == NULL)
+		return;
+
+	rc = packet_copy_data(packet, data, size);
+	if (rc != EOK)
+		return;
+
+	nic_report_send_ok(nic_data, 1, size);
 	nic_received_noneth_packet(nic_data, packet);
 }
@@ -88,5 +99,5 @@
 	
 	dev->driver_data = nic_data;
-	nic_set_write_packet_handler(nic_data, lo_write_packet);
+	nic_set_send_frame_handler(nic_data, lo_send_frame);
 	
 	int rc = nic_connect_to_services(nic_data);
Index: uspace/drv/nic/ne2k/dp8390.c
===================================================================
--- uspace/drv/nic/ne2k/dp8390.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -404,8 +404,9 @@
  *
  * @param[in,out] ne2k   Network interface structure.
- * @param[in]     packet Frame to be sent.
- *
- */
-void ne2k_send(nic_t *nic_data, packet_t *packet)
+ * @param[in]     data   Pointer to frame data
+ * @param[in]     size   Frame size in bytes
+ *
+ */
+void ne2k_send(nic_t *nic_data, void *data, size_t size)
 {
 	ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
@@ -419,6 +420,4 @@
 		fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex);
 	}
-	void *buf = packet_get_data(packet);
-	size_t size = packet_get_data_length(packet);
 	
 	if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) {
@@ -428,5 +427,5 @@
 
 	/* Upload the frame to the ethernet card */
-	ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size);
+	ne2k_upload(ne2k, data, ne2k->sq.page * DP_PAGE, size);
 	ne2k->sq.dirty = true;
 	ne2k->sq.size = size;
@@ -438,7 +437,4 @@
 	pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA);
 	fibril_mutex_unlock(&ne2k->sq_mutex);
-
-	/* Relase packet */
-	nic_release_packet(nic_data, packet);
 }
 
Index: uspace/drv/nic/ne2k/dp8390.h
===================================================================
--- uspace/drv/nic/ne2k/dp8390.h	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/ne2k/dp8390.h	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -262,5 +262,5 @@
 extern int ne2k_up(ne2k_t *);
 extern void ne2k_down(ne2k_t *);
-extern void ne2k_send(nic_t *, packet_t *);
+extern void ne2k_send(nic_t *, void *, size_t);
 extern void ne2k_interrupt(nic_t *, uint8_t, uint8_t);
 extern packet_t *ne2k_alloc_packet(nic_t *, size_t);
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -343,5 +343,5 @@
 		return ENOMEM;
 	
-	nic_set_write_packet_handler(nic_data, ne2k_send);
+	nic_set_send_frame_handler(nic_data, ne2k_send);
 	nic_set_state_change_handlers(nic_data,
 		ne2k_on_activating, NULL, ne2k_on_stopping);
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -389,5 +389,5 @@
 static int rtl8139_on_activated(nic_t *nic_data);
 static int rtl8139_on_stopped(nic_t *nic_data);
-static void rtl8139_write_packet(nic_t *nic_data, packet_t *packet);
+static void rtl8139_send_frame(nic_t *nic_data, void *data, size_t size);
 
 /** Check if the transmit buffer is busy */
@@ -399,9 +399,10 @@
  *
  * @param nic_data  The nic driver data structure
- * @param packet    The packet to send
+ * @param data      Frame data
+ * @param size      Frame size in bytes
  *
  * @return EOK if succeed, error code in the case of error
  */
-static void rtl8139_write_packet(nic_t *nic_data, packet_t *packet)
+static void rtl8139_send_frame(nic_t *nic_data, void *data, size_t size)
 {
 	assert(nic_data);
@@ -409,20 +410,14 @@
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
 	assert(rtl8139);
-	ddf_msg(LVL_DEBUG, "Sending packet");
-
-	/* Get the packet data and check if it can be send */
-	size_t packet_length = packet_get_data_length(packet);
-	void *packet_data = packet_get_data(packet);
-
-	assert(packet_data);
-
-	if ((packet_length > RTL8139_PACKET_MAX_LENGTH) || !packet_data) {
-		ddf_msg(LVL_ERROR, "Write packet length error: data %p, length %z", 
-		    packet_data, packet_length);
+	ddf_msg(LVL_DEBUG, "Sending frame");
+
+	if (size > RTL8139_PACKET_MAX_LENGTH) {
+		ddf_msg(LVL_ERROR, "Send frame: frame too long, %zu bytes",
+		    size);
 		nic_report_send_error(rtl8139->nic_data, NIC_SEC_OTHER, 1);
 		goto err_size;
 	}
 
-	assert((packet_length & TSD_SIZE_MASK) == packet_length);
+	assert((size & TSD_SIZE_MASK) == size);
 
 	/* Lock transmitter structure for obtaining next buffer */
@@ -449,10 +444,10 @@
 	assert(!rtl8139_tbuf_busy(tsd));
 
-	/* Write packet data to the buffer, set the size to TSD and clear OWN bit */
-	memcpy(buf_addr, packet_data, packet_length);
+	/* Write frame data to the buffer, set the size to TSD and clear OWN bit */
+	memcpy(buf_addr, data, size);
 
 	/* Set size of the data to send */
 	uint32_t tsd_value = pio_read_32(tsd);
-	tsd_value = rtl8139_tsd_set_size(tsd_value, packet_length);
+	tsd_value = rtl8139_tsd_set_size(tsd_value, size);
 	pio_write_32(tsd, tsd_value);
 
@@ -462,10 +457,8 @@
 	tsd_value &= ~(uint32_t)TSD_OWN;
 	pio_write_32(tsd, tsd_value);
-	nic_release_packet(nic_data, packet);
 	return;
 
 err_busy_no_inc:
 err_size:
-	nic_release_packet(nic_data, packet);
 	return;
 };
@@ -1022,5 +1015,5 @@
 	rtl8139->nic_data = nic_data;
 	nic_set_specific(nic_data, rtl8139);
-	nic_set_write_packet_handler(nic_data, rtl8139_write_packet);
+	nic_set_send_frame_handler(nic_data, rtl8139_send_frame);
 	nic_set_state_change_handlers(nic_data,
 		rtl8139_on_activated, NULL, rtl8139_on_stopped);
Index: uspace/lib/c/generic/device/nic.c
===================================================================
--- uspace/lib/c/generic/device/nic.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/c/generic/device/nic.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -44,20 +44,31 @@
 #include <ipc/services.h>
 
-/** Send a packet through the device
- *
- * @param[in] dev_sess
- * @param[in] packet_id Id of the sent packet
- *
- * @return EOK If the operation was successfully completed
- *
- */
-int nic_send_message(async_sess_t *dev_sess, packet_id_t packet_id)
-{
-	async_exch_t *exch = async_exchange_begin(dev_sess);
-	int rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
-	    NIC_SEND_MESSAGE, packet_id);
-	async_exchange_end(exch);
-	
-	return rc;
+/** Send frame from NIC
+ *
+ * @param[in] dev_sess
+ * @param[in] data     Frame data
+ * @param[in] size     Frame size in bytes
+ *
+ * @return EOK If the operation was successfully completed
+ *
+ */
+int nic_send_frame(async_sess_t *dev_sess, void *data, size_t size)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
+	    NIC_SEND_MESSAGE, &answer);
+	sysarg_t retval = async_data_write_start(exch, data, size);
+	
+	async_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+	return retval;
 }
 
Index: uspace/lib/c/include/device/nic.h
===================================================================
--- uspace/lib/c/include/device/nic.h	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/c/include/device/nic.h	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -85,5 +85,5 @@
 } nic_funcs_t;
 
-extern int nic_send_message(async_sess_t *, packet_id_t);
+extern int nic_send_frame(async_sess_t *, void *, size_t);
 extern int nic_connect_to_nil(async_sess_t *, services_t, nic_device_id_t);
 extern int nic_get_state(async_sess_t *, nic_device_state_t *);
Index: uspace/lib/drv/generic/remote_nic.c
===================================================================
--- uspace/lib/drv/generic/remote_nic.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/drv/generic/remote_nic.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -39,18 +39,26 @@
 #include <errno.h>
 #include <ipc/services.h>
-#include <adt/measured_strings.h>
 #include <sys/time.h>
 #include "ops/nic.h"
 
-static void remote_nic_send_message(ddf_fun_t *dev, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	nic_iface_t *nic_iface = (nic_iface_t *) iface;
-	assert(nic_iface->send_message);
-	
-	packet_id_t packet_id = (packet_id_t) IPC_GET_ARG2(*call);
-	
-	int rc = nic_iface->send_message(dev, packet_id);
-	async_answer_0(callid, rc);
+static void remote_nic_send_frame(ddf_fun_t *dev, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	nic_iface_t *nic_iface = (nic_iface_t *) iface;
+	assert(nic_iface->send_frame);
+	
+	void *data;
+	size_t size;
+	int rc;
+	
+	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
+	if (rc != EOK) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	
+	rc = nic_iface->send_frame(dev, data, size);
+	async_answer_0(callid, rc);
+	free(data);
 }
 
@@ -1194,5 +1202,5 @@
  */
 static remote_iface_func_ptr_t remote_nic_iface_ops[] = {
-	&remote_nic_send_message,
+	&remote_nic_send_frame,
 	&remote_nic_connect_to_nil,
 	&remote_nic_get_state,
Index: uspace/lib/drv/include/ops/nic.h
===================================================================
--- uspace/lib/drv/include/ops/nic.h	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/drv/include/ops/nic.h	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -37,5 +37,4 @@
 #define LIBDRV_OPS_NIC_H_
 
-#include <net/packet.h>
 #include <ipc/services.h>
 #include <net/device.h>
@@ -46,5 +45,5 @@
 typedef struct nic_iface {
 	/** Mandatory methods */
-	int (*send_message)(ddf_fun_t *, packet_id_t);
+	int (*send_frame)(ddf_fun_t *, void *, size_t);
 	int (*connect_to_nil)(ddf_fun_t *, services_t, nic_device_id_t);
 	int (*get_state)(ddf_fun_t *, nic_device_state_t *);
Index: uspace/lib/nic/include/nic.h
===================================================================
--- uspace/lib/nic/include/nic.h	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/nic/include/nic.h	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -77,7 +77,8 @@
  *
  * @param nic_data
- * @param packet	Pointer to the packet to be sent
- */
-typedef void (*write_packet_handler)(nic_t *, packet_t *);
+ * @param data		Pointer to frame data
+ * @param size		Size of frame data in bytes
+ */
+typedef void (*send_frame_handler)(nic_t *, void *, size_t);
 /**
  * The handler for transitions between driver states.
@@ -206,5 +207,5 @@
 extern int nic_get_resources(nic_t *, hw_res_list_parsed_t *);
 extern void nic_set_specific(nic_t *, void *);
-extern void nic_set_write_packet_handler(nic_t *, write_packet_handler);
+extern void nic_set_send_frame_handler(nic_t *, send_frame_handler);
 extern void nic_set_state_change_handlers(nic_t *,
 	state_change_handler, state_change_handler, state_change_handler);
Index: uspace/lib/nic/include/nic_driver.h
===================================================================
--- uspace/lib/nic/include/nic_driver.h	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/nic/include/nic_driver.h	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -134,5 +134,5 @@
 	 * Called with the main_lock locked for reading.
 	 */
-	write_packet_handler write_packet;
+	send_frame_handler send_frame;
 	/**
 	 * Event handler called when device goes to the ACTIVE state.
Index: uspace/lib/nic/include/nic_impl.h
===================================================================
--- uspace/lib/nic/include/nic_impl.h	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/nic/include/nic_impl.h	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -48,5 +48,5 @@
 
 extern int nic_get_address_impl(ddf_fun_t *dev_fun, nic_address_t *address);
-extern int nic_send_message_impl(ddf_fun_t *dev_fun, packet_id_t packet_id);
+extern int nic_send_frame_impl(ddf_fun_t *dev_fun, void *data, size_t size);
 extern int nic_connect_to_nil_impl(ddf_fun_t *dev_fun, services_t nil_service,
 	int device_id);
Index: uspace/lib/nic/src/nic_driver.c
===================================================================
--- uspace/lib/nic/src/nic_driver.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/nic/src/nic_driver.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -114,6 +114,6 @@
 		if (!iface->set_state)
 			iface->set_state = nic_set_state_impl;
-		if (!iface->send_message)
-			iface->send_message = nic_send_message_impl;
+		if (!iface->send_frame)
+			iface->send_frame = nic_send_frame_impl;
 		if (!iface->connect_to_nil)
 			iface->connect_to_nil = nic_connect_to_nil_impl;
@@ -168,9 +168,9 @@
  *
  * @param nic_data
- * @param wpfunc		Function handling the write_packet request
- */
-void nic_set_write_packet_handler(nic_t *nic_data, write_packet_handler wpfunc)
-{
-	nic_data->write_packet = wpfunc;
+ * @param sffunc	Function handling the send_frame request
+ */
+void nic_set_send_frame_handler(nic_t *nic_data, send_frame_handler sffunc)
+{
+	nic_data->send_frame = sffunc;
 }
 
@@ -765,5 +765,5 @@
 	nic_data->poll_mode = NIC_POLL_IMMEDIATE;
 	nic_data->default_poll_mode = NIC_POLL_IMMEDIATE;
-	nic_data->write_packet = NULL;
+	nic_data->send_frame = NULL;
 	nic_data->on_activating = NULL;
 	nic_data->on_going_down = NULL;
Index: uspace/lib/nic/src/nic_impl.c
===================================================================
--- uspace/lib/nic/src/nic_impl.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/lib/nic/src/nic_impl.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -39,6 +39,4 @@
 #include <ipc/services.h>
 #include <ns.h>
-#include <packet_client.h>
-#include <packet_remote.h>
 #include "nic_driver.h"
 #include "nic_impl.h"
@@ -159,46 +157,25 @@
 
 /**
- * Default implementation of the send_message method.
+ * Default implementation of the send_frame method.
  * Send messages to the network.
  *
  * @param	fun
- * @param	packet_id	ID of the first packet in a queue of sent packets
+ * @param	data	Frame data
+ * @param 	size	Frame size in bytes
  *
  * @return EOK		If the message was sent
- * @return EBUSY	If the device is not in state when the packet can be set.
- * @return EINVAL	If the packet ID is invalid
- */
-int nic_send_message_impl(ddf_fun_t *fun, packet_id_t packet_id)
-{
-	nic_t *nic_data = (nic_t *) fun->driver_data;
-	packet_t *packet, *next;
+ * @return EBUSY	If the device is not in state when the frame can be sent.
+ */
+int nic_send_frame_impl(ddf_fun_t *fun, void *data, size_t size)
+{
+	nic_t *nic_data = (nic_t *) fun->driver_data;
 
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	if (nic_data->state != NIC_STATE_ACTIVE || nic_data->tx_busy) {
 		fibril_rwlock_read_unlock(&nic_data->main_lock);
-		pq_release_remote(nic_data->net_session, packet_id);
 		return EBUSY;
 	}
 
-	int rc = packet_translate_remote(nic_data->net_session, &packet, packet_id);
-
-	if (rc != EOK) {
-		fibril_rwlock_read_unlock(&nic_data->main_lock);
-		return EINVAL;
-	}
-
-	/*
-	 * Process the packet queue. Each sent packet must be detached from the
-	 * queue and destroyed. This is why the cycle differs from loopback's
-	 * cycle, where the packets are immediately used in upper layers and
-	 * therefore they must not be destroyed (released).
-	 */
-	assert(nic_data->write_packet != NULL);
-	do {
-		next = pq_detach(packet);
-		nic_data->write_packet(nic_data, packet);
-		packet = next;
-	} while (packet);
-	fibril_rwlock_read_unlock(&nic_data->main_lock);
+	nic_data->send_frame(nic_data, data, size);
 	return EOK;
 }
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/srv/net/nil/eth/eth.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -802,11 +802,11 @@
 			next = tmp;
 		} else {
+			nic_send_frame(device->sess, packet_get_data(next),
+			    packet_get_data_length(next));
 			next = pq_next(next);
 		}
 	} while (next);
 	
-	/* Send packet queue */
-	if (packet)
-		nic_send_message(device->sess, packet_get_id(packet));
+	pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
 	
 	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 6d8455d96fd6cd160666aef7ea55519828d14f42)
@@ -345,4 +345,6 @@
     services_t sender)
 {
+	packet_t *p;
+	
 	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
 	
@@ -354,7 +356,12 @@
 	}
 	
-	/* Send packet queue */
-	if (packet)
-		nic_send_message(device->sess, packet_get_id(packet));
+	p = packet;
+	do {
+		nic_send_frame(device->sess, packet_get_data(p),
+		    packet_get_data_length(p));
+		p = pq_next(p);
+	} while (p != NULL);
+	
+	pq_release_remote(nildummy_globals.net_sess, packet_get_id(packet));
 	
 	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
