2 * OSPF AS Boundary Router functions.
3 * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
5 * This file is part of GNU Zebra.
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
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.
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
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"
47 /* Remove external route. */
48 void ospf_external_route_remove(struct ospf
*ospf
, struct prefix_ipv4
*p
)
50 struct route_node
*rn
;
51 struct ospf_route
* or ;
53 rn
= route_node_lookup(ospf
->old_external_route
, (struct prefix
*)p
);
55 if ((or = rn
->info
)) {
56 zlog_info("Route[%s/%d]: external path deleted",
57 inet_ntoa(p
->prefix
), p
->prefixlen
);
59 /* Remove route from zebra. */
60 if (or->type
== OSPF_DESTINATION_NETWORK
)
62 ospf
, (struct prefix_ipv4
*)&rn
->p
, or);
67 route_unlock_node(rn
);
68 route_unlock_node(rn
);
72 zlog_info("Route[%s/%d]: no such external path", inet_ntoa(p
->prefix
),
76 /* Lookup external route. */
77 struct ospf_route
*ospf_external_route_lookup(struct ospf
*ospf
,
78 struct prefix_ipv4
*p
)
80 struct route_node
*rn
;
82 rn
= route_node_lookup(ospf
->old_external_route
, (struct prefix
*)p
);
84 route_unlock_node(rn
);
89 zlog_warn("Route[%s/%d]: lookup, no such prefix", inet_ntoa(p
->prefix
),
96 /* Add an External info for AS-external-LSA. */
97 struct external_info
*ospf_external_info_new(uint8_t type
,
98 unsigned short instance
)
100 struct external_info
*new;
102 new = (struct external_info
*)XCALLOC(MTYPE_OSPF_EXTERNAL_INFO
,
103 sizeof(struct external_info
));
105 new->instance
= instance
;
107 ospf_reset_route_map_set_values(&new->route_map_set
);
111 static void ospf_external_info_free(struct external_info
*ei
)
113 XFREE(MTYPE_OSPF_EXTERNAL_INFO
, ei
);
116 void ospf_reset_route_map_set_values(struct route_map_set_values
*values
)
119 values
->metric_type
= -1;
122 int ospf_route_map_set_compare(struct route_map_set_values
*values1
,
123 struct route_map_set_values
*values2
)
125 return values1
->metric
== values2
->metric
126 && values1
->metric_type
== values2
->metric_type
;
129 /* Add an External info for AS-external-LSA. */
130 struct external_info
*
131 ospf_external_info_add(struct ospf
*ospf
, uint8_t type
, unsigned short instance
,
132 struct prefix_ipv4 p
, ifindex_t ifindex
,
133 struct in_addr nexthop
, route_tag_t tag
)
135 struct external_info
*new;
136 struct route_node
*rn
;
137 struct ospf_external
*ext
;
138 char inetbuf
[INET6_BUFSIZ
];
140 ext
= ospf_external_lookup(ospf
, type
, instance
);
142 ext
= ospf_external_add(ospf
, type
, instance
);
144 rn
= route_node_get(EXTERNAL_INFO(ext
), (struct prefix
*)&p
);
145 /* If old info exists, -- discard new one or overwrite with new one? */
149 if ((new->ifindex
== ifindex
)
150 && (new->nexthop
.s_addr
== nexthop
.s_addr
)
151 && (new->tag
== tag
)) {
152 route_unlock_node(rn
);
153 return NULL
; /* NULL => no LSA to refresh */
156 inet_ntop(AF_INET
, (void *)&nexthop
.s_addr
, inetbuf
,
159 "Redistribute[%s][%d][%u]: %s/%d discarding old info with NH %s.",
160 ospf_redist_string(type
), instance
,
161 ospf
->vrf_id
, inet_ntoa(p
.prefix
), p
.prefixlen
,
163 XFREE(MTYPE_OSPF_EXTERNAL_INFO
, rn
->info
);
167 /* Create new External info instance. */
168 new = ospf_external_info_new(type
, instance
);
170 new->ifindex
= ifindex
;
171 new->nexthop
= nexthop
;
174 /* we don't unlock rn from the get() because we're attaching the info */
178 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
179 inet_ntop(AF_INET
, (void *)&nexthop
.s_addr
, inetbuf
,
182 "Redistribute[%s][%u]: %s/%d external info created, with NH %s",
183 ospf_redist_string(type
), ospf
->vrf_id
,
184 inet_ntoa(p
.prefix
), p
.prefixlen
, inetbuf
);
189 void ospf_external_info_delete(struct ospf
*ospf
, uint8_t type
,
190 unsigned short instance
, struct prefix_ipv4 p
)
192 struct route_node
*rn
;
193 struct ospf_external
*ext
;
195 ext
= ospf_external_lookup(ospf
, type
, instance
);
199 rn
= route_node_lookup(EXTERNAL_INFO(ext
), (struct prefix
*)&p
);
201 ospf_external_info_free(rn
->info
);
203 route_unlock_node(rn
);
204 route_unlock_node(rn
);
208 struct external_info
*ospf_external_info_lookup(struct ospf
*ospf
, uint8_t type
,
209 unsigned short instance
,
210 struct prefix_ipv4
*p
)
212 struct route_node
*rn
;
213 struct ospf_external
*ext
;
215 ext
= ospf_external_lookup(ospf
, type
, instance
);
219 rn
= route_node_lookup(EXTERNAL_INFO(ext
), (struct prefix
*)p
);
221 route_unlock_node(rn
);
229 struct ospf_lsa
*ospf_external_info_find_lsa(struct ospf
*ospf
,
230 struct prefix_ipv4
*p
)
232 struct ospf_lsa
*lsa
;
233 struct as_external_lsa
*al
;
234 struct in_addr mask
, id
;
236 lsa
= ospf_lsdb_lookup_by_id(ospf
->lsdb
, OSPF_AS_EXTERNAL_LSA
,
237 p
->prefix
, ospf
->router_id
);
242 al
= (struct as_external_lsa
*)lsa
->data
;
244 masklen2ip(p
->prefixlen
, &mask
);
246 if (mask
.s_addr
!= al
->mask
.s_addr
) {
247 id
.s_addr
= p
->prefix
.s_addr
| (~mask
.s_addr
);
248 lsa
= ospf_lsdb_lookup_by_id(ospf
->lsdb
, OSPF_AS_EXTERNAL_LSA
,
249 id
, ospf
->router_id
);
258 /* Update ASBR status. */
259 void ospf_asbr_status_update(struct ospf
*ospf
, uint8_t status
)
261 zlog_info("ASBR[Status:%d]: Update", status
);
266 if (IS_OSPF_ASBR(ospf
)) {
267 zlog_info("ASBR[Status:%d]: Already ASBR", status
);
270 SET_FLAG(ospf
->flags
, OSPF_FLAG_ASBR
);
272 /* Already non ASBR. */
273 if (!IS_OSPF_ASBR(ospf
)) {
274 zlog_info("ASBR[Status:%d]: Already non ASBR", status
);
277 UNSET_FLAG(ospf
->flags
, OSPF_FLAG_ASBR
);
280 /* Transition from/to status ASBR, schedule timer. */
281 ospf_spf_calculate_schedule(ospf
, SPF_FLAG_ASBR_STATUS_CHANGE
);
282 ospf_router_lsa_update(ospf
);
285 void ospf_redistribute_withdraw(struct ospf
*ospf
, uint8_t type
,
286 unsigned short instance
)
288 struct route_node
*rn
;
289 struct external_info
*ei
;
290 struct ospf_external
*ext
;
292 ext
= ospf_external_lookup(ospf
, type
, instance
);
296 /* Delete external info for specified type. */
297 if (EXTERNAL_INFO(ext
))
298 for (rn
= route_top(EXTERNAL_INFO(ext
)); rn
;
301 if (ospf_external_info_find_lsa(ospf
, &ei
->p
)) {
302 if (is_prefix_default(&ei
->p
)
303 && ospf
->default_originate
304 != DEFAULT_ORIGINATE_NONE
)
306 ospf_external_lsa_flush(
308 ei
->ifindex
/*, ei->nexthop */);
310 ospf_external_info_free(ei
);
311 route_unlock_node(rn
);