diff --git a/os/include/nic/packet_allocator.h b/os/include/nic/packet_allocator.h
new file mode 100644
index 0000000000..33ebced178
--- /dev/null
+++ b/os/include/nic/packet_allocator.h
@@ -0,0 +1,128 @@
+/*
+ * \brief Fast-bitmap allocator for NIC-session packet streams
+ * \author Sebastian Sumpf
+ * \date 2012-07-30
+ *
+ * This allocator can be used with a nic session. It is *not* required though.
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__NIC__PACKET_ALLOCATOR__
+#define _INCLUDE__NIC__PACKET_ALLOCATOR__
+
+#include
+#include
+
+namespace Nic {
+
+ class Packet_allocator : public Genode::Range_allocator
+ {
+ private:
+
+ Genode::Allocator *_md_alloc; /* meta-data allocator */
+ unsigned _block_size; /* network packet size */
+ Genode::addr_t _base; /* allocation base */
+ unsigned *_free; /* free list */
+ int _curr_idx; /* current index in free list */
+ int _count; /* number of elements */
+
+ public:
+
+ enum { DEFAULT_PACKET_SIZE = 1600 };
+
+ /**
+ * Constructor
+ *
+ * \param md_alloc Meta-data allocator
+ * \param block_size Size of network packet in stream
+ */
+ Packet_allocator(Genode::Allocator *md_alloc,
+ unsigned block_size = DEFAULT_PACKET_SIZE)
+ : _md_alloc(md_alloc), _block_size(block_size), _base(0), _free(0),
+ _curr_idx(0), _count(0)
+ {}
+
+ ~Packet_allocator()
+ {
+ if (_free)
+ _md_alloc->free(_free, sizeof(unsigned) * (_count / 32));
+ }
+
+
+ /*******************************
+ ** Range-allocator interface **
+ *******************************/
+
+ int add_range(Genode::addr_t base, Genode::size_t size)
+ {
+ if (_count)
+ return -1;
+
+ _base = base;
+ _count = size / _block_size;
+ _free = (unsigned *)_md_alloc->alloc(sizeof(unsigned) * (_count / 32));
+
+ Genode::memset(_free, 0xff, sizeof(unsigned) * (_count / 32));
+ return 0;
+ }
+
+ bool alloc_aligned(Genode::size_t size, void **out_addr, int) {
+ return alloc(size, out_addr); }
+
+ bool alloc(Genode::size_t size, void **out_addr)
+ {
+ int free_cnt = _count / 32;
+
+ for (register int i = 0; i < free_cnt; i++) {
+
+ if (_free[_curr_idx] != 0) {
+ unsigned msb = Genode::log2(_free[_curr_idx]);
+ int elem_idx = (_curr_idx * 32) + msb;
+
+ if (elem_idx < _count) {
+ _free[_curr_idx] ^= (1 << msb);
+ *out_addr = reinterpret_cast(_base + (_block_size * elem_idx));
+ return true;
+ }
+ }
+
+ _curr_idx = (_curr_idx + 1) % free_cnt;
+ }
+ return false;
+ }
+
+ void free(void *addr)
+ {
+ Genode::addr_t a = reinterpret_cast(addr);
+
+ int elem_idx = (a - _base) / _block_size;
+ if (elem_idx >= _count)
+ return;
+
+ _curr_idx = elem_idx / 32;
+ _free[_curr_idx] |= (1 << (elem_idx % 32));
+ }
+
+ void free(void *addr, Genode::size_t) { free(addr); }
+
+
+ /*********************
+ ** Dummy functions **
+ *********************/
+
+ Genode::size_t overhead(Genode::size_t) { return 0;}
+ int remove_range(Genode::addr_t, Genode::size_t) { return 0;}
+ Genode::size_t avail() { return 0; }
+ bool valid_addr(Genode::addr_t) { return 0; }
+ Genode::Range_allocator::Alloc_return alloc_addr(Genode::size_t, Genode::addr_t) {
+ return OUT_OF_METADATA; }
+ };
+};
+
+#endif /* _INCLUDE__NIC__PACKET_ALLOCATOR__ */