--- /dev/null
+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
+ | _ ->
+ ()
+ )
+ | _ -> ()
+
| _ -> 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
"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
| 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);