]>
git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripng_nexthop.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2002 6WIND <vincent.jardin@6wind.com>
6 /* This file is required in order to support properly the RIPng nexthop
12 /* For struct udphdr. */
13 #include <netinet/udp.h>
23 #include "ripngd/ripngd.h"
24 #include "ripngd/ripng_debug.h"
25 #include "ripngd/ripng_nexthop.h"
27 DEFINE_MTYPE_STATIC(RIPNGD
, RIPNG_RTE_DATA
, "RIPng rte data");
31 struct ripng_rte_data
{
32 struct prefix_ipv6
*p
;
33 struct ripng_info
*rinfo
;
34 struct ripng_aggregate
*aggregate
;
37 void _ripng_rte_del(struct ripng_rte_data
*A
);
38 int _ripng_rte_cmp(struct ripng_rte_data
*A
, struct ripng_rte_data
*B
);
40 #define METRIC_OUT(a) \
41 ((a)->rinfo ? (a)->rinfo->metric_out : (a)->aggregate->metric_out)
42 #define NEXTHOP_OUT_PTR(a) \
43 ((a)->rinfo ? &((a)->rinfo->nexthop_out) \
44 : &((a)->aggregate->nexthop_out))
45 #define TAG_OUT(a) ((a)->rinfo ? (a)->rinfo->tag_out : (a)->aggregate->tag_out)
47 struct list
*ripng_rte_new(void)
52 rte
->cmp
= (int (*)(void *, void *))_ripng_rte_cmp
;
53 rte
->del
= (void (*)(void *))_ripng_rte_del
;
58 void ripng_rte_free(struct list
*ripng_rte_list
)
60 list_delete(&ripng_rte_list
);
64 void _ripng_rte_del(struct ripng_rte_data
*A
)
66 XFREE(MTYPE_RIPNG_RTE_DATA
, A
);
74 int _ripng_rte_cmp(struct ripng_rte_data
*A
, struct ripng_rte_data
*B
)
76 return addr6_cmp(NEXTHOP_OUT_PTR(A
), NEXTHOP_OUT_PTR(B
));
79 /* Add routing table entry */
80 void ripng_rte_add(struct list
*ripng_rte_list
, struct prefix_ipv6
*p
,
81 struct ripng_info
*rinfo
, struct ripng_aggregate
*aggregate
)
84 struct ripng_rte_data
*data
;
86 /* At least one should not be null */
87 assert(!rinfo
|| !aggregate
);
89 data
= XMALLOC(MTYPE_RIPNG_RTE_DATA
, sizeof(*data
));
92 data
->aggregate
= aggregate
;
94 listnode_add_sort(ripng_rte_list
, data
);
97 /* Send the RTE with the nexthop support
99 void ripng_rte_send(struct list
*ripng_rte_list
, struct interface
*ifp
,
100 struct sockaddr_in6
*to
)
102 struct ripng_interface
*ri
= ifp
->info
;
103 struct ripng
*ripng
= ri
->ripng
;
104 struct ripng_rte_data
*data
;
105 struct listnode
*node
, *nnode
;
107 struct in6_addr last_nexthop
;
108 struct in6_addr myself_nexthop
;
116 /* Most of the time, there is no nexthop */
117 memset(&last_nexthop
, 0, sizeof(last_nexthop
));
119 /* Use myself_nexthop if the nexthop is not a link-local address,
121 * we remain a right path without beeing the optimal one.
123 memset(&myself_nexthop
, 0, sizeof(myself_nexthop
));
125 /* Output stream get from ripng structre. XXX this should be
126 interface structure. */
129 /* Reset stream and RTE counter. */
137 rtemax
= (MIN(mtu
, RIPNG_MAX_PACKET_SIZE
) - IPV6_HDRLEN
138 - sizeof(struct udphdr
) - sizeof(struct ripng_packet
)
139 + sizeof(struct rte
))
140 / sizeof(struct rte
);
142 for (ALL_LIST_ELEMENTS(ripng_rte_list
, node
, nnode
, data
)) {
143 /* (2.1) Next hop support */
144 if (!IPV6_ADDR_SAME(&last_nexthop
, NEXTHOP_OUT_PTR(data
))) {
146 /* A nexthop entry should be at least followed by 1 RTE
148 if (num
== (rtemax
- 1)) {
149 ret
= ripng_send_packet((caddr_t
)STREAM_DATA(s
),
150 stream_get_endp(s
), to
,
153 if (ret
>= 0 && IS_RIPNG_DEBUG_SEND
)
155 (struct ripng_packet
*)
157 stream_get_endp(s
), "SEND");
162 /* Add the nexthop (2.1) */
164 /* If the received next hop address is not a link-local
166 * it should be treated as 0:0:0:0:0:0:0:0.
168 if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data
)))
169 last_nexthop
= myself_nexthop
;
171 last_nexthop
= *NEXTHOP_OUT_PTR(data
);
173 num
= ripng_write_rte(num
, s
, NULL
, &last_nexthop
, 0,
174 RIPNG_METRIC_NEXTHOP
);
176 /* Rewrite the nexthop for each new packet */
178 && !IPV6_ADDR_SAME(&last_nexthop
, &myself_nexthop
))
179 num
= ripng_write_rte(num
, s
, NULL
,
181 RIPNG_METRIC_NEXTHOP
);
183 num
= ripng_write_rte(num
, s
, data
->p
, NULL
, TAG_OUT(data
),
187 ret
= ripng_send_packet((caddr_t
)STREAM_DATA(s
),
188 stream_get_endp(s
), to
, ifp
);
190 if (ret
>= 0 && IS_RIPNG_DEBUG_SEND
)
192 (struct ripng_packet
*)STREAM_DATA(s
),
193 stream_get_endp(s
), "SEND");
199 /* If unwritten RTE exist, flush it. */
201 ret
= ripng_send_packet((caddr_t
)STREAM_DATA(s
),
202 stream_get_endp(s
), to
, ifp
);
204 if (ret
>= 0 && IS_RIPNG_DEBUG_SEND
)
205 ripng_packet_dump((struct ripng_packet
*)STREAM_DATA(s
),
206 stream_get_endp(s
), "SEND");