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