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