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