ffho_net.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. #!/usr/bin/python
  2. import re
  3. mac_prefix = "f2"
  4. vrf_table_map = {
  5. 'vrf_external' : 1023,
  6. }
  7. sites = None
  8. def _get_site_no (sites_config, site_name):
  9. global sites
  10. if sites == None:
  11. sites = {}
  12. for site in sites_config:
  13. if site.startswith ("_"):
  14. continue
  15. sites[site] = sites_config[site].get ("site_no", -2)
  16. return sites.get (site_name, -1)
  17. #
  18. # Generate a MAC address after the format f2:dd:dd:ss:nn:nn where
  19. # dd:dd is the hexadecimal reprensentation of the nodes device_id
  20. # ff:ff representing the gluon nodes
  21. #
  22. # ss is the hexadecimal reprensentation of the site_id the interface is connected to
  23. #
  24. # nn:nn is the decimal representation of the network the interface is connected to, with
  25. # 00:00 being the dummy interface
  26. # 00:0f being the VEth internal side interface
  27. # 00:e0 being an external instance dummy interface
  28. # 00:e1 being an inter-gw-vpn interface
  29. # 00:e4 being an nodes fastd tunnel interface of IPv4 transport
  30. # 00:e6 being an nodes fastd tunnel interface of IPv6 transport
  31. # 00:ef being an extenral instance VEth interface side
  32. # 02:xx being a connection to local Vlan 2xx
  33. # 1b:24 being the ibss 2.4GHz bssid
  34. # 1b:05 being the ibss 5GHz bssid
  35. # ff:ff being the gluon next-node interface
  36. # xx:xx being a VXLAN tunnel for site ss, with xx being a the underlay VLAN ID (1xyz, 2xyz)
  37. def gen_batman_iface_mac (site_no, device_no, network):
  38. net_type_map = {
  39. 'dummy' : "00:00",
  40. 'int2ext' : "00:0f",
  41. 'dummy-e' : "00:e0",
  42. 'intergw' : "00:e1",
  43. 'nodes4' : "00:e4",
  44. 'nodes6' : "00:e6",
  45. 'ext2int' : "00:ef",
  46. }
  47. # Well-known network type?
  48. if network in net_type_map:
  49. last = net_type_map[network]
  50. elif type (network) == int:
  51. last = re.sub (r'(\d{2})(\d{2})', '\g<1>:\g<2>', "%04d" % network)
  52. else:
  53. last = "ee:ee"
  54. # Convert device_no to hex, format number to 4 digits with leading zeros and : betwwen 2nd and 3rd digit
  55. device_no_hex = re.sub (r'([0-9a-fA-F]{2})([0-9a-fA-F]{2})', '\g<1>:\g<2>', "%04x" % int (device_no))
  56. # Format site_no to two digit number with leading zero
  57. site_no_hex = "%02d" % int (site_no)
  58. return "%s:%s:%s:%s" % (mac_prefix, device_no_hex, site_no_hex, last)
  59. #
  60. # Default parameters added to any given bonding/bridge interface,
  61. # if not specified at the interface configuration.
  62. default_bond_config = {
  63. 'bond-mode': '802.3ad',
  64. 'bond-min-links': '1',
  65. 'bond-xmit-hash-policy': 'layer3+4'
  66. }
  67. default_bridge_config = {
  68. 'bridge-fd' : '0',
  69. 'bridge-stp' : 'no'
  70. }
  71. #
  72. # Hop penalty to set if none is explicitly specified
  73. # Check if one of these roles is configured for any given node, use first match.
  74. default_hop_penalty_by_role = {
  75. 'bbr' : 5,
  76. 'bras' : 50,
  77. 'batman_gw' : 50,
  78. }
  79. batman_role_evaluation_order = [ 'bbr', 'batman_gw', 'bras' ]
  80. # Gather B.A.T.M.A.N. related config options for real batman devices (e.g. bat0)
  81. # as well as for batman member interfaces (e.g. eth0.100, fastd ifaces etc.)
  82. def _update_batman_config (node_config, iface, sites_config):
  83. try:
  84. node_batman_hop_penalty = int (node_config['batman']['hop-penalty'])
  85. except KeyError,ValueError:
  86. node_batman_hop_penalty = None
  87. iface_config = node_config['ifaces'][iface]
  88. iface_type = iface_config.get ('type', 'inet')
  89. batman_config = {}
  90. for item, value in iface_config.items ():
  91. if item.startswith ('batman-'):
  92. batman_config[item] = value
  93. iface_config.pop (item)
  94. # B.A.T.M.A.N. device (e.g. bat0)
  95. if iface_type == 'batman':
  96. if 'batman-hop-penalty' not in batman_config:
  97. # If there's a hop penalty set for the node, but not for the interface
  98. # apply the nodes hop penalty
  99. if node_batman_hop_penalty:
  100. batman_config['batman-hop-penalty'] = node_batman_hop_penalty
  101. # If there's no hop penalty set for the node, use a default hop penalty
  102. # for the roles the node might have, if any
  103. else:
  104. node_roles = node_config.get ('roles', [])
  105. for role in batman_role_evaluation_order:
  106. if role in node_roles:
  107. batman_config['batman-hop-penalty'] = default_hop_penalty_by_role[role]
  108. # If batman ifaces were specified as a list - which they should -
  109. # generate a sorted list of interface names as string representation
  110. if 'batman-ifaces' in batman_config and type (batman_config['batman-ifaces']) == list:
  111. batman_iface_str = " ".join (sorted (batman_config['batman-ifaces']))
  112. batman_config['batman-ifaces'] = batman_iface_str
  113. # B.A.T.M.A.N. member interface (e.g. eth.100, fastd ifaces, etc.)
  114. elif iface_type == 'batman_iface':
  115. # Generate unique MAC address for every batman iface, as B.A.T.M.A.N.
  116. # will get puzzled with multiple interfaces having the same MAC and
  117. # do nasty things.
  118. site = iface_config.get ('site')
  119. site_no = _get_site_no (sites_config, site)
  120. device_no = node_config.get ('id')
  121. network = 1234
  122. # Generate a unique BATMAN-MAC for this interfaces
  123. match = re.search (r'^vlan(\d+)', iface)
  124. if match:
  125. network = int (match.group (1))
  126. iface_config['hwaddress'] = gen_batman_iface_mac (site_no, device_no, network)
  127. iface_config['batman'] = batman_config
  128. # Mangle bond specific config items with default values and store them in
  129. # separate sub-dict for easier access and configuration.
  130. def _update_bond_config (config):
  131. bond_config = default_bond_config.copy ()
  132. for item, value in config.items ():
  133. if item.startswith ('bond-'):
  134. bond_config[item] = value
  135. config.pop (item)
  136. if bond_config['bond-mode'] not in ['2', 'balance-xor', '4', '802.3ad']:
  137. bond_config.pop ('bond-xmit-hash-policy')
  138. config['bond'] = bond_config
  139. # Mangle bridge specific config items with default values and store them in
  140. # separate sub-dict for easier access and configuration.
  141. def _update_bridge_config (config):
  142. bridge_config = default_bridge_config.copy ()
  143. for item, value in config.items ():
  144. if item.startswith ('bridge-'):
  145. bridge_config[item] = value
  146. config.pop (item)
  147. # Fix and salt mangled string interpretation back to real string.
  148. if type (value) == bool:
  149. bridge_config[item] = "yes" if value else "no"
  150. # If bridge ports were specified as a list - which they should -
  151. # generate a sorted list of interface names as string representation
  152. if 'bridge-ports' in bridge_config and type (bridge_config['bridge-ports']) == list:
  153. bridge_ports_str = " ".join (sorted (bridge_config['bridge-ports']))
  154. bridge_config['bridge-ports'] = bridge_ports_str
  155. config['bridge'] = bridge_config
  156. # Move vlan specific config items into a sub-dict for easier access and pretty-printing
  157. # in the configuration file
  158. def _update_vlan_config (config):
  159. vlan_config = {}
  160. for item, value in config.items ():
  161. if item.startswith ('vlan-'):
  162. vlan_config[item] = value
  163. config.pop (item)
  164. config['vlan'] = vlan_config
  165. # Generate configuration entries for any batman related interfaces not
  166. # configured explicitly, but asked for implicitly by role batman and a
  167. # (list of) site(s) specified in the node config.
  168. def _generate_batman_interface_config (node_config, ifaces, sites_config):
  169. # No role 'batman', nothing to do
  170. roles = node_config.get ('roles', [])
  171. if 'batman' not in roles:
  172. return
  173. # Should there be a 2nd external BATMAN instance?
  174. batman_ext = 'batman_ext' in roles or 'bras' in roles
  175. device_no = node_config.get ('id', -1)
  176. for site in node_config.get ('sites', []):
  177. site_no = _get_site_no (sites_config, site)
  178. # Predefine interface names for regular/external BATMAN instance
  179. # and possible VEth link pair for connecting both instances.
  180. bat_site_if = "bat-%s" % site
  181. dummy_site_if = "dummy-%s" % site
  182. bat_site_if_ext = "bat-%s-ext" % site
  183. dummy_site_if_ext = "dummy-%s-e" % site
  184. int2ext_site_if = "i2e-%s" % site
  185. ext2int_site_if = "e2i-%s" % site
  186. site_ifaces = {
  187. # Regular BATMAN interface, always present
  188. bat_site_if : {
  189. 'type' : 'batman',
  190. # int2ext_site_if will be added automagically if requred
  191. 'batman-ifaces' : [ dummy_site_if ],
  192. 'batman-ifaces-ignore-regex': '.*_.*',
  193. },
  194. # Dummy interface always present in regular BATMAN instance
  195. dummy_site_if : {
  196. 'link-type' : 'dummy',
  197. 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'dummy'),
  198. },
  199. # Optional 2nd "external" BATMAN instance
  200. bat_site_if_ext : {
  201. 'type' : 'batman',
  202. 'batman-ifaces' : [ dummy_site_if_ext, ext2int_site_if ],
  203. 'batman-ifaces-ignore-regex': '.*_.*',
  204. 'ext_only' : True,
  205. },
  206. # Optional dummy interface always present in 2nd "external" BATMAN instance
  207. dummy_site_if_ext : {
  208. 'link-type' : 'dummy',
  209. 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'dummy-e'),
  210. 'ext_only' : True,
  211. },
  212. # Optional VEth interface pair - internal side
  213. int2ext_site_if : {
  214. 'link-type' : 'veth',
  215. 'veth-peer' : ext2int_site_if,
  216. 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'int2ext'),
  217. 'ext_only' : True,
  218. },
  219. # Optional VEth interface pair - "external" side
  220. ext2int_site_if : {
  221. 'hwaddress' : gen_batman_iface_mac (site_no, device_no, 'ext2int'),
  222. 'ext_only' : True,
  223. },
  224. }
  225. for iface, iface_config_tmpl in site_ifaces.items ():
  226. # Ignore any interface only relevant when role batman_ext is set
  227. # but it isn't
  228. if not batman_ext and iface_config_tmpl.get ('ext_only', False):
  229. continue
  230. # Remove ext_only key so we don't leak it into ifaces dict
  231. if 'ext_only' in iface_config_tmpl:
  232. del iface_config_tmpl['ext_only']
  233. # If there is no trace of the desired iface config yet...
  234. if iface not in ifaces:
  235. # ... just place our template there.
  236. ifaces[iface] = iface_config_tmpl
  237. # If there should be an 2nd external BATMAN instance make sure
  238. # the internal side of the VEth iface pair is connected to the
  239. # internal BATMAN instance.
  240. if batman_ext and iface == bat_site_if:
  241. iface_config_tmpl['batman-ifaces'].append (int2ext_site_if)
  242. # If there already is an interface configuration try to enhance it with
  243. # meaningful values from our template and force correct hwaddress to be
  244. # used.
  245. else:
  246. iface_config = ifaces[iface]
  247. # Force hwaddress to be what we expect.
  248. if 'hwaddress' in iface_config_tmpl:
  249. ifaces_config['hwaddress'] = iface_config_tmpl['hwaddress']
  250. # Copy every attribute of the config template missing in iface config
  251. for attr in iface_config_tmpl:
  252. if attr not in iface_config:
  253. iface_config[attr] = iface_config_tmpl[attr]
  254. # Make sure there is a bridge present for every site where a mesh_breakout
  255. # interface should be configured.
  256. for iface, config in ifaces.items ():
  257. iface_type = config.get ('type', 'inet')
  258. if iface_type not in ['mesh_breakout', 'batman_iface']:
  259. continue
  260. site = config.get ('site')
  261. site_bridge = "br-%s" % site
  262. batman_site_if = "bat-%s" % site
  263. if iface_type == 'mesh_breakout':
  264. # If the bridge has already been defined (with an IP maybe) make
  265. # sure that the corresbonding batman device is part of the bridge-
  266. # ports.
  267. if site_bridge in ifaces:
  268. bridge_config = ifaces.get (site_bridge)
  269. # If there already is/are (a) bridge-port(s) defined, add
  270. # the batman and the breakout interfaces if not present...
  271. bridge_ports = bridge_config.get ('bridge-ports', None)
  272. if bridge_ports:
  273. for dev in (batman_site_if, iface):
  274. if not dev in bridge_ports:
  275. if type (bridge_ports) == list:
  276. bridge_ports.append (dev)
  277. else:
  278. bridge_config['bridge-ports'] += ' ' + dev
  279. # ...if there is no bridge-port defined yet, just used
  280. # the batman and breakout iface.
  281. else:
  282. bridge_config['bridge-ports'] = [ iface, batman_site_if ]
  283. # If the bridge isn't present alltogether, add it.
  284. else:
  285. ifaces[site_bridge] = {
  286. 'bridge-ports' : [ iface, batman_site_if ],
  287. }
  288. elif iface_type == 'batman_iface':
  289. batman_ifaces = ifaces[bat_site_if]['batman-ifaces']
  290. if iface not in batman_ifaces:
  291. if type (batman_ifaces) == list:
  292. batman_ifaces.append (iface)
  293. else:
  294. batman_ifaces += ' ' + iface
  295. ## Generate VXLAN tunnels for every configured batman peer for every site
  296. ## configured on this and the peer node.
  297. #def _generate_vxlan_interface_config_complex (node_config, ifaces, node_id, nodes_config):
  298. # # No role 'batman', nothing to do
  299. # if 'batman' not in node_config.get ('roles', []):
  300. # return
  301. #
  302. # # No batman peers configred, nothing to do
  303. # try:
  304. # peers = node_config['batman']['peers']
  305. # if type (peers) != list:
  306. # return
  307. # except KeyError:
  308. # return
  309. #
  310. # # Sites configured on this node. Nothing to do, if none.
  311. # my_sites = node_config.get ('sites', [])
  312. # if len (my_sites) == 0:
  313. # return
  314. #
  315. # device_no = node_config.get ('id', -1)
  316. #
  317. # # ...
  318. # for peer in peers:
  319. # try:
  320. # # Try to get node config of peer
  321. # peer_config = nodes_config.get (peer)
  322. #
  323. # # Not a batman node?
  324. # if not 'batman' in peer_config['roles']:
  325. # continue
  326. #
  327. # # Verify we are in peers list of peer
  328. # peers_of_peer = peer_config['batman']['peers']
  329. # if type (peers_of_peer) != list:
  330. # continue
  331. # if node_id not in peers_of_peer:
  332. # continue
  333. #
  334. # # Get sites configured on peers
  335. # sites_of_peer = peer_config.get ('sites')
  336. # except KeyError:
  337. # continue
  338. #
  339. # for site in my_sites:
  340. # if site not in sites_of_peer:
  341. # continue
  342. #
  343. # # Build tunnel here
  344. def _generate_vxlan_interface_config (node_config, ifaces, sites_config):
  345. # No role 'batman', nothing to do
  346. if 'batman' not in node_config.get ('roles', []):
  347. return
  348. # Sites configured on this node. Nothing to do, if none.
  349. my_sites = node_config.get ('sites', [])
  350. if len (my_sites) == 0:
  351. return
  352. # As we're still here we can now safely assume that a B.A.T.M.A.N.
  353. # device has been configured for every site specified in sites list.
  354. device_no = node_config.get ('id', -1)
  355. for iface, iface_config in ifaces.items ():
  356. batman_connect_sites = iface_config.get ('batman_connect_sites', [])
  357. # If we got a string, convert it to a list with a single element
  358. if type (batman_connect_sites) == str:
  359. batman_connect_sites = [ batman_connect_sites ]
  360. # If the string 'all' is part of the list, blindly use all sites configured for this node
  361. if 'all' in batman_connect_sites:
  362. batman_connect_sites = my_sites
  363. for site in batman_connect_sites:
  364. # Silenty ignore sites not configured on this node
  365. if site not in my_sites:
  366. continue
  367. # iface_name := vx_<last 5 chars of underlay iface>_<site> stripped to 15 chars
  368. vx_iface = "vx_%s_%s" % (re.sub ('vlan', 'v', iface)[-5:], site)[:15]
  369. site_no = _get_site_no (sites_config, site)
  370. vni = 100 + site_no
  371. bat_iface = "bat-%s" % site
  372. try:
  373. iface_id = int (re.sub ('vlan', '', iface))
  374. # Gather interface specific mcast address.
  375. # The address is derived from the vlan-id of the underlying interface,
  376. # assuming that it in fact is a vlan interface.
  377. # Mangle the vlan-id into two 2 digit values, eliminating any leading zeros.
  378. iface_id_4digit = "%04d" % iface_id
  379. octet2 = int (iface_id_4digit[0:2])
  380. octet3 = int (iface_id_4digit[2:4])
  381. mcast_ip = "225.%s.%s.%s" % (octet2, octet3, site_no)
  382. vni = octet2 * 256 * 256 + octet3 * 256 + site_no
  383. except ValueError:
  384. iface_id = 9999
  385. mcast_ip = "225.0.0.%s" % site_no
  386. vni = site_no
  387. # bail out if VXLAN tunnel already configured
  388. if vx_iface in ifaces:
  389. continue
  390. # If there's no batman interface for this site, there's no point
  391. # in setting up a VXLAN interfaces
  392. if bat_iface not in ifaces:
  393. continue
  394. # Add the VXLAN interface
  395. ifaces[vx_iface] = {
  396. 'vxlan' : {
  397. 'vxlan-id' : vni,
  398. 'vxlan-svcnodeip' : mcast_ip,
  399. 'vxlan-physdev' : iface,
  400. },
  401. 'hwaddress' : gen_batman_iface_mac (site_no, device_no, iface_id),
  402. }
  403. # If the batman interface for this site doesn't have any interfaces
  404. # set up - which basicly cannot happen - add this VXLAN tunnel as
  405. # the first in the list.
  406. if not 'batman-ifaces' in ifaces[bat_iface]:
  407. ifaces[bat_iface]['batman-ifaces'] = [ vx_iface ]
  408. continue
  409. # In the hope there already are interfaces for batman set up already
  410. # add this VXLAN tunnel to the list
  411. batman_ifaces = ifaces[bat_iface]['batman-ifaces']
  412. if vx_iface not in batman_ifaces:
  413. if type (batman_ifaces) == list:
  414. batman_ifaces.append (vx_iface)
  415. else:
  416. batman_ifaces += ' ' + vx_iface
  417. def _generate_vrfs (ifaces):
  418. for iface, iface_config in ifaces.items ():
  419. vrf = iface_config.get ('vrf', None)
  420. if vrf and vrf not in ifaces:
  421. ifaces[vrf] = {
  422. 'vrf-table' : vrf_table_map.get (vrf, 1234)
  423. }
  424. GRE_FFRL_attrs = {
  425. 'mode' : 'gre',
  426. 'method' : 'tunnel',
  427. 'mtu' : '1400',
  428. 'ttl' : '64',
  429. }
  430. def _generate_ffrl_gre_tunnels (ifaces):
  431. for iface, iface_config in ifaces.items ():
  432. # We only care for GRE_FFRL type interfaces
  433. if iface_config.get ('type', '') != 'GRE_FFRL':
  434. continue
  435. # Copy default values to interface config
  436. for attr, val in GRE_FFRL_attrs.items ():
  437. if not attr in iface_config:
  438. iface_config[attr] = val
  439. # Guesstimate local IPv4 tunnel endpoint address from tunnel-physdev
  440. if not 'local' in iface_config and 'tunnel-physdev' in iface_config:
  441. try:
  442. physdev_prefixes = [p.split ('/')[0] for p in ifaces[iface_config['tunnel-physdev']]['prefixes'] if '.' in p]
  443. if len (physdev_prefixes) == 1:
  444. iface_config['local'] = physdev_prefixes[0]
  445. except KeyError:
  446. pass
  447. def get_interface_config (node_config, sites_config):
  448. # Get config of this node and dict of all configured ifaces
  449. ifaces = node_config.get ('ifaces', {})
  450. # Generate configuration entries for any batman related interfaces not
  451. # configured explicitly, but asked for implicitly by role <batman> and
  452. # a (list of) site(s) specified in the node config.
  453. _generate_batman_interface_config (node_config, ifaces, sites_config)
  454. # Generate VXLAN tunnels for every interfaces specifying 'batman_connect_sites'
  455. _generate_vxlan_interface_config (node_config, ifaces, sites_config)
  456. # Enhance ifaces configuration with some meaningful defaults for
  457. # bonding, bridge and vlan interfaces, MAC address for batman ifaces, etc.
  458. for interface, config in ifaces.items ():
  459. iface_type = config.get ('type', 'inet')
  460. if 'batman-ifaces' in config or iface_type.startswith ('batman'):
  461. _update_batman_config (node_config, interface, sites_config)
  462. if 'bond-slaves' in config:
  463. _update_bond_config (config)
  464. # FIXME: This maybe will not match on bridges without any member ports configured!
  465. if 'bridge-ports' in config or interface.startswith ('br-'):
  466. _update_bridge_config (config)
  467. if 'vlan-raw-device' in config or 'vlan-id' in config:
  468. _update_vlan_config (config)
  469. # Auto generated VRF devices for any VRF found in ifaces and not already configured.
  470. _generate_vrfs (ifaces)
  471. # Pimp GRE_FFRL type inteface configuration with default values
  472. _generate_ffrl_gre_tunnels (ifaces)
  473. # Drop any config parameters used in node interface configuration not
  474. # relevant anymore for config file generation.
  475. for interface, config in ifaces.items ():
  476. for key in [ 'batman_connect_sites', 'ospf', 'site', 'type' ]:
  477. if key in config:
  478. config.pop (key)
  479. # This leaves 'auto', 'prefixes' and 'desc' as keys which should not be directly
  480. # printed into the remaining configuration. These are handled within the jinja
  481. # interface template.
  482. return ifaces
  483. # Generate entries for /etc/bat-hosts for every batman interface we will configure on any node.
  484. # For readability purposes superflous/redundant information is being stripped/supressed.
  485. # As these names will only show up in batctl calls with a specific site, site_names in interfaces
  486. # are stripped. Dummy interfaces are stripped as well.
  487. def gen_bat_hosts (nodes_config, sites_config):
  488. bat_hosts = {}
  489. for node_id in sorted (nodes_config.keys ()):
  490. node_config = nodes_config.get (node_id)
  491. node_name = node_id.split ('.')[0]
  492. ifaces = get_interface_config (node_config, sites_config)
  493. for iface in sorted (ifaces):
  494. iface_config = ifaces.get (iface)
  495. hwaddress = iface_config.get ('hwaddress', None)
  496. if hwaddress == None:
  497. continue
  498. entry_name = node_name
  499. match = re.search (r'^dummy-([^-]+)(-e)?$', iface)
  500. if match and match.group (2):
  501. entry_name += "-e"
  502. else:
  503. entry_name += "/%s" % re.sub (r'^(vx_.*|gw2e|e2gw)_(.*)$', '\g<1>', iface)
  504. bat_hosts[hwaddress] = entry_name
  505. if 'fastd' in node_config.get ('roles', []):
  506. device_no = node_config.get ('id')
  507. for site in node_config.get ('sites', []):
  508. site_no = _get_site_no (sites_config, site)
  509. for network in ('intergw', 'nodes4', 'nodes6'):
  510. hwaddress = gen_batman_iface_mac (site_no, device_no, network)
  511. bat_hosts[hwaddress] = "%s/%s" % (node_name, network)
  512. return bat_hosts
  513. # Generate eBGP session parameters for FFRL Transit from nodes pillar information.
  514. def get_ffrl_bgp_config (ifaces, proto):
  515. from ipcalc import IP
  516. _generate_ffrl_gre_tunnels (ifaces)
  517. sessions = {}
  518. for iface in sorted (ifaces):
  519. # We only care for GRE tunnels to the FFRL Backbone
  520. if not iface.startswith ('gre_ffrl_'):
  521. continue
  522. iface_config = ifaces.get (iface)
  523. # Search for IPv4/IPv6 prefix as defined by proto parameter
  524. local = None
  525. neighbor = None
  526. for prefix in iface_config.get ('prefixes', []):
  527. if (proto == 'v4' and '.' in prefix) or (proto == 'v6' and ':' in prefix):
  528. local = prefix.split ('/')[0]
  529. # Calculate neighbor IP as <local IP> - 1
  530. if proto == 'v4':
  531. neighbor = str (IP (int (IP (local)) - 1, version = 4))
  532. else:
  533. neighbor = str (IP (int (IP (local)) - 1, version = 6))
  534. break
  535. # Strip gre_ prefix iface name and use it as identifier for the eBGP session.
  536. name = re.sub ('gre_ffrl_', 'ffrl_', iface)
  537. sessions[name] = {
  538. 'local' : local,
  539. 'neighbor' : neighbor,
  540. 'bgp_local_pref' : iface_config.get ('bgp_local_pref', None),
  541. }
  542. return sessions