]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nexthop.c
Quagga: prefix2str fixup
[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 int
355 bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
356 {
357 struct bgp_node *rn1;
358 struct bgp_node *rn2;
359 struct prefix p;
360 int ret;
361
362 p.family = AF_INET;
363 p.prefixlen = IPV4_MAX_BITLEN;
364 p.u.prefix4 = nexthop;
365
366 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
367 if (!rn1)
368 return 0;
369
370 p.family = AF_INET;
371 p.prefixlen = IPV4_MAX_BITLEN;
372 p.u.prefix4 = peer->su.sin.sin_addr;
373
374 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
375 if (!rn2)
376 {
377 bgp_unlock_node(rn1);
378 return 0;
379 }
380
381 ret = (rn1 == rn2) ? 1 : 0;
382
383 bgp_unlock_node(rn1);
384 bgp_unlock_node(rn2);
385
386 return (ret);
387 }
388
389 static int
390 show_ip_bgp_nexthop_table (struct vty *vty, int detail)
391 {
392 struct bgp_node *rn;
393 struct bgp_nexthop_cache *bnc;
394 char buf[INET6_ADDRSTRLEN];
395 struct nexthop *nexthop;
396 time_t tbuf;
397
398 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
399 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
400 if ((bnc = rn->info) != NULL)
401 {
402 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
403 {
404 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
405 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN),
406 bnc->metric, bnc->path_count, VTY_NEWLINE);
407 if (detail)
408 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
409 switch (nexthop->type)
410 {
411 case NEXTHOP_TYPE_IPV4:
412 vty_out (vty, " gate %s%s",
413 inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
414 INET6_ADDRSTRLEN), VTY_NEWLINE);
415 break;
416 case NEXTHOP_TYPE_IFINDEX:
417 vty_out (vty, " if %s%s",
418 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
419 break;
420 case NEXTHOP_TYPE_IPV4_IFINDEX:
421 vty_out (vty, " gate %s, if %s%s",
422 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
423 INET6_ADDRSTRLEN),
424 ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
425 break;
426 default:
427 vty_out (vty, " invalid nexthop type %u%s",
428 nexthop->type, VTY_NEWLINE);
429 }
430 }
431 else
432 {
433 vty_out (vty, " %s invalid%s",
434 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
435
436 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
437 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
438 }
439 #ifdef HAVE_CLOCK_MONOTONIC
440 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
441 vty_out (vty, " Last update: %s", ctime(&tbuf));
442 #else
443 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
444 #endif /* HAVE_CLOCK_MONOTONIC */
445
446 vty_out(vty, "%s", VTY_NEWLINE);
447 }
448
449 #ifdef HAVE_IPV6
450 {
451 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
452 rn;
453 rn = bgp_route_next (rn))
454 if ((bnc = rn->info) != NULL)
455 {
456 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
457 {
458 vty_out (vty, " %s valid [IGP metric %d]%s",
459 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf,
460 INET6_ADDRSTRLEN),
461 bnc->metric, VTY_NEWLINE);
462 if (detail)
463 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
464 switch (nexthop->type)
465 {
466 case NEXTHOP_TYPE_IPV6:
467 vty_out (vty, " gate %s%s",
468 inet_ntop (AF_INET6, &nexthop->gate.ipv6,
469 buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
470 break;
471 case NEXTHOP_TYPE_IPV6_IFINDEX:
472 vty_out(vty, " gate %s, if %s%s",
473 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
474 INET6_ADDRSTRLEN),
475 ifindex2ifname(nexthop->ifindex),
476 VTY_NEWLINE);
477 break;
478 case NEXTHOP_TYPE_IFINDEX:
479 vty_out (vty, " if %s%s",
480 ifindex2ifname(nexthop->ifindex),
481 VTY_NEWLINE);
482 break;
483 default:
484 vty_out (vty, " invalid nexthop type %u%s",
485 nexthop->type, VTY_NEWLINE);
486 }
487 }
488 else
489 {
490 vty_out (vty, " %s invalid%s",
491 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
492 VTY_NEWLINE);
493
494 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
495 vty_out (vty, " Must be Connected%s", VTY_NEWLINE);
496 }
497 #ifdef HAVE_CLOCK_MONOTONIC
498 tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
499 vty_out (vty, " Last update: %s", ctime(&tbuf));
500 #else
501 vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
502 #endif /* HAVE_CLOCK_MONOTONIC */
503
504 vty_out(vty, "%s", VTY_NEWLINE);
505 }
506 }
507 #endif /* HAVE_IPV6 */
508 return CMD_SUCCESS;
509 }
510
511 DEFUN (show_ip_bgp_nexthop,
512 show_ip_bgp_nexthop_cmd,
513 "show ip bgp nexthop",
514 SHOW_STR
515 IP_STR
516 BGP_STR
517 "BGP nexthop table\n")
518 {
519 return show_ip_bgp_nexthop_table (vty, 0);
520 }
521
522 DEFUN (show_ip_bgp_nexthop_detail,
523 show_ip_bgp_nexthop_detail_cmd,
524 "show ip bgp nexthop detail",
525 SHOW_STR
526 IP_STR
527 BGP_STR
528 "BGP nexthop table\n")
529 {
530 return show_ip_bgp_nexthop_table (vty, 1);
531 }
532
533 void
534 bgp_scan_init (void)
535 {
536 bgp_nexthop_cache_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
537 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
538 bgp_import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
539
540 #ifdef HAVE_IPV6
541 bgp_nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
542 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
543 bgp_import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
544 #endif /* HAVE_IPV6 */
545
546 }
547
548 void
549 bgp_scan_vty_init (void)
550 {
551 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
552 install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
553 install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd);
554 install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd);
555 }
556
557 void
558 bgp_scan_finish (void)
559 {
560 /* Only the current one needs to be reset. */
561 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
562
563 bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP]);
564 bgp_nexthop_cache_table[AFI_IP] = NULL;
565
566 bgp_table_unlock (bgp_connected_table[AFI_IP]);
567 bgp_connected_table[AFI_IP] = NULL;
568
569 bgp_table_unlock (bgp_import_check_table[AFI_IP]);
570 bgp_import_check_table[AFI_IP] = NULL;
571
572 #ifdef HAVE_IPV6
573 /* Only the current one needs to be reset. */
574 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
575
576 bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP6]);
577 bgp_nexthop_cache_table[AFI_IP6] = NULL;
578
579 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
580 bgp_connected_table[AFI_IP6] = NULL;
581
582 bgp_table_unlock (bgp_import_check_table[AFI_IP6]);
583 bgp_import_check_table[AFI_IP6] = NULL;
584 #endif /* HAVE_IPV6 */
585 }