]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_nb_state.c
Merge pull request #13601 from opensourcerouting/build-yang-embed-20230525
[mirror_frr.git] / ripd / rip_nb_state.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2018 NetDEF, Inc.
4 * Renato Westphal
5 */
6
7 #include <zebra.h>
8
9 #include "if.h"
10 #include "vrf.h"
11 #include "log.h"
12 #include "prefix.h"
13 #include "table.h"
14 #include "command.h"
15 #include "routemap.h"
16 #include "northbound.h"
17 #include "libfrr.h"
18
19 #include "ripd/ripd.h"
20 #include "ripd/rip_nb.h"
21 #include "ripd/rip_debug.h"
22 #include "ripd/rip_interface.h"
23
24 /*
25 * XPath: /frr-ripd:ripd/instance
26 */
27 const void *ripd_instance_get_next(struct nb_cb_get_next_args *args)
28 {
29 struct rip *rip = (struct rip *)args->list_entry;
30
31 if (args->list_entry == NULL)
32 rip = RB_MIN(rip_instance_head, &rip_instances);
33 else
34 rip = RB_NEXT(rip_instance_head, rip);
35
36 return rip;
37 }
38
39 int ripd_instance_get_keys(struct nb_cb_get_keys_args *args)
40 {
41 const struct rip *rip = args->list_entry;
42
43 args->keys->num = 1;
44 strlcpy(args->keys->key[0], rip->vrf_name, sizeof(args->keys->key[0]));
45
46 return NB_OK;
47 }
48
49 const void *ripd_instance_lookup_entry(struct nb_cb_lookup_entry_args *args)
50 {
51 const char *vrf_name = args->keys->key[0];
52
53 return rip_lookup_by_vrf_name(vrf_name);
54 }
55
56 /*
57 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor
58 */
59 const void *ripd_instance_state_neighbors_neighbor_get_next(
60 struct nb_cb_get_next_args *args)
61 {
62 const struct rip *rip = args->parent_list_entry;
63 struct listnode *node;
64
65 if (args->list_entry == NULL)
66 node = listhead(rip->peer_list);
67 else
68 node = listnextnode((struct listnode *)args->list_entry);
69
70 return node;
71 }
72
73 int ripd_instance_state_neighbors_neighbor_get_keys(
74 struct nb_cb_get_keys_args *args)
75 {
76 const struct listnode *node = args->list_entry;
77 const struct rip_peer *peer = listgetdata(node);
78
79 args->keys->num = 1;
80 (void)inet_ntop(AF_INET, &peer->addr, args->keys->key[0],
81 sizeof(args->keys->key[0]));
82
83 return NB_OK;
84 }
85
86 const void *ripd_instance_state_neighbors_neighbor_lookup_entry(
87 struct nb_cb_lookup_entry_args *args)
88 {
89 const struct rip *rip = args->parent_list_entry;
90 struct in_addr address;
91 struct rip_peer *peer;
92 struct listnode *node;
93
94 yang_str2ipv4(args->keys->key[0], &address);
95
96 for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, peer)) {
97 if (IPV4_ADDR_SAME(&peer->addr, &address))
98 return node;
99 }
100
101 return NULL;
102 }
103
104 /*
105 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/address
106 */
107 struct yang_data *ripd_instance_state_neighbors_neighbor_address_get_elem(
108 struct nb_cb_get_elem_args *args)
109 {
110 const struct listnode *node = args->list_entry;
111 const struct rip_peer *peer = listgetdata(node);
112
113 return yang_data_new_ipv4(args->xpath, &peer->addr);
114 }
115
116 /*
117 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/last-update
118 */
119 struct yang_data *ripd_instance_state_neighbors_neighbor_last_update_get_elem(
120 struct nb_cb_get_elem_args *args)
121 {
122 /* TODO: yang:date-and-time is tricky */
123 return NULL;
124 }
125
126 /*
127 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd
128 */
129 struct yang_data *
130 ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
131 struct nb_cb_get_elem_args *args)
132 {
133 const struct listnode *node = args->list_entry;
134 const struct rip_peer *peer = listgetdata(node);
135
136 return yang_data_new_uint32(args->xpath, peer->recv_badpackets);
137 }
138
139 /*
140 * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd
141 */
142 struct yang_data *
143 ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
144 struct nb_cb_get_elem_args *args)
145 {
146 const struct listnode *node = args->list_entry;
147 const struct rip_peer *peer = listgetdata(node);
148
149 return yang_data_new_uint32(args->xpath, peer->recv_badroutes);
150 }
151
152 /*
153 * XPath: /frr-ripd:ripd/instance/state/routes/route
154 */
155 const void *
156 ripd_instance_state_routes_route_get_next(struct nb_cb_get_next_args *args)
157 {
158 const struct rip *rip = args->parent_list_entry;
159 struct route_node *rn;
160
161 if (args->list_entry == NULL)
162 rn = route_top(rip->table);
163 else
164 rn = route_next((struct route_node *)args->list_entry);
165 /* Optimization: skip empty route nodes. */
166 while (rn && rn->info == NULL)
167 rn = route_next(rn);
168
169 return rn;
170 }
171
172 int ripd_instance_state_routes_route_get_keys(struct nb_cb_get_keys_args *args)
173 {
174 const struct route_node *rn = args->list_entry;
175
176 args->keys->num = 1;
177 (void)prefix2str(&rn->p, args->keys->key[0],
178 sizeof(args->keys->key[0]));
179
180 return NB_OK;
181 }
182
183 const void *ripd_instance_state_routes_route_lookup_entry(
184 struct nb_cb_lookup_entry_args *args)
185 {
186 const struct rip *rip = args->parent_list_entry;
187 struct prefix prefix;
188 struct route_node *rn;
189
190 yang_str2ipv4p(args->keys->key[0], &prefix);
191
192 rn = route_node_lookup(rip->table, &prefix);
193 if (!rn || !rn->info)
194 return NULL;
195
196 route_unlock_node(rn);
197
198 return rn;
199 }
200
201 /*
202 * XPath: /frr-ripd:ripd/instance/state/routes/route/prefix
203 */
204 struct yang_data *ripd_instance_state_routes_route_prefix_get_elem(
205 struct nb_cb_get_elem_args *args)
206 {
207 const struct route_node *rn = args->list_entry;
208 const struct rip_info *rinfo = listnode_head(rn->info);
209
210 assert(rinfo);
211 return yang_data_new_ipv4p(args->xpath, &rinfo->rp->p);
212 }
213
214 /*
215 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop
216 */
217 const void *ripd_instance_state_routes_route_nexthops_nexthop_get_next(
218 struct nb_cb_get_next_args *args)
219 {
220 const struct route_node *rn = args->parent_list_entry;
221 const struct listnode *node = args->list_entry;
222
223 assert(rn);
224 if (node)
225 return listnextnode(node);
226 assert(rn->info);
227 return listhead((struct list *)rn->info);
228 }
229
230 static inline const struct rip_info *get_rip_info(const void *info)
231 {
232 return (const struct rip_info *)listgetdata(
233 (const struct listnode *)info);
234 }
235
236 /*
237 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/nh-type
238 */
239 struct yang_data *
240 ripd_instance_state_routes_route_nexthops_nexthop_nh_type_get_elem(
241 struct nb_cb_get_elem_args *args)
242 {
243 const struct rip_info *rinfo = get_rip_info(args->list_entry);
244
245 assert(rinfo);
246 return yang_data_new_enum(args->xpath, rinfo->nh.type);
247 }
248
249 /*
250 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/protocol
251 */
252 struct yang_data *
253 ripd_instance_state_routes_route_nexthops_nexthop_protocol_get_elem(
254 struct nb_cb_get_elem_args *args)
255 {
256 const struct rip_info *rinfo = get_rip_info(args->list_entry);
257
258 assert(rinfo);
259 return yang_data_new_enum(args->xpath, rinfo->type);
260 }
261
262 /*
263 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/rip-type
264 */
265 struct yang_data *
266 ripd_instance_state_routes_route_nexthops_nexthop_rip_type_get_elem(
267 struct nb_cb_get_elem_args *args)
268 {
269 const struct rip_info *rinfo = get_rip_info(args->list_entry);
270
271 assert(rinfo);
272 return yang_data_new_enum(args->xpath, rinfo->sub_type);
273 }
274
275 /*
276 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/gateway
277 */
278 struct yang_data *
279 ripd_instance_state_routes_route_nexthops_nexthop_gateway_get_elem(
280 struct nb_cb_get_elem_args *args)
281 {
282 const struct rip_info *rinfo = get_rip_info(args->list_entry);
283
284 if (rinfo->nh.type != NEXTHOP_TYPE_IPV4 &&
285 rinfo->nh.type != NEXTHOP_TYPE_IPV4_IFINDEX)
286 return NULL;
287
288 return yang_data_new_ipv4(args->xpath, &rinfo->nh.gate.ipv4);
289 }
290
291 /*
292 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/interface
293 */
294 struct yang_data *
295 ripd_instance_state_routes_route_nexthops_nexthop_interface_get_elem(
296 struct nb_cb_get_elem_args *args)
297 {
298 const struct rip_info *rinfo = get_rip_info(args->list_entry);
299 const struct rip *rip = rip_info_get_instance(rinfo);
300
301 if (rinfo->nh.type != NEXTHOP_TYPE_IFINDEX &&
302 rinfo->nh.type != NEXTHOP_TYPE_IPV4_IFINDEX)
303 return NULL;
304
305 return yang_data_new_string(
306 args->xpath,
307 ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id));
308 }
309
310 /*
311 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/from
312 */
313 struct yang_data *
314 ripd_instance_state_routes_route_nexthops_nexthop_from_get_elem(
315 struct nb_cb_get_elem_args *args)
316 {
317 const struct rip_info *rinfo = get_rip_info(args->list_entry);
318
319 if (rinfo->type != ZEBRA_ROUTE_RIP || rinfo->sub_type != RIP_ROUTE_RTE)
320 return NULL;
321
322 return yang_data_new_ipv4(args->xpath, &rinfo->from);
323 }
324
325 /*
326 * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/tag
327 */
328 struct yang_data *
329 ripd_instance_state_routes_route_nexthops_nexthop_tag_get_elem(
330 struct nb_cb_get_elem_args *args)
331 {
332 const struct rip_info *rinfo = get_rip_info(args->list_entry);
333
334 return yang_data_new_uint32(args->xpath, rinfo->tag);
335 }
336
337 /*
338 * XPath:
339 * /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/external-metric
340 */
341 struct yang_data *
342 ripd_instance_state_routes_route_nexthops_nexthop_external_metric_get_elem(
343 struct nb_cb_get_elem_args *args)
344 {
345 const struct rip_info *rinfo = get_rip_info(args->list_entry);
346
347 if ((rinfo->type == ZEBRA_ROUTE_RIP &&
348 rinfo->sub_type == RIP_ROUTE_RTE) ||
349 rinfo->metric == RIP_METRIC_INFINITY || rinfo->external_metric == 0)
350 return NULL;
351 return yang_data_new_uint32(args->xpath, rinfo->external_metric);
352 }
353
354 /*
355 * XPath:
356 * /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/expire-time
357 */
358 struct yang_data *
359 ripd_instance_state_routes_route_nexthops_nexthop_expire_time_get_elem(
360 struct nb_cb_get_elem_args *args)
361 {
362 const struct rip_info *rinfo = get_rip_info(args->list_entry);
363 struct event *event;
364
365 if ((event = rinfo->t_timeout) == NULL)
366 event = rinfo->t_garbage_collect;
367 if (!event)
368 return NULL;
369
370 return yang_data_new_uint32(args->xpath,
371 event_timer_remain_second(event));
372 }
373
374 /*
375 * XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop
376 */
377 struct yang_data *ripd_instance_state_routes_route_next_hop_get_elem(
378 struct nb_cb_get_elem_args *args)
379 {
380 const struct route_node *rn = args->list_entry;
381 const struct rip_info *rinfo = listnode_head(rn->info);
382
383 switch (rinfo->nh.type) {
384 case NEXTHOP_TYPE_IPV4:
385 case NEXTHOP_TYPE_IPV4_IFINDEX:
386 return yang_data_new_ipv4(args->xpath, &rinfo->nh.gate.ipv4);
387 case NEXTHOP_TYPE_IFINDEX:
388 case NEXTHOP_TYPE_IPV6:
389 case NEXTHOP_TYPE_IPV6_IFINDEX:
390 case NEXTHOP_TYPE_BLACKHOLE:
391 return NULL;
392 }
393
394 assert(!"Reached end of function where we do not expect to reach");
395 }
396
397 /*
398 * XPath: /frr-ripd:ripd/instance/state/routes/route/interface
399 */
400 struct yang_data *ripd_instance_state_routes_route_interface_get_elem(
401 struct nb_cb_get_elem_args *args)
402 {
403 const struct route_node *rn = args->list_entry;
404 const struct rip_info *rinfo = listnode_head(rn->info);
405 const struct rip *rip = rip_info_get_instance(rinfo);
406
407 switch (rinfo->nh.type) {
408 case NEXTHOP_TYPE_IFINDEX:
409 case NEXTHOP_TYPE_IPV4_IFINDEX:
410 return yang_data_new_string(
411 args->xpath,
412 ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id));
413 case NEXTHOP_TYPE_IPV4:
414 case NEXTHOP_TYPE_IPV6:
415 case NEXTHOP_TYPE_IPV6_IFINDEX:
416 case NEXTHOP_TYPE_BLACKHOLE:
417 return NULL;
418 }
419
420 assert(!"Reached end of function where we do not expect to reach");
421 }
422
423 /*
424 * XPath: /frr-ripd:ripd/instance/state/routes/route/metric
425 */
426 struct yang_data *ripd_instance_state_routes_route_metric_get_elem(
427 struct nb_cb_get_elem_args *args)
428 {
429 const struct route_node *rn = args->list_entry;
430 const struct rip_info *rinfo = listnode_head(rn->info);
431
432 return yang_data_new_uint8(args->xpath, rinfo->metric);
433 }