Skip to content

Commit 6cc2616

Browse files
authored
Merge pull request #86 from sharady/CA-201728
CA-201728: Add new function `is_vlan_in_use`
2 parents 7aa4234 + 0b1198a commit 6cc2616

File tree

2 files changed

+40
-13
lines changed

2 files changed

+40
-13
lines changed

lib/network_utils.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,19 @@ module Proc = struct
678678
else
679679
raise Not_found
680680

681+
let get_vlans () =
682+
try
683+
Unixext.file_lines_fold (fun vlans line ->
684+
try
685+
let x = Scanf.sscanf line "%s | %d | %s" (fun device vlan parent -> device, vlan, parent) in
686+
x :: vlans
687+
with _ ->
688+
vlans
689+
) [] "/proc/net/vlan/config"
690+
with e ->
691+
error "Error: could not read /proc/net/vlan/config";
692+
[]
693+
681694
let get_bond_links_up name =
682695
let statusses = get_bond_slave_info name "MII Status" in
683696
List.fold_left (fun x (_, y) -> x + (if y = "up" then 1 else 0)) 0 statusses

networkd/network_server.ml

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ module Interface = struct
336336
Sysfs.is_physical name
337337
) ()
338338

339+
let has_vlan _ dbg ~name ~vlan =
340+
(* Identify the vlan is used by kernel which is unknown to XAPI *)
341+
Debug.with_thread_associated dbg (fun () ->
342+
List.exists (fun (_, v, p) -> v = vlan && p = name) (Proc.get_vlans ())
343+
) ()
344+
339345
let bring_up _ dbg ~name =
340346
Debug.with_thread_associated dbg (fun () ->
341347
debug "Bringing up interface %s" name;
@@ -507,18 +513,7 @@ module Bridge = struct
507513
match vlan with
508514
| None -> ()
509515
| Some (parent, vlan) ->
510-
(* Robustness enhancement: ensure there are no other VLANs in the bridge *)
511-
let current_interfaces = List.filter (fun n ->
512-
String.startswith "eth" n || String.startswith "bond" n
513-
) (Sysfs.bridge_to_interfaces name) in
514-
debug "Removing these non-VIF interfaces found on the bridge: %s"
515-
(String.concat ", " current_interfaces);
516-
List.iter (fun interface ->
517-
Brctl.destroy_port name interface;
518-
Interface.bring_down () dbg ~name:interface
519-
) current_interfaces;
520-
521-
(* Now create the new VLAN device and add it to the bridge *)
516+
let bridge_interfaces = Sysfs.bridge_to_interfaces name in
522517
let parent_bridge_interface = List.hd (List.filter (fun n ->
523518
String.startswith "eth" n || String.startswith "bond" n
524519
) (Sysfs.bridge_to_interfaces parent)) in
@@ -532,8 +527,27 @@ module Bridge = struct
532527
end else
533528
parent_bridge_interface
534529
in
535-
Ip.create_vlan parent_interface vlan;
536530
let vlan_name = Ip.vlan_name parent_interface vlan in
531+
(* Check if the VLAN is already in use by something else *)
532+
List.iter (fun (device, vlan', parent') ->
533+
(* A device for the same VLAN (parent + tag), but with a different
534+
* device name or not on the requested bridge is bad. *)
535+
if parent' = parent && vlan' = vlan &&
536+
(device <> vlan_name || not (List.mem device bridge_interfaces)) then
537+
raise (Vlan_in_use (parent, vlan))
538+
) (Proc.get_vlans ());
539+
(* Robustness enhancement: ensure there are no other VLANs in the bridge *)
540+
let current_interfaces = List.filter (fun n ->
541+
String.startswith "eth" n || String.startswith "bond" n
542+
) bridge_interfaces in
543+
debug "Removing these non-VIF interfaces found on the bridge: %s"
544+
(String.concat ", " current_interfaces);
545+
List.iter (fun interface ->
546+
Brctl.destroy_port name interface;
547+
Interface.bring_down () dbg ~name:interface
548+
) current_interfaces;
549+
(* Now create the new VLAN device and add it to the bridge *)
550+
Ip.create_vlan parent_interface vlan;
537551
Interface.bring_up () dbg ~name:vlan_name;
538552
Brctl.create_port name vlan_name
539553
end;

0 commit comments

Comments
 (0)