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