@@ -26,6 +26,7 @@ type context = unit
2626
2727let network_conf = ref " /etc/xcp/network.conf"
2828let config : config_t ref = ref empty_config
29+ let backend_kind = ref Openvswitch
2930
3031let legacy_management_interface_start () =
3132 try
@@ -84,6 +85,13 @@ let set_dns_interface _ dbg ~name =
8485 debug " Setting DNS interface to %s" name;
8586 config := {! config with dns_interface = Some name}
8687
88+ (* The enic driver is for Cisco UCS devices. The current driver adds VLAN0 headers
89+ * to all incoming packets, which confuses certain guests OSes. The workaround
90+ * constitutes adding a VLAN0 Linux device to strip those headers again.
91+ *)
92+ let need_enic_workaround () =
93+ ! backend_kind = Bridge && List. mem " enic" (Sysfs. list_drivers () )
94+
8795module Interface = struct
8896 let get_config name =
8997 get_config ! config.interface_config default_interface name
@@ -356,6 +364,17 @@ module Interface = struct
356364 end else
357365 config
358366 in
367+ let config =
368+ if need_enic_workaround () then
369+ List. fold_left (fun accu (name , interface ) ->
370+ if (Sysfs. is_physical name && Linux_bonding. get_bond_master_of name = None ) || Linux_bonding. is_bond_device name then
371+ (name, interface) :: (Ip. vlan_name name 0 , interface) :: accu
372+ else
373+ (name, interface) :: accu
374+ ) [] config
375+ else
376+ config
377+ in
359378 debug " ** Configuring the following interfaces: %s" (String. concat " , " (List. map (fun (name , _ ) -> name) config));
360379 let exec f = if conservative then (try f () with _ -> () ) else f () in
361380 List. iter (function (name, ({ipv4_conf; ipv4_gateway; ipv6_conf; ipv6_gateway; ipv4_routes; dns= nameservers,domains; mtu;
@@ -378,7 +397,6 @@ module Interface = struct
378397end
379398
380399module Bridge = struct
381- let kind = ref Openvswitch
382400 let add_default = ref []
383401
384402 let get_config name =
@@ -394,25 +412,25 @@ module Bridge = struct
394412 try
395413 let backend = String. strip String. isspace (Unixext. string_of_file ! network_conf) in
396414 match backend with
397- | "openvswitch" | "vswitch" -> kind := Openvswitch
398- | "bridge" -> kind := Bridge
415+ | "openvswitch" | "vswitch" -> backend_kind := Openvswitch
416+ | "bridge" -> backend_kind := Bridge
399417 | backend ->
400418 warn " Network backend unknown (%s). Falling back to Open vSwitch." backend;
401- kind := Openvswitch
419+ backend_kind := Openvswitch
402420 with _ ->
403421 warn " Network-conf file not found. Falling back to Open vSwitch." ;
404- kind := Openvswitch
422+ backend_kind := Openvswitch
405423
406424 let get_bond_links_up _ dbg ~name =
407425 Debug. with_thread_associated dbg (fun () ->
408- match ! kind with
426+ match ! backend_kind with
409427 | Openvswitch -> Ovs. get_bond_links_up name
410428 | Bridge -> Proc. get_bond_links_up name
411429 ) ()
412430
413431 let get_all _ dbg () =
414432 Debug. with_thread_associated dbg (fun () ->
415- match ! kind with
433+ match ! backend_kind with
416434 | Openvswitch -> Ovs. list_bridges ()
417435 | Bridge -> Sysfs. get_all_bridges ()
418436 ) ()
@@ -424,7 +442,7 @@ module Bridge = struct
424442 | Some (parent , vlan ) -> Printf. sprintf " (VLAN %d on bridge %s)" vlan parent
425443 );
426444 update_config name {(get_config name) with vlan; bridge_mac= mac; other_config};
427- begin match ! kind with
445+ begin match ! backend_kind with
428446 | Openvswitch ->
429447 let fail_mode =
430448 if not (List. mem_assoc " vswitch-controller-fail-mode" other_config) then
@@ -499,7 +517,7 @@ module Bridge = struct
499517 let destroy _ dbg ?(force =false ) ~name () =
500518 Debug. with_thread_associated dbg (fun () ->
501519 Interface. bring_down () dbg ~name ;
502- match ! kind with
520+ match ! backend_kind with
503521 | Openvswitch ->
504522 if Ovs. get_vlans name = [] || force then begin
505523 debug " Destroying bridge %s" name;
@@ -532,8 +550,14 @@ module Bridge = struct
532550 Interface. bring_down () dbg ~name: dev;
533551 if Linux_bonding. is_bond_device dev then
534552 Linux_bonding. remove_bond_master dev;
535- if String. startswith " eth" dev && String. contains dev '.' then
536- ignore (Ip. destroy_vlan dev)
553+ if (String. startswith " eth" dev || String. startswith " bond" dev) && String. contains dev '.' then begin
554+ ignore (Ip. destroy_vlan dev);
555+ let n = String. length dev in
556+ if String. sub dev (n - 2 ) 2 = " .0" && need_enic_workaround () then
557+ let vlan_base = String. sub dev 0 (n - 2 ) in
558+ if Linux_bonding. is_bond_device vlan_base then
559+ Linux_bonding. remove_bond_master (String. sub dev 0 (n - 2 ))
560+ end ;
537561 ) ifs;
538562 Interface. set_ipv4_conf () dbg ~name ~conf: None4 ;
539563 ignore (Brctl. destroy_bridge name)
@@ -543,12 +567,12 @@ module Bridge = struct
543567
544568 let get_kind _ dbg () =
545569 Debug. with_thread_associated dbg (fun () ->
546- ! kind
570+ ! backend_kind
547571 ) ()
548572
549573 let get_ports _ dbg ~name =
550574 Debug. with_thread_associated dbg (fun () ->
551- match ! kind with
575+ match ! backend_kind with
552576 | Openvswitch -> Ovs. bridge_to_ports name
553577 | Bridge -> raise Not_implemented
554578 ) ()
@@ -559,14 +583,14 @@ module Bridge = struct
559583 let ports = List. concat (List. map (fun (_ , {ports} ) -> ports) ! config.bridge_config) in
560584 List. map (fun (port , {interfaces} ) -> port, interfaces) ports
561585 else
562- match ! kind with
586+ match ! backend_kind with
563587 | Openvswitch -> List. concat (List. map Ovs. bridge_to_ports (Ovs. list_bridges () ))
564588 | Bridge -> raise Not_implemented
565589 ) ()
566590
567591 let get_bonds _ dbg ~name =
568592 Debug. with_thread_associated dbg (fun () ->
569- match ! kind with
593+ match ! backend_kind with
570594 | Openvswitch -> Ovs. bridge_to_ports name
571595 | Bridge -> raise Not_implemented
572596 ) ()
@@ -578,21 +602,21 @@ module Bridge = struct
578602 let names = List. map (fun (port , {interfaces} ) -> port, interfaces) ports in
579603 List. filter (fun (_ , ifs ) -> List. length ifs > 1 ) names
580604 else
581- match ! kind with
605+ match ! backend_kind with
582606 | Openvswitch -> List. concat (List. map Ovs. bridge_to_ports (Ovs. list_bridges () ))
583607 | Bridge -> raise Not_implemented
584608 ) ()
585609
586610 let get_vlan _ dbg ~name =
587611 Debug. with_thread_associated dbg (fun () ->
588- match ! kind with
612+ match ! backend_kind with
589613 | Openvswitch -> Ovs. bridge_to_vlan name
590614 | Bridge -> raise Not_implemented
591615 ) ()
592616
593617 let add_default_flows _ dbg bridge mac interfaces =
594618 Debug. with_thread_associated dbg (fun () ->
595- match ! kind with
619+ match ! backend_kind with
596620 | Openvswitch -> Ovs. add_default_flows bridge mac interfaces
597621 | Bridge -> ()
598622 ) ()
@@ -611,7 +635,7 @@ module Bridge = struct
611635 debug " Adding port %s to bridge %s with interfaces %s%s" name bridge
612636 (String. concat " , " interfaces)
613637 (match bond_mac with Some mac -> " and MAC " ^ mac | None -> " " );
614- match ! kind with
638+ match ! backend_kind with
615639 | Openvswitch ->
616640 if List. length interfaces = 1 then begin
617641 List. iter (fun name -> Interface. bring_up () dbg ~name ) interfaces;
@@ -636,10 +660,9 @@ module Bridge = struct
636660 name bridge
637661 end
638662 | Bridge ->
639- if List. length interfaces = 1 then begin
640- List. iter (fun name -> Interface. bring_up () dbg ~name ) interfaces;
641- ignore (Brctl. create_port bridge name)
642- end else begin
663+ if List. length interfaces = 1 then
664+ List. iter (fun name -> Interface. bring_up () dbg ~name ) interfaces
665+ else begin
643666 if not (List. mem name (Sysfs. bridge_to_interfaces bridge)) then begin
644667 Linux_bonding. add_bond_master name;
645668 let bond_properties =
@@ -655,9 +678,16 @@ module Bridge = struct
655678 | None -> warn " No MAC address specified for the bond"
656679 end
657680 end ;
658- Interface. bring_up () dbg ~name ;
681+ Interface. bring_up () dbg ~name
682+ end ;
683+ if need_enic_workaround () then begin
684+ debug " Applying enic workaround: adding VLAN0 device to bridge" ;
685+ Ip. create_vlan name 0 ;
686+ let vlan0 = Ip. vlan_name name 0 in
687+ Interface. bring_up () dbg ~name: vlan0;
688+ ignore (Brctl. create_port bridge vlan0)
689+ end else
659690 ignore (Brctl. create_port bridge name)
660- end
661691 ) ()
662692
663693 let remove_port _ dbg ~bridge ~name =
@@ -668,7 +698,7 @@ module Bridge = struct
668698 let ports = List. remove_assoc name config.ports in
669699 update_config bridge {config with ports}
670700 end ;
671- match ! kind with
701+ match ! backend_kind with
672702 | Openvswitch ->
673703 ignore (Ovs. destroy_port name)
674704 | Bridge ->
@@ -677,7 +707,7 @@ module Bridge = struct
677707
678708 let get_interfaces _ dbg ~name =
679709 Debug. with_thread_associated dbg (fun () ->
680- match ! kind with
710+ match ! backend_kind with
681711 | Openvswitch ->
682712 Ovs. bridge_to_interfaces name
683713 | Bridge ->
@@ -686,7 +716,7 @@ module Bridge = struct
686716
687717 let get_fail_mode _ dbg ~name =
688718 Debug. with_thread_associated dbg (fun () ->
689- match ! kind with
719+ match ! backend_kind with
690720 | Openvswitch ->
691721 begin match Ovs. get_fail_mode name with
692722 | "standalone" -> Some Standalone
@@ -769,7 +799,7 @@ let on_startup () =
769799 (* the following is best-effort *)
770800 read_config () ;
771801 remove_centos_config () ;
772- if ! Bridge. kind = Openvswitch then
802+ if ! backend_kind = Openvswitch then
773803 Ovs. set_max_idle 5000 ;
774804 Bridge. make_config () dbg ~conservative: true ~config: ! config.bridge_config () ;
775805 Interface. make_config () dbg ~conservative: true ~config: ! config.interface_config () ;
0 commit comments