1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
16 #include "ripd/ripd.h"
17 #include "ripd/rip_bfd.h"
19 DEFINE_MTYPE_STATIC(RIPD
, RIP_PEER
, "RIP peer");
21 static struct rip_peer
*rip_peer_new(void)
23 return XCALLOC(MTYPE_RIP_PEER
, sizeof(struct rip_peer
));
26 void rip_peer_free(struct rip_peer
*peer
)
28 bfd_sess_free(&peer
->bfd_session
);
29 EVENT_OFF(peer
->t_timeout
);
30 XFREE(MTYPE_RIP_PEER
, peer
);
33 struct rip_peer
*rip_peer_lookup(struct rip
*rip
, struct in_addr
*addr
)
35 struct rip_peer
*peer
;
36 struct listnode
*node
, *nnode
;
38 for (ALL_LIST_ELEMENTS(rip
->peer_list
, node
, nnode
, peer
)) {
39 if (IPV4_ADDR_SAME(&peer
->addr
, addr
))
45 struct rip_peer
*rip_peer_lookup_next(struct rip
*rip
, struct in_addr
*addr
)
47 struct rip_peer
*peer
;
48 struct listnode
*node
, *nnode
;
50 for (ALL_LIST_ELEMENTS(rip
->peer_list
, node
, nnode
, peer
)) {
51 if (htonl(peer
->addr
.s_addr
) > htonl(addr
->s_addr
))
57 /* RIP peer is timeout. */
58 static void rip_peer_timeout(struct event
*t
)
60 struct rip_peer
*peer
;
63 listnode_delete(peer
->rip
->peer_list
, peer
);
67 /* Get RIP peer. At the same time update timeout thread. */
68 static struct rip_peer
*rip_peer_get(struct rip
*rip
, struct rip_interface
*ri
,
71 struct rip_peer
*peer
;
73 peer
= rip_peer_lookup(rip
, addr
);
76 EVENT_OFF(peer
->t_timeout
);
78 peer
= rip_peer_new();
82 rip_bfd_session_update(peer
);
83 listnode_add_sort(rip
->peer_list
, peer
);
86 /* Update timeout thread. */
87 event_add_timer(master
, rip_peer_timeout
, peer
, RIP_PEER_TIMER_DEFAULT
,
90 /* Last update time set. */
96 void rip_peer_update(struct rip
*rip
, struct rip_interface
*ri
,
97 struct sockaddr_in
*from
, uint8_t version
)
99 struct rip_peer
*peer
;
100 peer
= rip_peer_get(rip
, ri
, &from
->sin_addr
);
101 peer
->version
= version
;
104 void rip_peer_bad_route(struct rip
*rip
, struct rip_interface
*ri
,
105 struct sockaddr_in
*from
)
107 struct rip_peer
*peer
;
108 peer
= rip_peer_get(rip
, ri
, &from
->sin_addr
);
109 peer
->recv_badroutes
++;
112 void rip_peer_bad_packet(struct rip
*rip
, struct rip_interface
*ri
,
113 struct sockaddr_in
*from
)
115 struct rip_peer
*peer
;
116 peer
= rip_peer_get(rip
, ri
, &from
->sin_addr
);
117 peer
->recv_badpackets
++;
120 /* Display peer uptime. */
121 static char *rip_peer_uptime(struct rip_peer
*peer
, char *buf
, size_t len
)
125 /* If there is no connection has been done before print `never'. */
126 if (peer
->uptime
== 0) {
127 snprintf(buf
, len
, "never ");
131 /* Get current time. */
133 uptime
-= peer
->uptime
;
135 frrtime_to_interval(uptime
, buf
, len
);
140 void rip_peer_display(struct vty
*vty
, struct rip
*rip
)
142 struct rip_peer
*peer
;
143 struct listnode
*node
, *nnode
;
144 #define RIP_UPTIME_LEN 25
145 char timebuf
[RIP_UPTIME_LEN
];
147 for (ALL_LIST_ELEMENTS(rip
->peer_list
, node
, nnode
, peer
)) {
148 vty_out(vty
, " %-17pI4 %9d %9d %9d %11s\n",
149 &peer
->addr
, peer
->recv_badpackets
,
150 peer
->recv_badroutes
, ZEBRA_RIP_DISTANCE_DEFAULT
,
151 rip_peer_uptime(peer
, timebuf
, RIP_UPTIME_LEN
));
155 int rip_peer_list_cmp(struct rip_peer
*p1
, struct rip_peer
*p2
)
157 if (p2
->addr
.s_addr
== p1
->addr
.s_addr
)
160 return (htonl(p1
->addr
.s_addr
) < htonl(p2
->addr
.s_addr
)) ? -1 : 1;
163 void rip_peer_list_del(void *arg
)
168 void rip_peer_delete_routes(const struct rip_peer
*peer
)
170 struct route_node
*route_node
;
172 for (route_node
= route_top(peer
->rip
->table
); route_node
;
173 route_node
= route_next(route_node
)) {
174 struct rip_info
*route_entry
;
175 struct listnode
*listnode
;
176 struct listnode
*listnode_next
;
179 list
= route_node
->info
;
183 for (ALL_LIST_ELEMENTS(list
, listnode
, listnode_next
,
185 if (!rip_route_rte(route_entry
))
187 if (route_entry
->from
.s_addr
!= peer
->addr
.s_addr
)
190 if (listcount(list
) == 1) {
191 EVENT_OFF(route_entry
->t_timeout
);
192 EVENT_OFF(route_entry
->t_garbage_collect
);
193 listnode_delete(list
, route_entry
);
194 if (list_isempty(list
)) {
195 list_delete((struct list
**)&route_node
197 route_unlock_node(route_node
);
199 rip_info_free(route_entry
);
201 /* Signal the output process to trigger an
202 * update (see section 2.5). */
203 rip_event(peer
->rip
, RIP_TRIGGERED_UPDATE
, 0);
205 rip_ecmp_delete(peer
->rip
, route_entry
);