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