simplify out-of-band cap transfer to avoid asynchronously reporting errors back to...
authorAndrew Baumann <andrew.baumann@microsoft.com>
Mon, 23 Jan 2012 21:32:56 +0000 (13:32 -0800)
committerAndrew Baumann <andrew.baumann@microsoft.com>
Mon, 23 Jan 2012 21:32:56 +0000 (13:32 -0800)
As discussed on the mailing list (10.01.2012 "Proposed change to
out-of-band cap transfer"), this change changes the semantics so that
an error in delivery of the cap is reported to the receiver (rather
than asynchronously to the sender) along with a NULL capref. This
simplifies the implementation within the monitor, and results in saner
error handling on both sides.

if/intermon.if
if/monitor.if
include/barrelfish/monitor_client.h
lib/barrelfish/monitor_client.c
lib/barrelfish/multihop_chan.c
tools/flounder/Multihop.hs
tools/flounder/UMPCommon.hs
usr/monitor/inter.c
usr/monitor/monitor_server.c
usr/monitor/multihop_support.c

index 42660c2..96f56c5 100644 (file)
@@ -93,13 +93,11 @@ interface intermon "The Interface between monitors" {
         message cap_send_request(con_id_t con_id,
                                  capid_t capid,
                                  caprep cap,
+                                 errval err,
                                  bool give_away,
                                  bool has_descendents,
                                  coremask on_cores,
                                 bool null_cap);
-        message cap_send_reply(con_id_t con_id,
-                               capid_t capid,
-                               errval err);
 
         message span_domain_request(state_id_t state_id,
                                     genpaddr vnodebase,
@@ -137,6 +135,5 @@ interface intermon "The Interface between monitors" {
     message bind_multihop_intermon_reply(vci_t receiver_vci, vci_t sender_vci, errval err);
 
     message multihop_message(vci_t vci, uint8 direction, uint8 flags, uint32 ack, uint8 payload[size]);
-    message multihop_cap_send(vci_t vci, uint8 direction, capid_t capid, caprep cap, bool null_cap);
-    message multihop_cap_reply(vci_t vci, uint8 direction, capid_t capid, errval err);
+    message multihop_cap_send(vci_t vci, uint8 direction, capid_t capid, errval err, caprep cap, bool null_cap);
 };
index 9a1d67e..51c4144 100644 (file)
@@ -125,12 +125,9 @@ interface monitor "The monitor to client Interface" {
                         cap cap,
                         capid_t capid,
                        uint8 give_away);
-          response cap_send_reply(
-                        uintptr conn_id,
-                        capid_t capid,
-                       errval err);
           response cap_receive_request(
                         uintptr conn_id,
+                        errval err,
                         cap cap,
                         capid_t capid);
 
@@ -167,6 +164,5 @@ interface monitor "The monitor to client Interface" {
           message multihop_message(vci_t vci, uint8 direction, uint8 flags, uint32 ack, uint8 payload[size]);
           
           // cap transfer
-          call multihop_cap_send(vci_t vci, uint8 direction, cap cap, capid_t capid);
-          response multihop_cap_reply(vci_t vci, uint8 direction, capid_t capid, errval err);
+          call multihop_cap_send(vci_t vci, uint8 direction, errval err, cap cap, capid_t capid);
 };
index 9109b6e..c2e339e 100644 (file)
@@ -20,8 +20,8 @@ struct monitor_lmp_binding;
 /// Handlers for incoming/outgoing capabilities on the monitor binding
 struct monitor_cap_handlers {
     void *st; ///< state pointer passed to handler functions
-    void (*cap_receive_handler)(void *st, struct capref cap, uint32_t capid);
-    void (*cap_send_reply_handler)(void *st, uint32_t capid, errval_t success);
+    void (*cap_receive_handler)(void *st, errval_t success, struct capref cap,
+                                uint32_t capid);
 };
 
 /* XXX: duplicate of monitor_bind_continuation_fn in generated code */
index 9aec4a3..e81efd6 100644 (file)
@@ -31,24 +31,14 @@ static void error_handler(struct monitor_binding *b, errval_t err)
 /// Handler for incoming LMP messages from the monitor binding with an
 /// indirected cap for a UMP/BMP/... channel
 static void cap_receive_request_handler(struct monitor_binding *b,
-                                        uintptr_t conn_id,
+                                        uintptr_t conn_id, errval_t success,
                                         struct capref cap, uint32_t capid)
 {
     /* XXX: this relies on the monitor_cap_handlers table being the first thing
      * in every channel state struct */
     struct monitor_cap_handlers *h = (void *)conn_id;
     assert(h->cap_receive_handler != NULL);
-    h->cap_receive_handler(h->st, cap, capid);
-}
-
-static void cap_send_reply_handler(struct monitor_binding *b, uintptr_t conn_id,
-                                   uint32_t capid, errval_t err)
-{
-    /* XXX: this relies on the monitor_cap_handlers table being the first thing
-     * in every channel state struct */
-    struct monitor_cap_handlers *h = (void *)conn_id;
-    assert(h->cap_send_reply_handler != NULL);
-    h->cap_send_reply_handler(h->st, capid, err);
+    h->cap_receive_handler(h->st, success, cap, capid);
 }
 
 /// vtable for handlers declared in this file
@@ -56,7 +46,6 @@ static void cap_send_reply_handler(struct monitor_binding *b, uintptr_t conn_id,
 // functions after we bind to the monitor
 static struct monitor_rx_vtbl monitor_rx_vtbl = {
     .cap_receive_request = cap_receive_request_handler,
-    .cap_send_reply = cap_send_reply_handler,
 };
 
 static void monitor_accept_recv_handler(void *arg)
index 11c6f85..8a7d07c 100644 (file)
@@ -489,7 +489,9 @@ errval_t multihop_send_capability(struct multihop_chan *mc,
 
     // send the message
     err = mon_binding->tx_vtbl.multihop_cap_send(mon_binding, _continuation,
-            mc->vci, mc->direction, cap, cap_state->tx_capnum);
+                                                 mc->vci, mc->direction,
+                                                 SYS_ERR_OK, cap,
+                                                 cap_state->tx_capnum);
 
     if (err_is_ok(err)) {
         // increase capability number
@@ -565,7 +567,8 @@ static void handle_multihop_message(struct monitor_binding *mon_closure,
  *
  */
 static void multihop_handle_capability(struct monitor_binding *mon_closure,
-        multihop_vci_t vci, uint8_t direction, struct capref cap, uint32_t capid)
+        multihop_vci_t vci, uint8_t direction, errval_t msgerr,
+        struct capref cap, uint32_t capid)
 {
 
     struct multihop_chan *mc = multihop_chan_mappings_lookup(vci);
@@ -573,21 +576,7 @@ static void multihop_handle_capability(struct monitor_binding *mon_closure,
     assert(mc->cap_handlers.cap_receive_handler != NULL);
 
     // deliver capability to the handler
-    mc->cap_handlers.cap_receive_handler(mc->cap_handlers.st, cap, capid);
-}
-
-/**
- * \ brief Handle a capability reply
- */
-static void multihop_handle_capability_reply(
-        struct monitor_binding *mon_closure, multihop_vci_t vci, uint8_t direction,
-        uint32_t capid, errval_t msgerr)
-{
-
-    struct multihop_chan *mc = multihop_chan_mappings_lookup(vci);
-    assert(mc->connstate == MULTIHOP_CONNECTED);
-    assert(mc->cap_handlers.cap_send_reply_handler != NULL);
-    mc->cap_handlers.cap_send_reply_handler(mc->cap_handlers.st, capid, msgerr);
+    mc->cap_handlers.cap_receive_handler(mc->cap_handlers.st, msgerr, cap, capid);
 }
 
 ///////////////////////////////////////////////////////
@@ -649,5 +638,4 @@ void multihop_init(void)
     mb->rx_vtbl.multihop_bind_client_reply = &multihop_bind_reply_handler; // handler for incoming reply messages from the monitor
     mb->rx_vtbl.multihop_message = &handle_multihop_message; // handler for incoming messages from the monitor
     mb->rx_vtbl.multihop_cap_send = &multihop_handle_capability; // handler for incoming capabilities from the monitor
-    mb->rx_vtbl.multihop_cap_reply = &multihop_handle_capability_reply; // handler for capability reply messages
 }
index 90f29fd..45b1bd6 100644 (file)
@@ -100,7 +100,6 @@ rx_handler_name ifn = ifscope ifn "multihop_rx_handler"
 -- Name of the caps receive handlers
 caps_rx_handler_name :: String -> String
 caps_rx_handler_name ifn = ifscope ifn "multihop_caps_rx_handler"
-caps_rx_reply_handler_name ifn = ifscope ifn "multihop_caps_reply_handler"
 
 -- Names of the control functions
 change_waitset_fn_name, control_fn_name :: String -> String
@@ -137,7 +136,6 @@ multihop_header_body infile interface@(Interface name descr decls) = [
     multihop_connect_handler_proto name,
     multihop_rx_handler_proto name,
     multihop_caps_rx_handler_proto name,
-    multihop_caps_reply_rx_handler_proto name,
     C.Blank
     ]
 
@@ -208,18 +206,10 @@ multihop_caps_rx_handler_proto ifn = C.GVarDecl C.Extern C.NonConst
 
 multihop_caps_rx_handler_params :: [C.Param]
 multihop_caps_rx_handler_params = [C.Param (C.Ptr C.Void) "arg",
+                                   C.Param (C.TypeName "errval_t") "success",
                                    C.Param (C.Struct "capref") "cap",
                                    C.Param (C.TypeName "uint32_t") "capid"]
-                                  
-multihop_caps_reply_rx_handler_proto :: String -> C.Unit
-multihop_caps_reply_rx_handler_proto ifn = C.GVarDecl C.Extern C.NonConst
-                                           (C.Function C.NoScope C.Void multihop_caps_reply_rx_handler_params)
-                                           (caps_rx_reply_handler_name ifn) Nothing
-                                           
-multihop_caps_reply_rx_handler_params = [C.Param (C.Ptr C.Void) "arg",
-                                         C.Param (C.TypeName "uint32_t") "capid",
-                                         C.Param (C.TypeName "errval_t") "success"]
-                                  
+
 ------------------------------------------------------------------------
 -- Language mapping: Create the stub (implementation) for this interconnect driver
 ------------------------------------------------------------------------
@@ -284,7 +274,6 @@ multihop_stub_body arch infile intf@(Interface ifn descr decls) = C.UnitList [
 
       C.MultiComment [ "Cap receive handlers" ],
       caps_rx_handler arch ifn types messages msg_specs,
-      caps_reply_rx_handler arch ifn,
       C.Blank,
 
       C.MultiComment [ "Message sender functions" ],
@@ -402,8 +391,7 @@ multihop_bind_cont_fn ifn =
        [C.AddressOf $ C.DerefField multihop_bind_var "chan",
         C.StructConstant "monitor_cap_handlers"
         [("st", C.Variable "st"),
-         ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn)),
-         ("cap_send_reply_handler", C.Variable (caps_rx_reply_handler_name ifn))
+         ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn))
         ]]]
       
       [ C.Ex $ C.Call (multihop_destroy_fn_name ifn) [multihop_bind_var]],
@@ -462,8 +450,7 @@ multihop_connect_handler_fn ifn =
     [C.AddressOf $ C.DerefField multihop_bind_var "chan",
      C.StructConstant "monitor_cap_handlers"
      [("st", multihop_bind_var),
-      ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn)),
-      ("cap_send_reply_handler", C.Variable (caps_rx_reply_handler_name ifn))
+      ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn))
      ]],
     C.SBlank,
     
@@ -1005,6 +992,14 @@ caps_rx_handler arch ifn typedefs msgdefs msgs =
       C.Ex $ C.Call "assert" [C.Binary C.Equals (C.Variable "capid") (capst `C.FieldOf` "rx_capnum")],
       C.SBlank, 
      
+      C.SComment "Check if there's an associated error",
+      C.SComment "FIXME: how should we report this to the user? at present we just deliver a NULL capref",
+      C.If (C.Call "err_is_fail" [C.Variable "success"])
+           [C.Ex $ C.Call "DEBUG_ERR" 
+                 [C.Variable "success", C.StringConstant "could not send cap over multihop channel"]
+           ] [],
+      C.SBlank,
+
       C.SComment "Switch on current incoming message",
       C.Switch (C.DerefField bindvar "rx_msgnum") cases
       [C.Ex $ C.Call "assert"
@@ -1049,18 +1044,3 @@ cap_rx_handler_case arch ifn typedefs mn (Message _ _ msgargs _) nfrags caps =
           rx_msgfrag_field = C.DerefField bindvar "rx_msg_fragment"
           
           is_last = (ncap + 1 == length caps)
-
--- handle a caps reply message
-caps_reply_rx_handler :: Arch -> String -> C.Unit
-caps_reply_rx_handler arch ifn = 
-  C.FunctionDef C.NoScope C.Void (caps_rx_reply_handler_name ifn) multihop_caps_reply_rx_handler_params 
-  [  
-    localvar (C.Ptr $ C.Struct $ intf_bind_type ifn) intf_bind_var (Just $ C.Variable "arg"),
-    C.SBlank,
-  
-    C.If (C.Call "err_is_fail" [C.Variable "success"])
-    [C.Ex $ C.Call "DEBUG_ERR" 
-     [C.Variable "success", C.StringConstant "could not send cap over multihop channel"],
-     report_user_err $ C.Variable "success"
-    ] [] 
-  ]
index 052ffcc..21a5ba5 100644 (file)
@@ -110,7 +110,6 @@ rx_handler_name p ifn = ump_ifscope p ifn "rx_handler"
 
 -- Name of the cap send/recv handlers
 cap_rx_handler_name p ifn = ump_ifscope p ifn "cap_rx_handler"
-cap_tx_reply_handler_name p ifn = ump_ifscope p ifn "cap_tx_reply_handler"
 
 -- Names of the control functions
 change_waitset_fn_name p ifn = ump_ifscope p ifn "change_waitset"
@@ -246,7 +245,6 @@ stub_body p infile intf@(Interface ifn descr decls) = C.UnitList [
 
       C.MultiComment [ "Cap send/receive handlers" ],
       cap_rx_handler p ifn types messages msg_specs,
-      cap_tx_reply_handler p ifn,
       C.Blank,
 
       C.UnitList $ if has_caps then
@@ -1077,41 +1075,34 @@ rx_handler p ifn typedefs msgdefs msgs =
         rx_fragment_increment
             = C.Ex $ C.PostInc $ C.DerefField bindvar "rx_msg_fragment"
 
-cap_tx_reply_handler :: UMPParams -> String -> C.Unit
-cap_tx_reply_handler p ifn
-    = C.FunctionDef C.Static C.Void (cap_tx_reply_handler_name p ifn)
-        [C.Param (C.Ptr C.Void) "st",
-         C.Param (C.TypeName "uint32_t") "capid",
-         C.Param (C.TypeName "errval_t") "err"]
-        [
-        localvar (C.Ptr $ C.Struct $ intf_bind_type ifn) intf_bind_var (Just $ C.Variable "st"),
-        C.If (C.Call "err_is_fail" [errvar])
-            [C.Ex $ C.Call "DEBUG_ERR" [errvar,
-                        C.StringConstant "monitor refused to accept cap for UMP send"],
-             report_user_tx_err $
-                    C.Call "err_push" [errvar, C.Variable "LIB_ERR_MONITOR_CAP_SEND"]] []
-        ]
-
 cap_rx_handler :: UMPParams -> String -> [TypeDef] -> [MessageDef] -> [MsgSpec] -> C.Unit
 cap_rx_handler p ifn typedefs msgdefs msgspecs
     = C.FunctionDef C.Static C.Void (cap_rx_handler_name p ifn)
         [C.Param (C.Ptr C.Void) "arg",
+         C.Param (C.TypeName "errval_t") "success",
          C.Param (C.Struct "capref") "cap",
          C.Param (C.TypeName "uint32_t") "capid"]
-        [
-        handler_preamble p ifn,
+        [handler_preamble p ifn,
 
-        C.Ex $ C.Call "assert" [C.Binary C.Equals
+         C.Ex $ C.Call "assert" [C.Binary C.Equals
                                        (C.Variable "capid")
                                        (capst `C.FieldOf` "rx_capnum")],
-        C.SBlank,
-
-        C.SComment "Switch on current incoming message",
-        C.Switch (C.DerefField bindvar "rx_msgnum") cases
+         C.SBlank,
+
+         C.SComment "Check if there's an associated error",
+         C.SComment "FIXME: how should we report this to the user? at present we just deliver a NULL capref",
+         C.If (C.Call "err_is_fail" [C.Variable "success"])
+              [C.Ex $ C.Call "DEBUG_ERR" [errvar,
+                                          C.StringConstant "error in cap transfer"]]
+              [],
+         C.SBlank,
+
+         C.SComment "Switch on current incoming message",
+         C.Switch (C.DerefField bindvar "rx_msgnum") cases
             [C.Ex $ C.Call "assert"
                     [C.Unary C.Not $ C.StringConstant "invalid message number"],
              report_user_err (C.Variable "FLOUNDER_ERR_INVALID_STATE")]
-    ]
+        ]
     where
         umpst = C.DerefField my_bindvar "ump_state"
         capst = umpst `C.FieldOf` "capst"
@@ -1164,9 +1155,7 @@ setup_cap_handlers p ifn = [
     C.SComment "setup cap handlers",
     C.Ex $ C.Assignment (C.FieldOf handlers "st") my_bindvar,
     C.Ex $ C.Assignment (C.FieldOf handlers "cap_receive_handler")
-                        (C.Variable $ cap_rx_handler_name p ifn),
-    C.Ex $ C.Assignment (C.FieldOf handlers "cap_send_reply_handler")
-                        (C.Variable $ cap_tx_reply_handler_name p ifn) ]
+                        (C.Variable $ cap_rx_handler_name p ifn) ]
     where
         chanvar = my_bindvar `C.DerefField` "ump_state" `C.FieldOf` "chan"
         handlers = chanvar `C.FieldOf` "cap_handlers"
index 9365196..4e1d2aa 100644 (file)
@@ -70,8 +70,6 @@ static void monitor_initialized(struct intermon_binding *b)
 
 static void cap_receive_request_handler(struct monitor_binding *b,
                                         struct monitor_msg_queue_elem *e);
-static void cap_send_reply_handler(struct intermon_binding *b,
-                                   struct intermon_msg_queue_elem *e);
 
 struct cap_receive_request_state {
     struct monitor_msg_queue_elem elem;
@@ -80,54 +78,12 @@ struct cap_receive_request_state {
     struct intermon_binding *b;
 };
 
-struct cap_send_reply_state {
-    struct intermon_msg_queue_elem elem;
-    struct intermon_cap_send_reply__args args;
-};
-
-static void cap_send_reply_cont(struct intermon_binding *b,
-                                uintptr_t your_mon_id, uint32_t capid,
-                                errval_t err)
-{
-    errval_t err2;
-
-    /* Send reply back to the requesting monitor */
-    err2 = b->tx_vtbl.cap_send_reply(b, NOP_CONT, your_mon_id, capid, err);
-    if (err_is_fail(err2)) {
-        if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
-            struct cap_send_reply_state *me =
-                malloc(sizeof(struct cap_send_reply_state));
-            struct intermon_state *st = b->st;
-            me->args.con_id = your_mon_id;
-            me->args.capid = capid;
-            me->args.err = err;
-            me->elem.cont = cap_send_reply_handler;
-
-            err = intermon_enqueue_send(b, &st->queue, get_default_waitset(),
-                                        &me->elem.queue);
-            if (err_is_fail(err)) {
-                USER_PANIC_ERR(err, "intermon_enqueue_send failed");
-            }
-            return;
-        }
-
-        USER_PANIC_ERR(err, "cap send reply to monitor failed");
-    }
-}
-
-static void cap_send_reply_handler(struct intermon_binding *b,
-                                   struct intermon_msg_queue_elem *e)
-{
-    struct cap_send_reply_state *st = (struct cap_send_reply_state *)e;
-    cap_send_reply_cont(b, st->args.con_id, st->args.capid, st->args.err);
-    free(e);
-}
-
 static void
 cap_receive_request_enqueue(struct monitor_binding *domain_binding,
-                         uintptr_t domain_id, struct capref cap,
-                         uint32_t capid, uintptr_t your_mon_id,
-                         struct intermon_binding *b)
+                            uintptr_t domain_id, errval_t msgerr,
+                            struct capref cap, uint32_t capid,
+                            uintptr_t your_mon_id,
+                            struct intermon_binding *b)
 {
     errval_t err;
 
@@ -135,6 +91,7 @@ cap_receive_request_enqueue(struct monitor_binding *domain_binding,
         malloc(sizeof(struct cap_receive_request_state));
     assert(me != NULL);
     me->args.conn_id = domain_id;
+    me->args.err = msgerr;
     me->args.cap = cap;
     me->args.capid = capid;
     me->your_mon_id = your_mon_id;
@@ -151,7 +108,8 @@ cap_receive_request_enqueue(struct monitor_binding *domain_binding,
 
 static void
 cap_receive_request_cont(struct monitor_binding *domain_binding,
-                         uintptr_t domain_id, struct capref cap,
+                         uintptr_t domain_id, errval_t msgerr,
+                         struct capref cap,
                          uint32_t capid, uintptr_t your_mon_id,
                          struct intermon_binding *b)
 {
@@ -165,29 +123,23 @@ cap_receive_request_cont(struct monitor_binding *domain_binding,
         cont = MKCONT(destroy_outgoing_cap, capp);
     }
     err = domain_binding->tx_vtbl.
-        cap_receive_request(domain_binding, cont, domain_id, cap, capid);
+        cap_receive_request(domain_binding, cont, domain_id, msgerr, cap, capid);
 
     if (err_is_fail(err)) {
         free(capp);
         if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
-            cap_receive_request_enqueue(domain_binding, domain_id, cap, capid,
-                                        your_mon_id, b);
-            return;
-        }
-
-        if (!capref_is_null(cap)) {
-            err2 = cap_destroy(cap);
-            if (err_is_fail(err2)) {
-                USER_PANIC_ERR(err, "cap_destroy failed");
+            cap_receive_request_enqueue(domain_binding, domain_id, msgerr, cap,
+                                        capid, your_mon_id, b);
+        } else {
+            if (!capref_is_null(cap)) {
+                err2 = cap_destroy(cap);
+                if (err_is_fail(err2)) {
+                    USER_PANIC_ERR(err, "cap_destroy failed");
+                }
             }
-            err = err_push(err, MON_ERR_CAP_SEND);
-        } 
-        goto reply;
-    }
-
-reply:
-    if(err_is_fail(err)) {
-        cap_send_reply_cont(b, your_mon_id, capid, err);
+            // TODO: handle sanely: kill dispatcher/teardown binding/etc.
+            USER_PANIC_ERR(err, "error delivering cap to local dispatcher");
+        }
     }
 }
 
@@ -196,14 +148,14 @@ static void cap_receive_request_handler(struct monitor_binding *b,
 {
     struct cap_receive_request_state *st =
         (struct cap_receive_request_state *)e;
-    cap_receive_request_cont(b, st->args.conn_id, st->args.cap, st->args.capid,
-                             st->your_mon_id, st->b);
+    cap_receive_request_cont(b, st->args.conn_id, st->args.err, st->args.cap,
+                             st->args.capid, st->your_mon_id, st->b);
     free(e);
 }
 
 static void cap_send_request(struct intermon_binding *b,
                              mon_id_t my_mon_id, uint32_t capid,
-                             intermon_caprep_t caprep, 
+                             intermon_caprep_t caprep, errval_t msgerr,
                              bool give_away, bool remote_has_desc,
                              intermon_coremask_t on_cores, 
                              bool null_cap) 
@@ -228,7 +180,7 @@ static void cap_send_request(struct intermon_binding *b,
         err = slot_alloc(&cap);
         if (err_is_fail(err)) {
             err = err_push(err, LIB_ERR_SLOT_ALLOC);
-            goto reply;
+            goto send_error;
         }
 
         err = monitor_cap_create(cap, capability, core_id);
@@ -280,6 +232,7 @@ static void cap_send_request(struct intermon_binding *b,
 
     }
 
+do_send: ;
     /* Get the user domain's connection and connection id */
     struct monitor_binding *domain_binding = conn->domain_binding;
     uintptr_t domain_id = conn->domain_id;
@@ -287,15 +240,16 @@ static void cap_send_request(struct intermon_binding *b,
     /* Try to send cap to the user domain, but only if the queue is empty */
     struct monitor_state *mst = domain_binding->st;
     if (msg_queue_is_empty(&mst->queue)) {
-        cap_receive_request_cont(domain_binding, domain_id, cap, capid,
+        cap_receive_request_cont(domain_binding, domain_id, msgerr, cap, capid,
                                  your_mon_id, b);
     } else {
         // don't allow sends to bypass the queue
-        cap_receive_request_enqueue(domain_binding, domain_id, cap, capid,
+        cap_receive_request_enqueue(domain_binding, domain_id, msgerr, cap, capid,
                                     your_mon_id, b);
     }
 
-    goto out;
+    free(on_cores);
+    return;
 
 cleanup2:
     err2 = cap_destroy(cap);
@@ -307,71 +261,10 @@ cleanup1:
     if (err_is_fail(err2)) {
         USER_PANIC_ERR(err2, "slot_free failed");
     }
-reply:
-    cap_send_reply_cont(b, your_mon_id, capid, err);
-out:
-    free(on_cores);
-}
-
-struct monitor_cap_send_reply_state {
-    struct monitor_msg_queue_elem elem;
-    struct monitor_cap_send_reply__args args;
-};
-
-static void monitor_cap_send_reply_handler(struct monitor_binding *b,
-                                           struct monitor_msg_queue_elem *e);
-
-static void monitor_cap_send_reply_cont(struct monitor_binding *domain_binding,
-                                        uintptr_t domain_id, uint32_t capid,
-                                        errval_t msgerr)
-{
-    errval_t err;
-
-    err = domain_binding->tx_vtbl.cap_send_reply(domain_binding, NOP_CONT,
-                                                 domain_id, capid, msgerr);
-    if (err_is_fail(err)) {
-        if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
-            struct monitor_cap_send_reply_state *me =
-                malloc(sizeof(struct monitor_cap_send_reply_state));
-            struct monitor_state *st = domain_binding->st;
-            me->args.conn_id = domain_id;
-            me->args.capid = capid;
-            me->args.err = msgerr;
-            me->elem.cont = monitor_cap_send_reply_handler;
-
-            err = monitor_enqueue_send(domain_binding, &st->queue,
-                                       get_default_waitset(), &me->elem.queue);
-            if (err_is_fail(err)) {
-                USER_PANIC_ERR(err, "monitor_enqueue_send failed");
-            }
-            return;
-        }
-
-        USER_PANIC_ERR(err, "cap send reply to user failed");
-    }
-}
-
-static void monitor_cap_send_reply_handler(struct monitor_binding *b,
-                                           struct monitor_msg_queue_elem *e)
-{
-    struct monitor_cap_send_reply_state *st =
-        (struct monitor_cap_send_reply_state *)e;
-    monitor_cap_send_reply_cont(b, st->args.conn_id,
-                                st->args.capid, st->args.err);
-    free(e);
-}
-
-static void cap_send_reply(struct intermon_binding *binding,
-                           con_id_t con_id, uint32_t capid,
-                           errval_t msgerr)
-{
-    struct remote_conn_state *conn = remote_conn_lookup(con_id);
-    assert(conn != NULL);
-
-    /* Forward reply */
-    uintptr_t domain_id = conn->domain_id;
-    struct monitor_binding *domain_binding = conn->domain_binding;
-    monitor_cap_send_reply_cont(domain_binding, domain_id, capid, msgerr);
+send_error:
+    msgerr = err;
+    cap = NULL_CAP;
+    goto do_send;
 }
 
 static void span_domain_request(struct intermon_binding *b,
@@ -684,7 +577,6 @@ static struct intermon_rx_vtbl the_intermon_vtable = {
     .spawnd_image_request      = spawnd_image_request,
 
     .cap_send_request          = cap_send_request,
-    .cap_send_reply            = cap_send_reply,
 
     .span_domain_request       = span_domain_request,
     .span_domain_reply         = span_domain_reply,
index bce5585..2f50a0c 100644 (file)
@@ -552,12 +552,14 @@ struct send_cap_st {
     uint32_t capid;
     uint8_t give_away;
     struct capability capability;
+    errval_t msgerr;
     bool has_descendants;
     coremask_t on_cores;
 };
 
 static void cap_send_request_2(uintptr_t my_mon_id, struct capref cap,
                                uint32_t capid, struct capability capability,
+                               errval_t msgerr,
                                uint8_t give_away, bool has_descendants,
                                coremask_t on_cores);
 
@@ -574,7 +576,8 @@ static void cap_send_request_cb(void * st_arg) {
         assert (err_is_ok(err));
     } else {
         cap_send_request_2(st->my_mon_id, st->cap, st->capid, st->capability,
-                           st->give_away, st->has_descendants, st->on_cores);
+                           st->msgerr, st->give_away, st->has_descendants,
+                           st->on_cores);
     }
 }
 
@@ -584,36 +587,33 @@ static void cap_send_request(struct monitor_binding *b,
                              uintptr_t my_mon_id, struct capref cap,
                              uint32_t capid, uint8_t give_away)
 {
-    errval_t err;
+    errval_t err, msgerr = SYS_ERR_OK;
     struct capability capability;
     bool has_descendants;
     coremask_t on_cores;
 
+    if (!capref_is_null(cap)) {
+        err = monitor_cap_identify(cap, &capability);
+        if (err_is_fail(err)) {
+            USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored");
+            return;
+        }
+
+        // if we can't transfer the cap, it is delivered as NULL
+        if (!monitor_can_send_cap(&capability)) {
+            cap = NULL_CAP;
+            msgerr = MON_ERR_CAP_SEND;
+        }
+    }
+
     if (capref_is_null(cap)) {
         // we don't care about capabilities, has_descendants, or on_cores here,
         // make the compiler happy though
         static struct capability null_capability;
         static coremask_t null_mask;
         cap_send_request_2(my_mon_id, cap, capid, null_capability,
-                           give_away, false, null_mask);
-        return;
-    }
-
-    err = monitor_cap_identify(cap, &capability);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored");
-        return;
-    }
-
-    if (!monitor_can_send_cap(&capability)) {
-        struct remote_conn_state *rcs = remote_conn_lookup(my_mon_id);
-        err = b->tx_vtbl.cap_send_reply(b, NOP_CONT, rcs->domain_id, capid,
-                                        MON_ERR_CAP_SEND);
-        assert(err_is_ok(err));
-        return;
-    }
-
-    if (!give_away) {
+                           msgerr, give_away, false, null_mask);
+    } else if (!give_away) {
         if (!rcap_db_exists(&capability)) {
             err = monitor_cap_remote(cap, true, &has_descendants);
             if (err_is_fail(err)) {
@@ -641,6 +641,7 @@ static void cap_send_request(struct monitor_binding *b,
         send_cap_st->cap        = cap;
         send_cap_st->capability = capability;
         send_cap_st->capid      = capid;
+        send_cap_st->msgerr     = msgerr;
         send_cap_st->give_away  = give_away;
         send_cap_st->has_descendants = has_descendants;
         send_cap_st->on_cores   = on_cores;
@@ -649,7 +650,7 @@ static void cap_send_request(struct monitor_binding *b,
         assert (err_is_ok(err));
         // continues in cap_send_request_2 (after cap_send_request_cb)
 
-    } else {
+    } else { // give_away cap
         err = monitor_cap_remote(cap, true, &has_descendants);
         if (err_is_fail(err)) {
             USER_PANIC_ERR(err, "monitor_cap_remote failed");
@@ -659,7 +660,7 @@ static void cap_send_request(struct monitor_binding *b,
         // TODO ensure that no more copies of this cap are on this core
         static coremask_t null_mask;
         // call continuation directly
-        cap_send_request_2(my_mon_id, cap, capid, capability, give_away, 
+        cap_send_request_2(my_mon_id, cap, capid, capability, msgerr, give_away,
                            has_descendants, null_mask);
     }
 }
@@ -668,6 +669,7 @@ struct cap_send_request_state {
     struct intermon_msg_queue_elem elem;
     uintptr_t your_mon_id;
     uint32_t capid;
+    errval_t msgerr;
     intermon_caprep_t caprep;
     uint8_t give_away;
     bool has_descendants;
@@ -682,7 +684,7 @@ static void cap_send_request_2_handler(struct intermon_binding *b,
     struct cap_send_request_state *st = (struct cap_send_request_state*)e;
 
     err = b->tx_vtbl.cap_send_request(b, NOP_CONT, st->your_mon_id, st->capid,
-                                      st->caprep, st->give_away,
+                                      st->caprep, st->msgerr, st->give_away,
                                       st->has_descendants, st->on_cores.bits,
                                       st->null_cap); 
     if (err_is_fail(err)) {
@@ -695,6 +697,7 @@ static void cap_send_request_2_handler(struct intermon_binding *b,
             ms->your_mon_id = st->your_mon_id;
             ms->capid = st->capid;
             ms->caprep = st->caprep;
+            ms->msgerr = st->msgerr;
             ms->give_away = st->give_away;
             ms->has_descendants = st->has_descendants;
             ms->on_cores = st->on_cores;
@@ -717,6 +720,7 @@ static void cap_send_request_2_handler(struct intermon_binding *b,
 
 static void cap_send_request_2(uintptr_t my_mon_id, struct capref cap,
                                uint32_t capid, struct capability capability,
+                               errval_t msgerr,
                                uint8_t give_away, bool has_descendants,
                                coremask_t on_cores)
 {
@@ -747,7 +751,7 @@ static void cap_send_request_2(uintptr_t my_mon_id, struct capref cap,
 
     err = binding->tx_vtbl.
         cap_send_request(binding, NOP_CONT, your_mon_id, capid,
-                         caprep, give_away, has_descendants, on_cores.bits,
+                         caprep, msgerr, give_away, has_descendants, on_cores.bits,
                          null_cap);
     if (err_is_fail(err)) {
         if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
@@ -759,6 +763,7 @@ static void cap_send_request_2(uintptr_t my_mon_id, struct capref cap,
             ms->your_mon_id = your_mon_id;
             ms->capid = capid;
             ms->caprep = caprep;
+            ms->msgerr = msgerr;
             ms->give_away = give_away;
             ms->has_descendants = has_descendants;
             ms->on_cores = on_cores;
index b564ad9..a09e6f4 100644 (file)
@@ -1234,20 +1234,14 @@ static void multihop_cap_send_intermon_forward_cont(struct intermon_binding *b,
 
 static inline void multihop_cap_send_intermon_forward(
         struct intermon_binding *b, multihop_vci_t vci, uint8_t direction,
-        uint32_t capid, intermon_caprep_t caprep, bool null_cap);
+        uint32_t capid, errval_t msgerr, intermon_caprep_t caprep, bool null_cap);
 
 static void multihop_cap_send_forward_cont(struct monitor_binding *b,
         struct monitor_msg_queue_elem *e);
 
 inline static void multihop_cap_send_forward(struct monitor_binding *b,
-        multihop_vci_t vci, uint8_t direction, uint32_t capid, struct capref cap);
-
-inline static void multihop_intermon_cap_send_reply(struct intermon_binding *b,
-        multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t err);
-
-inline static void multihop_monitor_cap_send_reply(
-        struct monitor_binding *mon_binding, multihop_vci_t vci, uint8_t direction,
-        uint32_t capid, errval_t msgerr);
+        multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t msgerr,
+        struct capref cap);
 
 // intermonitor capability forwarding state
 struct multihop_intermon_capability_forwarding_state {
@@ -1274,7 +1268,7 @@ struct multihop_capability_forwarding_state {
  */
 static void multihop_cap_send_request_handler(
         struct monitor_binding *monitor_binding, multihop_vci_t vci,
-        uint8_t direction, struct capref cap, uint32_t capid)
+        uint8_t direction, errval_t msgerr, struct capref cap, uint32_t capid)
 {
 
     MULTIHOP_DEBUG(
@@ -1287,6 +1281,9 @@ static void multihop_cap_send_request_handler(
     bool null_cap = capref_is_null(cap);
     bool has_descendants;
 
+    // XXX: this field is ignored when the local dispatcher originates the cap
+    msgerr = SYS_ERR_OK;
+
     // get forwarding information
     struct monitor_multihop_chan_state *chan_state = forwarding_table_lookup(
             vci);
@@ -1294,7 +1291,6 @@ static void multihop_cap_send_request_handler(
     struct intermon_binding *b = dir->binding.intermon_binding;
 
     if (!null_cap) {
-
         // get binary representation of capability
         err = monitor_cap_identify(cap, &capability);
         if (err_is_fail(err)) {
@@ -1302,16 +1298,16 @@ static void multihop_cap_send_request_handler(
             return;
         }
 
+        // if we can't transfer the cap, it is delivered as NULL
         if (!monitor_can_send_cap(&capability)) {
-
-            // if we can't send this capability, we send an reply back
-            // the the dispatcher
-            direction = multihop_get_opposite_direction(chan_state, direction,
-                    &dir);
-            multihop_monitor_cap_send_reply(dir->binding.monitor_binding,
-                    dir->vci, direction, capid, MON_ERR_CAP_SEND);
-            return;
+            cap = NULL_CAP;
+            null_cap = true;
+            msgerr = MON_ERR_CAP_SEND;
         }
+    }
+
+    if (!null_cap) {
+        // FIXME: this seems to be totally bogus. it assumes a give_away cap -AB
 
         // mark capability as remote
         err = monitor_cap_remote(cap, true, &has_descendants);
@@ -1338,6 +1334,7 @@ static void multihop_cap_send_request_handler(
     me->args.vci = dir->vci;
     me->args.direction = direction;
     me->args.capid = capid;
+    me->args.err = msgerr;
     me->args.cap = caprep;
     me->args.null_cap = null_cap;
     me->elem.cont = multihop_cap_send_intermon_forward_cont;
@@ -1354,7 +1351,7 @@ static void multihop_cap_send_intermon_forward_cont(struct intermon_binding *b,
     struct multihop_intermon_capability_forwarding_state *st =
             (struct multihop_intermon_capability_forwarding_state *) e;
     multihop_cap_send_intermon_forward(b, st->args.vci, st->args.direction,
-            st->args.capid, st->args.cap, st->args.null_cap);
+        st->args.capid, st->args.err, st->args.cap, st->args.null_cap);
     free(e);
 }
 
@@ -1364,13 +1361,13 @@ static void multihop_cap_send_intermon_forward_cont(struct intermon_binding *b,
  */
 static inline void multihop_cap_send_intermon_forward(
         struct intermon_binding *b, multihop_vci_t vci, uint8_t direction,
-        uint32_t capid, intermon_caprep_t caprep, bool null_cap)
+        uint32_t capid, errval_t msgerr, intermon_caprep_t caprep, bool null_cap)
 {
 
     errval_t err;
 
     // try to forward
-    err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, capid,
+    err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, capid, msgerr,
             caprep, null_cap);
 
     if (err_is_fail(err)) {
@@ -1382,6 +1379,7 @@ static inline void multihop_cap_send_intermon_forward(
             me->args.vci = vci;
             me->args.direction = direction;
             me->args.capid = capid;
+            me->args.err = msgerr;
             me->args.cap = caprep;
             me->args.null_cap = null_cap;
             me->elem.cont = multihop_cap_send_intermon_forward_cont;
@@ -1405,8 +1403,8 @@ static inline void multihop_cap_send_intermon_forward(
  */
 static void multihop_intermon_cap_send_handler(
         struct intermon_binding *intermon_binding, multihop_vci_t vci,
-        uint8_t direction, uint32_t capid, intermon_caprep_t caprep,
-        bool null_cap)
+        uint8_t direction, uint32_t capid, errval_t msgerr,
+        intermon_caprep_t caprep, bool null_cap)
 {
 
     MULTIHOP_DEBUG(
@@ -1430,13 +1428,11 @@ static void multihop_intermon_cap_send_handler(
             err = slot_alloc(&cap);
             if (err_is_fail(err)) {
 
-                // send a reply back indicating that we failed
+                // send a msg indicating that we failed
                 // to allocate a slot for the capability
-                direction = multihop_get_opposite_direction(chan_state,
-                        direction, &dir);
-                multihop_intermon_cap_send_reply(dir->binding.intermon_binding,
-                        direction, dir->vci, capid, err);
-                return;
+                cap = NULL_CAP;
+                msgerr = err;
+                goto do_send;
             }
 
             // create capability
@@ -1446,14 +1442,11 @@ static void multihop_intermon_cap_send_handler(
             if (err_is_fail(err)) {
                 slot_free(cap);
 
-                // send a reply back indicating that we failed
+                // send a msg indicating that we failed
                 // to create the capability
-                err = err_push(err, MON_ERR_CAP_CREATE);
-                direction = multihop_get_opposite_direction(chan_state,
-                        direction, &dir);
-                multihop_intermon_cap_send_reply(dir->binding.intermon_binding,
-                        dir->vci, direction, capid, err);
-                return;
+                cap = NULL_CAP;
+                msgerr = err_push(err, MON_ERR_CAP_CREATE);
+                goto do_send;
             }
 
             // mark capability as remote
@@ -1465,6 +1458,7 @@ static void multihop_intermon_cap_send_handler(
             }
         }
 
+do_send: ;
         // enqueue the capability in order to be forwarded to
         // the local dispatcher
         struct monitor_binding *b = dir->binding.monitor_binding;
@@ -1476,6 +1470,7 @@ static void multihop_intermon_cap_send_handler(
         me->args.direction = direction;
         me->args.cap = cap;
         me->args.capid = capid;
+        me->args.err = msgerr;
         me->elem.cont = multihop_cap_send_forward_cont;
 
         err = monitor_enqueue_send(b, &ist->queue, get_default_waitset(),
@@ -1493,6 +1488,7 @@ static void multihop_intermon_cap_send_handler(
         me->args.vci = dir->vci;
         me->args.direction = direction;
         me->args.capid = capid;
+        me->args.err = msgerr;
         me->args.cap = caprep;
         me->args.null_cap = null_cap;
         me->elem.cont = multihop_cap_send_intermon_forward_cont;
@@ -1511,7 +1507,7 @@ static void multihop_cap_send_forward_cont(struct monitor_binding *b,
     struct multihop_capability_forwarding_state *st =
             (struct multihop_capability_forwarding_state *) e;
     multihop_cap_send_forward(b, st->args.vci, st->args.direction,
-            st->args.capid, st->args.cap);
+                              st->args.capid, st->args.err, st->args.cap);
     free(e);
 }
 
@@ -1520,12 +1516,14 @@ static void multihop_cap_send_forward_cont(struct monitor_binding *b,
  *
  */
 inline static void multihop_cap_send_forward(struct monitor_binding *b,
-        multihop_vci_t vci, uint8_t direction, uint32_t capid, struct capref cap)
+        multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t msgerr,
+        struct capref cap)
 {
     errval_t err;
 
 // try to send
-    err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, cap, capid);
+    err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, msgerr,
+                                       cap, capid);
 
     if (err_is_fail(err)) {
         if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
@@ -1537,6 +1535,7 @@ inline static void multihop_cap_send_forward(struct monitor_binding *b,
             me->args.direction = direction;
             me->args.cap = cap;
             me->args.capid = capid;
+            me->args.err = msgerr;
             me->elem.cont = multihop_cap_send_forward_cont;
 
             err = monitor_enqueue_send_at_front(b, &ist->queue,
@@ -1550,127 +1549,6 @@ inline static void multihop_cap_send_forward(struct monitor_binding *b,
     }
 }
 
-// intermonitor capability reply forwarding state
-struct multihop_intermon_cap_send_reply_state {
-    struct intermon_msg_queue_elem elem;
-    struct intermon_multihop_cap_reply__args args;
-};
-
-// continue function for intermonitor capability reply forwarding
-static void multihop_intermon_cap_send_reply_busy_cont(
-        struct intermon_binding *b, struct intermon_msg_queue_elem *e)
-{
-    struct multihop_intermon_cap_send_reply_state *st =
-            (struct multihop_intermon_cap_send_reply_state *) e;
-    multihop_intermon_cap_send_reply(b, st->args.vci, st->args.direction,
-            st->args.capid, st->args.err);
-    free(e);
-}
-
-/**
- * Forward a reply to next monitor
- */
-inline static void multihop_intermon_cap_send_reply(struct intermon_binding *b,
-        multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t err)
-{
-
-    errval_t err2;
-    err2 = b->tx_vtbl.multihop_cap_reply(b, NOP_CONT, vci, direction, capid,
-            err);
-
-    if (err_is_fail(err2)) {
-        if (err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
-
-            struct multihop_intermon_cap_send_reply_state *me = malloc(
-                    sizeof(struct multihop_intermon_cap_send_reply_state));
-            struct intermon_state *ist = b->st;
-            me->args.vci = vci;
-            me->args.direction = direction;
-            me->args.capid = capid;
-            me->args.err = err;
-            me->elem.cont = multihop_intermon_cap_send_reply_busy_cont;
-
-            err2 = intermon_enqueue_send(b, &ist->queue, get_default_waitset(),
-                    &me->elem.queue);
-            assert(err_is_ok(err2));
-            return;
-        }
-
-        USER_PANIC_ERR(err2,
-                "Could not forward cap reply over multi-hop channel\n");
-    }
-}
-
-// struct for reply monitor forwarding state
-struct multihop_monitor_cap_send_reply_state {
-    struct monitor_msg_queue_elem elem;
-    struct monitor_multihop_cap_reply__args args;
-};
-
-// continue function for monitor capability reply forwarding
-static void multihop_monitor_cap_send_reply_busy_cont(struct monitor_binding *b,
-        struct monitor_msg_queue_elem *e)
-{
-    struct multihop_monitor_cap_send_reply_state *st =
-            (struct multihop_monitor_cap_send_reply_state *) e;
-    multihop_monitor_cap_send_reply(b, st->args.vci, st->args.direction,
-            st->args.capid, st->args.err);
-    free(e);
-}
-
-/**
- * Forward a reply message to a local dispatcher
- */
-inline static void multihop_monitor_cap_send_reply(
-        struct monitor_binding *mon_binding, multihop_vci_t vci, uint8_t direction,
-        uint32_t capid, errval_t msgerr)
-{
-
-    errval_t err;
-    err = mon_binding->tx_vtbl.multihop_cap_reply(mon_binding, NOP_CONT, vci,
-            direction, capid, msgerr);
-
-    if (err_is_fail(err)) {
-        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
-            struct multihop_monitor_cap_send_reply_state *me = malloc(
-                    sizeof(struct multihop_monitor_cap_send_reply_state));
-            assert(me != NULL);
-            struct monitor_state *ist = mon_binding->st;
-            me->args.vci = vci;
-            me->args.direction = direction;
-            me->args.capid = capid;
-            me->args.err = msgerr;
-            me->elem.cont = multihop_monitor_cap_send_reply_busy_cont;
-
-            err = monitor_enqueue_send(mon_binding, &ist->queue,
-                    get_default_waitset(), &me->elem.queue);
-            assert(err_is_ok(err));
-            return;
-        }
-    }
-}
-
-/**
- * \brief Handler a capability reply coming from another monitor
- */
-static void multihop_intermon_cap_reply_handler(
-        struct intermon_binding *intermon_binding, multihop_vci_t vci,
-        uint8_t direction, uint32_t capid, errval_t msgerr)
-{
-    struct monitor_multihop_chan_state *chan_state = forwarding_table_lookup(
-            vci);
-    struct direction *dir = multihop_get_direction(chan_state, direction);
-
-    if (dir->type == MULTIHOP_ENDPOINT) { // we have to forward the reply to a local dispatcher
-        multihop_monitor_cap_send_reply(dir->binding.monitor_binding, dir->vci,
-                direction, capid, msgerr);
-    } else {
-        // we have to forward the reply to the next hop
-        multihop_intermon_cap_send_reply(dir->binding.intermon_binding,
-                dir->vci, direction, capid, msgerr);
-    }
-}
-
 ///////////////////////////////////////////////////////
 
 // INITIALIZATION
@@ -1686,7 +1564,6 @@ errval_t multihop_intermon_init(struct intermon_binding *ib)
             &multihop_intermon_bind_reply_handler;
     ib->rx_vtbl.multihop_message = &intermon_multihop_message_handler;
     ib->rx_vtbl.multihop_cap_send = &multihop_intermon_cap_send_handler;
-    ib->rx_vtbl.multihop_cap_reply = &multihop_intermon_cap_reply_handler;
     ib->rx_vtbl.multihop_routing_table_request =
             &multihop_handle_routing_table_request;
     ib->rx_vtbl.multihop_routing_table_response =