]>
git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_nexthop.c
2 * Copyright (C) 2002 6WIND <vincent.jardin@6wind.com>
4 * This file is part of GNU Zebra.
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
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.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 /* This file is required in order to support properly the RIPng nexthop
28 /* For struct udphdr. */
29 #include <netinet/udp.h>
39 #include "ripngd/ripngd.h"
40 #include "ripngd/ripng_debug.h"
41 #include "ripngd/ripng_nexthop.h"
45 #define min(a, b) ((a) < (b) ? (a) : (b))
47 struct ripng_rte_data
{
48 struct prefix_ipv6
*p
;
49 struct ripng_info
*rinfo
;
50 struct ripng_aggregate
*aggregate
;
53 void _ripng_rte_del(struct ripng_rte_data
*A
);
54 int _ripng_rte_cmp(struct ripng_rte_data
*A
, struct ripng_rte_data
*B
);
56 #define METRIC_OUT(a) \
57 (a->rinfo ? a->rinfo->metric_out : a->aggregate->metric_out)
58 #define NEXTHOP_OUT(a) \
59 (a->rinfo ? a->rinfo->nexthop_out : a->aggregate->nexthop_out)
61 (a->rinfo ? a->rinfo->tag_out : a->aggregate->tag_out)
68 rte
->cmp
= (int (*)(void *, void *)) _ripng_rte_cmp
;
69 rte
->del
= (void (*)(void *)) _ripng_rte_del
;
75 ripng_rte_free(struct list
*ripng_rte_list
) {
76 list_delete(ripng_rte_list
);
81 _ripng_rte_del(struct ripng_rte_data
*A
) {
82 XFREE(MTYPE_RIPNG_RTE_DATA
, A
);
91 _ripng_rte_cmp(struct ripng_rte_data
*A
, struct ripng_rte_data
*B
) {
92 return addr6_cmp(&NEXTHOP_OUT(A
), &NEXTHOP_OUT(B
));
95 /* Add routing table entry */
97 ripng_rte_add(struct list
*ripng_rte_list
, struct prefix_ipv6
*p
,
98 struct ripng_info
*rinfo
, struct ripng_aggregate
*aggregate
) {
100 struct ripng_rte_data
*data
;
102 /* At least one should not be null */
103 assert(!rinfo
|| !aggregate
);
105 data
= XMALLOC(MTYPE_RIPNG_RTE_DATA
, sizeof(*data
));
108 data
->aggregate
= aggregate
;
110 listnode_add_sort(ripng_rte_list
, data
);
113 /* Send the RTE with the nexthop support
116 ripng_rte_send(struct list
*ripng_rte_list
, struct interface
*ifp
,
117 struct sockaddr_in6
*to
) {
119 struct ripng_rte_data
*data
;
120 struct listnode
* nn
;
122 struct in6_addr last_nexthop
;
123 struct in6_addr myself_nexthop
;
131 /* Most of the time, there is no nexthop */
132 memset(&last_nexthop
, 0, sizeof(last_nexthop
));
134 /* Use myself_nexthop if the nexthop is not a link-local address, because
135 * we remain a right path without beeing the optimal one.
137 memset(&myself_nexthop
, 0, sizeof(myself_nexthop
));
139 /* Output stream get from ripng structre. XXX this should be
140 interface structure. */
143 /* Reset stream and RTE counter. */
151 rtemax
= (min (mtu
, RIPNG_MAX_PACKET_SIZE
) -
153 sizeof (struct udphdr
) -
154 sizeof (struct ripng_packet
) +
155 sizeof (struct rte
)) / sizeof (struct rte
);
157 LIST_LOOP(ripng_rte_list
, data
, nn
) {
159 /* (2.1) Next hop support */
160 if (!IPV6_ADDR_SAME(&last_nexthop
, &NEXTHOP_OUT(data
))) {
162 /* A nexthop entry should be at least followed by 1 RTE */
163 if (num
== (rtemax
-1)) {
164 ret
= ripng_send_packet (STREAM_DATA (s
), stream_get_endp (s
),
167 if (ret
>= 0 && IS_RIPNG_DEBUG_SEND
)
168 ripng_packet_dump((struct ripng_packet
*)STREAM_DATA (s
),
169 stream_get_endp(s
), "SEND");
174 /* Add the nexthop (2.1) */
176 /* If the received next hop address is not a link-local address,
177 * it should be treated as 0:0:0:0:0:0:0:0.
179 if (!IN6_IS_ADDR_LINKLOCAL(&NEXTHOP_OUT(data
)))
180 last_nexthop
= myself_nexthop
;
182 last_nexthop
= NEXTHOP_OUT(data
);
184 num
= ripng_write_rte(num
, s
, NULL
, &last_nexthop
, 0, RIPNG_METRIC_NEXTHOP
);
186 /* Rewrite the nexthop for each new packet */
187 if ((num
== 0) && !IPV6_ADDR_SAME(&last_nexthop
, &myself_nexthop
))
188 num
= ripng_write_rte(num
, s
, NULL
, &last_nexthop
, 0, RIPNG_METRIC_NEXTHOP
);
190 num
= ripng_write_rte(num
, s
, data
->p
, NULL
,
191 TAG_OUT(data
), METRIC_OUT(data
));
194 ret
= ripng_send_packet (STREAM_DATA (s
), stream_get_endp (s
),
197 if (ret
>= 0 && IS_RIPNG_DEBUG_SEND
)
198 ripng_packet_dump((struct ripng_packet
*)STREAM_DATA (s
),
199 stream_get_endp(s
), "SEND");
205 /* If unwritten RTE exist, flush it. */
207 ret
= ripng_send_packet (STREAM_DATA (s
), stream_get_endp (s
),
210 if (ret
>= 0 && IS_RIPNG_DEBUG_SEND
)
211 ripng_packet_dump ((struct ripng_packet
*)STREAM_DATA (s
),
212 stream_get_endp (s
), "SEND");