]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nexthop.c
quagga-fix-stop-vty.patch
[mirror_frr.git] / bgpd / bgp_nexthop.c
1 /* BGP nexthop scan
2 Copyright (C) 2000 Kunihiro Ishiguro
3
4 This file is part of GNU Zebra.
5
6 GNU Zebra is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 GNU Zebra is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "thread.h"
25 #include "prefix.h"
26 #include "zclient.h"
27 #include "stream.h"
28 #include "network.h"
29 #include "log.h"
30 #include "memory.h"
31 #include "hash.h"
32 #include "jhash.h"
33 #include "nexthop.h"
34 #include "queue.h"
35
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_table.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_nexthop.h"
41 #include "bgpd/bgp_nht.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_damp.h"
44 #include "zebra/rib.h"
45 #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
46
47
48
49 /* Route table for next-hop lookup cache. */
50 struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
51
52 /* Route table for connected route. */
53 static struct bgp_table *bgp_connected_table[AFI_MAX];
54
55 /* Route table for import-check */
56 struct bgp_table *bgp_import_check_table[AFI_MAX];
57
58 char *
59 bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
60 {
61 prefix2str(&(bnc->node->p), buf, size);
62 return buf;
63 }
64
65 void
66 bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
67 {
68 struct nexthop *nexthop;
69 struct nexthop *next = NULL;
70
71 for (nexthop = bnc->nexthop; nexthop; nexthop = next)
72 {
73 next = nexthop->next;
74 XFREE (MTYPE_NEXTHOP, nexthop);
75 }
76 }
77
78 struct bgp_nexthop_cache *
79 bnc_new (void)
80 {
81 struct bgp_nexthop_cache *bnc;
82
83 bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
84 LIST_INIT(&(bnc->paths));
85 return bnc;
86 }
87
88 void
89 bnc_free (struct bgp_nexthop_cache *bnc)
90 {
91 bnc_nexthop_free (bnc);
92 XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
93 }
94
95 /* Reset and free all BGP nexthop cache. */
96 static void
97 bgp_nexthop_cache_reset (struct bgp_table *table)
98 {
99 struct bgp_node *rn;
100 struct bgp_nexthop_cache *bnc;
101
102 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
103 if ((bnc = rn->info) != NULL)
104 {
105 bnc_free (bnc);
106 rn->info = NULL;
107 bgp_unlock_node (rn);
108 }
109 }
110
111 /* BGP own address structure */
112 struct bgp_addr
113 {
114 struct in_addr addr;
115 int refcnt;
116 };
117
118 static struct hash *bgp_address_hash;
119
120 static void *
121 bgp_address_hash_alloc (void *p)
122 {
123 const struct in_addr *val = (const struct in_addr *)p;
124 struct bgp_addr *addr;
125
126 addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
127 addr->refcnt = 0;
128 addr->addr.s_addr = val->s_addr;
129
130 return addr;
131 }
132
133 static unsigned int
134 bgp_address_hash_key_make (void *p)
135 {
136 const struct bgp_addr *addr = p;
137
138 return jhash_1word(addr->addr.s_addr, 0);
139 }
140
141 static int
142 bgp_address_hash_cmp (const void *p1, const void *p2)
143 {
144 const struct bgp_addr *addr1 = p1;
145 const struct bgp_addr *addr2 = p2;
146
147 return addr1->addr.s_addr == addr2->addr.s_addr;
148 }
149
150 void
151 bgp_address_init (void)
152 {
153 bgp_address_hash = hash_create (bgp_address_hash_key_make,
154 bgp_address_hash_cmp);
155 }
156
157 static void
158 bgp_address_add (struct prefix *p)
159 {
160 struct bgp_addr tmp;
161 struct bgp_addr *addr;
162
163 tmp.addr = p->u.prefix4;
164
165 addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
166 if (!addr)
167 return;
168
169 addr->refcnt++;
170 }
171
172 static void
173 bgp_address_del (struct prefix *p)
174 {
175 struct bgp_addr tmp;
176 struct bgp_addr *addr;
177
178 tmp.addr = p->u.prefix4;
179
180 addr = hash_lookup (bgp_address_hash, &tmp);
181 /* may have been deleted earlier by bgp_interface_down() */
182 if (addr == NULL)
183 return;
184
185 addr->refcnt--;
186
187 if (addr->refcnt == 0)
188 {
189 hash_release (bgp_address_hash, addr);
190 XFREE (MTYPE_BGP_ADDR, addr);
191 }
192 }
193
194
195 struct bgp_connected_ref
196 {
197 unsigned int refcnt;
198 };
199
200 void
201 bgp_connected_add (struct connected *ifc)
202 {
203 struct prefix p;
204 struct prefix *addr;
205 struct bgp_node *rn;
206 struct bgp_connected_ref *bc;
207
208 addr = ifc->address;
209
210 if (addr->family == AF_INET)
211 {
212 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
213 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
214
215 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
216 return;
217
218 bgp_address_add (addr);
219
220 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
221 if (rn->info)
222 {
223 bc = rn->info;
224 bc->refcnt++;
225 }
226 else
227 {
228 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
229 bc->refcnt = 1;
230 rn->info = bc;
231 }
232 }
233 #ifdef HAVE_IPV6
234 else if (addr->family == AF_INET6)
235 {
236 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
237 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
238
239 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
240 return;
241
242 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
243 return;
244
245 rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
246 if (rn->info)
247 {
248 bc = rn->info;
249 bc->refcnt++;
250 }
251 else
252 {
253 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
254 bc->refcnt = 1;
255 rn->info = bc;
256 }
257 }
258 #endif /* HAVE_IPV6 */
259 }
260
261 void
262 bgp_connected_delete (struct connected *ifc)
263 {
264 struct prefix p;
265 struct prefix *addr;
266 struct bgp_node *rn;
267 struct bgp_connected_ref *bc;
268
269 addr = ifc->address;
270
271 if (addr->family == AF_INET)
272 {
273 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
274 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
275
276 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
277 return;
278
279 bgp_address_del (addr);
280
281 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
282 if (! rn)
283 return;
284
285 bc = rn->info;
286 bc->refcnt--;
287 if (bc->refcnt == 0)
288 {
289 XFREE (MTYPE_BGP_CONN, bc);
290 rn->info = NULL;
291 }
292 bgp_unlock_node (rn);
293 bgp_unlock_node (rn);
294 }
295 #ifdef HAVE_IPV6
296 else if (addr->family == AF_INET6)
297 {
298 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
299 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
300
301 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
302 return;
303
304 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
305 return;
306
307 rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
308 if (! rn)
309 return;
310
311 bc = rn->info;
312 bc->refcnt--;
313 if (bc->refcnt == 0)
314 {
315 XFREE (MTYPE_BGP_CONN, bc);
316 rn->info = NULL;
317 }
318 bgp_unlock_node (rn);
319 bgp_unlock_node (rn);
320 }
321 #endif /* HAVE_IPV6 */
322 }
323
324 int
325 bgp_nexthop_self (struct attr *attr)
326 {
327 struct bgp_addr tmp, *addr;
328
329 tmp.addr = attr->nexthop;
330
331 addr = hash_lookup (bgp_address_hash, &tmp);
332 if (addr)
333 return 1;
334
335 return 0;
336 }
337
338
339 int
340 bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
341 {
342 struct bgp_node *rn1;
343 struct bgp_node *rn2;
344 struct prefix p;
345 int ret;
346
347 p.family = AF_INET;
348 p.prefixlen = IPV4_MAX_BITLEN;
349 p.u.prefix4 = nexthop;
350
351 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
352 if (!rn1)
353 return 0;
354
355 p.family = AF_INET;
356 p.prefixlen = IPV4_MAX_BITLEN;
357 p.u.prefix4 = peer->su.sin.sin_addr;
358
359 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
360 if (!rn2)
361 {
362 bgp_unlock_node(rn1);
363 return 0;
364 }
365
366 ret = (rn1 == rn2) ? 1 : 0;
367
368 bgp_unlock_node(rn1);
369 bgp_unlock_node(rn2);
370
371 return (ret);
372 }
373
374 static int
375 show_ip_bgp_nexthop_table (struct vty *vty, int detail)
376 {
377 struct bgp_node *rn;
378 struct bgp_nexthop_cache *bnc;
379 char buf[INET6_ADDRSTRLEN];
380 struct nexthop *nexthop;
381 time_t tbuf;
382
383 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
384 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
385 if ((bnc = rn->info) != NULL)
386 {
387 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
388 {
389 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
390 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN),
391 bnc->metric, bnc->path_count, VTY_NEWLINE);
392 if (detail)
393 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
394 switch (nexthop->type)
395 {
396 case NEXTHOP_TYPE_IPV4:
397 vty_out (vty, " gate %s%s",
398 inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
399 INET6_ADDRSTRLEN), VTY_NEWLINE);
400 break;
401 case NEXTHOP_TYPE_IFINDEX:
402 vty_out (vty, " if %s%s",
403 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
404 break;
405 case NEXTHOP_TYPE_IPV4_IFINDEX:
406 vty_out (vty, " gate %s, if %s%s",
407 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
408 INET6_ADDRSTRLEN),
409 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
410 break;
411 default:
412 vty_out (vty, " invalid nexthop type %u%s",
413 nexthop->type, VTY_NEWLINE);
414 }
415 }
416 else
417 {
418 vty_out (vty, " %s invalid%s",
419 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
420
421 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
422 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
423 }
424 #ifdef HAVE_CLOCK_MONOTONIC
425 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
426 vty_out (vty, " Last update: %s", ctime(&tbuf));
427 #else
428 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
429 #endif /* HAVE_CLOCK_MONOTONIC */
430
431 vty_out(vty, "%s", VTY_NEWLINE);
432 }
433
434 #ifdef HAVE_IPV6
435 {
436 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
437 rn;
438 rn = bgp_route_next (rn))
439 if ((bnc = rn->info) != NULL)
440 {
441 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
442 {
443 vty_out (vty, " %s valid [IGP metric %d]%s",
444 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf,
445 INET6_ADDRSTRLEN),
446 bnc->metric, VTY_NEWLINE);
447 if (detail)
448 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
449 switch (nexthop->type)
450 {
451 case NEXTHOP_TYPE_IPV6:
452 vty_out (vty, " gate %s%s",
453 inet_ntop (AF_INET6, &nexthop->gate.ipv6,
454 buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
455 break;
456 case NEXTHOP_TYPE_IPV6_IFINDEX:
457 vty_out(vty, " gate %s, if %s%s",
458 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
459 INET6_ADDRSTRLEN),
460 ifindex2ifname(nexthop->ifindex),
461 VTY_NEWLINE);
462 break;
463 case NEXTHOP_TYPE_IFINDEX:
464 vty_out (vty, " ifidx %u%s", nexthop->ifindex,
465 VTY_NEWLINE);
466 break;
467 default:
468 vty_out (vty, " invalid nexthop type %u%s",
469 nexthop->type, VTY_NEWLINE);
470 }
471 }
472 else
473 {
474 vty_out (vty, " %s invalid%s",
475 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
476 VTY_NEWLINE);
477
478 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
479 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
480 }
481 #ifdef HAVE_CLOCK_MONOTONIC
482 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
483 vty_out (vty, " Last update: %s", ctime(&tbuf));
484 #else
485 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
486 #endif /* HAVE_CLOCK_MONOTONIC */
487
488 vty_out(vty, "%s", VTY_NEWLINE);
489 }
490 }
491 #endif /* HAVE_IPV6 */
492 return CMD_SUCCESS;
493 }
494
495 DEFUN (show_ip_bgp_nexthop,
496 show_ip_bgp_nexthop_cmd,
497 "show ip bgp nexthop",
498 SHOW_STR
499 IP_STR
500 BGP_STR
501 "BGP nexthop table\n")
502 {
503 return show_ip_bgp_nexthop_table (vty, 0);
504 }
505
506 DEFUN (show_ip_bgp_nexthop_detail,
507 show_ip_bgp_nexthop_detail_cmd,
508 "show ip bgp nexthop detail",
509 SHOW_STR
510 IP_STR
511 BGP_STR
512 "BGP nexthop table\n")
513 {
514 return show_ip_bgp_nexthop_table (vty, 1);
515 }
516
517 void
518 bgp_scan_init (void)
519 {
520 bgp_nexthop_cache_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
521 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
522 bgp_import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
523
524 #ifdef HAVE_IPV6
525 bgp_nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
526 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
527 bgp_import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
528 #endif /* HAVE_IPV6 */
529
530 }
531
532 void
533 bgp_scan_vty_init (void)
534 {
535 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
536 install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
537 install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd);
538 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd);
539 }
540
541 void
542 bgp_scan_finish (void)
543 {
544 /* Only the current one needs to be reset. */
545 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
546
547 bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP]);
548 bgp_nexthop_cache_table[AFI_IP] = NULL;
549
550 bgp_table_unlock (bgp_connected_table[AFI_IP]);
551 bgp_connected_table[AFI_IP] = NULL;
552
553 bgp_table_unlock (bgp_import_check_table[AFI_IP]);
554 bgp_import_check_table[AFI_IP] = NULL;
555
556 #ifdef HAVE_IPV6
557 /* Only the current one needs to be reset. */
558 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
559
560 bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP6]);
561 bgp_nexthop_cache_table[AFI_IP6] = NULL;
562
563 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
564 bgp_connected_table[AFI_IP6] = NULL;
565
566 bgp_table_unlock (bgp_import_check_table[AFI_IP6]);
567 bgp_import_check_table[AFI_IP6] = NULL;
568 #endif /* HAVE_IPV6 */
569 }