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

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/>. 

18 

19"""BIRD RIP configuration parser.""" 

20 

21from typing import Any 

22 

23from .....exceptions import BirdPlanConfigError 

24from .... import BirdConfig 

25from ....config_parser import ConfigParser 

26 

27__all__ = ["RIPConfigParser"] 

28 

29 

30class RIPConfigParser(ConfigParser): 

31 """RIP configuration parser.""" 

32 

33 _birdconf: BirdConfig 

34 

35 def parse(self, config: dict[str, Any]) -> None: 

36 """Configure RIP protocol.""" 

37 

38 self._config_rip(config) 

39 

40 def _config_rip(self, config: dict[str, Any]) -> None: 

41 """Configure rip section.""" 

42 

43 # If we have no rip section, just return 

44 if "rip" not in config: 

45 return 

46 

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") 

51 

52 self._config_rip_accept(config) 

53 self._config_rip_redistribute(config) 

54 self._config_rip_interfaces(config) 

55 

56 def _config_rip_accept(self, config: dict[str, Any]) -> None: 

57 """Configure rip:accept section.""" 

58 

59 # If we don't have an accept section, just return 

60 if "accept" not in config["rip"]: 

61 return 

62 

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") 

71 

72 def _config_rip_redistribute(self, config: dict[str, Any]) -> None: # noqa: C901,PLR0912 

73 """Configure rip:redistribute section.""" 

74 

75 # If we don't have a redistribute section just return 

76 if "redistribute" not in config["rip"]: 

77 return 

78 

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") 

127 

128 def _config_rip_interfaces(self, config: dict[str, Any]) -> None: 

129 """Configure rip:interfaces section.""" 

130 

131 # If we don't have interfaces in our rip section, just return 

132 if "interfaces" not in config["rip"]: 

133 return 

134 

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)