diff --git a/lib/network_utils.ml b/lib/network_utils.ml index aeaccc5b2..c9aa5f253 100644 --- a/lib/network_utils.ml +++ b/lib/network_utils.ml @@ -74,6 +74,13 @@ module Sysfs = struct warn "Failed to obtain list of drivers from sysfs"; [] + let get_driver_version driver () = + try + Some (String.strip String.isspace (Unixext.string_of_file ("/sys/bus/pci/drivers/" ^ driver ^ "/module/version"))) + with _ -> + warn "Failed to obtain driver version from sysfs"; + None + let getpath dev attr = Printf.sprintf "/sys/class/net/%s/%s" dev attr diff --git a/networkd/network_server.ml b/networkd/network_server.ml index 53fbdf169..36c5e1bae 100644 --- a/networkd/network_server.ml +++ b/networkd/network_server.ml @@ -27,6 +27,7 @@ type context = unit let network_conf = ref "/etc/xcp/network.conf" let config : config_t ref = ref empty_config let backend_kind = ref Openvswitch +let enic_workaround_until_version = ref "2.3.0.30" let legacy_management_interface_start () = try @@ -85,12 +86,30 @@ let set_dns_interface _ dbg ~name = debug "Setting DNS interface to %s" name; config := {!config with dns_interface = Some name} +(* Returns `true` if vs1 is older than vs2 *) +let is_older_version vs1 vs2 () = + try + let list_of_version vs = List.map int_of_string (String.split '.' vs) in + let rec loop vs1' vs2' = + match vs1', vs2' with + | [], _ | _, [] -> false + | a :: _, b :: _ when a < b -> true + | _ :: tl1, _ :: tl2 -> loop tl1 tl2 + in + loop (list_of_version vs1) (list_of_version vs2) + with _ -> + warn "Failed to compare driver version."; + false + (* The enic driver is for Cisco UCS devices. The current driver adds VLAN0 headers * to all incoming packets, which confuses certain guests OSes. The workaround * constitutes adding a VLAN0 Linux device to strip those headers again. *) let need_enic_workaround () = - !backend_kind = Bridge && List.mem "enic" (Sysfs.list_drivers ()) + !backend_kind = Bridge && List.mem "enic" (Sysfs.list_drivers ()) && (!enic_workaround_until_version <> "") && ( + match Sysfs.get_driver_version "enic" () with + | Some vs -> (is_older_version vs !enic_workaround_until_version ()) + | None -> false ) module Interface = struct let get_config name = diff --git a/networkd/networkd.ml b/networkd/networkd.ml index 9929de17f..b0041e95a 100644 --- a/networkd/networkd.ml +++ b/networkd/networkd.ml @@ -53,9 +53,9 @@ let resources = [ let options = [ "monitor_blacklist", Arg.String (fun x -> Network_monitor_thread.monitor_blacklist := String.split ',' x), (fun () -> String.concat "," !Network_monitor_thread.monitor_blacklist), "List of prefixes of interface names that are not to be monitored"; "mac-table-size", Arg.Set_int Network_utils.mac_table_size, (fun () -> string_of_int !Network_utils.mac_table_size), "Default value for the mac-table-size openvswitch parameter (see ovs-vswitchd.conf.db.5)"; + "enic-workaround-until-version", Arg.Set_string Network_server.enic_workaround_until_version, (fun () -> !Network_server.enic_workaround_until_version), "The version till enic driver workaround will be applied or the version set to an empty string for not applying the workaround."; ] - let start server = Network_monitor_thread.start (); Network_server.on_startup (); diff --git a/xcp-networkd.conf b/xcp-networkd.conf index 1e7e9d04a..231eaf354 100644 --- a/xcp-networkd.conf +++ b/xcp-networkd.conf @@ -18,3 +18,6 @@ #The list of prefix interfaces that are not to be monitored #monitor-blacklist=dummy,xenbr,xapi,ovs-system,xenapi + +# The version till enic driver workaround will be applied or set the version to an empty string for not applying the workaround. +# enic-workaround-until-version = "2.3.0.30"