]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_asbr.c
Merge pull request #549 from qlyoung/fix-poll-eof
[mirror_frr.git] / ospfd / ospf_asbr.c
1 /*
2 * OSPF AS Boundary Router functions.
3 * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <zebra.h>
23
24 #include "thread.h"
25 #include "memory.h"
26 #include "linklist.h"
27 #include "prefix.h"
28 #include "if.h"
29 #include "table.h"
30 #include "vty.h"
31 #include "filter.h"
32 #include "log.h"
33
34 #include "ospfd/ospfd.h"
35 #include "ospfd/ospf_interface.h"
36 #include "ospfd/ospf_asbr.h"
37 #include "ospfd/ospf_lsa.h"
38 #include "ospfd/ospf_lsdb.h"
39 #include "ospfd/ospf_neighbor.h"
40 #include "ospfd/ospf_spf.h"
41 #include "ospfd/ospf_flood.h"
42 #include "ospfd/ospf_route.h"
43 #include "ospfd/ospf_zebra.h"
44 #include "ospfd/ospf_dump.h"
45
46
47 /* Remove external route. */
48 void
49 ospf_external_route_remove (struct ospf *ospf, struct prefix_ipv4 *p)
50 {
51 struct route_node *rn;
52 struct ospf_route *or;
53
54 rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p);
55 if (rn)
56 if ((or = rn->info))
57 {
58 zlog_info ("Route[%s/%d]: external path deleted",
59 inet_ntoa (p->prefix), p->prefixlen);
60
61 /* Remove route from zebra. */
62 if (or->type == OSPF_DESTINATION_NETWORK)
63 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
64
65 ospf_route_free (or);
66 rn->info = NULL;
67
68 route_unlock_node (rn);
69 route_unlock_node (rn);
70 return;
71 }
72
73 zlog_info ("Route[%s/%d]: no such external path",
74 inet_ntoa (p->prefix), p->prefixlen);
75 }
76
77 /* Lookup external route. */
78 struct ospf_route *
79 ospf_external_route_lookup (struct ospf *ospf,
80 struct prefix_ipv4 *p)
81 {
82 struct route_node *rn;
83
84 rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p);
85 if (rn)
86 {
87 route_unlock_node (rn);
88 if (rn->info)
89 return rn->info;
90 }
91
92 zlog_warn ("Route[%s/%d]: lookup, no such prefix",
93 inet_ntoa (p->prefix), p->prefixlen);
94
95 return NULL;
96 }
97
98
99 /* Add an External info for AS-external-LSA. */
100 struct external_info *
101 ospf_external_info_new (u_char type, u_short instance)
102 {
103 struct external_info *new;
104
105 new = (struct external_info *)
106 XCALLOC (MTYPE_OSPF_EXTERNAL_INFO, sizeof (struct external_info));
107 new->type = type;
108 new->instance = instance;
109
110 ospf_reset_route_map_set_values (&new->route_map_set);
111 return new;
112 }
113
114 static void
115 ospf_external_info_free (struct external_info *ei)
116 {
117 XFREE (MTYPE_OSPF_EXTERNAL_INFO, ei);
118 }
119
120 void
121 ospf_reset_route_map_set_values (struct route_map_set_values *values)
122 {
123 values->metric = -1;
124 values->metric_type = -1;
125 }
126
127 int
128 ospf_route_map_set_compare (struct route_map_set_values *values1,
129 struct route_map_set_values *values2)
130 {
131 return values1->metric == values2->metric &&
132 values1->metric_type == values2->metric_type;
133 }
134
135 /* Add an External info for AS-external-LSA. */
136 struct external_info *
137 ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p,
138 ifindex_t ifindex, struct in_addr nexthop,
139 route_tag_t tag)
140 {
141 struct external_info *new;
142 struct route_node *rn;
143 struct ospf_external *ext;
144 char inetbuf[INET6_BUFSIZ];
145
146 ext = ospf_external_lookup(type, instance);
147 if (!ext)
148 ext = ospf_external_add(type, instance);
149
150 rn = route_node_get (EXTERNAL_INFO (ext), (struct prefix *) &p);
151 /* If old info exists, -- discard new one or overwrite with new one? */
152 if (rn)
153 if (rn->info)
154 {
155 new = rn->info;
156 if ((new->ifindex == ifindex) &&
157 (new->nexthop.s_addr == nexthop.s_addr) && (new->tag == tag))
158 {
159 route_unlock_node(rn);
160 return NULL; /* NULL => no LSA to refresh */
161 }
162
163 inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, INET6_BUFSIZ);
164 zlog_warn ("Redistribute[%s][%d]: %s/%d discarding old info with NH %s.",
165 ospf_redist_string(type), instance,
166 inet_ntoa (p.prefix), p.prefixlen, inetbuf);
167 XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
168 rn->info = NULL;
169 }
170
171 /* Create new External info instance. */
172 new = ospf_external_info_new (type, instance);
173 new->p = p;
174 new->ifindex = ifindex;
175 new->nexthop = nexthop;
176 new->tag = tag;
177
178 /* we don't unlock rn from the get() because we're attaching the info */
179 if (rn)
180 rn->info = new;
181
182 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
183 {
184 inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, INET6_BUFSIZ);
185 zlog_debug ("Redistribute[%s]: %s/%d external info created, with NH %s",
186 ospf_redist_string(type),
187 inet_ntoa (p.prefix), p.prefixlen, inetbuf);
188 }
189 return new;
190 }
191
192 void
193 ospf_external_info_delete (u_char type, u_short instance, struct prefix_ipv4 p)
194 {
195 struct route_node *rn;
196 struct ospf_external *ext;
197
198 ext = ospf_external_lookup(type, instance);
199 if (!ext)
200 return;
201
202 rn = route_node_lookup (EXTERNAL_INFO (ext), (struct prefix *) &p);
203 if (rn)
204 {
205 ospf_external_info_free (rn->info);
206 rn->info = NULL;
207 route_unlock_node (rn);
208 route_unlock_node (rn);
209 }
210 }
211
212 struct external_info *
213 ospf_external_info_lookup (u_char type, u_short instance, struct prefix_ipv4 *p)
214 {
215 struct route_node *rn;
216 struct ospf_external *ext;
217
218 ext = ospf_external_lookup(type, instance);
219 if (!ext)
220 return NULL;
221
222 rn = route_node_lookup (EXTERNAL_INFO (ext), (struct prefix *) p);
223 if (rn)
224 {
225 route_unlock_node (rn);
226 if (rn->info)
227 return rn->info;
228 }
229
230 return NULL;
231 }
232
233 struct ospf_lsa *
234 ospf_external_info_find_lsa (struct ospf *ospf,
235 struct prefix_ipv4 *p)
236 {
237 struct ospf_lsa *lsa;
238 struct as_external_lsa *al;
239 struct in_addr mask, id;
240
241 lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA,
242 p->prefix, ospf->router_id);
243
244 if (!lsa)
245 return NULL;
246
247 al = (struct as_external_lsa *) lsa->data;
248
249 masklen2ip (p->prefixlen, &mask);
250
251 if (mask.s_addr != al->mask.s_addr)
252 {
253 id.s_addr = p->prefix.s_addr | (~mask.s_addr);
254 lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA,
255 id, ospf->router_id);
256 if (!lsa)
257 return NULL;
258 }
259
260 return lsa;
261 }
262
263
264 /* Update ASBR status. */
265 void
266 ospf_asbr_status_update (struct ospf *ospf, u_char status)
267 {
268 zlog_info ("ASBR[Status:%d]: Update", status);
269
270 /* ASBR on. */
271 if (status)
272 {
273 /* Already ASBR. */
274 if (IS_OSPF_ASBR (ospf))
275 {
276 zlog_info ("ASBR[Status:%d]: Already ASBR", status);
277 return;
278 }
279 SET_FLAG (ospf->flags, OSPF_FLAG_ASBR);
280 }
281 else
282 {
283 /* Already non ASBR. */
284 if (! IS_OSPF_ASBR (ospf))
285 {
286 zlog_info ("ASBR[Status:%d]: Already non ASBR", status);
287 return;
288 }
289 UNSET_FLAG (ospf->flags, OSPF_FLAG_ASBR);
290 }
291
292 /* Transition from/to status ASBR, schedule timer. */
293 ospf_spf_calculate_schedule (ospf, SPF_FLAG_ASBR_STATUS_CHANGE);
294 ospf_router_lsa_update (ospf);
295 }
296
297 void
298 ospf_redistribute_withdraw (struct ospf *ospf, u_char type, u_short instance)
299 {
300 struct route_node *rn;
301 struct external_info *ei;
302 struct ospf_external *ext;
303
304 ext = ospf_external_lookup(type, instance);
305 if (!ext)
306 return;
307
308 /* Delete external info for specified type. */
309 if (EXTERNAL_INFO (ext))
310 for (rn = route_top (EXTERNAL_INFO (ext)); rn; rn = route_next (rn))
311 if ((ei = rn->info))
312 if (ospf_external_info_find_lsa (ospf, &ei->p))
313 {
314 if (is_prefix_default (&ei->p) &&
315 ospf->default_originate != DEFAULT_ORIGINATE_NONE)
316 continue;
317 ospf_external_lsa_flush (ospf, type, &ei->p,
318 ei->ifindex /*, ei->nexthop */);
319
320 ospf_external_info_free (ei);
321 route_unlock_node (rn);
322 rn->info = NULL;
323 }
324 }