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\
2629log syslog informational\n\
2730log 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+
29245int 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
275491int 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
0 commit comments