Coverage for src/birdplan/bird_config/sections/protocols/rip/rip_config_parser.py: 87%
62 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-25 07:38 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-25 07:38 +0000
1#
2# SPDX-License-Identifier: GPL-3.0-or-later
3#
4# Copyright (c) 2019-2025, AllWorldIT
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
19"""BIRD RIP configuration parser."""
21from typing import Any
23from .....exceptions import BirdPlanConfigError
24from .... import BirdConfig
25from ....config_parser import ConfigParser
27__all__ = ["RIPConfigParser"]
30class RIPConfigParser(ConfigParser):
31 """RIP configuration parser."""
33 _birdconf: BirdConfig
35 def parse(self, config: dict[str, Any]) -> None:
36 """Configure RIP protocol."""
38 self._config_rip(config)
40 def _config_rip(self, config: dict[str, Any]) -> None:
41 """Configure rip section."""
43 # If we have no rip section, just return
44 if "rip" not in config:
45 return
47 # Check configuration options are supported
48 for config_item in config["rip"]:
49 if config_item not in ("accept", "redistribute", "interfaces"):
50 raise BirdPlanConfigError(f"The 'rip' config item '{config_item}' is not supported")
52 self._config_rip_accept(config)
53 self._config_rip_redistribute(config)
54 self._config_rip_interfaces(config)
56 def _config_rip_accept(self, config: dict[str, Any]) -> None:
57 """Configure rip:accept section."""
59 # If we don't have an accept section, just return
60 if "accept" not in config["rip"]:
61 return
63 # Loop with accept items
64 for accept, accept_config in config["rip"]["accept"].items():
65 # Allow accept of the default route
66 if accept == "default":
67 self.birdconf.protocols.rip.route_policy_accept.default = accept_config
68 # If we don't understand this 'accept' entry, throw an error
69 else:
70 raise BirdPlanConfigError(f"Configuration item '{accept}' not understood in RIP accept")
72 def _config_rip_redistribute(self, config: dict[str, Any]) -> None: # noqa: C901,PLR0912
73 """Configure rip:redistribute section."""
75 # If we don't have a redistribute section just return
76 if "redistribute" not in config["rip"]:
77 return
79 # Loop with redistribution items
80 for redistribute, redistribute_config in config["rip"]["redistribute"].items():
81 # Add connected route redistribution
82 if redistribute == "connected":
83 # Set type
84 redistribute_connected: bool | list[str]
85 # Check what kind of config we go...
86 if isinstance(redistribute_config, bool):
87 redistribute_connected = redistribute_config
88 # Else if its a dict, we need to treat it a bit differently
89 elif isinstance(redistribute_config, dict):
90 # Check it has an "interfaces" key
91 if "interfaces" not in redistribute_config:
92 raise BirdPlanConfigError(
93 f"Configurion item '{redistribute}' has no 'interfaces' option in rip:redistribute"
94 )
95 # If it does, check that it is a list
96 if not isinstance(redistribute_config["interfaces"], list):
97 raise BirdPlanConfigError(
98 f"Configurion item '{redistribute}:interfaces' has an invalid type in rip:redistribute"
99 )
100 # Set redistribute_connected as the interface list
101 redistribute_connected = redistribute_config["interfaces"]
102 else:
103 raise BirdPlanConfigError(f"Configurion item '{redistribute}' has an unsupported value")
104 # Add configuration
105 self.birdconf.protocols.rip.route_policy_redistribute.connected = redistribute_connected
106 # Add kernel route redistribution
107 elif redistribute == "kernel":
108 self.birdconf.protocols.rip.route_policy_redistribute.kernel = redistribute_config
109 # Add kernel default route redistribution
110 elif redistribute == "kernel_default":
111 self.birdconf.protocols.rip.route_policy_redistribute.kernel_default = redistribute_config
112 # Allow redistribution of RIP routes
113 elif redistribute == "rip":
114 self.birdconf.protocols.rip.route_policy_redistribute.rip = redistribute_config
115 # Allow redistribution of RIP default routes
116 elif redistribute == "rip_default":
117 self.birdconf.protocols.rip.route_policy_redistribute.rip_default = redistribute_config
118 # Add static route redistribution
119 elif redistribute == "static":
120 self.birdconf.protocols.rip.route_policy_redistribute.static = redistribute_config
121 # Add static default route redistribution
122 elif redistribute == "static_default":
123 self.birdconf.protocols.rip.route_policy_redistribute.static_default = redistribute_config
124 # If we don't understand this 'redistribute' entry, throw an error
125 else:
126 raise BirdPlanConfigError(f"Configuration item '{redistribute}' not understood in rip:redistribute")
128 def _config_rip_interfaces(self, config: dict[str, Any]) -> None:
129 """Configure rip:interfaces section."""
131 # If we don't have interfaces in our rip section, just return
132 if "interfaces" not in config["rip"]:
133 return
135 # Loop with each interface and its config
136 for interface_name, interface in config["rip"]["interfaces"].items():
137 # See if we have interface config
138 interface_config = {}
139 # Loop with each config item in the peer
140 for config_item, config_value in interface.items():
141 if config_item in ("update-time", "metric"):
142 interface_config[config_item] = config_value
143 # If we don't understand this 'redistribute' entry, throw an error
144 else:
145 raise BirdPlanConfigError(f"Configuration item '{config_item}' not understood in RIP area")
146 # Add interface
147 self.birdconf.protocols.rip.add_interface(interface_name, interface_config)