]> git.sommitrealweird.co.uk Git - quagga-debian.git/blob - bgpd/bgp_nht.c
Import Upstream version 1.2.2
[quagga-debian.git] / bgpd / bgp_nht.c
1 /* BGP Nexthop tracking
2  * Copyright (C) 2013 Cumulus Networks, Inc.
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
22 #include <zebra.h>
23
24 #include "command.h"
25 #include "thread.h"
26 #include "prefix.h"
27 #include "zclient.h"
28 #include "stream.h"
29 #include "network.h"
30 #include "log.h"
31 #include "memory.h"
32 #include "nexthop.h"
33 #include "filter.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_debug.h"
41 #include "bgpd/bgp_nht.h"
42 #include "bgpd/bgp_fsm.h"
43 #include "bgpd/bgp_zebra.h"
44
45 extern struct zclient *zclient;
46 extern struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
47
48 static void register_nexthop(struct bgp_nexthop_cache *bnc);
49 static void unregister_nexthop (struct bgp_nexthop_cache *bnc);
50 static void evaluate_paths(struct bgp_nexthop_cache *bnc);
51 static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
52 static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
53                         int keep);
54
55 int
56 bgp_nexthop_check (struct bgp_info *path, int connected)
57 {
58   struct bgp_nexthop_cache *bnc = path->nexthop;
59
60   if (!bnc)
61     return 0;
62
63   if (BGP_DEBUG(nht, NHT))
64     {
65       char buf[INET6_ADDRSTRLEN];
66       zlog_debug("%s: NHT checking %s", 
67                  __FUNCTION__,
68                  bnc_str (bnc, buf, INET6_ADDRSTRLEN));
69     }
70
71   if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
72     return 0;
73
74   return (bgp_zebra_num_connects() == 0 ||
75           CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
76 }
77
78 /* Helper to get the rn for the appropriate nexthop for path or peer.
79  * returns the locked rn - caller must bump down the refcnt.
80  *
81  * may return NULL in error cases.
82  */
83 static
84 struct bgp_node *
85 bgp_get_nexthop_rn (struct bgp_info *path, struct peer *peer)
86 {
87   struct prefix p;
88   afi_t afi;
89   
90   assert (path || peer);
91   
92   if (!(path || peer))
93     return NULL;
94   
95   if (path)
96     {
97       afi = family2afi (path->net->p.family);
98       if (make_prefix(afi, path, &p) < 0)
99         return NULL;
100     }
101   else
102     {
103       afi = family2afi(peer->su.sa.sa_family);
104       if (afi == AFI_IP)
105         {
106           p.family = AF_INET;
107           p.prefixlen = IPV4_MAX_BITLEN;
108           p.u.prefix4 = peer->su.sin.sin_addr;
109         }
110       else if (afi == AFI_IP6)
111         {
112           p.family = AF_INET6;
113           p.prefixlen = IPV6_MAX_BITLEN;
114           p.u.prefix6 = peer->su.sin6.sin6_addr;
115         }
116       else
117         return NULL;
118     }
119   
120   return bgp_node_get (bgp_nexthop_cache_table[afi], &p);
121 }
122
123 static
124 struct bgp_nexthop_cache *
125 bgp_find_nexthop (struct bgp_info *path, struct peer *peer)
126 {
127   struct bgp_nexthop_cache *bnc = NULL;
128   struct bgp_node *rn = bgp_get_nexthop_rn (path, peer);
129   
130   if (!rn)
131     return NULL;
132   
133   bnc = rn->info;
134   bgp_unlock_node (rn);
135   
136   return bnc;
137 }
138
139 static void
140 bgp_unlink_nexthop_check (struct bgp_nexthop_cache *bnc)
141 {
142   if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
143     {
144       if (BGP_DEBUG(nht, NHT))
145         {
146           char buf[INET6_ADDRSTRLEN];
147           zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
148                      bnc_str (bnc, buf, INET6_ADDRSTRLEN));
149         }
150       unregister_nexthop(bnc);
151       bnc->node->info = NULL;
152       bgp_unlock_node (bnc->node);
153       bnc->node = NULL;
154       bnc_free (bnc);
155     }
156 }
157
158 void
159 bgp_unlink_nexthop (struct bgp_info *path)
160 {
161   struct bgp_nexthop_cache *bnc = path->nexthop;
162
163   if (!bnc)
164     return;
165
166   if (BGP_DEBUG(nht, NHT))
167     {
168       char buf[INET6_ADDRSTRLEN];
169       zlog_debug("%s: NHT unlinking %s", 
170                  __FUNCTION__, bnc_str (bnc, buf, INET6_ADDRSTRLEN));
171     }
172   
173   path_nh_map(path, NULL, 0);
174   
175   bgp_unlink_nexthop_check (bnc);
176 }
177
178 void
179 bgp_unlink_nexthop_by_peer (struct peer *peer)
180 {
181   struct bgp_nexthop_cache *bnc = bgp_find_nexthop (NULL, peer);
182      
183   if (!bnc)
184     return;
185
186   if (BGP_DEBUG(nht, NHT))
187     zlog_debug("%s: NHT unlinking %s", 
188                 __FUNCTION__, peer->host);
189   
190   bnc->nht_info = NULL;
191   
192   bgp_unlink_nexthop_check (bnc);
193 }
194
195 int
196 bgp_ensure_nexthop (struct bgp_info *ri, struct peer *peer,
197                     int connected)
198 {
199   struct bgp_node *rn;
200   struct bgp_nexthop_cache *bnc;
201   
202   rn = bgp_get_nexthop_rn (ri, peer);
203   
204   if (!rn)
205     {
206       zlog_debug("%s: NHT could not ensure, failed to get rn!", 
207                  __FUNCTION__);
208       return 0;
209     }
210   
211   if (!rn->info)
212     {
213       bnc = bnc_new();
214       rn->info = bnc;
215       bnc->node = rn;
216       bgp_lock_node(rn);
217       if (connected)
218         SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
219     }
220
221   bnc = rn->info;
222   bgp_unlock_node (rn);
223
224   if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
225     register_nexthop(bnc);
226
227   if (ri)
228     {
229       path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */
230
231       if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
232         (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
233       else if (ri->extra)
234         ri->extra->igpmetric = 0;
235     }
236   else if (peer)
237     bnc->nht_info = (void *)peer; /* NHT peer reference */
238
239   if (BGP_DEBUG(nht, NHT))
240     {
241       char buf[INET6_ADDRSTRLEN];
242       zlog_debug("%s: NHT ensured %s", 
243                  __FUNCTION__, bnc_str (bnc, buf, INET6_ADDRSTRLEN));
244     }
245   
246   return (bgp_zebra_num_connects() == 0 ||
247           CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
248 }
249
250 void
251 bgp_parse_nexthop_update (void)
252 {
253   struct stream *s;
254   struct bgp_node *rn;
255   struct bgp_nexthop_cache *bnc;
256   struct nexthop *nexthop;
257   struct nexthop *oldnh;
258   struct nexthop *nhlist_head = NULL;
259   struct nexthop *nhlist_tail = NULL;
260   uint32_t metric;
261   u_char nexthop_num;
262   struct prefix p;
263   int i;
264
265   s = zclient->ibuf;
266
267   memset(&p, 0, sizeof(struct prefix));
268   p.family = stream_getw(s);
269   p.prefixlen = stream_getc(s);
270   switch (p.family)
271     {
272     case AF_INET:
273       p.u.prefix4.s_addr = stream_get_ipv4 (s);
274       break;
275     case AF_INET6:
276       stream_get(&p.u.prefix6, s, 16);
277       break;
278     default:
279       break;
280     }
281
282   rn = bgp_node_lookup(bgp_nexthop_cache_table[family2afi(p.family)], &p);
283   if (!rn || !rn->info)
284     {
285       if (BGP_DEBUG(nht, NHT))
286         {
287           char buf[INET6_ADDRSTRLEN];
288           prefix2str(&p, buf, INET6_ADDRSTRLEN);
289           zlog_debug("parse nexthop update(%s): rn not found", buf);
290         }
291       if (rn)
292         bgp_unlock_node (rn);
293       return;
294     }
295
296   bnc = rn->info;
297   bgp_unlock_node (rn);
298   bnc->last_update = bgp_clock();
299   bnc->change_flags = 0;
300   metric = stream_getl (s);
301   nexthop_num = stream_getc (s);
302
303   /* debug print the input */
304   if (BGP_DEBUG(nht, NHT))
305     {
306       char buf[INET6_ADDRSTRLEN];
307       prefix2str(&p, buf, INET6_ADDRSTRLEN);
308       zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf,
309                  metric, nexthop_num);
310     }
311
312   if (metric != bnc->metric)
313     bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
314
315   if(nexthop_num != bnc->nexthop_num)
316     bnc->change_flags |= BGP_NEXTHOP_CHANGED;
317
318   if (nexthop_num)
319     {
320       bnc->flags |= BGP_NEXTHOP_VALID;
321       bnc->metric = metric;
322       bnc->nexthop_num = nexthop_num;
323
324       for (i = 0; i < nexthop_num; i++)
325         {
326           nexthop = nexthop_new();
327           nexthop->type = stream_getc (s);
328           switch (nexthop->type)
329             {
330             case ZEBRA_NEXTHOP_IPV4:
331               nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
332               break;
333             case ZEBRA_NEXTHOP_IFINDEX:
334             case ZEBRA_NEXTHOP_IFNAME:
335               nexthop->ifindex = stream_getl (s);
336               break;
337             case ZEBRA_NEXTHOP_IPV4_IFINDEX:
338             case ZEBRA_NEXTHOP_IPV4_IFNAME:
339               nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
340               nexthop->ifindex = stream_getl (s);
341               break;
342 #ifdef HAVE_IPV6
343             case ZEBRA_NEXTHOP_IPV6:
344               stream_get (&nexthop->gate.ipv6, s, 16);
345               break;
346             case ZEBRA_NEXTHOP_IPV6_IFINDEX:
347             case ZEBRA_NEXTHOP_IPV6_IFNAME:
348               stream_get (&nexthop->gate.ipv6, s, 16);
349               nexthop->ifindex = stream_getl (s);
350               break;
351 #endif
352             default:
353               /* do nothing */
354               break;
355             }
356
357           if (nhlist_tail)
358             {
359               nhlist_tail->next = nexthop;
360               nhlist_tail = nexthop;
361             }
362           else
363             {
364               nhlist_tail = nexthop;
365               nhlist_head = nexthop;
366             }
367
368           /* No need to evaluate the nexthop if we have already determined
369            * that there has been a change.
370            */
371           if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
372             continue;
373
374           for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
375               if (nexthop_same_no_recurse(oldnh, nexthop))
376                   break;
377
378           if (!oldnh)
379             bnc->change_flags |= BGP_NEXTHOP_CHANGED;
380         }
381       bnc_nexthop_free(bnc);
382       bnc->nexthop = nhlist_head;
383     }
384   else
385     {
386       bnc->flags &= ~BGP_NEXTHOP_VALID;
387       UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
388       bnc_nexthop_free(bnc);
389       bnc->nexthop = NULL;
390     }
391
392   evaluate_paths(bnc);
393 }
394
395 /**
396  * make_prefix - make a prefix structure from the path (essentially
397  * path's node.
398  */
399 static int
400 make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
401 {
402   memset (p, 0, sizeof (struct prefix));
403   switch (afi)
404     {
405     case AFI_IP:
406       p->family = AF_INET;
407       p->prefixlen = IPV4_MAX_BITLEN;
408       p->u.prefix4 = ri->attr->nexthop;
409       break;
410 #ifdef HAVE_IPV6
411     case AFI_IP6:
412       if (ri->attr->extra->mp_nexthop_len != 16
413           || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global))
414         return -1;
415
416       p->family = AF_INET6;
417       p->prefixlen = IPV6_MAX_BITLEN;
418       p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
419       break;
420 #endif
421     default:
422       break;
423     }
424   return 0;
425 }
426
427 /**
428  * sendmsg_nexthop -- Format and send a nexthop register/Unregister
429  *   command to Zebra.
430  * ARGUMENTS:
431  *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
432  *   int command -- either ZEBRA_NEXTHOP_REGISTER or ZEBRA_NEXTHOP_UNREGISTER
433  * RETURNS:
434  *   void.
435  */
436 static void
437 sendmsg_nexthop (struct bgp_nexthop_cache *bnc, int command)
438 {
439   struct stream *s;
440   struct prefix *p;
441   int ret;
442
443   /* Check socket. */
444   if (!zclient || zclient->sock < 0)
445     {
446       zlog_debug("%s: Can't send NH register, Zebra client not established",
447                  __FUNCTION__);
448       return;
449     }
450
451   p = &(bnc->node->p);
452   s = zclient->obuf;
453   stream_reset (s);
454   zclient_create_header (s, command, VRF_DEFAULT);
455   if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
456     stream_putc(s, 1);
457   else
458     stream_putc(s, 0);
459
460   stream_putw(s, PREFIX_FAMILY(p));
461   stream_putc(s, p->prefixlen);
462   switch (PREFIX_FAMILY(p))
463     {
464     case AF_INET:
465       stream_put_in_addr (s, &p->u.prefix4);
466       break;
467     case AF_INET6:
468       stream_put(s, &(p->u.prefix6), 16);
469       break;
470     default:
471       break;
472     }
473   stream_putw_at (s, 0, stream_get_endp (s));
474
475   ret = zclient_send_message(zclient);
476   /* TBD: handle the failure */
477   if (ret < 0)
478     zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
479
480   if (command == ZEBRA_NEXTHOP_REGISTER)
481     SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
482   else if (command == ZEBRA_NEXTHOP_UNREGISTER)
483     UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
484   return;
485 }
486
487 /**
488  * register_nexthop - register a nexthop with Zebra for notification
489  *    when the route to the nexthop changes.
490  * ARGUMENTS:
491  *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
492  * RETURNS:
493  *   void.
494  */
495 static void
496 register_nexthop (struct bgp_nexthop_cache *bnc)
497 {
498   /* Check if we have already registered */
499   if (bnc->flags & BGP_NEXTHOP_REGISTERED)
500     return;
501   sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_REGISTER);
502 }
503
504 /**
505  * unregister_nexthop -- Unregister the nexthop from Zebra.
506  * ARGUMENTS:
507  *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
508  * RETURNS:
509  *   void.
510  */
511 static void
512 unregister_nexthop (struct bgp_nexthop_cache *bnc)
513 {
514   /* Check if we have already registered */
515   if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
516     return;
517
518   sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_UNREGISTER);
519 }
520
521 /**
522  * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
523  * ARGUMENTS:
524  *   struct bgp_nexthop_cache *bnc -- the nexthop structure.
525  * RETURNS:
526  *   void.
527  */
528 static void
529 evaluate_paths (struct bgp_nexthop_cache *bnc)
530 {
531   struct bgp_node *rn;
532   struct bgp_info *path;
533   struct bgp *bgp = bgp_get_default();
534   int afi;
535   struct peer *peer = (struct peer *)bnc->nht_info;
536
537   LIST_FOREACH(path, &(bnc->paths), nh_thread)
538     {
539       if (!(path->type == ZEBRA_ROUTE_BGP &&
540             path->sub_type == BGP_ROUTE_NORMAL))
541         continue;
542
543       rn = path->net;
544       afi = family2afi(rn->p.family);
545
546       /* Path becomes valid/invalid depending on whether the nexthop
547        * reachable/unreachable.
548        */
549       if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) !=
550           (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? 1 : 0))
551         {
552           if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
553             {
554               bgp_aggregate_decrement (bgp, &rn->p, path,
555                                        afi, SAFI_UNICAST);
556               bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
557             }
558           else
559             {
560               bgp_info_set_flag (rn, path, BGP_INFO_VALID);
561               bgp_aggregate_increment (bgp, &rn->p, path,
562                                        afi, SAFI_UNICAST);
563             }
564         }
565
566       /* Copy the metric to the path. Will be used for bestpath computation */
567       if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
568         (bgp_info_extra_get(path))->igpmetric = bnc->metric;
569       else if (path->extra)
570         path->extra->igpmetric = 0;
571
572       if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_METRIC_CHANGED) ||
573           CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CHANGED))
574         SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
575
576       bgp_process(bgp, rn, afi, SAFI_UNICAST);
577     }
578
579   if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED))
580     {
581       if (BGP_DEBUG(nht, NHT))
582         zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host);
583       SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
584     }
585
586   RESET_FLAG(bnc->change_flags);
587 }
588
589 /**
590  * path_nh_map - make or break path-to-nexthop association.
591  * ARGUMENTS:
592  *   path - pointer to the path structure
593  *   bnc - pointer to the nexthop structure
594  *   make - if set, make the association. if unset, just break the existing
595  *          association.
596  */
597 static void
598 path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make)
599 {
600   if (path->nexthop)
601     {
602       LIST_REMOVE(path, nh_thread);
603       path->nexthop->path_count--;
604       path->nexthop = NULL;
605     }
606   if (make)
607     {
608       LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
609       path->nexthop = bnc;
610       path->nexthop->path_count++;
611     }
612 }