@@ -835,7 +835,7 @@ def finalize_config(self, dps):
835835
836836 dp_by_name = {}
837837 vlan_by_name = {}
838- external_ports = False
838+ vlans_with_external_ports = set ()
839839
840840 def resolve_ports (port_names ):
841841 """Resolve list of ports, by port by name or number."""
@@ -856,12 +856,21 @@ def resolve_vlan(vlan_name):
856856 return self .vlans [vlan_name ]
857857 return None
858858
859+ def resolve_vlans (vlan_names ):
860+ """Resolve a list of VLAN names."""
861+ vlans = []
862+ for vlan_name in vlan_names :
863+ vlan = resolve_vlan (vlan_name )
864+ if vlan :
865+ vlans .append (vlan )
866+ return vlans
867+
859868 def resolve_stack_dps ():
860869 """Resolve DP references in stacking config."""
861870 if self .stack_ports :
862871 if self .stack is None :
863872 self .stack = {}
864- self .stack ['externals' ] = external_ports
873+ self .stack ['externals' ] = bool ( vlans_with_external_ports )
865874 port_stack_dp = {}
866875 for port in self .stack_ports :
867876 stack_dp = port .stack ['dp' ]
@@ -1037,70 +1046,66 @@ def resolve_acls():
10371046 for tunnel_acl in self .tunnel_acls .values ():
10381047 tunnel_acl .verify_tunnel_compatibility_rules (self )
10391048
1040- def resolve_vlan_names_in_routers ():
1049+ def resolve_routers ():
10411050 """Resolve VLAN references in routers."""
10421051 dp_routers = {}
10431052 for router_name , router in self .routers .items ():
10441053 if router .bgp_vlan ():
10451054 router .set_bgp_vlan (resolve_vlan (router .bgp_vlan ()))
1046- vlans = []
1047- for vlan_name in router .vlans :
1048- vlan = resolve_vlan (vlan_name )
1049- if vlan is not None :
1050- vlans .append (vlan )
1051- if len (vlans ):
1055+ vlans = resolve_vlans (router .vlans )
1056+ if vlans or router .bgp_vlan ():
10521057 dp_router = copy .copy (router )
10531058 dp_router .vlans = vlans
10541059 dp_routers [router_name ] = dp_router
1060+ self .routers = dp_routers
1061+
1062+ if self .global_vlan :
1063+ vids = {vlan .vid for vlan in self .vlans .values ()}
1064+ test_config_condition (
1065+ self .global_vlan in vids , 'global_vlan VID %s conflicts with existing VLAN' % self .global_vlan )
1066+
1067+ # Check for overlapping VIP subnets or VLANs.
1068+ all_router_vlans = set ()
1069+ for router_name , router in self .routers .items ():
10551070 vips = set ()
1056- for vlan in vlans :
1057- for vip in vlan .faucet_vips :
1058- if vip . ip . is_link_local :
1059- continue
1060- vips .add (vip )
1071+ for vlan in router . vlans :
1072+ vips . update ({ vip for vip in vlan .faucet_vips if not vip . ip . is_link_local })
1073+ test_config_condition (
1074+ vlan in all_router_vlans , 'VLAN %s in more than one router' % vlan )
1075+ all_router_vlans .add (vlan )
10611076 for vip in vips :
10621077 for other_vip in vips - set ([vip ]):
10631078 test_config_condition (
10641079 vip .ip in other_vip .network ,
10651080 'VIPs %s and %s overlap in router %s' % (
10661081 vip , other_vip , router_name ))
1067- self .routers = dp_routers
1082+ bgp_routers = self .bgp_routers ()
1083+ if bgp_routers :
1084+ for bgp_router in bgp_routers :
1085+ bgp_vlan = bgp_router .bgp_vlan ()
1086+ vlan_dps = [dp for dp in dps if bgp_vlan .vid in dp .vlans ]
1087+ test_config_condition (len (vlan_dps ) != 1 , (
1088+ 'DPs %s sharing a BGP speaker VLAN is unsupported' ))
1089+ test_config_condition (bgp_router .bgp_server_addresses () != (
1090+ bgp_routers [0 ].bgp_server_addresses ()), (
1091+ 'BGP server addresses must all be the same' ))
1092+ router_ids = {bgp_router .bgp_routerid () for bgp_router in bgp_routers }
1093+ test_config_condition (len (router_ids ) != 1 , 'BGP router IDs must all be the same: %s' % router_ids )
1094+ bgp_ports = {bgp_router .bgp_port () for bgp_router in bgp_routers }
1095+ test_config_condition (len (bgp_ports ) != 1 , 'BGP ports must all be the same: %s' % bgp_ports )
10681096
1069- test_config_condition (not self .vlans , 'no VLANs referenced by interfaces in %s' % self .name )
1070-
1071- for dp in dps :
1072- dp_by_name [dp .name ] = dp
1073- for vlan in self .vlans .values ():
1074- vlan_by_name [vlan .name ] = vlan
1075- if self .global_vlan :
1076- test_config_condition (
1077- self .global_vlan == vlan .vid , 'VLAN %u is reserved by global_vlan' % vlan .vid )
10781097
1079- for vlan in vlan_by_name .values ():
1080- if vlan .loop_protect_external_ports ():
1081- external_ports = True
1082- break
1098+ test_config_condition (not self .vlans , 'no VLANs referenced by interfaces in %s' % self .name )
1099+ dp_by_name = {dp .name : dp for dp in dps }
1100+ vlan_by_name = {vlan .name : vlan for vlan in self .vlans .values ()}
1101+ vlans_with_external_ports = {
1102+ vlan for vlan in self .vlans .values () if vlan .loop_protect_external_ports ()}
10831103
10841104 resolve_stack_dps ()
10851105 resolve_mirror_destinations ()
10861106 resolve_override_output_ports ()
1087- resolve_vlan_names_in_routers ()
10881107 resolve_acls ()
1089-
1090- bgp_routers = self .bgp_routers ()
1091- if bgp_routers :
1092- for bgp_router in bgp_routers :
1093- bgp_vlan = bgp_router .bgp_vlan ()
1094- vlan_dps = [dp for dp in dps if bgp_vlan .vid in dp .vlans ]
1095- test_config_condition (len (vlan_dps ) != 1 , (
1096- 'DPs %s sharing a BGP speaker VLAN is unsupported' ))
1097- test_config_condition (bgp_router .bgp_server_addresses () != (
1098- bgp_routers [0 ].bgp_server_addresses ()), (
1099- 'BGP server addresses must all be the same' ))
1100- router_ids = {bgp_router .bgp_routerid () for bgp_router in bgp_routers }
1101- test_config_condition (len (router_ids ) != 1 , 'BGP router IDs must all be the same: %s' % router_ids )
1102- bgp_ports = {bgp_router .bgp_port () for bgp_router in bgp_routers }
1103- test_config_condition (len (bgp_ports ) != 1 , 'BGP ports must all be the same: %s' % bgp_ports )
1108+ resolve_routers ()
11041109
11051110 self ._configure_tables ()
11061111
0 commit comments