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 18 * along with GNU Zebra; see the file COPYING. If not, write to the Free 19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 */ 22 23#include <zebra.h> 24 25#include "thread.h" 26#include "memory.h" 27#include "linklist.h" 28#include "prefix.h" 29#include "if.h" 30#include "table.h" 31#include "vty.h" 32#include "filter.h" 33#include "log.h" 34 35#include "ospfd/ospfd.h" 36#include "ospfd/ospf_interface.h" 37#include "ospfd/ospf_asbr.h" 38#include "ospfd/ospf_lsa.h" 39#include "ospfd/ospf_lsdb.h" 40#include "ospfd/ospf_neighbor.h" 41#include "ospfd/ospf_spf.h" 42#include "ospfd/ospf_flood.h" 43#include "ospfd/ospf_route.h" 44#include "ospfd/ospf_zebra.h" 45#include "ospfd/ospf_dump.h" 46 47 48/* Remove external route. */ 49void 50ospf_external_route_remove (struct ospf *ospf, struct prefix_ipv4 *p) 51{ 52 struct route_node *rn; 53 struct ospf_route *or; 54 55 rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p); 56 if (rn) 57 if ((or = rn->info)) 58 { 59 zlog_info ("Route[%s/%d]: external path deleted", 60 inet_ntoa (p->prefix), p->prefixlen); 61 62 /* Remove route from zebra. */ 63 if (or->type == OSPF_DESTINATION_NETWORK) 64 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or); 65 66 ospf_route_free (or); 67 rn->info = NULL; 68 69 route_unlock_node (rn); 70 route_unlock_node (rn); 71 return; 72 } 73 74 zlog_info ("Route[%s/%d]: no such external path", 75 inet_ntoa (p->prefix), p->prefixlen); 76} 77 78/* Lookup external route. */ 79struct ospf_route * 80ospf_external_route_lookup (struct ospf *ospf, 81 struct prefix_ipv4 *p) 82{ 83 struct route_node *rn; 84 85 rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p); 86 if (rn) 87 { 88 route_unlock_node (rn); 89 if (rn->info) 90 return rn->info; 91 } 92 93 zlog_warn ("Route[%s/%d]: lookup, no such prefix", 94 inet_ntoa (p->prefix), p->prefixlen); 95 96 return NULL; 97} 98 99 100/* Add an External info for AS-external-LSA. */ 101struct external_info * 102ospf_external_info_new (u_char type) 103{ 104 struct external_info *new; 105 106 new = (struct external_info *) 107 XCALLOC (MTYPE_OSPF_EXTERNAL_INFO, sizeof (struct external_info)); 108 new->type = type; 109 110 ospf_reset_route_map_set_values (&new->route_map_set); 111 return new; 112} 113 114static void 115ospf_external_info_free (struct external_info *ei) 116{ 117 XFREE (MTYPE_OSPF_EXTERNAL_INFO, ei); 118} 119 120void 121ospf_reset_route_map_set_values (struct route_map_set_values *values) 122{ 123 values->metric = -1; 124 values->metric_type = -1; 125} 126 127int 128ospf_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. */ 136struct external_info * 137ospf_external_info_add (u_char type, struct prefix_ipv4 p, 138 unsigned int ifindex, struct in_addr nexthop) 139{ 140 struct external_info *new; 141 struct route_node *rn; 142 143 /* Initialize route table. */ 144 if (EXTERNAL_INFO (type) == NULL) 145 EXTERNAL_INFO (type) = route_table_init (); 146 147 rn = route_node_get (EXTERNAL_INFO (type), (struct prefix *) &p); 148 /* If old info exists, -- discard new one or overwrite with new one? */ 149 if (rn) 150 if (rn->info) 151 { 152 route_unlock_node (rn); 153 zlog_warn ("Redistribute[%s]: %s/%d already exists, discard.", 154 ospf_redist_string(type), 155 inet_ntoa (p.prefix), p.prefixlen); 156 /* XFREE (MTYPE_OSPF_TMP, rn->info); */ 157 return rn->info; 158 } 159 160 /* Create new External info instance. */ 161 new = ospf_external_info_new (type); 162 new->p = p; 163 new->ifindex = ifindex; 164 new->nexthop = nexthop; 165 new->tag = 0; 166 167 if (rn) 168 rn->info = new; 169 170 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) 171 zlog_debug ("Redistribute[%s]: %s/%d external info created.", 172 ospf_redist_string(type), 173 inet_ntoa (p.prefix), p.prefixlen); 174 return new; 175} 176 177void 178ospf_external_info_delete (u_char type, struct prefix_ipv4 p) 179{ 180 struct route_node *rn; 181 182 rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p); 183 if (rn) 184 { 185 ospf_external_info_free (rn->info); 186 rn->info = NULL; 187 route_unlock_node (rn); 188 route_unlock_node (rn); 189 } 190} 191 192struct external_info * 193ospf_external_info_lookup (u_char type, struct prefix_ipv4 *p) 194{ 195 struct route_node *rn; 196 rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) p); 197 if (rn) 198 { 199 route_unlock_node (rn); 200 if (rn->info) 201 return rn->info; 202 } 203 204 return NULL; 205} 206 207struct ospf_lsa * 208ospf_external_info_find_lsa (struct ospf *ospf, 209 struct prefix_ipv4 *p) 210{ 211 struct ospf_lsa *lsa; 212 struct as_external_lsa *al; 213 struct in_addr mask, id; 214 215 lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA, 216 p->prefix, ospf->router_id); 217 218 if (!lsa) 219 return NULL; 220 221 al = (struct as_external_lsa *) lsa->data; 222 223 masklen2ip (p->prefixlen, &mask); 224 225 if (mask.s_addr != al->mask.s_addr) 226 { 227 id.s_addr = p->prefix.s_addr | (~mask.s_addr); 228 lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA, 229 id, ospf->router_id); 230 if (!lsa) 231 return NULL; 232 } 233 234 return lsa; 235} 236 237 238/* Update ASBR status. */ 239void 240ospf_asbr_status_update (struct ospf *ospf, u_char status) 241{ 242 zlog_info ("ASBR[Status:%d]: Update", status); 243 244 /* ASBR on. */ 245 if (status) 246 { 247 /* Already ASBR. */ 248 if (IS_OSPF_ASBR (ospf)) 249 { 250 zlog_info ("ASBR[Status:%d]: Already ASBR", status); 251 return; 252 } 253 SET_FLAG (ospf->flags, OSPF_FLAG_ASBR); 254 } 255 else 256 { 257 /* Already non ASBR. */ 258 if (! IS_OSPF_ASBR (ospf)) 259 { 260 zlog_info ("ASBR[Status:%d]: Already non ASBR", status); 261 return; 262 } 263 UNSET_FLAG (ospf->flags, OSPF_FLAG_ASBR); 264 } 265 266 /* Transition from/to status ASBR, schedule timer. */ 267 ospf_spf_calculate_schedule (ospf, SPF_FLAG_ASBR_STATUS_CHANGE); 268 ospf_router_lsa_update (ospf); 269} 270 271void 272ospf_redistribute_withdraw (struct ospf *ospf, u_char type) 273{ 274 struct route_node *rn; 275 struct external_info *ei; 276 277 /* Delete external info for specified type. */ 278 if (EXTERNAL_INFO (type)) 279 for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn)) 280 if ((ei = rn->info)) 281 if (ospf_external_info_find_lsa (ospf, &ei->p)) 282 { 283 if (is_prefix_default (&ei->p) && 284 ospf->default_originate != DEFAULT_ORIGINATE_NONE) 285 continue; 286 ospf_external_lsa_flush (ospf, type, &ei->p, 287 ei->ifindex /*, ei->nexthop */); 288 289 ospf_external_info_free (ei); 290 route_unlock_node (rn); 291 rn->info = NULL; 292 } 293} 294