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