]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_mpls.c
zebra: lsp_install() failed due to ZEBRA_FLAG_SELECTED check
[mirror_frr.git] / zebra / zebra_mpls.c
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"
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"
38 #include "lib/json.h"
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
49 DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object")
50 DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object")
51 DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config")
52 DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object")
53 DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object")
54 DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname")
55
56 int mpls_enabled;
57
58 /* Default rtm_table for all clients */
59 extern struct zebra_t zebrad;
60
61 /* static function declarations */
62
63 static void
64 fec_evaluate (struct zebra_vrf *zvrf, int add);
65 static u_int32_t
66 fec_derive_label_from_index (struct zebra_vrf *vrf, zebra_fec_t *fec);
67 static int
68 lsp_install (struct zebra_vrf *zvrf, mpls_label_t label,
69 struct route_node *rn, struct rib *rib);
70 static int
71 lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label);
72 static int
73 fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label);
74 static int
75 fec_send (zebra_fec_t *fec, struct zserv *client);
76 static void
77 fec_update_clients (zebra_fec_t *fec);
78 static void
79 fec_print (zebra_fec_t *fec, struct vty *vty);
80 static zebra_fec_t *
81 fec_find (struct route_table *table, struct prefix *p);
82 static zebra_fec_t *
83 fec_add (struct route_table *table, struct prefix *p, mpls_label_t label,
84 u_int32_t flags, u_int32_t label_index);
85 static int
86 fec_del (zebra_fec_t *fec);
87
88 static unsigned int
89 label_hash (void *p);
90 static int
91 label_cmp (const void *p1, const void *p2);
92 static int
93 nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop);
94 static int
95 nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop);
96 static int
97 nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe);
98
99 static void
100 lsp_select_best_nhlfe (zebra_lsp_t *lsp);
101 static void
102 lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt);
103 static void
104 lsp_schedule (struct hash_backet *backet, void *ctxt);
105 static wq_item_status
106 lsp_process (struct work_queue *wq, void *data);
107 static void
108 lsp_processq_del (struct work_queue *wq, void *data);
109 static void
110 lsp_processq_complete (struct work_queue *wq);
111 static int
112 lsp_processq_add (zebra_lsp_t *lsp);
113 static void *
114 lsp_alloc (void *p);
115
116 static char *
117 nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size);
118 static int
119 nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
120 union g_addr *gate, ifindex_t ifindex);
121 static zebra_nhlfe_t *
122 nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
123 enum nexthop_types_t gtype, union g_addr *gate,
124 ifindex_t ifindex);
125 static zebra_nhlfe_t *
126 nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
127 enum nexthop_types_t gtype, union g_addr *gate,
128 ifindex_t ifindex, mpls_label_t out_label);
129 static int
130 nhlfe_del (zebra_nhlfe_t *snhlfe);
131 static void
132 nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label);
133 static int
134 mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
135 enum lsp_types_t type);
136 static int
137 mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label);
138 static void
139 nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty);
140 static void
141 lsp_print (zebra_lsp_t *lsp, void *ctxt);
142 static void *
143 slsp_alloc (void *p);
144 static int
145 snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
146 union g_addr *gate, ifindex_t ifindex);
147 static zebra_snhlfe_t *
148 snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
149 union g_addr *gate, ifindex_t ifindex);
150 static zebra_snhlfe_t *
151 snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
152 union g_addr *gate, ifindex_t ifindex, mpls_label_t out_label);
153 static int
154 snhlfe_del (zebra_snhlfe_t *snhlfe);
155 static int
156 snhlfe_del_all (zebra_slsp_t *slsp);
157 static char *
158 snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size);
159 static void
160 mpls_processq_init (struct zebra_t *zebra);
161
162
163
164
165 /* Static functions */
166
167 /*
168 * Install label forwarding entry based on labeled-route entry.
169 */
170 static int
171 lsp_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
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 */
287 static int
288 lsp_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
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 */
360 static void
361 fec_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 {
371 if (zvrf->fec_table[af] == NULL)
372 continue;
373
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 */
420 static u_int32_t
421 fec_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
436 /*
437 * There is a change for this FEC. Install or uninstall label forwarding
438 * entries, as appropriate.
439 */
440 static int
441 fec_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
483 /*
484 * Inform about FEC to a registered client.
485 */
486 static int
487 fec_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 */
511 static void
512 fec_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
526 /*
527 * Print a FEC-label binding entry.
528 */
529 static void
530 fec_print (zebra_fec_t *fec, struct vty *vty)
531 {
532 struct route_node *rn;
533 struct listnode *node;
534 struct zserv *client;
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));
541 if (fec->label_index != MPLS_INVALID_LABEL_INDEX)
542 vty_out(vty, ", Label Index: %u", fec->label_index);
543 vty_out(vty, "%s", VTY_NEWLINE);
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 }
552 }
553
554 /*
555 * Locate FEC-label binding that matches with passed info.
556 */
557 static zebra_fec_t *
558 fec_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 /*
572 * Add a FEC. This may be upon a client registering for a binding
573 * or when a binding is configured.
574 */
575 static zebra_fec_t *
576 fec_add (struct route_table *table, struct prefix *p,
577 mpls_label_t label, u_int32_t flags, u_int32_t label_index)
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;
600 fec->client_list = list_new();
601 }
602 else
603 route_unlock_node (rn); /* for the route_node_get */
604
605 fec->label_index = label_index;
606 fec->flags = flags;
607
608 return fec;
609 }
610
611 /*
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.
615 */
616 static int
617 fec_del (zebra_fec_t *fec)
618 {
619 list_free (fec->client_list);
620 fec->rn->info = NULL;
621 route_unlock_node (fec->rn);
622 XFREE (MTYPE_FEC, fec);
623 return 0;
624 }
625
626 /*
627 * Hash function for label.
628 */
629 static unsigned int
630 label_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 */
640 static int
641 label_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
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 */
654 static int
655 nhlfe_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;
661 struct nexthop *match_nh;
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 {
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 }
695 }
696
697 return 0;
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 */
706 static int
707 nhlfe_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 */
752 static int
753 nhlfe_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:
766 case NEXTHOP_TYPE_IPV4_IFINDEX:
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 {
783 ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT);
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 */
811 static void
812 lsp_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 */
898 static void
899 lsp_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 */
912 static void
913 lsp_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 */
925 static wq_item_status
926 lsp_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 */
977 static void
978 lsp_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 */
1024 static void
1025 lsp_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 */
1033 static int
1034 lsp_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 */
1048 static void *
1049 lsp_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 */
1066 static char *
1067 nhlfe2str (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:
1076 case NEXTHOP_TYPE_IPV4_IFINDEX:
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 */
1092 static int
1093 nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
1094 union g_addr *gate, ifindex_t ifindex)
1095 {
1096 struct nexthop *nhop;
1097 int cmp = 1;
1098
1099 nhop = nhlfe->nexthop;
1100 if (!nhop)
1101 return 1;
1102
1103 if (nhop->type != gtype)
1104 return 1;
1105
1106 switch (nhop->type)
1107 {
1108 case NEXTHOP_TYPE_IPV4:
1109 case NEXTHOP_TYPE_IPV4_IFINDEX:
1110 cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4),
1111 sizeof(struct in_addr));
1112 if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1113 cmp = !(nhop->ifindex == ifindex);
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 */
1133 static zebra_nhlfe_t *
1134 nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
1135 enum nexthop_types_t gtype, union g_addr *gate,
1136 ifindex_t ifindex)
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;
1147 if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifindex))
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 */
1158 static zebra_nhlfe_t *
1159 nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
1160 enum nexthop_types_t gtype, union g_addr *gate,
1161 ifindex_t ifindex, mpls_label_t out_label)
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 }
1183 nexthop_add_labels (nexthop, lsp_type, 1, &out_label);
1184
1185 nexthop->type = gtype;
1186 switch (nexthop->type)
1187 {
1188 case NEXTHOP_TYPE_IPV4:
1189 case NEXTHOP_TYPE_IPV4_IFINDEX:
1190 nexthop->gate.ipv4 = gate->ipv4;
1191 if (ifindex)
1192 nexthop->ifindex = ifindex;
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 */
1219 static int
1220 nhlfe_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
1243 if (nhlfe == lsp->best_nhlfe)
1244 lsp->best_nhlfe = NULL;
1245
1246 XFREE (MTYPE_NHLFE, nhlfe);
1247
1248 return 0;
1249 }
1250
1251 /*
1252 * Update label for NHLFE entry.
1253 */
1254 static void
1255 nhlfe_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
1260 static int
1261 mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
1262 enum lsp_types_t type)
1263 {
1264 zebra_nhlfe_t *nhlfe, *nhlfe_next;
1265 int schedule_lsp = 0;
1266 char buf[BUFSIZ];
1267
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 */
1274 if (nhlfe->type != type)
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",
1281 lsp->ile.in_label, type, buf, nhlfe->flags);
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
1317 /*
1318 * Uninstall all static NHLFEs for a particular LSP forwarding entry.
1319 * If no other NHLFEs exist, the entry would be deleted.
1320 */
1321 static int
1322 mpls_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
1342 static json_object *
1343 nhlfe_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:
1360 case NEXTHOP_TYPE_IPV4_IFINDEX:
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)
1370 json_object_string_add(json_nhlfe, "interface", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT));
1371 break;
1372 default:
1373 break;
1374 }
1375 return json_nhlfe;
1376 }
1377
1378 /*
1379 * Print the NHLFE for a LSP forwarding entry.
1380 */
1381 static void
1382 nhlfe_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:
1398 case NEXTHOP_TYPE_IPV4_IFINDEX:
1399 vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
1400 if (nexthop->ifindex)
1401 vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT));
1402 break;
1403 case NEXTHOP_TYPE_IPV6:
1404 case NEXTHOP_TYPE_IPV6_IFINDEX:
1405 vty_out (vty, " via %s",
1406 inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
1407 if (nexthop->ifindex)
1408 vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT));
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 */
1421 static void
1422 lsp_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 /*
1439 * JSON objects for an LSP forwarding entry.
1440 */
1441 static json_object *
1442 lsp_json (zebra_lsp_t *lsp)
1443 {
1444 zebra_nhlfe_t *nhlfe = NULL;
1445 json_object *json = json_object_new_object();
1446 json_object *json_nhlfe_list = json_object_new_array();
1447
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");
1452
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 */
1462 static struct list *
1463 hash_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;
1476 }
1477
1478 /*
1479 * Compare two LSPs based on their label values.
1480 */
1481 static int
1482 lsp_cmp (zebra_lsp_t *lsp1, zebra_lsp_t *lsp2)
1483 {
1484 if (lsp1->ile.in_label < lsp2->ile.in_label)
1485 return -1;
1486
1487 if (lsp1->ile.in_label > lsp2->ile.in_label)
1488 return 1;
1489
1490 return 0;
1491 }
1492
1493 /*
1494 * Callback to allocate static LSP.
1495 */
1496 static void *
1497 slsp_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
1507 /*
1508 * Compare two static LSPs based on their label values.
1509 */
1510 static int
1511 slsp_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
1522 /*
1523 * Check if static NHLFE matches with search info passed.
1524 */
1525 static int
1526 snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
1527 union g_addr *gate, ifindex_t ifindex)
1528 {
1529 int cmp = 1;
1530
1531 if (snhlfe->gtype != gtype)
1532 return 1;
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 */
1557 static zebra_snhlfe_t *
1558 snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
1559 union g_addr *gate, ifindex_t ifindex)
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 {
1568 if (!snhlfe_match (snhlfe, gtype, gate, ifindex))
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 */
1580 static zebra_snhlfe_t *
1581 snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
1582 union g_addr *gate, ifindex_t ifindex,
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 */
1621 static int
1622 snhlfe_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 */
1651 static int
1652 snhlfe_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 */
1671 static char *
1672 snhlfe2str (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)
1684 strcat (buf, ifindex2ifname (snhlfe->ifindex, VRF_DEFAULT));
1685 break;
1686 default:
1687 break;
1688 }
1689
1690 return buf;
1691 }
1692
1693 /*
1694 * Initialize work queue for processing changed LSPs.
1695 */
1696 static void
1697 mpls_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
1714
1715
1716 /* Public functions */
1717
1718 /*
1719 * String to label conversion, labels separated by '/'.
1720 */
1721 int
1722 mpls_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 {
1731 mpls_label_t label;
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 */
1763 char *
1764 mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
1765 char *buf, int len, int pretty)
1766 {
1767 char *buf_ptr = buf;
1768 buf[0] = '\0';
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 }
1788 return buf;
1789 }
1790
1791 /*
1792 * Install dynamic LSP entry.
1793 */
1794 int
1795 zebra_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 */
1824 int
1825 zebra_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
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.
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.
1850 */
1851 int
1852 zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p,
1853 u_int32_t label_index, struct zserv *client)
1854 {
1855 struct route_table *table;
1856 zebra_fec_t *fec;
1857 char buf[BUFSIZ];
1858 int new_client;
1859 int label_change = 0;
1860 u_int32_t old_label;
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 {
1873 fec = fec_add (table, p, MPLS_INVALID_LABEL, 0, label_index);
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 }
1881
1882 old_label = MPLS_INVALID_LABEL;
1883 new_client = 1;
1884 }
1885 else
1886 {
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)
1890 /* Duplicate register */
1891 return 0;
1892
1893 /* Save current label, update label index */
1894 old_label = fec->label;
1895 fec->label_index = label_index;
1896 }
1897
1898 if (new_client)
1899 listnode_add (fec->client_list, client);
1900
1901 if (IS_ZEBRA_DEBUG_MPLS)
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;
1916
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)
1926 {
1927 if (IS_ZEBRA_DEBUG_MPLS)
1928 zlog_debug ("Update client label %u", fec->label);
1929 fec_send (fec, client);
1930 }
1931
1932 if (new_client || label_change)
1933 return fec_change_update_lsp (zvrf, fec, old_label);
1934
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 */
1943 int
1944 zebra_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
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 }
1984
1985 return 0;
1986 }
1987
1988 /*
1989 * Cleanup any FECs registered by this client.
1990 */
1991 int
1992 zebra_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
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 */
2035 zebra_fec_t *
2036 zebra_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 */
2063 int
2064 zebra_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 /*
2070 * Add static FEC to label binding. If there are clients registered for this
2071 * FEC, notify them. If there are labeled routes for this FEC, install the
2072 * label forwarding entry.
2073 */
2074 int
2075 zebra_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];
2081 mpls_label_t old_label;
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 {
2095 fec = fec_add (table, p, in_label, FEC_FLAG_CONFIGURED,
2096 MPLS_INVALID_LABEL_INDEX);
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
2114 /* Label change, update clients. */
2115 old_label = fec->label;
2116 if (IS_ZEBRA_DEBUG_MPLS)
2117 zlog_debug ("Update fec %s new label %u", buf, in_label);
2118
2119 fec->label = in_label;
2120 fec_update_clients (fec);
2121
2122 /* Update label forwarding entries appropriately */
2123 ret = fec_change_update_lsp (zvrf, fec, old_label);
2124 }
2125
2126 return ret;
2127 }
2128
2129 /*
2130 * Remove static FEC to label binding. If there are no clients registered
2131 * for this FEC, delete the FEC; else notify clients
2132 * Note: Upon delete of static binding, if label index exists for this FEC,
2133 * client may need to be updated with derived label.
2134 */
2135 int
2136 zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p)
2137 {
2138 struct route_table *table;
2139 zebra_fec_t *fec;
2140 mpls_label_t old_label;
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);
2158 zlog_debug ("Delete fec %s label index %u",
2159 buf, fec->label_index);
2160 }
2161
2162 old_label = fec->label;
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
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;
2179 fec_update_clients (fec);
2180
2181 /* Update label forwarding entries appropriately */
2182 return fec_change_update_lsp (zvrf, fec, old_label);
2183 }
2184
2185 /*
2186 * Display MPLS FEC to label binding configuration (VTY command handler).
2187 */
2188 int
2189 zebra_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 */
2226 void
2227 zebra_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 */
2249 void
2250 zebra_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
2271 /*
2272 * Install/uninstall a FEC-To-NHLFE (FTN) binding.
2273 */
2274 int
2275 mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
2276 struct prefix *prefix, enum nexthop_types_t gtype,
2277 union g_addr *gate, ifindex_t ifindex, u_int8_t distance,
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. */
2286 table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf_id (zvrf));
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)
2304 {
2305 switch (nexthop->type)
2306 {
2307 case NEXTHOP_TYPE_IPV4:
2308 case NEXTHOP_TYPE_IPV4_IFINDEX:
2309 if (gtype != NEXTHOP_TYPE_IPV4 && gtype != NEXTHOP_TYPE_IPV4_IFINDEX)
2310 continue;
2311 if (! IPV4_ADDR_SAME (&nexthop->gate.ipv4, &gate->ipv4))
2312 continue;
2313 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX &&
2314 nexthop->ifindex != ifindex)
2315 continue;
2316 goto found;
2317 case NEXTHOP_TYPE_IPV6:
2318 case NEXTHOP_TYPE_IPV6_IFINDEX:
2319 if (gtype != NEXTHOP_TYPE_IPV6 && gtype != NEXTHOP_TYPE_IPV6_IFINDEX)
2320 continue;
2321 if (! IPV6_ADDR_SAME (&nexthop->gate.ipv6, &gate->ipv6))
2322 continue;
2323 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX &&
2324 nexthop->ifindex != ifindex)
2325 continue;
2326 goto found;
2327 default:
2328 break;
2329 }
2330 }
2331 /* nexthop not found */
2332 return -1;
2333
2334 found:
2335 if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE)
2336 nexthop_add_labels (nexthop, type, 1, &out_label);
2337 else if (!add && nexthop->nh_label_type == type)
2338 nexthop_del_labels (nexthop);
2339 else
2340 return 0;
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 */
2354 int
2355 mpls_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,
2358 ifindex_t ifindex)
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;
2376 nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
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 */
2405 nhlfe = nhlfe_add (lsp, type, gtype, gate, ifindex, out_label);
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 */
2431 int
2432 mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type,
2433 mpls_label_t in_label, enum nexthop_types_t gtype,
2434 union g_addr *gate, ifindex_t ifindex)
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;
2452 nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
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 */
2495 void
2496 mpls_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 */
2515 void
2516 mpls_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. */
2525 table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf));
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
2547 #if defined(HAVE_CUMULUS)
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 */
2554 int
2555 zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
2556 mpls_label_t out_label, enum nexthop_types_t gtype,
2557 union g_addr *gate, ifindex_t ifindex)
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
2575 snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
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 }
2603 #endif /* HAVE_CUMULUS */
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 */
2612 int
2613 zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
2614 mpls_label_t out_label, enum nexthop_types_t gtype,
2615 union g_addr *gate, ifindex_t ifindex)
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;
2633 snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
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 */
2652 snhlfe = snhlfe_add (slsp, gtype, gate, ifindex, out_label);
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
2664 /* (Re)Install LSP in the main table. */
2665 if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype,
2666 gate, ifindex))
2667 return -1;
2668
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 */
2679 int
2680 zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
2681 enum nexthop_types_t gtype, union g_addr *gate,
2682 ifindex_t ifindex)
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
2706 /* Uninstall entire LSP from the main table. */
2707 mpls_static_lsp_uninstall_all (zvrf, in_label);
2708
2709 /* Delete all static NHLFEs */
2710 snhlfe_del_all (slsp);
2711 }
2712 else
2713 {
2714 /* Find specific NHLFE, exit if not found. */
2715 snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
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
2727 /* Uninstall LSP from the main table. */
2728 mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate,
2729 ifindex);
2730
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
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 */
2751 void
2752 zebra_mpls_lsp_schedule (struct zebra_vrf *zvrf)
2753 {
2754 if (!zvrf)
2755 return;
2756 hash_iterate(zvrf->lsp_table, lsp_schedule, NULL);
2757 }
2758
2759 /*
2760 * Display MPLS label forwarding table for a specific LSP
2761 * (VTY command handler).
2762 */
2763 void
2764 zebra_mpls_print_lsp (struct vty *vty, struct zebra_vrf *zvrf, mpls_label_t label,
2765 u_char use_json)
2766 {
2767 struct hash *lsp_table;
2768 zebra_lsp_t *lsp;
2769 zebra_ile_t tmp_ile;
2770 json_object *json = NULL;
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
2783 if (use_json)
2784 {
2785 json = lsp_json(lsp);
2786 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
2787 json_object_free(json);
2788 }
2789 else
2790 lsp_print (lsp, (void *)vty);
2791 }
2792
2793 /*
2794 * Display MPLS label forwarding table (VTY command handler).
2795 */
2796 void
2797 zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf,
2798 u_char use_json)
2799 {
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
2816 vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE);
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:
2835 case NEXTHOP_TYPE_IPV4_IFINDEX:
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
2853 list_delete (lsp_list);
2854 }
2855
2856 /*
2857 * Display MPLS LSP configuration of all static LSPs (VTY command handler).
2858 */
2859 int
2860 zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf)
2861 {
2862 zebra_slsp_t *slsp;
2863 zebra_snhlfe_t *snhlfe;
2864 struct listnode *node;
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 {
2871 char buf[INET6_ADDRSTRLEN];
2872 char lstr[30];
2873
2874 snhlfe2str (snhlfe, buf, BUFSIZ);
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
2888 vty_out (vty, "mpls lsp %u %s %s%s",
2889 slsp->ile.in_label, buf, lstr, VTY_NEWLINE);
2890 }
2891 }
2892
2893 list_delete (slsp_list);
2894 return (zvrf->slsp_table->count ? 1 : 0);
2895 }
2896
2897 /*
2898 * Add/update global label block.
2899 */
2900 int
2901 zebra_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;
2906
2907 /* Evaluate registered FECs to see if any get a label or not. */
2908 fec_evaluate (zvrf, 1);
2909 return 0;
2910 }
2911
2912 /*
2913 * Delete global label block.
2914 */
2915 int
2916 zebra_mpls_label_block_del (struct zebra_vrf *zvrf)
2917 {
2918 zvrf->mpls_srgb.start_label = 0;
2919 zvrf->mpls_srgb.end_label = 0;
2920
2921 /* Process registered FECs to clear their local label, if needed. */
2922 fec_evaluate (zvrf, 0);
2923 return 0;
2924 }
2925
2926 /*
2927 * Display MPLS global label block configuration (VTY command handler).
2928 */
2929 int
2930 zebra_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
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 */
2947 void
2948 zebra_mpls_close_tables (struct zebra_vrf *zvrf)
2949 {
2950 hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL);
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);
2955 }
2956
2957 /*
2958 * Allocate MPLS tables for this VRF and do other initialization.
2959 * NOTE: Currently supported only for default VRF.
2960 */
2961 void
2962 zebra_mpls_init_tables (struct zebra_vrf *zvrf)
2963 {
2964 if (!zvrf)
2965 return;
2966 zvrf->slsp_table = hash_create(label_hash, label_cmp);
2967 zvrf->lsp_table = hash_create(label_hash, label_cmp);
2968 zvrf->fec_table[AFI_IP] = route_table_init();
2969 zvrf->fec_table[AFI_IP6] = route_table_init();
2970 zvrf->mpls_flags = 0;
2971 zvrf->mpls_srgb.start_label = 0;
2972 zvrf->mpls_srgb.end_label = 0;
2973 }
2974
2975 /*
2976 * Global MPLS initialization.
2977 */
2978 void
2979 zebra_mpls_init (void)
2980 {
2981 if (mpls_kernel_init () < 0)
2982 {
2983 zlog_warn ("Disabling MPLS support (no kernel support)");
2984 return;
2985 }
2986
2987 mpls_enabled = 1;
2988 mpls_processq_init (&zebrad);
2989 }