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
35 #include "bgpd/bgpd.h"
36 #include "bgpd/bgp_table.h"
37 #include "bgpd/bgp_route.h"
38 #include "bgpd/bgp_attr.h"
39 #include "bgpd/bgp_nexthop.h"
40 #include "bgpd/bgp_nht.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_damp.h"
43 #include "zebra/rib.h"
44 #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
48 /* Route table for next-hop lookup cache. */
49 struct bgp_table
*bgp_nexthop_cache_table
[AFI_MAX
];
50 static struct bgp_table
*cache1_table
[AFI_MAX
];
52 /* Route table for connected route. */
53 static struct bgp_table
*bgp_connected_table
[AFI_MAX
];
57 bnc_str (struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
59 prefix2str(&(bnc
->node
->p
), buf
, size
);
64 bnc_nexthop_free (struct bgp_nexthop_cache
*bnc
)
66 struct nexthop
*nexthop
;
67 struct nexthop
*next
= NULL
;
69 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= next
)
72 XFREE (MTYPE_NEXTHOP
, nexthop
);
76 struct bgp_nexthop_cache
*
79 struct bgp_nexthop_cache
*bnc
;
81 bnc
= XCALLOC (MTYPE_BGP_NEXTHOP_CACHE
, sizeof (struct bgp_nexthop_cache
));
82 LIST_INIT(&(bnc
->paths
));
87 bnc_free (struct bgp_nexthop_cache
*bnc
)
89 bnc_nexthop_free (bnc
);
90 XFREE (MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
93 /* If nexthop exists on connected network return 1. */
95 bgp_nexthop_onlink (afi_t afi
, struct attr
*attr
)
99 /* Lookup the address is onlink or not. */
102 rn
= bgp_node_match_ipv4 (bgp_connected_table
[AFI_IP
], &attr
->nexthop
);
105 bgp_unlock_node (rn
);
110 else if (afi
== AFI_IP6
)
112 if (attr
->extra
->mp_nexthop_len
== 32)
114 else if (attr
->extra
->mp_nexthop_len
== 16)
116 if (IN6_IS_ADDR_LINKLOCAL (&attr
->extra
->mp_nexthop_global
))
119 rn
= bgp_node_match_ipv6 (bgp_connected_table
[AFI_IP6
],
120 &attr
->extra
->mp_nexthop_global
);
123 bgp_unlock_node (rn
);
128 #endif /* HAVE_IPV6 */
132 /* Reset and free all BGP nexthop cache. */
134 bgp_nexthop_cache_reset (struct bgp_table
*table
)
137 struct bgp_nexthop_cache
*bnc
;
139 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
140 if ((bnc
= rn
->info
) != NULL
)
144 bgp_unlock_node (rn
);
148 /* BGP own address structure */
155 static struct hash
*bgp_address_hash
;
158 bgp_address_hash_alloc (void *p
)
160 struct in_addr
*val
= p
;
161 struct bgp_addr
*addr
;
163 addr
= XMALLOC (MTYPE_BGP_ADDR
, sizeof (struct bgp_addr
));
165 addr
->addr
.s_addr
= val
->s_addr
;
171 bgp_address_hash_key_make (void *p
)
173 const struct bgp_addr
*addr
= p
;
175 return jhash_1word(addr
->addr
.s_addr
, 0);
179 bgp_address_hash_cmp (const void *p1
, const void *p2
)
181 const struct bgp_addr
*addr1
= p1
;
182 const struct bgp_addr
*addr2
= p2
;
184 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
188 bgp_address_init (void)
190 bgp_address_hash
= hash_create (bgp_address_hash_key_make
,
191 bgp_address_hash_cmp
);
195 bgp_address_add (struct prefix
*p
)
198 struct bgp_addr
*addr
;
200 tmp
.addr
= p
->u
.prefix4
;
202 addr
= hash_get (bgp_address_hash
, &tmp
, bgp_address_hash_alloc
);
210 bgp_address_del (struct prefix
*p
)
213 struct bgp_addr
*addr
;
215 tmp
.addr
= p
->u
.prefix4
;
217 addr
= hash_lookup (bgp_address_hash
, &tmp
);
218 /* may have been deleted earlier by bgp_interface_down() */
224 if (addr
->refcnt
== 0)
226 hash_release (bgp_address_hash
, addr
);
227 XFREE (MTYPE_BGP_ADDR
, addr
);
232 struct bgp_connected_ref
238 bgp_connected_add (struct connected
*ifc
)
242 struct interface
*ifp
;
244 struct bgp_connected_ref
*bc
;
251 if (if_is_loopback (ifp
))
256 if (addr
->family
== AF_INET
)
258 PREFIX_COPY_IPV4(&p
, CONNECTED_PREFIX(ifc
));
259 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
261 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
264 bgp_address_add (addr
);
266 rn
= bgp_node_get (bgp_connected_table
[AFI_IP
], (struct prefix
*) &p
);
274 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
280 else if (addr
->family
== AF_INET6
)
282 PREFIX_COPY_IPV6(&p
, CONNECTED_PREFIX(ifc
));
283 apply_mask_ipv6 ((struct prefix_ipv6
*) &p
);
285 if (IN6_IS_ADDR_UNSPECIFIED (&p
.u
.prefix6
))
288 if (IN6_IS_ADDR_LINKLOCAL (&p
.u
.prefix6
))
291 rn
= bgp_node_get (bgp_connected_table
[AFI_IP6
], (struct prefix
*) &p
);
299 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
304 #endif /* HAVE_IPV6 */
308 bgp_connected_delete (struct connected
*ifc
)
312 struct interface
*ifp
;
314 struct bgp_connected_ref
*bc
;
318 if (if_is_loopback (ifp
))
323 if (addr
->family
== AF_INET
)
325 PREFIX_COPY_IPV4(&p
, CONNECTED_PREFIX(ifc
));
326 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
328 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
331 bgp_address_del (addr
);
333 rn
= bgp_node_lookup (bgp_connected_table
[AFI_IP
], &p
);
341 XFREE (MTYPE_BGP_CONN
, bc
);
344 bgp_unlock_node (rn
);
345 bgp_unlock_node (rn
);
348 else if (addr
->family
== AF_INET6
)
350 PREFIX_COPY_IPV6(&p
, CONNECTED_PREFIX(ifc
));
351 apply_mask_ipv6 ((struct prefix_ipv6
*) &p
);
353 if (IN6_IS_ADDR_UNSPECIFIED (&p
.u
.prefix6
))
356 if (IN6_IS_ADDR_LINKLOCAL (&p
.u
.prefix6
))
359 rn
= bgp_node_lookup (bgp_connected_table
[AFI_IP6
], (struct prefix
*) &p
);
367 XFREE (MTYPE_BGP_CONN
, bc
);
370 bgp_unlock_node (rn
);
371 bgp_unlock_node (rn
);
373 #endif /* HAVE_IPV6 */
377 bgp_nexthop_self (struct attr
*attr
)
379 struct bgp_addr tmp
, *addr
;
381 tmp
.addr
= attr
->nexthop
;
383 addr
= hash_lookup (bgp_address_hash
, &tmp
);
392 bgp_multiaccess_check_v4 (struct in_addr nexthop
, struct peer
*peer
)
394 struct bgp_node
*rn1
;
395 struct bgp_node
*rn2
;
400 p
.prefixlen
= IPV4_MAX_BITLEN
;
401 p
.u
.prefix4
= nexthop
;
403 rn1
= bgp_node_match (bgp_connected_table
[AFI_IP
], &p
);
408 p
.prefixlen
= IPV4_MAX_BITLEN
;
409 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
411 rn2
= bgp_node_match (bgp_connected_table
[AFI_IP
], &p
);
414 bgp_unlock_node(rn1
);
418 ret
= (rn1
== rn2
) ? 1 : 0;
420 bgp_unlock_node(rn1
);
421 bgp_unlock_node(rn2
);
427 show_ip_bgp_nexthop_table (struct vty
*vty
, int detail
)
430 struct bgp_nexthop_cache
*bnc
;
431 char buf
[INET6_ADDRSTRLEN
];
432 struct nexthop
*nexthop
;
436 vty_out (vty
, "Current BGP nexthop cache:%s", VTY_NEWLINE
);
437 for (rn
= bgp_table_top (bgp_nexthop_cache_table
[AFI_IP
]); rn
; rn
= bgp_route_next (rn
))
438 if ((bnc
= rn
->info
) != NULL
)
440 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
))
442 vty_out (vty
, " %s valid [IGP metric %d], #paths %d%s",
443 inet_ntop (AF_INET
, &rn
->p
.u
.prefix4
, buf
, INET6_ADDRSTRLEN
),
444 bnc
->metric
, bnc
->path_count
, VTY_NEWLINE
);
446 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
447 switch (nexthop
->type
)
449 case NEXTHOP_TYPE_IPV4
:
450 vty_out (vty
, " gate %s%s",
451 inet_ntop (AF_INET
, &nexthop
->gate
.ipv4
, buf
,
452 INET6_ADDRSTRLEN
), VTY_NEWLINE
);
454 case NEXTHOP_TYPE_IFINDEX
:
455 vty_out (vty
, " if %s%s",
456 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
458 case NEXTHOP_TYPE_IPV4_IFINDEX
:
459 vty_out (vty
, " gate %s, if %s%s",
460 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
462 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
465 vty_out (vty
, " invalid nexthop type %u%s",
466 nexthop
->type
, VTY_NEWLINE
);
470 vty_out (vty
, " %s invalid%s",
471 inet_ntop (AF_INET
, &rn
->p
.u
.prefix4
, buf
, INET6_ADDRSTRLEN
), VTY_NEWLINE
);
472 #ifdef HAVE_CLOCK_MONOTONIC
473 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
474 vty_out (vty
, " Last update: %s", ctime(&tbuf
));
476 vty_out (vty
, " Last update: %s", ctime(&bnc
->uptime
));
477 #endif /* HAVE_CLOCK_MONOTONIC */
479 vty_out(vty
, "%s", VTY_NEWLINE
);
484 for (rn
= bgp_table_top (bgp_nexthop_cache_table
[AFI_IP6
]);
486 rn
= bgp_route_next (rn
))
487 if ((bnc
= rn
->info
) != NULL
)
489 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
))
491 vty_out (vty
, " %s valid [IGP metric %d]%s",
492 inet_ntop (AF_INET6
, &rn
->p
.u
.prefix6
, buf
,
494 bnc
->metric
, VTY_NEWLINE
);
496 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
497 switch (nexthop
->type
)
499 case NEXTHOP_TYPE_IPV6
:
500 vty_out (vty
, " gate %s%s",
501 inet_ntop (AF_INET6
, &nexthop
->gate
.ipv6
,
502 buf
, INET6_ADDRSTRLEN
), VTY_NEWLINE
);
504 case NEXTHOP_TYPE_IPV6_IFINDEX
:
505 vty_out(vty
, " gate %s, if %s%s",
506 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
508 ifindex2ifname(nexthop
->ifindex
),
511 case NEXTHOP_TYPE_IFINDEX
:
512 vty_out (vty
, " ifidx %u%s", nexthop
->ifindex
,
516 vty_out (vty
, " invalid nexthop type %u%s",
517 nexthop
->type
, VTY_NEWLINE
);
521 vty_out (vty
, " %s invalid%s",
522 inet_ntop (AF_INET6
, &rn
->p
.u
.prefix6
, buf
, INET6_ADDRSTRLEN
),
524 #ifdef HAVE_CLOCK_MONOTONIC
525 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
526 vty_out (vty
, " Last update: %s", ctime(&tbuf
));
528 vty_out (vty
, " Last update: %s", ctime(&bnc
->uptime
));
529 #endif /* HAVE_CLOCK_MONOTONIC */
531 vty_out(vty
, "%s", VTY_NEWLINE
);
534 #endif /* HAVE_IPV6 */
538 DEFUN (show_ip_bgp_nexthop
,
539 show_ip_bgp_nexthop_cmd
,
540 "show ip bgp nexthop",
544 "BGP nexthop table\n")
546 return show_ip_bgp_nexthop_table (vty
, 0);
549 DEFUN (show_ip_bgp_nexthop_detail
,
550 show_ip_bgp_nexthop_detail_cmd
,
551 "show ip bgp nexthop detail",
555 "BGP nexthop table\n")
557 return show_ip_bgp_nexthop_table (vty
, 1);
563 cache1_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
564 bgp_nexthop_cache_table
[AFI_IP
] = cache1_table
[AFI_IP
];
566 bgp_connected_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
569 cache1_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
570 bgp_nexthop_cache_table
[AFI_IP6
] = cache1_table
[AFI_IP6
];
571 bgp_connected_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
572 #endif /* HAVE_IPV6 */
579 install_element (ENABLE_NODE
, &show_ip_bgp_nexthop_cmd
);
580 install_element (VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
581 install_element (VIEW_NODE
, &show_ip_bgp_nexthop_detail_cmd
);
582 install_element (ENABLE_NODE
, &show_ip_bgp_nexthop_detail_cmd
);
586 bgp_scan_finish (void)
588 /* Only the current one needs to be reset. */
589 bgp_nexthop_cache_reset (bgp_nexthop_cache_table
[AFI_IP
]);
591 bgp_table_unlock (cache1_table
[AFI_IP
]);
592 cache1_table
[AFI_IP
] = NULL
;
594 bgp_table_unlock (bgp_connected_table
[AFI_IP
]);
595 bgp_connected_table
[AFI_IP
] = NULL
;
598 /* Only the current one needs to be reset. */
599 bgp_nexthop_cache_reset (bgp_nexthop_cache_table
[AFI_IP6
]);
601 bgp_table_unlock (cache1_table
[AFI_IP6
]);
602 cache1_table
[AFI_IP6
] = NULL
;
604 bgp_table_unlock (bgp_connected_table
[AFI_IP6
]);
605 bgp_connected_table
[AFI_IP6
] = NULL
;
606 #endif /* HAVE_IPV6 */