From: Jon Ludlam Date: Tue, 25 Aug 2009 12:24:19 +0000 (+0100) Subject: Generate MAC/bridge on reading the config file rather than on starting the VM X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=7de09299301d804ba82ad0e52bb4b7002d1dc1d3;p=xenclient%2Ftoolstack.git Generate MAC/bridge on reading the config file rather than on starting the VM --- diff --git a/xenvm/vmact.ml b/xenvm/vmact.ml index 5fe4f11..ad8794e 100644 --- a/xenvm/vmact.ml +++ b/xenvm/vmact.ml @@ -111,65 +111,9 @@ let add_disk_to_vm ~xs state disk = () let add_nic_to_vm ~xs state nic = - nic.nic_bridge_gen <- ( - match nic.nic_bridge with - | None -> - let l = Netdev.Bridge.list () in - if List.length l > 0 then - List.hd l - else - "" - | Some bridge -> - if Netdev.Bridge.exists bridge then - bridge - else - "" - ); - if nic.nic_mac_gen = "" then ( - let generate_random_mac () = - String.concat ":" (List.map (sprintf "%02x") - ([0x00; 0x16; 0x3e] @ - List.map Random.int [0x80; 0x100; 0x100])) - in - let generate_vm_mac nic_id nic_model vm_uuid = - let s_of_c c1 c2 = - let s = String.create 2 in - s.[0] <- c1; s.[1] <- c2; s - in - let unicast_local h = - let v = int_of_string ("0x" ^ (List.hd h)) in - let n = sprintf "%02x" (0x2 lor (v land 0xfe)) in - n :: (List.tl h) - in - let vector = - (if nic_id = -1 then [] else [ string_of_int nic_id ]) @ - (match nic_model with None -> [] | Some x -> [ x ]) @ - [ vm_uuid ] - in - let digest = Digest.to_hex (Digest.string (String.concat " " vector)) in - let hexs = List.map (fun i -> s_of_c digest.[i] digest.[i + 12]) [ 0; 2; 1; 7; 6; 4 ] in - String.concat ":" (unicast_local hexs) - in - let is_valid_mac s = - let x = String.split ':' s in - if List.length x != 6 then - false - else ( - try ignore (List.map (fun s -> int_of_string ("0x" ^ s)) x); true - with _ -> false - ) - in - nic.nic_mac_gen <- ( - match nic.nic_mac with - | Some "random" -> generate_random_mac (); - | None | Some "vm" -> generate_vm_mac nic.nic_id nic.nic_model state.vm_uuid - | Some mac -> - if is_valid_mac mac then mac else generate_vm_mac nic.nic_id nic.nic_model state.vm_uuid - ) - ); - let netty = Netman.Bridge nic.nic_bridge_gen in + let netty = Netman.Bridge nic.nic_bridge in let (_: Device_common.device) = - Device.Vif.add ~xs ~devid:nic.nic_id ~netty ~mac:nic.nic_mac_gen + Device.Vif.add ~xs ~devid:nic.nic_id ~netty ~mac:nic.nic_mac ~protocol:(devproto_of_state state) state.vm_domid in () @@ -191,7 +135,7 @@ let get_pcis cfg = let dm_info_of_cfg cfg = let nics = get_nics cfg in - let nics = List.map (fun nic -> nic.nic_mac_gen, nic.nic_bridge_gen, nic.nic_model) nics in + let nics = List.map (fun nic -> nic.nic_mac, nic.nic_bridge, if nic.nic_model="" then None else Some nic.nic_model) nics in let disp = match cfg.display with | DisplayNone -> Device.Dm.NONE @@ -610,7 +554,7 @@ let device_cmd xc xs state ty subcmd args = let nic_list args = let l = List.map (fun nic -> sprintf "id: %d, bridge:%s, mac:%s\n" - nic.nic_id nic.nic_bridge_gen nic.nic_mac_gen + nic.nic_id nic.nic_bridge nic.nic_mac ) cfg.nics in Xenvmlib.Msg (String.concat "" l) in @@ -652,7 +596,7 @@ let get_new_config state = match state.vm_next_cfg with | None -> state.vm_cfg | Some cfg -> cfg - + let set_new_config state cfg = state.vm_next_cfg <- Some cfg @@ -679,13 +623,13 @@ let add_disk state path device ty mode devtype = Xenvmlib.Ok let add_nic state bridge mac model = - let nic = { Vmconfig.default_nic with - Vmconfig.nic_bridge = bridge; - Vmconfig.nic_mac = mac; - Vmconfig.nic_model = model; - } in + let nic = Vmconfig.default_nic in + let nic = match bridge with Some x -> {nic with nic_bridge=x} | None -> nic in + let nic = match mac with Some x -> {nic with nic_mac=x} | None -> nic in + let nic = match model with Some x -> {nic with nic_model=x} | None -> nic in let cfg = get_new_config state in - let cfg = { cfg with nics = cfg.nics @ [ nic ] } in + let nics = Vmconfig.Config.sanitise_nics state.vm_uuid (cfg.nics @ [ nic ]) in + let cfg = { cfg with nics = nics } in set_new_config state cfg; Xenvmlib.Ok diff --git a/xenvm/vmconfig.ml b/xenvm/vmconfig.ml index 15a5aa2..d687393 100644 --- a/xenvm/vmconfig.ml +++ b/xenvm/vmconfig.ml @@ -87,11 +87,9 @@ type config_disk = { type config_nic = { nic_id: int; - nic_bridge: string option; - mutable nic_bridge_gen: string; - nic_mac: string option; - mutable nic_mac_gen: string; - nic_model: string option; + nic_bridge: string; + nic_mac: string; + nic_model: string; nic_dynadded: bool; } @@ -156,11 +154,9 @@ type config = { let default_nic = { nic_id = -1; - nic_bridge = None; - nic_bridge_gen = ""; - nic_mac = None; - nic_mac_gen = ""; - nic_model = None; + nic_bridge = ""; + nic_mac = ""; + nic_model = ""; nic_dynadded = false; } @@ -212,9 +208,9 @@ let config_nic_of_string s = let ls = if s = "" then [] else String.split ',' s in let id = ref (-1) - and bridge = ref None - and model = ref None - and mac = ref None in + and bridge = ref "" + and model = ref "" + and mac = ref "" in List.iter (fun v -> let lv = String.split '=' v in @@ -223,9 +219,9 @@ let config_nic_of_string s = match lvalue with | "id" -> id := int_of_string value - | "bridge" -> bridge := Some value - | "model" -> model := Some value - | "mac" -> mac := Some value + | "bridge" -> bridge := value + | "model" -> model := value + | "mac" -> mac := value | _ -> () ) ls; @@ -236,8 +232,8 @@ let config_nic_of_string s = nic_model = !model; } -(* Where NIC IDs have been left blank (or explicitly set to -1), here we allocate them a reasonable number *) -let assign_nic_ids nics = +(* Where NIC IDs have been left blank (or explicitly set to -1), here we allocate them a reasonable number. We also allocate a bridge and a mac, if necessary *) +let sanitise_nics vm_uuid nics = let sort_nics nics = List.sort (fun nic1 nic2 -> compare nic1.nic_id nic2.nic_id) nics in let assert_ok nics = ignore(List.fold_left (fun last_id nic -> @@ -259,7 +255,69 @@ let assign_nic_ids nics = let (assigned,unassigned) = List.partition (fun nic -> nic.nic_id >= 0) nics in let nics = List.fold_right allocate_nic_id unassigned (sort_nics assigned) in assert_ok nics; - nics + + let fix_bridge nic = + {nic with nic_bridge = + match nic.nic_bridge with + | "" -> + let l = Netdev.Bridge.list () in + if List.length l > 0 then + List.hd l + else + "" + | bridge -> + if Netdev.Bridge.exists bridge then + bridge + else + ""} in + + let nics = List.map fix_bridge nics in + + let fix_mac nic = + {nic with nic_mac = + if nic.nic_mac <> "" then nic.nic_mac else ( + let generate_random_mac () = + String.concat ":" (List.map (sprintf "%02x") + ([0x00; 0x16; 0x3e] @ + List.map Random.int [0x80; 0x100; 0x100])) + in + let generate_vm_mac nic_id nic_model vm_uuid = + let s_of_c c1 c2 = + let s = String.create 2 in + s.[0] <- c1; s.[1] <- c2; s + in + let unicast_local h = + let v = int_of_string ("0x" ^ (List.hd h)) in + let n = sprintf "%02x" (0x2 lor (v land 0xfe)) in + n :: (List.tl h) + in + let vector = + (if nic_id = -1 then [] else [ string_of_int nic_id ]) @ + (match nic_model with "" -> [] | x -> [ x ]) @ + [ vm_uuid ] + in + let digest = Digest.to_hex (Digest.string (String.concat " " vector)) in + let hexs = List.map (fun i -> s_of_c digest.[i] digest.[i + 12]) [ 0; 2; 1; 7; 6; 4 ] in + String.concat ":" (unicast_local hexs) + in + let is_valid_mac s = + let x = String.split ':' s in + if List.length x != 6 then + false + else ( + try ignore (List.map (fun s -> int_of_string ("0x" ^ s)) x); true + with _ -> false + ) + in + match nic.nic_mac with + | "random" -> generate_random_mac (); + | "" | "vm" -> generate_vm_mac nic.nic_id nic.nic_model vm_uuid + | mac -> + if is_valid_mac mac then mac else generate_vm_mac nic.nic_id nic.nic_model vm_uuid + ) + } + in + List.map fix_mac nics let config_disk_of_string s = (* physpath:phystype:virtpath:mode:devtype *) @@ -588,7 +646,7 @@ let of_file uuid error_report file = Config.Error ls -> error_report ls end; - let nics = assign_nic_ids !cfg.nics in + let nics = sanitise_nics uuid !cfg.nics in { !cfg with __uuid = !__uuid; diff --git a/xenvm/xenvm.ml b/xenvm/xenvm.ml index 32e0a3a..989193c 100644 --- a/xenvm/xenvm.ml +++ b/xenvm/xenvm.ml @@ -289,8 +289,8 @@ let monitor_vm state = let online = Hotplug.device_is_online ~xs device in let connected = Hotplug.device_is_connected ~xs device in if online && not connected then ( - let netty = Netman.Bridge nic.nic_bridge_gen in - let mac = nic.nic_mac_gen in + let netty = Netman.Bridge nic.nic_bridge in + let mac = nic.nic_mac in let protocol = Vmact.devproto_of_state state in let (_: Device_common.device) = Device.Vif.plug ~xs ~netty ~mac ~protocol device in ()