]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_sr.c
OSPFD: Add Experimental Segment Routing support
[mirror_frr.git] / ospfd / ospf_sr.c
1 /*
2 * This is an implementation of Segment Routing
3 * as per draft-ietf-ospf-segment-routing-extensions-24
4 *
5 * Module name: Segment Routing
6 *
7 * Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
8 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
9 *
10 * Copyright (C) 2016 - 2017 Orange Labs http://www.orange.com
11 *
12 * This file is part of FRR.
13 *
14 * FRR is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2, or (at your option) any
17 * later version.
18 *
19 * FRR is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with FRR; see the file COPYING. If not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 */
29
30 #include <math.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <zebra.h>
34
35 #include "command.h"
36 #include "hash.h"
37 #include "if.h"
38 #include "if.h"
39 #include "jhash.h"
40 #include "libospf.h" /* for ospf interface types */
41 #include "linklist.h"
42 #include "log.h"
43 #include "memory.h"
44 #include "monotime.h"
45 #include "network.h"
46 #include "prefix.h"
47 #include "sockunion.h" /* for inet_aton() */
48 #include "stream.h"
49 #include "table.h"
50 #include "thread.h"
51 #include "vty.h"
52 #include "zclient.h"
53
54 #include "ospfd/ospfd.h"
55 #include "ospfd/ospf_interface.h"
56 #include "ospfd/ospf_ism.h"
57 #include "ospfd/ospf_asbr.h"
58 #include "ospfd/ospf_lsa.h"
59 #include "ospfd/ospf_lsdb.h"
60 #include "ospfd/ospf_neighbor.h"
61 #include "ospfd/ospf_nsm.h"
62 #include "ospfd/ospf_flood.h"
63 #include "ospfd/ospf_packet.h"
64 #include "ospfd/ospf_spf.h"
65 #include "ospfd/ospf_dump.h"
66 #include "ospfd/ospf_route.h"
67 #include "ospfd/ospf_ase.h"
68 #include "ospfd/ospf_sr.h"
69 #include "ospfd/ospf_ri.h"
70 #include "ospfd/ospf_ext.h"
71 #include "ospfd/ospf_zebra.h"
72
73 /*
74 * Global variable to manage Segment Routing on this node.
75 * Note that all parameter values are stored in network byte order.
76 */
77 static struct ospf_sr_db OspfSR;
78 static void ospf_sr_register_vty(void);
79 static inline void del_sid_nhlfe(struct sr_nhlfe nhlfe);
80
81 /*
82 * Segment Routing Data Base functions
83 */
84
85 /* Hash function for Segment Routing entry */
86 static unsigned int sr_hash(void *p)
87 {
88 const struct in_addr *rid = p;
89
90 return (jhash_1word(rid->s_addr, 0));
91 }
92
93 /* Compare 2 Router ID hash entries based on SR Node */
94 static int sr_cmp(const void *p1, const void *p2)
95 {
96 const struct sr_node *srn = p1;
97 const struct in_addr *rid = p2;
98
99 return (IPV4_ADDR_SAME(&srn->adv_router, rid));
100 }
101
102 /* Functions to free memory space, segment routing */
103 static void del_sr_info(void *val)
104 {
105 XFREE(MTYPE_OSPF_SR_PARAMS, val);
106 return;
107 }
108
109 /* Allocate new Segment Routine node */
110 static struct sr_node *sr_node_new(struct in_addr *rid)
111 {
112
113 if (rid == NULL)
114 return NULL;
115
116 struct sr_node *new;
117
118 /* Allocate Segment Routing node memory */
119 new = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_node));
120
121 /* Sanity Check */
122 if (new == NULL) {
123 zlog_err(
124 "SR (ospf_sr_node_new):"
125 "Abort! can't create new SR node");
126 return NULL;
127 }
128
129 /* Default Algorithm, SRGB and MSD */
130 for (int i = 0; i < ALGORITHM_COUNT; i++)
131 OspfSR.algo[i] = SR_ALGORITHM_UNSET;
132
133 new->srgb.range_size = 0;
134 new->srgb.lower_bound = 0;
135 new->msd = 0;
136
137 /* Create Link, Prefix and Range TLVs list */
138 new->ext_link = list_new();
139 new->ext_prefix = list_new();
140 new->ext_link->del = del_sr_info;
141 new->ext_prefix->del = del_sr_info;
142
143 /* Check if list are correctly created */
144 if (new->ext_link == NULL || new->ext_prefix == NULL) {
145 list_delete_original(new->ext_link);
146 list_delete_original(new->ext_prefix);
147 XFREE(MTYPE_OSPF_SR_PARAMS, new);
148 return NULL;
149 }
150
151 IPV4_ADDR_COPY(&new->adv_router, rid);
152 new->neighbor = NULL;
153 new->instance = 0;
154
155 if (IS_DEBUG_OSPF_SR)
156 zlog_debug(" |- Created new SR node for %s",
157 inet_ntoa(new->adv_router));
158 return new;
159 }
160
161 /* Delete Segment Routing node */
162 static void sr_node_del(struct sr_node *srn)
163 {
164 struct listnode *node;
165 struct sr_link *srl;
166 struct sr_prefix *srp;
167
168 /* Sanity Check */
169 if (srn == NULL)
170 return;
171
172 /* Clean Extended Link */
173 if (listcount(srn->ext_link) != 0) {
174 for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
175 listnode_delete(srn->ext_link, srl);
176 XFREE(MTYPE_OSPF_SR_PARAMS, srl);
177 }
178 }
179 list_delete_original(srn->ext_link);
180
181 /* Clean Prefix List */
182 if (listcount(srn->ext_prefix) != 0) {
183 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
184 listnode_delete(srn->ext_prefix, srp);
185 XFREE(MTYPE_OSPF_SR_PARAMS, srp);
186 }
187 }
188 list_delete_original(srn->ext_prefix);
189
190 XFREE(MTYPE_OSPF_SR_PARAMS, srn);
191 }
192
193 /* Get SR Node for a given nexthop */
194 static struct sr_node *get_sr_node_by_nexthop(struct ospf *ospf,
195 struct in_addr nexthop)
196 {
197 struct ospf_interface *oi = NULL;
198 struct ospf_neighbor *nbr = NULL;
199 struct listnode *node;
200 struct route_node *rn;
201 struct sr_node *srn;
202
203 /* Sanity check */
204 if (OspfSR.neighbors == NULL)
205 return NULL;
206
207 if (IS_DEBUG_OSPF_SR)
208 zlog_debug(" |- Search SR-Node for nexthop %s",
209 inet_ntoa(nexthop));
210
211 /* First, search neighbor Router ID for this nexthop */
212 for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
213 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
214 if ((nbr = rn->info))
215 break;
216
217 if (nbr == NULL)
218 return NULL;
219
220 if (IS_DEBUG_OSPF_SR)
221 zlog_debug(" |- Found nexthop Router ID %s",
222 inet_ntoa(nbr->router_id));
223 /* Then, search SR Node */
224 srn = (struct sr_node *)hash_lookup(OspfSR.neighbors, &nbr->router_id);
225
226 return srn;
227 }
228
229 /*
230 * Segment Routing Initialization functions
231 */
232
233 /* Segment Routing starter function */
234 static int ospf_sr_start(struct ospf *ospf)
235 {
236 struct route_node *rn;
237 struct ospf_lsa *lsa;
238 struct sr_node *srn;
239 int rc = 0;
240
241 if (IS_DEBUG_OSPF_SR)
242 zlog_debug("SR (ospf_sr_start): Start Segment Routing");
243
244 /* Initialize self SR Node */
245 srn = hash_get(OspfSR.neighbors, (void *)&(ospf->router_id),
246 (void *)sr_node_new);
247
248 /* Sanity Check */
249 if (srn == NULL)
250 return rc;
251
252 /* Complete & Store self SR Node */
253 srn->srgb.range_size = OspfSR.srgb.range_size;
254 srn->srgb.lower_bound = OspfSR.srgb.lower_bound;
255 srn->algo[0] = OspfSR.algo[0];
256 srn->msd = OspfSR.msd;
257 OspfSR.self = srn;
258
259 if (IS_DEBUG_OSPF_EVENT)
260 zlog_debug("SR (ospf_sr_start): Update SR-DB from LSDB");
261
262 /* Start by looking to Router Info & Extended LSA in lsdb */
263 if ((ospf != NULL) && (ospf->backbone != NULL)) {
264 LSDB_LOOP(OPAQUE_AREA_LSDB(ospf->backbone), rn, lsa)
265 {
266 if (IS_LSA_MAXAGE(lsa) || IS_LSA_SELF(lsa))
267 continue;
268 int lsa_id =
269 GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
270 switch (lsa_id) {
271 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
272 ospf_sr_ri_lsa_update(lsa);
273 break;
274 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
275 ospf_sr_ext_prefix_lsa_update(lsa);
276 break;
277 case OPAQUE_TYPE_EXTENDED_LINK_LSA:
278 ospf_sr_ext_link_lsa_update(lsa);
279 break;
280 default:
281 break;
282 }
283 }
284 }
285
286 rc = 1;
287 return rc;
288 }
289
290 /* Remove an SR Node in the SRDB */
291 static void ospf_sr_node_nhlfe_del(struct hash_backet *backet, void *args)
292 {
293 struct sr_node *srn = (struct sr_node *)backet->data;
294 struct listnode *node;
295 struct sr_prefix *srp;
296 struct sr_link *srl;
297
298 /* Sanity Check */
299 if (srn == NULL)
300 return;
301
302 if (IS_DEBUG_OSPF_SR)
303 zlog_debug(" |- Delete all Prefix for SR Node %s",
304 inet_ntoa(srn->adv_router));
305
306 /* Remove Extended Prefix */
307 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp))
308 del_sid_nhlfe(srp->nhlfe);
309
310 if (IS_DEBUG_OSPF_SR)
311 zlog_debug(" |- Delete all Link for SR Node %s",
312 inet_ntoa(srn->adv_router));
313
314 /* Remove Extended Link */
315 for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
316 /* Remove NHLFE entries for this Link */
317 del_sid_nhlfe(srl->nhlfe[0]);
318 del_sid_nhlfe(srl->nhlfe[1]);
319 }
320
321 if (IS_DEBUG_OSPF_SR)
322 zlog_debug(" |- Remove SR Node %s",
323 inet_ntoa(srn->adv_router));
324 }
325
326 /* Stop Segment Routing */
327 static void ospf_sr_stop(void)
328 {
329
330 if (IS_DEBUG_OSPF_SR)
331 zlog_debug("SR (ospf_sr_stop): Stop Segment Routing");
332
333 /* Start by removing all Prefix and Link for each SR Node */
334 hash_iterate(OspfSR.neighbors, (void (*)(struct hash_backet *,
335 void *))ospf_sr_node_nhlfe_del,
336 NULL);
337
338 /* Finish by cleaning the hash table */
339 hash_clean(OspfSR.neighbors, (void *)sr_node_del);
340 }
341
342 /*
343 * Segment Routing initialize function
344 *
345 * @param - nothing
346 *
347 * @return 0 if OK, -1 otherwise
348 */
349 int ospf_sr_init(void)
350 {
351 int rc = -1;
352
353 zlog_info("SR (ospf_sr_init): Initialize SR Data Base");
354
355 memset(&OspfSR, 0, sizeof(struct ospf_sr_db));
356 OspfSR.enabled = false;
357 /* Only AREA flooding is supported in this release */
358 OspfSR.scope = OSPF_OPAQUE_AREA_LSA;
359
360 /* Initialize SRGB, Algorithms and MSD TLVs */
361 /* Only Algorithm SPF is supported */
362 OspfSR.algo[0] = SR_ALGORITHM_SPF;
363 for (int i = 1; i < ALGORITHM_COUNT; i++)
364 OspfSR.algo[i] = SR_ALGORITHM_UNSET;
365
366 OspfSR.srgb.range_size = MPLS_DEFAULT_MAX_SRGB_SIZE;
367 OspfSR.srgb.lower_bound = MPLS_DEFAULT_MIN_SRGB_LABEL;
368 OspfSR.msd = MPLS_MAX_LABELS;
369
370 /* Initialize Hash table for neighbor SR nodes */
371 OspfSR.neighbors = hash_create(sr_hash, sr_cmp, "OSPF_SR");
372 if (OspfSR.neighbors == NULL)
373 return rc;
374
375 /* Initialize Route Table for prefix */
376 OspfSR.prefix = route_table_init();
377 if (OspfSR.prefix == NULL)
378 return rc;
379
380 /* Register Segment Routing VTY command */
381 ospf_sr_register_vty();
382
383 rc = 0;
384 return rc;
385 }
386
387 /*
388 * Segment Routing termination function
389 *
390 * @param - nothing
391 *
392 * @return - nothing
393 */
394 void ospf_sr_term(void)
395 {
396
397 /* Stop Segment Routing */
398 ospf_sr_stop();
399
400 /* Clear SR Node Table */
401 if (OspfSR.neighbors)
402 hash_free(OspfSR.neighbors);
403
404 /* Clear Prefix Table */
405 if (OspfSR.prefix)
406 route_table_finish(OspfSR.prefix);
407
408 OspfSR.enabled = false;
409 }
410
411 /*
412 * Following functions are used to manipulate the
413 * Next Hop Label Forwarding entry (NHLFE)
414 */
415
416 /* Compute label from index */
417 static mpls_label_t index2label(u_int32_t index, struct sr_srgb srgb)
418 {
419 mpls_label_t label;
420
421 label = srgb.lower_bound + index;
422 if (label > (srgb.lower_bound + srgb.range_size))
423 return MPLS_INVALID_LABEL;
424 else
425 return label;
426 }
427
428 /* Get neighbor full structure from address */
429 static struct ospf_neighbor *get_neighbor_by_addr(struct ospf *top,
430 struct in_addr addr)
431 {
432 struct ospf_neighbor *nbr;
433 struct ospf_interface *oi;
434 struct listnode *node;
435 struct route_node *rn;
436
437 /* Sanity Check */
438 if (top == NULL)
439 return NULL;
440
441 for (ALL_LIST_ELEMENTS_RO(top->oiflist, node, oi))
442 for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
443 if ((nbr = rn->info))
444 if (IPV4_ADDR_SAME(&nbr->address.u.prefix4,
445 &addr)
446 || IPV4_ADDR_SAME(&nbr->router_id, &addr)) {
447 route_unlock_node(rn);
448 return nbr;
449 }
450
451 return NULL;
452 }
453
454 /* Get OSPF Path from address */
455 static struct ospf_path *get_nexthop_by_addr(struct ospf *top,
456 struct prefix_ipv4 p)
457 {
458 struct ospf_route * or ;
459 struct ospf_path *path;
460 struct listnode *node;
461 struct route_node *rn;
462
463 /* Sanity Check */
464 if ((top == NULL) && (top->new_table))
465 return NULL;
466
467 if (IS_DEBUG_OSPF_SR)
468 zlog_debug(" |- Search Nexthop for prefix %s/%d",
469 inet_ntoa(p.prefix), p.prefixlen);
470
471 rn = route_node_lookup(top->new_table, (struct prefix *)&p);
472
473 /* Check if we found an OSPF route. May be NULL if SPF has not
474 * yet populate routing table for this prefix. */
475 if (rn == NULL)
476 return NULL;
477
478 route_unlock_node(rn);
479
480 if ((or = rn->info) == NULL)
481 return NULL;
482
483 /* Then search path from this route */
484 for (ALL_LIST_ELEMENTS_RO(or->paths, node, path))
485 if (path->nexthop.s_addr != INADDR_ANY || path->ifindex != 0)
486 return path;
487
488 return NULL;
489 }
490
491 /* Compute NHLFE entry for Extended Link */
492 static int compute_link_nhlfe(struct sr_link *srl)
493 {
494 struct ospf *top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
495 struct ospf_neighbor *nh;
496 int rc = 0;
497
498 if (IS_DEBUG_OSPF_SR)
499 zlog_debug(" |- Compute NHLFE for link %s/%d",
500 inet_ntoa(srl->nhlfe[0].prefv4.prefix),
501 srl->nhlfe[0].prefv4.prefixlen);
502
503 /* First determine the OSPF Neighbor */
504 nh = get_neighbor_by_addr(top, srl->nhlfe[0].nexthop);
505
506 /* Neighbor could be not found when OSPF Adjacency just fire up
507 * because SPF don't yet populate routing table. This NHLFE will
508 * be fixed later when SR SPF schedule will be called.
509 */
510 if (nh == NULL)
511 return rc;
512
513 if (IS_DEBUG_OSPF_SR)
514 zlog_debug(" |- Found nexthop NHLFE %s",
515 inet_ntoa(nh->router_id));
516
517 /* Set ifindex for this neighbor */
518 srl->nhlfe[0].ifindex = nh->oi->ifp->ifindex;
519 srl->nhlfe[1].ifindex = nh->oi->ifp->ifindex;
520
521 /* Set Input & Output Label */
522 if (CHECK_FLAG(srl->flags[0], EXT_SUBTLV_LINK_ADJ_SID_VFLG))
523 srl->nhlfe[0].label_in = srl->sid[0];
524 else
525 srl->nhlfe[0].label_in =
526 index2label(srl->sid[0], srl->srn->srgb);
527 if (CHECK_FLAG(srl->flags[1], EXT_SUBTLV_LINK_ADJ_SID_VFLG))
528 srl->nhlfe[1].label_in = srl->sid[1];
529 else
530 srl->nhlfe[1].label_in =
531 index2label(srl->sid[1], srl->srn->srgb);
532
533 srl->nhlfe[0].label_out = MPLS_IMP_NULL_LABEL;
534 srl->nhlfe[1].label_out = MPLS_IMP_NULL_LABEL;
535
536 rc = 1;
537 return rc;
538 }
539
540 /*
541 * Compute NHLFE entry for Extended Prefix
542 *
543 * @param srp - Segment Routing Prefix
544 *
545 * @return -1 if next hop is not found, 0 if nexthop has not changed
546 * and 1 if success
547 */
548 static int compute_prefix_nhlfe(struct sr_prefix *srp)
549 {
550 struct ospf *top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
551 struct ospf_path *nh = NULL;
552 struct sr_node *srnext;
553 int rc = -1;
554
555 if (IS_DEBUG_OSPF_SR)
556 zlog_debug(" |- Compute NHLFE for prefix %s/%d",
557 inet_ntoa(srp->nhlfe.prefv4.prefix),
558 srp->nhlfe.prefv4.prefixlen);
559
560 /* First determine the nexthop */
561 nh = get_nexthop_by_addr(top, srp->nhlfe.prefv4);
562
563 /* Nexthop could be not found when OSPF Adjacency just fire up
564 * because SPF don't yet populate routing table. This NHLFE will
565 * be fixed later when SR SPF schedule will be called.
566 */
567 if (nh == NULL)
568 return rc;
569
570 /* Check if NextHop has changed when call after running a new SPF */
571 if (IPV4_ADDR_SAME(&nh->nexthop, &srp->nhlfe.nexthop)
572 && (nh->ifindex == srp->nhlfe.ifindex))
573 return 0;
574
575 if (IS_DEBUG_OSPF_SR)
576 zlog_debug(" |- Found new next hop for this NHLFE: %s",
577 inet_ntoa(nh->nexthop));
578
579 /* Get SR-Node for this nexthop */
580 srnext = get_sr_node_by_nexthop(top, nh->nexthop);
581 /* and store this information for later SRGB update */
582 srnext->neighbor = OspfSR.self;
583 if (IPV4_ADDR_SAME(&srnext->adv_router, &srp->adv_router))
584 srp->nexthop = NULL;
585 else
586 srp->nexthop = srnext;
587
588 /*
589 * SR Node could be known, but SRGB could be not initialize
590 * This is due to the fact that Extended Link / Prefix could
591 * be received before corresponding Router Information LSA
592 */
593 if ((srnext == NULL) || (srnext->srgb.lower_bound == 0)
594 || (srnext->srgb.range_size == 0))
595 return rc;
596
597 if (IS_DEBUG_OSPF_SR)
598 zlog_debug(" |- Found SRGB %d/%d for next hop SR-Node %s",
599 srnext->srgb.range_size, srnext->srgb.lower_bound,
600 inet_ntoa(srnext->adv_router));
601
602 /* Set ip addr & ifindex for this neighbor */
603 IPV4_ADDR_COPY(&srp->nhlfe.nexthop, &nh->nexthop);
604 srp->nhlfe.ifindex = nh->ifindex;
605
606 /* Compute Input Label with self SRGB */
607 srp->nhlfe.label_in = index2label(srp->sid, OspfSR.srgb);
608 /* and Output Label with Next hop SR Node SRGB or Implicit Null label
609 * if next hop is the destination and request PHP */
610 if ((srp->nexthop == NULL)
611 && (!CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)))
612 srp->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
613 else if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_VFLG))
614 srp->nhlfe.label_out = srp->sid;
615 else
616 srp->nhlfe.label_out = index2label(srp->sid, srnext->srgb);
617
618 if (IS_DEBUG_OSPF_SR)
619 zlog_debug(" |- Computed new labels in: %d out: %d",
620 srp->nhlfe.label_in, srp->nhlfe.label_out);
621
622 rc = 1;
623 return rc;
624 }
625
626 /* Send MPLS Label entry to Zebra for installation or deletion */
627 static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe)
628 {
629 struct stream *s;
630
631 /* Reset stream. */
632 s = zclient->obuf;
633 stream_reset(s);
634
635 zclient_create_header(s, cmd, VRF_DEFAULT);
636 stream_putc(s, ZEBRA_LSP_SR);
637 /* OSPF Segment Routing currently support only IPv4 */
638 stream_putl(s, nhlfe.prefv4.family);
639 stream_put_in_addr(s, &nhlfe.prefv4.prefix);
640 stream_putc(s, nhlfe.prefv4.prefixlen);
641 stream_put_in_addr(s, &nhlfe.nexthop);
642 stream_putl(s, nhlfe.ifindex);
643 stream_putc(s, OSPF_SR_PRIORITY_DEFAULT);
644 stream_putl(s, nhlfe.label_in);
645 stream_putl(s, nhlfe.label_out);
646
647 /* Put length at the first point of the stream. */
648 stream_putw_at(s, 0, stream_get_endp(s));
649
650 if (IS_DEBUG_OSPF_SR)
651 zlog_debug(" |- %s LSP %d/%d for %s/%d via %d",
652 cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",
653 nhlfe.label_in, nhlfe.label_out,
654 inet_ntoa(nhlfe.prefv4.prefix),
655 nhlfe.prefv4.prefixlen, nhlfe.ifindex);
656
657 return (zclient_send_message(zclient));
658 }
659
660 /* Request zebra to install/remove FEC in FIB */
661 static int ospf_zebra_send_mpls_ftn(int cmd, struct sr_nhlfe nhlfe)
662 {
663 struct zapi_route api;
664 struct zapi_nexthop *api_nh;
665
666 /* Support only IPv4 */
667 if (nhlfe.prefv4.family != AF_INET)
668 return -1;
669
670 memset(&api, 0, sizeof(api));
671 api.vrf_id = VRF_DEFAULT;
672 api.type = ZEBRA_ROUTE_OSPF_SR;
673 api.safi = SAFI_UNICAST;
674 memcpy(&api.prefix, &nhlfe.prefv4, sizeof(struct prefix_ipv4));
675
676 if (cmd == ZEBRA_ROUTE_ADD) {
677 /* Metric value. */
678 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
679 api.metric = OSPF_SR_DEFAULT_METRIC;
680 /* Nexthop */
681 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
682 api_nh = &api.nexthops[0];
683 IPV4_ADDR_COPY(&api_nh->gate.ipv4, &nhlfe.nexthop);
684 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
685 api_nh->ifindex = nhlfe.ifindex;
686 /* MPLS labels */
687 SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
688 api_nh->labels[0] = nhlfe.label_out;
689 api_nh->label_num = 1;
690 api.nexthop_num = 1;
691 }
692
693 if (IS_DEBUG_OSPF_SR)
694 zlog_debug(" |- %s FEC %d for %s/%d via %d",
695 cmd == ZEBRA_ROUTE_ADD ? "Add" : "Delete",
696 nhlfe.label_out, inet_ntoa(nhlfe.prefv4.prefix),
697 nhlfe.prefv4.prefixlen, nhlfe.ifindex);
698
699 return (zclient_route_send(cmd, zclient, &api));
700
701 return -1;
702 }
703
704 /* Add new NHLFE entry for SID */
705 static inline void add_sid_nhlfe(struct sr_nhlfe nhlfe)
706 {
707 if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0)) {
708 ospf_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, nhlfe);
709 if (nhlfe.label_out != MPLS_IMP_NULL_LABEL)
710 ospf_zebra_send_mpls_ftn(ZEBRA_ROUTE_ADD, nhlfe);
711 }
712 }
713
714 /* Remove NHLFE entry for SID */
715 static inline void del_sid_nhlfe(struct sr_nhlfe nhlfe)
716 {
717 if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0)) {
718 ospf_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, nhlfe);
719 if (nhlfe.label_out != MPLS_IMP_NULL_LABEL)
720 ospf_zebra_send_mpls_ftn(ZEBRA_ROUTE_DELETE, nhlfe);
721 }
722 }
723
724 /* Update NHLFE entry for SID */
725 static inline void update_sid_nhlfe(struct sr_nhlfe n1, struct sr_nhlfe n2)
726 {
727
728 del_sid_nhlfe(n1);
729 add_sid_nhlfe(n2);
730 }
731
732 /*
733 * Functions to parse and get Extended Link / Prefix
734 * TLVs and SubTLVs
735 */
736
737 /* Extended Link SubTLVs Getter */
738 static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh)
739 {
740
741 struct sr_link *srl;
742 struct ext_tlv_link *link = (struct ext_tlv_link *)tlvh;
743 struct ext_subtlv_adj_sid *adj_sid;
744 struct ext_subtlv_lan_adj_sid *lan_sid;
745 struct ext_subtlv_rmt_itf_addr *rmt_itf;
746
747 struct tlv_header *sub_tlvh;
748 u_int16_t length = 0, sum = 0, i = 0;
749
750 srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link));
751
752 if (srl == NULL)
753 return NULL;
754
755 /* Initialize TLV browsing */
756 length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE;
757 sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
758 + EXT_TLV_LINK_SIZE);
759 for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
760 switch (ntohs(sub_tlvh->type)) {
761 case EXT_SUBTLV_ADJ_SID:
762 adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh;
763 srl->type = ADJ_SID;
764 i = CHECK_FLAG(adj_sid->flags,
765 EXT_SUBTLV_LINK_ADJ_SID_BFLG)
766 ? 1
767 : 0;
768 srl->flags[i] = adj_sid->flags;
769 if (CHECK_FLAG(adj_sid->flags,
770 EXT_SUBTLV_LINK_ADJ_SID_VFLG))
771 srl->sid[i] = GET_LABEL(ntohl(adj_sid->value));
772 else
773 srl->sid[i] = ntohl(adj_sid->value);
774 IPV4_ADDR_COPY(&srl->nhlfe[i].nexthop, &link->link_id);
775 break;
776 case EXT_SUBTLV_LAN_ADJ_SID:
777 lan_sid = (struct ext_subtlv_lan_adj_sid *)sub_tlvh;
778 srl->type = LAN_ADJ_SID;
779 i = CHECK_FLAG(lan_sid->flags,
780 EXT_SUBTLV_LINK_ADJ_SID_BFLG)
781 ? 1
782 : 0;
783 srl->flags[i] = lan_sid->flags;
784 if (CHECK_FLAG(lan_sid->flags,
785 EXT_SUBTLV_LINK_ADJ_SID_VFLG))
786 srl->sid[i] = GET_LABEL(ntohl(lan_sid->value));
787 else
788 srl->sid[i] = ntohl(lan_sid->value);
789 IPV4_ADDR_COPY(&srl->nhlfe[i].nexthop,
790 &lan_sid->neighbor_id);
791 break;
792 case EXT_SUBTLV_RMT_ITF_ADDR:
793 rmt_itf = (struct ext_subtlv_rmt_itf_addr *)sub_tlvh;
794 IPV4_ADDR_COPY(&srl->nhlfe[0].nexthop, &rmt_itf->value);
795 IPV4_ADDR_COPY(&srl->nhlfe[1].nexthop, &rmt_itf->value);
796 break;
797 default:
798 break;
799 }
800 sum += TLV_SIZE(sub_tlvh);
801 }
802
803 IPV4_ADDR_COPY(&srl->nhlfe[0].prefv4.prefix, &link->link_data);
804 srl->nhlfe[0].prefv4.prefixlen = IPV4_MAX_PREFIXLEN;
805 srl->nhlfe[0].prefv4.family = AF_INET;
806 apply_mask_ipv4(&srl->nhlfe[0].prefv4);
807 IPV4_ADDR_COPY(&srl->nhlfe[1].prefv4.prefix, &link->link_data);
808 srl->nhlfe[1].prefv4.prefixlen = IPV4_MAX_PREFIXLEN;
809 srl->nhlfe[1].prefv4.family = AF_INET;
810 apply_mask_ipv4(&srl->nhlfe[1].prefv4);
811
812 if (IS_DEBUG_OSPF_SR) {
813 zlog_debug(" |- Found primary Adj/Lan Sid %d for %s/%d",
814 srl->sid[0], inet_ntoa(srl->nhlfe[0].prefv4.prefix),
815 srl->nhlfe[0].prefv4.prefixlen);
816 zlog_debug(" |- Found backup Adj/Lan Sid %d for %s/%d",
817 srl->sid[1], inet_ntoa(srl->nhlfe[1].prefv4.prefix),
818 srl->nhlfe[1].prefv4.prefixlen);
819 }
820
821 return srl;
822 }
823
824 /* Extended Prefix SubTLVs Getter */
825 static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh)
826 {
827
828 struct sr_prefix *srp;
829 struct ext_tlv_prefix *pref = (struct ext_tlv_prefix *)tlvh;
830 struct ext_subtlv_prefix_sid *psid;
831
832 struct tlv_header *sub_tlvh;
833 u_int16_t length = 0, sum = 0;
834
835 srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
836
837 if (srp == NULL)
838 return NULL;
839
840 /* Initialize TLV browsing */
841 length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE;
842 sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
843 + EXT_TLV_PREFIX_SIZE);
844 for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
845 switch (ntohs(sub_tlvh->type)) {
846 case EXT_SUBTLV_PREFIX_SID:
847 psid = (struct ext_subtlv_prefix_sid *)sub_tlvh;
848 if (psid->algorithm != SR_ALGORITHM_SPF) {
849 zlog_err(
850 "SR (get_ext_prefix_sid): "
851 "Unsupported Algorithm");
852 XFREE(MTYPE_OSPF_SR_PARAMS, srp);
853 return NULL;
854 }
855 srp->type = PREF_SID;
856 srp->flags = psid->flags;
857 if (CHECK_FLAG(psid->flags, EXT_SUBTLV_PREFIX_SID_VFLG))
858 srp->sid = GET_LABEL(ntohl(psid->value));
859 else
860 srp->sid = ntohl(psid->value);
861 IPV4_ADDR_COPY(&srp->nhlfe.prefv4.prefix,
862 &pref->address);
863 srp->nhlfe.prefv4.prefixlen = pref->pref_length;
864 srp->nhlfe.prefv4.family = AF_INET;
865 apply_mask_ipv4(&srp->nhlfe.prefv4);
866 break;
867 default:
868 break;
869 }
870 sum += TLV_SIZE(sub_tlvh);
871 }
872
873 if (IS_DEBUG_OSPF_SR)
874 zlog_debug(" |- Found SID %d for prefix %s/%d", srp->sid,
875 inet_ntoa(srp->nhlfe.prefv4.prefix),
876 srp->nhlfe.prefv4.prefixlen);
877 return srp;
878 }
879
880 /*
881 * Functions to manipulate Segment Routing Link & Prefix structures
882 */
883
884 /* Compare two Segment Link: return 0 if equal, 1 otherwise */
885 static inline int sr_link_cmp(struct sr_link *srl1, struct sr_link *srl2)
886 {
887 if ((srl1->sid[0] == srl2->sid[0]) && (srl1->sid[1] == srl2->sid[1])
888 && (srl1->type == srl2->type) && (srl1->flags[0] == srl2->flags[0])
889 && (srl1->flags[1] == srl2->flags[1]))
890 return 0;
891 else
892 return 1;
893 }
894
895 /* Compare two Segment Prefix: return 0 if equal, 1 otherwise */
896 static inline int sr_prefix_cmp(struct sr_prefix *srp1, struct sr_prefix *srp2)
897 {
898 if ((srp1->sid == srp2->sid) && (srp1->flags == srp2->flags))
899 return 0;
900 else
901 return 1;
902 }
903
904 /* Update Segment Link of given Segment Routing Node */
905 static void update_ext_link_sid(struct sr_node *srn, struct sr_link *srl,
906 u_char lsa_flags)
907 {
908 struct listnode *node;
909 struct sr_link *lk;
910 bool found = false;
911
912 /* Sanity check */
913 if ((srn == NULL) || (srl == NULL))
914 return;
915
916 if (IS_DEBUG_OSPF_SR)
917 zlog_debug(" |- Process Extended Link Adj/Lan-SID");
918
919 /* Process only Local Adj/Lan_Adj SID coming from LSA SELF */
920 if (!CHECK_FLAG(srl->flags[0], EXT_SUBTLV_LINK_ADJ_SID_LFLG)
921 || !CHECK_FLAG(srl->flags[1], EXT_SUBTLV_LINK_ADJ_SID_LFLG)
922 || !CHECK_FLAG(lsa_flags, OSPF_LSA_SELF))
923 return;
924
925 /* Search for existing Segment Link */
926 for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, lk))
927 if (lk->instance == srl->instance) {
928 found = true;
929 break;
930 }
931
932 if (IS_DEBUG_OSPF_SR)
933 zlog_debug(" |- %s SR Link 8.0.0.%d for SR node %s",
934 found ? "Update" : "Add",
935 GET_OPAQUE_ID(srl->instance),
936 inet_ntoa(srn->adv_router));
937
938 /* if not found, add new Segment Link and install NHLFE */
939 if (!found) {
940 /* Complete SR-Link and add it to SR-Node list */
941 srl->srn = srn;
942 IPV4_ADDR_COPY(&srl->adv_router, &srn->adv_router);
943 listnode_add(srn->ext_link, srl);
944 /* Try to set MPLS table */
945 if (compute_link_nhlfe(srl)) {
946 add_sid_nhlfe(srl->nhlfe[0]);
947 add_sid_nhlfe(srl->nhlfe[1]);
948 }
949 } else {
950 if (sr_link_cmp(lk, srl)) {
951 if (compute_link_nhlfe(srl)) {
952 update_sid_nhlfe(lk->nhlfe[0], srl->nhlfe[0]);
953 update_sid_nhlfe(lk->nhlfe[1], srl->nhlfe[1]);
954 /* Replace Segment List */
955 listnode_delete(srn->ext_link, lk);
956 XFREE(MTYPE_OSPF_SR_PARAMS, lk);
957 srl->srn = srn;
958 IPV4_ADDR_COPY(&srl->adv_router,
959 &srn->adv_router);
960 listnode_add(srn->ext_link, srl);
961 } else {
962 XFREE(MTYPE_OSPF_SR_PARAMS, srl);
963 }
964 } else {
965 /* This is just an LSA refresh.
966 * Stop processing and free SR Link */
967 XFREE(MTYPE_OSPF_SR_PARAMS, srl);
968 }
969 }
970 }
971
972 /* Update Segment Prefix of given Segment Routing Node */
973 static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp)
974 {
975
976 struct listnode *node;
977 struct sr_prefix *pref;
978 bool found = false;
979
980 /* Sanity check */
981 if (srn == NULL || srp == NULL)
982 return;
983
984 if (IS_DEBUG_OSPF_SR)
985 zlog_debug(" |- Process Extended Prefix SID %d", srp->sid);
986
987 /* Process only Global Prefix SID */
988 if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_LFLG))
989 return;
990
991 /* Search for existing Segment Prefix */
992 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, pref))
993 if (pref->instance == srp->instance) {
994 found = true;
995 break;
996 }
997
998 if (IS_DEBUG_OSPF_SR)
999 zlog_debug(" |- %s SR LSA ID 7.0.0.%d for SR node %s",
1000 found ? "Update" : "Add",
1001 GET_OPAQUE_ID(srp->instance),
1002 inet_ntoa(srn->adv_router));
1003
1004 /* if not found, add new Segment Prefix and install NHLFE */
1005 if (!found) {
1006 /* Complete SR-Prefix and add it to SR-Node list */
1007 srp->srn = srn;
1008 IPV4_ADDR_COPY(&srp->adv_router, &srn->adv_router);
1009 listnode_add(srn->ext_prefix, srp);
1010 /* Try to set MPLS table */
1011 if (compute_prefix_nhlfe(srp) == 1) {
1012 add_sid_nhlfe(srp->nhlfe);
1013 }
1014 } else {
1015 if (sr_prefix_cmp(pref, srp)) {
1016 if (compute_prefix_nhlfe(srp) == 1) {
1017 update_sid_nhlfe(pref->nhlfe, srp->nhlfe);
1018 /* Replace Segment Prefix */
1019 listnode_delete(srn->ext_prefix, pref);
1020 XFREE(MTYPE_OSPF_SR_PARAMS, pref);
1021 srp->srn = srn;
1022 IPV4_ADDR_COPY(&srp->adv_router,
1023 &srn->adv_router);
1024 listnode_add(srn->ext_prefix, srp);
1025 } else {
1026 /* New NHLFE was not found.
1027 * Just free the SR Prefix */
1028 XFREE(MTYPE_OSPF_SR_PARAMS, srp);
1029 }
1030 } else {
1031 /* This is just an LSA refresh.
1032 * Stop processing and free SR Prefix */
1033 XFREE(MTYPE_OSPF_SR_PARAMS, srp);
1034 }
1035 }
1036 }
1037
1038 /*
1039 * When change the FRR Self SRGB, update the NHLFE Input Label
1040 * for all Extended Prefix with SID index through hash_iterate()
1041 */
1042 static void update_in_nhlfe(struct hash_backet *backet, void *args)
1043 {
1044 struct listnode *node;
1045 struct sr_node *srn = (struct sr_node *)backet->data;
1046 struct sr_prefix *srp;
1047 struct sr_nhlfe new;
1048
1049 /* Skip Self Node */
1050 if (srn == OspfSR.self)
1051 return;
1052
1053 /* Process Every Extended Prefix for this SR-Node */
1054 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
1055 /* Process only SID Index */
1056 if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_VFLG))
1057 continue;
1058 /* Compute new NHLFE */
1059 memcpy(&new, &srp->nhlfe, sizeof(struct sr_nhlfe));
1060 new.label_in = index2label(srp->sid, OspfSR.srgb);
1061 /* Update MPLS LFIB */
1062 update_sid_nhlfe(srp->nhlfe, new);
1063 /* Finally update Input Label */
1064 srp->nhlfe.label_in = new.label_in;
1065 }
1066 }
1067
1068 /*
1069 * When SRGB has changed, update NHLFE Output Label for all Extended Prefix
1070 * with SID index which use the given SR-Node as nexthop though hash_iterate()
1071 */
1072 static void update_out_nhlfe(struct hash_backet *backet, void *args)
1073 {
1074 struct listnode *node;
1075 struct sr_node *srn = (struct sr_node *)backet->data;
1076 struct sr_node *srnext = (struct sr_node *)args;
1077 struct sr_prefix *srp;
1078 struct sr_nhlfe new;
1079
1080 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
1081 /* Process only SID Index for next hop without PHP */
1082 if ((srp->nexthop == NULL)
1083 && (!CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)))
1084 continue;
1085 memcpy(&new, &srp->nhlfe, sizeof(struct sr_nhlfe));
1086 new.label_out = index2label(srp->sid, srnext->srgb);
1087 update_sid_nhlfe(srp->nhlfe, new);
1088 srp->nhlfe.label_out = new.label_out;
1089 }
1090 }
1091
1092 /*
1093 * Following functions are call when new Segment Routing LSA are received
1094 * - Router Information: ospf_sr_ri_lsa_update() & ospf_sr_ri_lsa_delete()
1095 * - Extended Link: ospf_sr_ext_link_update() & ospf_sr_ext_link_delete()
1096 * - Extended Prefix: ospf_ext_prefix_update() & ospf_sr_ext_prefix_delete()
1097 */
1098
1099 /* Update Segment Routing from Router Information LSA */
1100 void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
1101 {
1102 struct sr_node *srn;
1103 struct tlv_header *tlvh;
1104 struct lsa_header *lsah = (struct lsa_header *)lsa->data;
1105 struct ri_sr_tlv_sid_label_range *ri_srgb;
1106 struct ri_sr_tlv_sr_algorithm *algo;
1107 struct sr_srgb srgb;
1108 u_int16_t length = 0, sum = 0;
1109
1110 if (IS_DEBUG_OSPF_SR)
1111 zlog_debug(
1112 "SR (ospf_sr_ri_lsa_update): Process Router "
1113 "Information LSA 4.0.0.%d from %s",
1114 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1115 inet_ntoa(lsah->adv_router));
1116
1117 /* Sanity check */
1118 if (IS_LSA_SELF(lsa))
1119 return;
1120
1121 if (OspfSR.neighbors == NULL) {
1122 zlog_err(
1123 "SR (ospf_sr_ri_lsa_update): Abort! no valid "
1124 "SR DataBase");
1125 return;
1126 }
1127
1128 /* Get SR Node in hash table from Router ID */
1129 srn = hash_get(OspfSR.neighbors, (void *)&(lsah->adv_router),
1130 (void *)sr_node_new);
1131
1132 /* Sanity check */
1133 if (srn == NULL) {
1134 zlog_err(
1135 "SR (ospf_sr_ri_lsa_update): Abort! can't create "
1136 "SR node in hash table");
1137 return;
1138 }
1139
1140 if ((srn->instance != 0) && (srn->instance != ntohl(lsah->id.s_addr))) {
1141 zlog_err(
1142 "SR (ospf_sr_ri_lsa_update): Abort! Wrong "
1143 "LSA ID 4.0.0.%d for SR node %s/%d",
1144 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1145 inet_ntoa(lsah->adv_router), srn->instance);
1146 return;
1147 }
1148
1149 /* Collect Router Information Sub TLVs */
1150 /* Initialize TLV browsing */
1151 length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
1152 srgb.range_size = 0;
1153 srgb.lower_bound = 0;
1154
1155 for (tlvh = TLV_HDR_TOP(lsah); sum < length;
1156 tlvh = TLV_HDR_NEXT(tlvh)) {
1157 switch (ntohs(tlvh->type)) {
1158 case RI_SR_TLV_SR_ALGORITHM:
1159 algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
1160 int i;
1161 for (i = 0; i < ntohs(algo->header.length); i++)
1162 srn->algo[i] = algo->value[0];
1163 for (; i < ALGORITHM_COUNT; i++)
1164 srn->algo[i] = SR_ALGORITHM_UNSET;
1165 sum += TLV_SIZE(tlvh);
1166 break;
1167 case RI_SR_TLV_SID_LABEL_RANGE:
1168 ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh;
1169 srgb.range_size = GET_RANGE_SIZE(ntohl(ri_srgb->size));
1170 srgb.lower_bound =
1171 GET_LABEL(ntohl(ri_srgb->lower.value));
1172 sum += TLV_SIZE(tlvh);
1173 break;
1174 case RI_SR_TLV_NODE_MSD:
1175 srn->msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value;
1176 sum += TLV_SIZE(tlvh);
1177 break;
1178 default:
1179 sum += TLV_SIZE(tlvh);
1180 break;
1181 }
1182 }
1183
1184 /* Check that we collect mandatory parameters */
1185 if (srn->algo[0] == SR_ALGORITHM_UNSET || srgb.range_size == 0
1186 || srgb.lower_bound == 0) {
1187 zlog_warn(
1188 "SR (ospf_sr_ri_lsa_update): Missing "
1189 "mandatory parameters. Abort!");
1190 hash_release(OspfSR.neighbors, &(srn->adv_router));
1191 XFREE(MTYPE_OSPF_SR_PARAMS, srn);
1192 return;
1193 }
1194
1195 /* Check if it is a new SR Node or not */
1196 if (srn->instance == 0) {
1197 /* update LSA ID */
1198 srn->instance = ntohl(lsah->id.s_addr);
1199 /* Copy SRGB */
1200 srn->srgb.range_size = srgb.range_size;
1201 srn->srgb.lower_bound = srgb.lower_bound;
1202 }
1203
1204 /* Check if SRGB has changed */
1205 if ((srn->srgb.range_size != srgb.range_size)
1206 || (srn->srgb.lower_bound != srgb.lower_bound)) {
1207 srn->srgb.range_size = srgb.range_size;
1208 srn->srgb.lower_bound = srgb.lower_bound;
1209 /* Update NHLFE if it is a neighbor SR node */
1210 if (srn->neighbor == OspfSR.self)
1211 hash_iterate(OspfSR.neighbors,
1212 (void (*)(struct hash_backet *,
1213 void *))update_out_nhlfe,
1214 (void *)srn);
1215 }
1216
1217 return;
1218 }
1219
1220 /*
1221 * Delete SR Node entry in hash table information corresponding to an expired
1222 * Router Information LSA
1223 */
1224 void ospf_sr_ri_lsa_delete(struct ospf_lsa *lsa)
1225 {
1226 struct sr_node *srn;
1227 struct lsa_header *lsah = (struct lsa_header *)lsa->data;
1228
1229 if (IS_DEBUG_OSPF_SR)
1230 zlog_debug(
1231 "SR (ospf_sr_ri_lsa_delete): Remove SR node %s "
1232 "from lsa_id 4.0.0.%d",
1233 inet_ntoa(lsah->adv_router),
1234 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)));
1235
1236 /* Sanity check */
1237 if (OspfSR.neighbors == NULL) {
1238 zlog_err(
1239 "SR (ospf_sr_ri_lsa_delete): Abort! no valid "
1240 "SR Data Base");
1241 return;
1242 }
1243
1244 /* Release Router ID entry in SRDB hash table */
1245 srn = hash_release(OspfSR.neighbors, &(lsah->adv_router));
1246
1247 /* Sanity check */
1248 if (srn == NULL) {
1249 zlog_err(
1250 "SR (ospf_sr_ri_lsa_delete): Abort! no entry in SRDB "
1251 "for SR Node %s",
1252 inet_ntoa(lsah->adv_router));
1253 return;
1254 }
1255
1256 if ((srn->instance != 0) && (srn->instance != ntohl(lsah->id.s_addr))) {
1257 zlog_err(
1258 "SR (ospf_sr_ri_lsa_delete): Abort! Wrong "
1259 "LSA ID 4.0.0.%d for SR node %s",
1260 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1261 inet_ntoa(lsah->adv_router));
1262 return;
1263 }
1264
1265 /* Remove SR node */
1266 sr_node_del(srn);
1267
1268 return;
1269 }
1270
1271 /* Update Segment Routing from Extended Link LSA */
1272 void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa)
1273 {
1274 struct sr_node *srn;
1275 struct tlv_header *tlvh;
1276 struct lsa_header *lsah = (struct lsa_header *)lsa->data;
1277 struct sr_link *srl;
1278
1279 u_int16_t length, sum;
1280
1281 if (IS_DEBUG_OSPF_SR)
1282 zlog_debug(
1283 "SR (ospf_sr_ext_link_lsa_update): Process "
1284 "Extended Link LSA 8.0.0.%d from %s",
1285 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1286 inet_ntoa(lsah->adv_router));
1287
1288 /* Sanity check */
1289 if (OspfSR.neighbors == NULL) {
1290 zlog_err(
1291 "SR (ospf_sr_ext_link_lsa_update): Abort! no "
1292 "valid SR DataBase");
1293 return;
1294 }
1295
1296 /* Get SR Node in hash table from Router ID */
1297 srn = (struct sr_node *)hash_get(OspfSR.neighbors,
1298 (void *)&(lsah->adv_router),
1299 (void *)sr_node_new);
1300
1301 /* Sanity check */
1302 if (srn == NULL) {
1303 zlog_err(
1304 "SR (ospf_sr_ext_link_lsa_update): Abort! can't "
1305 "create SR node in hash table");
1306 return;
1307 }
1308
1309 /* Initialize TLV browsing */
1310 length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
1311 sum = 0;
1312 for (tlvh = TLV_HDR_TOP(lsah); sum < length;
1313 tlvh = TLV_HDR_NEXT(tlvh)) {
1314 if (ntohs(tlvh->type) == EXT_TLV_LINK) {
1315 /* Got Extended Link information */
1316 srl = get_ext_link_sid(tlvh);
1317 /* Update SID if not null */
1318 if (srl != NULL) {
1319 srl->instance = ntohl(lsah->id.s_addr);
1320 update_ext_link_sid(srn, srl, lsa->flags);
1321 }
1322 }
1323 sum += TLV_SIZE(tlvh);
1324 }
1325 }
1326
1327 /* Delete Segment Routing from Extended Link LSA */
1328 void ospf_sr_ext_link_lsa_delete(struct ospf_lsa *lsa)
1329 {
1330 struct listnode *node;
1331 struct sr_link *srl;
1332 struct sr_node *srn;
1333 struct lsa_header *lsah = (struct lsa_header *)lsa->data;
1334 u_int32_t instance = ntohl(lsah->id.s_addr);
1335
1336 if (IS_DEBUG_OSPF_SR)
1337 zlog_debug(
1338 "SR (ospf_sr_ext_link_lsa_delete): Remove "
1339 "Extended Link LSA 8.0.0.%d from %s",
1340 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1341 inet_ntoa(lsah->adv_router));
1342
1343 /* Sanity check */
1344 if (OspfSR.neighbors == NULL) {
1345 zlog_err(
1346 "SR (ospf_sr_ext_link_lsa_delete): Abort! no "
1347 "valid SR DataBase");
1348 return;
1349 }
1350
1351 /* Search SR Node in hash table from Router ID */
1352 srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
1353 (void *)&(lsah->adv_router));
1354
1355 /* Sanity check */
1356 if (srn == NULL) {
1357 zlog_err(
1358 "SR (ospf_sr_ext_link_lsa_delete): Abort! "
1359 "no entry in SRDB for SR Node %s",
1360 inet_ntoa(lsah->adv_router));
1361 return;
1362 }
1363
1364 /* Search for corresponding Segment Link */
1365 for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl))
1366 if (srl->instance == instance)
1367 break;
1368
1369 /* Remove Segment Link if found */
1370 if (srl->instance == instance) {
1371 del_sid_nhlfe(srl->nhlfe[0]);
1372 del_sid_nhlfe(srl->nhlfe[1]);
1373 listnode_delete(srn->ext_link, srl);
1374 XFREE(MTYPE_OSPF_SR_PARAMS, srl);
1375 } else {
1376 zlog_warn(
1377 "SR (ospf_sr_ext_link_lsa_delete): Didn't "
1378 "found corresponding SR Link 8.0.0.%d for SR Node %s",
1379 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1380 inet_ntoa(lsah->adv_router));
1381 }
1382
1383 return;
1384 }
1385
1386 /* Update Segment Routing from Extended Prefix LSA */
1387 void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa)
1388 {
1389 struct sr_node *srn;
1390 struct tlv_header *tlvh;
1391 struct lsa_header *lsah = (struct lsa_header *)lsa->data;
1392 struct sr_prefix *srp;
1393
1394 u_int16_t length, sum;
1395
1396 if (IS_DEBUG_OSPF_SR)
1397 zlog_debug(
1398 "SR (ospf_sr_ext_prefix_lsa_update): Process "
1399 "Extended Prefix LSA 7.0.0.%d from %s",
1400 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1401 inet_ntoa(lsah->adv_router));
1402
1403 /* Sanity check */
1404 if (OspfSR.neighbors == NULL) {
1405 zlog_err(
1406 "SR (ospf_sr_ext_prefix_lsa_update): Abort! no "
1407 "valid SR DataBase");
1408 return;
1409 }
1410
1411 /* Get SR Node in hash table from Router ID */
1412 srn = (struct sr_node *)hash_get(OspfSR.neighbors,
1413 (void *)&(lsah->adv_router),
1414 (void *)sr_node_new);
1415
1416 /* Sanity check */
1417 if (srn == NULL) {
1418 zlog_err(
1419 "SR (ospf_sr_ext_prefix_lsa_update): Abort! can't "
1420 "create SR node in hash table");
1421 return;
1422 }
1423
1424 /* Initialize TLV browsing */
1425 length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
1426 sum = 0;
1427 for (tlvh = TLV_HDR_TOP(lsah); sum < length;
1428 tlvh = TLV_HDR_NEXT(tlvh)) {
1429 if (ntohs(tlvh->type) == EXT_TLV_LINK) {
1430 /* Got Extended Link information */
1431 srp = get_ext_prefix_sid(tlvh);
1432 /* Update SID if not null */
1433 if (srp != NULL) {
1434 srp->instance = ntohl(lsah->id.s_addr);
1435 update_ext_prefix_sid(srn, srp);
1436 }
1437 }
1438 sum += TLV_SIZE(tlvh);
1439 }
1440 }
1441
1442 /* Delete Segment Routing from Extended Prefix LSA */
1443 void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *lsa)
1444 {
1445 struct listnode *node;
1446 struct sr_prefix *srp;
1447 struct sr_node *srn;
1448 struct lsa_header *lsah = (struct lsa_header *)lsa->data;
1449 u_int32_t instance = ntohl(lsah->id.s_addr);
1450
1451 if (IS_DEBUG_OSPF_SR)
1452 zlog_debug(
1453 "SR (ospf_sr_ext_prefix_lsa_delete): Remove "
1454 "Extended Prefix LSA 7.0.0.%d from %s",
1455 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1456 inet_ntoa(lsah->adv_router));
1457
1458 /* Sanity check */
1459 if (OspfSR.neighbors == NULL) {
1460 zlog_err(
1461 "SR (ospf_sr_ext_prefix_lsa_delete): Abort! no "
1462 "valid SR DataBase");
1463 return;
1464 }
1465
1466 /* Search SR Node in hash table from Router ID */
1467 srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
1468 (void *)&(lsah->adv_router));
1469
1470 /* Sanity check */
1471 if (srn == NULL) {
1472 zlog_err(
1473 "SR (ospf_sr_ext_prefix_lsa_delete): Abort! "
1474 "no entry in SRDB for SR Node %s",
1475 inet_ntoa(lsah->adv_router));
1476 return;
1477 }
1478
1479 /* Search for corresponding Segment Link */
1480 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp))
1481 if (srp->instance == instance)
1482 break;
1483
1484 /* Remove Segment Link if found */
1485 if (srp->instance == instance) {
1486 del_sid_nhlfe(srp->nhlfe);
1487 listnode_delete(srn->ext_link, srp);
1488 XFREE(MTYPE_OSPF_SR_PARAMS, srp);
1489 } else {
1490 zlog_warn(
1491 "SR (ospf_sr_ext_prefix_lsa_delete): Didn't found"
1492 "corresponding SR Prefix 7.0.0.%d for SR Node %s",
1493 GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
1494 inet_ntoa(lsah->adv_router));
1495 }
1496
1497 return;
1498 }
1499
1500 /* Get Label for Extended Link SID */
1501 /* TODO: To be replace by Zebra Label Manager */
1502 u_int32_t get_ext_link_label_value(void)
1503 {
1504 static u_int32_t label = ADJ_SID_MIN - 1;
1505
1506 if (label < ADJ_SID_MAX)
1507 label += 1;
1508
1509 return label;
1510 }
1511
1512 /*
1513 * Following functions are used to update MPLS LFIB after a SPF run
1514 */
1515
1516 static void ospf_sr_nhlfe_update(struct hash_backet *backet, void *args)
1517 {
1518
1519 struct sr_node *srn = (struct sr_node *)backet->data;
1520 struct listnode *node;
1521 struct sr_prefix *srp;
1522 struct sr_nhlfe old;
1523 struct interface *ifp;
1524 struct prefix p;
1525 int rc;
1526
1527 /* Sanity Check */
1528 if (srn == NULL)
1529 return;
1530
1531 if (IS_DEBUG_OSPF_SR)
1532 zlog_debug(" |- Update Prefix for SR Node %s",
1533 inet_ntoa(srn->adv_router));
1534
1535 /* For FRR router check if there is no SR Prefix
1536 * waiting to be communicated to Extended Prefix */
1537 if (srn == OspfSR.self) {
1538 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
1539
1540 /* Skip Prefix already engaged */
1541 if (srp->instance != 0)
1542 continue;
1543 /* Get Interface and check if it is a Loopback */
1544 p.family = AF_INET;
1545 p.prefixlen = srp->nhlfe.prefv4.prefixlen;
1546 IPV4_ADDR_COPY(&p.u.prefix4, &srp->nhlfe.prefv4.prefix);
1547 ifp = if_lookup_prefix(&p, VRF_DEFAULT);
1548 if (ifp == NULL)
1549 continue;
1550 /* If interface is not a loopback, remove SR prefix */
1551 if (!if_is_loopback(ifp)) {
1552 zlog_warn(
1553 " |- Interface %s is not a "
1554 "Loopback. Remove prefix",
1555 ifp->name);
1556 listnode_delete(srn->ext_prefix, srp);
1557 XFREE(MTYPE_OSPF_SR_PARAMS, srp);
1558 continue;
1559 }
1560 /* OK. Let's update Extended Prefix LSA */
1561 rc = ospf_ext_schedule_prefix_index(ifp, srp->sid,
1562 &srp->nhlfe.prefv4);
1563 srp->instance = SET_OPAQUE_LSID(
1564 OPAQUE_TYPE_EXTENDED_PREFIX_LSA, rc);
1565 srp->nhlfe.ifindex = ifp->ifindex;
1566 }
1567 return;
1568 }
1569
1570 /* Update Extended Prefix */
1571 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
1572
1573 /* Backup current NHLFE */
1574 memcpy(&old, &srp->nhlfe, sizeof(struct sr_nhlfe));
1575
1576 /* Compute the new NHLFE */
1577 rc = compute_prefix_nhlfe(srp);
1578
1579 /* Check computation result */
1580 switch (rc) {
1581 /* next hop is not know, remove old NHLFE to avoid loop */
1582 case -1:
1583 del_sid_nhlfe(srp->nhlfe);
1584 break;
1585 /* next hop has not changed, skip it */
1586 case 0:
1587 break;
1588 /* there is a new next hop, update NHLFE */
1589 case 1:
1590 update_sid_nhlfe(old, srp->nhlfe);
1591 break;
1592 default:
1593 break;
1594 }
1595 }
1596 }
1597
1598 static int ospf_sr_update_schedule(struct thread *t)
1599 {
1600
1601 struct ospf *ospf;
1602 struct timeval start_time, stop_time;
1603
1604 ospf = THREAD_ARG(t);
1605 ospf->t_sr_update = NULL;
1606
1607 if (!OspfSR.update)
1608 return 0;
1609
1610 monotime(&start_time);
1611
1612 if (IS_DEBUG_OSPF_SR)
1613 zlog_debug("SR (ospf_sr_update_schedule): Start SPF update");
1614
1615 hash_iterate(OspfSR.neighbors, (void (*)(struct hash_backet *,
1616 void *))ospf_sr_nhlfe_update,
1617 NULL);
1618
1619 monotime(&stop_time);
1620
1621 zlog_info(
1622 "SR (ospf_sr_update_schedule): SPF Processing Time(usecs): "
1623 "%lld\n",
1624 (stop_time.tv_sec - start_time.tv_sec) * 1000000LL
1625 + (stop_time.tv_usec - start_time.tv_usec));
1626
1627 OspfSR.update = false;
1628 return 1;
1629 }
1630
1631 #define OSPF_SR_UPDATE_INTERVAL 1
1632
1633 void ospf_sr_update_timer_add(struct ospf *ospf)
1634 {
1635
1636 if (ospf == NULL)
1637 return;
1638
1639 /* Check if an update is not alreday engage */
1640 if (OspfSR.update)
1641 return;
1642
1643 OspfSR.update = true;
1644
1645 thread_add_timer(master, ospf_sr_update_schedule, ospf,
1646 OSPF_SR_UPDATE_INTERVAL, &ospf->t_sr_update);
1647 }
1648
1649 /*------------------------------------------------------------------------*
1650 * Followings are vty command functions.
1651 *------------------------------------------------------------------------*/
1652
1653 /*
1654 * Segment Routing Router configuration
1655 *
1656 * Must be centralize as it concerns both Extended Link/Prefix LSA
1657 * and Router Information LSA. Choose to call it from Extended Prefix
1658 * write_config() call back.
1659 *
1660 * @param vty VTY output
1661 *
1662 * @return none
1663 */
1664 void ospf_sr_config_write_router(struct vty *vty)
1665 {
1666 struct listnode *node;
1667 struct sr_prefix *srp;
1668
1669 if (OspfSR.enabled) {
1670 vty_out(vty, " segment-routing on\n");
1671
1672 vty_out(vty, " segment-routing global-block %d %d\n",
1673 OspfSR.srgb.lower_bound,
1674 OspfSR.srgb.lower_bound + OspfSR.srgb.range_size - 1);
1675
1676 if (OspfSR.msd != 0)
1677 vty_out(vty, " segment-routing node-msd %d\n",
1678 OspfSR.msd);
1679
1680 if (OspfSR.self != NULL) {
1681 for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node,
1682 srp)) {
1683 vty_out(vty,
1684 " segment-routing prefix %s/%d "
1685 "index %d\n",
1686 inet_ntoa(srp->nhlfe.prefv4.prefix),
1687 srp->nhlfe.prefv4.prefixlen, srp->sid);
1688 }
1689 }
1690 }
1691 }
1692
1693 DEFUN(ospf_sr_enable,
1694 ospf_sr_enable_cmd,
1695 "segment-routing on",
1696 SR_STR
1697 "Enable Segment Routing\n")
1698 {
1699
1700 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
1701
1702 if (OspfSR.enabled)
1703 return CMD_SUCCESS;
1704
1705 if (IS_DEBUG_OSPF_EVENT)
1706 zlog_debug("SR: Segment Routing: OFF -> ON");
1707
1708 /* Start Segment Routing */
1709 OspfSR.enabled = true;
1710 if (!ospf_sr_start(ospf)) {
1711 zlog_warn("SR: Unable to start Segment Routing. Abort!");
1712 return CMD_WARNING;
1713 }
1714
1715 /* Set Router Information SR parameters */
1716 if (IS_DEBUG_OSPF_EVENT)
1717 zlog_debug("SR: Activate SR for Router Information LSA");
1718
1719 ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
1720
1721 /* Update Ext LSA */
1722 if (IS_DEBUG_OSPF_EVENT)
1723 zlog_debug("SR: Activate SR for Extended Link/Prefix LSA");
1724
1725 ospf_ext_update_sr(true);
1726
1727 return CMD_SUCCESS;
1728 }
1729
1730 DEFUN (no_ospf_sr_enable,
1731 no_ospf_sr_enable_cmd,
1732 "no segment-routing [on]",
1733 NO_STR
1734 SR_STR
1735 "Disable Segment Routing\n")
1736 {
1737
1738 if (!OspfSR.enabled)
1739 return CMD_SUCCESS;
1740
1741 if (IS_DEBUG_OSPF_EVENT)
1742 zlog_debug("SR: Segment Routing: ON -> OFF");
1743
1744 /* Start by Disabling Extended Link & Prefix LSA */
1745 ospf_ext_update_sr(false);
1746
1747 /* then, disable Router Information SR parameters */
1748 ospf_router_info_update_sr(false, OspfSR.srgb, OspfSR.msd);
1749
1750 /* Finally, stop Segment Routing */
1751 ospf_sr_stop();
1752 OspfSR.enabled = false;
1753
1754 return CMD_SUCCESS;
1755 }
1756
1757 static int ospf_sr_enabled(struct vty *vty)
1758 {
1759 if (OspfSR.enabled)
1760 return 1;
1761
1762 if (vty)
1763 vty_out(vty, "%% OSPF SR is not turned on\n");
1764
1765 return 0;
1766 }
1767
1768 DEFUN (sr_sid_label_range,
1769 sr_sid_label_range_cmd,
1770 "segment-routing global-block (0-1048575) (0-1048575)",
1771 SR_STR
1772 "Segment Routing Global Block label range\n"
1773 "Lower-bound range in decimal (0-1048575)\n"
1774 "Upper-bound range in decimal (0-1048575)\n")
1775 {
1776 u_int32_t upper;
1777 u_int32_t lower;
1778 u_int32_t size;
1779 int idx_low = 2;
1780 int idx_up = 3;
1781
1782 if (!ospf_sr_enabled(vty))
1783 return CMD_WARNING_CONFIG_FAILED;
1784
1785 if (sscanf(argv[idx_low]->arg, "%d", &lower) != 1) {
1786 vty_out(vty, "segment-routing: fscanf: %s\n",
1787 safe_strerror(errno));
1788 return CMD_WARNING_CONFIG_FAILED;
1789 }
1790
1791 if (sscanf(argv[idx_up]->arg, "%d", &upper) != 1) {
1792 vty_out(vty, "segment-routing: fscanf: %s\n",
1793 safe_strerror(errno));
1794 return CMD_WARNING_CONFIG_FAILED;
1795 }
1796
1797 size = upper - lower + 1;
1798
1799 if (size > MPLS_DEFAULT_MAX_SRGB_SIZE || size <= 0) {
1800 vty_out(vty,
1801 "Range size cannot be less than 0 or more than %d\n",
1802 MPLS_DEFAULT_MAX_SRGB_SIZE);
1803 return CMD_WARNING_CONFIG_FAILED;
1804 }
1805
1806 if (upper > MPLS_DEFAULT_MAX_SRGB_LABEL) {
1807 vty_out(vty, "Upper-bound cannot exceed %d\n",
1808 MPLS_DEFAULT_MAX_SRGB_LABEL);
1809 return CMD_WARNING_CONFIG_FAILED;
1810 }
1811
1812 if (upper < MPLS_DEFAULT_MIN_SRGB_LABEL) {
1813 vty_out(vty, "Upper-bound cannot be lower than %d\n",
1814 MPLS_DEFAULT_MIN_SRGB_LABEL);
1815 return CMD_WARNING_CONFIG_FAILED;
1816 }
1817
1818 /* Set SID/Label range SRGB */
1819 OspfSR.srgb.range_size = size;
1820 OspfSR.srgb.lower_bound = lower;
1821
1822 /* Set Router Information SR parameters */
1823 ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
1824
1825 /* Update NHLFE entries */
1826 hash_iterate(OspfSR.neighbors,
1827 (void (*)(struct hash_backet *, void *))update_in_nhlfe,
1828 NULL);
1829
1830 return CMD_SUCCESS;
1831 }
1832
1833 DEFUN (no_sr_sid_label_range,
1834 no_sr_sid_label_range_cmd,
1835 "no segment-routing global-block",
1836 NO_STR
1837 SR_STR
1838 "Delete Segment Routing Global Block label range\n")
1839 {
1840
1841 if (!ospf_sr_enabled(vty))
1842 return CMD_WARNING_CONFIG_FAILED;
1843
1844 /* Revert to default SRGB value */
1845 OspfSR.srgb.range_size = MPLS_DEFAULT_MIN_SRGB_SIZE;
1846 OspfSR.srgb.lower_bound = MPLS_DEFAULT_MIN_SRGB_LABEL;
1847
1848 /* Set Router Information SR parameters */
1849 ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
1850
1851 /* Update NHLFE entries */
1852 hash_iterate(OspfSR.neighbors,
1853 (void (*)(struct hash_backet *, void *))update_in_nhlfe,
1854 NULL);
1855
1856 return CMD_SUCCESS;
1857 }
1858
1859 DEFUN (sr_node_msd,
1860 sr_node_msd_cmd,
1861 "segment-routing node-msd (1-16)",
1862 SR_STR
1863 "Maximum Stack Depth for this router\n"
1864 "Maximum number of label that could be stack (1-16)\n")
1865 {
1866 u_int32_t msd;
1867 int idx_number = 2;
1868
1869 if (!ospf_sr_enabled(vty))
1870 return CMD_WARNING_CONFIG_FAILED;
1871
1872 if (sscanf(argv[idx_number]->arg, "%d", &msd) != 1) {
1873 vty_out(vty, "segment-routing: fscanf: %s\n",
1874 safe_strerror(errno));
1875 return CMD_WARNING_CONFIG_FAILED;
1876 }
1877
1878 if (msd < 1 || msd > MPLS_MAX_LABELS) {
1879 vty_out(vty, "MSD must be comprise between 1 and %d\n",
1880 MPLS_MAX_LABELS);
1881 return CMD_WARNING_CONFIG_FAILED;
1882 }
1883
1884 /* Set this router MSD */
1885 OspfSR.msd = msd;
1886
1887 /* Set Router Information SR parameters */
1888 ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
1889
1890 return CMD_SUCCESS;
1891 }
1892
1893 DEFUN (no_sr_node_msd,
1894 no_sr_node_msd_cmd,
1895 "no segment-routing node-msd",
1896 NO_STR
1897 SR_STR
1898 "Disable Maximum Stack Depth for this router\n")
1899 {
1900
1901 if (!ospf_sr_enabled(vty))
1902 return CMD_WARNING_CONFIG_FAILED;
1903
1904 /* unset this router MSD */
1905 OspfSR.msd = 0;
1906
1907 /* Set Router Information SR parameters */
1908 ospf_router_info_update_sr(true, OspfSR.srgb, 0);
1909
1910 return CMD_SUCCESS;
1911 }
1912
1913 DEFUN (sr_prefix_sid,
1914 sr_prefix_sid_cmd,
1915 "segment-routing prefix A.B.C.D/M index (0-65535)",
1916 SR_STR
1917 "Prefix SID\n"
1918 "IPv4 Prefix as A.B.C.D/M\n"
1919 "SID index for this prefix in decimal (0-65535)\n"
1920 "Index value inside SRGB (lower_bound < index < upper_bound)\n")
1921 {
1922 int idx_prefix = 2;
1923 int idx_index = 4;
1924 struct prefix p;
1925 uint32_t index;
1926 struct listnode *node;
1927 struct sr_prefix *srp;
1928 struct interface *ifp;
1929
1930 if (!ospf_sr_enabled(vty))
1931 return CMD_WARNING_CONFIG_FAILED;
1932
1933 /* Get network prefix */
1934 str2prefix(argv[idx_prefix]->arg, &p);
1935
1936 /* Get & verify index value */
1937 index = strtoul(argv[idx_index]->arg, NULL, 10);
1938 if (index > OspfSR.srgb.range_size - 1) {
1939 vty_out(vty, "Index %d must be lower than range size %d\n",
1940 index, OspfSR.srgb.range_size);
1941 return CMD_WARNING_CONFIG_FAILED;
1942 }
1943
1944 /* check that the index is not already used */
1945 for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
1946 if (srp->sid == index) {
1947 vty_out(vty, "Index %d is already used\n", index);
1948 return CMD_WARNING_CONFIG_FAILED;
1949 }
1950 }
1951
1952 /* Get Interface and check if it is a Loopback */
1953 ifp = if_lookup_prefix(&p, VRF_DEFAULT);
1954 if (ifp == NULL) {
1955 /* Interface could be not yet available i.e. when this
1956 * command is in the configuration file, OSPF is not yet
1957 * ready. In this case, store the prefix SID for latter
1958 * (i.e. when SPF run) communication to Extended Prefix */
1959 srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
1960 srp->instance = 0;
1961 IPV4_ADDR_COPY(&srp->nhlfe.prefv4.prefix, &p.u.prefix4);
1962 srp->nhlfe.prefv4.prefixlen = p.prefixlen;
1963 srp->nhlfe.prefv4.family = p.family;
1964 srp->sid = index;
1965 listnode_add(OspfSR.self->ext_prefix, srp);
1966 vty_out(vty,
1967 "Interface for prefix %s not found. Deferred LSA "
1968 "flooding\n",
1969 argv[idx_prefix]->arg);
1970 return CMD_SUCCESS;
1971 }
1972 if (!if_is_loopback(ifp)) {
1973 vty_out(vty, "interface %s is not a Loopback\n", ifp->name);
1974 return CMD_WARNING_CONFIG_FAILED;
1975 }
1976
1977 /* Update Extended Prefix LSA */
1978 if (!ospf_ext_schedule_prefix_index(ifp, index,
1979 (struct prefix_ipv4 *)&p)) {
1980 vty_out(vty, "Unable to set index %d for prefix %s\n", index,
1981 argv[idx_prefix]->arg);
1982 return CMD_WARNING;
1983 }
1984
1985 return CMD_SUCCESS;
1986 }
1987
1988 DEFUN (no_sr_prefix_sid,
1989 no_sr_prefix_sid_cmd,
1990 "no segment-routing prefix A.B.C.D/M",
1991 NO_STR
1992 SR_STR
1993 "Prefix SID\n"
1994 "IPv4 Prefix as A.B.C.D/M\n")
1995 {
1996 int idx_prefix = 2;
1997 struct prefix p;
1998 struct listnode *node;
1999 struct sr_prefix *srp;
2000 struct interface *ifp;
2001 bool found = false;
2002
2003 /* Get network prefix */
2004 str2prefix(argv[idx_prefix]->arg, &p);
2005
2006 /* check that the prefix is already set */
2007 for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp))
2008 if (IPV4_ADDR_SAME(&srp->nhlfe.prefv4.prefix, &p.u.prefix4)
2009 && (srp->nhlfe.prefv4.prefixlen == p.prefixlen))
2010 found = true;
2011
2012 if (!found) {
2013 vty_out(vty, "Prefix %s is not found. Abort!\n",
2014 argv[idx_prefix]->arg);
2015 return CMD_WARNING_CONFIG_FAILED;
2016 }
2017
2018 /* Get Interface and check if it is a Loopback */
2019 ifp = if_lookup_prefix(&p, VRF_DEFAULT);
2020 if (ifp == NULL) {
2021 vty_out(vty, "interface for prefix %s not found.\n",
2022 argv[idx_prefix]->arg);
2023 return CMD_WARNING_CONFIG_FAILED;
2024 }
2025 if (!if_is_loopback(ifp)) {
2026 vty_out(vty, "interface %s is not a Loopback\n", ifp->name);
2027 return CMD_WARNING_CONFIG_FAILED;
2028 }
2029 /* Update Extended Prefix LSA */
2030 if (!ospf_ext_schedule_prefix_index(ifp, 0, NULL)) {
2031 vty_out(vty, "No corresponding loopback interface. Abort!\n");
2032 return CMD_WARNING;
2033 }
2034
2035 return CMD_SUCCESS;
2036 }
2037
2038 static void show_vty_sr_node(struct vty *vty, struct sr_node *srn)
2039 {
2040
2041 struct listnode *node;
2042 struct sr_link *srl;
2043 struct sr_prefix *srp;
2044 struct interface *itf;
2045 char pref[16];
2046 char sid[20];
2047 char label[8];
2048
2049 /* Sanity Check */
2050 if (srn == NULL)
2051 return;
2052
2053 vty_out(vty, "SR-Node: %s", inet_ntoa(srn->adv_router));
2054 vty_out(vty, "\tSRGB (Size/Label): %d/%d", srn->srgb.range_size,
2055 srn->srgb.lower_bound);
2056 vty_out(vty, "\tAlgorithm(s): %s",
2057 srn->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
2058 for (int i = 1; i < ALGORITHM_COUNT; i++) {
2059 if (srn->algo[i] == SR_ALGORITHM_UNSET)
2060 continue;
2061 vty_out(vty, "/%s",
2062 srn->algo[i] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
2063 }
2064 if (srn->msd != 0)
2065 vty_out(vty, "\tMSD: %d", srn->msd);
2066
2067 vty_out(vty,
2068 "\n\n Prefix or Link Label In Label Out "
2069 "Node or Adj. SID Interface Nexthop\n");
2070 vty_out(vty,
2071 "------------------ -------- --------- "
2072 "-------------------- --------- ---------------\n");
2073 for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
2074 strncpy(pref, inet_ntoa(srp->nhlfe.prefv4.prefix), 16);
2075 snprintf(sid, 20, "SR Pfx (idx %d)", srp->sid);
2076 if (srp->nhlfe.label_out == MPLS_IMP_NULL_LABEL)
2077 sprintf(label, "pop");
2078 else
2079 sprintf(label, "%d", srp->nhlfe.label_out);
2080 itf = if_lookup_by_index(srp->nhlfe.ifindex, VRF_DEFAULT);
2081 vty_out(vty, "%15s/%d %8d %9s %20s %9s %15s\n", pref,
2082 srp->nhlfe.prefv4.prefixlen, srp->nhlfe.label_in, label,
2083 sid, itf ? itf->name : "-",
2084 inet_ntoa(srp->nhlfe.nexthop));
2085 }
2086
2087 for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
2088 strncpy(pref, inet_ntoa(srl->nhlfe[0].prefv4.prefix), 16);
2089 snprintf(sid, 20, "SR Adj. (lbl %d)", srl->sid[0]);
2090 if (srl->nhlfe[0].label_out == MPLS_IMP_NULL_LABEL)
2091 sprintf(label, "pop");
2092 else
2093 sprintf(label, "%d", srl->nhlfe[0].label_out);
2094 itf = if_lookup_by_index(srl->nhlfe[0].ifindex, VRF_DEFAULT);
2095 vty_out(vty, "%15s/%d %8d %9s %20s %9s %15s\n", pref,
2096 srl->nhlfe[0].prefv4.prefixlen, srl->nhlfe[0].label_in,
2097 label, sid, itf ? itf->name : "-",
2098 inet_ntoa(srl->nhlfe[0].nexthop));
2099 snprintf(sid, 20, "SR Adj. (lbl %d)", srl->sid[1]);
2100 if (srl->nhlfe[1].label_out == MPLS_IMP_NULL_LABEL)
2101 sprintf(label, "pop");
2102 else
2103 sprintf(label, "%d", srl->nhlfe[0].label_out);
2104 vty_out(vty, "%15s/%d %8d %9s %20s %9s %15s\n", pref,
2105 srl->nhlfe[1].prefv4.prefixlen, srl->nhlfe[1].label_in,
2106 label, sid, itf ? itf->name : "-",
2107 inet_ntoa(srl->nhlfe[1].nexthop));
2108 }
2109 vty_out(vty, "\n");
2110 }
2111
2112 static void show_srdb_entry(struct hash_backet *backet, void *args)
2113 {
2114 struct vty *vty = (struct vty *)args;
2115 struct sr_node *srn = (struct sr_node *)backet->data;
2116
2117 show_vty_sr_node(vty, srn);
2118 }
2119
2120 DEFUN (show_ip_opsf_srdb,
2121 show_ip_ospf_srdb_cmd,
2122 "show ip ospf database segment-routing [adv-router A.B.C.D|self-originate]",
2123 SHOW_STR
2124 IP_STR
2125 OSPF_STR
2126 "Database summary\n"
2127 "Show Segment Routing Data Base\n"
2128 "Advertising SR node\n"
2129 "Advertising SR node ID (as an IP address)\n"
2130 "Self-originated SR node\n")
2131 {
2132 int idx_ip = 6;
2133 struct in_addr rid;
2134 struct sr_node *srn;
2135
2136 if (!OspfSR.enabled) {
2137 vty_out(vty, "Segment Routing is disabled on this router\n");
2138 return CMD_WARNING_CONFIG_FAILED;
2139 }
2140
2141 vty_out(vty, "\n OSPF Segment Routing database for ID %s\n\n",
2142 inet_ntoa(OspfSR.self->adv_router));
2143
2144 if (argc < idx_ip) {
2145 /* Iterate through all the SRDB */
2146 hash_iterate(
2147 OspfSR.neighbors,
2148 (void (*)(struct hash_backet *, void *))show_srdb_entry,
2149 (void *)vty);
2150 } else {
2151 /* or show only specified SR Node */
2152 if (argc == idx_ip) {
2153 srn = OspfSR.self;
2154 } else {
2155 if (!inet_aton(argv[idx_ip]->arg, &rid)) {
2156 vty_out(vty,
2157 "Specified Router ID %s is "
2158 "invalid\n",
2159 argv[idx_ip]->arg);
2160 return CMD_WARNING_CONFIG_FAILED;
2161 }
2162 /* Get the SR Node from the SRDB */
2163 srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
2164 (void *)&rid);
2165 }
2166 show_vty_sr_node(vty, srn);
2167 }
2168 return CMD_SUCCESS;
2169 }
2170
2171 /* Install new CLI commands */
2172 void ospf_sr_register_vty(void)
2173 {
2174 install_element(VIEW_NODE, &show_ip_ospf_srdb_cmd);
2175
2176 install_element(OSPF_NODE, &ospf_sr_enable_cmd);
2177 install_element(OSPF_NODE, &no_ospf_sr_enable_cmd);
2178 install_element(OSPF_NODE, &sr_sid_label_range_cmd);
2179 install_element(OSPF_NODE, &no_sr_sid_label_range_cmd);
2180 install_element(OSPF_NODE, &sr_node_msd_cmd);
2181 install_element(OSPF_NODE, &no_sr_node_msd_cmd);
2182 install_element(OSPF_NODE, &sr_prefix_sid_cmd);
2183 install_element(OSPF_NODE, &no_sr_prefix_sid_cmd);
2184
2185 return;
2186 }