diff --git a/mc/hijacknet_extctrl2014.c b/mc/hijacknet_extctrl2014.c
index b1c0919cfc6a90e1ef020fe70c5ec5099008a472..ba77d4e855ae5f84092851379a6f9c784efe67b7 100644
--- a/mc/hijacknet_extctrl2014.c
+++ b/mc/hijacknet_extctrl2014.c
@@ -44,7 +44,8 @@ acN.value[0] acN.value[1] acN.value[2] acN.value[3] idN
 #define MAX_JOINT 128
 #define MAX_ROBOT 4
 #define MAX_FORCE_SENSORS 1
-#define BUFFER_SIZE 1500
+#define WRITE_BUFFER_SIZE 1500
+#define READ_BUFFER_SIZE 8192
 
 extern unsigned long int cpuFrequency;
 
@@ -86,18 +87,26 @@ static struct state {
   int channel;
   int cookie;
   int received;
-  struct encoder_writer {
+  struct {
     struct labcomm2014_writer writer;
     struct labcomm2014_writer_action_context action_context;
+    struct labcomm2014_encoder *encoder;
+    int sequence;
     int unadjusted;
     int need_ack;
     int frag_start;
-    unsigned char buffer[BUFFER_SIZE];
+    unsigned char buffer[WRITE_BUFFER_SIZE];
   } writer;
   struct {
-    struct labcomm2014_encoder *encoder;
-    int sequence;
-  } encoder;
+    struct labcomm2014_reader reader;
+    struct labcomm2014_reader_action_context action_context;
+    SEM_ID sem;
+    int lpconsume;
+    unsigned char buffer[READ_BUFFER_SIZE];
+    unsigned int read_pos;
+    unsigned int write_pos;
+    unsigned int available;
+  } reader;
   struct {
     struct labcomm2014_decoder *decoder;
     int sequence;
@@ -956,8 +965,8 @@ static int writer_alloc(
 {
   printf("%s %s %s\n", __FUNCTION__, __DATE__, __TIME__);
   w->data = state.writer.buffer;
-  w->data_size = BUFFER_SIZE;
-  w->count = BUFFER_SIZE;
+  w->data_size = WRITE_BUFFER_SIZE;
+  w->count = WRITE_BUFFER_SIZE;
   w->pos = 0;
 
   return w->error;
@@ -1016,7 +1025,7 @@ static int writer_start(
   labcomm2014_write_byte(w, flags);
   labcomm2014_write_packed32(w, state.channel);
   labcomm2014_write_int(w, cookie);
-  labcomm2014_write_int(w, index);
+  labcomm2014_write_int(w, state.writer.sequence);
   /* reserve maximum space for frag_num and frag_length */
   state.writer.frag_start = w->pos;
   w->pos += 10;
@@ -1048,7 +1057,8 @@ static int writer_end(
   }
   printf("%s %d\n", __FUNCTION__, w->pos);
   hijacknet_send(state.driver, w->data, w->pos);
-   
+
+  taskDelay(1000);
   return w->error;
 }
 
@@ -1079,23 +1089,177 @@ static void init_writer()
   state.writer.writer.action_context = &state.writer.action_context;
   state.writer.writer.memory = NULL;
   state.writer.writer.data = state.writer.buffer;
-  state.writer.writer.data_size = BUFFER_SIZE;
-  state.writer.writer.count = BUFFER_SIZE;
+  state.writer.writer.data_size = WRITE_BUFFER_SIZE;
+  state.writer.writer.count = WRITE_BUFFER_SIZE;
   state.writer.writer.pos = 0;
 }
 
+static int reader_fill(
+  struct labcomm2014_reader *r, 
+  struct labcomm2014_reader_action_context *action_context)
+{
+  int result = 0;
+
+  if (state.reader.available) {
+    unsigned int consume;
+
+    consume = state.reader.available;
+    if (r->pos == READ_BUFFER_SIZE) {
+      /* Handle wrap around */
+      r->pos = 0;
+    } else if (r->pos + consume > READ_BUFFER_SIZE) {
+      /* Packet wraps around, consume first part */
+      consume = READ_BUFFER_SIZE - r->pos;
+    }
+    r->count = r->pos + consume;
+    state.reader.available -= consume;
+    result = consume;
+    printf("Fill %d %d %d\n", consume, state.reader.available, r->pos);
+  } else {
+    r->count = 0;
+    r->error = -ENODATA;
+    printf("Fill error\n");
+  }
+  return result;
+}
+
+static const struct labcomm2014_reader_action reader_action = {
+  .alloc = NULL,
+  .free = NULL,
+  .start = NULL,
+  .fill = reader_fill,
+  .end = NULL,
+  .ioctl = NULL
+};
+
+static void init_reader()
+{
+  state.reader.read_pos = 0;
+  state.reader.write_pos = 0;
+  state.reader.available = 0;
+  state.reader.action_context.next = NULL;
+  state.reader.action_context.action = &reader_action;
+  state.reader.action_context.context = &state.reader;
+  state.reader.reader.action_context = &state.reader.action_context;
+  state.reader.reader.memory = NULL;
+  state.reader.reader.data = state.reader.buffer;
+  state.reader.reader.data_size = READ_BUFFER_SIZE;
+  state.reader.reader.count = 0;
+  state.reader.reader.pos = 0;
+}
+
 static int receive_hook(HIJACKNET_DRIVER *driver,
                         void *data, int length,
                         void *context)
 {
   FP_CONTEXT  fp_context;
-
+  unsigned int free, avail;
+  unsigned char *src = data;
+  
   fppSave(&fp_context);
-  state.received += length;
+  avail = (state.reader.write_pos - state.reader.read_pos) % READ_BUFFER_SIZE;
+  free = READ_BUFFER_SIZE - avail;
+  if (free >= length + 2) {
+    unsigned int i, pos;
+
+    pos = state.reader.write_pos;
+    state.reader.buffer[pos] = (length & 0xff00) >> 8;
+    pos = (pos + 1) % READ_BUFFER_SIZE;
+    state.reader.buffer[pos] = (length & 0xff);
+    pos = (pos + 1) % READ_BUFFER_SIZE;
+    for (i = 0 ; i < length ; i++) {
+      state.reader.buffer[pos] = src[i];
+      pos = (pos + 1) % READ_BUFFER_SIZE;
+    }
+    state.reader.write_pos = pos;
+  }
+
   fppRestore(&fp_context);
   return length;
 }
 
+static int lp_consume()
+{
+  unsigned int avail;
+
+  while (1) {
+    semTake(state.reader.sem, 1000);
+    avail = (state.reader.write_pos - state.reader.read_pos) % READ_BUFFER_SIZE;
+    if (avail > 2) {
+      unsigned int length, pos, sane, i, channel, cookie, index;
+      unsigned short id;
+      unsigned char flags;
+      
+      pos = state.reader.read_pos;
+      printf("read_pos=%d avail=%d\n", pos, avail);
+      
+      /* Length of raw packet */
+      length = state.reader.buffer[pos] << 8;
+      pos = (pos + 1) % READ_BUFFER_SIZE;
+      printf("length=%d pos=%d\n", length, pos);
+      length |= state.reader.buffer[pos];
+      pos = (pos + 1) % READ_BUFFER_SIZE;
+      printf("length=%d pos=%d\n", length, pos);
+
+      /* Setup reader */
+      state.reader.available = length;
+      state.reader.reader.pos = pos;
+      labcomm2014_reader_fill(&state.reader.reader,
+                              state.reader.reader.action_context);
+
+
+      /* Sanity check package */
+      sane = 1;
+      for (i = 0 ; i < 6 ; i++) {
+        unsigned char b;
+
+        b = labcomm2014_read_byte(&state.reader.reader);
+        sane &= (b == state.src[i]);
+      }
+      printf("sane=%d\n", sane);
+      for (i = 0 ; i < 6 ; i++) {
+        unsigned char b;
+
+        b = labcomm2014_read_byte(&state.reader.reader);
+        sane &= (b == state.dst[i]);
+      }
+      id = labcomm2014_read_short(&state.reader.reader);
+      sane &= (id == EXTCTRL2015_ETH_ID);
+      flags = labcomm2014_read_byte(&state.reader.reader);
+      channel = labcomm2014_read_packed32(&state.reader.reader);
+      sane &= (channel == state.channel);
+      cookie = labcomm2014_read_int(&state.reader.reader);
+      index = labcomm2014_read_int(&state.reader.reader);
+
+      printf("sane=%d flags=%02x channel=%d cookie=%x index=%u\n",
+             sane, flags, channel, cookie, index);
+
+      if (!sane) { goto out; }
+      if ((flags & flag_LAST_FRAG) == 0) {
+        printf("Implement defragmentation\n");
+        goto out;
+      }
+      if ((flags & flag_IS_ACK) != 0) {
+        if (index == state.ack) {
+          self.ack = 0;
+          NOTIFY;
+        }
+        if (index ==
+      /* Decode one package */
+      
+
+    out:
+      /* Update read position */
+      state.reader.read_pos =
+        (state.reader.read_pos + 2 + length) % READ_BUFFER_SIZE;
+      
+
+    }
+    printf("Available: %d\n", avail);
+  }
+  return 0;
+}
+
 static int read_robot_data(char *path)
 {
   int result = 0;
@@ -1269,8 +1433,20 @@ int hijacknet_extctrl2014_connect(char *interface,
     return -9;
   }
 
+  state.cpu_MHz = cpuFrequency / 1000000;
+  state.mutex = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
+  state.sem = semBCreate(0, 0);
+  state.sem_communicate = semBCreate(0, 0);
+  state.reader.sem = semBCreate(0, 0);
+
+  /* Enumerate signatures, since no proper code init in VxWorks */
   init_extctrl2014__signatures();
-  state.received = 0;
+  init_writer();
+  init_reader();
+
+  state.reader.lpconsume = taskSpawn("HNlpconsume", 254, 0, 20000, lp_consume,
+                                     0,0,0,0,0,0,0,0,0,0);
+
   state.driver = hijacknet_open(interface);
   hijacknet_get_mac_address(state.driver, state.src);
   
@@ -1278,7 +1454,6 @@ int hijacknet_extctrl2014_connect(char *interface,
   printf("%s", etoa(state.src));
 
   hijacknet_extctrl2014_status();
-  init_writer();
   hijacknet_add_receive_hook(state.driver, EXTCTRL2015_ETH_ID,
                              receive_hook, NULL);
   
@@ -1289,34 +1464,32 @@ int hijacknet_extctrl2014_connect(char *interface,
   labcomm2014_writer_end(&state.writer.writer,
                          state.writer.writer.action_context);
   /* Immediate retry... */
+  taskDelay(1000);
   labcomm2014_writer_end(&state.writer.writer,
                          state.writer.writer.action_context);
 
   /* register data types */
-  state.encoder.encoder = labcomm2014_encoder_new(
+  state.writer.encoder = labcomm2014_encoder_new(
     &state.writer.writer,
     labcomm2014_default_error_handler,
     labcomm2014_default_memory,
     labcomm2014_default_scheduler);
   labcomm2014_encoder_register_extctrl2014_irb2ext_net(
-    state.encoder.encoder);
+    state.writer.encoder);
   labcomm2014_encoder_register_extctrl2014_force_torque_net(
-    state.encoder.encoder);    
-  taskDelay(1000);
-  labcomm2014_encoder_free(state.encoder.encoder);
+    state.writer.encoder);    
+  taskDelay(10000);
+  labcomm2014_encoder_free(state.writer.encoder);
   hijacknet_del_receive_hook(state.driver, EXTCTRL2015_ETH_ID,
                              receive_hook, NULL);
   hijacknet_close(state.driver);
-  printf("Received: %d\n", state.received);
+  printf("%d %d\n", state.reader.write_pos, state.reader.read_pos);
+  taskDelete(state.reader.lpconsume);
 #if 0
 #endif
 //  state.decoder.decoder = labcomm2014_decoder_new(reader, &state);
 
 //  state.unit = unit;
-  state.cpu_MHz = cpuFrequency / 1000000;
-  state.mutex = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
-  state.sem = semBCreate(0, 0);
-  state.sem_communicate = semBCreate(0, 0);
 
 #if 0
   if (lth_net_add_hook(state.unit, hook, &state) != 0) {
diff --git a/simulator/extctrl2014.py b/simulator/extctrl2014.py
index 28e7029a21484146b3b818a888dc4cae87539acd..4ed94e443b5b56bd5736ba65350565e1515b0c01 100644
--- a/simulator/extctrl2014.py
+++ b/simulator/extctrl2014.py
@@ -216,7 +216,7 @@ class ExtCtrl(object):
         self.max_length = max_length
         self.read_data = list()
         self.cond = threading.Condition()
-        self.local_index = random.randint(0,2**32-1)
+        self.local_index = random.randint(1,2**32-1)
         self.remote_index = None
         self.cookie = None
         self.ack = None
@@ -227,7 +227,9 @@ class ExtCtrl(object):
             self.send_INIT()
         elif self.robot:
             self.await_INIT()
-        
+
+    def next_index(self):
+        self.local_index = max(1, (self.local_index + 1) & 0xffffffff)
 
     def recv_loop(self):
         ack = None
@@ -330,7 +332,7 @@ class ExtCtrl(object):
         for i in self.retries(self.local_index):
             for f in fragmenter.fragments(max_length=self.max_length):
                 self.ethernet.send(f.getvalue())
-        self.local_index += 1
+        self.next_index()
 
     def send_INIT_ACK(self):
         flags = kind_INIT | flag_IS_ACK
@@ -364,7 +366,7 @@ class ExtCtrl(object):
         for i in self.retries(self.local_index):
             for f in fragmenter.fragments(max_length=self.max_length):
                 self.ethernet.send(f.getvalue())
-        self.local_index += 1
+        self.next_index()
 
     def send_DATA(self, data):
         flags = kind_DATA
@@ -376,7 +378,7 @@ class ExtCtrl(object):
         fragmenter.write(data)
         for f in fragmenter.fragments(max_length=self.max_length):
             self.ethernet.send(f.getvalue())
-        self.local_index += 1
+        self.next_index()
 
     def writer(self):
         class Writer: