From 9e26335aa0e4dda59c2aa37cefaa96878833e880 Mon Sep 17 00:00:00 2001 From: Tomasz Wroblewski Date: Tue, 19 Jan 2010 17:32:13 +0000 Subject: [PATCH] [xenvm] Track NetworkManager connection status & delegate to guest --- libs/stdext/stringext.ml | 9 ++++ libs/stdext/stringext.mli | 6 +++ xenvm/Makefile | 2 +- xenvm/network_manager.ml | 95 +++++++++++++++++++++++++++++++++++++++ xenvm/xenvm.ml | 8 ++++ 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 xenvm/network_manager.ml diff --git a/libs/stdext/stringext.ml b/libs/stdext/stringext.ml index 37fb89f..e705be3 100644 --- a/libs/stdext/stringext.ml +++ b/libs/stdext/stringext.ml @@ -194,4 +194,13 @@ let map_unlikely s f = ) else s +let left s n = + let l = String.length s in + let n = min n l in + String.sub s 0 n + +let right s n = + let l = String.length s in + let p = max 0 (l - n) in + String.sub s p (l - p) end diff --git a/libs/stdext/stringext.mli b/libs/stdext/stringext.mli index 8034c0d..4383fd5 100644 --- a/libs/stdext/stringext.mli +++ b/libs/stdext/stringext.mli @@ -99,4 +99,10 @@ module String : (** map a string trying to fill the buffer by chunk *) val map_unlikely : string -> (char -> string option) -> string + + (** get beginning portion of string *) + val left : string -> int -> string + + (** get end portion of string *) + val right : string -> int -> string end diff --git a/xenvm/Makefile b/xenvm/Makefile index ab63769..d868106 100644 --- a/xenvm/Makefile +++ b/xenvm/Makefile @@ -16,7 +16,7 @@ OCAMLOPTFLAGS += -thread # balloon device_common hotplug device \ # domain -xenvm_OBJS = $(TOPLEVEL)/common/config xenvmlib tasks misc vmconfig vmstate vmact xenvm +xenvm_OBJS = $(TOPLEVEL)/common/config xenvmlib tasks misc vmconfig vmstate vmact network_manager xenvm xenvm-cmd_OBJS = xenvmlib xenvm_cmd xenops_OBJS = xenops diff --git a/xenvm/network_manager.ml b/xenvm/network_manager.ml new file mode 100644 index 0000000..117a6d2 --- /dev/null +++ b/xenvm/network_manager.ml @@ -0,0 +1,95 @@ +open Vmstate + +module D=Debug.Debugger(struct let name="xenvm" end) +open D + +type devstate = + NM_DEVICE_STATE_UNKNOWN + | NM_DEVICE_STATE_UNMANAGED + | NM_DEVICE_STATE_UNAVAILABLE + | NM_DEVICE_STATE_DISCONNECTED + | NM_DEVICE_STATE_PREPARE + | NM_DEVICE_STATE_CONFIG + | NM_DEVICE_STATE_NEED_AUTH + | NM_DEVICE_STATE_IP_CONFIG + | NM_DEVICE_STATE_ACTIVATED + | NM_DEVICE_STATE_FAILED + +let devstate_of_int = function + | 1 -> NM_DEVICE_STATE_UNMANAGED + | 2 -> NM_DEVICE_STATE_UNAVAILABLE + | 3 -> NM_DEVICE_STATE_DISCONNECTED + | 4 -> NM_DEVICE_STATE_PREPARE + | 5 -> NM_DEVICE_STATE_CONFIG + | 6 -> NM_DEVICE_STATE_NEED_AUTH + | 7 -> NM_DEVICE_STATE_IP_CONFIG + | 8 -> NM_DEVICE_STATE_ACTIVATED + | 9 -> NM_DEVICE_STATE_FAILED + | _ -> NM_DEVICE_STATE_UNKNOWN + +let get_devstate bus path = + let call = DBus.Message.new_method_call + "org.freedesktop.NetworkManager" path "org.freedesktop.DBus.Properties" "Get" in + DBus.Message.append call [DBus.String "org.freedesktop.NetworkManager.Device"; + DBus.String "State"]; + let resp = DBus.Connection.send_with_reply_and_block bus call (-1) in + match DBus.Message.get_type resp with + | DBus.Message.Method_return -> + (match DBus.Message.get resp with + | [DBus.Variant (DBus.UInt32 state)] -> + devstate_of_int (Int32.to_int state) + | _ -> failwith "Unexpected response") + | _ -> failwith "Failed to get device state" + +let get_devintf bus path = + let call = DBus.Message.new_method_call + "org.freedesktop.NetworkManager" path "org.freedesktop.DBus.Properties" "Get" in + DBus.Message.append call [DBus.String "org.freedesktop.NetworkManager.Device"; + DBus.String "Interface"]; + let resp = DBus.Connection.send_with_reply_and_block bus call (-1) in + match DBus.Message.get_type resp with + | DBus.Message.Method_return -> + (match DBus.Message.get resp with + | [DBus.Variant (DBus.String intf)] -> + intf + | _ -> failwith "Unexpected response") + | _ -> failwith "Failed to get interface name" + +let when_conn_changed xs state nic_id news olds = + if news <> olds then ( + let xsnode = Printf.sprintf "/local/domain/%d/device/vif/%d/disconnect" state.vm_domid nic_id in + match news, olds with + | NM_DEVICE_STATE_ACTIVATED, _ -> + info "Detected active net connection (NetworkManager) for id %d" nic_id; + xs.Xs.write xsnode "0"; + | _, NM_DEVICE_STATE_ACTIVATED -> + info "Detected inactive net connection (NetworkManager) for id %d" nic_id; + xs.Xs.write xsnode "1"; + | _ -> () + ) + +let process_signal state xs bus msg = + let interface = match DBus.Message.get_interface msg with None -> "" | Some i -> i in + let member = match DBus.Message.get_member msg with None -> "" | Some m -> m in + let path = match DBus.Message.get_path msg with None -> "" | Some p -> p in + let params = DBus.Message.get msg in + match interface, member, params with + | "org.freedesktop.NetworkManager.Device", + "StateChanged", + [DBus.UInt32 news; DBus.UInt32 olds; DBus.UInt32 reason] -> + (* new state *) + let news = devstate_of_int (Int32.to_int news) in + (* previous state *) + let olds = devstate_of_int (Int32.to_int olds) in + (* to keep it simple we look the nic by bridge name.. *) + let bridge = get_devintf bus path in + let nics = List.filter (fun n -> n.ns_bridge = bridge) state.vm_nics in + (match nics with + | [nic] -> + let id = nic.ns_id in + when_conn_changed xs state id news olds + | _ -> + () + ) + | _ -> () + diff --git a/xenvm/xenvm.ml b/xenvm/xenvm.ml index b31df63..066c97c 100644 --- a/xenvm/xenvm.ml +++ b/xenvm/xenvm.ml @@ -748,6 +748,9 @@ let monitor_rpc_dbus state = | _ -> failwith (Printf.sprintf "cannot grab dbus intf %s" intf) ); (*DBus.Bus.add_match bus match_s false;*) + (* listen to Network Manager notificatons *) + DBus.Bus.add_match bus "type='signal',interface='org.freedesktop.NetworkManager.Device'" false; + DBus.Connection.flush bus; let outgoing_mutex = Mutex.create () in @@ -814,6 +817,10 @@ let monitor_rpc_dbus state = "expecting string method followed by dictionnary" in Some (err_msg) in + let process_signal msg = + (* handle network manager signals *) + with_xs (fun xs -> Network_manager.process_signal state xs bus msg) + in let process_message msg = let ty = DBus.Message.get_type msg in match ty with @@ -824,6 +831,7 @@ let monitor_rpc_dbus state = | DBus.Message.Method_call -> process_method_call msg | DBus.Message.Signal -> + process_signal msg; None | _ -> info "unknown dbus message %s" (DBus.Message.string_of_message_ty ty); -- 2.39.5