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

CA-201728: Add new function is_vlan_in_use #86

Merged
merged 1 commit into from
Jul 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lib/network_utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,19 @@ module Proc = struct
else
raise Not_found

let get_vlans () =
try
Unixext.file_lines_fold (fun vlans line ->
try
let x = Scanf.sscanf line "%s | %d | %s" (fun device vlan parent -> device, vlan, parent) in
x :: vlans
with _ ->
vlans
) [] "/proc/net/vlan/config"
with e ->
error "Error: could not read /proc/net/vlan/config";
[]

let get_bond_links_up name =
let statusses = get_bond_slave_info name "MII Status" in
List.fold_left (fun x (_, y) -> x + (if y = "up" then 1 else 0)) 0 statusses
Expand Down
40 changes: 27 additions & 13 deletions networkd/network_server.ml
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ module Interface = struct
Sysfs.is_physical name
) ()

let has_vlan _ dbg ~name ~vlan =
(* Identify the vlan is used by kernel which is unknown to XAPI *)
Debug.with_thread_associated dbg (fun () ->
List.exists (fun (_, v, p) -> v = vlan && p = name) (Proc.get_vlans ())
) ()

let bring_up _ dbg ~name =
Debug.with_thread_associated dbg (fun () ->
debug "Bringing up interface %s" name;
Expand Down Expand Up @@ -507,18 +513,7 @@ module Bridge = struct
match vlan with
| None -> ()
| Some (parent, vlan) ->
(* Robustness enhancement: ensure there are no other VLANs in the bridge *)
let current_interfaces = List.filter (fun n ->
String.startswith "eth" n || String.startswith "bond" n
) (Sysfs.bridge_to_interfaces name) in
debug "Removing these non-VIF interfaces found on the bridge: %s"
(String.concat ", " current_interfaces);
List.iter (fun interface ->
Brctl.destroy_port name interface;
Interface.bring_down () dbg ~name:interface
) current_interfaces;

(* Now create the new VLAN device and add it to the bridge *)
let bridge_interfaces = Sysfs.bridge_to_interfaces name in
let parent_bridge_interface = List.hd (List.filter (fun n ->
String.startswith "eth" n || String.startswith "bond" n
) (Sysfs.bridge_to_interfaces parent)) in
Expand All @@ -532,8 +527,27 @@ module Bridge = struct
end else
parent_bridge_interface
in
Ip.create_vlan parent_interface vlan;
let vlan_name = Ip.vlan_name parent_interface vlan in
(* Check if the VLAN is already in use by something else *)
List.iter (fun (device, vlan', parent') ->
(* A device for the same VLAN (parent + tag), but with a different
* device name or not on the requested bridge is bad. *)
if parent' = parent && vlan' = vlan &&
(device <> vlan_name || not (List.mem device bridge_interfaces)) then
raise (Vlan_in_use (parent, vlan))
) (Proc.get_vlans ());
(* Robustness enhancement: ensure there are no other VLANs in the bridge *)
let current_interfaces = List.filter (fun n ->
String.startswith "eth" n || String.startswith "bond" n
) bridge_interfaces in
debug "Removing these non-VIF interfaces found on the bridge: %s"
(String.concat ", " current_interfaces);
List.iter (fun interface ->
Brctl.destroy_port name interface;
Interface.bring_down () dbg ~name:interface
) current_interfaces;
(* Now create the new VLAN device and add it to the bridge *)
Ip.create_vlan parent_interface vlan;
Interface.bring_up () dbg ~name:vlan_name;
Brctl.create_port name vlan_name
end;
Expand Down