12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436 |
- import collections
- from functools import cmp_to_key
- import ipaddress
- import re
- from copy import deepcopy
- import ffho
- mac_prefix = "f2"
- vrf_info = {
- 'vrf_external' : {
- 'table' : 1023,
- 'fwmark' : [ '0x1', '0x1023' ],
- },
- 'vrf_mgmt' : {
- 'table' : 1042,
- },
- }
- default_bond_config = {
- 'bond-mode': '802.3ad',
- 'bond-min-links': '1',
- 'bond-xmit-hash-policy': 'layer3+4'
- }
- default_bridge_config = {
- 'bridge-fd' : '0',
- 'bridge-stp' : 'no',
- 'bridge-ports-condone-regex' : '^[a-zA-Z0-9]+_(v[0-9]{1,4}|eth[0-9])$',
- }
- default_hop_penalty_by_role = {
- 'bbr' : 5,
- 'bras' : 50,
- 'batman_gw' : 50,
- 'batman_ext': 50,
- }
- batman_role_evaluation_order = [ 'bbr', 'batman_gw', 'bras' ]
- default_batman_iface_penalty_by_role = {
- 'default' : 0,
- 'DCI' : 5,
- 'WBBL' : 10,
- 'WBBL_backup' : 15,
- 'VPN_intergw' : 80,
- 'VPN_node' : 100,
- }
- GRE_FFRL_attrs = {
- 'mode' : 'gre',
- 'method' : 'tunnel',
- 'mtu' : '1400',
- 'ttl' : '64',
- }
- loopback_prefix = {
- 'v4' : '10.132.255.',
- 'v6' : '2a03:2260:2342:ffff::',
- }
- MTU = {
-
-
-
- 'default' : 1500,
-
-
-
-
- 'batman_underlay_iface' : 1560,
-
-
-
-
-
-
-
- 'vxlan_underlay_iface' : 1610,
-
-
-
-
-
-
-
- 'vxlan_underlay_iface_ipv6' : 1630,
- }
- class Prefix (object):
- """An internet address with a prefix length.
- The given address is expected to be of format ip/plen in CIDR notation.
- The IP as well as the prefix length and address family will be stored
- in attributes.
- .. code-block:: pycon
- >>> a = Prefix ('10.132.23.42/24')
- >>> str (a.ip)
- '10.132.23.42'
- >>> str (a.af)
- '4'
- >>> str (a.plen)
- '24'
- >>> str (a.netmask)
- '255.255.255.0'
- >>> str (a.network_address)
- '10.132.23.0'
- """
- def __init__ (self, prefix):
- self.prefix = prefix
- self.ip_network = ipaddress.ip_network (u'%s' % prefix, strict = False)
- def __eq__ (self, other):
- if isinstance (other, Prefix):
- return self.ip_network == other.ip_network
- return NotImplemented
- def __lt__ (self, other):
- if isinstance (other, Prefix):
- return self.ip_network < other.ip_network
- return NotImplemented
- def __str__ (self):
- return self.prefix
- @property
- def ip (self):
- return self.prefix.split ('/')[0]
- @property
- def af (self):
- return self.ip_network.version
- @property
- def plen (self):
- return self.ip_network.prefixlen
- @property
- def netmask (self):
- return self.ip_network.netmask
- @property
- def network_address (self):
- return self.ip_network.network_address
- sites = None
- def _get_site_no (sites_config, site_name):
- global sites
- if sites == None:
- sites = {}
- for site in sites_config:
- if site.startswith ("_"):
- continue
- sites[site] = sites_config[site].get ("site_no", -2)
- return sites.get (site_name, -1)
- def gen_batman_iface_mac (site_no, device_no, network):
- net_type_map = {
- 'bat' : "00:00",
- 'dummy' : "00:0d",
- 'int2ext' : "00:0f",
- 'bat-e' : "00:e0",
- 'intergw' : "00:e1",
- 'nodes4' : "00:e4",
- 'nodes6' : "00:e6",
- 'dummy-e' : "00:ed",
- 'ext2int' : "00:ef",
- }
-
- if network in net_type_map:
- last = net_type_map[network]
- elif type (network) == int:
- last = re.sub (r'(\d{2})(\d{2})', '\g<1>:\g<2>', "%04d" % network)
- else:
- last = "ee:ee"
-
- device_no_hex = re.sub (r'([0-9a-fA-F]{2})([0-9a-fA-F]{2})', '\g<1>:\g<2>', "%04x" % int (device_no))
-
- site_no_hex = "%02d" % int (site_no)
- return "%s:%s:%s:%s" % (mac_prefix, device_no_hex, site_no_hex, last)
- def _update_batman_config (node_config, iface, sites_config):
- try:
- node_batman_hop_penalty = int (node_config['batman']['hop-penalty'])
- except (KeyError,ValueError):
- node_batman_hop_penalty = None
- iface_config = node_config['ifaces'][iface]
- iface_type = iface_config.get ('type', 'inet')
- batman_config = {}
- for item in list (iface_config.keys ()):
- value = iface_config.get (item)
- if item.startswith ('batman-'):
- batman_config[item] = value
- iface_config.pop (item)
-
- if iface_type == 'batman':
- if 'batman-hop-penalty' not in batman_config:
-
-
- if node_batman_hop_penalty:
- batman_config['batman-hop-penalty'] = node_batman_hop_penalty
-
-
- else:
- node_roles = node_config.get ('roles', [])
- for role in batman_role_evaluation_order:
- if role in node_roles:
- batman_config['batman-hop-penalty'] = default_hop_penalty_by_role[role]
- break
- if 'batman_ext' in node_roles and iface.endswith('-ext'):
- batman_config['batman-hop-penalty'] = default_hop_penalty_by_role['batman_ext']
-
-
- if 'batman-ifaces' in batman_config and type (batman_config['batman-ifaces']) == list:
- batman_iface_str = " ".join (sorted (batman_config['batman-ifaces']))
- batman_config['batman-ifaces'] = batman_iface_str
-
- elif iface_type == 'batman_iface':
-
-
-
- site = iface_config.get ('site')
- site_no = _get_site_no (sites_config, site)
- device_no = node_config.get ('id')
- network = 1234
-
- match = re.search (r'^vlan(\d+)', iface)
- if match:
- network = int (match.group (1))
- iface_config['hwaddress'] = gen_batman_iface_mac (site_no, device_no, network)
- iface_config['batman'] = batman_config
- def _update_bond_config (config):
- bond_config = default_bond_config.copy ()
- to_pop = []
- for item, value in config.items ():
- if item.startswith ('bond-'):
- bond_config[item] = value
- to_pop.append (item)
- for item in to_pop:
- config.pop (item)
- if bond_config['bond-mode'] not in ['2', 'balance-xor', '4', '802.3ad']:
- bond_config.pop ('bond-xmit-hash-policy')
- config['bond'] = bond_config
- def _update_bridge_config (config):
- bridge_config = default_bridge_config.copy ()
- for item in list (config.keys ()):
- value = config.get (item)
- if not item.startswith ('bridge-'):
- continue
- bridge_config[item] = value
- config.pop (item)
-
- if type (value) == bool:
- bridge_config[item] = "yes" if value else "no"
-
-
- if 'bridge-ports' in bridge_config and type (bridge_config['bridge-ports']) == list:
- bridge_ports_str = " ".join (sorted (bridge_config['bridge-ports']))
- if not bridge_ports_str:
- bridge_ports_str = "none"
- bridge_config['bridge-ports'] = bridge_ports_str
- if config.get ('vlan-mode') == 'tagged':
- bridge_config['bridge-vlan-aware'] = 'yes'
- if config.get ('tagged_vlans'):
- bridge_config['bridge-vids'] = " ".join (map (str, config['tagged_vlans']))
- config['bridge'] = bridge_config
- def _update_bridge_member_config (config):
- bridge_config = {}
- if config.get ('tagged_vlans'):
- bridge_config['bridge-vids'] = " ".join (map (str, config['tagged_vlans']))
- config['bridge'] = bridge_config
- def _update_vlan_config (config):
- vlan_config = {}
- for item in list (config.keys ()):
- value = config.get (item)
- if item.startswith ('vlan-'):
- vlan_config[item] = value
- config.pop (item)
- config['vlan'] = vlan_config
- def _update_veth_config (interface, config):
- veth_peer_name = {
- 'veth_ext2int' : 'veth_int2ext',
- 'veth_int2ext' : 'veth_ext2int'
- }
- if interface not in veth_peer_name:
- return
- if 'link-type' not in config:
- config['link-type'] = 'veth'
- if 'veth-peer-name' not in config:
- config['veth-peer-name'] = veth_peer_name[interface]
- def _set_mtu_to_iface_and_upper (ifaces, iface_name, mtu):
- iface_config = ifaces.get (iface_name)
-
-
-
- set_automtu = True
-
-
- if mtu <= 0:
- set_automtu = False
- mtu = iface_config.get ('mtu', MTU['default'])
-
-
-
- if 'mtu' in iface_config:
- set_automtu = False
-
-
-
-
-
-
-
- elif 'automtu' in iface_config and iface_config['automtu'] >= mtu:
- set_automtu = False
-
- if set_automtu:
- iface_config['automtu'] = mtu
-
-
- vlan_raw_device = None
- if 'vlan-raw-device' in iface_config:
- vlan_raw_device = iface_config['vlan-raw-device']
- elif 'vlan' in iface_config and 'vlan-raw-device' in iface_config['vlan']:
- vlan_raw_device = iface_config['vlan']['vlan-raw-device']
- if vlan_raw_device:
- vlan_raw_device_config = ifaces.get (vlan_raw_device, None)
-
-
-
- if vlan_raw_device_config == None:
- vlan_raw_device_config = {}
- ifaces[vlan_raw_device] = vlan_raw_device_config
-
- if 'mtu' in vlan_raw_device_config:
- return
- if 'automtu' in vlan_raw_device_config and vlan_raw_device_config['automtu'] >= mtu:
- return
- vlan_raw_device_config['automtu'] = mtu
- def _generate_batman_interface_config (node_config, ifaces, sites_config):
-
- roles = node_config.get ('roles', [])
- if 'batman' not in roles:
- return
-
- batman_ext = 'batman_ext' in roles or 'bras' in roles
- device_no = node_config.get ('id', -1)
- for site in node_config.get ('sites', []):
- site_no = _get_site_no (sites_config, site)
-
-
- bat_site_if = "bat-%s" % site
- dummy_site_if = "dummy-%s" % site
- bat_site_if_ext = "bat-%s-ext" % site
- dummy_site_if_ext = "dummy-%s-e" % site
- int2ext_site_if = "i2e-%s" % site
- ext2int_site_if = "e2i-%s" % site
- site_ifaces = {
-
- bat_site_if : {
- 'type' : 'batman',
-
- 'batman-ifaces' : [ dummy_site_if ],
- 'batman-ifaces-ignore-regex': '.*_.*',
- 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'bat'),
- },
-
- dummy_site_if : {
- 'link-type' : 'dummy',
- 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'dummy'),
- 'mtu' : MTU['batman_underlay_iface'],
- },
-
- bat_site_if_ext : {
- 'type' : 'batman',
- 'batman-ifaces' : [ dummy_site_if_ext, ext2int_site_if ],
- 'batman-ifaces-ignore-regex': '.*_.*',
- 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'bat-e'),
- 'ext_only' : True,
- },
-
- dummy_site_if_ext : {
- 'link-type' : 'dummy',
- 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'dummy-e'),
- 'ext_only' : True,
- 'mtu' : MTU['batman_underlay_iface'],
- },
-
- int2ext_site_if : {
- 'link-type' : 'veth',
- 'veth-peer-name' : ext2int_site_if,
- 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'int2ext'),
- 'mtu' : MTU['batman_underlay_iface'],
- 'ext_only' : True,
- },
-
- ext2int_site_if : {
- 'link-type' : 'veth',
- 'veth-peer-name' : int2ext_site_if,
- 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'ext2int'),
- 'mtu' : MTU['batman_underlay_iface'],
- 'ext_only' : True,
- },
- }
- for iface, iface_config_tmpl in site_ifaces.items ():
-
-
- if not batman_ext and iface_config_tmpl.get ('ext_only', False):
- continue
-
- if 'ext_only' in iface_config_tmpl:
- del iface_config_tmpl['ext_only']
-
- if iface not in ifaces:
-
- ifaces[iface] = iface_config_tmpl
-
-
-
- if batman_ext and iface == bat_site_if:
- iface_config_tmpl['batman-ifaces'].append (int2ext_site_if)
-
-
-
- else:
- iface_config = ifaces[iface]
-
- if 'hwaddress' in iface_config_tmpl:
- iface_config['hwaddress'] = iface_config_tmpl['hwaddress']
-
- for attr in iface_config_tmpl:
- if attr not in iface_config:
- iface_config[attr] = iface_config_tmpl[attr]
-
- site_bridge = "br-%s" % site
- if site_bridge in ifaces:
- bridge_config = ifaces.get (site_bridge)
- bridge_ports = bridge_config.get ('bridge-ports', None)
-
- if bridge_ports and bat_site_if not in bridge_ports:
- if type (bridge_ports) == list:
- bridge_ports.append (bat_site_if)
- else:
- bridge_config['bridge-ports'] += ' ' + bat_site_if
-
- if not bridge_ports:
- bridge_config['bridge-ports'] = bat_site_if
-
-
- for iface in list (ifaces.keys ()):
- config = ifaces.get (iface)
- iface_type = config.get ('type', 'inet')
- if iface_type not in ['mesh_breakout', 'batman_iface']:
- continue
- site = config.get ('site')
- site_bridge = "br-%s" % site
- batman_site_if = "bat-%s" % site
- if iface_type == 'mesh_breakout':
-
-
-
- if site_bridge in ifaces:
- bridge_config = ifaces.get (site_bridge)
-
-
- bridge_ports = bridge_config.get ('bridge-ports', None)
- if bridge_ports:
- for dev in (batman_site_if, iface):
- if not dev in bridge_ports:
- if type (bridge_ports) == list:
- bridge_ports.append (dev)
- else:
- bridge_config['bridge-ports'] += ' ' + dev
-
-
- else:
- bridge_config['bridge-ports'] = [ iface, batman_site_if ]
-
- else:
- ifaces[site_bridge] = {
- 'bridge-ports' : [ iface, batman_site_if ],
- }
- elif iface_type == 'batman_iface':
- batman_ifaces = ifaces[batman_site_if]['batman-ifaces']
- if iface not in batman_ifaces:
- if type (batman_ifaces) == list:
- batman_ifaces.append (iface)
- else:
- batman_ifaces += ' ' + iface
-
-
- mtu = config.get('mtu', MTU['batman_underlay_iface'])
- _set_mtu_to_iface_and_upper (ifaces, iface, mtu)
- def _generate_vxlan_interface_config (node_config, ifaces, sites_config):
-
- if 'batman' not in node_config.get ('roles', []):
- return
-
- my_sites = node_config.get ('sites', [])
- if len (my_sites) == 0:
- return
-
-
- device_no = node_config.get ('id', -1)
- for iface in list (ifaces.keys ()):
- iface_config = ifaces.get (iface)
- batman_connect_sites = iface_config.get ('batman_connect_sites', [])
- iface_has_prefixes = len (iface_config.get ('prefixes', {})) != 0
-
- if type (batman_connect_sites) == str:
- batman_connect_sites = [ batman_connect_sites ]
-
- if len (batman_connect_sites) == 0:
- continue
-
-
-
-
- underlay_mtu = MTU['vxlan_underlay_iface']
- if not iface_has_prefixes:
- underlay_mtu = MTU['vxlan_underlay_iface_ipv6']
- _set_mtu_to_iface_and_upper (ifaces, iface, underlay_mtu)
-
- if 'all' in batman_connect_sites:
- batman_connect_sites = my_sites
- for site in batman_connect_sites:
-
- if site not in my_sites:
- continue
-
- vx_iface = ("vx_%s_%s" % (re.sub ('vlan', 'v', iface)[-5:], re.sub (r'[_-]', '', site)))[:15]
- site_no = _get_site_no (sites_config, site)
- bat_iface = "bat-%s" % site
-
-
- if bat_iface not in ifaces:
- continue
-
- if vx_iface in ifaces:
- continue
- try:
- iface_id = int (re.sub ('vlan', '', iface))
-
-
-
-
- iface_id_4digit = "%04d" % iface_id
- octet2 = int (iface_id_4digit[0:2])
- octet3 = int (iface_id_4digit[2:4])
- vni = octet2 * 256 * 256 + octet3 * 256 + site_no
- vtep_config = {
- 'vxlan-id' : vni,
- 'vxlan-physdev' : iface,
- }
-
- if iface_has_prefixes:
- vtep_config['vxlan-svcnodeip'] = "225.%s.%s.%s" % (octet2, octet3, site_no)
- else:
- vtep_config['vxlan-remote-group'] = "ff42:%s::%s" % (iface_id, site_no)
- except ValueError as v:
- vtep_config = {
- 'vxlan-config-error' : str (v),
- }
- iface_id = 9999
- mcast_ip = "225.0.0.%s" % site_no
- vni = site_no
-
- ifaces[vx_iface] = {
- 'vxlan' : vtep_config,
- 'hwaddress' : gen_batman_iface_mac (site_no, device_no, iface_id),
- 'mtu' : MTU['batman_underlay_iface'],
- }
- iface_penalty = get_batman_iface_penalty (iface)
- if iface_penalty:
- ifaces[vx_iface]['batman'] = {
- 'batman-hop-penalty' : iface_penalty
- }
-
-
-
- if not 'batman-ifaces' in ifaces[bat_iface]:
- ifaces[bat_iface]['batman-ifaces'] = [ vx_iface ]
- continue
-
-
- batman_ifaces = ifaces[bat_iface]['batman-ifaces']
- if vx_iface not in batman_ifaces:
- if type (batman_ifaces) == list:
- batman_ifaces.append (vx_iface)
- else:
- batman_ifaces += ' ' + vx_iface
- def _generate_vrfs (ifaces):
- for iface in list (ifaces.keys ()):
- iface_config = ifaces.get (iface)
- vrf = iface_config.get ('vrf', None)
- if vrf and vrf not in ifaces:
- conf = vrf_info.get (vrf, {})
- table = conf.get ('table', 1234)
- fwmark = conf.get ('fwmark', None)
- ifaces[vrf] = {
- 'vrf-table' : table,
- }
-
- if fwmark:
- up = []
-
- if type (fwmark) in (str, int):
- fwmark = [ fwmark ]
-
- for mark in fwmark:
- up.append ("ip rule add fwmark %s table %s" % (mark, table))
- up.append ("ip -6 rule add fwmark %s table %s" % (mark, table))
- ifaces[vrf]['up'] = up
- def _generate_ffrl_gre_tunnels (ifaces):
- for iface, iface_config in ifaces.items ():
-
- if iface_config.get ('type', '') != 'GRE_FFRL':
- continue
-
- for attr, val in GRE_FFRL_attrs.items ():
- if not attr in iface_config:
- iface_config[attr] = val
-
- if not 'local' in iface_config and 'tunnel-physdev' in iface_config:
- try:
- physdev_prefixes = [p.split ('/')[0] for p in ifaces[iface_config['tunnel-physdev']]['prefixes'] if '.' in p]
- if len (physdev_prefixes) == 1:
- iface_config['local'] = physdev_prefixes[0]
- except KeyError:
- pass
- def _generate_loopback_ips (ifaces, node_config, node_id):
-
-
-
- if node_config.get ('primary_ips', False):
- return
- v4_ip = "%s/32" % get_primary_ip (node_config, 'v4').ip
- v6_ip = "%s/128" % get_primary_ip (node_config, 'v6').ip
-
- if 'lo' not in ifaces:
- ifaces['lo'] = { 'prefixes' : [] }
-
- if 'prefixes' not in ifaces['lo']:
- ifaces['lo']['prefixes'] = []
- prefixes = ifaces['lo']['prefixes']
- if v4_ip not in prefixes:
- prefixes.append (v4_ip)
- if v6_ip not in prefixes:
- prefixes.append (v6_ip)
- def _update_interface_desc (node_config, sites_config):
-
- if 'batman' not in node_config.get ('roles', []):
- return
- for iface, iface_config in node_config.get ('ifaces', {}).items ():
- if 'desc' in sites_config:
- continue
-
-
- match = re.search (r'^br-([a-z_-]+)$', iface)
- if match and match.group (1) in sites_config:
- try:
- iface_config['desc'] = sites_config[match.group (1)]['name']
- except KeyError:
- pass
- def get_interface_config (node_config, sites_config, node_id = ""):
-
-
-
-
- node_config = deepcopy (node_config)
-
- ifaces = node_config.get ('ifaces', {})
-
-
-
- _generate_batman_interface_config (node_config, ifaces, sites_config)
-
- _generate_vxlan_interface_config (node_config, ifaces, sites_config)
-
-
- for interface in list (ifaces.keys ()):
- config = ifaces.get (interface)
- iface_type = config.get ('type', 'inet')
-
- if config.get ('enabled', True) == False:
- del ifaces[interface]
- continue
-
- if 'pppoe' in config.get ('tags', []):
- del ifaces[interface]
- continue
- if 'batman-ifaces' in config or iface_type.startswith ('batman'):
- _update_batman_config (node_config, interface, sites_config)
- if 'bond-slaves' in config:
- _update_bond_config (config)
-
- if 'bridge-ports' in config or interface.startswith ('br-'):
- _update_bridge_config (config)
- if 'bridge-member' in config:
- _update_bridge_member_config (config)
- if 'vlan-raw-device' in config or 'vlan-id' in config:
- _update_vlan_config (config)
- _set_mtu_to_iface_and_upper (ifaces, interface, 0)
-
- if interface.startswith ('veth_'):
- _update_veth_config (interface, config)
-
- _generate_loopback_ips (ifaces, node_config, node_id)
-
- _generate_vrfs (ifaces)
-
- _generate_ffrl_gre_tunnels (ifaces)
-
-
- for interface, config in ifaces.items ():
-
- if interface != 'lo' and ('mtu' not in config):
-
-
- config['mtu'] = config.get ('automtu', MTU['default'])
- for key in [ 'automtu', 'enabled', 'batman_connect_sites', 'bridge-member', 'has_gateway', 'ospf', 'site', 'type', 'tagged_vlans', 'vlan-mode' ]:
- if key in config:
- config.pop (key)
-
- if 'metric' in config and not 'router' in node_config.get ('roles', []):
- config.pop ('metric')
-
-
-
-
- _update_interface_desc (node_config, sites_config)
- return ifaces
- vlan_vxlan_iface_re = re.compile (r'^vlan(\d+)|^vx_v(\d+)_(\w+)')
- def _iface_sort (iface_a, iface_b):
- a = vlan_vxlan_iface_re.search (iface_a)
- b = vlan_vxlan_iface_re.search (iface_b)
-
- if not a or not b:
- return ffho.cmp (iface_a, iface_b)
-
- vid_a = a.group (1) if a.group (1) else a.group (2)
- vid_b = b.group (1) if b.group (1) else b.group (2)
-
- if (a.group (1) == None) != (b.group (1) == None):
- return ffho.cmp (iface_a, iface_b)
-
-
- if a.group (2) and vid_a == vid_b:
- return ffho.cmp (a.groups (2), b.groups (2))
-
- else:
- return ffho.cmp (int (vid_a), int (vid_b))
- def get_interface_list (ifaces):
- iface_list = []
- for iface in sorted (ifaces.keys (), key = cmp_to_key (_iface_sort)):
- iface_list.append (iface)
- return iface_list
- def gen_bat_hosts (nodes_config, sites_config):
- bat_hosts = {}
- for node_id in sorted (nodes_config.keys ()):
- node_config = nodes_config.get (node_id)
- node_name = node_id.split ('.')[0]
- if 'batman' not in node_config['roles']:
- continue
- ifaces = get_interface_config (node_config, sites_config, node_id)
- for iface in sorted (ifaces):
- iface_config = ifaces.get (iface)
- hwaddress = iface_config.get ('hwaddress', None)
- if hwaddress == None:
- continue
- entry_name = node_name
- match = re.search (r'^dummy-(.+)(-e)?$', iface)
- if match:
- if match.group (2):
- entry_name += "-e"
-
- entry_name += "/%s" % match.group (1)
- else:
- entry_name += "/%s" % re.sub (r'^(vx_.*|i2e|e2i)[_-](.*)$', '\g<1>/\g<2>', iface)
- bat_hosts[hwaddress] = entry_name
- if 'fastd' in node_config.get ('roles', []):
- device_no = node_config.get ('id')
- for site in node_config.get ('sites', []):
- site_no = _get_site_no (sites_config, site)
- for network in ('intergw', 'nodes4', 'nodes6'):
- hwaddress = gen_batman_iface_mac (site_no, device_no, network)
- bat_hosts[hwaddress] = "%s/%s/%s" % (node_name, network, site)
- return bat_hosts
- def get_batman_iface_penalty (iface):
- if iface.startswith ('vlan'):
- vid = int (re.sub ('vlan', '', iface))
- if 1400 <= vid < 1500:
- return default_batman_iface_penalty_by_role.get ('DCI')
- if 2000 <= vid < 2100:
- return default_batman_iface_penalty_by_role.get ('WBBL')
- if 2200 <= vid < 2300:
- return default_batman_iface_penalty_by_role.get ('WBBL_backup')
- if 'intergw' in iface:
- return default_batman_iface_penalty_by_role.get ('VPN_intergw')
- if 'nodes' in iface:
- return default_batman_iface_penalty_by_role.get ('VPN_node')
- return default_batman_iface_penalty_by_role.get ('default', 0)
- def get_ffrl_bgp_config (ifaces, proto):
- _generate_ffrl_gre_tunnels (ifaces)
- sessions = {}
- for iface in sorted (ifaces):
-
- if not iface.startswith ('gre_ffrl_'):
- continue
- iface_config = ifaces.get (iface)
-
- local = None
- neighbor = None
- for prefix in iface_config.get ('prefixes', []):
- if (proto == 'v4' and '.' in prefix) or (proto == 'v6' and ':' in prefix):
- local = prefix.split ('/')[0]
-
- neighbor = str (ipaddress.ip_address (u'%s' % local) - 1)
- break
-
- name = re.sub ('gre_ffrl_', 'ffrl_', iface)
- sessions[name] = {
- 'local' : local,
- 'neighbor' : neighbor,
- 'bgp_local_pref' : iface_config.get ('bgp_local_pref', None),
- }
- return sessions
- def get_node_iface_ips (node_config, iface_name, with_mask = False):
- ips = {
- 'v4' : [],
- 'v6' : [],
- }
- ifaces = node_config.get ('ifaces', {})
- ifaces_names = [ iface_name ]
- if iface_name.startswith ('vrf_'):
-
- ifaces_names = []
- vrf = iface_name
- for iface, iface_config in ifaces.items ():
-
- if iface_config.get ('vrf', None) != vrf:
- continue
-
- if iface.startswith ('veth'):
- continue
- ifaces_names.append (iface)
- try:
- for iface in ifaces_names:
- for prefix in ifaces[iface]['prefixes']:
- ip_ver = 'v6' if ':' in prefix else 'v4'
- if not with_mask:
- prefix = prefix.split ('/')[0]
- ips[ip_ver].append (prefix)
- except KeyError:
- pass
- return ips
- def get_primary_ip (node_config, af):
-
- if 'primary_ips' not in node_config:
- return Prefix ("%s%s" % (loopback_prefix[af], node_config['id']))
- return Prefix (node_config['primary_ips'][af])
- def get_router_id (node_config, node_id):
- return get_primary_ip (node_config, 'v4').ip
- def get_ospf_config (node_config, grains_id):
- ospf_config = {
-
-
-
-
-
- }
- for iface, iface_config in node_config.get ('ifaces', {}).items ():
-
- ospf_on = False
- area = 0
-
- ospf_iface_cfg = {
- 'stub' : True,
- 'cost' : 12345,
-
- }
-
- ospf_iface_cfg_pillar = iface_config.get ('ospf', {})
-
- if ospf_iface_cfg_pillar.get ('ignore', False):
- continue
-
- if not iface_config.get ('prefixes'):
- continue
-
- if iface_config.get ('vrf'):
- continue
-
- if re.search (r'^vlan90\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = True
- ospf_iface_cfg['cost'] = 10
- ospf_iface_cfg['desc'] = "Wireless Local Link (WLL)"
-
- elif re.search (r'^(br-?|br\d+\.|vlan)10\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 100
- ospf_iface_cfg['desc'] = "Wired Gigabit connection"
-
- elif re.search (r'^vlan12\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 10
- ospf_iface_cfg['desc'] = "Wired 10Gb/s connection"
-
- elif re.search (r'^vlan15\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 200
- ospf_iface_cfg['desc'] = "VLL connection"
-
- elif re.search (r'^vlan20\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 1000
- ospf_iface_cfg['desc'] = "WBBL connection"
-
- elif re.search (r'^vlan22\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 1000
- ospf_iface_cfg['desc'] = "WBBL connection"
-
- elif re.search (r'^vlan30\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = True
- ospf_iface_cfg['cost'] = 10
-
- elif re.search (r'^vlan32\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 10
- ospf_iface_cfg['AF'] = 4
- area = 51
-
- elif re.search (r'^vlan39\d\d$', iface):
- ospf_on = True
- ospf_iface_cfg['stub'] = True
- ospf_iface_cfg['cost'] = 10
-
- elif iface.startswith ('ovpn-'):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 10000
-
- if iface.startswith ('ovpn-cr') and grains_id.startswith ('cr'):
- ospf_iface_cfg['cost'] = 5000
-
- elif iface.startswith ('ovpn-er-'):
- ospf_iface_cfg['type'] = 'broadcast'
-
- elif iface.startswith ('wg-'):
- ospf_on = True
- ospf_iface_cfg['stub'] = False
- ospf_iface_cfg['cost'] = 10000
-
- if iface.startswith ('wg-cr') and grains_id.startswith ('cr'):
- ospf_iface_cfg['cost'] = 5000
-
- elif 'ospf' in iface_config:
- ospf_on = True
-
-
- if not ospf_on:
- continue
-
- for attr, val in ospf_iface_cfg_pillar.items ():
- ospf_iface_cfg[attr] = val
-
- if area not in ospf_config:
- ospf_config[area] = {}
- ospf_config[area][iface] = ospf_iface_cfg
- return ospf_config
- def get_te_prefixes (te_node_config, grains_id, proto):
- te_config = {}
- for prefix, prefix_config in te_node_config.get ('prefixes', {}).items ():
- prefix_proto = 'v6' if ':' in prefix else 'v4'
-
-
- if grains_id in prefix_config.get ('nodes', []) and prefix_proto == proto:
- te_config[prefix] = prefix_config
- return te_config
- def cidr_to_dotted_mask (prefix):
- return str (ipaddress.ip_network (prefix, strict = False).netmask)
- def is_subprefix (prefix, subprefix):
- p = ipaddress.ip_network (prefix, strict = False)
- s = ipaddress.ip_network (subprefix, strict = False)
- return s.subnet_of (p)
- def get_network_address (prefix, with_prefixlen = False):
- net_h = ipaddress.ip_network (u'%s' % prefix, strict = False)
- network = str (net_h.network_address)
- if with_prefixlen:
- network += "/%s" % net_h.prefixlen
- return network
|