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
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "lib/zebra.h"
25 #include "lib/prefix.h"
26 #include "lib/table.h"
28 #include "lib/memory.h"
29 #include "lib/routemap.h"
31 #include "lib/linklist.h"
32 #include "lib/command.h"
33 #include "lib/stream.h"
35 #include "bgpd/bgpd.h"
36 #include "bgpd/bgp_ecommunity.h"
37 #include "bgpd/bgp_attr.h"
39 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
40 #include "bgpd/rfapi/rfapi.h"
41 #include "bgpd/rfapi/rfapi_backend.h"
43 #include "bgpd/bgp_route.h"
44 #include "bgpd/bgp_mplsvpn.h"
45 #include "bgpd/bgp_aspath.h"
46 #include "bgpd/bgp_advertise.h"
48 #include "bgpd/rfapi/rfapi_import.h"
49 #include "bgpd/rfapi/rfapi_private.h"
50 #include "bgpd/rfapi/rfapi_monitor.h"
51 #include "bgpd/rfapi/rfapi_vty.h"
52 #include "bgpd/rfapi/vnc_export_bgp.h"
53 #include "bgpd/rfapi/vnc_export_bgp_p.h"
54 #include "bgpd/rfapi/vnc_zebra.h"
55 #include "bgpd/rfapi/vnc_import_bgp.h"
56 #include "bgpd/rfapi/rfapi_rib.h"
58 #include "bgpd/rfapi/rfapi_ap.h"
59 #include "bgpd/rfapi/vnc_debug.h"
62 * Per-NVE Advertised prefixes
64 * We maintain a list of prefixes advertised by each NVE.
65 * There are two indices: by prefix and by lifetime.
69 * key: ptr to struct prefix (when storing, point to prefix that
70 * is part of rfapi_adb).
72 * value: ptr to struct rfapi_adb
74 * BY-LIFETIME skiplist
76 * key: ptr to struct rfapi_adb
77 * value: ptr to struct rfapi_adb
82 * Skiplist sort function that sorts first according to lifetime
83 * and then according to adb pointer value. The adb pointer
84 * is used to spread out the sort for adbs with the same lifetime
85 * and thereby make the skip list operations more efficient.
87 static int sl_adb_lifetime_cmp(void *adb1
, void *adb2
)
89 struct rfapi_adb
*a1
= adb1
;
90 struct rfapi_adb
*a2
= adb2
;
92 if (a1
->lifetime
< a2
->lifetime
)
94 if (a1
->lifetime
> a2
->lifetime
)
105 void rfapiApInit(struct rfapi_advertised_prefixes
*ap
)
107 ap
->ipN_by_prefix
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
108 ap
->ip0_by_ether
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
109 ap
->by_lifetime
= skiplist_new(0, sl_adb_lifetime_cmp
, NULL
);
112 void rfapiApRelease(struct rfapi_advertised_prefixes
*ap
)
114 struct rfapi_adb
*adb
;
116 /* Free ADBs and lifetime items */
117 while (0 == skiplist_first(ap
->by_lifetime
, NULL
, (void **)&adb
)) {
119 skiplist_delete_first(ap
->by_lifetime
);
122 while (0 == skiplist_delete_first(ap
->ipN_by_prefix
))
124 while (0 == skiplist_delete_first(ap
->ip0_by_ether
))
128 skiplist_free(ap
->ipN_by_prefix
);
129 skiplist_free(ap
->ip0_by_ether
);
130 skiplist_free(ap
->by_lifetime
);
132 ap
->ipN_by_prefix
= NULL
;
133 ap
->ip0_by_ether
= NULL
;
134 ap
->by_lifetime
= NULL
;
137 int rfapiApCount(struct rfapi_descriptor
*rfd
)
139 if (!rfd
->advertised
.by_lifetime
)
142 return skiplist_count(rfd
->advertised
.by_lifetime
);
145 int rfapiApCountAll(struct bgp
*bgp
)
148 struct listnode
*node
;
149 struct rfapi_descriptor
*rfd
;
154 for (ALL_LIST_ELEMENTS_RO(&h
->descriptors
, node
, rfd
)) {
155 total
+= rfapiApCount(rfd
);
162 void rfapiApReadvertiseAll(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
164 struct rfapi_adb
*adb
;
168 for (rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
169 (void **)&adb
, &cursor
);
170 rc
== 0; rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
171 (void **)&adb
, &cursor
)) {
173 struct prefix_rd prd
;
174 uint32_t local_pref
= rfp_cost_to_localpref(adb
->cost
);
177 prd
.family
= AF_UNSPEC
;
181 * TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
182 * we need to substitute the VN address as the prefix
184 add_vnc_route(rfd
, bgp
, SAFI_MPLS_VPN
, &adb
->u
.s
.prefix_ip
,
185 &prd
, /* RD to use (0 for ENCAP) */
186 &rfd
->vn_addr
, /* nexthop */
187 &local_pref
, &adb
->lifetime
, NULL
,
188 NULL
, /* struct rfapi_un_option */
189 NULL
, /* struct rfapi_vn_option */
190 rfd
->rt_export_list
, NULL
, /* med */
191 NULL
, ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, 0);
195 void rfapiApWithdrawAll(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
197 struct rfapi_adb
*adb
;
203 for (rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
204 (void **)&adb
, &cursor
);
205 rc
== 0; rc
= skiplist_next(rfd
->advertised
.by_lifetime
, NULL
,
206 (void **)&adb
, &cursor
)) {
208 struct prefix pfx_vn_buf
;
209 struct prefix
*pfx_ip
;
211 if (!(RFAPI_0_PREFIX(&adb
->u
.s
.prefix_ip
)
212 && RFAPI_HOST_PREFIX(&adb
->u
.s
.prefix_ip
))) {
214 pfx_ip
= &adb
->u
.s
.prefix_ip
;
221 * 0/32 or 0/128 => mac advertisement
223 if (rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn_buf
)) {
225 * Bad: it means we can't delete the route
227 vnc_zlog_debug_verbose(
228 "%s: BAD: handle has bad vn_addr: skipping",
234 del_vnc_route(rfd
, rfd
->peer
, bgp
, SAFI_MPLS_VPN
,
235 pfx_ip
? pfx_ip
: &pfx_vn_buf
,
236 &adb
->u
.s
.prd
, /* RD to use (0 for ENCAP) */
237 ZEBRA_ROUTE_BGP
, BGP_ROUTE_RFP
, NULL
, 0);
242 * returns nonzero if tunnel readvertisement is needed, 0 otherwise
244 static int rfapiApAdjustLifetimeStats(
245 struct rfapi_descriptor
*rfd
,
246 uint32_t *old_lifetime
, /* set if removing/replacing */
247 uint32_t *new_lifetime
) /* set if replacing/adding */
253 vnc_zlog_debug_verbose("%s: rfd=%p, pOldLife=%p, pNewLife=%p", __func__
,
254 rfd
, old_lifetime
, new_lifetime
);
256 vnc_zlog_debug_verbose("%s: OldLife=%d", __func__
,
259 vnc_zlog_debug_verbose("%s: NewLife=%d", __func__
,
264 * Adding new lifetime
268 * replacing existing lifetime
272 /* old and new are same */
273 if (*old_lifetime
== *new_lifetime
)
276 if (*old_lifetime
== rfd
->min_prefix_lifetime
) {
279 if (*old_lifetime
== rfd
->max_prefix_lifetime
) {
283 /* no need to search if new value is at or equals
285 if (*new_lifetime
<= rfd
->min_prefix_lifetime
) {
286 rfd
->min_prefix_lifetime
= *new_lifetime
;
289 if (*new_lifetime
>= rfd
->max_prefix_lifetime
) {
290 rfd
->max_prefix_lifetime
= *new_lifetime
;
297 * Just adding new lifetime
299 if (*new_lifetime
< rfd
->min_prefix_lifetime
) {
300 rfd
->min_prefix_lifetime
= *new_lifetime
;
302 if (*new_lifetime
> rfd
->max_prefix_lifetime
) {
304 rfd
->max_prefix_lifetime
= *new_lifetime
;
313 * See if the max prefix lifetime for this NVE has decreased.
314 * The easy optimization: track min & max; walk the table only
315 * if they are different.
316 * The general optimization: index the advertised_prefixes
319 * Note: for a given nve_descriptor, only one of the
320 * advertised_prefixes[] tables will be used: viz., the
321 * address family that matches the VN address.
324 if (rfd
->max_prefix_lifetime
== rfd
->min_prefix_lifetime
) {
327 * Common case: all lifetimes are the same. Only
328 * thing we need to do here is check if there are
329 * no exported routes left. In that case, reinitialize
330 * the max and min values.
332 if (!rfapiApCount(rfd
)) {
333 rfd
->max_prefix_lifetime
= 0;
334 rfd
->min_prefix_lifetime
= UINT32_MAX
;
340 if (*old_lifetime
== rfd
->min_prefix_lifetime
) {
343 if (*old_lifetime
== rfd
->max_prefix_lifetime
) {
350 if (find_min
|| find_max
) {
351 uint32_t min
= UINT32_MAX
;
354 struct rfapi_adb
*adb_min
;
355 struct rfapi_adb
*adb_max
;
357 if (!skiplist_first(rfd
->advertised
.by_lifetime
,
358 (void **)&adb_min
, NULL
)
359 && !skiplist_last(rfd
->advertised
.by_lifetime
,
360 (void **)&adb_max
, NULL
)) {
363 * This should always work
365 min
= adb_min
->lifetime
;
366 max
= adb_max
->lifetime
;
371 struct rfapi_rib_key rk
;
372 struct rfapi_adb
*adb
;
375 vnc_zlog_debug_verbose(
376 "%s: walking to find new min/max", __func__
);
379 for (rc
= skiplist_next(rfd
->advertised
.ipN_by_prefix
,
380 (void **)&rk
, (void **)&adb
,
383 rc
= skiplist_next(rfd
->advertised
.ipN_by_prefix
,
384 (void **)&rk
, (void **)&adb
,
387 uint32_t lt
= adb
->lifetime
;
395 for (rc
= skiplist_next(rfd
->advertised
.ip0_by_ether
,
396 (void **)&rk
, (void **)&adb
,
399 rc
= skiplist_next(rfd
->advertised
.ip0_by_ether
,
400 (void **)&rk
, (void **)&adb
,
403 uint32_t lt
= adb
->lifetime
;
413 * trigger tunnel route update
414 * but only if we found a VPN route and it had
415 * a lifetime greater than 0
417 if (max
&& rfd
->max_prefix_lifetime
!= max
)
419 rfd
->max_prefix_lifetime
= max
;
420 rfd
->min_prefix_lifetime
= min
;
423 vnc_zlog_debug_verbose("%s: returning advertise=%d, min=%d, max=%d",
424 __func__
, advertise
, rfd
->min_prefix_lifetime
,
425 rfd
->max_prefix_lifetime
);
427 return (advertise
!= 0);
433 * 0 No need to advertise tunnel route
434 * non-0 advertise tunnel route
436 int rfapiApAdd(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
437 struct prefix
*pfx_ip
, struct prefix
*pfx_eth
,
438 struct prefix_rd
*prd
, uint32_t lifetime
, uint8_t cost
,
439 struct rfapi_l2address_option
*l2o
) /* other options TBD */
442 struct rfapi_adb
*adb
;
443 uint32_t old_lifetime
= 0;
445 struct rfapi_rib_key rk
;
447 rfapi_rib_key_init(pfx_ip
, prd
, pfx_eth
, &rk
);
448 if (RFAPI_0_PREFIX(pfx_ip
) && RFAPI_HOST_PREFIX(pfx_ip
)) {
451 rc
= skiplist_search(rfd
->advertised
.ip0_by_ether
, &rk
,
456 /* find prefix in advertised prefixes list */
457 rc
= skiplist_search(rfd
->advertised
.ipN_by_prefix
, &rk
,
464 adb
= XCALLOC(MTYPE_RFAPI_ADB
, sizeof(struct rfapi_adb
));
466 adb
->lifetime
= lifetime
;
471 skiplist_insert(rfd
->advertised
.ip0_by_ether
,
474 skiplist_insert(rfd
->advertised
.ipN_by_prefix
,
478 skiplist_insert(rfd
->advertised
.by_lifetime
, adb
, adb
);
480 old_lifetime
= adb
->lifetime
;
481 if (old_lifetime
!= lifetime
) {
482 assert(!skiplist_delete(rfd
->advertised
.by_lifetime
,
484 adb
->lifetime
= lifetime
;
485 assert(!skiplist_insert(rfd
->advertised
.by_lifetime
,
493 memset(&adb
->l2o
, 0, sizeof(struct rfapi_l2address_option
));
495 if (rfapiApAdjustLifetimeStats(rfd
, (rc
? NULL
: &old_lifetime
),
503 * After this function returns successfully, caller should call
504 * rfapiAdjustLifetimeStats() and possibly rfapiTunnelRouteAnnounce()
506 int rfapiApDelete(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
507 struct prefix
*pfx_ip
, struct prefix
*pfx_eth
,
508 struct prefix_rd
*prd
, int *advertise_tunnel
) /* out */
511 struct rfapi_adb
*adb
;
512 uint32_t old_lifetime
;
514 struct rfapi_rib_key rk
;
516 if (advertise_tunnel
)
517 *advertise_tunnel
= 0;
519 rfapi_rib_key_init(pfx_ip
, prd
, pfx_eth
, &rk
);
520 /* find prefix in advertised prefixes list */
521 if (RFAPI_0_PREFIX(pfx_ip
) && RFAPI_HOST_PREFIX(pfx_ip
)) {
525 rc
= skiplist_search(rfd
->advertised
.ip0_by_ether
, &rk
,
530 /* find prefix in advertised prefixes list */
531 rc
= skiplist_search(rfd
->advertised
.ipN_by_prefix
, &rk
,
539 old_lifetime
= adb
->lifetime
;
542 rc
= skiplist_delete(rfd
->advertised
.ip0_by_ether
, &rk
, NULL
);
544 rc
= skiplist_delete(rfd
->advertised
.ipN_by_prefix
, &rk
, NULL
);
548 rc
= skiplist_delete(rfd
->advertised
.by_lifetime
, adb
, NULL
);
553 if (rfapiApAdjustLifetimeStats(rfd
, &old_lifetime
, NULL
)) {
554 if (advertise_tunnel
)
555 *advertise_tunnel
= 1;