3 * Copyright 2009-2016, LabN Consulting, L.L.C.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "lib/zebra.h"
24 #include "lib/prefix.h"
25 #include "lib/table.h"
27 #include "lib/memory.h"
28 #include "lib/routemap.h"
30 #include "lib/linklist.h"
31 #include "lib/command.h"
32 #include "lib/stream.h"
34 #include "bgpd/bgpd.h"
35 #include "bgpd/bgp_ecommunity.h"
36 #include "bgpd/bgp_attr.h"
38 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
39 #include "bgpd/rfapi/rfapi.h"
40 #include "bgpd/rfapi/rfapi_backend.h"
42 #include "bgpd/bgp_route.h"
43 #include "bgpd/bgp_mplsvpn.h"
44 #include "bgpd/bgp_aspath.h"
45 #include "bgpd/bgp_advertise.h"
47 #include "bgpd/rfapi/rfapi_import.h"
48 #include "bgpd/rfapi/rfapi_private.h"
49 #include "bgpd/rfapi/rfapi_monitor.h"
50 #include "bgpd/rfapi/rfapi_vty.h"
51 #include "bgpd/rfapi/vnc_export_bgp.h"
52 #include "bgpd/rfapi/vnc_export_bgp_p.h"
53 #include "bgpd/rfapi/vnc_zebra.h"
54 #include "bgpd/rfapi/vnc_import_bgp.h"
55 #include "bgpd/rfapi/rfapi_rib.h"
57 #include "bgpd/rfapi/rfapi_ap.h"
58 #include "bgpd/rfapi/vnc_debug.h"
61 * Per-NVE Advertised prefixes
63 * We maintain a list of prefixes advertised by each NVE.
64 * There are two indices: by prefix and by lifetime.
68 * key: ptr to struct prefix (when storing, point to prefix that
69 * is part of rfapi_adb).
71 * value: ptr to struct rfapi_adb
73 * BY-LIFETIME skiplist
75 * key: ptr to struct rfapi_adb
76 * value: ptr to struct rfapi_adb
81 * Skiplist sort function that sorts first according to lifetime
82 * and then according to adb pointer value. The adb pointer
83 * is used to spread out the sort for adbs with the same lifetime
84 * and thereby make the skip list operations more efficient.
86 static int sl_adb_lifetime_cmp(void *adb1
, void *adb2
)
88 struct rfapi_adb
*a1
= adb1
;
89 struct rfapi_adb
*a2
= adb2
;
91 if (a1
->lifetime
< a2
->lifetime
)
93 if (a1
->lifetime
> a2
->lifetime
)
104 void rfapiApInit(struct rfapi_advertised_prefixes
*ap
)
106 ap
->ipN_by_prefix
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
107 ap
->ip0_by_ether
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
108 ap
->by_lifetime
= skiplist_new(0, sl_adb_lifetime_cmp
, NULL
);
111 void rfapiApRelease(struct rfapi_advertised_prefixes
*ap
)
113 struct rfapi_adb
*adb
;
115 /* Free ADBs and lifetime items */
116 while (0 == skiplist_first(ap
->by_lifetime
, NULL
, (void **)&adb
)) {
118 skiplist_delete_first(ap
->by_lifetime
);
121 while (0 == skiplist_delete_first(ap
->ipN_by_prefix
))
123 while (0 == skiplist_delete_first(ap
->ip0_by_ether
))
127 skiplist_free(ap
->ipN_by_prefix
);
128 skiplist_free(ap
->ip0_by_ether
);
129 skiplist_free(ap
->by_lifetime
);
131 ap
->ipN_by_prefix
= NULL
;
132 ap
->ip0_by_ether
= NULL
;
133 ap
->by_lifetime
= NULL
;
136 int rfapiApCount(struct rfapi_descriptor
*rfd
)
138 if (!rfd
->advertised
.by_lifetime
)
141 return skiplist_count(rfd
->advertised
.by_lifetime
);
144 int rfapiApCountAll(struct bgp
*bgp
)
147 struct listnode
*node
;
148 struct rfapi_descriptor
*rfd
;
153 for (ALL_LIST_ELEMENTS_RO(&h
->descriptors
, node
, rfd
)) {
154 total
+= rfapiApCount(rfd
);
161 void rfapiApReadvertiseAll(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
163 struct rfapi_adb
*adb
;
167 for (rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
168 (void **)&adb
, &cursor
);
169 rc
== 0; rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
170 (void **)&adb
, &cursor
)) {
172 struct prefix_rd prd
;
173 uint32_t local_pref
= rfp_cost_to_localpref(adb
->cost
);
176 prd
.family
= AF_UNSPEC
;
180 * TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
181 * we need to substitute the VN address as the prefix
183 add_vnc_route(rfd
, bgp
, SAFI_MPLS_VPN
, &adb
->u
.s
.prefix_ip
,
184 &prd
, /* RD to use (0 for ENCAP) */
185 &rfd
->vn_addr
, /* nexthop */
186 &local_pref
, &adb
->lifetime
, NULL
,
187 NULL
, /* struct rfapi_un_option */
188 NULL
, /* struct rfapi_vn_option */
189 rfd
->rt_export_list
, NULL
, /* med */
190 NULL
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
194 void rfapiApWithdrawAll(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
196 struct rfapi_adb
*adb
;
202 for (rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
203 (void **)&adb
, &cursor
);
204 rc
== 0; rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
205 (void **)&adb
, &cursor
)) {
207 struct prefix pfx_vn_buf
;
208 struct prefix
*pfx_ip
;
210 if (!(RFAPI_0_PREFIX(&adb
->u
.s
.prefix_ip
)
211 && RFAPI_HOST_PREFIX(&adb
->u
.s
.prefix_ip
))) {
213 pfx_ip
= &adb
->u
.s
.prefix_ip
;
220 * 0/32 or 0/128 => mac advertisement
222 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn_buf
)) {
224 * Bad: it means we can't delete the route
226 vnc_zlog_debug_verbose(
227 "%s: BAD: handle has bad vn_addr: skipping",
233 del_vnc_route(rfd
, rfd
->peer
, bgp
, SAFI_MPLS_VPN
,
234 pfx_ip
? pfx_ip
: &pfx_vn_buf
,
235 &adb
->u
.s
.prd
, /* RD to use (0 for ENCAP) */
236 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
, 0);
241 * returns nonzero if tunnel readvertisement is needed, 0 otherwise
243 static int rfapiApAdjustLifetimeStats(
244 struct rfapi_descriptor
*rfd
,
245 uint32_t *old_lifetime
, /* set if removing/replacing */
246 uint32_t *new_lifetime
) /* set if replacing/adding */
252 vnc_zlog_debug_verbose("%s: rfd=%p, pOldLife=%p, pNewLife=%p", __func__
,
253 rfd
, old_lifetime
, new_lifetime
);
255 vnc_zlog_debug_verbose("%s: OldLife=%d", __func__
,
258 vnc_zlog_debug_verbose("%s: NewLife=%d", __func__
,
263 * Adding new lifetime
267 * replacing existing lifetime
271 /* old and new are same */
272 if (*old_lifetime
== *new_lifetime
)
275 if (*old_lifetime
== rfd
->min_prefix_lifetime
) {
278 if (*old_lifetime
== rfd
->max_prefix_lifetime
) {
282 /* no need to search if new value is at or equals
284 if (*new_lifetime
<= rfd
->min_prefix_lifetime
) {
285 rfd
->min_prefix_lifetime
= *new_lifetime
;
288 if (*new_lifetime
>= rfd
->max_prefix_lifetime
) {
289 rfd
->max_prefix_lifetime
= *new_lifetime
;
296 * Just adding new lifetime
298 if (*new_lifetime
< rfd
->min_prefix_lifetime
) {
299 rfd
->min_prefix_lifetime
= *new_lifetime
;
301 if (*new_lifetime
> rfd
->max_prefix_lifetime
) {
303 rfd
->max_prefix_lifetime
= *new_lifetime
;
312 * See if the max prefix lifetime for this NVE has decreased.
313 * The easy optimization: track min & max; walk the table only
314 * if they are different.
315 * The general optimization: index the advertised_prefixes
318 * Note: for a given nve_descriptor, only one of the
319 * advertised_prefixes[] tables will be used: viz., the
320 * address family that matches the VN address.
323 if (rfd
->max_prefix_lifetime
== rfd
->min_prefix_lifetime
) {
326 * Common case: all lifetimes are the same. Only
327 * thing we need to do here is check if there are
328 * no exported routes left. In that case, reinitialize
329 * the max and min values.
331 if (!rfapiApCount(rfd
)) {
332 rfd
->max_prefix_lifetime
= 0;
333 rfd
->min_prefix_lifetime
= UINT32_MAX
;
339 if (*old_lifetime
== rfd
->min_prefix_lifetime
) {
342 if (*old_lifetime
== rfd
->max_prefix_lifetime
) {
349 if (find_min
|| find_max
) {
350 uint32_t min
= UINT32_MAX
;
353 struct rfapi_adb
*adb_min
;
354 struct rfapi_adb
*adb_max
;
356 if (!skiplist_first(rfd
->advertised
.by_lifetime
,
357 (void **)&adb_min
, NULL
)
358 && !skiplist_last(rfd
->advertised
.by_lifetime
,
359 (void **)&adb_max
, NULL
)) {
362 * This should always work
364 min
= adb_min
->lifetime
;
365 max
= adb_max
->lifetime
;
370 struct rfapi_rib_key rk
;
371 struct rfapi_adb
*adb
;
374 vnc_zlog_debug_verbose(
375 "%s: walking to find new min/max", __func__
);
378 for (rc
= skiplist_next(rfd
->advertised
.ipN_by_prefix
,
379 (void **)&rk
, (void **)&adb
,
382 rc
= skiplist_next(rfd
->advertised
.ipN_by_prefix
,
383 (void **)&rk
, (void **)&adb
,
386 uint32_t lt
= adb
->lifetime
;
394 for (rc
= skiplist_next(rfd
->advertised
.ip0_by_ether
,
395 (void **)&rk
, (void **)&adb
,
398 rc
= skiplist_next(rfd
->advertised
.ip0_by_ether
,
399 (void **)&rk
, (void **)&adb
,
402 uint32_t lt
= adb
->lifetime
;
412 * trigger tunnel route update
413 * but only if we found a VPN route and it had
414 * a lifetime greater than 0
416 if (max
&& rfd
->max_prefix_lifetime
!= max
)
418 rfd
->max_prefix_lifetime
= max
;
419 rfd
->min_prefix_lifetime
= min
;
422 vnc_zlog_debug_verbose("%s: returning advertise=%d, min=%d, max=%d",
423 __func__
, advertise
, rfd
->min_prefix_lifetime
,
424 rfd
->max_prefix_lifetime
);
426 return (advertise
!= 0);
432 * 0 No need to advertise tunnel route
433 * non-0 advertise tunnel route
435 int rfapiApAdd(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
436 struct prefix
*pfx_ip
, struct prefix
*pfx_eth
,
437 struct prefix_rd
*prd
, uint32_t lifetime
, uint8_t cost
,
438 struct rfapi_l2address_option
*l2o
) /* other options TBD */
441 struct rfapi_adb
*adb
;
442 uint32_t old_lifetime
= 0;
444 struct rfapi_rib_key rk
;
446 rfapi_rib_key_init(pfx_ip
, prd
, pfx_eth
, &rk
);
447 if (RFAPI_0_PREFIX(pfx_ip
) && RFAPI_HOST_PREFIX(pfx_ip
)) {
450 rc
= skiplist_search(rfd
->advertised
.ip0_by_ether
, &rk
,
455 /* find prefix in advertised prefixes list */
456 rc
= skiplist_search(rfd
->advertised
.ipN_by_prefix
, &rk
,
463 adb
= XCALLOC(MTYPE_RFAPI_ADB
, sizeof(struct rfapi_adb
));
465 adb
->lifetime
= lifetime
;
470 skiplist_insert(rfd
->advertised
.ip0_by_ether
,
473 skiplist_insert(rfd
->advertised
.ipN_by_prefix
,
477 skiplist_insert(rfd
->advertised
.by_lifetime
, adb
, adb
);
479 old_lifetime
= adb
->lifetime
;
480 if (old_lifetime
!= lifetime
) {
481 assert(!skiplist_delete(rfd
->advertised
.by_lifetime
,
483 adb
->lifetime
= lifetime
;
484 assert(!skiplist_insert(rfd
->advertised
.by_lifetime
,
492 memset(&adb
->l2o
, 0, sizeof(struct rfapi_l2address_option
));
494 if (rfapiApAdjustLifetimeStats(rfd
, (rc
? NULL
: &old_lifetime
),
502 * After this function returns successfully, caller should call
503 * rfapiAdjustLifetimeStats() and possibly rfapiTunnelRouteAnnounce()
505 int rfapiApDelete(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
506 struct prefix
*pfx_ip
, struct prefix
*pfx_eth
,
507 struct prefix_rd
*prd
, int *advertise_tunnel
) /* out */
510 struct rfapi_adb
*adb
;
511 uint32_t old_lifetime
;
513 struct rfapi_rib_key rk
;
515 if (advertise_tunnel
)
516 *advertise_tunnel
= 0;
518 rfapi_rib_key_init(pfx_ip
, prd
, pfx_eth
, &rk
);
519 /* find prefix in advertised prefixes list */
520 if (RFAPI_0_PREFIX(pfx_ip
) && RFAPI_HOST_PREFIX(pfx_ip
)) {
524 rc
= skiplist_search(rfd
->advertised
.ip0_by_ether
, &rk
,
529 /* find prefix in advertised prefixes list */
530 rc
= skiplist_search(rfd
->advertised
.ipN_by_prefix
, &rk
,
538 old_lifetime
= adb
->lifetime
;
541 rc
= skiplist_delete(rfd
->advertised
.ip0_by_ether
, &rk
, NULL
);
543 rc
= skiplist_delete(rfd
->advertised
.ipN_by_prefix
, &rk
, NULL
);
547 rc
= skiplist_delete(rfd
->advertised
.by_lifetime
, adb
, NULL
);
552 if (rfapiApAdjustLifetimeStats(rfd
, &old_lifetime
, NULL
)) {
553 if (advertise_tunnel
)
554 *advertise_tunnel
= 1;