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