]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_mpls.c
*: make consistent & update GPLv2 file headers
[mirror_frr.git] / zebra / zebra_mpls.c
CommitLineData
7758e3f3 1/* Zebra MPLS code
2 * Copyright (C) 2013 Cumulus Networks, Inc.
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
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
7758e3f3 19 */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "table.h"
25#include "memory.h"
7758e3f3 26#include "command.h"
27#include "if.h"
28#include "log.h"
29#include "sockunion.h"
30#include "linklist.h"
31#include "thread.h"
32#include "workqueue.h"
33#include "prefix.h"
34#include "routemap.h"
35#include "stream.h"
36#include "nexthop.h"
b78b820d 37#include "lib/json.h"
7758e3f3 38
39#include "zebra/rib.h"
40#include "zebra/rt.h"
41#include "zebra/zserv.h"
42#include "zebra/redistribute.h"
43#include "zebra/debug.h"
44#include "zebra/zebra_memory.h"
45#include "zebra/zebra_vrf.h"
46#include "zebra/zebra_mpls.h"
47
48DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object")
f31e084c 49DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object")
7758e3f3 50DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config")
40c7bdb0 51DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object")
7758e3f3 52DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object")
53DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname")
54
fe6c7157
RW
55int mpls_enabled;
56
7758e3f3 57/* Default rtm_table for all clients */
58extern struct zebra_t zebrad;
59
60/* static function declarations */
f31e084c 61
28d58fd7
VV
62static void
63fec_evaluate (struct zebra_vrf *zvrf, int add);
64static u_int32_t
65fec_derive_label_from_index (struct zebra_vrf *vrf, zebra_fec_t *fec);
a64448ba
DS
66static int
67lsp_install (struct zebra_vrf *zvrf, mpls_label_t label,
68 struct route_node *rn, struct rib *rib);
69static int
70lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label);
71static int
72fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label);
5aba114a
DS
73static int
74fec_send (zebra_fec_t *fec, struct zserv *client);
75static void
76fec_update_clients (zebra_fec_t *fec);
f31e084c
DS
77static void
78fec_print (zebra_fec_t *fec, struct vty *vty);
79static zebra_fec_t *
80fec_find (struct route_table *table, struct prefix *p);
81static zebra_fec_t *
a64448ba 82fec_add (struct route_table *table, struct prefix *p, mpls_label_t label,
28d58fd7 83 u_int32_t flags, u_int32_t label_index);
f31e084c
DS
84static int
85fec_del (zebra_fec_t *fec);
86
7758e3f3 87static unsigned int
88label_hash (void *p);
89static int
90label_cmp (const void *p1, const void *p2);
40c7bdb0 91static int
92nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop);
93static int
94nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop);
95static int
96nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe);
f31e084c 97
40c7bdb0 98static void
99lsp_select_best_nhlfe (zebra_lsp_t *lsp);
100static void
101lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt);
102static void
103lsp_schedule (struct hash_backet *backet, void *ctxt);
104static wq_item_status
105lsp_process (struct work_queue *wq, void *data);
106static void
107lsp_processq_del (struct work_queue *wq, void *data);
108static void
109lsp_processq_complete (struct work_queue *wq);
110static int
111lsp_processq_add (zebra_lsp_t *lsp);
112static void *
113lsp_alloc (void *p);
f31e084c 114
40c7bdb0 115static char *
116nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size);
117static int
118nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
a64448ba 119 union g_addr *gate, ifindex_t ifindex);
40c7bdb0 120static zebra_nhlfe_t *
121nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
122 enum nexthop_types_t gtype, union g_addr *gate,
a64448ba 123 ifindex_t ifindex);
40c7bdb0 124static zebra_nhlfe_t *
125nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
126 enum nexthop_types_t gtype, union g_addr *gate,
a64448ba 127 ifindex_t ifindex, mpls_label_t out_label);
40c7bdb0 128static int
129nhlfe_del (zebra_nhlfe_t *snhlfe);
a64448ba
DS
130static void
131nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label);
40c7bdb0 132static int
ce549947
RW
133mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
134 enum lsp_types_t type);
40c7bdb0 135static int
ce549947 136mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label);
7758e3f3 137static void
3ab18ff2 138nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty);
139static void
140lsp_print (zebra_lsp_t *lsp, void *ctxt);
7758e3f3 141static void *
142slsp_alloc (void *p);
143static int
144snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
a64448ba 145 union g_addr *gate, ifindex_t ifindex);
7758e3f3 146static zebra_snhlfe_t *
147snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
a64448ba 148 union g_addr *gate, ifindex_t ifindex);
7758e3f3 149static zebra_snhlfe_t *
150snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
a64448ba 151 union g_addr *gate, ifindex_t ifindex, mpls_label_t out_label);
7758e3f3 152static int
153snhlfe_del (zebra_snhlfe_t *snhlfe);
154static int
155snhlfe_del_all (zebra_slsp_t *slsp);
156static char *
157snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size);
33c32282 158static int
40c7bdb0 159mpls_processq_init (struct zebra_t *zebra);
7758e3f3 160
161
162
163
164/* Static functions */
165
a64448ba
DS
166/*
167 * Install label forwarding entry based on labeled-route entry.
168 */
169static int
170lsp_install (struct zebra_vrf *zvrf, mpls_label_t label,
171 struct route_node *rn, struct rib *rib)
172{
173 struct hash *lsp_table;
174 zebra_ile_t tmp_ile;
175 zebra_lsp_t *lsp;
176 zebra_nhlfe_t *nhlfe;
177 struct nexthop *nexthop;
178 enum lsp_types_t lsp_type;
179 char buf[BUFSIZ];
180 int added, changed;
181
182 /* Lookup table. */
183 lsp_table = zvrf->lsp_table;
184 if (!lsp_table)
185 return -1;
186
a64448ba
DS
187 lsp_type = lsp_type_from_rib_type (rib->type);
188 added = changed = 0;
189
190 /* Locate or allocate LSP entry. */
191 tmp_ile.in_label = label;
192 lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
193 if (!lsp)
194 return -1;
195
196 /* For each active nexthop, create NHLFE. Note that we deliberately skip
197 * recursive nexthops right now, because intermediate hops won't understand
198 * the label advertised by the recursive nexthop (plus we don't have the
199 * logic yet to push multiple labels).
200 */
201 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
202 {
203 /* Skip inactive and recursive entries. */
204 if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
205 continue;
206 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
207 continue;
208
209 nhlfe = nhlfe_find (lsp, lsp_type, nexthop->type, &nexthop->gate,
210 nexthop->ifindex);
211 if (nhlfe)
212 {
213 /* Clear deleted flag (in case it was set) */
214 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
215 if (nexthop_labels_match (nhlfe->nexthop, nexthop))
216 /* No change */
217 continue;
218
219
220 if (IS_ZEBRA_DEBUG_MPLS)
221 {
222 nhlfe2str (nhlfe, buf, BUFSIZ);
223 zlog_debug ("LSP in-label %u type %d nexthop %s "
224 "out-label changed",
225 lsp->ile.in_label, lsp_type, buf);
226 }
227
228 /* Update out label, trigger processing. */
229 nhlfe_out_label_update (nhlfe, nexthop->nh_label);
230 SET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
231 changed++;
232 }
233 else
234 {
235 /* Add LSP entry to this nexthop */
236 nhlfe = nhlfe_add (lsp, lsp_type, nexthop->type,
237 &nexthop->gate, nexthop->ifindex,
238 nexthop->nh_label->label[0]);
239 if (!nhlfe)
240 return -1;
241
242 if (IS_ZEBRA_DEBUG_MPLS)
243 {
244 nhlfe2str (nhlfe, buf, BUFSIZ);
245 zlog_debug ("Add LSP in-label %u type %d nexthop %s "
246 "out-label %u",
247 lsp->ile.in_label, lsp_type, buf,
248 nexthop->nh_label->label[0]);
249 }
250
251 lsp->addr_family = NHLFE_FAMILY (nhlfe);
252
253 /* Mark NHLFE as changed. */
254 SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
255 added++;
256 }
257 }
258
259 /* Queue LSP for processing if necessary. If no NHLFE got added (special
260 * case), delete the LSP entry; this case results in somewhat ugly logging.
261 */
262 if (added || changed)
263 {
264 if (lsp_processq_add (lsp))
265 return -1;
266 }
267 else if (!lsp->nhlfe_list &&
268 !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
269 {
270 if (IS_ZEBRA_DEBUG_MPLS)
271 zlog_debug ("Free LSP in-label %u flags 0x%x",
272 lsp->ile.in_label, lsp->flags);
273
274 lsp = hash_release(lsp_table, &lsp->ile);
275 if (lsp)
276 XFREE(MTYPE_LSP, lsp);
277 }
278
279 return 0;
280}
281
282/*
283 * Uninstall all non-static NHLFEs of a label forwarding entry. If all
284 * NHLFEs are removed, the entire entry is deleted.
285 */
286static int
287lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label)
288{
289 struct hash *lsp_table;
290 zebra_ile_t tmp_ile;
291 zebra_lsp_t *lsp;
292 zebra_nhlfe_t *nhlfe, *nhlfe_next;
293 char buf[BUFSIZ];
294
295 /* Lookup table. */
296 lsp_table = zvrf->lsp_table;
297 if (!lsp_table)
298 return -1;
299
300 /* If entry is not present, exit. */
301 tmp_ile.in_label = label;
302 lsp = hash_lookup (lsp_table, &tmp_ile);
303 if (!lsp || !lsp->nhlfe_list)
304 return 0;
305
306 /* Mark NHLFEs for delete or directly delete, as appropriate. */
307 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next)
308 {
309 nhlfe_next = nhlfe->next;
310
311 /* Skip static NHLFEs */
312 if (nhlfe->type == ZEBRA_LSP_STATIC)
313 continue;
314
315 if (IS_ZEBRA_DEBUG_MPLS)
316 {
317 nhlfe2str (nhlfe, buf, BUFSIZ);
318 zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
319 label, nhlfe->type, buf, nhlfe->flags);
320 }
321
322 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED))
323 {
324 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
325 SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
326 }
327 else
328 {
329 nhlfe_del (nhlfe);
330 }
331 }
332
333 /* Queue LSP for processing, if needed, else delete. */
334 if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
335 {
336 if (lsp_processq_add (lsp))
337 return -1;
338 }
339 else if (!lsp->nhlfe_list &&
340 !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
341 {
342 if (IS_ZEBRA_DEBUG_MPLS)
343 zlog_debug ("Del LSP in-label %u flags 0x%x",
344 lsp->ile.in_label, lsp->flags);
345
346 lsp = hash_release(lsp_table, &lsp->ile);
347 if (lsp)
348 XFREE(MTYPE_LSP, lsp);
349 }
350
351 return 0;
352}
353
28d58fd7
VV
354/*
355 * This function is invoked upon change to label block configuration; it
356 * will walk all registered FECs with label-index and appropriately update
357 * their local labels and trigger client updates.
358 */
359static void
360fec_evaluate (struct zebra_vrf *zvrf, int add)
361{
362 struct route_node *rn;
363 zebra_fec_t *fec;
364 u_int32_t old_label, new_label;
365 int af;
366 char buf[BUFSIZ];
367
368 for (af = AFI_IP; af < AFI_MAX; af++)
369 {
95169c2f
DS
370 if (zvrf->fec_table[af] == NULL)
371 continue;
372
28d58fd7
VV
373 for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
374 {
375 if ((fec = rn->info) == NULL)
376 continue;
377
378 /* Skip configured FECs and those without a label index. */
379 if (fec->flags & FEC_FLAG_CONFIGURED ||
380 fec->label_index == MPLS_INVALID_LABEL_INDEX)
381 continue;
382
383 if (IS_ZEBRA_DEBUG_MPLS)
384 prefix2str(&rn->p, buf, BUFSIZ);
385
386 /* Save old label, determine new label. */
387 old_label = fec->label;
388 if (add)
389 {
390 new_label = zvrf->mpls_srgb.start_label + fec->label_index;
391 if (new_label >= zvrf->mpls_srgb.end_label)
392 new_label = MPLS_INVALID_LABEL;
393 }
394 else
395 new_label = MPLS_INVALID_LABEL;
396
397 /* If label has changed, update FEC and clients. */
398 if (new_label == old_label)
399 continue;
400
401 if (IS_ZEBRA_DEBUG_MPLS)
402 zlog_debug ("Update fec %s new label %u upon label block %s",
403 buf, new_label, add ? "ADD" : "DEL");
404
405 fec->label = new_label;
406 fec_update_clients (fec);
407
408 /* Update label forwarding entries appropriately */
409 fec_change_update_lsp (zvrf, fec, old_label);
410 }
411 }
412}
413
414/*
415 * Derive (if possible) and update the local label for the FEC based on
416 * its label index. The index is "acceptable" if it falls within the
417 * globally configured label block (SRGB).
418 */
419static u_int32_t
420fec_derive_label_from_index (struct zebra_vrf *zvrf, zebra_fec_t *fec)
421{
422 u_int32_t label;
423
424 if (fec->label_index != MPLS_INVALID_LABEL_INDEX &&
425 zvrf->mpls_srgb.start_label &&
426 ((label = zvrf->mpls_srgb.start_label + fec->label_index) <
427 zvrf->mpls_srgb.end_label))
428 fec->label = label;
429 else
430 fec->label = MPLS_INVALID_LABEL;
431
432 return fec->label;
433}
434
a64448ba
DS
435/*
436 * There is a change for this FEC. Install or uninstall label forwarding
437 * entries, as appropriate.
438 */
439static int
440fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label)
441{
442 struct route_table *table;
443 struct route_node *rn;
444 struct rib *rib;
445 afi_t afi;
446
447 /* Uninstall label forwarding entry, if previously installed. */
448 if (old_label != MPLS_INVALID_LABEL &&
449 old_label != MPLS_IMP_NULL_LABEL)
450 lsp_uninstall (zvrf, old_label);
451
452 /* Install label forwarding entry corr. to new label, if needed. */
453 if (fec->label == MPLS_INVALID_LABEL ||
454 fec->label == MPLS_IMP_NULL_LABEL)
455 return 0;
456
457 afi = family2afi(PREFIX_FAMILY(&fec->rn->p));
458 table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf));
459 if (!table)
460 return 0;
461
462 /* See if labeled route exists. */
463 rn = route_node_lookup (table, &fec->rn->p);
464 if (!rn)
465 return 0;
466
467 RNODE_FOREACH_RIB (rn, rib)
468 {
469 if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
470 break;
471 }
472
473 if (!rib || !zebra_rib_labeled_unicast (rib))
474 return 0;
475
476 if (lsp_install (zvrf, fec->label, rn, rib))
477 return -1;
478
479 return 0;
480}
481
5aba114a
DS
482/*
483 * Inform about FEC to a registered client.
484 */
485static int
486fec_send (zebra_fec_t *fec, struct zserv *client)
487{
488 struct stream *s;
489 struct route_node *rn;
490
491 rn = fec->rn;
492
493 /* Get output stream. */
494 s = client->obuf;
495 stream_reset (s);
496
497 zserv_create_header (s, ZEBRA_FEC_UPDATE, VRF_DEFAULT);
498
499 stream_putw(s, rn->p.family);
500 stream_put_prefix (s, &rn->p);
501 stream_putl(s, fec->label);
502 stream_putw_at(s, 0, stream_get_endp(s));
503 return zebra_server_send_message(client);
504}
505
506/*
507 * Update all registered clients about this FEC. Caller should've updated
508 * FEC and ensure no duplicate updates.
509 */
510static void
511fec_update_clients (zebra_fec_t *fec)
512{
513 struct listnode *node;
514 struct zserv *client;
515
516 for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client))
517 {
518 if (IS_ZEBRA_DEBUG_MPLS)
519 zlog_debug ("Update client %s", zebra_route_string(client->proto));
520 fec_send(fec, client);
521 }
522}
523
524
f31e084c
DS
525/*
526 * Print a FEC-label binding entry.
527 */
528static void
529fec_print (zebra_fec_t *fec, struct vty *vty)
530{
531 struct route_node *rn;
5aba114a
DS
532 struct listnode *node;
533 struct zserv *client;
f31e084c
DS
534 char buf[BUFSIZ];
535
536 rn = fec->rn;
537 prefix2str(&rn->p, buf, BUFSIZ);
538 vty_out(vty, "%s%s", buf, VTY_NEWLINE);
539 vty_out(vty, " Label: %s", label2str(fec->label, buf, BUFSIZ));
28d58fd7
VV
540 if (fec->label_index != MPLS_INVALID_LABEL_INDEX)
541 vty_out(vty, ", Label Index: %u", fec->label_index);
f31e084c 542 vty_out(vty, "%s", VTY_NEWLINE);
5aba114a
DS
543 if (!list_isempty(fec->client_list))
544 {
545 vty_out(vty, " Client list:");
546 for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client))
547 vty_out(vty, " %s(fd %d)",
548 zebra_route_string(client->proto), client->sock);
549 vty_out(vty, "%s", VTY_NEWLINE);
550 }
f31e084c
DS
551}
552
553/*
554 * Locate FEC-label binding that matches with passed info.
555 */
556static zebra_fec_t *
557fec_find (struct route_table *table, struct prefix *p)
558{
559 struct route_node *rn;
560
561 apply_mask (p);
562 rn = route_node_lookup(table, p);
563 if (!rn)
564 return NULL;
565
566 route_unlock_node(rn);
567 return (rn->info);
568}
569
570/*
5aba114a
DS
571 * Add a FEC. This may be upon a client registering for a binding
572 * or when a binding is configured.
f31e084c
DS
573 */
574static zebra_fec_t *
575fec_add (struct route_table *table, struct prefix *p,
28d58fd7 576 mpls_label_t label, u_int32_t flags, u_int32_t label_index)
f31e084c
DS
577{
578 struct route_node *rn;
579 zebra_fec_t *fec;
580
581 apply_mask (p);
582
583 /* Lookup (or add) route node.*/
584 rn = route_node_get (table, p);
585 if (!rn)
586 return NULL;
587
588 fec = rn->info;
589
590 if (!fec)
591 {
592 fec = XCALLOC (MTYPE_FEC, sizeof(zebra_fec_t));
593 if (!fec)
594 return NULL;
595
596 rn->info = fec;
597 fec->rn = rn;
598 fec->label = label;
5aba114a 599 fec->client_list = list_new();
f31e084c
DS
600 }
601 else
602 route_unlock_node (rn); /* for the route_node_get */
603
28d58fd7 604 fec->label_index = label_index;
f31e084c
DS
605 fec->flags = flags;
606
607 return fec;
608}
609
610/*
5aba114a
DS
611 * Delete a FEC. This may be upon the last client deregistering for
612 * a FEC and no binding exists or when the binding is deleted and there
613 * are no registered clients.
f31e084c
DS
614 */
615static int
616fec_del (zebra_fec_t *fec)
617{
5aba114a 618 list_free (fec->client_list);
f31e084c
DS
619 fec->rn->info = NULL;
620 route_unlock_node (fec->rn);
621 XFREE (MTYPE_FEC, fec);
622 return 0;
623}
624
7758e3f3 625/*
626 * Hash function for label.
627 */
628static unsigned int
629label_hash (void *p)
630{
631 const zebra_ile_t *ile = p;
632
633 return (jhash_1word(ile->in_label, 0));
634}
635
636/*
637 * Compare 2 LSP hash entries based on in-label.
638 */
639static int
640label_cmp (const void *p1, const void *p2)
641{
642 const zebra_ile_t *ile1 = p1;
643 const zebra_ile_t *ile2 = p2;
644
645 return (ile1->in_label == ile2->in_label);
646}
647
40c7bdb0 648/*
649 * Check if an IPv4 nexthop for a NHLFE is active. Update nexthop based on
650 * the passed flag.
651 * NOTE: Looking only for connected routes right now.
652 */
653static int
654nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop)
655{
656 struct route_table *table;
657 struct prefix_ipv4 p;
658 struct route_node *rn;
659 struct rib *match;
88d88a9c 660 struct nexthop *match_nh;
40c7bdb0 661
662 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
663 if (!table)
664 return 0;
665
666 /* Lookup nexthop in IPv4 routing table. */
667 memset (&p, 0, sizeof (struct prefix_ipv4));
668 p.family = AF_INET;
669 p.prefixlen = IPV4_MAX_PREFIXLEN;
670 p.prefix = nexthop->gate.ipv4;
671
672 rn = route_node_match (table, (struct prefix *) &p);
673 if (!rn)
674 return 0;
675
676 route_unlock_node (rn);
677
678 /* Locate a valid connected route. */
679 RNODE_FOREACH_RIB (rn, match)
680 {
88d88a9c
RW
681 if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED) ||
682 !CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
683 continue;
684
685 for (match_nh = match->nexthop; match_nh; match_nh = match_nh->next)
686 {
687 if (match->type == ZEBRA_ROUTE_CONNECT ||
688 nexthop->ifindex == match_nh->ifindex)
689 {
690 nexthop->ifindex = match_nh->ifindex;
691 return 1;
692 }
693 }
40c7bdb0 694 }
695
88d88a9c 696 return 0;
40c7bdb0 697}
698
699
700/*
701 * Check if an IPv6 nexthop for a NHLFE is active. Update nexthop based on
702 * the passed flag.
703 * NOTE: Looking only for connected routes right now.
704 */
705static int
706nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop)
707{
708 struct route_table *table;
709 struct prefix_ipv6 p;
710 struct route_node *rn;
711 struct rib *match;
712
713 table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
714 if (!table)
715 return 0;
716
717 /* Lookup nexthop in IPv6 routing table. */
718 memset (&p, 0, sizeof (struct prefix_ipv6));
719 p.family = AF_INET6;
720 p.prefixlen = IPV6_MAX_PREFIXLEN;
721 p.prefix = nexthop->gate.ipv6;
722
723 rn = route_node_match (table, (struct prefix *) &p);
724 if (!rn)
725 return 0;
726
727 route_unlock_node (rn);
728
729 /* Locate a valid connected route. */
730 RNODE_FOREACH_RIB (rn, match)
731 {
732 if ((match->type == ZEBRA_ROUTE_CONNECT) &&
733 !CHECK_FLAG (match->status, RIB_ENTRY_REMOVED) &&
734 CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
735 break;
736 }
737
738 if (!match || !match->nexthop)
739 return 0;
740
741 nexthop->ifindex = match->nexthop->ifindex;
742 return 1;
743}
744
745
746/*
747 * Check the nexthop reachability for a NHLFE and return if valid (reachable)
748 * or not.
749 * NOTE: Each NHLFE points to only 1 nexthop.
750 */
751static int
752nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe)
753{
754 struct nexthop *nexthop;
755 struct interface *ifp;
756
757 nexthop = nhlfe->nexthop;
758 if (!nexthop) // unexpected
759 return 0;
760
761 /* Check on nexthop based on type. */
762 switch (nexthop->type)
763 {
764 case NEXTHOP_TYPE_IPV4:
88d88a9c 765 case NEXTHOP_TYPE_IPV4_IFINDEX:
40c7bdb0 766 if (nhlfe_nexthop_active_ipv4 (nhlfe, nexthop))
767 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
768 else
769 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
770 break;
771
772 case NEXTHOP_TYPE_IPV6:
773 if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop))
774 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
775 else
776 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
777 break;
778
779 case NEXTHOP_TYPE_IPV6_IFINDEX:
780 if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
781 {
7e2b7603 782 ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT);
40c7bdb0 783 if (ifp && if_is_operative(ifp))
784 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
785 else
786 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
787 }
788 else
789 {
790 if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop))
791 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
792 else
793 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
794 }
795 break;
796
797 default:
798 break;
799 }
800
801 return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
802}
803
804/*
805 * Walk through NHLFEs for a LSP forwarding entry, verify nexthop
806 * reachability and select the best. Multipath entries are also
807 * marked. This is invoked when an LSP scheduled for processing (due
808 * to some change) is examined.
809 */
810static void
811lsp_select_best_nhlfe (zebra_lsp_t *lsp)
812{
813 zebra_nhlfe_t *nhlfe;
814 zebra_nhlfe_t *best;
815 struct nexthop *nexthop;
816 int changed = 0;
817
818 if (!lsp)
819 return;
820
821 best = NULL;
822 lsp->num_ecmp = 0;
823 UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED);
824
825 /*
826 * First compute the best path, after checking nexthop status. We are only
827 * concerned with non-deleted NHLFEs.
828 */
829 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
830 {
831 /* Clear selection flags. */
832 UNSET_FLAG (nhlfe->flags,
833 (NHLFE_FLAG_SELECTED | NHLFE_FLAG_MULTIPATH));
834
835 if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) &&
836 nhlfe_nexthop_active (nhlfe))
837 {
838 if (!best || (nhlfe->distance < best->distance))
839 best = nhlfe;
840 }
841 }
842
843 lsp->best_nhlfe = best;
844 if (!lsp->best_nhlfe)
845 return;
846
847 /* Mark best NHLFE as selected. */
848 SET_FLAG (lsp->best_nhlfe->flags, NHLFE_FLAG_SELECTED);
849
850 /*
851 * If best path exists, see if there is ECMP. While doing this, note if a
852 * new (uninstalled) NHLFE has been selected, an installed entry that is
853 * still selected has a change or an installed entry is to be removed.
854 */
855 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
856 {
857 int nh_chg, nh_sel, nh_inst;
858
859 nexthop = nhlfe->nexthop;
860 if (!nexthop) // unexpected
861 continue;
862
863 if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) &&
864 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) &&
865 (nhlfe->distance == lsp->best_nhlfe->distance))
866 {
867 SET_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED);
868 SET_FLAG (nhlfe->flags, NHLFE_FLAG_MULTIPATH);
869 lsp->num_ecmp++;
870 }
871
872 if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED) &&
873 !changed)
874 {
875 nh_chg = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
876 nh_sel = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED);
877 nh_inst = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED);
878
879 if ((nh_sel && !nh_inst) ||
880 (nh_sel && nh_inst && nh_chg) ||
881 (nh_inst && !nh_sel))
882 changed = 1;
883 }
884
885 /* We have finished examining, clear changed flag. */
886 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
887 }
888
889 if (changed)
890 SET_FLAG (lsp->flags, LSP_FLAG_CHANGED);
891}
892
893/*
894 * Delete LSP forwarding entry from kernel, if installed. Called upon
895 * process exit.
896 */
897static void
898lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt)
899{
900 zebra_lsp_t *lsp;
901
902 lsp = (zebra_lsp_t *) backet->data;
903 if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
904 kernel_del_lsp (lsp);
905}
906
907/*
908 * Schedule LSP forwarding entry for processing. Called upon changes
909 * that may impact LSPs such as nexthop / connected route changes.
910 */
911static void
912lsp_schedule (struct hash_backet *backet, void *ctxt)
913{
914 zebra_lsp_t *lsp;
915
916 lsp = (zebra_lsp_t *) backet->data;
917 lsp_processq_add (lsp);
918}
919
920/*
921 * Process a LSP entry that is in the queue. Recalculate best NHLFE and
922 * any multipaths and update or delete from the kernel, as needed.
923 */
924static wq_item_status
925lsp_process (struct work_queue *wq, void *data)
926{
927 zebra_lsp_t *lsp;
928 zebra_nhlfe_t *oldbest, *newbest;
929 char buf[BUFSIZ], buf2[BUFSIZ];
930
931 lsp = (zebra_lsp_t *)data;
932 if (!lsp) // unexpected
933 return WQ_SUCCESS;
934
935 oldbest = lsp->best_nhlfe;
936
937 /* Select best NHLFE(s) */
938 lsp_select_best_nhlfe (lsp);
939
940 newbest = lsp->best_nhlfe;
941
942 if (IS_ZEBRA_DEBUG_MPLS)
943 {
944 if (oldbest)
945 nhlfe2str (oldbest, buf, BUFSIZ);
946 if (newbest)
947 nhlfe2str (newbest, buf2, BUFSIZ);
948 zlog_debug ("Process LSP in-label %u oldbest %s newbest %s "
949 "flags 0x%x ecmp# %d",
950 lsp->ile.in_label, oldbest ? buf : "NULL",
951 newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp);
952 }
953
954 if (!CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED))
955 {
956 /* Not already installed */
957 if (newbest)
958 kernel_add_lsp (lsp);
959 }
960 else
961 {
962 /* Installed, may need an update and/or delete. */
963 if (!newbest)
964 kernel_del_lsp (lsp);
965 else if (CHECK_FLAG (lsp->flags, LSP_FLAG_CHANGED))
966 kernel_upd_lsp (lsp);
967 }
968
969 return WQ_SUCCESS;
970}
971
972
973/*
974 * Callback upon processing completion of a LSP forwarding entry.
975 */
976static void
977lsp_processq_del (struct work_queue *wq, void *data)
978{
979 struct zebra_vrf *zvrf;
980 zebra_lsp_t *lsp;
981 struct hash *lsp_table;
982 zebra_nhlfe_t *nhlfe, *nhlfe_next;
983
984 zvrf = vrf_info_lookup(VRF_DEFAULT);
985 assert (zvrf);
986
987 lsp_table = zvrf->lsp_table;
988 if (!lsp_table) // unexpected
989 return;
990
991 lsp = (zebra_lsp_t *)data;
992 if (!lsp) // unexpected
993 return;
994
995 /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs exist,
996 * delete LSP entry also.
997 */
998 UNSET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED);
999
1000 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next)
1001 {
1002 nhlfe_next = nhlfe->next;
1003 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED))
1004 nhlfe_del (nhlfe);
1005 }
1006
1007 if (!lsp->nhlfe_list)
1008 {
1009 if (IS_ZEBRA_DEBUG_MPLS)
1010 zlog_debug ("Free LSP in-label %u flags 0x%x",
1011 lsp->ile.in_label, lsp->flags);
1012
1013 lsp = hash_release(lsp_table, &lsp->ile);
1014 if (lsp)
1015 XFREE(MTYPE_LSP, lsp);
1016 }
1017}
1018
1019/*
1020 * Callback upon finishing the processing of all scheduled
1021 * LSP forwarding entries.
1022 */
1023static void
1024lsp_processq_complete (struct work_queue *wq)
1025{
1026 /* Nothing to do for now. */
1027}
1028
1029/*
1030 * Add LSP forwarding entry to queue for subsequent processing.
1031 */
1032static int
1033lsp_processq_add (zebra_lsp_t *lsp)
1034{
1035 /* If already scheduled, exit. */
1036 if (CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
1037 return 0;
1038
33c32282
DW
1039 if (zebrad.lsp_process_q == NULL)
1040 {
1041 zlog_err ("%s: work_queue does not exist!", __func__);
1042 return -1;
1043 }
1044
40c7bdb0 1045 work_queue_add (zebrad.lsp_process_q, lsp);
1046 SET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED);
1047 return 0;
1048}
1049
1050/*
1051 * Callback to allocate LSP forwarding table entry.
1052 */
1053static void *
1054lsp_alloc (void *p)
1055{
1056 const zebra_ile_t *ile = p;
1057 zebra_lsp_t *lsp;
1058
1059 lsp = XCALLOC (MTYPE_LSP, sizeof(zebra_lsp_t));
1060 lsp->ile = *ile;
1061
1062 if (IS_ZEBRA_DEBUG_MPLS)
1063 zlog_debug ("Alloc LSP in-label %u", lsp->ile.in_label);
1064
1065 return ((void *)lsp);
1066}
1067
1068/*
1069 * Create printable string for NHLFE entry.
1070 */
1071static char *
1072nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size)
1073{
1074 struct nexthop *nexthop;
1075
1076 buf[0] = '\0';
1077 nexthop = nhlfe->nexthop;
1078 switch (nexthop->type)
1079 {
1080 case NEXTHOP_TYPE_IPV4:
88d88a9c 1081 case NEXTHOP_TYPE_IPV4_IFINDEX:
40c7bdb0 1082 inet_ntop (AF_INET, &nexthop->gate.ipv4, buf, size);
1083 break;
1084 case NEXTHOP_TYPE_IPV6:
1085 inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, size);
1086 break;
1087 default:
1088 break;
1089 }
1090
1091 return buf;
1092}
1093
1094/*
1095 * Check if NHLFE matches with search info passed.
1096 */
1097static int
1098nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
a64448ba 1099 union g_addr *gate, ifindex_t ifindex)
40c7bdb0 1100{
1101 struct nexthop *nhop;
ea6bebb8 1102 int cmp = 1;
40c7bdb0 1103
1104 nhop = nhlfe->nexthop;
1105 if (!nhop)
ea6bebb8 1106 return 1;
40c7bdb0 1107
1108 if (nhop->type != gtype)
ea6bebb8 1109 return 1;
40c7bdb0 1110
1111 switch (nhop->type)
1112 {
1113 case NEXTHOP_TYPE_IPV4:
88d88a9c 1114 case NEXTHOP_TYPE_IPV4_IFINDEX:
40c7bdb0 1115 cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4),
ea6bebb8 1116 sizeof(struct in_addr));
88d88a9c
RW
1117 if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1118 cmp = !(nhop->ifindex == ifindex);
40c7bdb0 1119 break;
1120 case NEXTHOP_TYPE_IPV6:
1121 case NEXTHOP_TYPE_IPV6_IFINDEX:
1122 cmp = memcmp(&(nhop->gate.ipv6), &(gate->ipv6),
1123 sizeof(struct in6_addr));
1124 if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1125 cmp = !(nhop->ifindex == ifindex);
1126 break;
1127 default:
1128 break;
1129 }
1130
1131 return cmp;
1132}
1133
1134
1135/*
1136 * Locate NHLFE that matches with passed info.
1137 */
1138static zebra_nhlfe_t *
1139nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
1140 enum nexthop_types_t gtype, union g_addr *gate,
a64448ba 1141 ifindex_t ifindex)
40c7bdb0 1142{
1143 zebra_nhlfe_t *nhlfe;
1144
1145 if (!lsp)
1146 return NULL;
1147
1148 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1149 {
1150 if (nhlfe->type != lsp_type)
1151 continue;
a64448ba 1152 if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifindex))
40c7bdb0 1153 break;
1154 }
1155
1156 return nhlfe;
1157}
1158
1159/*
1160 * Add NHLFE. Base entry must have been created and duplicate
1161 * check done.
1162 */
1163static zebra_nhlfe_t *
1164nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
1165 enum nexthop_types_t gtype, union g_addr *gate,
a64448ba 1166 ifindex_t ifindex, mpls_label_t out_label)
40c7bdb0 1167{
1168 zebra_nhlfe_t *nhlfe;
1169 struct nexthop *nexthop;
1170
1171 if (!lsp)
1172 return NULL;
1173
1174 nhlfe = XCALLOC(MTYPE_NHLFE, sizeof(zebra_nhlfe_t));
1175 if (!nhlfe)
1176 return NULL;
1177
1178 nhlfe->lsp = lsp;
1179 nhlfe->type = lsp_type;
1180 nhlfe->distance = lsp_distance (lsp_type);
1181
1182 nexthop = nexthop_new();
1183 if (!nexthop)
1184 {
1185 XFREE (MTYPE_NHLFE, nhlfe);
1186 return NULL;
1187 }
ce549947 1188 nexthop_add_labels (nexthop, lsp_type, 1, &out_label);
40c7bdb0 1189
1190 nexthop->type = gtype;
1191 switch (nexthop->type)
1192 {
1193 case NEXTHOP_TYPE_IPV4:
88d88a9c 1194 case NEXTHOP_TYPE_IPV4_IFINDEX:
40c7bdb0 1195 nexthop->gate.ipv4 = gate->ipv4;
88d88a9c
RW
1196 if (ifindex)
1197 nexthop->ifindex = ifindex;
40c7bdb0 1198 break;
1199 case NEXTHOP_TYPE_IPV6:
1200 case NEXTHOP_TYPE_IPV6_IFINDEX:
1201 nexthop->gate.ipv6 = gate->ipv6;
1202 if (ifindex)
1203 nexthop->ifindex = ifindex;
1204 break;
1205 default:
1206 nexthop_free(nexthop);
1207 XFREE (MTYPE_NHLFE, nhlfe);
1208 return NULL;
1209 break;
1210 }
1211
1212 nhlfe->nexthop = nexthop;
1213 if (lsp->nhlfe_list)
1214 lsp->nhlfe_list->prev = nhlfe;
1215 nhlfe->next = lsp->nhlfe_list;
1216 lsp->nhlfe_list = nhlfe;
1217
1218 return nhlfe;
1219}
1220
1221/*
1222 * Delete NHLFE. Entry must be present on list.
1223 */
1224static int
1225nhlfe_del (zebra_nhlfe_t *nhlfe)
1226{
1227 zebra_lsp_t *lsp;
1228
1229 if (!nhlfe)
1230 return -1;
1231
1232 lsp = nhlfe->lsp;
1233 if (!lsp)
1234 return -1;
1235
1236 /* Free nexthop. */
1237 if (nhlfe->nexthop)
1238 nexthop_free(nhlfe->nexthop);
1239
1240 /* Unlink from LSP */
1241 if (nhlfe->next)
1242 nhlfe->next->prev = nhlfe->prev;
1243 if (nhlfe->prev)
1244 nhlfe->prev->next = nhlfe->next;
1245 else
1246 lsp->nhlfe_list = nhlfe->next;
1247
bb49a121
FR
1248 if (nhlfe == lsp->best_nhlfe)
1249 lsp->best_nhlfe = NULL;
1250
40c7bdb0 1251 XFREE (MTYPE_NHLFE, nhlfe);
1252
1253 return 0;
1254}
1255
a64448ba
DS
1256/*
1257 * Update label for NHLFE entry.
1258 */
1259static void
1260nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label)
1261{
1262 nhlfe->nexthop->nh_label->label[0] = nh_label->label[0];
1263}
1264
40c7bdb0 1265static int
ce549947
RW
1266mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
1267 enum lsp_types_t type)
40c7bdb0 1268{
40c7bdb0 1269 zebra_nhlfe_t *nhlfe, *nhlfe_next;
1270 int schedule_lsp = 0;
1271 char buf[BUFSIZ];
1272
40c7bdb0 1273 /* Mark NHLFEs for delete or directly delete, as appropriate. */
1274 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next)
1275 {
1276 nhlfe_next = nhlfe->next;
1277
1278 /* Skip non-static NHLFEs */
ce549947 1279 if (nhlfe->type != type)
40c7bdb0 1280 continue;
1281
1282 if (IS_ZEBRA_DEBUG_MPLS)
1283 {
1284 nhlfe2str (nhlfe, buf, BUFSIZ);
1285 zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
ce549947 1286 lsp->ile.in_label, type, buf, nhlfe->flags);
40c7bdb0 1287 }
1288
1289 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
1290 {
1291 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
1292 SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
1293 schedule_lsp = 1;
1294 }
1295 else
1296 {
1297 nhlfe_del (nhlfe);
1298 }
1299 }
1300
1301 /* Queue LSP for processing, if needed, else delete. */
1302 if (schedule_lsp)
1303 {
1304 if (lsp_processq_add (lsp))
1305 return -1;
1306 }
1307 else if (!lsp->nhlfe_list &&
1308 !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
1309 {
1310 if (IS_ZEBRA_DEBUG_MPLS)
1311 zlog_debug ("Free LSP in-label %u flags 0x%x",
1312 lsp->ile.in_label, lsp->flags);
1313
1314 lsp = hash_release(lsp_table, &lsp->ile);
1315 if (lsp)
1316 XFREE(MTYPE_LSP, lsp);
1317 }
1318
1319 return 0;
1320}
1321
ce549947
RW
1322/*
1323 * Uninstall all static NHLFEs for a particular LSP forwarding entry.
1324 * If no other NHLFEs exist, the entry would be deleted.
1325 */
1326static int
1327mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label)
1328{
1329 struct hash *lsp_table;
1330 zebra_ile_t tmp_ile;
1331 zebra_lsp_t *lsp;
1332
1333 /* Lookup table. */
1334 lsp_table = zvrf->lsp_table;
1335 if (!lsp_table)
1336 return -1;
1337
1338 /* If entry is not present, exit. */
1339 tmp_ile.in_label = in_label;
1340 lsp = hash_lookup (lsp_table, &tmp_ile);
1341 if (!lsp || !lsp->nhlfe_list)
1342 return 0;
1343
1344 return mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_STATIC);
1345}
1346
b78b820d 1347static json_object *
1348nhlfe_json (zebra_nhlfe_t *nhlfe)
1349{
1350 char buf[BUFSIZ];
1351 json_object *json_nhlfe = NULL;
1352 struct nexthop *nexthop = nhlfe->nexthop;
1353
1354 json_nhlfe = json_object_new_object();
1355 json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type));
1356 json_object_int_add(json_nhlfe, "outLabel", nexthop->nh_label->label[0]);
1357 json_object_int_add(json_nhlfe, "distance", nhlfe->distance);
1358
1359 if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED))
1360 json_object_boolean_true_add(json_nhlfe, "installed");
1361
1362 switch (nexthop->type)
1363 {
1364 case NEXTHOP_TYPE_IPV4:
88d88a9c 1365 case NEXTHOP_TYPE_IPV4_IFINDEX:
b78b820d 1366 json_object_string_add(json_nhlfe, "nexthop",
1367 inet_ntoa (nexthop->gate.ipv4));
1368 break;
1369 case NEXTHOP_TYPE_IPV6:
1370 case NEXTHOP_TYPE_IPV6_IFINDEX:
1371 json_object_string_add(json_nhlfe, "nexthop",
1372 inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
1373
1374 if (nexthop->ifindex)
baaea325 1375 json_object_string_add(json_nhlfe, "interface", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT));
b78b820d 1376 break;
1377 default:
1378 break;
1379 }
1380 return json_nhlfe;
1381}
1382
3ab18ff2 1383/*
1384 * Print the NHLFE for a LSP forwarding entry.
1385 */
1386static void
1387nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty)
1388{
1389 struct nexthop *nexthop;
1390 char buf[BUFSIZ];
1391
1392 nexthop = nhlfe->nexthop;
1393 if (!nexthop || !nexthop->nh_label) // unexpected
1394 return;
1395
1396 vty_out(vty, " type: %s remote label: %s distance: %d%s",
1397 nhlfe_type2str(nhlfe->type),
1398 label2str(nexthop->nh_label->label[0], buf, BUFSIZ),
1399 nhlfe->distance, VTY_NEWLINE);
1400 switch (nexthop->type)
1401 {
1402 case NEXTHOP_TYPE_IPV4:
88d88a9c 1403 case NEXTHOP_TYPE_IPV4_IFINDEX:
3ab18ff2 1404 vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
88d88a9c 1405 if (nexthop->ifindex)
baaea325 1406 vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT));
3ab18ff2 1407 break;
1408 case NEXTHOP_TYPE_IPV6:
1409 case NEXTHOP_TYPE_IPV6_IFINDEX:
1410 vty_out (vty, " via %s",
b78b820d 1411 inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
3ab18ff2 1412 if (nexthop->ifindex)
baaea325 1413 vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT));
3ab18ff2 1414 break;
1415 default:
1416 break;
1417 }
1418 vty_out(vty, "%s", CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) ?
1419 " (installed)" : "");
1420 vty_out(vty, "%s", VTY_NEWLINE);
1421}
1422
1423/*
1424 * Print an LSP forwarding entry.
1425 */
1426static void
1427lsp_print (zebra_lsp_t *lsp, void *ctxt)
1428{
1429 zebra_nhlfe_t *nhlfe;
1430 struct vty *vty;
1431
1432 vty = (struct vty *) ctxt;
1433
1434 vty_out(vty, "Local label: %u%s%s",
1435 lsp->ile.in_label,
1436 CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" : "",
1437 VTY_NEWLINE);
1438
1439 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1440 nhlfe_print (nhlfe, vty);
1441}
1442
1443/*
b78b820d 1444 * JSON objects for an LSP forwarding entry.
3ab18ff2 1445 */
b78b820d 1446static json_object *
1447lsp_json (zebra_lsp_t *lsp)
3ab18ff2 1448{
b78b820d 1449 zebra_nhlfe_t *nhlfe = NULL;
1450 json_object *json = json_object_new_object();
1451 json_object *json_nhlfe_list = json_object_new_array();
3ab18ff2 1452
b78b820d 1453 json_object_int_add(json, "inLabel", lsp->ile.in_label);
1454
1455 if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED))
1456 json_object_boolean_true_add(json, "installed");
3ab18ff2 1457
b78b820d 1458 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
1459 json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe));
1460
1461 json_object_object_add(json, "nexthops", json_nhlfe_list);
1462 return json;
1463}
1464
1465
1466/* Return a sorted linked list of the hash contents */
1467static struct list *
1468hash_get_sorted_list (struct hash *hash, void *cmp)
1469{
1470 unsigned int i;
1471 struct hash_backet *hb;
1472 struct list *sorted_list = list_new();
1473
1474 sorted_list->cmp = (int (*)(void *, void *)) cmp;
1475
1476 for (i = 0; i < hash->size; i++)
1477 for (hb = hash->index[i]; hb; hb = hb->next)
1478 listnode_add_sort(sorted_list, hb->data);
1479
1480 return sorted_list;
3ab18ff2 1481}
1482
7758e3f3 1483/*
b78b820d 1484 * Compare two LSPs based on their label values.
7758e3f3 1485 */
b78b820d 1486static int
1487lsp_cmp (zebra_lsp_t *lsp1, zebra_lsp_t *lsp2)
7758e3f3 1488{
b78b820d 1489 if (lsp1->ile.in_label < lsp2->ile.in_label)
1490 return -1;
7758e3f3 1491
b78b820d 1492 if (lsp1->ile.in_label > lsp2->ile.in_label)
1493 return 1;
7758e3f3 1494
b78b820d 1495 return 0;
7758e3f3 1496}
1497
1498/*
1499 * Callback to allocate static LSP.
1500 */
1501static void *
1502slsp_alloc (void *p)
1503{
1504 const zebra_ile_t *ile = p;
1505 zebra_slsp_t *slsp;
1506
1507 slsp = XCALLOC (MTYPE_SLSP, sizeof(zebra_slsp_t));
1508 slsp->ile = *ile;
1509 return ((void *)slsp);
1510}
1511
b78b820d 1512/*
1513 * Compare two static LSPs based on their label values.
1514 */
1515static int
1516slsp_cmp (zebra_slsp_t *slsp1, zebra_slsp_t *slsp2)
1517{
1518 if (slsp1->ile.in_label < slsp2->ile.in_label)
1519 return -1;
1520
1521 if (slsp1->ile.in_label > slsp2->ile.in_label)
1522 return 1;
1523
1524 return 0;
1525}
1526
7758e3f3 1527/*
1528 * Check if static NHLFE matches with search info passed.
1529 */
1530static int
1531snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
a64448ba 1532 union g_addr *gate, ifindex_t ifindex)
7758e3f3 1533{
ea6bebb8 1534 int cmp = 1;
7758e3f3 1535
1536 if (snhlfe->gtype != gtype)
ea6bebb8 1537 return 1;
7758e3f3 1538
1539 switch (snhlfe->gtype)
1540 {
1541 case NEXTHOP_TYPE_IPV4:
1542 cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4),
1543 sizeof(struct in_addr));
1544 break;
1545 case NEXTHOP_TYPE_IPV6:
1546 case NEXTHOP_TYPE_IPV6_IFINDEX:
1547 cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6),
1548 sizeof(struct in6_addr));
1549 if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1550 cmp = !(snhlfe->ifindex == ifindex);
1551 break;
1552 default:
1553 break;
1554 }
1555
1556 return cmp;
1557}
1558
1559/*
1560 * Locate static NHLFE that matches with passed info.
1561 */
1562static zebra_snhlfe_t *
1563snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
a64448ba 1564 union g_addr *gate, ifindex_t ifindex)
7758e3f3 1565{
1566 zebra_snhlfe_t *snhlfe;
1567
1568 if (!slsp)
1569 return NULL;
1570
1571 for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next)
1572 {
a64448ba 1573 if (!snhlfe_match (snhlfe, gtype, gate, ifindex))
7758e3f3 1574 break;
1575 }
1576
1577 return snhlfe;
1578}
1579
1580
1581/*
1582 * Add static NHLFE. Base LSP config entry must have been created
1583 * and duplicate check done.
1584 */
1585static zebra_snhlfe_t *
1586snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
a64448ba 1587 union g_addr *gate, ifindex_t ifindex,
7758e3f3 1588 mpls_label_t out_label)
1589{
1590 zebra_snhlfe_t *snhlfe;
1591
1592 if (!slsp)
1593 return NULL;
1594
1595 snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t));
1596 snhlfe->slsp = slsp;
1597 snhlfe->out_label = out_label;
1598 snhlfe->gtype = gtype;
1599 switch (gtype)
1600 {
1601 case NEXTHOP_TYPE_IPV4:
1602 snhlfe->gate.ipv4 = gate->ipv4;
1603 break;
1604 case NEXTHOP_TYPE_IPV6:
1605 case NEXTHOP_TYPE_IPV6_IFINDEX:
1606 snhlfe->gate.ipv6 = gate->ipv6;
1607 if (ifindex)
1608 snhlfe->ifindex = ifindex;
1609 break;
1610 default:
1611 XFREE (MTYPE_SNHLFE, snhlfe);
1612 return NULL;
1613 }
1614
1615 if (slsp->snhlfe_list)
1616 slsp->snhlfe_list->prev = snhlfe;
1617 snhlfe->next = slsp->snhlfe_list;
1618 slsp->snhlfe_list = snhlfe;
1619
1620 return snhlfe;
1621}
1622
1623/*
1624 * Delete static NHLFE. Entry must be present on list.
1625 */
1626static int
1627snhlfe_del (zebra_snhlfe_t *snhlfe)
1628{
1629 zebra_slsp_t *slsp;
1630
1631 if (!snhlfe)
1632 return -1;
1633
1634 slsp = snhlfe->slsp;
1635 if (!slsp)
1636 return -1;
1637
1638 if (snhlfe->next)
1639 snhlfe->next->prev = snhlfe->prev;
1640 if (snhlfe->prev)
1641 snhlfe->prev->next = snhlfe->next;
1642 else
1643 slsp->snhlfe_list = snhlfe->next;
1644
1645 snhlfe->prev = snhlfe->next = NULL;
1646 if (snhlfe->ifname)
1647 XFREE (MTYPE_SNHLFE_IFNAME, snhlfe->ifname);
1648 XFREE (MTYPE_SNHLFE, snhlfe);
1649
1650 return 0;
1651}
1652
1653/*
1654 * Delete all static NHLFE entries for this LSP (in label).
1655 */
1656static int
1657snhlfe_del_all (zebra_slsp_t *slsp)
1658{
1659 zebra_snhlfe_t *snhlfe, *snhlfe_next;
1660
1661 if (!slsp)
1662 return -1;
1663
1664 for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe_next)
1665 {
1666 snhlfe_next = snhlfe->next;
1667 snhlfe_del (snhlfe);
1668 }
1669
1670 return 0;
1671}
1672
1673/*
1674 * Create printable string for NHLFE configuration.
1675 */
1676static char *
1677snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size)
1678{
1679 buf[0] = '\0';
1680 switch (snhlfe->gtype)
1681 {
1682 case NEXTHOP_TYPE_IPV4:
1683 inet_ntop (AF_INET, &snhlfe->gate.ipv4, buf, size);
1684 break;
1685 case NEXTHOP_TYPE_IPV6:
1686 case NEXTHOP_TYPE_IPV6_IFINDEX:
1687 inet_ntop (AF_INET6, &snhlfe->gate.ipv6, buf, size);
1688 if (snhlfe->ifindex)
baaea325 1689 strcat (buf, ifindex2ifname (snhlfe->ifindex, VRF_DEFAULT));
7758e3f3 1690 break;
1691 default:
1692 break;
1693 }
1694
1695 return buf;
1696}
1697
40c7bdb0 1698/*
1699 * Initialize work queue for processing changed LSPs.
1700 */
33c32282 1701static int
40c7bdb0 1702mpls_processq_init (struct zebra_t *zebra)
1703{
1704 zebra->lsp_process_q = work_queue_new (zebra->master, "LSP processing");
1705 if (!zebra->lsp_process_q)
1706 {
1707 zlog_err ("%s: could not initialise work queue!", __func__);
33c32282 1708 return -1;
40c7bdb0 1709 }
1710
1711 zebra->lsp_process_q->spec.workfunc = &lsp_process;
1712 zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del;
1713 zebra->lsp_process_q->spec.errorfunc = NULL;
1714 zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete;
1715 zebra->lsp_process_q->spec.max_retries = 0;
1716 zebra->lsp_process_q->spec.hold = 10;
33c32282
DW
1717
1718 return 0;
40c7bdb0 1719}
1720
7758e3f3 1721
1722
1723/* Public functions */
1724
a22f3f5d 1725/*
1726 * String to label conversion, labels separated by '/'.
1727 */
1728int
1729mpls_str2label (const char *label_str, u_int8_t *num_labels,
1730 mpls_label_t *labels)
1731{
1732 char *endp;
1733 int i;
1734
1735 *num_labels = 0;
1736 for (i = 0; i < MPLS_MAX_LABELS; i++)
1737 {
a64448ba 1738 mpls_label_t label;
a22f3f5d 1739
1740 label = strtoul(label_str, &endp, 0);
1741
1742 /* validity checks */
1743 if (endp == label_str)
1744 return -1;
1745
1746 if (!IS_MPLS_UNRESERVED_LABEL(label))
1747 return -1;
1748
1749 labels[i] = label;
1750 if (*endp == '\0')
1751 {
1752 *num_labels = i + 1;
1753 return 0;
1754 }
1755
1756 /* Check separator. */
1757 if (*endp != '/')
1758 return -1;
1759
1760 label_str = endp + 1;
1761 }
1762
1763 /* Too many labels. */
1764 return -1;
1765}
1766
1767/*
1768 * Label to string conversion, labels in string separated by '/'.
1769 */
1770char *
1771mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
4caac24b 1772 char *buf, int len, int pretty)
a22f3f5d 1773{
4caac24b 1774 char *buf_ptr = buf;
a22f3f5d 1775 buf[0] = '\0';
4caac24b
DW
1776
1777 if (pretty) {
1778 if (num_labels == 1) {
1779 label2str(labels[0], buf, len);
1780 } else if (num_labels == 2) {
1781 label2str(labels[0], buf, len);
1782 buf_ptr += strlen(buf);
1783
1784 snprintf (buf_ptr, len, "/");
1785 buf_ptr++;
1786
1787 label2str(labels[1], buf_ptr, len);
1788 }
1789 } else {
1790 if (num_labels == 1)
1791 snprintf (buf, len, "%u", labels[0]);
1792 else if (num_labels == 2)
1793 snprintf (buf, len, "%u/%u", labels[0], labels[1]);
1794 }
a22f3f5d 1795 return buf;
1796}
1797
a64448ba
DS
1798/*
1799 * Install dynamic LSP entry.
1800 */
1801int
1802zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
1803{
1804 struct route_table *table;
1805 zebra_fec_t *fec;
1806
1807 table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
1808 if (!table)
1809 return -1;
1810
1811 /* See if there is a configured label binding for this FEC. */
1812 fec = fec_find (table, &rn->p);
1813 if (!fec || fec->label == MPLS_INVALID_LABEL)
1814 return 0;
1815
1816 /* We cannot install a label forwarding entry if local label is the
1817 * implicit-null label.
1818 */
1819 if (fec->label == MPLS_IMP_NULL_LABEL)
1820 return 0;
1821
1822 if (lsp_install (zvrf, fec->label, rn, rib))
1823 return -1;
1824
1825 return 0;
1826}
1827
1828/*
1829 * Uninstall dynamic LSP entry, if any.
1830 */
1831int
1832zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
1833{
1834 struct route_table *table;
1835 zebra_fec_t *fec;
1836
1837 table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
1838 if (!table)
1839 return -1;
1840
1841 /* See if there is a configured label binding for this FEC. */
1842 fec = fec_find (table, &rn->p);
1843 if (!fec || fec->label == MPLS_INVALID_LABEL)
1844 return 0;
1845
1846 /* Uninstall always removes all dynamic NHLFEs. */
1847 return lsp_uninstall (zvrf, fec->label);
1848}
1849
5aba114a
DS
1850/*
1851 * Registration from a client for the label binding for a FEC. If a binding
1852 * already exists, it is informed to the client.
28d58fd7
VV
1853 * NOTE: If there is a manually configured label binding, that is used.
1854 * Otherwise, if aa label index is specified, it means we have to allocate the
1855 * label from a locally configured label block (SRGB), if one exists and index
1856 * is acceptable.
5aba114a
DS
1857 */
1858int
1859zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p,
28d58fd7 1860 u_int32_t label_index, struct zserv *client)
5aba114a
DS
1861{
1862 struct route_table *table;
1863 zebra_fec_t *fec;
1864 char buf[BUFSIZ];
28d58fd7
VV
1865 int new_client;
1866 int label_change = 0;
1867 u_int32_t old_label;
5aba114a
DS
1868
1869 table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
1870 if (!table)
1871 return -1;
1872
1873 if (IS_ZEBRA_DEBUG_MPLS)
1874 prefix2str(p, buf, BUFSIZ);
1875
1876 /* Locate FEC */
1877 fec = fec_find (table, p);
1878 if (!fec)
1879 {
28d58fd7 1880 fec = fec_add (table, p, MPLS_INVALID_LABEL, 0, label_index);
5aba114a
DS
1881 if (!fec)
1882 {
1883 prefix2str(p, buf, BUFSIZ);
1884 zlog_err("Failed to add FEC %s upon register, client %s",
1885 buf, zebra_route_string(client->proto));
1886 return -1;
1887 }
28d58fd7
VV
1888
1889 old_label = MPLS_INVALID_LABEL;
1890 new_client = 1;
5aba114a
DS
1891 }
1892 else
1893 {
28d58fd7
VV
1894 /* Client may register same FEC with different label index. */
1895 new_client = (listnode_lookup(fec->client_list, client) == NULL);
1896 if (!new_client && fec->label_index == label_index)
5aba114a
DS
1897 /* Duplicate register */
1898 return 0;
28d58fd7
VV
1899
1900 /* Save current label, update label index */
1901 old_label = fec->label;
1902 fec->label_index = label_index;
5aba114a
DS
1903 }
1904
28d58fd7
VV
1905 if (new_client)
1906 listnode_add (fec->client_list, client);
5aba114a
DS
1907
1908 if (IS_ZEBRA_DEBUG_MPLS)
28d58fd7
VV
1909 zlog_debug("FEC %s Label Index %u %s by client %s",
1910 buf, label_index, new_client ? "registered" : "updated",
1911 zebra_route_string(client->proto));
1912
1913 /* If not a configured FEC, derive the local label (from label index)
1914 * or reset it.
1915 */
1916 if (!(fec->flags & FEC_FLAG_CONFIGURED))
1917 {
1918 fec_derive_label_from_index (zvrf, fec);
1919
1920 /* If no label change, exit. */
1921 if (fec->label == old_label)
1922 return 0;
5aba114a 1923
28d58fd7
VV
1924 label_change = 1;
1925 }
1926
1927 /* If new client or label change, update client and install or uninstall
1928 * label forwarding entry as needed.
1929 */
1930 /* Inform client of label, if needed. */
1931 if ((new_client && fec->label != MPLS_INVALID_LABEL) ||
1932 label_change)
5aba114a
DS
1933 {
1934 if (IS_ZEBRA_DEBUG_MPLS)
1935 zlog_debug ("Update client label %u", fec->label);
1936 fec_send (fec, client);
1937 }
1938
28d58fd7
VV
1939 if (new_client || label_change)
1940 return fec_change_update_lsp (zvrf, fec, old_label);
1941
5aba114a
DS
1942 return 0;
1943}
1944
1945/*
1946 * Deregistration from a client for the label binding for a FEC. The FEC
1947 * itself is deleted if no other registered clients exist and there is no
1948 * label bound to the FEC.
1949 */
1950int
1951zebra_mpls_fec_unregister (struct zebra_vrf *zvrf, struct prefix *p,
1952 struct zserv *client)
1953{
1954 struct route_table *table;
1955 zebra_fec_t *fec;
1956 char buf[BUFSIZ];
1957
1958 table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
1959 if (!table)
1960 return -1;
1961
1962 if (IS_ZEBRA_DEBUG_MPLS)
1963 prefix2str(p, buf, BUFSIZ);
1964
1965 fec = fec_find (table, p);
1966 if (!fec)
1967 {
1968 prefix2str(p, buf, BUFSIZ);
1969 zlog_err("Failed to find FEC %s upon unregister, client %s",
1970 buf, zebra_route_string(client->proto));
1971 return -1;
1972 }
1973
1974 listnode_delete(fec->client_list, client);
1975
1976 if (IS_ZEBRA_DEBUG_MPLS)
1977 zlog_debug("FEC %s unregistered by client %s",
1978 buf, zebra_route_string(client->proto));
1979
28d58fd7
VV
1980 /* If not a configured entry, delete the FEC if no other clients. Before
1981 * deleting, see if any LSP needs to be uninstalled.
1982 */
1983 if (!(fec->flags & FEC_FLAG_CONFIGURED) &&
1984 list_isempty(fec->client_list))
1985 {
1986 mpls_label_t old_label = fec->label;
1987 fec->label = MPLS_INVALID_LABEL; /* reset */
1988 fec_change_update_lsp (zvrf, fec, old_label);
1989 fec_del (fec);
1990 }
5aba114a
DS
1991
1992 return 0;
1993}
1994
1995/*
1996 * Cleanup any FECs registered by this client.
1997 */
1998int
1999zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client)
2000{
2001 struct route_node *rn;
2002 zebra_fec_t *fec;
2003 struct listnode *node;
2004 struct zserv *fec_client;
2005 int af;
2006
2007 for (af = AFI_IP; af < AFI_MAX; af++)
2008 {
2009 if (zvrf->fec_table[af] == NULL)
2010 continue;
2011
2012 for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
2013 {
2014 fec = rn->info;
2015 if (!fec || list_isempty(fec->client_list))
2016 continue;
2017
2018 for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, fec_client))
2019 {
2020 if (fec_client == client)
2021 {
2022 listnode_delete(fec->client_list, fec_client);
2023 if (!(fec->flags & FEC_FLAG_CONFIGURED) &&
2024 list_isempty(fec->client_list))
2025 fec_del (fec);
2026 break;
2027 }
2028 }
2029 }
2030 }
2031
2032 return 0;
2033}
2034
f31e084c
DS
2035/*
2036 * Return FEC (if any) to which this label is bound.
2037 * Note: Only works for per-prefix binding and when the label is not
2038 * implicit-null.
2039 * TODO: Currently walks entire table, can optimize later with another
2040 * hash..
2041 */
2042zebra_fec_t *
2043zebra_mpls_fec_for_label (struct zebra_vrf *zvrf, mpls_label_t label)
2044{
2045 struct route_node *rn;
2046 zebra_fec_t *fec;
2047 int af;
2048
2049 for (af = AFI_IP; af < AFI_MAX; af++)
2050 {
2051 if (zvrf->fec_table[af] == NULL)
2052 continue;
2053
2054 for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
2055 {
2056 if (!rn->info)
2057 continue;
2058 fec = rn->info;
2059 if (fec->label == label)
2060 return fec;
2061 }
2062 }
2063
2064 return NULL;
2065}
2066
2067/*
2068 * Inform if specified label is currently bound to a FEC or not.
2069 */
2070int
2071zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label)
2072{
2073 return (zebra_mpls_fec_for_label (zvrf, label) ? 1 : 0);
2074}
2075
2076/*
5aba114a 2077 * Add static FEC to label binding. If there are clients registered for this
a64448ba
DS
2078 * FEC, notify them. If there are labeled routes for this FEC, install the
2079 * label forwarding entry.
5aba114a 2080*/
f31e084c
DS
2081int
2082zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
2083 mpls_label_t in_label)
2084{
2085 struct route_table *table;
2086 zebra_fec_t *fec;
2087 char buf[BUFSIZ];
a64448ba 2088 mpls_label_t old_label;
f31e084c
DS
2089 int ret = 0;
2090
2091 table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
2092 if (!table)
2093 return -1;
2094
2095 if (IS_ZEBRA_DEBUG_MPLS)
2096 prefix2str(p, buf, BUFSIZ);
2097
2098 /* Update existing FEC or create a new one. */
2099 fec = fec_find (table, p);
2100 if (!fec)
2101 {
28d58fd7
VV
2102 fec = fec_add (table, p, in_label, FEC_FLAG_CONFIGURED,
2103 MPLS_INVALID_LABEL_INDEX);
f31e084c
DS
2104 if (!fec)
2105 {
2106 prefix2str(p, buf, BUFSIZ);
2107 zlog_err ("Failed to add FEC %s upon config", buf);
2108 return -1;
2109 }
2110
2111 if (IS_ZEBRA_DEBUG_MPLS)
2112 zlog_debug ("Add fec %s label %u", buf, in_label);
2113 }
2114 else
2115 {
2116 fec->flags |= FEC_FLAG_CONFIGURED;
2117 if (fec->label == in_label)
2118 /* Duplicate config */
2119 return 0;
2120
5aba114a 2121 /* Label change, update clients. */
a64448ba 2122 old_label = fec->label;
f31e084c
DS
2123 if (IS_ZEBRA_DEBUG_MPLS)
2124 zlog_debug ("Update fec %s new label %u", buf, in_label);
2125
2126 fec->label = in_label;
5aba114a 2127 fec_update_clients (fec);
a64448ba
DS
2128
2129 /* Update label forwarding entries appropriately */
2130 ret = fec_change_update_lsp (zvrf, fec, old_label);
f31e084c
DS
2131 }
2132
2133 return ret;
2134}
2135
2136/*
5aba114a
DS
2137 * Remove static FEC to label binding. If there are no clients registered
2138 * for this FEC, delete the FEC; else notify clients
28d58fd7
VV
2139 * Note: Upon delete of static binding, if label index exists for this FEC,
2140 * client may need to be updated with derived label.
f31e084c
DS
2141 */
2142int
2143zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p)
2144{
2145 struct route_table *table;
2146 zebra_fec_t *fec;
a64448ba 2147 mpls_label_t old_label;
f31e084c
DS
2148 char buf[BUFSIZ];
2149
2150 table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
2151 if (!table)
2152 return -1;
2153
2154 fec = fec_find (table, p);
2155 if (!fec)
2156 {
2157 prefix2str(p, buf, BUFSIZ);
2158 zlog_err("Failed to find FEC %s upon delete", buf);
2159 return -1;
2160 }
2161
2162 if (IS_ZEBRA_DEBUG_MPLS)
2163 {
2164 prefix2str(p, buf, BUFSIZ);
28d58fd7
VV
2165 zlog_debug ("Delete fec %s label index %u",
2166 buf, fec->label_index);
f31e084c
DS
2167 }
2168
a64448ba 2169 old_label = fec->label;
5aba114a
DS
2170 fec->flags &= ~FEC_FLAG_CONFIGURED;
2171 fec->label = MPLS_INVALID_LABEL;
2172
2173 /* If no client exists, just delete the FEC. */
2174 if (list_isempty(fec->client_list))
2175 {
2176 fec_del (fec);
2177 return 0;
2178 }
2179
28d58fd7
VV
2180 /* Derive the local label (from label index) or reset it. */
2181 fec_derive_label_from_index (zvrf, fec);
2182
2183 /* If there is a label change, update clients. */
2184 if (fec->label == old_label)
2185 return 0;
5aba114a
DS
2186 fec_update_clients (fec);
2187
a64448ba
DS
2188 /* Update label forwarding entries appropriately */
2189 return fec_change_update_lsp (zvrf, fec, old_label);
f31e084c
DS
2190}
2191
2192/*
2193 * Display MPLS FEC to label binding configuration (VTY command handler).
2194 */
2195int
2196zebra_mpls_write_fec_config (struct vty *vty, struct zebra_vrf *zvrf)
2197{
2198 struct route_node *rn;
2199 int af;
2200 zebra_fec_t *fec;
2201 char buf[BUFSIZ];
2202 int write = 0;
2203
2204 for (af = AFI_IP; af < AFI_MAX; af++)
2205 {
2206 if (zvrf->fec_table[af] == NULL)
2207 continue;
2208
2209 for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
2210 {
2211 if (!rn->info)
2212 continue;
2213
2214 char lstr[BUFSIZ];
2215 fec = rn->info;
2216
2217 if (!(fec->flags & FEC_FLAG_CONFIGURED))
2218 continue;
2219
2220 write = 1;
2221 prefix2str(&rn->p, buf, BUFSIZ);
2222 vty_out(vty, "mpls label bind %s %s%s", buf,
2223 label2str(fec->label, lstr, BUFSIZ), VTY_NEWLINE);
2224 }
2225 }
2226
2227 return write;
2228}
2229
2230/*
2231 * Display MPLS FEC to label binding (VTY command handler).
2232 */
2233void
2234zebra_mpls_print_fec_table (struct vty *vty, struct zebra_vrf *zvrf)
2235{
2236 struct route_node *rn;
2237 int af;
2238
2239 for (af = AFI_IP; af < AFI_MAX; af++)
2240 {
2241 if (zvrf->fec_table[af] == NULL)
2242 continue;
2243
2244 for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
2245 {
2246 if (!rn->info)
2247 continue;
2248 fec_print (rn->info, vty);
2249 }
2250 }
2251}
2252
2253/*
2254 * Display MPLS FEC to label binding for a specific FEC (VTY command handler).
2255 */
2256void
2257zebra_mpls_print_fec (struct vty *vty, struct zebra_vrf *zvrf, struct prefix *p)
2258{
2259 struct route_table *table;
2260 struct route_node *rn;
2261
2262 table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
2263 if (!table)
2264 return;
2265
2266 apply_mask (p);
2267 rn = route_node_lookup(table, p);
2268 if (!rn)
2269 return;
2270
2271 route_unlock_node(rn);
2272 if (!rn->info)
2273 return;
2274
2275 fec_print (rn->info, vty);
2276}
2277
ce549947
RW
2278/*
2279 * Install/uninstall a FEC-To-NHLFE (FTN) binding.
2280 */
2281int
2282mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
88d88a9c
RW
2283 struct prefix *prefix, enum nexthop_types_t gtype,
2284 union g_addr *gate, ifindex_t ifindex, u_int8_t distance,
ce549947
RW
2285 mpls_label_t out_label)
2286{
2287 struct route_table *table;
2288 struct route_node *rn;
2289 struct rib *rib;
2290 struct nexthop *nexthop;
2291
2292 /* Lookup table. */
661512bf 2293 table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf_id (zvrf));
ce549947
RW
2294 if (! table)
2295 return -1;
2296
2297 /* Lookup existing route */
2298 rn = route_node_get (table, prefix);
2299 RNODE_FOREACH_RIB (rn, rib)
2300 {
2301 if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
2302 continue;
2303 if (rib->distance == distance)
2304 break;
2305 }
2306
2307 if (rib == NULL)
2308 return -1;
2309
2310 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
88d88a9c 2311 {
4312ff1c 2312 switch (nexthop->type)
88d88a9c
RW
2313 {
2314 case NEXTHOP_TYPE_IPV4:
2315 case NEXTHOP_TYPE_IPV4_IFINDEX:
4312ff1c
RW
2316 if (gtype != NEXTHOP_TYPE_IPV4 && gtype != NEXTHOP_TYPE_IPV4_IFINDEX)
2317 continue;
ce549947
RW
2318 if (! IPV4_ADDR_SAME (&nexthop->gate.ipv4, &gate->ipv4))
2319 continue;
4312ff1c
RW
2320 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX &&
2321 nexthop->ifindex != ifindex)
ce549947 2322 continue;
88d88a9c
RW
2323 goto found;
2324 case NEXTHOP_TYPE_IPV6:
2325 case NEXTHOP_TYPE_IPV6_IFINDEX:
4312ff1c
RW
2326 if (gtype != NEXTHOP_TYPE_IPV6 && gtype != NEXTHOP_TYPE_IPV6_IFINDEX)
2327 continue;
ce549947
RW
2328 if (! IPV6_ADDR_SAME (&nexthop->gate.ipv6, &gate->ipv6))
2329 continue;
4312ff1c
RW
2330 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX &&
2331 nexthop->ifindex != ifindex)
88d88a9c 2332 continue;
ce549947 2333 goto found;
ce549947
RW
2334 default:
2335 break;
88d88a9c
RW
2336 }
2337 }
ce549947
RW
2338 /* nexthop not found */
2339 return -1;
2340
2341 found:
daca38ae 2342 if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE)
ce549947 2343 nexthop_add_labels (nexthop, type, 1, &out_label);
daca38ae 2344 else if (!add && nexthop->nh_label_type == type)
ce549947 2345 nexthop_del_labels (nexthop);
daca38ae
RW
2346 else
2347 return 0;
ce549947
RW
2348
2349 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
2350 SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
2351 rib_queue_add (rn);
2352
2353 return 0;
2354}
2355
2356/*
2357 * Install/update a NHLFE for an LSP in the forwarding table. This may be
2358 * a new LSP entry or a new NHLFE for an existing in-label or an update of
2359 * the out-label for an existing NHLFE (update case).
2360 */
2361int
2362mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type,
2363 mpls_label_t in_label, mpls_label_t out_label,
2364 enum nexthop_types_t gtype, union g_addr *gate,
a64448ba 2365 ifindex_t ifindex)
ce549947
RW
2366{
2367 struct hash *lsp_table;
2368 zebra_ile_t tmp_ile;
2369 zebra_lsp_t *lsp;
2370 zebra_nhlfe_t *nhlfe;
2371 char buf[BUFSIZ];
2372
2373 /* Lookup table. */
2374 lsp_table = zvrf->lsp_table;
2375 if (!lsp_table)
2376 return -1;
2377
2378 /* If entry is present, exit. */
2379 tmp_ile.in_label = in_label;
2380 lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
2381 if (!lsp)
2382 return -1;
a64448ba 2383 nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
ce549947
RW
2384 if (nhlfe)
2385 {
2386 struct nexthop *nh = nhlfe->nexthop;
2387
2388 assert (nh);
2389 assert (nh->nh_label);
2390
2391 /* Clear deleted flag (in case it was set) */
2392 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
2393 if (nh->nh_label->label[0] == out_label)
2394 /* No change */
2395 return 0;
2396
2397 if (IS_ZEBRA_DEBUG_MPLS)
2398 {
2399 nhlfe2str (nhlfe, buf, BUFSIZ);
2400 zlog_debug ("LSP in-label %u type %d nexthop %s "
2401 "out-label changed to %u (old %u)",
2402 in_label, type, buf,
2403 out_label, nh->nh_label->label[0]);
2404 }
2405
2406 /* Update out label, trigger processing. */
2407 nh->nh_label->label[0] = out_label;
2408 }
2409 else
2410 {
2411 /* Add LSP entry to this nexthop */
a64448ba 2412 nhlfe = nhlfe_add (lsp, type, gtype, gate, ifindex, out_label);
ce549947
RW
2413 if (!nhlfe)
2414 return -1;
2415
2416 if (IS_ZEBRA_DEBUG_MPLS)
2417 {
2418 nhlfe2str (nhlfe, buf, BUFSIZ);
2419 zlog_debug ("Add LSP in-label %u type %d nexthop %s "
2420 "out-label %u", in_label, type, buf, out_label);
2421 }
2422
2423 lsp->addr_family = NHLFE_FAMILY (nhlfe);
2424 }
2425
2426 /* Mark NHLFE, queue LSP for processing. */
2427 SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
2428 if (lsp_processq_add (lsp))
2429 return -1;
2430
2431 return 0;
2432}
2433
2434/*
2435 * Uninstall a particular NHLFE in the forwarding table. If this is
2436 * the only NHLFE, the entire LSP forwarding entry has to be deleted.
2437 */
2438int
2439mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type,
2440 mpls_label_t in_label, enum nexthop_types_t gtype,
a64448ba 2441 union g_addr *gate, ifindex_t ifindex)
ce549947
RW
2442{
2443 struct hash *lsp_table;
2444 zebra_ile_t tmp_ile;
2445 zebra_lsp_t *lsp;
2446 zebra_nhlfe_t *nhlfe;
2447 char buf[BUFSIZ];
2448
2449 /* Lookup table. */
2450 lsp_table = zvrf->lsp_table;
2451 if (!lsp_table)
2452 return -1;
2453
2454 /* If entry is not present, exit. */
2455 tmp_ile.in_label = in_label;
2456 lsp = hash_lookup (lsp_table, &tmp_ile);
2457 if (!lsp)
2458 return 0;
a64448ba 2459 nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
ce549947
RW
2460 if (!nhlfe)
2461 return 0;
2462
2463 if (IS_ZEBRA_DEBUG_MPLS)
2464 {
2465 nhlfe2str (nhlfe, buf, BUFSIZ);
2466 zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
2467 in_label, type, buf, nhlfe->flags);
2468 }
2469
2470 /* Mark NHLFE for delete or directly delete, as appropriate. */
2471 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
2472 {
2473 UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
2474 SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
2475 if (lsp_processq_add (lsp))
2476 return -1;
2477 }
2478 else
2479 {
2480 nhlfe_del (nhlfe);
2481
2482 /* Free LSP entry if no other NHLFEs and not scheduled. */
2483 if (!lsp->nhlfe_list &&
2484 !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
2485 {
2486 if (IS_ZEBRA_DEBUG_MPLS)
2487 zlog_debug ("Free LSP in-label %u flags 0x%x",
2488 lsp->ile.in_label, lsp->flags);
2489
2490 lsp = hash_release(lsp_table, &lsp->ile);
2491 if (lsp)
2492 XFREE(MTYPE_LSP, lsp);
2493 }
2494 }
2495 return 0;
2496}
2497
2498/*
2499 * Uninstall all LDP NHLFEs for a particular LSP forwarding entry.
2500 * If no other NHLFEs exist, the entry would be deleted.
2501 */
2502void
2503mpls_ldp_lsp_uninstall_all (struct hash_backet *backet, void *ctxt)
2504{
2505 zebra_lsp_t *lsp;
2506 struct hash *lsp_table;
2507
2508 lsp = (zebra_lsp_t *) backet->data;
2509 if (!lsp || !lsp->nhlfe_list)
2510 return;
2511
2512 lsp_table = ctxt;
2513 if (!lsp_table)
2514 return;
2515
2516 mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_LDP);
2517}
2518
2519/*
2520 * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family.
2521 */
2522void
2523mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi)
2524{
2525 struct route_table *table;
2526 struct route_node *rn;
2527 struct rib *rib;
2528 struct nexthop *nexthop;
2529 int update;
2530
2531 /* Process routes of interested address-families. */
661512bf 2532 table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf));
ce549947
RW
2533 if (!table)
2534 return;
2535
2536 for (rn = route_top (table); rn; rn = route_next (rn))
2537 {
2538 update = 0;
2539 RNODE_FOREACH_RIB (rn, rib)
2540 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
2541 if (nexthop->nh_label_type == ZEBRA_LSP_LDP)
2542 {
2543 nexthop_del_labels (nexthop);
2544 SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
2545 SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
2546 update = 1;
2547 }
2548
2549 if (update)
2550 rib_queue_add (rn);
2551 }
2552}
2553
1c1cf002 2554#if defined(HAVE_CUMULUS)
7758e3f3 2555/*
2556 * Check that the label values used in LSP creation are consistent. The
2557 * main criteria is that if there is ECMP, the label operation must still
2558 * be consistent - i.e., all paths either do a swap or do PHP. This is due
2559 * to current HW restrictions.
2560 */
2561int
2562zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
2563 mpls_label_t out_label, enum nexthop_types_t gtype,
a64448ba 2564 union g_addr *gate, ifindex_t ifindex)
7758e3f3 2565{
2566 struct hash *slsp_table;
2567 zebra_ile_t tmp_ile;
2568 zebra_slsp_t *slsp;
2569 zebra_snhlfe_t *snhlfe;
2570
2571 /* Lookup table. */
2572 slsp_table = zvrf->slsp_table;
2573 if (!slsp_table)
2574 return 0;
2575
2576 /* If entry is not present, exit. */
2577 tmp_ile.in_label = in_label;
2578 slsp = hash_lookup (slsp_table, &tmp_ile);
2579 if (!slsp)
2580 return 1;
2581
a64448ba 2582 snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
7758e3f3 2583 if (snhlfe)
2584 {
2585 if (snhlfe->out_label == out_label)
2586 return 1;
2587
2588 /* If not only NHLFE, cannot allow label change. */
2589 if (snhlfe != slsp->snhlfe_list ||
2590 snhlfe->next)
2591 return 0;
2592 }
2593 else
2594 {
2595 /* If other NHLFEs exist, label operation must match. */
2596 if (slsp->snhlfe_list)
2597 {
2598 int cur_op, new_op;
2599
2600 cur_op = (slsp->snhlfe_list->out_label == MPLS_IMP_NULL_LABEL);
2601 new_op = (out_label == MPLS_IMP_NULL_LABEL);
2602 if (cur_op != new_op)
2603 return 0;
2604 }
2605 }
2606
2607 /* Label values are good. */
2608 return 1;
2609}
1c1cf002 2610#endif /* HAVE_CUMULUS */
7758e3f3 2611
2612/*
2613 * Add static LSP entry. This may be the first entry for this incoming label
2614 * or an additional nexthop; an existing entry may also have outgoing label
2615 * changed.
2616 * Note: The label operation (swap or PHP) is common for the LSP entry (all
2617 * NHLFEs).
2618 */
2619int
2620zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
2621 mpls_label_t out_label, enum nexthop_types_t gtype,
a64448ba 2622 union g_addr *gate, ifindex_t ifindex)
7758e3f3 2623{
2624 struct hash *slsp_table;
2625 zebra_ile_t tmp_ile;
2626 zebra_slsp_t *slsp;
2627 zebra_snhlfe_t *snhlfe;
2628 char buf[BUFSIZ];
2629
2630 /* Lookup table. */
2631 slsp_table = zvrf->slsp_table;
2632 if (!slsp_table)
2633 return -1;
2634
2635 /* If entry is present, exit. */
2636 tmp_ile.in_label = in_label;
2637 slsp = hash_get (slsp_table, &tmp_ile, slsp_alloc);
2638 if (!slsp)
2639 return -1;
a64448ba 2640 snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
7758e3f3 2641 if (snhlfe)
2642 {
2643 if (snhlfe->out_label == out_label)
2644 /* No change */
2645 return 0;
2646
2647 if (IS_ZEBRA_DEBUG_MPLS)
2648 {
2649 snhlfe2str (snhlfe, buf, BUFSIZ);
2650 zlog_debug ("Upd static LSP in-label %u nexthop %s "
2651 "out-label %u (old %u)",
2652 in_label, buf, out_label, snhlfe->out_label);
2653 }
2654 snhlfe->out_label = out_label;
2655 }
2656 else
2657 {
2658 /* Add static LSP entry to this nexthop */
a64448ba 2659 snhlfe = snhlfe_add (slsp, gtype, gate, ifindex, out_label);
7758e3f3 2660 if (!snhlfe)
2661 return -1;
2662
2663 if (IS_ZEBRA_DEBUG_MPLS)
2664 {
2665 snhlfe2str (snhlfe, buf, BUFSIZ);
2666 zlog_debug ("Add static LSP in-label %u nexthop %s out-label %u",
2667 in_label, buf, out_label);
2668 }
2669 }
2670
40c7bdb0 2671 /* (Re)Install LSP in the main table. */
ce549947 2672 if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype,
a64448ba 2673 gate, ifindex))
40c7bdb0 2674 return -1;
2675
7758e3f3 2676 return 0;
2677}
2678
2679/*
2680 * Delete static LSP entry. This may be the delete of one particular
2681 * NHLFE for this incoming label or the delete of the entire entry (i.e.,
2682 * all NHLFEs).
2683 * NOTE: Delete of the only NHLFE will also end up deleting the entire
2684 * LSP configuration.
2685 */
2686int
2687zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
2688 enum nexthop_types_t gtype, union g_addr *gate,
a64448ba 2689 ifindex_t ifindex)
7758e3f3 2690{
2691 struct hash *slsp_table;
2692 zebra_ile_t tmp_ile;
2693 zebra_slsp_t *slsp;
2694 zebra_snhlfe_t *snhlfe;
2695
2696 /* Lookup table. */
2697 slsp_table = zvrf->slsp_table;
2698 if (!slsp_table)
2699 return -1;
2700
2701 /* If entry is not present, exit. */
2702 tmp_ile.in_label = in_label;
2703 slsp = hash_lookup (slsp_table, &tmp_ile);
2704 if (!slsp)
2705 return 0;
2706
2707 /* Is it delete of entire LSP or a specific NHLFE? */
2708 if (gtype == NEXTHOP_TYPE_BLACKHOLE)
2709 {
2710 if (IS_ZEBRA_DEBUG_MPLS)
2711 zlog_debug ("Del static LSP in-label %u", in_label);
2712
40c7bdb0 2713 /* Uninstall entire LSP from the main table. */
ce549947 2714 mpls_static_lsp_uninstall_all (zvrf, in_label);
40c7bdb0 2715
7758e3f3 2716 /* Delete all static NHLFEs */
2717 snhlfe_del_all (slsp);
2718 }
2719 else
2720 {
2721 /* Find specific NHLFE, exit if not found. */
a64448ba 2722 snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
7758e3f3 2723 if (!snhlfe)
2724 return 0;
2725
2726 if (IS_ZEBRA_DEBUG_MPLS)
2727 {
2728 char buf[BUFSIZ];
2729 snhlfe2str (snhlfe, buf, BUFSIZ);
2730 zlog_debug ("Del static LSP in-label %u nexthop %s",
2731 in_label, buf);
2732 }
2733
40c7bdb0 2734 /* Uninstall LSP from the main table. */
ce549947 2735 mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate,
a64448ba 2736 ifindex);
40c7bdb0 2737
7758e3f3 2738 /* Delete static LSP NHLFE */
2739 snhlfe_del (snhlfe);
2740 }
2741
2742 /* Remove entire static LSP entry if no NHLFE - valid in either case above. */
2743 if (!slsp->snhlfe_list)
2744 {
2745 slsp = hash_release(slsp_table, &tmp_ile);
2746 if (slsp)
2747 XFREE(MTYPE_SLSP, slsp);
2748 }
2749
2750 return 0;
2751}
2752
40c7bdb0 2753/*
2754 * Schedule all MPLS label forwarding entries for processing.
2755 * Called upon changes that may affect one or more of them such as
2756 * interface or nexthop state changes.
2757 */
2758void
2759zebra_mpls_lsp_schedule (struct zebra_vrf *zvrf)
2760{
2761 if (!zvrf)
2762 return;
2763 hash_iterate(zvrf->lsp_table, lsp_schedule, NULL);
2764}
2765
3ab18ff2 2766/*
2767 * Display MPLS label forwarding table for a specific LSP
2768 * (VTY command handler).
2769 */
2770void
b78b820d 2771zebra_mpls_print_lsp (struct vty *vty, struct zebra_vrf *zvrf, mpls_label_t label,
2772 u_char use_json)
3ab18ff2 2773{
2774 struct hash *lsp_table;
2775 zebra_lsp_t *lsp;
2776 zebra_ile_t tmp_ile;
b78b820d 2777 json_object *json = NULL;
3ab18ff2 2778
2779 /* Lookup table. */
2780 lsp_table = zvrf->lsp_table;
2781 if (!lsp_table)
2782 return;
2783
2784 /* If entry is not present, exit. */
2785 tmp_ile.in_label = label;
2786 lsp = hash_lookup (lsp_table, &tmp_ile);
2787 if (!lsp)
2788 return;
2789
b78b820d 2790 if (use_json)
2791 {
2792 json = lsp_json(lsp);
2aac5767 2793 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
b78b820d 2794 json_object_free(json);
2795 }
2796 else
2797 lsp_print (lsp, (void *)vty);
3ab18ff2 2798}
2799
2800/*
2801 * Display MPLS label forwarding table (VTY command handler).
2802 */
2803void
b78b820d 2804zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf,
2805 u_char use_json)
3ab18ff2 2806{
b78b820d 2807 char buf[BUFSIZ];
2808 json_object *json = NULL;
2809 zebra_lsp_t *lsp = NULL;
2810 zebra_nhlfe_t *nhlfe = NULL;
2811 struct nexthop *nexthop = NULL;
2812 struct listnode *node = NULL;
2813 struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp);
2814
2815 if (use_json)
2816 {
2817 json = json_object_new_object();
2818
2819 for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp))
2820 json_object_object_add(json, label2str(lsp->ile.in_label, buf, BUFSIZ),
2821 lsp_json(lsp));
2822
2aac5767 2823 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
b78b820d 2824 json_object_free(json);
2825 }
2826 else
2827 {
2828 vty_out (vty, " Inbound Outbound%s", VTY_NEWLINE);
2829 vty_out (vty, " Label Type Nexthop Label%s", VTY_NEWLINE);
2830 vty_out (vty, "-------- ------- --------------- --------%s", VTY_NEWLINE);
2831
2832 for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp))
2833 {
2834 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next)
2835 {
2836 vty_out (vty, "%8d %7s ", lsp->ile.in_label, nhlfe_type2str(nhlfe->type));
2837 nexthop = nhlfe->nexthop;
2838
2839 switch (nexthop->type)
2840 {
2841 case NEXTHOP_TYPE_IPV4:
88d88a9c 2842 case NEXTHOP_TYPE_IPV4_IFINDEX:
b78b820d 2843 vty_out (vty, "%15s", inet_ntoa (nexthop->gate.ipv4));
2844 break;
2845 case NEXTHOP_TYPE_IPV6:
2846 case NEXTHOP_TYPE_IPV6_IFINDEX:
2847 vty_out (vty, "%15s", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
2848 break;
2849 default:
2850 break;
2851 }
2852
2853 vty_out (vty, " %8d%s", nexthop->nh_label->label[0], VTY_NEWLINE);
2854 }
2855 }
2856
2857 vty_out (vty, "%s", VTY_NEWLINE);
2858 }
2859
58ac32e2 2860 list_delete (lsp_list);
3ab18ff2 2861}
2862
7758e3f3 2863/*
2864 * Display MPLS LSP configuration of all static LSPs (VTY command handler).
2865 */
2866int
2867zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf)
2868{
b78b820d 2869 zebra_slsp_t *slsp;
2870 zebra_snhlfe_t *snhlfe;
2871 struct listnode *node;
b78b820d 2872 struct list *slsp_list = hash_get_sorted_list(zvrf->slsp_table, slsp_cmp);
2873
2874 for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp))
2875 {
2876 for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next)
2877 {
e64f3c32 2878 char buf[INET6_ADDRSTRLEN];
b78b820d 2879 char lstr[30];
e64f3c32 2880
b78b820d 2881 snhlfe2str (snhlfe, buf, BUFSIZ);
e64f3c32
RW
2882 switch (snhlfe->out_label) {
2883 case MPLS_V4_EXP_NULL_LABEL:
2884 case MPLS_V6_EXP_NULL_LABEL:
2885 strlcpy(lstr, "explicit-null", sizeof(lstr));
2886 break;
2887 case MPLS_IMP_NULL_LABEL:
2888 strlcpy(lstr, "implicit-null", sizeof(lstr));
2889 break;
2890 default:
2891 sprintf(lstr, "%u", snhlfe->out_label);
2892 break;
2893 }
2894
b78b820d 2895 vty_out (vty, "mpls lsp %u %s %s%s",
e64f3c32 2896 slsp->ile.in_label, buf, lstr, VTY_NEWLINE);
b78b820d 2897 }
2898 }
2899
58ac32e2 2900 list_delete (slsp_list);
7758e3f3 2901 return (zvrf->slsp_table->count ? 1 : 0);
2902}
2903
1b6d5c7e
VV
2904/*
2905 * Add/update global label block.
2906 */
2907int
2908zebra_mpls_label_block_add (struct zebra_vrf *zvrf, u_int32_t start_label,
2909 u_int32_t end_label)
2910{
2911 zvrf->mpls_srgb.start_label = start_label;
2912 zvrf->mpls_srgb.end_label = end_label;
28d58fd7
VV
2913
2914 /* Evaluate registered FECs to see if any get a label or not. */
2915 fec_evaluate (zvrf, 1);
1b6d5c7e
VV
2916 return 0;
2917}
2918
2919/*
2920 * Delete global label block.
2921 */
2922int
2923zebra_mpls_label_block_del (struct zebra_vrf *zvrf)
2924{
2925 zvrf->mpls_srgb.start_label = 0;
2926 zvrf->mpls_srgb.end_label = 0;
28d58fd7
VV
2927
2928 /* Process registered FECs to clear their local label, if needed. */
2929 fec_evaluate (zvrf, 0);
1b6d5c7e
VV
2930 return 0;
2931}
2932
2933/*
2934 * Display MPLS global label block configuration (VTY command handler).
2935 */
2936int
2937zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *zvrf)
2938{
2939 if (zvrf->mpls_srgb.start_label == 0)
2940 return 0;
2941
2942 vty_out(vty, "mpls label global-block %u %u%s",
2943 zvrf->mpls_srgb.start_label, zvrf->mpls_srgb.end_label,
2944 VTY_NEWLINE);
2945
2946 return 1;
2947}
2948
40c7bdb0 2949/*
2950 * Called upon process exiting, need to delete LSP forwarding
2951 * entries from the kernel.
2952 * NOTE: Currently supported only for default VRF.
2953 */
2954void
2955zebra_mpls_close_tables (struct zebra_vrf *zvrf)
2956{
40c7bdb0 2957 hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL);
58ac32e2
RW
2958 hash_clean(zvrf->lsp_table, NULL);
2959 hash_free(zvrf->lsp_table);
2960 hash_clean(zvrf->slsp_table, NULL);
2961 hash_free(zvrf->slsp_table);
40c7bdb0 2962}
2963
7758e3f3 2964/*
2965 * Allocate MPLS tables for this VRF and do other initialization.
2966 * NOTE: Currently supported only for default VRF.
2967 */
2968void
2969zebra_mpls_init_tables (struct zebra_vrf *zvrf)
2970{
2971 if (!zvrf)
2972 return;
2973 zvrf->slsp_table = hash_create(label_hash, label_cmp);
40c7bdb0 2974 zvrf->lsp_table = hash_create(label_hash, label_cmp);
f31e084c
DS
2975 zvrf->fec_table[AFI_IP] = route_table_init();
2976 zvrf->fec_table[AFI_IP6] = route_table_init();
939fba27 2977 zvrf->mpls_flags = 0;
1b6d5c7e
VV
2978 zvrf->mpls_srgb.start_label = 0;
2979 zvrf->mpls_srgb.end_label = 0;
7758e3f3 2980}
2981
2982/*
2983 * Global MPLS initialization.
2984 */
2985void
2986zebra_mpls_init (void)
2987{
33c32282
DW
2988 mpls_enabled = 0;
2989
fe6c7157
RW
2990 if (mpls_kernel_init () < 0)
2991 {
2992 zlog_warn ("Disabling MPLS support (no kernel support)");
2993 return;
2994 }
2995
33c32282
DW
2996 if (! mpls_processq_init (&zebrad))
2997 mpls_enabled = 1;
7758e3f3 2998}