finished converting quagga services to config services

This commit is contained in:
Blake Harnden 2020-01-23 21:08:40 -08:00
parent fcc445bb72
commit b9cbbf5709
2 changed files with 249 additions and 2 deletions

View file

@ -1,12 +1,15 @@
import abc import abc
import logging
from typing import Any, Dict from typing import Any, Dict
import netaddr import netaddr
from core import constants from core import constants
from core.configservice.base import ConfigService, ConfigServiceMode from core.configservice.base import ConfigService, ConfigServiceMode
from core.emane.nodes import EmaneNet
from core.nodes.base import CoreNodeBase from core.nodes.base import CoreNodeBase
from core.nodes.interface import CoreInterface from core.nodes.interface import CoreInterface
from core.nodes.network import WlanNode
GROUP = "Quagga" GROUP = "Quagga"
@ -27,6 +30,20 @@ def has_mtu_mismatch(ifc: CoreInterface) -> bool:
return False return False
def get_min_mtu(ifc):
"""
Helper to discover the minimum MTU of interfaces linked with the
given interface.
"""
mtu = ifc.mtu
if not ifc.net:
return mtu
for i in ifc.net.netifs():
if i.mtu < mtu:
mtu = i.mtu
return mtu
def get_router_id(node: CoreNodeBase) -> str: def get_router_id(node: CoreNodeBase) -> str:
""" """
Helper to return the first IPv4 address of a node as its router ID. Helper to return the first IPv4 address of a node as its router ID.
@ -168,3 +185,231 @@ class Ospfv2(QuaggaService, ConfigService):
! !
""" """
return self.render_text(text, data) return self.render_text(text, data)
class Ospfv3(QuaggaService, ConfigService):
"""
The OSPFv3 service provides IPv6 routing for wired networks. It does
not build its own configuration file but has hooks for adding to the
unified Quagga.conf file.
"""
name = "OSPFv3"
shutdown = ("killall ospf6d",)
validate = ("pidof ospf6d",)
ipv4_routing = True
ipv6_routing = True
def quagga_interface_config(self, ifc: CoreInterface) -> str:
mtu = get_min_mtu(ifc)
if mtu < ifc.mtu:
return f"ipv6 ospf6 ifmtu {mtu}"
else:
return ""
def quagga_config(self) -> str:
router_id = get_router_id(self.node)
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
data = dict(router_id=router_id, ifnames=ifnames)
text = """
router ospf6
instance-id 65
router-id ${router_id}
% for ifname in ifnames:
interface ${ifname} area 0.0.0.0
% endfor
!
"""
return self.render_text(text, data)
class Ospfv3mdr(Ospfv3):
"""
The OSPFv3 MANET Designated Router (MDR) service provides IPv6
routing for wireless networks. It does not build its own
configuration file but has hooks for adding to the
unified Quagga.conf file.
"""
name = "OSPFv3MDR"
def data(self) -> Dict[str, Any]:
for ifc in self.node.netifs():
is_wireless = isinstance(ifc.net, (WlanNode, EmaneNet))
logging.info("MDR wireless: %s", is_wireless)
return dict()
def quagga_interface_config(self, ifc: CoreInterface) -> str:
config = super().quagga_interface_config(ifc)
if isinstance(ifc.net, (WlanNode, EmaneNet)):
config = self.clean_text(
f"""
{config}
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 6
ipv6 ospf6 retransmit-interval 5
ipv6 ospf6 network manet-designated-router
ipv6 ospf6 twohoprefresh 3
ipv6 ospf6 adjacencyconnectivity uniconnected
ipv6 ospf6 lsafullness mincostlsa
"""
)
return config
class Bgp(QuaggaService, ConfigService):
"""
The BGP service provides interdomain routing.
Peers must be manually configured, with a full mesh for those
having the same AS number.
"""
name = "BGP"
shutdown = ["killall bgpd"]
validate = ["pidof bgpd"]
ipv4_routing = True
ipv6_routing = True
def quagga_interface_config(self, ifc: CoreInterface) -> str:
router_id = get_router_id(self.node)
text = f"""
! BGP configuration
! You should configure the AS number below
! along with this router's peers.
router bgp {self.node.id}
bgp router-id {router_id}
redistribute connected
!neighbor 1.2.3.4 remote-as 555
!
"""
return self.clean_text(text)
class Rip(QuaggaService, ConfigService):
"""
The RIP service provides IPv4 routing for wired networks.
"""
name = "RIP"
shutdown = ["killall ripd"]
validate = ["pidof ripd"]
ipv4_routing = True
def quagga_config(self) -> str:
text = """
router rip
redistribute static
redistribute connected
redistribute ospf
network 0.0.0.0/0
!
"""
return self.clean_text(text)
class Ripng(QuaggaService, ConfigService):
"""
The RIP NG service provides IPv6 routing for wired networks.
"""
name = "RIPNG"
shutdown = ["killall ripngd"]
validate = ["pidof ripngd"]
ipv6_routing = True
def quagga_config(self) -> str:
text = """
router ripng
redistribute static
redistribute connected
redistribute ospf6
network ::/0
!
"""
return self.clean_text(text)
class Babel(QuaggaService, ConfigService):
"""
The Babel service provides a loop-avoiding distance-vector routing
protocol for IPv6 and IPv4 with fast convergence properties.
"""
name = "Babel"
shutdown = ["killall babeld"]
validate = ["pidof babeld"]
ipv6_routing = True
def quagga_config(self) -> str:
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
text = """
router babel
% for ifname in ifnames:
network ${ifname}
% endfor
redistribute static
redistribute connected
!
"""
data = dict(ifnames=ifnames)
return self.render_text(text, data)
def quagga_interface_config(self, ifc: CoreInterface) -> str:
if isinstance(ifc.net, (WlanNode, EmaneNet)):
text = """
babel wireless
no babel split-horizon
"""
else:
text = """
babel wired
babel split-horizon
"""
return self.clean_text(text)
class Xpimd(QuaggaService, ConfigService):
"""
PIM multicast routing based on XORP.
"""
name = "Xpimd"
shutdown = ["killall xpimd"]
validate = ["pidof xpimd"]
ipv4_routing = True
def quagga_config(self) -> str:
ifname = "eth0"
for ifc in self.node.netifs():
if ifc.name != "lo":
ifname = ifc.name
break
text = f"""
router mfea
!
router igmp
!
router pim
!ip pim rp-address 10.0.0.1
ip pim bsr-candidate {ifname}
ip pim rp-candidate {ifname}
!ip pim spt-threshold interval 10 bytes 80000
!
"""
return self.clean_text(text)
def quagga_interface_config(self, ifc: CoreInterface) -> str:
text = """
ip mfea
ip pim
"""
return self.clean_text(text)

View file

@ -10,9 +10,11 @@ interface ${ifc.name}
ipv6 address ${addr} ipv6 address ${addr}
% endfor % endfor
% endif % endif
% if is_control: % if not is_control:
% for service in services: % for service in services:
${service.quagga_interface_config(ifc)} % for line in service.quagga_interface_config(ifc).split("\n"):
${line}
% endfor
% endfor % endfor
% endif % endif
! !