diff --git a/repos/mml/run/raw_nic.run b/repos/mml/run/raw_nic.run
new file mode 100644
index 0000000000..f2c730a1ea
--- /dev/null
+++ b/repos/mml/run/raw_nic.run
@@ -0,0 +1,124 @@
+create_boot_directory
+import_from_depot [depot_user]/src/[base_src] \
+ [depot_user]/pkg/[drivers_nic_pkg] \
+ [depot_user]/src/init \
+ [depot_user]/src/libc \
+ [depot_user]/src/stdcxx \
+ [depot_user]/src/nic_router \
+ [depot_user]/src/vfs_audit \
+ [depot_user]/src/vfs
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+append qemu_args " -nographic "
+append_qemu_nic_args "host=10.0.2.1,dhcpstart=10.0.2.55,hostfwd=tcp::10080-:80,hostfwd=tcp::18080-:8080,hostfwd=udp::10007-:7,hostfwd=udp::17070-:7070"
+
+build { app/raw_nic app/ping }
+
+install_config $config
+build_boot_image { raw_nic ping }
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/src/app/raw_nic/main.cpp b/repos/mml/src/app/raw_nic/main.cpp
new file mode 100644
index 0000000000..8f740d703c
--- /dev/null
+++ b/repos/mml/src/app/raw_nic/main.cpp
@@ -0,0 +1,128 @@
+#include
+#include
+#include
+#include
+#include
+
+/* CiAO/IP includes */
+#include
+#include
+#include
+#include
+
+class Raw_nic : public hw::hal::NetworkDevice
+{
+ private:
+ Nic::Packet_allocator _nic_tx_alloc;
+ Nic::Connection _nic;
+ Genode::Mutex _mutex{};
+
+ unsigned char _mac[6];
+
+ Genode::Io_signal_handler _link_state_handler;
+ Genode::Io_signal_handler _rx_packet_handler;
+ Genode::Io_signal_handler _tx_ready_handler;
+
+ enum
+ {
+ PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
+ BUFF_SIZE = Nic::Session::QUEUE_SIZE * PACKET_SIZE
+ };
+
+ public:
+ void handle_link_state()
+ {
+ Genode::log("Link state requested.");
+ }
+
+ void handle_rx_packets()
+ {
+ auto &rx = *_nic.rx();
+
+ while (rx.packet_avail() && rx.ready_to_ack() ) {
+ Nic::Packet_descriptor packet = rx.get_packet();
+ Genode::log("Received packet of size ", packet.size());
+
+ void *eth_frame = rx.packet_content(packet);
+
+ demux(eth_frame, packet.size());
+ if (!rx.ready_to_ack())
+ return;
+
+ rx.acknowledge_packet(packet);
+ }
+ }
+
+ void handle_tx_ready()
+ {
+ auto &tx = *_nic.tx();
+
+ while (tx.ack_avail())
+ tx.release_packet(tx.get_acked_packet());
+
+ Genode::log("Send packets");
+ }
+
+ void send(const void* pkt, unsigned pkt_size ) override
+ {
+ try {
+ Nic::Packet_descriptor pkt_desc = _nic.tx()->alloc_packet(pkt_size);
+ void *pkt_base = _nic.tx()->packet_content(pkt_desc);
+
+ Genode::memcpy(pkt_base, pkt, pkt_size);
+
+ _nic.tx()->submit_packet(pkt_desc);
+ } catch (Nic::Packet_stream_source::Packet_alloc_failed) {
+ Genode::warning("Packet allocation has failed.");
+ }
+ }
+
+ Raw_nic(Genode::Env &env, Genode::Allocator &alloc) : _nic_tx_alloc(&alloc), _nic(env, &_nic_tx_alloc, BUFF_SIZE, BUFF_SIZE), _link_state_handler(env.ep(), *this, &Raw_nic::handle_link_state), _rx_packet_handler(env.ep(), *this, &Raw_nic::handle_rx_packets), _tx_ready_handler(env.ep(), *this, &Raw_nic::handle_tx_ready) {
+ Genode::log("Created NIC session.");
+ Genode::log("Registering callbacks");
+ _nic.link_state_sigh(_link_state_handler);
+ _nic.rx_channel()->sigh_packet_avail(_rx_packet_handler);
+ _nic.rx_channel()->sigh_ready_to_ack(_rx_packet_handler);
+ _nic.tx_channel()->sigh_ready_to_submit(_tx_ready_handler);
+ _nic.tx_channel()->sigh_ack_avail (_tx_ready_handler);
+ Genode::log("Callbacks registered. Waiting for incoming packets...");
+ Genode::log("MAC address from NIC session: ", _nic.mac_address());
+ _nic.mac_address().copy(_mac);
+ Genode::log("Mac address read: ", _mac[0], ":", _mac[1], ":", _mac[2], ":", _mac[3], ":", _mac[4], ":", _mac[5]);
+ init();
+ Genode::log("Initialized CiAO/IP");
+
+ ipstack::Interface *interface = IP::getInterface(0);
+ if (interface) {
+ interface->setIPv4Addr(10, 0, 3,55);
+ interface->setIPv4Subnetmask(255, 255, 255, 0);
+ interface->setIPv4Up(true);
+ ipstack::Router::Inst().ipv4_set_gateway_addr(ipstack::IPv4_Packet::convert_ipv4_addr(10, 0, 3, 1));
+ }
+ }
+
+ /* CiAO/IP NetworkDevice public interface */
+ const char* getName() override {
+ return "eth0";
+ }
+
+ unsigned getMTU() override {
+ return 1500;
+ }
+
+ const unsigned char *getAddress() override {
+ return _mac;
+ }
+
+ unsigned char getType() override { return 1; }
+
+
+};
+
+void Libc::Component::construct(Libc::Env &env)
+{
+ static Genode::Heap heap{env.ram(), env.rm()};
+
+ static Raw_nic _raw_nic(env, heap);
+
+}
\ No newline at end of file
diff --git a/repos/mml/src/app/raw_nic/target.mk b/repos/mml/src/app/raw_nic/target.mk
new file mode 100644
index 0000000000..7999f80592
--- /dev/null
+++ b/repos/mml/src/app/raw_nic/target.mk
@@ -0,0 +1,3 @@
+TARGET = raw_nic
+SRC_CC += main.cpp
+LIBS = base libm libc stdcxx lwip
\ No newline at end of file