Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multicast Listening on Unikernel? #362

Open
gabrik opened this issue May 3, 2018 · 1 comment
Open

Multicast Listening on Unikernel? #362

gabrik opened this issue May 3, 2018 · 1 comment

Comments

@gabrik
Copy link

gabrik commented May 3, 2018

Hi all,
I'm not sure this is an issue.
There is the possibility to listen on some multicast address when using mirage-tcpip inside an unikernel?
I see some ~group parameter in dhcp_ipv4_stack but I'm not sure is used for multicast groups.
I'm trying to modify the simple TCP example to be able to listen also to UDP multicast.

config.ml:

open Mirage

let main = foreign ~packages: [package "duration"; package "fmt"] "Unikernel.Main"  (stackv4 @-> console @-> job)
let stack = dhcp_ipv4_stack ~group:"239.0.0.5" default_network
let () =
  register "services" [ main $ stack $ default_console]

unikernel.ml:

open Lwt.Infix

module Main (S: Mirage_types_lwt.STACKV4) (C: Mirage_types_lwt.CONSOLE) = struct
  let report_and_close flow pp e message =
    let ip, port = S.TCPV4.dst flow in
    Logs.warn
      (fun m -> m "closing connection from %a:%d due to error %a while %s"
          Ipaddr.V4.pp_hum ip port pp e message);
    S.TCPV4.close flow

  let task duration marker =
    ignore @@ OS.Time.sleep_ns (Duration.of_sec duration);
    Lwt.return @@ marker ^ marker

  let listener console udp port ~src ~dst ~src_port buf =
    let s = Format.asprintf "Data from %s to %s" (Ipaddr.V4.to_string src) (Ipaddr.V4.to_string dst) in
    ignore @@ C.log console s;
    let src' = (Ipaddr.V4 dst), port in
    let dst' = (Ipaddr.V4 src), src_port in
    S.UDPV4.write ~src_port:port ~dst:src ~dst_port:src_port udp buf >>= function
          | Ok () -> Lwt.return_unit
          | Error e -> Lwt.return_unit
          
 
  let rec echo flow =
    S.TCPV4.read flow >>= function
    | Error e -> report_and_close flow S.TCPV4.pp_error e "reading in Echo"
    | Ok `Eof -> report_and_close flow Fmt.string "end of file" "reading in Echo"
    | Ok (`Data buf) ->

      Lwt.choose[(task 1 "+");(task 2 "=")] >>= (
        fun x ->
          let b = Cstruct.of_string x
          in
          S.TCPV4.write flow b >>= function
          | Ok () -> echo flow
          | Error e -> report_and_close flow S.TCPV4.pp_write_error e "writing in Echo")

  let start s c =
   
    S.listen_udpv4 s ~port:7 (listener c (S.udpv4 s) 7);
    S.listen_tcpv4 s ~port:7 echo;
    S.listen s

end

These is a way to do that?
I need a new direct stack with UDP?

@hannesm
Copy link
Member

hannesm commented Aug 26, 2020

Dear @gabrik, thanks for your report. The "group" argument of dhcp_ipv4_stack is just a name (used for command-line / boot arguments), and has no relation with multicast.

The mirage-tcpip stack does not have appropriate multicast support. From the Static_ipv4 module on the receiving side:

      let of_interest ip =
        Ipaddr.V4.(compare ip (Prefix.address t.cidr) = 0
                   || compare ip broadcast = 0
                   || compare ip (Prefix.broadcast t.cidr) = 0)
      in
      if not (of_interest packet.dst) then begin
        Log.debug (fun m -> m "dropping IP fragment not for us or broadcast %a"
                      Ipv4_packet.pp packet);
        Lwt.return_unit

This means that all packets which are not broadcast or unicast to the configured IP address are dropped.

If you're interested in implementing multicast into tcpip, please let us know and we can help where which changes would be necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants