blob: 09b4695166b25554a47cee85804d99257f916714 [file] [log] [blame]
Josh Bailey165b5ff2011-07-20 20:43:22 -07001/* $QuaggaId: Format:%an, %ai, %h$ $
2 *
3 * BGP Multipath
4 * Copyright (C) 2010 Google Inc.
5 *
6 * This file is part of Quagga
7 *
8 * Quagga is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * Quagga is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Quagga; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 */
23
24#include <zebra.h>
25
26#include "command.h"
Josh Bailey96450fa2011-07-20 20:45:12 -070027#include "prefix.h"
28#include "linklist.h"
29#include "sockunion.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070030
31#include "bgpd/bgpd.h"
Josh Bailey96450fa2011-07-20 20:45:12 -070032#include "bgpd/bgp_table.h"
33#include "bgpd/bgp_route.h"
34#include "bgpd/bgp_attr.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070035#include "bgpd/bgp_mpath.h"
36
37/*
38 * bgp_maximum_paths_set
39 *
40 * Record maximum-paths configuration for BGP instance
41 */
42int
43bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi,
44 int peertype, u_int16_t maxpaths)
45{
46 if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX))
47 return -1;
48
49 switch (peertype)
50 {
51 case BGP_PEER_IBGP:
52 bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths;
53 break;
54 case BGP_PEER_EBGP:
55 bgp->maxpaths[afi][safi].maxpaths_ebgp = maxpaths;
56 break;
57 default:
58 return -1;
59 }
60
61 return 0;
62}
63
64/*
65 * bgp_maximum_paths_unset
66 *
67 * Remove maximum-paths configuration from BGP instance
68 */
69int
70bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi,
71 int peertype)
72{
73 if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX))
74 return -1;
75
76 switch (peertype)
77 {
78 case BGP_PEER_IBGP:
79 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
80 break;
81 case BGP_PEER_EBGP:
82 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
83 break;
84 default:
85 return -1;
86 }
87
88 return 0;
89}
Josh Bailey96450fa2011-07-20 20:45:12 -070090
91/*
92 * bgp_info_nexthop_cmp
93 *
94 * Compare the nexthops of two paths. Return value is less than, equal to,
95 * or greater than zero if bi1 is respectively less than, equal to,
96 * or greater than bi2.
97 */
98static int
99bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2)
100{
101 struct attr_extra *ae1, *ae2;
102 int compare;
103
104 ae1 = bgp_attr_extra_get (bi1->attr);
105 ae2 = bgp_attr_extra_get (bi2->attr);
106
107 compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop);
108
109 if (!compare && ae1 && ae2 && (ae1->mp_nexthop_len == ae2->mp_nexthop_len))
110 {
111 switch (ae1->mp_nexthop_len)
112 {
113 case 4:
114 case 12:
115 compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in,
116 &ae2->mp_nexthop_global_in);
117 break;
118#ifdef HAVE_IPV6
119 case 16:
120 compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
121 &ae2->mp_nexthop_global);
122 break;
123 case 32:
124 compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
125 &ae2->mp_nexthop_global);
126 if (!compare)
127 compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local,
128 &ae2->mp_nexthop_local);
129 break;
130#endif /* HAVE_IPV6 */
131 }
132 }
133
134 return compare;
135}
136
137/*
138 * bgp_info_mpath_cmp
139 *
140 * This function determines our multipath list ordering. By ordering
141 * the list we can deterministically select which paths are included
142 * in the multipath set. The ordering also helps in detecting changes
143 * in the multipath selection so we can detect whether to send an
144 * update to zebra.
145 *
146 * The order of paths is determined first by received nexthop, and then
147 * by peer address if the nexthops are the same.
148 */
149static int
150bgp_info_mpath_cmp (void *val1, void *val2)
151{
152 struct bgp_info *bi1, *bi2;
153 int compare;
154
155 bi1 = val1;
156 bi2 = val2;
157
158 compare = bgp_info_nexthop_cmp (bi1, bi2);
159
160 if (!compare)
161 compare = sockunion_cmp (bi1->peer->su_remote, bi2->peer->su_remote);
162
163 return compare;
164}
165
166/*
167 * bgp_mp_list_init
168 *
169 * Initialize the mp_list, which holds the list of multipaths
170 * selected by bgp_best_selection
171 */
172void
173bgp_mp_list_init (struct list *mp_list)
174{
175 assert (mp_list);
176 memset (mp_list, 0, sizeof (struct list));
177 mp_list->cmp = bgp_info_mpath_cmp;
178}
179
180/*
181 * bgp_mp_list_clear
182 *
183 * Clears all entries out of the mp_list
184 */
185void
186bgp_mp_list_clear (struct list *mp_list)
187{
188 assert (mp_list);
189 list_delete_all_node (mp_list);
190}
191
192/*
193 * bgp_mp_list_add
194 *
195 * Adds a multipath entry to the mp_list
196 */
197void
198bgp_mp_list_add (struct list *mp_list, struct bgp_info *mpinfo)
199{
200 assert (mp_list && mpinfo);
201 listnode_add_sort (mp_list, mpinfo);
202}