]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_nexthop.c
*: add indent control files
[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
42#define DEBUG 1
43
44#define min(a, b) ((a) < (b) ? (a) : (b))
45
46struct ripng_rte_data {
47 struct prefix_ipv6 *p;
48 struct ripng_info *rinfo;
49 struct ripng_aggregate *aggregate;
50};
51
52void _ripng_rte_del(struct ripng_rte_data *A);
53int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B);
54
55#define METRIC_OUT(a) \
fa40f658 56 ((a)->rinfo ? (a)->rinfo->metric_out : (a)->aggregate->metric_out)
57#define NEXTHOP_OUT_PTR(a) \
58 ((a)->rinfo ? &((a)->rinfo->nexthop_out) : &((a)->aggregate->nexthop_out))
a94434b6 59#define TAG_OUT(a) \
fa40f658 60 ((a)->rinfo ? (a)->rinfo->tag_out : (a)->aggregate->tag_out)
a94434b6 61
62struct list *
63ripng_rte_new(void) {
64 struct list *rte;
65
66 rte = list_new();
67 rte->cmp = (int (*)(void *, void *)) _ripng_rte_cmp;
68 rte->del = (void (*)(void *)) _ripng_rte_del;
69
70 return rte;
71}
72
73void
74ripng_rte_free(struct list *ripng_rte_list) {
75 list_delete(ripng_rte_list);
76}
77
78/* Delete RTE */
79void
80_ripng_rte_del(struct ripng_rte_data *A) {
81 XFREE(MTYPE_RIPNG_RTE_DATA, A);
82}
83
84/* Compare RTE:
85 * return + if A > B
86 * 0 if A = B
87 * - if A < B
88 */
89int
90_ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B) {
fa40f658 91 return addr6_cmp(NEXTHOP_OUT_PTR(A), NEXTHOP_OUT_PTR(B));
a94434b6 92}
93
94/* Add routing table entry */
95void
96ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
97 struct ripng_info *rinfo, struct ripng_aggregate *aggregate) {
98
99 struct ripng_rte_data *data;
100
101 /* At least one should not be null */
102 assert(!rinfo || !aggregate);
103
104 data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data));
105 data->p = p;
106 data->rinfo = rinfo;
107 data->aggregate = aggregate;
108
109 listnode_add_sort(ripng_rte_list, data);
110}
111
112/* Send the RTE with the nexthop support
113 */
114void
115ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
116 struct sockaddr_in6 *to) {
117
118 struct ripng_rte_data *data;
1eb8ef25 119 struct listnode *node, *nnode;
a94434b6 120
121 struct in6_addr last_nexthop;
122 struct in6_addr myself_nexthop;
123
124 struct stream *s;
125 int num;
126 int mtu;
127 int rtemax;
128 int ret;
129
130 /* Most of the time, there is no nexthop */
131 memset(&last_nexthop, 0, sizeof(last_nexthop));
132
133 /* Use myself_nexthop if the nexthop is not a link-local address, because
134 * we remain a right path without beeing the optimal one.
135 */
136 memset(&myself_nexthop, 0, sizeof(myself_nexthop));
137
138 /* Output stream get from ripng structre. XXX this should be
139 interface structure. */
140 s = ripng->obuf;
141
142 /* Reset stream and RTE counter. */
143 stream_reset (s);
144 num = 0;
145
1203e1c0 146 mtu = ifp->mtu6;
a94434b6 147 if (mtu < 0)
148 mtu = IFMINMTU;
149
150 rtemax = (min (mtu, RIPNG_MAX_PACKET_SIZE) -
151 IPV6_HDRLEN -
152 sizeof (struct udphdr) -
153 sizeof (struct ripng_packet) +
154 sizeof (struct rte)) / sizeof (struct rte);
155
1eb8ef25 156 for (ALL_LIST_ELEMENTS (ripng_rte_list, node, nnode, data)) {
a94434b6 157 /* (2.1) Next hop support */
fa40f658 158 if (!IPV6_ADDR_SAME(&last_nexthop, NEXTHOP_OUT_PTR(data))) {
a94434b6 159
160 /* A nexthop entry should be at least followed by 1 RTE */
161 if (num == (rtemax-1)) {
c9e52be3 162 ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
a94434b6 163 to, ifp);
164
165 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
166 ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
167 stream_get_endp(s), "SEND");
168 num = 0;
169 stream_reset (s);
170 }
171
172 /* Add the nexthop (2.1) */
173
174 /* If the received next hop address is not a link-local address,
175 * it should be treated as 0:0:0:0:0:0:0:0.
176 */
fa40f658 177 if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data)))
a94434b6 178 last_nexthop = myself_nexthop;
179 else
fa40f658 180 last_nexthop = *NEXTHOP_OUT_PTR(data);
a94434b6 181
182 num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
183 } else {
184 /* Rewrite the nexthop for each new packet */
185 if ((num == 0) && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop))
186 num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
187 }
188 num = ripng_write_rte(num, s, data->p, NULL,
189 TAG_OUT(data), METRIC_OUT(data));
190
191 if (num == rtemax) {
c9e52be3 192 ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
a94434b6 193 to, ifp);
194
195 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
196 ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
197 stream_get_endp(s), "SEND");
198 num = 0;
199 stream_reset (s);
200 }
201 }
202
203 /* If unwritten RTE exist, flush it. */
204 if (num != 0) {
c9e52be3 205 ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
a94434b6 206 to, ifp);
207
208 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
209 ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),
210 stream_get_endp (s), "SEND");
a94434b6 211 stream_reset (s);
212 }
213}