small update to quagga config services, converted frr services to config services
This commit is contained in:
parent
b9cbbf5709
commit
531b55e1e7
7 changed files with 580 additions and 0 deletions
0
daemon/core/configservices/frrservices/__init__.py
Normal file
0
daemon/core/configservices/frrservices/__init__.py
Normal file
391
daemon/core/configservices/frrservices/services.py
Normal file
391
daemon/core/configservices/frrservices/services.py
Normal file
|
@ -0,0 +1,391 @@
|
||||||
|
import abc
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
|
||||||
|
from core import constants
|
||||||
|
from core.configservice.base import ConfigService, ConfigServiceMode
|
||||||
|
from core.emane.nodes import EmaneNet
|
||||||
|
from core.nodes.base import CoreNodeBase
|
||||||
|
from core.nodes.interface import CoreInterface
|
||||||
|
from core.nodes.network import WlanNode
|
||||||
|
|
||||||
|
GROUP = "FRR"
|
||||||
|
|
||||||
|
|
||||||
|
def has_mtu_mismatch(ifc: CoreInterface) -> bool:
|
||||||
|
"""
|
||||||
|
Helper to detect MTU mismatch and add the appropriate FRR
|
||||||
|
mtu-ignore command. This is needed when e.g. a node is linked via a
|
||||||
|
GreTap device.
|
||||||
|
"""
|
||||||
|
if ifc.mtu != 1500:
|
||||||
|
return True
|
||||||
|
if not ifc.net:
|
||||||
|
return False
|
||||||
|
for i in ifc.net.netifs():
|
||||||
|
if i.mtu != ifc.mtu:
|
||||||
|
return True
|
||||||
|
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:
|
||||||
|
"""
|
||||||
|
Helper to return the first IPv4 address of a node as its router ID.
|
||||||
|
"""
|
||||||
|
for ifc in node.netifs():
|
||||||
|
if getattr(ifc, "control", False):
|
||||||
|
continue
|
||||||
|
for a in ifc.addrlist:
|
||||||
|
a = a.split("/")[0]
|
||||||
|
if netaddr.valid_ipv4(a):
|
||||||
|
return a
|
||||||
|
return "0.0.0.0"
|
||||||
|
|
||||||
|
|
||||||
|
class FRRZebra(ConfigService):
|
||||||
|
name = "FRRzebra"
|
||||||
|
group = GROUP
|
||||||
|
directories = ["/usr/local/etc/frr", "/var/run/frr", "/var/log/frr"]
|
||||||
|
files = [
|
||||||
|
"/usr/local/etc/frr/frr.conf",
|
||||||
|
"frrboot.sh",
|
||||||
|
"/usr/local/etc/frr/vtysh.conf",
|
||||||
|
"/usr/local/etc/frr/daemons",
|
||||||
|
]
|
||||||
|
executables = ["zebra"]
|
||||||
|
dependencies = []
|
||||||
|
startup = ["sh frrboot.sh zebra"]
|
||||||
|
validate = ["pidof zebra"]
|
||||||
|
shutdown = ["killall zebra"]
|
||||||
|
validation_mode = ConfigServiceMode.BLOCKING
|
||||||
|
default_configs = []
|
||||||
|
modes = {}
|
||||||
|
|
||||||
|
def data(self) -> Dict[str, Any]:
|
||||||
|
frr_conf = self.files[0]
|
||||||
|
frr_bin_search = self.node.session.options.get_config(
|
||||||
|
"frr_bin_search", default="/usr/local/bin /usr/bin /usr/lib/frr"
|
||||||
|
).strip('"')
|
||||||
|
frr_sbin_search = self.node.session.options.get_config(
|
||||||
|
"frr_sbin_search", default="/usr/local/sbin /usr/sbin /usr/lib/frr"
|
||||||
|
).strip('"')
|
||||||
|
|
||||||
|
services = []
|
||||||
|
want_ip4 = False
|
||||||
|
want_ip6 = False
|
||||||
|
for service in self.node.config_services.values():
|
||||||
|
if self.name not in service.dependencies:
|
||||||
|
continue
|
||||||
|
if service.ipv4_routing:
|
||||||
|
want_ip4 = True
|
||||||
|
if service.ipv6_routing:
|
||||||
|
want_ip6 = True
|
||||||
|
services.append(service)
|
||||||
|
|
||||||
|
interfaces = []
|
||||||
|
for ifc in self.node.netifs():
|
||||||
|
ip4s = []
|
||||||
|
ip6s = []
|
||||||
|
for x in ifc.addrlist:
|
||||||
|
addr = x.split("/")[0]
|
||||||
|
if netaddr.valid_ipv4(addr):
|
||||||
|
ip4s.append(x)
|
||||||
|
else:
|
||||||
|
ip6s.append(x)
|
||||||
|
is_control = getattr(ifc, "control", False)
|
||||||
|
interfaces.append((ifc, ip4s, ip6s, is_control))
|
||||||
|
|
||||||
|
return dict(
|
||||||
|
frr_conf=frr_conf,
|
||||||
|
frr_sbin_search=frr_sbin_search,
|
||||||
|
frr_bin_search=frr_bin_search,
|
||||||
|
frr_state_dir=constants.FRR_STATE_DIR,
|
||||||
|
interfaces=interfaces,
|
||||||
|
want_ip4=want_ip4,
|
||||||
|
want_ip6=want_ip6,
|
||||||
|
services=services,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FrrService(abc.ABC):
|
||||||
|
group = GROUP
|
||||||
|
directories = []
|
||||||
|
files = []
|
||||||
|
executables = []
|
||||||
|
dependencies = ["FRRzebra"]
|
||||||
|
startup = []
|
||||||
|
validate = []
|
||||||
|
shutdown = []
|
||||||
|
validation_mode = ConfigServiceMode.BLOCKING
|
||||||
|
default_configs = []
|
||||||
|
modes = {}
|
||||||
|
ipv4_routing = False
|
||||||
|
ipv6_routing = False
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def frr_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def frr_config(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class FRROspfv2(FrrService, ConfigService):
|
||||||
|
"""
|
||||||
|
The OSPFv2 service provides IPv4 routing for wired networks. It does
|
||||||
|
not build its own configuration file but has hooks for adding to the
|
||||||
|
unified frr.conf file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "FRROSPFv2"
|
||||||
|
startup = ()
|
||||||
|
shutdown = ["killall ospfd"]
|
||||||
|
validate = ["pidof ospfd"]
|
||||||
|
ipv4_routing = True
|
||||||
|
|
||||||
|
def frr_config(self) -> str:
|
||||||
|
router_id = get_router_id(self.node)
|
||||||
|
addresses = []
|
||||||
|
for ifc in self.node.netifs():
|
||||||
|
if getattr(ifc, "control", False):
|
||||||
|
continue
|
||||||
|
for a in ifc.addrlist:
|
||||||
|
addr = a.split("/")[0]
|
||||||
|
if netaddr.valid_ipv4(addr):
|
||||||
|
addresses.append(a)
|
||||||
|
data = dict(router_id=router_id, addresses=addresses)
|
||||||
|
text = """
|
||||||
|
router ospf
|
||||||
|
router-id ${router_id}
|
||||||
|
% for addr in addresses:
|
||||||
|
network ${addr} area 0
|
||||||
|
% endfor
|
||||||
|
!
|
||||||
|
"""
|
||||||
|
return self.render_text(text, data)
|
||||||
|
|
||||||
|
def frr_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
if has_mtu_mismatch(ifc):
|
||||||
|
return "ip ospf mtu-ignore"
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
class FRROspfv3(FrrService, 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 frr.conf file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "FRROSPFv3"
|
||||||
|
shutdown = ["killall ospf6d"]
|
||||||
|
validate = ["pidof ospf6d"]
|
||||||
|
ipv4_routing = True
|
||||||
|
ipv6_routing = True
|
||||||
|
|
||||||
|
def frr_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
|
||||||
|
router-id ${router_id}
|
||||||
|
% for ifname in ifnames:
|
||||||
|
interface ${ifname} area 0.0.0.0
|
||||||
|
% endfor
|
||||||
|
!
|
||||||
|
"""
|
||||||
|
return self.render_text(text, data)
|
||||||
|
|
||||||
|
def frr_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
mtu = get_min_mtu(ifc)
|
||||||
|
if mtu < ifc.mtu:
|
||||||
|
return f"ipv6 ospf6 ifmtu {mtu}"
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
class FRRBgp(FrrService, ConfigService):
|
||||||
|
"""
|
||||||
|
The BGP service provides interdomain routing.
|
||||||
|
Peers must be manually configured, with a full mesh for those
|
||||||
|
having the same AS number.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "FRRBGP"
|
||||||
|
shutdown = ["killall bgpd"]
|
||||||
|
validate = ["pidof bgpd"]
|
||||||
|
custom_needed = True
|
||||||
|
ipv4_routing = True
|
||||||
|
ipv6_routing = True
|
||||||
|
|
||||||
|
def frr_config(self) -> 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)
|
||||||
|
|
||||||
|
def frr_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
class FRRRip(FrrService, ConfigService):
|
||||||
|
"""
|
||||||
|
The RIP service provides IPv4 routing for wired networks.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "FRRRIP"
|
||||||
|
shutdown = ["killall ripd"]
|
||||||
|
validate = ["pidof ripd"]
|
||||||
|
ipv4_routing = True
|
||||||
|
|
||||||
|
def frr_config(self) -> str:
|
||||||
|
text = """
|
||||||
|
router rip
|
||||||
|
redistribute static
|
||||||
|
redistribute connected
|
||||||
|
redistribute ospf
|
||||||
|
network 0.0.0.0/0
|
||||||
|
!
|
||||||
|
"""
|
||||||
|
return self.clean_text(text)
|
||||||
|
|
||||||
|
def frr_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
class FRRRipng(FrrService, ConfigService):
|
||||||
|
"""
|
||||||
|
The RIP NG service provides IPv6 routing for wired networks.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "FRRRIPNG"
|
||||||
|
shutdown = ["killall ripngd"]
|
||||||
|
validate = ["pidof ripngd"]
|
||||||
|
ipv6_routing = True
|
||||||
|
|
||||||
|
def frr_config(self) -> str:
|
||||||
|
text = """
|
||||||
|
router ripng
|
||||||
|
redistribute static
|
||||||
|
redistribute connected
|
||||||
|
redistribute ospf6
|
||||||
|
network ::/0
|
||||||
|
!
|
||||||
|
"""
|
||||||
|
return self.clean_text(text)
|
||||||
|
|
||||||
|
def frr_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
class FRRBabel(FrrService, ConfigService):
|
||||||
|
"""
|
||||||
|
The Babel service provides a loop-avoiding distance-vector routing
|
||||||
|
protocol for IPv6 and IPv4 with fast convergence properties.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "FRRBabel"
|
||||||
|
shutdown = ["killall babeld"]
|
||||||
|
validate = ["pidof babeld"]
|
||||||
|
ipv6_routing = True
|
||||||
|
|
||||||
|
def frr_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 ipv4 connected
|
||||||
|
!
|
||||||
|
"""
|
||||||
|
data = dict(ifnames=ifnames)
|
||||||
|
return self.render_text(text, data)
|
||||||
|
|
||||||
|
def frr_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 FRRpimd(FrrService, ConfigService):
|
||||||
|
"""
|
||||||
|
PIM multicast routing based on XORP.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "FRRpimd"
|
||||||
|
shutdown = ["killall pimd"]
|
||||||
|
validate = ["pidof pimd"]
|
||||||
|
ipv4_routing = True
|
||||||
|
|
||||||
|
def frr_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 frr_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
text = """
|
||||||
|
ip mfea
|
||||||
|
ip igmp
|
||||||
|
ip pim
|
||||||
|
"""
|
||||||
|
return self.clean_text(text)
|
59
daemon/core/configservices/frrservices/templates/daemons
Normal file
59
daemon/core/configservices/frrservices/templates/daemons
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#
|
||||||
|
# When activation a daemon at the first time, a config file, even if it is
|
||||||
|
# empty, has to be present *and* be owned by the user and group "frr", else
|
||||||
|
# the daemon will not be started by /etc/init.d/frr. The permissions should
|
||||||
|
# be u=rw,g=r,o=.
|
||||||
|
# When using "vtysh" such a config file is also needed. It should be owned by
|
||||||
|
# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
|
||||||
|
#
|
||||||
|
# The watchfrr and zebra daemons are always started.
|
||||||
|
#
|
||||||
|
bgpd=yes
|
||||||
|
ospfd=yes
|
||||||
|
ospf6d=yes
|
||||||
|
ripd=yes
|
||||||
|
ripngd=yes
|
||||||
|
isisd=yes
|
||||||
|
pimd=yes
|
||||||
|
ldpd=yes
|
||||||
|
nhrpd=yes
|
||||||
|
eigrpd=yes
|
||||||
|
babeld=yes
|
||||||
|
sharpd=yes
|
||||||
|
pbrd=yes
|
||||||
|
bfdd=yes
|
||||||
|
fabricd=yes
|
||||||
|
|
||||||
|
#
|
||||||
|
# If this option is set the /etc/init.d/frr script automatically loads
|
||||||
|
# the config via "vtysh -b" when the servers are started.
|
||||||
|
# Check /etc/pam.d/frr if you intend to use "vtysh"!
|
||||||
|
#
|
||||||
|
vtysh_enable=yes
|
||||||
|
zebra_options=" -A 127.0.0.1 -s 90000000"
|
||||||
|
bgpd_options=" -A 127.0.0.1"
|
||||||
|
ospfd_options=" -A 127.0.0.1"
|
||||||
|
ospf6d_options=" -A ::1"
|
||||||
|
ripd_options=" -A 127.0.0.1"
|
||||||
|
ripngd_options=" -A ::1"
|
||||||
|
isisd_options=" -A 127.0.0.1"
|
||||||
|
pimd_options=" -A 127.0.0.1"
|
||||||
|
ldpd_options=" -A 127.0.0.1"
|
||||||
|
nhrpd_options=" -A 127.0.0.1"
|
||||||
|
eigrpd_options=" -A 127.0.0.1"
|
||||||
|
babeld_options=" -A 127.0.0.1"
|
||||||
|
sharpd_options=" -A 127.0.0.1"
|
||||||
|
pbrd_options=" -A 127.0.0.1"
|
||||||
|
staticd_options="-A 127.0.0.1"
|
||||||
|
bfdd_options=" -A 127.0.0.1"
|
||||||
|
fabricd_options="-A 127.0.0.1"
|
||||||
|
|
||||||
|
# The list of daemons to watch is automatically generated by the init script.
|
||||||
|
#watchfrr_options=""
|
||||||
|
|
||||||
|
# for debugging purposes, you can specify a "wrap" command to start instead
|
||||||
|
# of starting the daemon directly, e.g. to use valgrind on ospfd:
|
||||||
|
# ospfd_wrap="/usr/bin/valgrind"
|
||||||
|
# or you can use "all_wrap" for all daemons, e.g. to use perf record:
|
||||||
|
# all_wrap="/usr/bin/perf record --call-graph -"
|
||||||
|
# the normal daemon command is added to this at the end.
|
25
daemon/core/configservices/frrservices/templates/frr.conf
Normal file
25
daemon/core/configservices/frrservices/templates/frr.conf
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
% for ifc, ip4s, ip6s, is_control in interfaces:
|
||||||
|
interface ${ifc.name}
|
||||||
|
% if want_ip4:
|
||||||
|
% for addr in ip4s:
|
||||||
|
ip address ${addr}
|
||||||
|
% endfor
|
||||||
|
% endif
|
||||||
|
% if want_ip6:
|
||||||
|
% for addr in ip6s:
|
||||||
|
ipv6 address ${addr}
|
||||||
|
% endfor
|
||||||
|
% endif
|
||||||
|
% if not is_control:
|
||||||
|
% for service in services:
|
||||||
|
% for line in service.frr_interface_config(ifc).split("\n"):
|
||||||
|
${line}
|
||||||
|
% endfor
|
||||||
|
% endfor
|
||||||
|
% endif
|
||||||
|
!
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
% for service in services:
|
||||||
|
${service.frr_config()}
|
||||||
|
% endfor
|
95
daemon/core/configservices/frrservices/templates/frrboot.sh
Normal file
95
daemon/core/configservices/frrservices/templates/frrboot.sh
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# auto-generated by zebra service (frr.py)
|
||||||
|
FRR_CONF="${frr_conf}"
|
||||||
|
FRR_SBIN_SEARCH="${frr_sbin_search}"
|
||||||
|
FRR_BIN_SEARCH="${frr_bin_search}"
|
||||||
|
FRR_STATE_DIR="${frr_state_dir}"
|
||||||
|
|
||||||
|
searchforprog()
|
||||||
|
{
|
||||||
|
prog=$1
|
||||||
|
searchpath=$@
|
||||||
|
ret=
|
||||||
|
for p in $searchpath; do
|
||||||
|
if [ -x $p/$prog ]; then
|
||||||
|
ret=$p
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
confcheck()
|
||||||
|
{
|
||||||
|
CONF_DIR=`dirname $FRR_CONF`
|
||||||
|
# if /etc/frr exists, point /etc/frr/frr.conf -> CONF_DIR
|
||||||
|
if [ "$CONF_DIR" != "/etc/frr" ] && [ -d /etc/frr ] && [ ! -e /etc/frr/frr.conf ]; then
|
||||||
|
ln -s $CONF_DIR/frr.conf /etc/frr/frr.conf
|
||||||
|
fi
|
||||||
|
# if /etc/frr exists, point /etc/frr/vtysh.conf -> CONF_DIR
|
||||||
|
if [ "$CONF_DIR" != "/etc/frr" ] && [ -d /etc/frr ] && [ ! -e /etc/frr/vtysh.conf ]; then
|
||||||
|
ln -s $CONF_DIR/vtysh.conf /etc/frr/vtysh.conf
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
bootdaemon()
|
||||||
|
{
|
||||||
|
FRR_SBIN_DIR=$(searchforprog $1 $FRR_SBIN_SEARCH)
|
||||||
|
if [ "z$FRR_SBIN_DIR" = "z" ]; then
|
||||||
|
echo "ERROR: FRR's '$1' daemon not found in search path:"
|
||||||
|
echo " $FRR_SBIN_SEARCH"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
flags=""
|
||||||
|
|
||||||
|
if [ "$1" = "pimd" ] && \\
|
||||||
|
grep -E -q '^[[:space:]]*router[[:space:]]+pim6[[:space:]]*$' $FRR_CONF; then
|
||||||
|
flags="$flags -6"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#force FRR to use CORE generated conf file
|
||||||
|
flags="$flags -d -f $FRR_CONF"
|
||||||
|
$FRR_SBIN_DIR/$1 $flags
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
echo "ERROR: FRR's '$1' daemon failed to start!:"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
bootfrr()
|
||||||
|
{
|
||||||
|
FRR_BIN_DIR=$(searchforprog 'vtysh' $FRR_BIN_SEARCH)
|
||||||
|
if [ "z$FRR_BIN_DIR" = "z" ]; then
|
||||||
|
echo "ERROR: FRR's 'vtysh' program not found in search path:"
|
||||||
|
echo " $FRR_BIN_SEARCH"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# fix /var/run/frr permissions
|
||||||
|
id -u frr 2>/dev/null >/dev/null
|
||||||
|
if [ "$?" = "0" ]; then
|
||||||
|
chown frr $FRR_STATE_DIR
|
||||||
|
fi
|
||||||
|
|
||||||
|
bootdaemon "zebra"
|
||||||
|
for r in rip ripng ospf6 ospf bgp babel; do
|
||||||
|
if grep -q "^router \\<$${}{r}\\>" $FRR_CONF; then
|
||||||
|
bootdaemon "$${}{r}d"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if grep -E -q '^[[:space:]]*router[[:space:]]+pim6?[[:space:]]*$' $FRR_CONF; then
|
||||||
|
bootdaemon "pimd"
|
||||||
|
fi
|
||||||
|
|
||||||
|
$FRR_BIN_DIR/vtysh -b
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$1" != "zebra" ]; then
|
||||||
|
echo "WARNING: '$1': all FRR daemons are launched by the 'zebra' service!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
confcheck
|
||||||
|
bootfrr
|
|
@ -0,0 +1 @@
|
||||||
|
service integrated-vtysh-config
|
|
@ -274,6 +274,9 @@ class Bgp(QuaggaService, ConfigService):
|
||||||
ipv4_routing = True
|
ipv4_routing = True
|
||||||
ipv6_routing = True
|
ipv6_routing = True
|
||||||
|
|
||||||
|
def quagga_config(self) -> str:
|
||||||
|
return ""
|
||||||
|
|
||||||
def quagga_interface_config(self, ifc: CoreInterface) -> str:
|
def quagga_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
router_id = get_router_id(self.node)
|
router_id = get_router_id(self.node)
|
||||||
text = f"""
|
text = f"""
|
||||||
|
@ -310,6 +313,9 @@ class Rip(QuaggaService, ConfigService):
|
||||||
"""
|
"""
|
||||||
return self.clean_text(text)
|
return self.clean_text(text)
|
||||||
|
|
||||||
|
def quagga_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
class Ripng(QuaggaService, ConfigService):
|
class Ripng(QuaggaService, ConfigService):
|
||||||
"""
|
"""
|
||||||
|
@ -332,6 +338,9 @@ class Ripng(QuaggaService, ConfigService):
|
||||||
"""
|
"""
|
||||||
return self.clean_text(text)
|
return self.clean_text(text)
|
||||||
|
|
||||||
|
def quagga_interface_config(self, ifc: CoreInterface) -> str:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
class Babel(QuaggaService, ConfigService):
|
class Babel(QuaggaService, ConfigService):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Add table
Reference in a new issue