DeviceQueue: forwarding working up to other endpoint, way back not yet
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 22 Aug 2016 16:06:45 +0000 (18:06 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 22 Aug 2016 16:06:45 +0000 (18:06 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

include/devif/queue_interface.h
lib/devif/queue_interface.c
usr/tests/devif/Hakefile
usr/tests/devif/forward_device.c [new file with mode: 0644]
usr/tests/devif/loopback_device.c
usr/tests/devif/queue_interface.c

index 0c48430..1f10139 100644 (file)
 #define MAX_DEVICE_NAME 256
 
 #define ENDPOINT_TYPE_FORWARD 0x1
-#define ENDPOINT_TYPE_BLOCK 0x2
-#define ENDPOINT_TYPE_NET 0x3
-#define ENDPOINT_TYPE_DIRECT 0x4
+#define ENDPOINT_TYPE_BLOCK 0x3
+#define ENDPOINT_TYPE_DEVICE 0x4
+#define ENDPOINT_TYPE_DIRECT 0x5
 
 // the user side of the queue
 #define ENDPOINT_TYPE_USER 0xF
+// only internal?
+#define ENDPOINT_TYPE_FORWARD_TX 0x11
 
 typedef uint32_t regionid_t;
 typedef uint32_t bufferid_t;
index b2db757..a5ca4d3 100644 (file)
@@ -62,9 +62,6 @@ struct devq {
     uint32_t q_size;
     uint32_t buf_size;
     
-    // devq struct with swapped rx/tx
-    struct devq* reverse;
-
     //TODO Other state needed ...
 };
 
@@ -108,9 +105,17 @@ static void mp_setup_request(struct devif_binding* b)
     struct endpoint_state* state = (struct endpoint_state*) b->st;
 
     // Call setup function on local device
-    err = state->f.setup(&features, &default_qsize, &default_bufsize, 
-                         &reconnect, name);
-    assert(err_is_ok(err));    
+    if (state->endpoint_type == ENDPOINT_TYPE_FORWARD) {
+        struct devq* tx = (struct devq*) state->q;
+        features = tx->end->features;
+        default_qsize = tx->q_size;
+        default_bufsize = tx->buf_size;
+        reconnect = false;
+    } else {
+        err = state->f.setup(&features, &default_qsize, &default_bufsize, 
+                             &reconnect, name);
+        assert(err_is_ok(err));    
+    }
 
     err = b->tx_vtbl.setup_reply(b, NOP_CONT, features, default_qsize,
                                  default_bufsize, reconnect, 
@@ -145,10 +150,21 @@ static void mp_create(struct devif_binding* b, struct capref rx,
     // Create the device queue
     // TODO we might need to know the name of the 
     // endpoint that connected to the device
-    err = devq_create(&q, state, "", 0);
-    if (err_is_fail(err)) {   
-        err = b->tx_vtbl.reply_err(b, NOP_CONT, err);
-        assert(err_is_ok(err));
+
+    if (state->endpoint_type != ENDPOINT_TYPE_FORWARD) {
+        err = devq_create(&q, state, "", 0);
+        if (err_is_fail(err)) {   
+            err = b->tx_vtbl.reply_err(b, NOP_CONT, err);
+            assert(err_is_ok(err));
+        }   
+    } else {
+        state->endpoint_type = ENDPOINT_TYPE_DEVICE;
+        err = devq_create(&q, state, "", 0);
+        if (err_is_fail(err)) {   
+            err = b->tx_vtbl.reply_err(b, NOP_CONT, err);
+            assert(err_is_ok(err));
+        }
+        state->endpoint_type = ENDPOINT_TYPE_FORWARD;
     }
     
     q->end = state;
@@ -181,12 +197,24 @@ static void mp_register(struct devif_binding* b, struct capref mem,
     DQI_DEBUG("Register Rid=%d \n", region_id);
     struct devq* q = (struct devq*) b->st;
     
-    // TODO Add to pool on this side
+    if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD) {
+        // forward directly
+        struct devq* tx = (struct devq*) q->end->q;
+        init_rpc(tx);
+        err = tx->b->tx_vtbl.reg(tx->b, NOP_CONT, mem, region_id);
+        wait_for_rpc(tx);    
+        if (err_is_fail(tx->err)) {
+            err = b->tx_vtbl.reply_err(b, NOP_CONT, err);
+            assert(err_is_ok(err));
+        }
+    
+    } else {
+        err = region_pool_add_region_with_id(q->pool, mem, region_id);
+        if (err_is_fail(err)) {
+            err = b->tx_vtbl.reply_err(b, NOP_CONT, err);
+            assert(err_is_ok(err));
+        }
 
-    err = region_pool_add_region_with_id(q->pool, mem, region_id);
-    if (err_is_fail(err)) {
-        err = b->tx_vtbl.reply_err(b, NOP_CONT, err);
-        assert(err_is_ok(err));
     }
 
     err = q->end->f.reg(q, mem, region_id); 
@@ -242,14 +270,60 @@ static void mp_control(struct devif_binding* b, uint64_t cmd,
 static void mp_notify(struct devif_binding* b, uint8_t num_slots)
 {
     errval_t err;
-    DQI_DEBUG("Notify \n");
     struct devq* q = (struct devq*) b->st;
-
     // Sending notification
-    err = q->end->f.notify(q, num_slots); 
-    assert(err_is_ok(err));
+
+    regionid_t region_id;
+    bufferid_t buffer_id;
+    lpaddr_t base;
+    size_t len;
+    uint64_t misc_flags;
+    if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD) {
+        // forward
+        struct devq* tx = (struct devq*) q->end->q;
+        for (int i = 0; i < num_slots; i++) {
+            err = descq_dequeue(q->rx, &region_id, &buffer_id,
+                                &base, &len, &misc_flags);
+            assert(err_is_ok(err));
+            // TODO call function locally to inform point (dequeue)
+            err = descq_enqueue(tx->tx, region_id, buffer_id,
+                                base, len, misc_flags);
+            assert(err_is_ok(err));
+        }
+
+        descq_writeout_head(tx->tx);
+        err = tx->b->tx_vtbl.notify(tx->b, NOP_CONT, num_slots);
+        assert(err_is_ok(err));
     
-    descq_writeout_tail(q->rx);
+        err = tx->end->f.notify(q, num_slots);
+    } else if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD_TX) {
+        // forward
+        USER_PANIC("NYI forwarding back \n");
+        /*
+        struct devq* tx = (struct devq*) q->end->q;
+        for (int i = 0; i < num_slots; i++) {
+            err = descq_dequeue(q->rx, &region_id, &buffer_id,
+                                &base, &len, &misc_flags);
+            assert(err_is_ok(err));
+
+            // TODO call function locally enqueue (dequeue)
+            err = descq_enqueue(tx->tx, region_id, buffer_id,
+                                base, len, misc_flags);
+            assert(err_is_ok(err));
+        }
+
+        descq_writeout_head(tx->tx);
+        err = tx->b->tx_vtbl.notify(tx->b, NOP_CONT, num_slots);
+        assert(err_is_ok(err));
+    
+        err = q->end->f.notify(q, num_slots);
+        */
+    } else {
+        err = q->end->f.notify(q, num_slots); 
+        assert(err_is_ok(err));
+        
+        descq_writeout_tail(q->rx);
+    }
 }
 
 static void mp_reply_err(struct devif_binding* b, errval_t err)
@@ -338,7 +412,7 @@ static errval_t connect_cb(void *st, struct devif_binding* b)
 errval_t devq_driver_export(struct endpoint_state* s)
 {
     errval_t err;
-        
+    
     err = devif_export(s, export_cb, connect_cb, get_default_waitset(),
                        IDC_BIND_FLAGS_DEFAULT);
     if (err_is_fail(err)) {
@@ -383,7 +457,7 @@ errval_t devq_create(struct devq **q,
     tmp->end = end;
 
     strncpy(tmp->endpoint_name, endpoint_name, MAX_DEVICE_NAME);
-    
+
     err = region_pool_init(&(tmp->pool));
     if (err_is_fail(err)) {
         free(tmp);
@@ -400,10 +474,7 @@ errval_t devq_create(struct devq **q,
                 return err;
             }
             break;
-        case ENDPOINT_TYPE_BLOCK:
-            tmp->b = tmp->end->b;
-            break;
-        case ENDPOINT_TYPE_NET:
+        case ENDPOINT_TYPE_DEVICE:
             tmp->b = tmp->end->b;
             break;
         case ENDPOINT_TYPE_DIRECT:
@@ -540,7 +611,45 @@ static errval_t devq_init_descqs(struct devq *q,
 static errval_t devq_init_forward(struct devq *q,
                                   uint64_t flags)
 {
-    USER_PANIC("NYI");
+    errval_t err;
+    
+    char* end_name = malloc(MAX_DEVICE_NAME);
+    
+    sprintf(end_name, "%s_%s", "forward", q->endpoint_name);
+    strncpy(q->end->device_name, end_name, MAX_DEVICE_NAME);
+
+    // allocate forward queue by hand
+    // this is the queue to the device
+    struct devq* tx = malloc(sizeof(struct devq));
+    tx->end = q->end;
+    tx->end = malloc(sizeof(struct endpoint_state));
+    tx->end->f = q->end->f;
+
+    strncpy(tx->endpoint_name, q->endpoint_name, MAX_DEVICE_NAME);
+    tx->end->endpoint_type = ENDPOINT_TYPE_FORWARD_TX;
+    tx->state = DEVQ_STATE_UNINITIALIZED;
+    tx->end->export_done = false;
+    tx->end->features = 0;
+    
+    err = devq_init_user(tx, flags);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    q->end->q = (void*) tx;
+    tx->end->q = (void*) q;
+    // export interface
+    err = devif_export(q->end, export_cb, connect_cb, get_default_waitset(),
+                       IDC_BIND_FLAGS_DEFAULT);
+    if (err_is_fail(err)) {
+        DQI_DEBUG("Exporting devif interface failed \n");   
+        return err;
+    }
+
+    while (!q->end->export_done) {
+        event_dispatch(get_default_waitset());
+    }
+
     return SYS_ERR_OK;
 }
 
index 0935a92..b43aa79 100644 (file)
@@ -16,5 +16,9 @@
 
   build application { target = "devif_loopback_device", 
                       cFiles = [ "loopback_device.c" ],
+                      addLibraries = [ "devif" ] },
+
+  build application { target = "devif_forward_device", 
+                      cFiles = [ "forward_device.c" ],
                       addLibraries = [ "devif" ] }
 ]
diff --git a/usr/tests/devif/forward_device.c b/usr/tests/devif/forward_device.c
new file mode 100644 (file)
index 0000000..f2f2a4f
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/waitset.h>
+#include <barrelfish/deferred.h>
+#include <devif/queue_interface.h>
+
+static struct devq_func_pointer f;
+
+errval_t create_forward(struct devq* q, uint64_t flags);
+errval_t register_forward(struct devq* q, struct capref cap,
+                         regionid_t rid);
+errval_t deregister_forward(struct devq* q, regionid_t rid);
+errval_t control_forward(struct devq* q, uint64_t cmd, uint64_t value);
+errval_t destroy_forward(struct devq* q);
+errval_t notify_forward(struct devq* q, uint8_t num_slots);
+
+
+errval_t create_forward(struct devq* q, uint64_t flags)
+{
+    return SYS_ERR_OK;
+}
+
+errval_t register_forward(struct devq* q, struct capref cap,
+                         regionid_t rid) 
+{
+    return SYS_ERR_OK;
+}
+
+
+errval_t deregister_forward(struct devq* q, regionid_t rid) 
+{
+    return SYS_ERR_OK;
+}
+
+
+errval_t control_forward(struct devq* q, uint64_t cmd, uint64_t value)
+{
+    return SYS_ERR_OK;
+}
+
+
+errval_t notify_forward(struct devq* q, uint8_t num_slots)
+{
+    return SYS_ERR_OK;
+}
+
+errval_t destroy_forward(struct devq* q)
+{
+    return SYS_ERR_OK;
+}
+
+int main(int argc, char *argv[])
+{
+
+    errval_t err;
+    struct devq* q;   
+    f.create = create_forward;
+    f.reg = register_forward;
+    f.dereg = deregister_forward;
+    f.notify = notify_forward;
+    f.destroy = destroy_forward;
+    f.ctrl = control_forward;   
+
+    struct endpoint_state my_state = {
+        .endpoint_type = ENDPOINT_TYPE_FORWARD,
+        .device_name = "", // name will be assigned 
+        .q = NULL,
+        .features = 0,
+        .f = f,
+    };
+
+    printf("Forward queue created\n");
+    err = devq_create(&q, &my_state, "loopback", 1);
+    if (err_is_fail(err)){
+        USER_PANIC("Allocating devq failed \n");
+    }    
+
+    while(true) {
+        event_dispatch(get_default_waitset());
+    }
+}
+
index 9999f01..ff28728 100644 (file)
@@ -32,7 +32,7 @@ int main(int argc, char *argv[])
     };
 
     struct endpoint_state my_state = {
-        .endpoint_type = ENDPOINT_TYPE_NET,
+        .endpoint_type = ENDPOINT_TYPE_DEVICE,
         .device_name = "loopback",
         .q = NULL,
         .features = 0,
index 2ac24d4..ea4dd62 100644 (file)
@@ -278,6 +278,71 @@ static void test_direct_device(void)
     printf("Direct device test ended\n");
 }
 
+
+static void test_forward_device(void) 
+{
+
+    errval_t err;
+    struct devq* q;   
+
+    struct devq_func_pointer f = {
+        .notify = notify_normal,
+    };
+
+    struct endpoint_state my_state = {
+        .endpoint_type = ENDPOINT_TYPE_USER,
+        .q = NULL,
+        .features = 0,
+        .f = f,
+    };
+
+    printf("Forward device test started \n");
+    err = devq_create(&q, &my_state, "forward_loopback", 1);
+    if (err_is_fail(err)){
+        USER_PANIC("Allocating devq failed \n");
+    }    
+
+    err = devq_register(q, memory, &regid);
+    if (err_is_fail(err)){
+        USER_PANIC("Registering memory to devq failed \n");
+    }
+    
+    bufferid_t ids[NUM_ENQ];
+    lpaddr_t addr;
+    for (int j = 0; j < NUM_ROUNDS; j++) {
+        for (int i = 0; i < NUM_ENQ; i++) {
+            addr = phys+(j*NUM_ENQ*2048+i*2048);
+            err = devq_enqueue(q, regid, addr, 2048, 
+                               1, &ids[i]);
+            if (err_is_fail(err)){
+                USER_PANIC("Devq enqueue failed \n");
+            }    
+        }
+     
+        err = devq_notify(q);
+        if (err_is_fail(err)) {
+            printf("%s",err_getstring(err));
+        }
+        event_dispatch(get_default_waitset());
+    }
+    
+    err = devq_control(q, 1, 1);
+    if (err_is_fail(err)){
+        printf("%s \n", err_getstring(err));
+        USER_PANIC("Devq control failed \n");
+    }
+
+    err = devq_deregister(q, regid, &memory);
+    if (err_is_fail(err)){
+        printf("%s \n", err_getstring(err));
+        USER_PANIC("Devq deregister failed \n");
+    }
+
+    err = devq_destroy(q);
+
+    printf("Forward device test ended\n");
+}
+
 int main(int argc, char *argv[])
 {
     errval_t err;
@@ -294,6 +359,7 @@ int main(int argc, char *argv[])
     
     phys = id.base;
 
+    test_forward_device();
     test_normal_device();
     test_direct_device();
 }