@@ -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