2 Copyright (C) 2000 Kunihiro Ishiguro
4 This file is part of GNU Zebra.
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
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.
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
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. */
50 /* Route table for next-hop lookup cache. */
51 struct bgp_table
*bgp_nexthop_cache_table
[AFI_MAX
];
53 /* Route table for connected route. */
54 static struct bgp_table
*bgp_connected_table
[AFI_MAX
];
56 /* Route table for import-check */
57 struct bgp_table
*bgp_import_check_table
[AFI_MAX
];
60 bnc_str (struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
62 prefix2str(&(bnc
->node
->p
), buf
, size
);
67 bnc_nexthop_free (struct bgp_nexthop_cache
*bnc
)
69 struct nexthop
*nexthop
;
70 struct nexthop
*next
= NULL
;
72 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= next
)
75 XFREE (MTYPE_NEXTHOP
, nexthop
);
79 struct bgp_nexthop_cache
*
82 struct bgp_nexthop_cache
*bnc
;
84 bnc
= XCALLOC (MTYPE_BGP_NEXTHOP_CACHE
, sizeof (struct bgp_nexthop_cache
));
85 LIST_INIT(&(bnc
->paths
));
90 bnc_free (struct bgp_nexthop_cache
*bnc
)
92 bnc_nexthop_free (bnc
);
93 XFREE (MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
96 /* Reset and free all BGP nexthop cache. */
98 bgp_nexthop_cache_reset (struct bgp_table
*table
)
101 struct bgp_nexthop_cache
*bnc
;
103 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
104 if ((bnc
= rn
->info
) != NULL
)
108 bgp_unlock_node (rn
);
112 /* BGP own address structure */
119 static struct hash
*bgp_address_hash
;
122 bgp_address_hash_alloc (void *p
)
124 const struct in_addr
*val
= (const struct in_addr
*)p
;
125 struct bgp_addr
*addr
;
127 addr
= XMALLOC (MTYPE_BGP_ADDR
, sizeof (struct bgp_addr
));
129 addr
->addr
.s_addr
= val
->s_addr
;
135 bgp_address_hash_key_make (void *p
)
137 const struct bgp_addr
*addr
= p
;
139 return jhash_1word(addr
->addr
.s_addr
, 0);
143 bgp_address_hash_cmp (const void *p1
, const void *p2
)
145 const struct bgp_addr
*addr1
= p1
;
146 const struct bgp_addr
*addr2
= p2
;
148 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
152 bgp_address_init (void)
154 bgp_address_hash
= hash_create (bgp_address_hash_key_make
,
155 bgp_address_hash_cmp
);
159 bgp_address_add (struct prefix
*p
)
162 struct bgp_addr
*addr
;
164 tmp
.addr
= p
->u
.prefix4
;
166 addr
= hash_get (bgp_address_hash
, &tmp
, bgp_address_hash_alloc
);
174 bgp_address_del (struct prefix
*p
)
177 struct bgp_addr
*addr
;
179 tmp
.addr
= p
->u
.prefix4
;
181 addr
= hash_lookup (bgp_address_hash
, &tmp
);
182 /* may have been deleted earlier by bgp_interface_down() */
188 if (addr
->refcnt
== 0)
190 hash_release (bgp_address_hash
, addr
);
191 XFREE (MTYPE_BGP_ADDR
, addr
);
196 struct bgp_connected_ref
202 bgp_connected_add (struct connected
*ifc
)
207 struct bgp_connected_ref
*bc
;
208 struct listnode
*node
, *nnode
, *mnode
;
214 p
= *(CONNECTED_PREFIX(ifc
));
215 if (addr
->family
== AF_INET
)
217 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
219 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
222 bgp_address_add (addr
);
224 rn
= bgp_node_get (bgp_connected_table
[AFI_IP
], (struct prefix
*) &p
);
232 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
237 for (ALL_LIST_ELEMENTS_RO (bm
->bgp
, mnode
, bgp
))
239 for (ALL_LIST_ELEMENTS (bgp
->peer
, node
, nnode
, peer
))
241 if (peer
->conf_if
&& (strcmp (peer
->conf_if
, ifc
->ifp
->name
) == 0) &&
242 !CHECK_FLAG(peer
->flags
, PEER_FLAG_IFPEER_V6ONLY
))
244 if (peer_active(peer
))
245 BGP_EVENT_ADD (peer
, BGP_Stop
);
246 BGP_EVENT_ADD (peer
, BGP_Start
);
252 else if (addr
->family
== AF_INET6
)
254 apply_mask_ipv6 ((struct prefix_ipv6
*) &p
);
256 if (IN6_IS_ADDR_UNSPECIFIED (&p
.u
.prefix6
))
259 if (IN6_IS_ADDR_LINKLOCAL (&p
.u
.prefix6
))
262 rn
= bgp_node_get (bgp_connected_table
[AFI_IP6
], (struct prefix
*) &p
);
270 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
275 #endif /* HAVE_IPV6 */
279 bgp_connected_delete (struct connected
*ifc
)
284 struct bgp_connected_ref
*bc
;
288 p
= *(CONNECTED_PREFIX(ifc
));
289 if (addr
->family
== AF_INET
)
291 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
293 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
296 bgp_address_del (addr
);
298 rn
= bgp_node_lookup (bgp_connected_table
[AFI_IP
], &p
);
306 XFREE (MTYPE_BGP_CONN
, bc
);
309 bgp_unlock_node (rn
);
310 bgp_unlock_node (rn
);
313 else if (addr
->family
== AF_INET6
)
315 apply_mask_ipv6 ((struct prefix_ipv6
*) &p
);
317 if (IN6_IS_ADDR_UNSPECIFIED (&p
.u
.prefix6
))
320 if (IN6_IS_ADDR_LINKLOCAL (&p
.u
.prefix6
))
323 rn
= bgp_node_lookup (bgp_connected_table
[AFI_IP6
], (struct prefix
*) &p
);
331 XFREE (MTYPE_BGP_CONN
, bc
);
334 bgp_unlock_node (rn
);
335 bgp_unlock_node (rn
);
337 #endif /* HAVE_IPV6 */
341 bgp_nexthop_self (struct attr
*attr
)
343 struct bgp_addr tmp
, *addr
;
345 tmp
.addr
= attr
->nexthop
;
347 addr
= hash_lookup (bgp_address_hash
, &tmp
);
355 bgp_multiaccess_check_v4 (struct in_addr nexthop
, struct peer
*peer
)
357 struct bgp_node
*rn1
;
358 struct bgp_node
*rn2
;
363 p
.prefixlen
= IPV4_MAX_BITLEN
;
364 p
.u
.prefix4
= nexthop
;
366 rn1
= bgp_node_match (bgp_connected_table
[AFI_IP
], &p
);
371 p
.prefixlen
= IPV4_MAX_BITLEN
;
372 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
374 rn2
= bgp_node_match (bgp_connected_table
[AFI_IP
], &p
);
377 bgp_unlock_node(rn1
);
381 ret
= (rn1
== rn2
) ? 1 : 0;
383 bgp_unlock_node(rn1
);
384 bgp_unlock_node(rn2
);
390 show_ip_bgp_nexthop_table (struct vty
*vty
, int detail
)
393 struct bgp_nexthop_cache
*bnc
;
394 char buf
[INET6_ADDRSTRLEN
];
395 struct nexthop
*nexthop
;
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
)
402 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
))
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
);
408 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
409 switch (nexthop
->type
)
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
);
416 case NEXTHOP_TYPE_IFINDEX
:
417 vty_out (vty
, " if %s%s",
418 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
420 case NEXTHOP_TYPE_IPV4_IFINDEX
:
421 vty_out (vty
, " gate %s, if %s%s",
422 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
424 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
427 vty_out (vty
, " invalid nexthop type %u%s",
428 nexthop
->type
, VTY_NEWLINE
);
433 vty_out (vty
, " %s invalid%s",
434 inet_ntop (AF_INET
, &rn
->p
.u
.prefix4
, buf
, INET6_ADDRSTRLEN
), VTY_NEWLINE
);
436 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
437 vty_out (vty
, " Must be Connected%s", VTY_NEWLINE
);
439 #ifdef HAVE_CLOCK_MONOTONIC
440 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
441 vty_out (vty
, " Last update: %s", ctime(&tbuf
));
443 vty_out (vty
, " Last update: %s", ctime(&bnc
->uptime
));
444 #endif /* HAVE_CLOCK_MONOTONIC */
446 vty_out(vty
, "%s", VTY_NEWLINE
);
451 for (rn
= bgp_table_top (bgp_nexthop_cache_table
[AFI_IP6
]);
453 rn
= bgp_route_next (rn
))
454 if ((bnc
= rn
->info
) != NULL
)
456 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
))
458 vty_out (vty
, " %s valid [IGP metric %d]%s",
459 inet_ntop (AF_INET6
, &rn
->p
.u
.prefix6
, buf
,
461 bnc
->metric
, VTY_NEWLINE
);
463 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
464 switch (nexthop
->type
)
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
);
471 case NEXTHOP_TYPE_IPV6_IFINDEX
:
472 vty_out(vty
, " gate %s, if %s%s",
473 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
475 ifindex2ifname(nexthop
->ifindex
),
478 case NEXTHOP_TYPE_IFINDEX
:
479 vty_out (vty
, " if %s%s",
480 ifindex2ifname(nexthop
->ifindex
),
484 vty_out (vty
, " invalid nexthop type %u%s",
485 nexthop
->type
, VTY_NEWLINE
);
490 vty_out (vty
, " %s invalid%s",
491 inet_ntop (AF_INET6
, &rn
->p
.u
.prefix6
, buf
, INET6_ADDRSTRLEN
),
494 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
495 vty_out (vty
, " Must be Connected%s", VTY_NEWLINE
);
497 #ifdef HAVE_CLOCK_MONOTONIC
498 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
499 vty_out (vty
, " Last update: %s", ctime(&tbuf
));
501 vty_out (vty
, " Last update: %s", ctime(&bnc
->uptime
));
502 #endif /* HAVE_CLOCK_MONOTONIC */
504 vty_out(vty
, "%s", VTY_NEWLINE
);
507 #endif /* HAVE_IPV6 */
511 DEFUN (show_ip_bgp_nexthop
,
512 show_ip_bgp_nexthop_cmd
,
513 "show ip bgp nexthop",
517 "BGP nexthop table\n")
519 return show_ip_bgp_nexthop_table (vty
, 0);
522 DEFUN (show_ip_bgp_nexthop_detail
,
523 show_ip_bgp_nexthop_detail_cmd
,
524 "show ip bgp nexthop detail",
528 "BGP nexthop table\n")
530 return show_ip_bgp_nexthop_table (vty
, 1);
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
);
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 */
549 bgp_scan_vty_init (void)
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
);
558 bgp_scan_finish (void)
560 /* Only the current one needs to be reset. */
561 bgp_nexthop_cache_reset (bgp_nexthop_cache_table
[AFI_IP
]);
563 bgp_table_unlock (bgp_nexthop_cache_table
[AFI_IP
]);
564 bgp_nexthop_cache_table
[AFI_IP
] = NULL
;
566 bgp_table_unlock (bgp_connected_table
[AFI_IP
]);
567 bgp_connected_table
[AFI_IP
] = NULL
;
569 bgp_table_unlock (bgp_import_check_table
[AFI_IP
]);
570 bgp_import_check_table
[AFI_IP
] = NULL
;
573 /* Only the current one needs to be reset. */
574 bgp_nexthop_cache_reset (bgp_nexthop_cache_table
[AFI_IP6
]);
576 bgp_table_unlock (bgp_nexthop_cache_table
[AFI_IP6
]);
577 bgp_nexthop_cache_table
[AFI_IP6
] = NULL
;
579 bgp_table_unlock (bgp_connected_table
[AFI_IP6
]);
580 bgp_connected_table
[AFI_IP6
] = NULL
;
582 bgp_table_unlock (bgp_import_check_table
[AFI_IP6
]);
583 bgp_import_check_table
[AFI_IP6
] = NULL
;
584 #endif /* HAVE_IPV6 */