]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_nexthop.c
*: require semicolon after DEFINE_MTYPE & co
[mirror_frr.git] / ripngd / ripng_nexthop.c
CommitLineData
a94434b6 1/* RIPngd Zebra
2 * Copyright (C) 2002 6WIND <vincent.jardin@6wind.com>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
a94434b6 19 */
20
21/* This file is required in order to support properly the RIPng nexthop
22 * feature.
23 */
24
25#include <zebra.h>
26
27/* For struct udphdr. */
28#include <netinet/udp.h>
29
30#include "linklist.h"
31#include "stream.h"
32#include "log.h"
33#include "memory.h"
34#include "vty.h"
35#include "if.h"
36#include "prefix.h"
37
38#include "ripngd/ripngd.h"
39#include "ripngd/ripng_debug.h"
40#include "ripngd/ripng_nexthop.h"
41
bf8d3d6a 42DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_RTE_DATA, "RIPng rte data");
b3a7e30d 43
a94434b6 44#define DEBUG 1
45
46#define min(a, b) ((a) < (b) ? (a) : (b))
47
48struct ripng_rte_data {
d62a17ae 49 struct prefix_ipv6 *p;
50 struct ripng_info *rinfo;
51 struct ripng_aggregate *aggregate;
a94434b6 52};
53
54void _ripng_rte_del(struct ripng_rte_data *A);
55int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B);
56
d62a17ae 57#define METRIC_OUT(a) \
58 ((a)->rinfo ? (a)->rinfo->metric_out : (a)->aggregate->metric_out)
59#define NEXTHOP_OUT_PTR(a) \
60 ((a)->rinfo ? &((a)->rinfo->nexthop_out) \
61 : &((a)->aggregate->nexthop_out))
62#define TAG_OUT(a) ((a)->rinfo ? (a)->rinfo->tag_out : (a)->aggregate->tag_out)
a94434b6 63
d62a17ae 64struct list *ripng_rte_new(void)
65{
66 struct list *rte;
a94434b6 67
d62a17ae 68 rte = list_new();
69 rte->cmp = (int (*)(void *, void *))_ripng_rte_cmp;
70 rte->del = (void (*)(void *))_ripng_rte_del;
a94434b6 71
d62a17ae 72 return rte;
a94434b6 73}
74
d62a17ae 75void ripng_rte_free(struct list *ripng_rte_list)
76{
6a154c88 77 list_delete(&ripng_rte_list);
a94434b6 78}
79
80/* Delete RTE */
d62a17ae 81void _ripng_rte_del(struct ripng_rte_data *A)
82{
83 XFREE(MTYPE_RIPNG_RTE_DATA, A);
a94434b6 84}
85
86/* Compare RTE:
87 * return + if A > B
88 * 0 if A = B
89 * - if A < B
90 */
d62a17ae 91int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B)
92{
93 return addr6_cmp(NEXTHOP_OUT_PTR(A), NEXTHOP_OUT_PTR(B));
a94434b6 94}
95
96/* Add routing table entry */
d62a17ae 97void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
98 struct ripng_info *rinfo, struct ripng_aggregate *aggregate)
99{
a94434b6 100
d62a17ae 101 struct ripng_rte_data *data;
a94434b6 102
d62a17ae 103 /* At least one should not be null */
104 assert(!rinfo || !aggregate);
a94434b6 105
d62a17ae 106 data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data));
107 data->p = p;
108 data->rinfo = rinfo;
109 data->aggregate = aggregate;
a94434b6 110
d62a17ae 111 listnode_add_sort(ripng_rte_list, data);
112}
a94434b6 113
114/* Send the RTE with the nexthop support
115 */
d62a17ae 116void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
117 struct sockaddr_in6 *to)
118{
5c84b9a5
RW
119 struct ripng_interface *ri = ifp->info;
120 struct ripng *ripng = ri->ripng;
d62a17ae 121 struct ripng_rte_data *data;
122 struct listnode *node, *nnode;
123
124 struct in6_addr last_nexthop;
125 struct in6_addr myself_nexthop;
126
127 struct stream *s;
128 int num;
129 int mtu;
130 int rtemax;
131 int ret;
132
133 /* Most of the time, there is no nexthop */
134 memset(&last_nexthop, 0, sizeof(last_nexthop));
135
136 /* Use myself_nexthop if the nexthop is not a link-local address,
137 * because
138 * we remain a right path without beeing the optimal one.
139 */
140 memset(&myself_nexthop, 0, sizeof(myself_nexthop));
141
142 /* Output stream get from ripng structre. XXX this should be
143 interface structure. */
144 s = ripng->obuf;
145
146 /* Reset stream and RTE counter. */
147 stream_reset(s);
148 num = 0;
149
150 mtu = ifp->mtu6;
151 if (mtu < 0)
152 mtu = IFMINMTU;
153
154 rtemax = (min(mtu, RIPNG_MAX_PACKET_SIZE) - IPV6_HDRLEN
155 - sizeof(struct udphdr) - sizeof(struct ripng_packet)
156 + sizeof(struct rte))
157 / sizeof(struct rte);
158
159 for (ALL_LIST_ELEMENTS(ripng_rte_list, node, nnode, data)) {
160 /* (2.1) Next hop support */
161 if (!IPV6_ADDR_SAME(&last_nexthop, NEXTHOP_OUT_PTR(data))) {
162
163 /* A nexthop entry should be at least followed by 1 RTE
164 */
165 if (num == (rtemax - 1)) {
166 ret = ripng_send_packet((caddr_t)STREAM_DATA(s),
167 stream_get_endp(s), to,
168 ifp);
169
170 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
171 ripng_packet_dump(
172 (struct ripng_packet *)
173 STREAM_DATA(s),
174 stream_get_endp(s), "SEND");
175 num = 0;
176 stream_reset(s);
177 }
178
179 /* Add the nexthop (2.1) */
180
181 /* If the received next hop address is not a link-local
182 * address,
183 * it should be treated as 0:0:0:0:0:0:0:0.
184 */
185 if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data)))
186 last_nexthop = myself_nexthop;
187 else
188 last_nexthop = *NEXTHOP_OUT_PTR(data);
189
190 num = ripng_write_rte(num, s, NULL, &last_nexthop, 0,
191 RIPNG_METRIC_NEXTHOP);
192 } else {
193 /* Rewrite the nexthop for each new packet */
194 if ((num == 0)
195 && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop))
196 num = ripng_write_rte(num, s, NULL,
197 &last_nexthop, 0,
198 RIPNG_METRIC_NEXTHOP);
199 }
200 num = ripng_write_rte(num, s, data->p, NULL, TAG_OUT(data),
201 METRIC_OUT(data));
202
203 if (num == rtemax) {
204 ret = ripng_send_packet((caddr_t)STREAM_DATA(s),
205 stream_get_endp(s), to, ifp);
206
207 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
208 ripng_packet_dump(
209 (struct ripng_packet *)STREAM_DATA(s),
210 stream_get_endp(s), "SEND");
211 num = 0;
212 stream_reset(s);
213 }
214 }
215
216 /* If unwritten RTE exist, flush it. */
217 if (num != 0) {
218 ret = ripng_send_packet((caddr_t)STREAM_DATA(s),
219 stream_get_endp(s), to, ifp);
220
221 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
222 ripng_packet_dump((struct ripng_packet *)STREAM_DATA(s),
223 stream_get_endp(s), "SEND");
224 stream_reset(s);
225 }
a94434b6 226}