Dear Miroslav,

thanks for reaching out.

So, your config.ml:
> open Mirage
> let stack = generic_stackv4v6 default_network
>
> let net = netif “secret”
> let secret_stack = generic_stackv4v6 net
> (* Main unikernel module *)
> let main =
>          main
>          ~packages:[package "cohttp-mirage"]
>          "Unikernel.Main"
>          (pclock @-> conduit @-> resolver @-> stackv4v6 @-> job)
>
> let () =
> register "frontend-server" [ main $ default_posix_clock $ conduit_direct stack $ resolver_dns stack $ stack ]

Here, you'll need to use & provide the "secret_stack":

let main =
         main
         ~packages:[package "cohttp-mirage"]
         "Unikernel.Main"
(pclock @-> conduit @-> conduit @-> resolver @-> stackv4v6 @-> job)

let () =
register "frontend-server" [ main $ default_posix_clock $ conduit_direct stack $ conduit_direct secret_stack $ resolver_dns secret_stack $ stack ]


Which will then result in your unikernel being a bit modified:
> module Main
>          (Pclock : Mirage_clock.PCLOCK)
>          (Conduit : Conduit_mirage.S)
>          (Resolver : Resolver_mirage.S)
>          (Stack : Tcpip.Stack.V4V6) = struct
>
>    module Client = Cohttp_mirage.Client.Make(Pclock)(Resolver)(Conduit)
>    module Server = Cohttp_mirage.Server.Make(Conduit)

will now be:

module Main
         (Pclock : Mirage_clock.PCLOCK)
         (Conduit : Conduit_mirage.S)
         (Secret_conduit : Conduit_mirage.S)
         (Secret_resolver : Resolver_mirage.S)
         (Stack : Tcpip.Stack.V4V6) = struct

module Client = Cohttp_mirage.Client.Make(Pclock)(Secret_resolver)(Secret_conduit)
   module Server = Cohttp_mirage.Server.Make(Conduit)


And then, also your "start" function is slightly adapted:
>    let start _pclock _conduit _resolver stack =

will be:
   let start _pclock _conduit _secret_conduit _secret_resolver stack =


And then your HTTP client will use the secret network stack, while the server uses the default one.

Hope this helps,

Hannes


On 01/05/2025 22:58, Belej, Miroslav wrote:
Hi, I am developing a unikernel webserver for my thesis and I would be glad for 
help, as I am not really good with OCaml. I already have a running and 
functional webserver, which acts as proxy between user and backend. Right now, 
it uses the same tcp/ip stack for both the user and for forwarding and 
receiving request from backend. I need to have separate stack for both of them. 
I am using Cohttp_mirage library. Here is the code for the unikernel I 
currently have :
open Lwt.Infix


let target_host = "http://192.168.254.11";
let target_port = 8081

module Main
         (Pclock : Mirage_clock.PCLOCK)
         (Conduit : Conduit_mirage.S)
         (Resolver : Resolver_mirage.S)
         (Stack : Tcpip.Stack.V4V6) = struct

   module Client = Cohttp_mirage.Client.Make(Pclock)(Resolver)(Conduit)
   module Server = Cohttp_mirage.Server.Make(Conduit)
   (*Define the forwarding logic*)
   let forward_request uri body resolver conduit =
     let target_uri = Uri.of_string target_host in
     let target_uri = Uri.with_port target_uri (Some target_port) in
     let target_uri = Uri.with_path target_uri (Uri.path uri ) in
     Logs.info (fun f -> f "Forwarding to %s" (Uri.to_string target_uri));
     let headers = Cohttp.Header.init () in
     let body = Cohttp_lwt.Body.of_string body in

     let ctx = Client.ctx resolver conduit in

     Client.post ~ctx ~headers ~body target_uri >>= fun (resp, resp_body) ->
     Cohttp_lwt.Body.to_string resp_body >|= fun body_str ->
     Logs.info (fun f -> f "Received response from %s" (Uri.to_string 
target_uri));
     (resp, body_str)


   (* Define the HTTP server callback *)
   let server_callback _conn req body resolver conduit =
     let uri = Cohttp.Request.uri req in
     let method_ = Cohttp.Request.meth req in
     Logs.info (fun f ->
             f "Received %s request for %s"
             (Cohttp.Code.string_of_method method_)
             (Uri.to_string uri));
     Cohttp_lwt.Body.to_string body >>= fun body_str ->
     let response_body = "This will be hashed-> " ^ body_str in
     Logs.info (fun f -> f "Response Body: %s" response_body);
     forward_request uri body_str resolver conduit >>= fun (response, 
response_body) ->
     Logs.info (fun f -> f "Response body from forwarded request: %s" 
response_body);
     Lwt.return (response, Cohttp_lwt.Body.of_string response_body)


     (* Start the HTTP server *)
   let start _pclock _conduit _resolver stack =
     Logs.info (fun f -> f "Before port");
     let port = 8080 in
     Logs.info (fun f -> f "Defined port");
     Logs.info (fun f -> f "Starting MirageOS HTTP server on port %d" port);
     let callback _conn req body = server_callback _conn req body _resolver 
_conduit in
     let mode : Conduit_mirage.server = `TCP port in
     let server = Server.make ~callback () in

     Server.listen stack mode server
end

with config.ml :

open Mirage
let stack = generic_stackv4v6 default_network

let net = netif “secret”
let secret_stack = generic_stackv4v6 net
(* Main unikernel module *)
let main =
         main
         ~packages:[package "cohttp-mirage"]
         "Unikernel.Main"
         (pclock @-> conduit @-> resolver @-> stackv4v6 @-> job)

let () =
   register "frontend-server" [ main $ default_posix_clock $ conduit_direct 
stack $ resolver_dns stack $ stack ]

So I would like to use the secret_stack for communicating with the backend. I 
am thankful for any response.


Reply via email to