]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_peer.c
Merge pull request #12780 from opensourcerouting/spdx-license-id
[mirror_frr.git] / ripngd / ripng_peer.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* RIPng peer support
3 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
4 */
5
6 /* RIPng support added by Vincent Jardin <vincent.jardin@6wind.com>
7 * Copyright (C) 2002 6WIND
8 */
9
10 #include <zebra.h>
11
12 #include "if.h"
13 #include "prefix.h"
14 #include "command.h"
15 #include "linklist.h"
16 #include "thread.h"
17 #include "memory.h"
18
19 #include "ripngd/ripngd.h"
20 #include "ripngd/ripng_nexthop.h"
21
22 DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_PEER, "RIPng peer");
23
24 static struct ripng_peer *ripng_peer_new(void)
25 {
26 return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer));
27 }
28
29 static void ripng_peer_free(struct ripng_peer *peer)
30 {
31 THREAD_OFF(peer->t_timeout);
32 XFREE(MTYPE_RIPNG_PEER, peer);
33 }
34
35 struct ripng_peer *ripng_peer_lookup(struct ripng *ripng, struct in6_addr *addr)
36 {
37 struct ripng_peer *peer;
38 struct listnode *node, *nnode;
39
40 for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
41 if (IPV6_ADDR_SAME(&peer->addr, addr))
42 return peer;
43 }
44 return NULL;
45 }
46
47 struct ripng_peer *ripng_peer_lookup_next(struct ripng *ripng,
48 struct in6_addr *addr)
49 {
50 struct ripng_peer *peer;
51 struct listnode *node, *nnode;
52
53 for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
54 if (addr6_cmp(&peer->addr, addr) > 0)
55 return peer;
56 }
57 return NULL;
58 }
59
60 /* RIPng peer is timeout.
61 * Garbage collector.
62 **/
63 static void ripng_peer_timeout(struct thread *t)
64 {
65 struct ripng_peer *peer;
66
67 peer = THREAD_ARG(t);
68 listnode_delete(peer->ripng->peer_list, peer);
69 ripng_peer_free(peer);
70 }
71
72 /* Get RIPng peer. At the same time update timeout thread. */
73 static struct ripng_peer *ripng_peer_get(struct ripng *ripng,
74 struct in6_addr *addr)
75 {
76 struct ripng_peer *peer;
77
78 peer = ripng_peer_lookup(ripng, addr);
79
80 if (peer) {
81 THREAD_OFF(peer->t_timeout);
82 } else {
83 peer = ripng_peer_new();
84 peer->ripng = ripng;
85 peer->addr = *addr;
86 listnode_add_sort(ripng->peer_list, peer);
87 }
88
89 /* Update timeout thread. */
90 thread_add_timer(master, ripng_peer_timeout, peer,
91 RIPNG_PEER_TIMER_DEFAULT, &peer->t_timeout);
92
93 /* Last update time set. */
94 time(&peer->uptime);
95
96 return peer;
97 }
98
99 void ripng_peer_update(struct ripng *ripng, struct sockaddr_in6 *from,
100 uint8_t version)
101 {
102 struct ripng_peer *peer;
103 peer = ripng_peer_get(ripng, &from->sin6_addr);
104 peer->version = version;
105 }
106
107 void ripng_peer_bad_route(struct ripng *ripng, struct sockaddr_in6 *from)
108 {
109 struct ripng_peer *peer;
110 peer = ripng_peer_get(ripng, &from->sin6_addr);
111 peer->recv_badroutes++;
112 }
113
114 void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from)
115 {
116 struct ripng_peer *peer;
117 peer = ripng_peer_get(ripng, &from->sin6_addr);
118 peer->recv_badpackets++;
119 }
120
121 /* Display peer uptime. */
122 static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len)
123 {
124 time_t uptime;
125
126 /* If there is no connection has been done before print `never'. */
127 if (peer->uptime == 0) {
128 snprintf(buf, len, "never ");
129 return buf;
130 }
131
132 /* Get current time. */
133 uptime = time(NULL);
134 uptime -= peer->uptime;
135
136 frrtime_to_interval(uptime, buf, len);
137
138 return buf;
139 }
140
141 void ripng_peer_display(struct vty *vty, struct ripng *ripng)
142 {
143 struct ripng_peer *peer;
144 struct listnode *node, *nnode;
145 #define RIPNG_UPTIME_LEN 25
146 char timebuf[RIPNG_UPTIME_LEN];
147
148 for (ALL_LIST_ELEMENTS(ripng->peer_list, node, nnode, peer)) {
149 vty_out(vty, " %pI6 \n%14s %10d %10d %10d %s\n",
150 &peer->addr, " ", peer->recv_badpackets,
151 peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT,
152 ripng_peer_uptime(peer, timebuf, RIPNG_UPTIME_LEN));
153 }
154 }
155
156 int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2)
157 {
158 return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr));
159 }
160
161 void ripng_peer_list_del(void *arg)
162 {
163 ripng_peer_free(arg);
164 }