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