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
21 #include "lib/zebra.h"
22 #include "lib/prefix.h"
23 #include "lib/agg_table.h"
25 #include "lib/memory.h"
26 #include "lib/routemap.h"
28 #include "lib/linklist.h"
29 #include "lib/command.h"
30 #include "lib/stream.h"
32 #include "bgpd/bgpd.h"
33 #include "bgpd/bgp_ecommunity.h"
34 #include "bgpd/bgp_attr.h"
36 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
37 #include "bgpd/rfapi/rfapi.h"
38 #include "bgpd/rfapi/rfapi_backend.h"
40 #include "bgpd/bgp_route.h"
41 #include "bgpd/bgp_mplsvpn.h"
42 #include "bgpd/bgp_aspath.h"
43 #include "bgpd/bgp_advertise.h"
45 #include "bgpd/rfapi/rfapi_import.h"
46 #include "bgpd/rfapi/rfapi_private.h"
47 #include "bgpd/rfapi/rfapi_monitor.h"
48 #include "bgpd/rfapi/rfapi_vty.h"
49 #include "bgpd/rfapi/vnc_export_bgp.h"
50 #include "bgpd/rfapi/vnc_export_bgp_p.h"
51 #include "bgpd/rfapi/vnc_zebra.h"
52 #include "bgpd/rfapi/vnc_import_bgp.h"
53 #include "bgpd/rfapi/rfapi_rib.h"
55 #include "bgpd/rfapi/rfapi_ap.h"
56 #include "bgpd/rfapi/vnc_debug.h"
59 * Per-NVE Advertised prefixes
61 * We maintain a list of prefixes advertised by each NVE.
62 * There are two indices: by prefix and by lifetime.
66 * key: ptr to struct prefix (when storing, point to prefix that
67 * is part of rfapi_adb).
69 * value: ptr to struct rfapi_adb
71 * BY-LIFETIME skiplist
73 * key: ptr to struct rfapi_adb
74 * value: ptr to struct rfapi_adb
79 * Skiplist sort function that sorts first according to lifetime
80 * and then according to adb pointer value. The adb pointer
81 * is used to spread out the sort for adbs with the same lifetime
82 * and thereby make the skip list operations more efficient.
84 static int sl_adb_lifetime_cmp(void *adb1
, void *adb2
)
86 struct rfapi_adb
*a1
= adb1
;
87 struct rfapi_adb
*a2
= adb2
;
89 if (a1
->lifetime
< a2
->lifetime
)
91 if (a1
->lifetime
> a2
->lifetime
)
102 void rfapiApInit(struct rfapi_advertised_prefixes
*ap
)
104 ap
->ipN_by_prefix
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
105 ap
->ip0_by_ether
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
106 ap
->by_lifetime
= skiplist_new(0, sl_adb_lifetime_cmp
, NULL
);
109 void rfapiApRelease(struct rfapi_advertised_prefixes
*ap
)
111 struct rfapi_adb
*adb
;
113 /* Free ADBs and lifetime items */
114 while (0 == skiplist_first(ap
->by_lifetime
, NULL
, (void **)&adb
)) {
116 skiplist_delete_first(ap
->by_lifetime
);
119 while (0 == skiplist_delete_first(ap
->ipN_by_prefix
))
121 while (0 == skiplist_delete_first(ap
->ip0_by_ether
))
125 skiplist_free(ap
->ipN_by_prefix
);
126 skiplist_free(ap
->ip0_by_ether
);
127 skiplist_free(ap
->by_lifetime
);
129 ap
->ipN_by_prefix
= NULL
;
130 ap
->ip0_by_ether
= NULL
;
131 ap
->by_lifetime
= NULL
;
134 int rfapiApCount(struct rfapi_descriptor
*rfd
)
136 if (!rfd
->advertised
.by_lifetime
)
139 return skiplist_count(rfd
->advertised
.by_lifetime
);
142 int rfapiApCountAll(struct bgp
*bgp
)
145 struct listnode
*node
;
146 struct rfapi_descriptor
*rfd
;
151 for (ALL_LIST_ELEMENTS_RO(&h
->descriptors
, node
, rfd
)) {
152 total
+= rfapiApCount(rfd
);
159 void rfapiApReadvertiseAll(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
161 struct rfapi_adb
*adb
;
165 for (rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
166 (void **)&adb
, &cursor
);
167 rc
== 0; rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
168 (void **)&adb
, &cursor
)) {
170 struct prefix_rd prd
;
171 uint32_t local_pref
= rfp_cost_to_localpref(adb
->cost
);
174 prd
.family
= AF_UNSPEC
;
178 * TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
179 * we need to substitute the VN address as the prefix
181 add_vnc_route(rfd
, bgp
, SAFI_MPLS_VPN
, &adb
->u
.s
.prefix_ip
,
182 &prd
, /* RD to use (0 for ENCAP) */
183 &rfd
->vn_addr
, /* nexthop */
184 &local_pref
, &adb
->lifetime
, NULL
,
185 NULL
, /* struct rfapi_un_option */
186 NULL
, /* struct rfapi_vn_option */
187 rfd
->rt_export_list
, NULL
, /* med */
188 NULL
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
192 void rfapiApWithdrawAll(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
194 struct rfapi_adb
*adb
;
200 for (rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
201 (void **)&adb
, &cursor
);
202 rc
== 0; rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
203 (void **)&adb
, &cursor
)) {
205 struct prefix pfx_vn_buf
;
206 struct prefix
*pfx_ip
;
208 if (!(RFAPI_0_PREFIX(&adb
->u
.s
.prefix_ip
)
209 && RFAPI_HOST_PREFIX(&adb
->u
.s
.prefix_ip
))) {
211 pfx_ip
= &adb
->u
.s
.prefix_ip
;
218 * 0/32 or 0/128 => mac advertisement
220 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn_buf
)) {
222 * Bad: it means we can't delete the route
224 vnc_zlog_debug_verbose(
225 "%s: BAD: handle has bad vn_addr: skipping",
231 del_vnc_route(rfd
, rfd
->peer
, bgp
, SAFI_MPLS_VPN
,
232 pfx_ip
? pfx_ip
: &pfx_vn_buf
,
233 &adb
->u
.s
.prd
, /* RD to use (0 for ENCAP) */
234 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
, 0);
239 * returns nonzero if tunnel readvertisement is needed, 0 otherwise
241 static int rfapiApAdjustLifetimeStats(
242 struct rfapi_descriptor
*rfd
,
243 uint32_t *old_lifetime
, /* set if removing/replacing */
244 uint32_t *new_lifetime
) /* set if replacing/adding */
250 vnc_zlog_debug_verbose("%s: rfd=%p, pOldLife=%p, pNewLife=%p", __func__
,
251 rfd
, old_lifetime
, new_lifetime
);
253 vnc_zlog_debug_verbose("%s: OldLife=%d", __func__
,
256 vnc_zlog_debug_verbose("%s: NewLife=%d", __func__
,
261 * Adding new lifetime
265 * replacing existing lifetime
269 /* old and new are same */
270 if (*old_lifetime
== *new_lifetime
)
273 if (*old_lifetime
== rfd
->min_prefix_lifetime
) {
276 if (*old_lifetime
== rfd
->max_prefix_lifetime
) {
280 /* no need to search if new value is at or equals
282 if (*new_lifetime
<= rfd
->min_prefix_lifetime
) {
283 rfd
->min_prefix_lifetime
= *new_lifetime
;
286 if (*new_lifetime
>= rfd
->max_prefix_lifetime
) {
287 rfd
->max_prefix_lifetime
= *new_lifetime
;
294 * Just adding new lifetime
296 if (*new_lifetime
< rfd
->min_prefix_lifetime
) {
297 rfd
->min_prefix_lifetime
= *new_lifetime
;
299 if (*new_lifetime
> rfd
->max_prefix_lifetime
) {
301 rfd
->max_prefix_lifetime
= *new_lifetime
;
310 * See if the max prefix lifetime for this NVE has decreased.
311 * The easy optimization: track min & max; walk the table only
312 * if they are different.
313 * The general optimization: index the advertised_prefixes
316 * Note: for a given nve_descriptor, only one of the
317 * advertised_prefixes[] tables will be used: viz., the
318 * address family that matches the VN address.
321 if (rfd
->max_prefix_lifetime
== rfd
->min_prefix_lifetime
) {
324 * Common case: all lifetimes are the same. Only
325 * thing we need to do here is check if there are
326 * no exported routes left. In that case, reinitialize
327 * the max and min values.
329 if (!rfapiApCount(rfd
)) {
330 rfd
->max_prefix_lifetime
= 0;
331 rfd
->min_prefix_lifetime
= UINT32_MAX
;
337 if (*old_lifetime
== rfd
->min_prefix_lifetime
) {
340 if (*old_lifetime
== rfd
->max_prefix_lifetime
) {
347 if (find_min
|| find_max
) {
348 uint32_t min
= UINT32_MAX
;
351 struct rfapi_adb
*adb_min
;
352 struct rfapi_adb
*adb_max
;
354 if (!skiplist_first(rfd
->advertised
.by_lifetime
,
355 (void **)&adb_min
, NULL
)
356 && !skiplist_last(rfd
->advertised
.by_lifetime
,
357 (void **)&adb_max
, NULL
)) {
360 * This should always work
362 min
= adb_min
->lifetime
;
363 max
= adb_max
->lifetime
;
368 struct rfapi_rib_key rk
;
369 struct rfapi_adb
*adb
;
372 vnc_zlog_debug_verbose(
373 "%s: walking to find new min/max", __func__
);
376 for (rc
= skiplist_next(rfd
->advertised
.ipN_by_prefix
,
377 (void **)&rk
, (void **)&adb
,
380 rc
= skiplist_next(rfd
->advertised
.ipN_by_prefix
,
381 (void **)&rk
, (void **)&adb
,
384 uint32_t lt
= adb
->lifetime
;
392 for (rc
= skiplist_next(rfd
->advertised
.ip0_by_ether
,
393 (void **)&rk
, (void **)&adb
,
396 rc
= skiplist_next(rfd
->advertised
.ip0_by_ether
,
397 (void **)&rk
, (void **)&adb
,
400 uint32_t lt
= adb
->lifetime
;
410 * trigger tunnel route update
411 * but only if we found a VPN route and it had
412 * a lifetime greater than 0
414 if (max
&& rfd
->max_prefix_lifetime
!= max
)
416 rfd
->max_prefix_lifetime
= max
;
417 rfd
->min_prefix_lifetime
= min
;
420 vnc_zlog_debug_verbose("%s: returning advertise=%d, min=%d, max=%d",
421 __func__
, advertise
, rfd
->min_prefix_lifetime
,
422 rfd
->max_prefix_lifetime
);
424 return (advertise
!= 0);
430 * 0 No need to advertise tunnel route
431 * non-0 advertise tunnel route
433 int rfapiApAdd(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
434 struct prefix
*pfx_ip
, struct prefix
*pfx_eth
,
435 struct prefix_rd
*prd
, uint32_t lifetime
, uint8_t cost
,
436 struct rfapi_l2address_option
*l2o
) /* other options TBD */
439 struct rfapi_adb
*adb
;
440 uint32_t old_lifetime
= 0;
442 struct rfapi_rib_key rk
;
444 rfapi_rib_key_init(pfx_ip
, prd
, pfx_eth
, &rk
);
445 if (RFAPI_0_PREFIX(pfx_ip
) && RFAPI_HOST_PREFIX(pfx_ip
)) {
448 rc
= skiplist_search(rfd
->advertised
.ip0_by_ether
, &rk
,
453 /* find prefix in advertised prefixes list */
454 rc
= skiplist_search(rfd
->advertised
.ipN_by_prefix
, &rk
,
461 adb
= XCALLOC(MTYPE_RFAPI_ADB
, sizeof(struct rfapi_adb
));
463 adb
->lifetime
= lifetime
;
468 skiplist_insert(rfd
->advertised
.ip0_by_ether
,
471 skiplist_insert(rfd
->advertised
.ipN_by_prefix
,
475 skiplist_insert(rfd
->advertised
.by_lifetime
, adb
, adb
);
477 old_lifetime
= adb
->lifetime
;
478 if (old_lifetime
!= lifetime
) {
479 assert(!skiplist_delete(rfd
->advertised
.by_lifetime
,
481 adb
->lifetime
= lifetime
;
482 assert(!skiplist_insert(rfd
->advertised
.by_lifetime
,
490 memset(&adb
->l2o
, 0, sizeof(struct rfapi_l2address_option
));
492 if (rfapiApAdjustLifetimeStats(rfd
, (rc
? NULL
: &old_lifetime
),
500 * After this function returns successfully, caller should call
501 * rfapiAdjustLifetimeStats() and possibly rfapiTunnelRouteAnnounce()
503 int rfapiApDelete(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
504 struct prefix
*pfx_ip
, struct prefix
*pfx_eth
,
505 struct prefix_rd
*prd
, int *advertise_tunnel
) /* out */
508 struct rfapi_adb
*adb
;
509 uint32_t old_lifetime
;
511 struct rfapi_rib_key rk
;
513 if (advertise_tunnel
)
514 *advertise_tunnel
= 0;
516 rfapi_rib_key_init(pfx_ip
, prd
, pfx_eth
, &rk
);
517 /* find prefix in advertised prefixes list */
518 if (RFAPI_0_PREFIX(pfx_ip
) && RFAPI_HOST_PREFIX(pfx_ip
)) {
522 rc
= skiplist_search(rfd
->advertised
.ip0_by_ether
, &rk
,
527 /* find prefix in advertised prefixes list */
528 rc
= skiplist_search(rfd
->advertised
.ipN_by_prefix
, &rk
,
536 old_lifetime
= adb
->lifetime
;
539 rc
= skiplist_delete(rfd
->advertised
.ip0_by_ether
, &rk
, NULL
);
541 rc
= skiplist_delete(rfd
->advertised
.ipN_by_prefix
, &rk
, NULL
);
545 rc
= skiplist_delete(rfd
->advertised
.by_lifetime
, adb
, NULL
);
550 if (rfapiApAdjustLifetimeStats(rfd
, &old_lifetime
, NULL
)) {
551 if (advertise_tunnel
)
552 *advertise_tunnel
= 1;