]> git.proxmox.com Git - mirror_frr.git/blame - babeld/xroute.c
Merge pull request #12751 from Pdoijode/pdoijode/ospf-vrf-neighbor-detail-1
[mirror_frr.git] / babeld / xroute.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: MIT
ca10883e
DS
2/*
3Copyright (c) 2007, 2008 by Juliusz Chroboczek
4Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
ca10883e
DS
5*/
6
7#include <zebra.h>
8#include "if.h"
9#include "log.h"
10
11#include "babeld.h"
12#include "kernel.h"
13#include "neighbour.h"
14#include "message.h"
15#include "route.h"
16#include "xroute.h"
17#include "util.h"
18#include "babel_interface.h"
19
20static int xroute_add_new_route(unsigned char prefix[16], unsigned char plen,
21 unsigned short metric, unsigned int ifindex,
22 int proto, int send_updates);
23
24static struct xroute *xroutes;
25static int numxroutes = 0, maxxroutes = 0;
26
27/* Add redistributed route to Babel table. */
28int
74489921 29babel_route_add (struct zapi_route *api)
ca10883e
DS
30{
31 unsigned char uchar_prefix[16];
32
74489921
RW
33 switch (api->prefix.family) {
34 case AF_INET:
35 inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
36 debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra.");
37 xroute_add_new_route(uchar_prefix, api->prefix.prefixlen + 96,
38 api->metric, api->nexthops[0].ifindex, 0, 1);
39 break;
40 case AF_INET6:
41 in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
42 debugf(BABEL_DEBUG_ROUTE, "Adding new ipv6 route coming from Zebra.");
43 xroute_add_new_route(uchar_prefix, api->prefix.prefixlen,
44 api->metric, api->nexthops[0].ifindex, 0, 1);
45 break;
ca10883e 46 }
ca10883e 47
ca10883e
DS
48 return 0;
49}
50
51/* Remove redistributed route from Babel table. */
52int
74489921 53babel_route_delete (struct zapi_route *api)
ca10883e
DS
54{
55 unsigned char uchar_prefix[16];
56 struct xroute *xroute = NULL;
57
74489921
RW
58 switch (api->prefix.family) {
59 case AF_INET:
60 inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
61 xroute = find_xroute(uchar_prefix, api->prefix.prefixlen + 96);
62 if (xroute != NULL) {
63 debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
64 flush_xroute(xroute);
65 }
66 break;
67 case AF_INET6:
68 in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
69 xroute = find_xroute(uchar_prefix, api->prefix.prefixlen);
70 if (xroute != NULL) {
71 debugf(BABEL_DEBUG_ROUTE, "Removing ipv6 route (from zebra).");
72 flush_xroute(xroute);
73 }
74 break;
ca10883e 75 }
74489921 76
ca10883e
DS
77 return 0;
78}
79
80struct xroute *
81find_xroute(const unsigned char *prefix, unsigned char plen)
82{
83 int i;
84 for(i = 0; i < numxroutes; i++) {
85 if(xroutes[i].plen == plen &&
86 memcmp(xroutes[i].prefix, prefix, 16) == 0)
87 return &xroutes[i];
88 }
89 return NULL;
90}
91
92void
93flush_xroute(struct xroute *xroute)
94{
95 int i;
96
97 i = xroute - xroutes;
98 assert(i >= 0 && i < numxroutes);
99
100 if(i != numxroutes - 1)
101 memcpy(xroutes + i, xroutes + numxroutes - 1, sizeof(struct xroute));
102 numxroutes--;
103 VALGRIND_MAKE_MEM_UNDEFINED(xroutes + numxroutes, sizeof(struct xroute));
104
105 if(numxroutes == 0) {
106 free(xroutes);
107 xroutes = NULL;
108 maxxroutes = 0;
109 } else if(maxxroutes > 8 && numxroutes < maxxroutes / 4) {
110 struct xroute *new_xroutes;
111 int n = maxxroutes / 2;
112 new_xroutes = realloc(xroutes, n * sizeof(struct xroute));
113 if(new_xroutes == NULL)
114 return;
115 xroutes = new_xroutes;
116 maxxroutes = n;
117 }
118}
119
120static int
121add_xroute(unsigned char prefix[16], unsigned char plen,
122 unsigned short metric, unsigned int ifindex, int proto)
123{
124 struct xroute *xroute = find_xroute(prefix, plen);
125 if(xroute) {
126 if(xroute->metric <= metric)
127 return 0;
128 xroute->metric = metric;
129 return 1;
130 }
131
132 if(numxroutes >= maxxroutes) {
133 struct xroute *new_xroutes;
134 int n = maxxroutes < 1 ? 8 : 2 * maxxroutes;
135 new_xroutes = xroutes == NULL ?
136 malloc(n * sizeof(struct xroute)) :
137 realloc(xroutes, n * sizeof(struct xroute));
138 if(new_xroutes == NULL)
139 return -1;
140 maxxroutes = n;
141 xroutes = new_xroutes;
142 }
143
144 memcpy(xroutes[numxroutes].prefix, prefix, 16);
145 xroutes[numxroutes].plen = plen;
146 xroutes[numxroutes].metric = metric;
147 xroutes[numxroutes].ifindex = ifindex;
148 xroutes[numxroutes].proto = proto;
149 numxroutes++;
150 return 1;
151}
152
153/* Returns an overestimate of the number of xroutes. */
154int
4d762f26 155xroutes_estimate(void)
ca10883e
DS
156{
157 return numxroutes;
158}
159
160struct xroute_stream {
161 int index;
162};
163
164struct
165xroute_stream *
dd15627e 166xroute_stream(void)
ca10883e
DS
167{
168 struct xroute_stream *stream = malloc(sizeof(struct xroute_stream));
169 if(stream == NULL)
170 return NULL;
171
172 stream->index = 0;
173 return stream;
174}
175
176struct xroute *
177xroute_stream_next(struct xroute_stream *stream)
178{
179 if(stream->index < numxroutes)
180 return &xroutes[stream->index++];
181 else
182 return NULL;
183}
184
185void
186xroute_stream_done(struct xroute_stream *stream)
187{
188 free(stream);
189}
190
191/* add an xroute, verifying some conditions; return 0 if there is no changes */
192static int
193xroute_add_new_route(unsigned char prefix[16], unsigned char plen,
194 unsigned short metric, unsigned int ifindex,
195 int proto, int send_updates)
196{
197 int rc;
198 if(martian_prefix(prefix, plen))
199 return 0;
200 metric = redistribute_filter(prefix, plen, ifindex, proto);
201 if(metric < INFINITY) {
202 rc = add_xroute(prefix, plen, metric, ifindex, proto);
203 if(rc > 0) {
204 struct babel_route *route;
205 route = find_installed_route(prefix, plen);
206 if(route)
207 uninstall_route(route);
208 if(send_updates)
209 send_update(NULL, 0, prefix, plen);
210 return 1;
211 }
212 }
213 return 0;
214}