1 /*
2  *
3  * Copyright 2009-2016, LabN Consulting, L.L.C.
4  *
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include "lib/zebra.h"
22 #include "lib/prefix.h"
23 #include "lib/agg_table.h"
24 #include "lib/vty.h"
25 #include "lib/memory.h"
26 #include "lib/routemap.h"
27 #include "lib/log.h"
28 #include "lib/linklist.h"
29 #include "lib/command.h"
30 #include "lib/stream.h"
31 
32 #include "bgpd/bgpd.h"
33 #include "bgpd/bgp_ecommunity.h"
34 #include "bgpd/bgp_attr.h"
35 
36 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
37 #include "bgpd/rfapi/rfapi.h"
38 #include "bgpd/rfapi/rfapi_backend.h"
39 
40 #include "bgpd/bgp_route.h"
41 #include "bgpd/bgp_mplsvpn.h"
42 #include "bgpd/bgp_aspath.h"
43 #include "bgpd/bgp_advertise.h"
44 
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"
54 
55 #include "bgpd/rfapi/rfapi_ap.h"
56 #include "bgpd/rfapi/vnc_debug.h"
57 
58 /*
59  * Per-NVE Advertised prefixes
60  *
61  * We maintain a list of prefixes advertised by each NVE.
62  * There are two indices: by prefix and by lifetime.
63  *
64  * BY-PREFIX skiplist
65  *
66  *  key:	ptr to struct prefix (when storing, point to prefix that
67  *		is part of rfapi_adb).
68  *
69  *  value:	ptr to struct rfapi_adb
70  *
71  * BY-LIFETIME skiplist
72  *
73  *  key:	ptr to struct rfapi_adb
74  *  value:	ptr to struct rfapi_adb
75  *
76  */
77 
78 /*
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.
83  */
sl_adb_lifetime_cmp(const void * adb1,const void * adb2)84 static int sl_adb_lifetime_cmp(const void *adb1, const void *adb2)
85 {
86 	const struct rfapi_adb *a1 = adb1;
87 	const struct rfapi_adb *a2 = adb2;
88 
89 	if (a1->lifetime < a2->lifetime)
90 		return -1;
91 	if (a1->lifetime > a2->lifetime)
92 		return 1;
93 
94 	if (a1 < a2)
95 		return -1;
96 	if (a1 > a2)
97 		return 1;
98 
99 	return 0;
100 }
101 
rfapiApInit(struct rfapi_advertised_prefixes * ap)102 void rfapiApInit(struct rfapi_advertised_prefixes *ap)
103 {
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);
107 }
108 
rfapiApRelease(struct rfapi_advertised_prefixes * ap)109 void rfapiApRelease(struct rfapi_advertised_prefixes *ap)
110 {
111 	struct rfapi_adb *adb;
112 
113 	/* Free ADBs and lifetime items */
114 	while (0 == skiplist_first(ap->by_lifetime, NULL, (void **)&adb)) {
115 		rfapiAdbFree(adb);
116 		skiplist_delete_first(ap->by_lifetime);
117 	}
118 
119 	while (0 == skiplist_delete_first(ap->ipN_by_prefix))
120 		;
121 	while (0 == skiplist_delete_first(ap->ip0_by_ether))
122 		;
123 
124 	/* Free lists */
125 	skiplist_free(ap->ipN_by_prefix);
126 	skiplist_free(ap->ip0_by_ether);
127 	skiplist_free(ap->by_lifetime);
128 
129 	ap->ipN_by_prefix = NULL;
130 	ap->ip0_by_ether = NULL;
131 	ap->by_lifetime = NULL;
132 }
133 
rfapiApCount(struct rfapi_descriptor * rfd)134 int rfapiApCount(struct rfapi_descriptor *rfd)
135 {
136 	if (!rfd->advertised.by_lifetime)
137 		return 0;
138 
139 	return skiplist_count(rfd->advertised.by_lifetime);
140 }
141 
rfapiApCountAll(struct bgp * bgp)142 int rfapiApCountAll(struct bgp *bgp)
143 {
144 	struct rfapi *h;
145 	struct listnode *node;
146 	struct rfapi_descriptor *rfd;
147 	int total = 0;
148 
149 	h = bgp->rfapi;
150 	if (h) {
151 		for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
152 			total += rfapiApCount(rfd);
153 		}
154 	}
155 	return total;
156 }
157 
158 
rfapiApReadvertiseAll(struct bgp * bgp,struct rfapi_descriptor * rfd)159 void rfapiApReadvertiseAll(struct bgp *bgp, struct rfapi_descriptor *rfd)
160 {
161 	struct rfapi_adb *adb;
162 	void *cursor = NULL;
163 	int rc;
164 
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)) {
169 
170 		struct prefix_rd prd;
171 		uint32_t local_pref = rfp_cost_to_localpref(adb->cost);
172 
173 		prd = rfd->rd;
174 		prd.family = AF_UNSPEC;
175 		prd.prefixlen = 64;
176 
177 		/*
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
180 		 */
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);
189 	}
190 }
191 
rfapiApWithdrawAll(struct bgp * bgp,struct rfapi_descriptor * rfd)192 void rfapiApWithdrawAll(struct bgp *bgp, struct rfapi_descriptor *rfd)
193 {
194 	struct rfapi_adb *adb;
195 	void *cursor;
196 	int rc;
197 
198 
199 	cursor = NULL;
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)) {
204 
205 		struct prefix pfx_vn_buf;
206 		struct prefix *pfx_ip;
207 
208 		if (!(RFAPI_0_PREFIX(&adb->u.s.prefix_ip)
209 		      && RFAPI_HOST_PREFIX(&adb->u.s.prefix_ip))) {
210 
211 			pfx_ip = &adb->u.s.prefix_ip;
212 
213 		} else {
214 
215 			pfx_ip = NULL;
216 
217 			/*
218 			 * 0/32 or 0/128 => mac advertisement
219 			 */
220 			if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) {
221 				/*
222 				 * Bad: it means we can't delete the route
223 				 */
224 				vnc_zlog_debug_verbose(
225 					"%s: BAD: handle has bad vn_addr: skipping",
226 					__func__);
227 				continue;
228 			}
229 		}
230 
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);
235 	}
236 }
237 
238 /*
239  * returns nonzero if tunnel readvertisement is needed, 0 otherwise
240  */
rfapiApAdjustLifetimeStats(struct rfapi_descriptor * rfd,uint32_t * old_lifetime,uint32_t * new_lifetime)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 */
245 {
246 	int advertise = 0;
247 	int find_max = 0;
248 	int find_min = 0;
249 
250 	vnc_zlog_debug_verbose("%s: rfd=%p, pOldLife=%p, pNewLife=%p", __func__,
251 			       rfd, old_lifetime, new_lifetime);
252 	if (old_lifetime)
253 		vnc_zlog_debug_verbose("%s: OldLife=%d", __func__,
254 				       *old_lifetime);
255 	if (new_lifetime)
256 		vnc_zlog_debug_verbose("%s: NewLife=%d", __func__,
257 				       *new_lifetime);
258 
259 	if (new_lifetime) {
260 		/*
261 		 * Adding new lifetime
262 		 */
263 		if (old_lifetime) {
264 			/*
265 			 * replacing existing lifetime
266 			 */
267 
268 
269 			/* old and new are same */
270 			if (*old_lifetime == *new_lifetime)
271 				return 0;
272 
273 			if (*old_lifetime == rfd->min_prefix_lifetime) {
274 				find_min = 1;
275 			}
276 			if (*old_lifetime == rfd->max_prefix_lifetime) {
277 				find_max = 1;
278 			}
279 
280 			/* no need to search if new value is at or equals
281 			 * min|max  */
282 			if (*new_lifetime <= rfd->min_prefix_lifetime) {
283 				rfd->min_prefix_lifetime = *new_lifetime;
284 				find_min = 0;
285 			}
286 			if (*new_lifetime >= rfd->max_prefix_lifetime) {
287 				rfd->max_prefix_lifetime = *new_lifetime;
288 				advertise = 1;
289 				find_max = 0;
290 			}
291 
292 		} else {
293 			/*
294 			 * Just adding new lifetime
295 			 */
296 			if (*new_lifetime < rfd->min_prefix_lifetime) {
297 				rfd->min_prefix_lifetime = *new_lifetime;
298 			}
299 			if (*new_lifetime > rfd->max_prefix_lifetime) {
300 				advertise = 1;
301 				rfd->max_prefix_lifetime = *new_lifetime;
302 			}
303 		}
304 	} else {
305 		/*
306 		 * Deleting
307 		 */
308 
309 		/*
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
314 		 * table by lifetime.
315 		 *
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.
319 		 *
320 		 */
321 		if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime) {
322 
323 			/*
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.
328 			 */
329 			if (!rfapiApCount(rfd)) {
330 				rfd->max_prefix_lifetime = 0;
331 				rfd->min_prefix_lifetime = UINT32_MAX;
332 			}
333 
334 
335 		} else {
336 			if (old_lifetime) {
337 				if (*old_lifetime == rfd->min_prefix_lifetime) {
338 					find_min = 1;
339 				}
340 				if (*old_lifetime == rfd->max_prefix_lifetime) {
341 					find_max = 1;
342 				}
343 			}
344 		}
345 	}
346 
347 	if (find_min || find_max) {
348 		uint32_t min = UINT32_MAX;
349 		uint32_t max = 0;
350 
351 		struct rfapi_adb *adb_min;
352 		struct rfapi_adb *adb_max;
353 
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)) {
358 
359 			/*
360 			 * This should always work
361 			 */
362 			min = adb_min->lifetime;
363 			max = adb_max->lifetime;
364 
365 		} else {
366 
367 			void *cursor;
368 			struct rfapi_rib_key rk;
369 			struct rfapi_adb *adb;
370 			int rc;
371 
372 			vnc_zlog_debug_verbose(
373 				"%s: walking to find new min/max", __func__);
374 
375 			cursor = NULL;
376 			for (rc = skiplist_next(rfd->advertised.ipN_by_prefix,
377 						(void **)&rk, (void **)&adb,
378 						&cursor);
379 			     !rc;
380 			     rc = skiplist_next(rfd->advertised.ipN_by_prefix,
381 						(void **)&rk, (void **)&adb,
382 						&cursor)) {
383 
384 				uint32_t lt = adb->lifetime;
385 
386 				if (lt > max)
387 					max = lt;
388 				if (lt < min)
389 					min = lt;
390 			}
391 			cursor = NULL;
392 			for (rc = skiplist_next(rfd->advertised.ip0_by_ether,
393 						(void **)&rk, (void **)&adb,
394 						&cursor);
395 			     !rc;
396 			     rc = skiplist_next(rfd->advertised.ip0_by_ether,
397 						(void **)&rk, (void **)&adb,
398 						&cursor)) {
399 
400 				uint32_t lt = adb->lifetime;
401 
402 				if (lt > max)
403 					max = lt;
404 				if (lt < min)
405 					min = lt;
406 			}
407 		}
408 
409 		/*
410 		 * trigger tunnel route update
411 		 * but only if we found a VPN route and it had
412 		 * a lifetime greater than 0
413 		 */
414 		if (max && rfd->max_prefix_lifetime != max)
415 			advertise = 1;
416 		rfd->max_prefix_lifetime = max;
417 		rfd->min_prefix_lifetime = min;
418 	}
419 
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);
423 
424 	return (advertise != 0);
425 }
426 
427 /*
428  * Return Value
429  *
430  *	0	No need to advertise tunnel route
431  *	non-0	advertise tunnel route
432  */
rfapiApAdd(struct bgp * bgp,struct rfapi_descriptor * rfd,struct prefix * pfx_ip,struct prefix * pfx_eth,struct prefix_rd * prd,uint32_t lifetime,uint8_t cost,struct rfapi_l2address_option * l2o)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 */
437 {
438 	int rc;
439 	struct rfapi_adb *adb;
440 	uint32_t old_lifetime = 0;
441 	int use_ip0 = 0;
442 	struct rfapi_rib_key rk;
443 
444 	rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
445 	if (RFAPI_0_PREFIX(pfx_ip) && RFAPI_HOST_PREFIX(pfx_ip)) {
446 		use_ip0 = 1;
447 		assert(pfx_eth);
448 		rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk,
449 				     (void **)&adb);
450 
451 	} else {
452 
453 		/* find prefix in advertised prefixes list */
454 		rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk,
455 				     (void **)&adb);
456 	}
457 
458 
459 	if (rc) {
460 		/* Not found */
461 		adb = XCALLOC(MTYPE_RFAPI_ADB, sizeof(struct rfapi_adb));
462 		assert(adb);
463 		adb->lifetime = lifetime;
464 		adb->u.key = rk;
465 
466 		if (use_ip0) {
467 			assert(pfx_eth);
468 			skiplist_insert(rfd->advertised.ip0_by_ether,
469 					&adb->u.key, adb);
470 		} else {
471 			skiplist_insert(rfd->advertised.ipN_by_prefix,
472 					&adb->u.key, adb);
473 		}
474 
475 		skiplist_insert(rfd->advertised.by_lifetime, adb, adb);
476 	} else {
477 		old_lifetime = adb->lifetime;
478 		if (old_lifetime != lifetime) {
479 			assert(!skiplist_delete(rfd->advertised.by_lifetime,
480 						adb, NULL));
481 			adb->lifetime = lifetime;
482 			assert(!skiplist_insert(rfd->advertised.by_lifetime,
483 						adb, adb));
484 		}
485 	}
486 	adb->cost = cost;
487 	if (l2o)
488 		adb->l2o = *l2o;
489 	else
490 		memset(&adb->l2o, 0, sizeof(struct rfapi_l2address_option));
491 
492 	if (rfapiApAdjustLifetimeStats(rfd, (rc ? NULL : &old_lifetime),
493 				       &lifetime))
494 		return 1;
495 
496 	return 0;
497 }
498 
499 /*
500  * After this function returns successfully, caller should call
501  * rfapiAdjustLifetimeStats() and possibly rfapiTunnelRouteAnnounce()
502  */
rfapiApDelete(struct bgp * bgp,struct rfapi_descriptor * rfd,struct prefix * pfx_ip,struct prefix * pfx_eth,struct prefix_rd * prd,int * advertise_tunnel)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 */
506 {
507 	int rc;
508 	struct rfapi_adb *adb;
509 	uint32_t old_lifetime;
510 	int use_ip0 = 0;
511 	struct rfapi_rib_key rk;
512 
513 	if (advertise_tunnel)
514 		*advertise_tunnel = 0;
515 
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)) {
519 		use_ip0 = 1;
520 		assert(pfx_eth);
521 
522 		rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk,
523 				     (void **)&adb);
524 
525 	} else {
526 
527 		/* find prefix in advertised prefixes list */
528 		rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk,
529 				     (void **)&adb);
530 	}
531 
532 	if (rc) {
533 		return ENOENT;
534 	}
535 
536 	old_lifetime = adb->lifetime;
537 
538 	if (use_ip0) {
539 		rc = skiplist_delete(rfd->advertised.ip0_by_ether, &rk, NULL);
540 	} else {
541 		rc = skiplist_delete(rfd->advertised.ipN_by_prefix, &rk, NULL);
542 	}
543 	assert(!rc);
544 
545 	rc = skiplist_delete(rfd->advertised.by_lifetime, adb, NULL);
546 	assert(!rc);
547 
548 	rfapiAdbFree(adb);
549 
550 	if (rfapiApAdjustLifetimeStats(rfd, &old_lifetime, NULL)) {
551 		if (advertise_tunnel)
552 			*advertise_tunnel = 1;
553 	}
554 
555 	return 0;
556 }
557