Skip to content

Commit 1cbc9a4

Browse files
committed
confd: initial support for rip
Fixes #582 Signed-off-by: Joachim Wiberg <[email protected]>
1 parent dc6e827 commit 1cbc9a4

File tree

16 files changed

+2213
-14
lines changed

16 files changed

+2213
-14
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# --log-level debug
2+
RIPD_ARGS="-A 127.0.0.1 -u frr -g frr -f /etc/frr/ripd.conf --log syslog"
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
service [2345] log:null <pid/zebra> ripd -A 127.0.0.1 -u frr -g frr -- RIP daemon
1+
service <pid/zebra> env:-/etc/default/ripd \
2+
[2345] ripd $RIPD_ARGS -- RIP daemon

src/confd/src/routing.c

Lines changed: 247 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#define OSPFD_CONF "/etc/frr/ospfd.conf"
1515
#define OSPFD_CONF_NEXT OSPFD_CONF "+"
1616
#define OSPFD_CONF_PREV OSPFD_CONF "-"
17+
#define RIPD_CONF "/etc/frr/ripd.conf"
18+
#define RIPD_CONF_NEXT RIPD_CONF "+"
19+
#define RIPD_CONF_PREV RIPD_CONF "-"
1720
#define BFDD_CONF "/etc/frr/bfd_enabled" /* Just signal that bfd should be enabled*/
1821
#define BFDD_CONF_NEXT BFDD_CONF "+"
1922

@@ -26,6 +29,219 @@ no log unique-id\n\
2629
log syslog informational\n\
2730
log facility local2\n"
2831

32+
int parse_rip_redistribute(sr_session_ctx_t *session, struct lyd_node *redistributes, FILE *fp)
33+
{
34+
struct lyd_node *tmp;
35+
36+
LY_LIST_FOR(lyd_child(redistributes), tmp) {
37+
const char *protocol = lydx_get_cattr(tmp, "protocol");
38+
39+
fprintf(fp, " redistribute %s\n", protocol);
40+
}
41+
42+
return 0;
43+
}
44+
45+
int parse_rip_interfaces(sr_session_ctx_t *session, struct lyd_node *interfaces, FILE *fp)
46+
{
47+
struct lyd_node *interface, *neighbors_node, *neighbor;
48+
int num_interfaces = 0;
49+
50+
/* First pass: network and passive-interface statements (inside router rip block) */
51+
LY_LIST_FOR(lyd_child(interfaces), interface) {
52+
const char *name;
53+
int passive;
54+
55+
name = lydx_get_cattr(interface, "interface");
56+
if (!name)
57+
continue;
58+
59+
passive = lydx_get_bool(interface, "passive");
60+
61+
/* Enable RIP on the interface by adding it to the network statement */
62+
fprintf(fp, " network %s\n", name);
63+
64+
if (passive)
65+
fprintf(fp, " passive-interface %s\n", name);
66+
67+
num_interfaces++;
68+
}
69+
70+
/* Handle explicit neighbors (inside router rip block) */
71+
LY_LIST_FOR(lyd_child(interfaces), interface) {
72+
neighbors_node = lydx_get_child(interface, "neighbors");
73+
if (neighbors_node) {
74+
LY_LIST_FOR(lyd_child(neighbors_node), neighbor) {
75+
const char *address = lydx_get_cattr(neighbor, "address");
76+
if (address)
77+
fprintf(fp, " neighbor %s\n", address);
78+
}
79+
}
80+
}
81+
82+
/* Second pass: interface-specific settings (outside router rip block) */
83+
LY_LIST_FOR(lyd_child(interfaces), interface) {
84+
const char *name, *split_horizon, *cost, *send_version, *recv_version;
85+
86+
name = lydx_get_cattr(interface, "interface");
87+
if (!name)
88+
continue;
89+
90+
split_horizon = lydx_get_cattr(interface, "split-horizon");
91+
cost = lydx_get_cattr(interface, "cost");
92+
send_version = lydx_get_cattr(interface, "send-version");
93+
recv_version = lydx_get_cattr(interface, "receive-version");
94+
95+
/* Only create interface block if there are per-interface settings */
96+
if (split_horizon || cost || send_version || recv_version) {
97+
fprintf(fp, "interface %s\n", name);
98+
99+
if (split_horizon) {
100+
if (!strcmp(split_horizon, "poison-reverse"))
101+
fputs(" ip rip split-horizon poisoned-reverse\n", fp);
102+
else if (!strcmp(split_horizon, "disabled"))
103+
fputs(" no ip rip split-horizon\n", fp);
104+
/* "simple" is default, no need to configure */
105+
}
106+
107+
/* Configure send version */
108+
if (send_version) {
109+
if (!strcmp(send_version, "1"))
110+
fputs(" ip rip send version 1\n", fp);
111+
else if (!strcmp(send_version, "1-2"))
112+
fputs(" ip rip send version 1 2\n", fp);
113+
/* "2" is default in augmentation, explicit config if needed */
114+
else if (!strcmp(send_version, "2"))
115+
fputs(" ip rip send version 2\n", fp);
116+
}
117+
118+
/* Configure receive version */
119+
if (recv_version) {
120+
if (!strcmp(recv_version, "1"))
121+
fputs(" ip rip receive version 1\n", fp);
122+
else if (!strcmp(recv_version, "1-2"))
123+
fputs(" ip rip receive version 1 2\n", fp);
124+
/* "2" is default in augmentation, explicit config if needed */
125+
else if (!strcmp(recv_version, "2"))
126+
fputs(" ip rip receive version 2\n", fp);
127+
}
128+
129+
if (cost) {
130+
/* FRR uses offset-list for per-interface cost adjustment */
131+
/* Note: offset-list is configured globally, not per-interface */
132+
/* This is just a placeholder - actual implementation would need
133+
access lists and global offset-list configuration */
134+
}
135+
}
136+
}
137+
138+
return num_interfaces;
139+
}
140+
141+
int parse_rip_timers(sr_session_ctx_t *session, struct lyd_node *timers, FILE *fp)
142+
{
143+
const char *update, *invalid, *holddown, *flush;
144+
145+
if (!timers)
146+
return 0;
147+
148+
update = lydx_get_cattr(timers, "update-interval");
149+
invalid = lydx_get_cattr(timers, "invalid-interval");
150+
holddown = lydx_get_cattr(timers, "holddown-interval");
151+
flush = lydx_get_cattr(timers, "flush-interval");
152+
153+
/* FRR timers basic: UPDATE TIMEOUT GARBAGE
154+
* TIMEOUT = invalid-interval (when route becomes invalid)
155+
* GARBAGE = flush-interval (when route is flushed)
156+
* Note: holddown-interval is used between invalid and flush
157+
*/
158+
DEBUG("Ignoring 'holddown interval %s' for now", holddown);
159+
if (update || invalid || flush) {
160+
fprintf(fp, " timers basic %s %s %s\n",
161+
update ? update : "30",
162+
invalid ? invalid : "180",
163+
flush ? flush : "240");
164+
}
165+
166+
return 0;
167+
}
168+
169+
int parse_rip(sr_session_ctx_t *session, struct lyd_node *rip)
170+
{
171+
struct lyd_node *interfaces, *timers, *default_route, *debug;
172+
const char *default_metric, *distance;
173+
int num_interfaces = 0;
174+
FILE *fp;
175+
176+
fp = fopen(RIPD_CONF_NEXT, "w");
177+
if (!fp) {
178+
ERROR("Failed to open %s", RIPD_CONF_NEXT);
179+
return SR_ERR_INTERNAL;
180+
}
181+
182+
fputs(FRR_STATIC_CONFIG, fp);
183+
184+
/* Handle RIP debug configuration */
185+
debug = lydx_get_child(rip, "debug");
186+
if (debug) {
187+
int any_debug = 0;
188+
189+
if (lydx_get_bool(debug, "events")) {
190+
fputs("debug rip events\n", fp);
191+
any_debug = 1;
192+
}
193+
if (lydx_get_bool(debug, "packet")) {
194+
fputs("debug rip packet\n", fp);
195+
any_debug = 1;
196+
}
197+
if (lydx_get_bool(debug, "kernel")) {
198+
fputs("debug rip zebra\n", fp);
199+
any_debug = 1;
200+
}
201+
202+
if (any_debug)
203+
fputs("!\n", fp);
204+
}
205+
206+
fputs("router rip\n", fp);
207+
fputs(" version 2\n", fp);
208+
209+
/* Global RIP parameters */
210+
default_metric = lydx_get_cattr(rip, "default-metric");
211+
if (default_metric)
212+
fprintf(fp, " default-metric %s\n", default_metric);
213+
214+
distance = lydx_get_cattr(rip, "distance");
215+
if (distance)
216+
fprintf(fp, " distance %s\n", distance);
217+
218+
/* Timers */
219+
timers = lydx_get_child(rip, "timers");
220+
parse_rip_timers(session, timers, fp);
221+
222+
/* Default route origination */
223+
default_route = lydx_get_child(rip, "originate-default-route");
224+
if (default_route && lydx_get_bool(default_route, "enabled"))
225+
fputs(" default-information originate\n", fp);
226+
227+
/* Redistribution */
228+
parse_rip_redistribute(session, lydx_get_child(rip, "redistribute"), fp);
229+
230+
/* Interfaces - must be done after router rip block and before interface blocks */
231+
interfaces = lydx_get_child(rip, "interfaces");
232+
if (interfaces)
233+
num_interfaces = parse_rip_interfaces(session, interfaces, fp);
234+
235+
fclose(fp);
236+
237+
if (!num_interfaces) {
238+
(void)remove(RIPD_CONF_NEXT);
239+
return 0;
240+
}
241+
242+
return 0;
243+
}
244+
29245
int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FILE *fp)
30246
{
31247
struct lyd_node *interface, *interfaces, *area;
@@ -274,9 +490,9 @@ static int parse_static_routes(sr_session_ctx_t *session, struct lyd_node *paren
274490

275491
int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd)
276492
{
277-
int staticd_enabled = 0, ospfd_enabled = 0, bfdd_enabled = 0;
493+
int staticd_enabled = 0, ospfd_enabled = 0, ripd_enabled = 0, bfdd_enabled = 0;
278494
struct lyd_node *cplane, *cplanes;
279-
bool ospfd_running, bfdd_running;
495+
bool ospfd_running, ripd_running, bfdd_running;
280496
bool restart_zebra = false;
281497
int rc = SR_ERR_OK;
282498
FILE *fp;
@@ -303,8 +519,10 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly
303519
/* Check if passed validation in previous event */
304520
staticd_enabled = fexist(STATICD_CONF_NEXT);
305521
ospfd_enabled = fexist(OSPFD_CONF_NEXT);
522+
ripd_enabled = fexist(RIPD_CONF_NEXT);
306523
bfdd_enabled = fexist(BFDD_CONF_NEXT);
307524
ospfd_running = !systemf("initctl -bfq status ospfd");
525+
ripd_running = !systemf("initctl -bfq status ripd");
308526
bfdd_running = !systemf("initctl -bfq status bfdd");
309527

310528
if (bfdd_running && !bfdd_enabled) {
@@ -327,6 +545,16 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly
327545
(void)remove(OSPFD_CONF);
328546
}
329547

548+
if (ripd_running && !ripd_enabled) {
549+
if (systemf("initctl -bfq disable ripd")) {
550+
ERROR("Failed to disable RIP routing daemon");
551+
rc = SR_ERR_INTERNAL;
552+
goto err_abandon;
553+
}
554+
/* Remove all generated files */
555+
(void)remove(RIPD_CONF);
556+
}
557+
330558
if (bfdd_enabled) {
331559
(void)rename(BFDD_CONF_NEXT, BFDD_CONF);
332560
if (!bfdd_running) {
@@ -353,6 +581,21 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly
353581
}
354582
}
355583

584+
if (ripd_enabled) {
585+
(void)remove(RIPD_CONF_PREV);
586+
(void)rename(RIPD_CONF, RIPD_CONF_PREV);
587+
(void)rename(RIPD_CONF_NEXT, RIPD_CONF);
588+
if (!ripd_running) {
589+
if (systemf("initctl -bnq enable ripd")) {
590+
ERROR("Failed to enable RIP routing daemon");
591+
rc = SR_ERR_INTERNAL;
592+
goto err_abandon;
593+
}
594+
} else {
595+
restart_zebra = true;
596+
}
597+
}
598+
356599
if (staticd_enabled) {
357600
(void)remove(STATICD_CONF_PREV);
358601
(void)rename(STATICD_CONF, STATICD_CONF_PREV);
@@ -389,6 +632,8 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly
389632
staticd_enabled = parse_static_routes(session, lydx_get_child(cplane, "static-routes"), fp);
390633
} else if (!strcmp(type, "infix-routing:ospfv2")) {
391634
parse_ospf(session, lydx_get_child(cplane, "ospf"));
635+
} else if (!strcmp(type, "infix-routing:ripv2")) {
636+
parse_rip(session, lydx_get_child(cplane, "rip"));
392637
}
393638
}
394639

src/confd/yang/confd.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ MODULES=(
1111
1212
1313
"[email protected] -e bfd -e explicit-router-id"
14+
1415
1516
1617

0 commit comments

Comments
 (0)