]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_te.c
ospfd: Force Opaque LSA & co to default VRF
[mirror_frr.git] / ospfd / ospf_te.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
16f1b9ee 3 * This is an implementation of RFC3630
718e3744 4 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
5 * http://www.kddlabs.co.jp/
6 *
16f1b9ee
OD
7 * Copyright (C) 2012 Orange Labs
8 * http://www.orange.com
718e3744 9 */
10
16f1b9ee
OD
11/* Add support of RFC7471 */
12/* Add support of RFC5392, RFC6827 */
718e3744 13
14#include <zebra.h>
16f1b9ee 15#include <math.h>
718e3744 16
718e3744 17#include "linklist.h"
18#include "prefix.h"
b2d7c082 19#include "vrf.h"
718e3744 20#include "if.h"
21#include "table.h"
22#include "memory.h"
23#include "command.h"
24#include "vty.h"
25#include "stream.h"
26#include "log.h"
24a58196 27#include "frrevent.h"
718e3744 28#include "hash.h"
d62a17ae 29#include "sockunion.h" /* for inet_aton() */
16f1b9ee 30#include "network.h"
f173deb3
OD
31#include "link_state.h"
32#include "zclient.h"
33#include "printfrr.h"
718e3744 34
35#include "ospfd/ospfd.h"
36#include "ospfd/ospf_interface.h"
37#include "ospfd/ospf_ism.h"
38#include "ospfd/ospf_asbr.h"
39#include "ospfd/ospf_lsa.h"
40#include "ospfd/ospf_lsdb.h"
41#include "ospfd/ospf_neighbor.h"
42#include "ospfd/ospf_nsm.h"
43#include "ospfd/ospf_flood.h"
44#include "ospfd/ospf_packet.h"
45#include "ospfd/ospf_spf.h"
46#include "ospfd/ospf_dump.h"
47#include "ospfd/ospf_route.h"
48#include "ospfd/ospf_ase.h"
49#include "ospfd/ospf_zebra.h"
50#include "ospfd/ospf_te.h"
f173deb3
OD
51#include "ospfd/ospf_sr.h"
52#include "ospfd/ospf_ri.h"
53#include "ospfd/ospf_ext.h"
16f1b9ee 54#include "ospfd/ospf_vty.h"
85c9b439 55#include "ospfd/ospf_errors.h"
718e3744 56
57/*
58 * Global variable to manage Opaque-LSA/MPLS-TE on this node.
59 * Note that all parameter values are stored in network byte order.
60 */
16f1b9ee 61struct ospf_mpls_te OspfMplsTE;
718e3744 62
2b64873d 63static const char *const mode2text[] = {"Off", "AS", "Area"};
718e3744 64
f173deb3 65
718e3744 66/*------------------------------------------------------------------------*
78dfa0c7 67 * Following are initialize/terminate functions for MPLS-TE handling.
718e3744 68 *------------------------------------------------------------------------*/
69
d62a17ae 70static int ospf_mpls_te_new_if(struct interface *ifp);
71static int ospf_mpls_te_del_if(struct interface *ifp);
72static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status);
73static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status);
74static void ospf_mpls_te_config_write_router(struct vty *vty);
3e63092b
RW
75static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json,
76 struct ospf_lsa *lsa);
d62a17ae 77static int ospf_mpls_te_lsa_originate_area(void *arg);
2efd7e2b
OD
78static int ospf_mpls_te_lsa_inter_as_as(void *arg);
79static int ospf_mpls_te_lsa_inter_as_area(void *arg);
d62a17ae 80static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa);
f173deb3
OD
81static int ospf_mpls_te_lsa_update(struct ospf_lsa *lsa);
82static int ospf_mpls_te_lsa_delete(struct ospf_lsa *lsa);
d62a17ae 83
84static void del_mpls_te_link(void *val);
85static void ospf_mpls_te_register_vty(void);
86
87int ospf_mpls_te_init(void)
88{
89 int rc;
90
2efd7e2b 91 /* Register Opaque AREA LSA Type 1 for Traffic Engineering */
d62a17ae 92 rc = ospf_register_opaque_functab(
f173deb3
OD
93 OSPF_OPAQUE_AREA_LSA,
94 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
95 ospf_mpls_te_new_if,
96 ospf_mpls_te_del_if,
97 ospf_mpls_te_ism_change,
98 ospf_mpls_te_nsm_change,
718e3744 99 ospf_mpls_te_config_write_router,
f173deb3 100 NULL, /* ospf_mpls_te_config_write_if */
d62a17ae 101 NULL, /* ospf_mpls_te_config_write_debug */
102 ospf_mpls_te_show_info, ospf_mpls_te_lsa_originate_area,
f173deb3
OD
103 ospf_mpls_te_lsa_refresh,
104 ospf_mpls_te_lsa_update, /* ospf_mpls_te_new_lsa_hook */
105 ospf_mpls_te_lsa_delete /* ospf_mpls_te_del_lsa_hook */);
d62a17ae 106 if (rc != 0) {
ade6974d 107 flog_warn(
cf444bcf 108 EC_OSPF_OPAQUE_REGISTRATION,
fd3c7692
OD
109 "MPLS-TE (%s): Failed to register Traffic Engineering functions",
110 __func__);
ead99d5f 111 return rc;
d62a17ae 112 }
718e3744 113
2efd7e2b
OD
114 /*
115 * Wee need also to register Opaque LSA Type 6 i.e. Inter-AS RFC5392 for
116 * both AREA and AS at least to have the possibility to call the show()
117 * function when looking to the opaque LSA of the OSPF database.
118 */
119 rc = ospf_register_opaque_functab(OSPF_OPAQUE_AREA_LSA,
120 OPAQUE_TYPE_INTER_AS_LSA, NULL,
121 NULL, NULL, NULL, NULL, NULL, NULL,
122 ospf_mpls_te_show_info,
123 ospf_mpls_te_lsa_inter_as_area,
124 ospf_mpls_te_lsa_refresh, NULL, NULL);
125 if (rc != 0) {
126 flog_warn(
127 EC_OSPF_OPAQUE_REGISTRATION,
128 "MPLS-TE (%s): Failed to register Inter-AS with Area scope",
129 __func__);
ead99d5f 130 return rc;
2efd7e2b 131 }
16f1b9ee 132
2efd7e2b
OD
133 rc = ospf_register_opaque_functab(OSPF_OPAQUE_AS_LSA,
134 OPAQUE_TYPE_INTER_AS_LSA, NULL,
d62a17ae 135 NULL, NULL, NULL, NULL, NULL, NULL,
136 ospf_mpls_te_show_info,
2efd7e2b 137 ospf_mpls_te_lsa_inter_as_as,
d62a17ae 138 ospf_mpls_te_lsa_refresh, NULL, NULL);
d62a17ae 139 if (rc != 0) {
2efd7e2b
OD
140 flog_warn(
141 EC_OSPF_OPAQUE_REGISTRATION,
142 "MPLS-TE (%s): Failed to register Inter-AS with AS scope",
143 __func__);
d62a17ae 144 return rc;
145 }
16f1b9ee 146
6006b807 147 memset(&OspfMplsTE, 0, sizeof(OspfMplsTE));
2efd7e2b
OD
148 OspfMplsTE.enabled = false;
149 OspfMplsTE.export = false;
150 OspfMplsTE.inter_as = Off;
151 OspfMplsTE.iflist = list_new();
152 OspfMplsTE.iflist->del = del_mpls_te_link;
bcf4475e 153
2efd7e2b 154 ospf_mpls_te_register_vty();
bcf4475e 155
2efd7e2b 156 return rc;
bcf4475e
OD
157}
158
d62a17ae 159void ospf_mpls_te_term(void)
718e3744 160{
6a154c88 161 list_delete(&OspfMplsTE.iflist);
718e3744 162
bcf4475e
OD
163 ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
164 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
2efd7e2b
OD
165 ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
166 OPAQUE_TYPE_INTER_AS_LSA);
167 ospf_delete_opaque_functab(OSPF_OPAQUE_AS_LSA,
168 OPAQUE_TYPE_INTER_AS_LSA);
bcf4475e 169
32ab5cf4 170 OspfMplsTE.enabled = false;
ead99d5f 171 OspfMplsTE.inter_as = Off;
f173deb3 172 OspfMplsTE.export = false;
16f1b9ee 173
d62a17ae 174 return;
718e3744 175}
176
bcf4475e
OD
177void ospf_mpls_te_finish(void)
178{
bcf4475e
OD
179 OspfMplsTE.enabled = false;
180 OspfMplsTE.inter_as = Off;
f173deb3 181 OspfMplsTE.export = false;
bcf4475e
OD
182}
183
718e3744 184/*------------------------------------------------------------------------*
78dfa0c7 185 * Following are control functions for MPLS-TE parameters management.
718e3744 186 *------------------------------------------------------------------------*/
d62a17ae 187static void del_mpls_te_link(void *val)
718e3744 188{
d62a17ae 189 XFREE(MTYPE_OSPF_MPLS_TE, val);
190 return;
718e3744 191}
192
d7c0a89a 193static uint32_t get_mpls_te_instance_value(void)
718e3744 194{
d7c0a89a 195 static uint32_t seqno = 0;
718e3744 196
d62a17ae 197 if (seqno < MAX_LEGAL_TE_INSTANCE_NUM)
198 seqno += 1;
199 else
200 seqno = 1; /* Avoid zero. */
718e3744 201
d62a17ae 202 return seqno;
718e3744 203}
204
d62a17ae 205static struct mpls_te_link *lookup_linkparams_by_ifp(struct interface *ifp)
718e3744 206{
d62a17ae 207 struct listnode *node, *nnode;
208 struct mpls_te_link *lp;
718e3744 209
d62a17ae 210 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
211 if (lp->ifp == ifp)
212 return lp;
718e3744 213
d62a17ae 214 return NULL;
718e3744 215}
216
d62a17ae 217static struct mpls_te_link *lookup_linkparams_by_instance(struct ospf_lsa *lsa)
718e3744 218{
d62a17ae 219 struct listnode *node;
220 struct mpls_te_link *lp;
221 unsigned int key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr));
718e3744 222
d62a17ae 223 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
224 if (lp->instance == key)
225 return lp;
718e3744 226
fd3c7692 227 ote_debug("MPLS-TE (%s): Entry not found: key(%x)", __func__, key);
d62a17ae 228 return NULL;
718e3744 229}
230
996c9314
LB
231static void ospf_mpls_te_foreach_area(
232 void (*func)(struct mpls_te_link *lp, enum lsa_opcode sched_opcode),
233 enum lsa_opcode sched_opcode)
718e3744 234{
d62a17ae 235 struct listnode *node, *nnode;
236 struct listnode *node2;
237 struct mpls_te_link *lp;
238 struct ospf_area *area;
718e3744 239
d62a17ae 240 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
241 /* Skip Inter-AS TEv2 Links */
242 if (IS_INTER_AS(lp->type))
243 continue;
244 if ((area = lp->area) == NULL)
245 continue;
32ab5cf4
OD
246 if (CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE))
247 continue;
718e3744 248
d62a17ae 249 if (func != NULL)
250 (*func)(lp, sched_opcode);
718e3744 251
d62a17ae 252 for (node2 = listnextnode(node); node2;
253 node2 = listnextnode(node2))
254 if ((lp = listgetdata(node2)) != NULL)
255 if (lp->area != NULL)
256 if (IPV4_ADDR_SAME(&lp->area->area_id,
257 &area->area_id))
258 SET_FLAG(lp->flags,
259 LPFLG_LOOKUP_DONE);
260 }
718e3744 261
d62a17ae 262 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
263 if (lp->area != NULL)
264 UNSET_FLAG(lp->flags, LPFLG_LOOKUP_DONE);
718e3744 265
d62a17ae 266 return;
718e3744 267}
268
d62a17ae 269static void set_mpls_te_router_addr(struct in_addr ipv4)
718e3744 270{
d62a17ae 271 OspfMplsTE.router_addr.header.type = htons(TE_TLV_ROUTER_ADDR);
272 OspfMplsTE.router_addr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
273 OspfMplsTE.router_addr.value = ipv4;
274 return;
718e3744 275}
276
d62a17ae 277static void set_linkparams_link_header(struct mpls_te_link *lp)
718e3744 278{
d7c0a89a 279 uint16_t length = 0;
718e3744 280
d62a17ae 281 /* TE_LINK_SUBTLV_LINK_TYPE */
282 if (ntohs(lp->link_type.header.type) != 0)
283 length += TLV_SIZE(&lp->link_type.header);
718e3744 284
d62a17ae 285 /* TE_LINK_SUBTLV_LINK_ID */
286 if (ntohs(lp->link_id.header.type) != 0)
287 length += TLV_SIZE(&lp->link_id.header);
718e3744 288
d62a17ae 289 /* TE_LINK_SUBTLV_LCLIF_IPADDR */
290 if (lp->lclif_ipaddr.header.type != 0)
291 length += TLV_SIZE(&lp->lclif_ipaddr.header);
718e3744 292
d62a17ae 293 /* TE_LINK_SUBTLV_RMTIF_IPADDR */
294 if (lp->rmtif_ipaddr.header.type != 0)
295 length += TLV_SIZE(&lp->rmtif_ipaddr.header);
718e3744 296
d62a17ae 297 /* TE_LINK_SUBTLV_TE_METRIC */
298 if (ntohs(lp->te_metric.header.type) != 0)
299 length += TLV_SIZE(&lp->te_metric.header);
718e3744 300
d62a17ae 301 /* TE_LINK_SUBTLV_MAX_BW */
302 if (ntohs(lp->max_bw.header.type) != 0)
303 length += TLV_SIZE(&lp->max_bw.header);
718e3744 304
d62a17ae 305 /* TE_LINK_SUBTLV_MAX_RSV_BW */
306 if (ntohs(lp->max_rsv_bw.header.type) != 0)
307 length += TLV_SIZE(&lp->max_rsv_bw.header);
718e3744 308
d62a17ae 309 /* TE_LINK_SUBTLV_UNRSV_BW */
310 if (ntohs(lp->unrsv_bw.header.type) != 0)
311 length += TLV_SIZE(&lp->unrsv_bw.header);
718e3744 312
d62a17ae 313 /* TE_LINK_SUBTLV_RSC_CLSCLR */
314 if (ntohs(lp->rsc_clsclr.header.type) != 0)
315 length += TLV_SIZE(&lp->rsc_clsclr.header);
316
317 /* TE_LINK_SUBTLV_LLRI */
318 if (ntohs(lp->llri.header.type) != 0)
319 length += TLV_SIZE(&lp->llri.header);
320
321 /* TE_LINK_SUBTLV_RIP */
322 if (ntohs(lp->rip.header.type) != 0)
323 length += TLV_SIZE(&lp->rip.header);
324
325 /* TE_LINK_SUBTLV_RAS */
326 if (ntohs(lp->ras.header.type) != 0)
327 length += TLV_SIZE(&lp->ras.header);
328
329 /* TE_LINK_SUBTLV_LRRID */
330 if (ntohs(lp->lrrid.header.type) != 0)
331 length += TLV_SIZE(&lp->lrrid.header);
332
333 /* TE_LINK_SUBTLV_AV_DELAY */
334 if (ntohs(lp->av_delay.header.type) != 0)
335 length += TLV_SIZE(&lp->av_delay.header);
336
337 /* TE_LINK_SUBTLV_MM_DELAY */
338 if (ntohs(lp->mm_delay.header.type) != 0)
339 length += TLV_SIZE(&lp->mm_delay.header);
340
341 /* TE_LINK_SUBTLV_DELAY_VAR */
342 if (ntohs(lp->delay_var.header.type) != 0)
343 length += TLV_SIZE(&lp->delay_var.header);
344
345 /* TE_LINK_SUBTLV_PKT_LOSS */
346 if (ntohs(lp->pkt_loss.header.type) != 0)
347 length += TLV_SIZE(&lp->pkt_loss.header);
348
349 /* TE_LINK_SUBTLV_RES_BW */
350 if (ntohs(lp->res_bw.header.type) != 0)
351 length += TLV_SIZE(&lp->res_bw.header);
352
353 /* TE_LINK_SUBTLV_AVA_BW */
354 if (ntohs(lp->ava_bw.header.type) != 0)
355 length += TLV_SIZE(&lp->ava_bw.header);
356
357 /* TE_LINK_SUBTLV_USE_BW */
358 if (ntohs(lp->use_bw.header.type) != 0)
359 length += TLV_SIZE(&lp->use_bw.header);
718e3744 360
d62a17ae 361 lp->link_header.header.type = htons(TE_TLV_LINK);
362 lp->link_header.header.length = htons(length);
363
364 return;
718e3744 365}
d62a17ae 366
367static void set_linkparams_link_type(struct ospf_interface *oi,
368 struct mpls_te_link *lp)
369{
370 lp->link_type.header.type = htons(TE_LINK_SUBTLV_LINK_TYPE);
371 lp->link_type.header.length = htons(TE_LINK_SUBTLV_TYPE_SIZE);
372
373 switch (oi->type) {
374 case OSPF_IFTYPE_POINTOPOINT:
375 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
376 break;
377 case OSPF_IFTYPE_BROADCAST:
378 case OSPF_IFTYPE_NBMA:
379 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
380 break;
381 default:
382 /* Not supported yet. */ /* XXX */
383 lp->link_type.header.type = htons(0);
384 break;
385 }
386 return;
718e3744 387}
d62a17ae 388
01c9b80a
OD
389static void set_linkparams_link_id(struct mpls_te_link *lp,
390 struct in_addr link_id)
718e3744 391{
718e3744 392
d62a17ae 393 lp->link_id.header.type = htons(TE_LINK_SUBTLV_LINK_ID);
394 lp->link_id.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
01c9b80a 395 lp->link_id.value = link_id;
d62a17ae 396 return;
718e3744 397}
398
d62a17ae 399static void set_linkparams_lclif_ipaddr(struct mpls_te_link *lp,
400 struct in_addr lclif)
16f1b9ee
OD
401{
402
d62a17ae 403 lp->lclif_ipaddr.header.type = htons(TE_LINK_SUBTLV_LCLIF_IPADDR);
404 lp->lclif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
405 lp->lclif_ipaddr.value[0] = lclif;
406 return;
16f1b9ee
OD
407}
408
d62a17ae 409static void set_linkparams_rmtif_ipaddr(struct mpls_te_link *lp,
410 struct in_addr rmtif)
16f1b9ee
OD
411{
412
d62a17ae 413 lp->rmtif_ipaddr.header.type = htons(TE_LINK_SUBTLV_RMTIF_IPADDR);
414 lp->rmtif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
415 lp->rmtif_ipaddr.value[0] = rmtif;
416 return;
16f1b9ee
OD
417}
418
d62a17ae 419static void set_linkparams_te_metric(struct mpls_te_link *lp,
d7c0a89a 420 uint32_t te_metric)
718e3744 421{
d62a17ae 422 lp->te_metric.header.type = htons(TE_LINK_SUBTLV_TE_METRIC);
423 lp->te_metric.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
424 lp->te_metric.value = htonl(te_metric);
425 return;
718e3744 426}
427
d62a17ae 428static void set_linkparams_max_bw(struct mpls_te_link *lp, float fp)
718e3744 429{
d62a17ae 430 lp->max_bw.header.type = htons(TE_LINK_SUBTLV_MAX_BW);
431 lp->max_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
432 lp->max_bw.value = htonf(fp);
433 return;
718e3744 434}
435
d62a17ae 436static void set_linkparams_max_rsv_bw(struct mpls_te_link *lp, float fp)
718e3744 437{
d62a17ae 438 lp->max_rsv_bw.header.type = htons(TE_LINK_SUBTLV_MAX_RSV_BW);
439 lp->max_rsv_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
440 lp->max_rsv_bw.value = htonf(fp);
441 return;
718e3744 442}
443
d62a17ae 444static void set_linkparams_unrsv_bw(struct mpls_te_link *lp, int priority,
445 float fp)
718e3744 446{
d62a17ae 447 /* Note that TLV-length field is the size of array. */
448 lp->unrsv_bw.header.type = htons(TE_LINK_SUBTLV_UNRSV_BW);
449 lp->unrsv_bw.header.length = htons(TE_LINK_SUBTLV_UNRSV_SIZE);
450 lp->unrsv_bw.value[priority] = htonf(fp);
451 return;
718e3744 452}
453
d62a17ae 454static void set_linkparams_rsc_clsclr(struct mpls_te_link *lp,
d7c0a89a 455 uint32_t classcolor)
718e3744 456{
d62a17ae 457 lp->rsc_clsclr.header.type = htons(TE_LINK_SUBTLV_RSC_CLSCLR);
458 lp->rsc_clsclr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
459 lp->rsc_clsclr.value = htonl(classcolor);
460 return;
718e3744 461}
462
d62a17ae 463static void set_linkparams_inter_as(struct mpls_te_link *lp,
d7c0a89a 464 struct in_addr addr, uint32_t as)
16f1b9ee
OD
465{
466
d62a17ae 467 /* Set the Remote ASBR IP address and then the associated AS number */
468 lp->rip.header.type = htons(TE_LINK_SUBTLV_RIP);
469 lp->rip.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
470 lp->rip.value = addr;
16f1b9ee 471
d62a17ae 472 lp->ras.header.type = htons(TE_LINK_SUBTLV_RAS);
473 lp->ras.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
474 lp->ras.value = htonl(as);
2efd7e2b
OD
475
476 /* Set Type & Flooding flag accordingly */
477 lp->type = INTER_AS;
478 if (OspfMplsTE.inter_as == AS)
479 SET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
480 else
481 UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
16f1b9ee
OD
482}
483
d62a17ae 484static void unset_linkparams_inter_as(struct mpls_te_link *lp)
16f1b9ee
OD
485{
486
d62a17ae 487 /* Reset the Remote ASBR IP address and then the associated AS number */
488 lp->rip.header.type = htons(0);
489 lp->rip.header.length = htons(0);
490 lp->rip.value.s_addr = htonl(0);
16f1b9ee 491
d62a17ae 492 lp->ras.header.type = htons(0);
493 lp->ras.header.length = htons(0);
494 lp->ras.value = htonl(0);
2efd7e2b
OD
495
496 /* Reset Type & Flooding flag accordingly */
497 lp->type = STD_TE;
498 UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
16f1b9ee
OD
499}
500
d7c0a89a
QY
501void set_linkparams_llri(struct mpls_te_link *lp, uint32_t local,
502 uint32_t remote)
16f1b9ee
OD
503{
504
d62a17ae 505 lp->llri.header.type = htons(TE_LINK_SUBTLV_LLRI);
506 lp->llri.header.length = htons(TE_LINK_SUBTLV_LLRI_SIZE);
507 lp->llri.local = htonl(local);
508 lp->llri.remote = htonl(remote);
16f1b9ee
OD
509}
510
d62a17ae 511void set_linkparams_lrrid(struct mpls_te_link *lp, struct in_addr local,
512 struct in_addr remote)
16f1b9ee
OD
513{
514
d62a17ae 515 lp->lrrid.header.type = htons(TE_LINK_SUBTLV_LRRID);
516 lp->lrrid.header.length = htons(TE_LINK_SUBTLV_LRRID_SIZE);
517 lp->lrrid.local.s_addr = local.s_addr;
518 lp->lrrid.remote.s_addr = remote.s_addr;
16f1b9ee
OD
519}
520
d7c0a89a
QY
521static void set_linkparams_av_delay(struct mpls_te_link *lp, uint32_t delay,
522 uint8_t anormal)
16f1b9ee 523{
d7c0a89a 524 uint32_t tmp;
d62a17ae 525 /* Note that TLV-length field is the size of array. */
526 lp->av_delay.header.type = htons(TE_LINK_SUBTLV_AV_DELAY);
527 lp->av_delay.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
528 tmp = delay & TE_EXT_MASK;
529 if (anormal)
530 tmp |= TE_EXT_ANORMAL;
531 lp->av_delay.value = htonl(tmp);
532 return;
16f1b9ee
OD
533}
534
d7c0a89a
QY
535static void set_linkparams_mm_delay(struct mpls_te_link *lp, uint32_t low,
536 uint32_t high, uint8_t anormal)
16f1b9ee 537{
d7c0a89a 538 uint32_t tmp;
d62a17ae 539 /* Note that TLV-length field is the size of array. */
540 lp->mm_delay.header.type = htons(TE_LINK_SUBTLV_MM_DELAY);
541 lp->mm_delay.header.length = htons(TE_LINK_SUBTLV_MM_DELAY_SIZE);
542 tmp = low & TE_EXT_MASK;
543 if (anormal)
544 tmp |= TE_EXT_ANORMAL;
545 lp->mm_delay.low = htonl(tmp);
546 lp->mm_delay.high = htonl(high);
547 return;
16f1b9ee
OD
548}
549
d7c0a89a 550static void set_linkparams_delay_var(struct mpls_te_link *lp, uint32_t jitter)
16f1b9ee 551{
d62a17ae 552 /* Note that TLV-length field is the size of array. */
553 lp->delay_var.header.type = htons(TE_LINK_SUBTLV_DELAY_VAR);
554 lp->delay_var.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
555 lp->delay_var.value = htonl(jitter & TE_EXT_MASK);
556 return;
16f1b9ee
OD
557}
558
d7c0a89a
QY
559static void set_linkparams_pkt_loss(struct mpls_te_link *lp, uint32_t loss,
560 uint8_t anormal)
16f1b9ee 561{
d7c0a89a 562 uint32_t tmp;
d62a17ae 563 /* Note that TLV-length field is the size of array. */
564 lp->pkt_loss.header.type = htons(TE_LINK_SUBTLV_PKT_LOSS);
565 lp->pkt_loss.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
566 tmp = loss & TE_EXT_MASK;
567 if (anormal)
568 tmp |= TE_EXT_ANORMAL;
569 lp->pkt_loss.value = htonl(tmp);
570 return;
16f1b9ee
OD
571}
572
d62a17ae 573static void set_linkparams_res_bw(struct mpls_te_link *lp, float fp)
16f1b9ee 574{
d62a17ae 575 /* Note that TLV-length field is the size of array. */
576 lp->res_bw.header.type = htons(TE_LINK_SUBTLV_RES_BW);
577 lp->res_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
578 lp->res_bw.value = htonf(fp);
579 return;
16f1b9ee
OD
580}
581
d62a17ae 582static void set_linkparams_ava_bw(struct mpls_te_link *lp, float fp)
16f1b9ee 583{
d62a17ae 584 /* Note that TLV-length field is the size of array. */
585 lp->ava_bw.header.type = htons(TE_LINK_SUBTLV_AVA_BW);
586 lp->ava_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
587 lp->ava_bw.value = htonf(fp);
588 return;
16f1b9ee
OD
589}
590
d62a17ae 591static void set_linkparams_use_bw(struct mpls_te_link *lp, float fp)
16f1b9ee 592{
d62a17ae 593 /* Note that TLV-length field is the size of array. */
594 lp->use_bw.header.type = htons(TE_LINK_SUBTLV_USE_BW);
595 lp->use_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
596 lp->use_bw.value = htonf(fp);
597 return;
16f1b9ee
OD
598}
599
600/* Update TE parameters from Interface */
d62a17ae 601static void update_linkparams(struct mpls_te_link *lp)
602{
603 int i;
604 struct interface *ifp;
605
606 /* Get the Interface structure */
607 if ((ifp = lp->ifp) == NULL) {
fd3c7692
OD
608 ote_debug(
609 "MPLS-TE (%s): Abort update TE parameters: no interface associated to Link Parameters",
610 __func__);
d62a17ae 611 return;
612 }
613 if (!HAS_LINK_PARAMS(ifp)) {
fd3c7692
OD
614 ote_debug(
615 "MPLS-TE (%s): Abort update TE parameters: no Link Parameters for interface",
616 __func__);
d62a17ae 617 return;
618 }
619
620 /* RFC3630 metrics */
621 if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
622 set_linkparams_rsc_clsclr(lp, ifp->link_params->admin_grp);
623 else
624 TLV_TYPE(lp->rsc_clsclr) = 0;
625
626 if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
627 set_linkparams_max_bw(lp, ifp->link_params->max_bw);
628 else
629 TLV_TYPE(lp->max_bw) = 0;
630
631 if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
632 set_linkparams_max_rsv_bw(lp, ifp->link_params->max_rsv_bw);
633 else
634 TLV_TYPE(lp->max_rsv_bw) = 0;
635
636 if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
637 for (i = 0; i < MAX_CLASS_TYPE; i++)
638 set_linkparams_unrsv_bw(lp, i,
639 ifp->link_params->unrsv_bw[i]);
640 else
641 TLV_TYPE(lp->unrsv_bw) = 0;
642
643 if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
644 set_linkparams_te_metric(lp, ifp->link_params->te_metric);
645 else
646 TLV_TYPE(lp->te_metric) = 0;
647
648 /* TE metric Extensions */
649 if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
650 set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0);
651 else
652 TLV_TYPE(lp->av_delay) = 0;
653
654 if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
655 set_linkparams_mm_delay(lp, ifp->link_params->min_delay,
656 ifp->link_params->max_delay, 0);
657 else
658 TLV_TYPE(lp->mm_delay) = 0;
659
660 if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
661 set_linkparams_delay_var(lp, ifp->link_params->delay_var);
662 else
663 TLV_TYPE(lp->delay_var) = 0;
664
665 if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
666 set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0);
667 else
668 TLV_TYPE(lp->pkt_loss) = 0;
669
670 if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
671 set_linkparams_res_bw(lp, ifp->link_params->res_bw);
672 else
673 TLV_TYPE(lp->res_bw) = 0;
674
675 if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
676 set_linkparams_ava_bw(lp, ifp->link_params->ava_bw);
677 else
678 TLV_TYPE(lp->ava_bw) = 0;
679
680 if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
681 set_linkparams_use_bw(lp, ifp->link_params->use_bw);
682 else
683 TLV_TYPE(lp->use_bw) = 0;
684
685 /* RFC5392 */
686 if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) {
687 /* Flush LSA if it engaged and was previously a STD_TE one */
688 if (IS_STD_TE(lp->type)
689 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
fd3c7692
OD
690 ote_debug(
691 "MPLS-TE (%s): Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]",
692 __func__, ifp->name, lp->flags, lp->type);
d62a17ae 693
694 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
695 /* Then, switch it to INTER-AS */
2efd7e2b
OD
696 if (OspfMplsTE.inter_as == AS) {
697 lp->type = INTER_AS;
698 SET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
699 } else {
700 lp->type = INTER_AS;
701 UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
d62a17ae 702 lp->area = ospf_area_lookup_by_area_id(
b5a8894d 703 ospf_lookup_by_vrf_id(VRF_DEFAULT),
d62a17ae 704 OspfMplsTE.interas_areaid);
705 }
706 }
707 set_linkparams_inter_as(lp, ifp->link_params->rmt_ip,
708 ifp->link_params->rmt_as);
709 } else {
fd3c7692
OD
710 ote_debug(
711 "MPLS-TE (%s): Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]",
712 __func__, ifp->name, lp->flags, lp->type);
d62a17ae 713
714 /* reset inter-as TE params */
715 /* Flush LSA if it engaged and was previously an INTER_AS one */
716 if (IS_INTER_AS(lp->type)
717 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
718 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
719 /* Then, switch it to Standard TE */
2efd7e2b
OD
720 lp->flags = STD_TE;
721 UNSET_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS);
d62a17ae 722 }
723 unset_linkparams_inter_as(lp);
724 }
725}
726
727static void initialize_linkparams(struct mpls_te_link *lp)
728{
729 struct interface *ifp = lp->ifp;
ead99d5f
OD
730 struct ospf_interface *oi = NULL;
731 struct route_node *rn;
d62a17ae 732
f173deb3
OD
733 ote_debug("MPLS-TE (%s): Initialize Link Parameters for interface %s",
734 __func__, ifp->name);
d62a17ae 735
ead99d5f 736 /* Search OSPF Interface parameters for this interface */
996c9314 737 for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
ead99d5f
OD
738
739 if ((oi = rn->info) == NULL)
740 continue;
741
742 if (oi->ifp == ifp)
743 break;
744 }
745
746 if ((oi == NULL) || (oi->ifp != ifp)) {
fd3c7692
OD
747 ote_debug(
748 "MPLS-TE (%s): Could not find corresponding OSPF Interface for %s",
749 __func__, ifp->name);
d62a17ae 750 return;
751 }
752
753 /*
754 * Try to set initial values those can be derived from
755 * zebra-interface information.
756 */
757 set_linkparams_link_type(oi, lp);
758
759 /* Set local IP addr */
760 set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
761
762 /* Set Remote IP addr if Point to Point Interface */
ead99d5f 763 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
d62a17ae 764 struct prefix *pref = CONNECTED_PREFIX(oi->connected);
765 if (pref != NULL)
766 set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
767 }
768
769 /* Keep Area information in combination with link parameters. */
770 lp->area = oi->area;
771
772 return;
773}
774
775static int is_mandated_params_set(struct mpls_te_link *lp)
776{
777 int rc = 0;
778
779 if (ntohs(OspfMplsTE.router_addr.header.type) == 0) {
fd3c7692
OD
780 flog_warn(EC_OSPF_TE_UNEXPECTED,
781 "MPLS-TE (%s): Missing Router Address", __func__);
ead99d5f 782 return rc;
d62a17ae 783 }
784
785 if (ntohs(lp->link_type.header.type) == 0) {
cf444bcf 786 flog_warn(EC_OSPF_TE_UNEXPECTED,
fd3c7692 787 "MPLS-TE (%s): Missing Link Type", __func__);
ead99d5f 788 return rc;
d62a17ae 789 }
790
791 if (!IS_INTER_AS(lp->type) && (ntohs(lp->link_id.header.type) == 0)) {
f173deb3
OD
792 flog_warn(EC_OSPF_TE_UNEXPECTED, "MPLS-TE (%s) Missing Link ID",
793 __func__);
ead99d5f 794 return rc;
d62a17ae 795 }
796
797 rc = 1;
d62a17ae 798 return rc;
718e3744 799}
800
801/*------------------------------------------------------------------------*
78dfa0c7 802 * Following are callback functions against generic Opaque-LSAs handling.
718e3744 803 *------------------------------------------------------------------------*/
804
d62a17ae 805static int ospf_mpls_te_new_if(struct interface *ifp)
718e3744 806{
d62a17ae 807 struct mpls_te_link *new;
718e3744 808
fd3c7692
OD
809 ote_debug("MPLS-TE (%s): Add new %s interface %s to MPLS-TE list",
810 __func__, ifp->link_params ? "Active" : "Inactive",
811 ifp->name);
16f1b9ee 812
2c72cf2a
DS
813 if (lookup_linkparams_by_ifp(ifp) != NULL)
814 return 0;
718e3744 815
d62a17ae 816 new = XCALLOC(MTYPE_OSPF_MPLS_TE, sizeof(struct mpls_te_link));
718e3744 817
d62a17ae 818 new->instance = get_mpls_te_instance_value();
819 new->ifp = ifp;
820 /* By default TE-Link is RFC3630 compatible flooding in Area and not
821 * active */
822 /* This default behavior will be adapted with call to
823 * ospf_mpls_te_update_if() */
2efd7e2b 824 new->type = STD_TE;
d62a17ae 825 new->flags = LPFLG_LSA_INACTIVE;
16f1b9ee 826
d62a17ae 827 /* Initialize Link Parameters from Interface */
828 initialize_linkparams(new);
718e3744 829
d62a17ae 830 /* Set TE Parameters from Interface */
831 update_linkparams(new);
718e3744 832
d62a17ae 833 /* Add Link Parameters structure to the list */
834 listnode_add(OspfMplsTE.iflist, new);
718e3744 835
fd3c7692
OD
836 ote_debug("MPLS-TE (%s): Add new LP context for %s[%d/%d]", __func__,
837 ifp->name, new->flags, new->type);
16f1b9ee 838
d62a17ae 839 /* Schedule Opaque-LSA refresh. */ /* XXX */
2c72cf2a 840 return 0;
718e3744 841}
842
d62a17ae 843static int ospf_mpls_te_del_if(struct interface *ifp)
718e3744 844{
d62a17ae 845 struct mpls_te_link *lp;
846 int rc = -1;
718e3744 847
d62a17ae 848 if ((lp = lookup_linkparams_by_ifp(ifp)) != NULL) {
849 struct list *iflist = OspfMplsTE.iflist;
718e3744 850
d62a17ae 851 /* Dequeue listnode entry from the list. */
852 listnode_delete(iflist, lp);
718e3744 853
d62a17ae 854 XFREE(MTYPE_OSPF_MPLS_TE, lp);
855 }
718e3744 856
d62a17ae 857 /* Schedule Opaque-LSA refresh. */ /* XXX */
718e3744 858
d62a17ae 859 rc = 0;
d62a17ae 860 return rc;
718e3744 861}
862
16f1b9ee
OD
863/* Main initialization / update function of the MPLS TE Link context */
864
865/* Call when interface TE Link parameters are modified */
d62a17ae 866void ospf_mpls_te_update_if(struct interface *ifp)
867{
868 struct mpls_te_link *lp;
869
fd3c7692
OD
870 ote_debug("MPLS-TE (%s): Update LSA parameters for interface %s [%s]",
871 __func__, ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF");
d62a17ae 872
873 /* Get Link context from interface */
874 if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) {
ade6974d 875 flog_warn(
cf444bcf 876 EC_OSPF_TE_UNEXPECTED,
fd3c7692
OD
877 "MPLS-TE (%s): Did not find Link Parameters context for interface %s",
878 __func__, ifp->name);
d62a17ae 879 return;
880 }
881
882 /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */
883 if (HAS_LINK_PARAMS(ifp)) {
884 SET_FLAG(lp->flags, LPFLG_LSA_ACTIVE);
885
886 /* Update TE parameters */
887 update_linkparams(lp);
888
889 /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is
890 * enabled */
32ab5cf4 891 if (OspfMplsTE.enabled)
d62a17ae 892 if (lp->area != NULL) {
32ab5cf4 893 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
996c9314
LB
894 ospf_mpls_te_lsa_schedule(
895 lp, REFRESH_THIS_LSA);
32ab5cf4 896 else
996c9314
LB
897 ospf_mpls_te_lsa_schedule(
898 lp, REORIGINATE_THIS_LSA);
d62a17ae 899 }
900 } else {
901 /* If MPLS TE is disable on this interface, flush LSA if it is
902 * already engaged */
32ab5cf4
OD
903 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
904 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
d62a17ae 905 else
906 /* Reset Activity flag */
907 lp->flags = LPFLG_LSA_INACTIVE;
908 }
909
910 return;
911}
912
01c9b80a
OD
913/*
914 * Just add interface and set available information. Other information
915 * and flooding of LSA will be done later when adjacency will be up
916 * See ospf_mpls_te_nsm_change() after
917 */
d62a17ae 918static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
919{
01c9b80a 920
d62a17ae 921 struct mpls_te_link *lp;
922
01c9b80a
OD
923 lp = lookup_linkparams_by_ifp(oi->ifp);
924 if (lp == NULL) {
ade6974d 925 flog_warn(
cf444bcf 926 EC_OSPF_TE_UNEXPECTED,
01c9b80a
OD
927 "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
928 __func__, IF_NAME(oi));
ead99d5f 929 return;
d62a17ae 930 }
931
932 if (oi->area == NULL || oi->area->ospf == NULL) {
ade6974d 933 flog_warn(
cf444bcf 934 EC_OSPF_TE_UNEXPECTED,
01c9b80a
OD
935 "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
936 __func__, IF_NAME(oi));
ead99d5f 937 return;
d62a17ae 938 }
01c9b80a 939
d62a17ae 940 /* Keep Area information in combination with linkparams. */
941 lp->area = oi->area;
942
d62a17ae 943 switch (oi->state) {
944 case ISM_PointToPoint:
945 case ISM_DROther:
946 case ISM_Backup:
947 case ISM_DR:
01c9b80a 948 /* Set Link type and Local IP addr */
d62a17ae 949 set_linkparams_link_type(oi, lp);
d62a17ae 950 set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
951
d62a17ae 952 break;
50ec09db
OD
953 case ISM_Down:
954 /* Interface goes Down: Flush LSA if engaged */
955 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
956 ote_debug(
957 "MPLS-TE (%s): Interface %s goes down: flush LSA",
958 __func__, IF_NAME(oi));
32ab5cf4 959 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
50ec09db
OD
960 return;
961 }
962 break;
963 default:
d62a17ae 964 break;
965 }
718e3744 966
fd3c7692
OD
967 ote_debug("MPLS-TE (%s): Update Link parameters for interface %s",
968 __func__, IF_NAME(oi));
01c9b80a 969
d62a17ae 970 return;
718e3744 971}
972
01c9b80a
OD
973/*
974 * Complete TE info and schedule LSA flooding
975 * Link-ID and Remote IP address must be set with neighbor info
976 * which are only valid once NSM state is FULL
977 */
d62a17ae 978static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state)
718e3744 979{
01c9b80a
OD
980 struct ospf_interface *oi = nbr->oi;
981 struct mpls_te_link *lp;
982
983 /* Process Neighbor only when its state is NSM Full */
984 if (nbr->state != NSM_Full)
985 return;
986
987 /* Get interface information for Traffic Engineering */
988 lp = lookup_linkparams_by_ifp(oi->ifp);
989 if (lp == NULL) {
990 flog_warn(
991 EC_OSPF_TE_UNEXPECTED,
992 "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
993 __func__, IF_NAME(oi));
994 return;
995 }
996
997 if (oi->area == NULL || oi->area->ospf == NULL) {
998 flog_warn(
999 EC_OSPF_TE_UNEXPECTED,
1000 "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
1001 __func__, IF_NAME(oi));
1002 return;
1003 }
1004
50ec09db
OD
1005 /* Flush TE Opaque LSA if Neighbor State goes Down or Deleted */
1006 if (OspfMplsTE.enabled
1007 && (nbr->state == NSM_Down || nbr->state == NSM_Deleted)) {
1008 if (CHECK_FLAG(lp->flags, EXT_LPFLG_LSA_ENGAGED)) {
1009 ote_debug(
1010 "MPLS-TE (%s): Interface %s goes down: flush LSA",
1011 __func__, IF_NAME(oi));
1012 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
1013 }
1014 return;
1015 }
1016
01c9b80a
OD
1017 /* Keep Area information in combination with SR info. */
1018 lp->area = oi->area;
1019
01c9b80a
OD
1020 /*
1021 * The Link ID is identical to the contents of the Link ID field
1022 * in the Router LSA for these link types.
1023 */
1024 switch (oi->state) {
1025 case ISM_PointToPoint:
1026 /* Set Link ID with neighbor Router ID */
1027 set_linkparams_link_id(lp, nbr->router_id);
1028 /* Set Remote IP address */
1029 set_linkparams_rmtif_ipaddr(lp, nbr->address.u.prefix4);
1030 break;
1031
1032 case ISM_DR:
1033 case ISM_DROther:
1034 case ISM_Backup:
1035 /* Set Link ID with the Designated Router ID */
1036 set_linkparams_link_id(lp, DR(oi));
1037 break;
1038
50ec09db
OD
1039 case ISM_Down:
1040 /* State goes Down: Flush LSA if engaged */
f173deb3
OD
1041 if (OspfMplsTE.enabled
1042 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
50ec09db
OD
1043 ote_debug(
1044 "MPLS-TE (%s): Interface %s goes down: flush LSA",
1045 __func__, IF_NAME(oi));
01c9b80a 1046 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
50ec09db 1047 }
01c9b80a 1048 return;
50ec09db
OD
1049 default:
1050 break;
01c9b80a
OD
1051 }
1052
fd3c7692
OD
1053 ote_debug("MPLS-TE (%s): Add Link-ID %pI4 for interface %s ", __func__,
1054 &lp->link_id.value, oi->ifp->name);
01c9b80a
OD
1055
1056 /* Try to Schedule LSA */
1057 if (OspfMplsTE.enabled) {
1058 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
1059 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
1060 else
1061 ospf_mpls_te_lsa_schedule(lp, REORIGINATE_THIS_LSA);
1062 }
d62a17ae 1063 return;
718e3744 1064}
1065
1066/*------------------------------------------------------------------------*
78dfa0c7 1067 * Following are OSPF protocol processing functions for MPLS-TE LSA.
718e3744 1068 *------------------------------------------------------------------------*/
1069
ead99d5f 1070static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
d62a17ae 1071{
ead99d5f 1072 stream_put(s, tlvh, sizeof(struct tlv_header));
d62a17ae 1073 return;
1074}
1075
1076static void build_router_tlv(struct stream *s)
1077{
ead99d5f 1078 struct tlv_header *tlvh = &OspfMplsTE.router_addr.header;
d62a17ae 1079 if (ntohs(tlvh->type) != 0) {
1080 build_tlv_header(s, tlvh);
5d0df50f 1081 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
d62a17ae 1082 }
1083 return;
1084}
1085
ead99d5f 1086static void build_link_subtlv(struct stream *s, struct tlv_header *tlvh)
d62a17ae 1087{
1088
1089 if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) {
1090 build_tlv_header(s, tlvh);
5d0df50f 1091 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
d62a17ae 1092 }
1093 return;
1094}
1095
1096static void build_link_tlv(struct stream *s, struct mpls_te_link *lp)
1097{
1098 set_linkparams_link_header(lp);
1099 build_tlv_header(s, &lp->link_header.header);
1100
1101 build_link_subtlv(s, &lp->link_type.header);
1102 build_link_subtlv(s, &lp->link_id.header);
1103 build_link_subtlv(s, &lp->lclif_ipaddr.header);
1104 build_link_subtlv(s, &lp->rmtif_ipaddr.header);
1105 build_link_subtlv(s, &lp->te_metric.header);
1106 build_link_subtlv(s, &lp->max_bw.header);
1107 build_link_subtlv(s, &lp->max_rsv_bw.header);
1108 build_link_subtlv(s, &lp->unrsv_bw.header);
1109 build_link_subtlv(s, &lp->rsc_clsclr.header);
1110 build_link_subtlv(s, &lp->lrrid.header);
1111 build_link_subtlv(s, &lp->llri.header);
1112 build_link_subtlv(s, &lp->rip.header);
1113 build_link_subtlv(s, &lp->ras.header);
1114 build_link_subtlv(s, &lp->av_delay.header);
1115 build_link_subtlv(s, &lp->mm_delay.header);
1116 build_link_subtlv(s, &lp->delay_var.header);
1117 build_link_subtlv(s, &lp->pkt_loss.header);
1118 build_link_subtlv(s, &lp->res_bw.header);
1119 build_link_subtlv(s, &lp->ava_bw.header);
1120 build_link_subtlv(s, &lp->use_bw.header);
1121
1122 return;
1123}
1124
1125static void ospf_mpls_te_lsa_body_set(struct stream *s, struct mpls_te_link *lp)
1126{
1127 /*
2efd7e2b
OD
1128 * The router address TLV is type 1, and ... It must appear in exactly
1129 * one Traffic Engineering LSA originated by a router but not in
1130 * Inter-AS TLV.
d62a17ae 1131 */
2efd7e2b
OD
1132 if (!IS_INTER_AS(lp->type))
1133 build_router_tlv(s);
d62a17ae 1134
1135 /*
1136 * Only one Link TLV shall be carried in each LSA, allowing for fine
1137 * granularity changes in topology.
1138 */
1139 build_link_tlv(s, lp);
1140 return;
718e3744 1141}
1142
1143/* Create new opaque-LSA. */
b5a8894d
CS
1144static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
1145 struct ospf_area *area,
d62a17ae 1146 struct mpls_te_link *lp)
1147{
1148 struct stream *s;
1149 struct lsa_header *lsah;
1150 struct ospf_lsa *new = NULL;
d7c0a89a 1151 uint8_t options, lsa_type = 0;
d62a17ae 1152 struct in_addr lsa_id;
d7c0a89a
QY
1153 uint32_t tmp;
1154 uint16_t length;
d62a17ae 1155
1156 /* Create a stream for LSA. */
266469eb 1157 s = stream_new(OSPF_MAX_LSA_SIZE);
d62a17ae 1158 lsah = (struct lsa_header *)STREAM_DATA(s);
1159
1160 options = OSPF_OPTION_O; /* Don't forget this :-) */
1161
1162 /* Set opaque-LSA header fields depending of the type of RFC */
1163 if (IS_INTER_AS(lp->type)) {
2efd7e2b 1164 if (IS_FLOOD_AS(lp->flags)) {
72c03801
QY
1165 /* Enable AS external as we flood Inter-AS with Opaque
1166 * Type 11
1167 */
1168 options |= OSPF_OPTION_E;
1169 lsa_type = OSPF_OPAQUE_AS_LSA;
1170 } else {
d62a17ae 1171 options |= LSA_OPTIONS_GET(
1172 area); /* Get area default option */
1173 options |= LSA_OPTIONS_NSSA_GET(area);
1174 lsa_type = OSPF_OPAQUE_AREA_LSA;
1175 }
1176 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1177 lsa_id.s_addr = htonl(tmp);
1178
0760d3c9
DS
1179 if (!ospf) {
1180 stream_free(s);
b5a8894d 1181 return NULL;
0760d3c9 1182 }
d62a17ae 1183
b5a8894d 1184 lsa_header_set(s, options, lsa_type, lsa_id, ospf->router_id);
d62a17ae 1185 } else {
1186 options |= LSA_OPTIONS_GET(area); /* Get area default option */
1187 options |= LSA_OPTIONS_NSSA_GET(area);
1188 lsa_type = OSPF_OPAQUE_AREA_LSA;
1189 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
1190 lp->instance);
1191 lsa_id.s_addr = htonl(tmp);
1192 lsa_header_set(s, options, lsa_type, lsa_id,
1193 area->ospf->router_id);
1194 }
1195
fd3c7692 1196 ote_debug(
50ec09db 1197 "MPLS-TE (%s): LSA[Type%d:%pI4]: Create an Opaque-LSA/MPLS-TE instance",
fd3c7692 1198 __func__, lsa_type, &lsa_id);
d62a17ae 1199
1200 /* Set opaque-LSA body fields. */
1201 ospf_mpls_te_lsa_body_set(s, lp);
1202
1203 /* Set length. */
1204 length = stream_get_endp(s);
1205 lsah->length = htons(length);
1206
1207 /* Now, create an OSPF LSA instance. */
5b3d4186 1208 new = ospf_lsa_new_and_data(length);
d62a17ae 1209
1210 new->area = area;
30ce6361
OD
1211 new->vrf_id = VRF_DEFAULT;
1212
d62a17ae 1213 SET_FLAG(new->flags, OSPF_LSA_SELF);
1214 memcpy(new->data, lsah, length);
1215 stream_free(s);
718e3744 1216
d62a17ae 1217 return new;
1218}
1219
1220static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
1221 struct mpls_te_link *lp)
1222{
b5a8894d 1223 struct ospf_lsa *new = NULL;
d62a17ae 1224 int rc = -1;
1225
1226 /* Create new Opaque-LSA/MPLS-TE instance. */
b5a8894d
CS
1227 new = ospf_mpls_te_lsa_new(area->ospf, area, lp);
1228 if (new == NULL) {
fd3c7692
OD
1229 flog_warn(EC_OSPF_TE_UNEXPECTED,
1230 "MPLS-TE (%s): ospf_mpls_te_lsa_new() ?", __func__);
ead99d5f 1231 return rc;
d62a17ae 1232 }
1233
1234 /* Install this LSA into LSDB. */
1235 if (ospf_lsa_install(area->ospf, NULL /*oi*/, new) == NULL) {
cf444bcf 1236 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
fd3c7692 1237 "MPLS-TE (%s): ospf_lsa_install() ?", __func__);
d62a17ae 1238 ospf_lsa_unlock(&new);
ead99d5f 1239 return rc;
d62a17ae 1240 }
1241
1242 /* Now this link-parameter entry has associated LSA. */
1243 SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
1244 /* Update new LSA origination count. */
1245 area->ospf->lsa_originate_count++;
1246
1247 /* Flood new LSA through area. */
1248 ospf_flood_through_area(area, NULL /*nbr*/, new);
1249
fd3c7692
OD
1250 ote_debug(
1251 "MPLS-TE (%s): LSA[Type%d:%pI4]: Originate Opaque-LSA/MPLS-TE: Area(%pI4), Link(%s)",
1252 __func__, new->data->type, &new->data->id, &area->area_id,
1253 lp->ifp->name);
1254 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
d62a17ae 1255 ospf_lsa_header_dump(new->data);
d62a17ae 1256
1257 rc = 0;
d62a17ae 1258 return rc;
1259}
1260
1261static int ospf_mpls_te_lsa_originate_area(void *arg)
1262{
1263 struct ospf_area *area = (struct ospf_area *)arg;
1264 struct listnode *node, *nnode;
1265 struct mpls_te_link *lp;
1266 int rc = -1;
1267
32ab5cf4 1268 if (!OspfMplsTE.enabled) {
fd3c7692 1269 ote_debug("MPLS-TE (%s): MPLS-TE is disabled now.", __func__);
d62a17ae 1270 rc = 0; /* This is not an error case. */
ead99d5f 1271 return rc;
d62a17ae 1272 }
1273
1274 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
1275 /* Process only enabled LSA with area scope flooding */
1276 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
2efd7e2b 1277 || IS_FLOOD_AS(lp->flags))
d62a17ae 1278 continue;
1279
1280 if (lp->area == NULL)
1281 continue;
1282
1283 if (!IPV4_ADDR_SAME(&lp->area->area_id, &area->area_id))
1284 continue;
1285
32ab5cf4
OD
1286 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
1287 if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
1288 UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
fd3c7692
OD
1289 ote_debug(
1290 "MPLS-TE (%s): Refresh instead of Originate",
1291 __func__);
32ab5cf4 1292 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
d62a17ae 1293 }
32ab5cf4
OD
1294 continue;
1295 }
1296
d62a17ae 1297 if (!is_mandated_params_set(lp)) {
fd3c7692
OD
1298 ote_debug(
1299 "MPLS-TE (%s): Link(%s) lacks some mandated MPLS-TE parameters.",
1300 __func__, lp->ifp ? lp->ifp->name : "?");
d62a17ae 1301 continue;
1302 }
1303
1304 /* Ok, let's try to originate an LSA for this area and Link. */
fd3c7692
OD
1305 ote_debug(
1306 "MPLS-TE (%s): Let's finally reoriginate the LSA %d through the Area %pI4 for Link %s",
1307 __func__, lp->instance, &area->area_id,
1308 lp->ifp ? lp->ifp->name : "?");
d62a17ae 1309 if (ospf_mpls_te_lsa_originate1(area, lp) != 0)
ead99d5f 1310 return rc;
d62a17ae 1311 }
1312
1313 rc = 0;
d62a17ae 1314 return rc;
1315}
718e3744 1316
d62a17ae 1317static int ospf_mpls_te_lsa_originate2(struct ospf *top,
1318 struct mpls_te_link *lp)
1319{
1320 struct ospf_lsa *new;
1321 int rc = -1;
1322
1323 /* Create new Opaque-LSA/Inter-AS instance. */
b5a8894d
CS
1324 new = ospf_mpls_te_lsa_new(top, NULL, lp);
1325 if (new == NULL) {
fd3c7692
OD
1326 flog_warn(EC_OSPF_LSA_UNEXPECTED,
1327 "MPLS-TE (%s): ospf_router_info_lsa_new() ?",
1328 __func__);
ead99d5f 1329 return rc;
d62a17ae 1330 }
1331
1332 /* Install this LSA into LSDB. */
1333 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
cf444bcf 1334 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
fd3c7692 1335 "MPLS-TE (%s): ospf_lsa_install() ?", __func__);
d62a17ae 1336 ospf_lsa_unlock(&new);
ead99d5f 1337 return rc;
d62a17ae 1338 }
1339
1340 /* Now this Router Info parameter entry has associated LSA. */
1341 SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
1342 /* Update new LSA origination count. */
1343 top->lsa_originate_count++;
1344
1345 /* Flood new LSA through AS. */
1346 ospf_flood_through_as(top, NULL /*nbr */, new);
1347
fd3c7692
OD
1348 ote_debug(
1349 "MPLS-TE (%s): LSA[Type%d:%pI4]: Originate Opaque-LSA/MPLS-TE Inter-AS",
1350 __func__, new->data->type, &new->data->id);
1351 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
d62a17ae 1352 ospf_lsa_header_dump(new->data);
fd3c7692 1353
d62a17ae 1354
1355 rc = 0;
d62a17ae 1356 return rc;
1357}
1358
1359static int ospf_mpls_te_lsa_originate_as(void *arg)
1360{
1361 struct ospf *top;
1362 struct ospf_area *area;
1363 struct listnode *node, *nnode;
1364 struct mpls_te_link *lp;
1365 int rc = -1;
1366
996c9314 1367 if ((!OspfMplsTE.enabled) || (OspfMplsTE.inter_as == Off)) {
fd3c7692
OD
1368 ote_debug("MPLS-TE (%s): Inter-AS is disabled for now",
1369 __func__);
d62a17ae 1370 rc = 0; /* This is not an error case. */
ead99d5f 1371 return rc;
d62a17ae 1372 }
1373
1374 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
1375 /* Process only enabled INTER_AS Links or Pseudo-Links */
1376 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
2efd7e2b 1377 || !CHECK_FLAG(lp->flags, LPFLG_LSA_FLOOD_AS)
d62a17ae 1378 || !IS_INTER_AS(lp->type))
1379 continue;
1380
32ab5cf4
OD
1381 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
1382 if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
996c9314 1383 UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
32ab5cf4 1384 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
d62a17ae 1385 }
32ab5cf4
OD
1386 continue;
1387 }
1388
d62a17ae 1389 if (!is_mandated_params_set(lp)) {
ade6974d 1390 flog_warn(
cf444bcf 1391 EC_OSPF_TE_UNEXPECTED,
fd3c7692
OD
1392 "MPLS-TE (%s): Link(%s) lacks some mandated MPLS-TE parameters.",
1393 __func__, lp->ifp ? lp->ifp->name : "?");
d62a17ae 1394 continue;
1395 }
1396
1397 /* Ok, let's try to originate an LSA for this AS and Link. */
fd3c7692
OD
1398 ote_debug(
1399 "MPLS-TE (%s): Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s",
1400 __func__, lp->instance,
2efd7e2b 1401 IS_FLOOD_AS(lp->flags) ? "AS" : "Area",
fd3c7692 1402 lp->ifp ? lp->ifp->name : "Unknown");
d62a17ae 1403
2efd7e2b 1404 if (IS_FLOOD_AS(lp->flags)) {
d62a17ae 1405 top = (struct ospf *)arg;
1406 ospf_mpls_te_lsa_originate2(top, lp);
1407 } else {
1408 area = (struct ospf_area *)arg;
1409 ospf_mpls_te_lsa_originate1(area, lp);
1410 }
1411 }
1412
1413 rc = 0;
d62a17ae 1414 return rc;
1415}
1416
2efd7e2b
OD
1417/*
1418 * As Inter-AS LSA must be registered with both AREA and AS flooding, and
1419 * because all origination callback functions are call (disregarding the Opaque
1420 * LSA type and Flooding scope) it is necessary to determine which flooding
1421 * scope is associated with the LSA origination as parameter is of type void and
1422 * must be cast to struct *ospf for AS flooding and to struct *ospf_area for
1423 * Area flooding.
1424 */
1425static int ospf_mpls_te_lsa_inter_as_as(void *arg)
1426{
1427 if (OspfMplsTE.inter_as == AS)
1428 return ospf_mpls_te_lsa_originate_as(arg);
1429 else
1430 return 0;
1431}
1432
1433static int ospf_mpls_te_lsa_inter_as_area(void *arg)
1434{
1435 if (OspfMplsTE.inter_as == Area)
1436 return ospf_mpls_te_lsa_originate_area(arg);
1437 else
1438 return 0;
1439}
1440
d62a17ae 1441static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
1442{
1443 struct mpls_te_link *lp;
1444 struct ospf_area *area = lsa->area;
1445 struct ospf *top;
1446 struct ospf_lsa *new = NULL;
1447
32ab5cf4 1448 if (!OspfMplsTE.enabled) {
d62a17ae 1449 /*
1450 * This LSA must have flushed before due to MPLS-TE status
1451 * change.
1452 * It seems a slip among routers in the routing domain.
1453 */
fd3c7692 1454 ote_debug("MPLS-TE (%s): MPLS-TE is disabled now", __func__);
d62a17ae 1455 lsa->data->ls_age =
1456 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1457 }
1458
1459 /* At first, resolve lsa/lp relationship. */
1460 if ((lp = lookup_linkparams_by_instance(lsa)) == NULL) {
cf444bcf 1461 flog_warn(EC_OSPF_TE_UNEXPECTED,
fd3c7692 1462 "MPLS-TE (%s): Invalid parameter?", __func__);
d62a17ae 1463 lsa->data->ls_age =
1464 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
20a7c80c
DS
1465 ospf_opaque_lsa_flush_schedule(lsa);
1466 return NULL;
d62a17ae 1467 }
1468
1469 /* Check if lp was not disable in the interval */
1470 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)) {
fd3c7692
OD
1471 flog_warn(EC_OSPF_TE_UNEXPECTED,
1472 "MPLS-TE (%s): lp was disabled: Flush it!", __func__);
d62a17ae 1473 lsa->data->ls_age =
1474 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1475 }
1476
1477 /* If the lsa's age reached to MaxAge, start flushing procedure. */
1478 if (IS_LSA_MAXAGE(lsa)) {
20a7c80c 1479 UNSET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
d62a17ae 1480 ospf_opaque_lsa_flush_schedule(lsa);
ead99d5f 1481 return NULL;
d62a17ae 1482 }
30ce6361 1483 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1484 /* Create new Opaque-LSA/MPLS-TE instance. */
b5a8894d
CS
1485 new = ospf_mpls_te_lsa_new(top, area, lp);
1486 if (new == NULL) {
cf444bcf 1487 flog_warn(EC_OSPF_TE_UNEXPECTED,
fd3c7692 1488 "MPLS-TE (%s): ospf_mpls_te_lsa_new() ?", __func__);
ead99d5f 1489 return NULL;
d62a17ae 1490 }
1491 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1492
1493 /* Install this LSA into LSDB. */
1494 /* Given "lsa" will be freed in the next function. */
1495 /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use
1496 * ospf_lookup() to get ospf instance */
1497 if (area)
1498 top = area->ospf;
d62a17ae 1499
1500 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
cf444bcf 1501 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
fd3c7692 1502 "MPLS-TE (%s): ospf_lsa_install() ?", __func__);
d62a17ae 1503 ospf_lsa_unlock(&new);
ead99d5f 1504 return NULL;
d62a17ae 1505 }
1506
1507 /* Flood updated LSA through AS or Area depending of the RFC of the link
1508 */
2efd7e2b 1509 if (IS_FLOOD_AS(lp->flags))
d62a17ae 1510 ospf_flood_through_as(top, NULL, new);
1511 else
1512 ospf_flood_through_area(area, NULL /*nbr*/, new);
1513
1514 /* Debug logging. */
fd3c7692
OD
1515 ote_debug("MPLS-TE (%s): LSA[Type%d:%pI4]: Refresh Opaque-LSA/MPLS-TE",
1516 __func__, new->data->type, &new->data->id);
1517 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
d62a17ae 1518 ospf_lsa_header_dump(new->data);
d62a17ae 1519
d62a17ae 1520 return new;
1521}
1522
2a39170c 1523void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, enum lsa_opcode opcode)
d62a17ae 1524{
1525 struct ospf_lsa lsa;
1526 struct lsa_header lsah;
1527 struct ospf *top;
d7c0a89a 1528 uint32_t tmp;
d62a17ae 1529
1530 memset(&lsa, 0, sizeof(lsa));
1531 memset(&lsah, 0, sizeof(lsah));
b5a8894d 1532 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1533
1534 /* Check if the pseudo link is ready to flood */
2efd7e2b 1535 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE))
d62a17ae 1536 return;
d62a17ae 1537
f173deb3
OD
1538 ote_debug("MPLS-TE (%s): Schedule %s%s%s LSA for interface %s",
1539 __func__,
fd3c7692
OD
1540 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1541 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1542 opcode == FLUSH_THIS_LSA ? "Flush" : "",
1543 lp->ifp ? lp->ifp->name : "-");
1544
d62a17ae 1545 lsa.area = lp->area;
1546 lsa.data = &lsah;
2efd7e2b 1547 if (IS_FLOOD_AS(lp->flags)) {
d62a17ae 1548 lsah.type = OSPF_OPAQUE_AS_LSA;
1549 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1550 lsah.id.s_addr = htonl(tmp);
1551 } else {
1552 lsah.type = OSPF_OPAQUE_AREA_LSA;
1553 if (IS_INTER_AS(lp->type)) {
1554 /* Set the area context if not know */
1555 if (lp->area == NULL)
1556 lp->area = ospf_area_lookup_by_area_id(
1557 top, OspfMplsTE.interas_areaid);
1558 /* Unable to set the area context. Abort! */
1559 if (lp->area == NULL) {
ade6974d 1560 flog_warn(
cf444bcf 1561 EC_OSPF_TE_UNEXPECTED,
fd3c7692
OD
1562 "MPLS-TE (%s): Area context is null. Abort !",
1563 __func__);
d62a17ae 1564 return;
1565 }
1566 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA,
1567 lp->instance);
1568 } else
1569 tmp = SET_OPAQUE_LSID(
1570 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
1571 lp->instance);
1572 lsah.id.s_addr = htonl(tmp);
1573 }
1574
1575 switch (opcode) {
1576 case REORIGINATE_THIS_LSA:
2efd7e2b 1577 if (IS_FLOOD_AS(lp->flags)) {
d62a17ae 1578 ospf_opaque_lsa_reoriginate_schedule(
1579 (void *)top, OSPF_OPAQUE_AS_LSA,
1580 OPAQUE_TYPE_INTER_AS_LSA);
2efd7e2b 1581 } else {
d62a17ae 1582 if (IS_INTER_AS(lp->type))
1583 ospf_opaque_lsa_reoriginate_schedule(
1584 (void *)lp->area, OSPF_OPAQUE_AREA_LSA,
1585 OPAQUE_TYPE_INTER_AS_LSA);
1586 else
1587 ospf_opaque_lsa_reoriginate_schedule(
1588 (void *)lp->area, OSPF_OPAQUE_AREA_LSA,
1589 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
d62a17ae 1590 }
1591 break;
1592 case REFRESH_THIS_LSA:
1593 ospf_opaque_lsa_refresh_schedule(&lsa);
1594 break;
1595 case FLUSH_THIS_LSA:
1596 /* Reset Activity flag */
1597 lp->flags = LPFLG_LSA_INACTIVE;
1598 ospf_opaque_lsa_flush_schedule(&lsa);
1599 break;
1600 default:
cf444bcf 1601 flog_warn(EC_OSPF_TE_UNEXPECTED,
fd3c7692 1602 "MPLS-TE (%s): Unknown opcode (%u)", __func__,
d62a17ae 1603 opcode);
1604 break;
1605 }
718e3744 1606}
1607
f173deb3
OD
1608/**
1609 * ------------------------------------------------------
78dfa0c7 1610 * Following are Link State Data Base control functions.
f173deb3
OD
1611 * ------------------------------------------------------
1612 */
718e3744 1613
f173deb3
OD
1614/**
1615 * Get Vertex from TED by the router which advertised the LSA. A new Vertex and
1616 * associated Link State Node are created if Vertex is not found.
1617 *
1618 * @param ted Link State Traffic Engineering Database
1619 * @param lsa OSPF Link State Advertisement
1620 *
1621 * @return Link State Vertex
1622 */
1623static struct ls_vertex *get_vertex(struct ls_ted *ted, struct ospf_lsa *lsa)
718e3744 1624{
f173deb3
OD
1625 struct ls_node_id lnid;
1626 struct ls_node *lnode;
1627 struct ls_vertex *vertex;
718e3744 1628
f173deb3
OD
1629 /* Sanity Check */
1630 if (!ted || !lsa || !lsa->data || !lsa->area)
1631 return NULL;
718e3744 1632
f173deb3
OD
1633 /* Search if a Link State Vertex already exist */
1634 lnid.origin = OSPFv2;
1635 lnid.id.ip.addr = lsa->data->adv_router;
1636 lnid.id.ip.area_id = lsa->area->area_id;
1637 vertex = ls_find_vertex_by_id(ted, lnid);
1638
1639 /* Create Node & Vertex in the Link State Date Base if not found */
1640 if (!vertex) {
1641 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
1642
1643 lnode = ls_node_new(lnid, inaddr_any, in6addr_any);
1644 snprintfrr(lnode->name, MAX_NAME_LENGTH, "%pI4",
1645 &lnid.id.ip.addr);
1646 vertex = ls_vertex_add(ted, lnode);
1647 }
1648
1649 if (IS_LSA_SELF(lsa))
1650 ted->self = vertex;
1651
1652 return vertex;
718e3744 1653}
1654
f173deb3
OD
1655/**
1656 * Get Edge from TED by Link State Attribute ID. A new Edge and associated Link
1657 * State Attributes are created if not found.
1658 *
1659 * @param ted Link State Traffic Engineering Database
1660 * @param adv Link State Node ID of router which advertised Edge
1661 * @param link_id Link State Attribute ID
1662 *
1663 * @return Link State Edge
1664 */
1665static struct ls_edge *get_edge(struct ls_ted *ted, struct ls_node_id adv,
1666 struct in_addr link_id)
718e3744 1667{
f173deb3
OD
1668 uint64_t key;
1669 struct ls_edge *edge;
1670 struct ls_attributes *attr;
1671
1672 /* Search Edge that corresponds to the Link ID */
1673 key = ((uint64_t)ntohl(link_id.s_addr)) & 0xffffffff;
1674 edge = ls_find_edge_by_key(ted, key);
1675
1676 /* Create new one if not exist */
1677 if (!edge) {
1678 attr = ls_attributes_new(adv, link_id, in6addr_any, 0);
1679 edge = ls_edge_add(ted, attr);
1680 }
718e3744 1681
f173deb3 1682 return edge;
718e3744 1683}
1684
f173deb3
OD
1685/**
1686 * Export Link State information to consumer daemon through ZAPI Link State
1687 * Opaque Message.
1688 *
1689 * @param type Type of Link State Element i.e. Vertex, Edge or Subnet
1690 * @param link_state Pointer to Link State Vertex, Edge or Subnet
1691 *
1692 * @return 0 if success, -1 otherwise
1693 */
1694static int ospf_te_export(uint8_t type, void *link_state)
718e3744 1695{
f173deb3
OD
1696 struct ls_message msg = {};
1697 int rc = 0;
718e3744 1698
f173deb3
OD
1699 if (!OspfMplsTE.export)
1700 return rc;
1701
1702 switch (type) {
1703 case LS_MSG_TYPE_NODE:
1704 ls_vertex2msg(&msg, (struct ls_vertex *)link_state);
1705 rc = ls_send_msg(zclient, &msg, NULL);
d62a17ae 1706 break;
f173deb3
OD
1707 case LS_MSG_TYPE_ATTRIBUTES:
1708 ls_edge2msg(&msg, (struct ls_edge *)link_state);
1709 rc = ls_send_msg(zclient, &msg, NULL);
1710 break;
1711 case LS_MSG_TYPE_PREFIX:
1712 ls_subnet2msg(&msg, (struct ls_subnet *)link_state);
1713 rc = ls_send_msg(zclient, &msg, NULL);
d62a17ae 1714 break;
1715 default:
f173deb3 1716 rc = -1;
d62a17ae 1717 break;
1718 }
718e3744 1719
f173deb3 1720 return rc;
718e3744 1721}
1722
f173deb3
OD
1723/**
1724 * Update Link State Edge & Attributes from the given Link State Attributes ID
1725 * and metric. This function is called when parsing Router LSA.
1726 *
1727 * @param ted Link State Traffic Engineering Database
1728 * @param vertex Vertex where the Edge is attached as source
1729 * @param link_data Link State Edge ID
1730 * @param metric Standard metric attached to this Edge
1731 */
1732static void ospf_te_update_link(struct ls_ted *ted, struct ls_vertex *vertex,
1733 struct in_addr link_data, uint8_t metric)
718e3744 1734{
f173deb3
OD
1735 struct ls_edge *edge;
1736 struct ls_attributes *attr;
718e3744 1737
f173deb3
OD
1738 /* Sanity check */
1739 if (!ted || !vertex || !vertex->node)
1740 return;
718e3744 1741
f173deb3
OD
1742 /* Get Corresponding Edge from Link State Data Base */
1743 edge = get_edge(ted, vertex->node->adv, link_data);
1744 attr = edge->attributes;
718e3744 1745
f173deb3
OD
1746 /* re-attached edge to vertex if needed */
1747 if (!edge->source)
1748 edge->source = vertex;
718e3744 1749
f173deb3
OD
1750 /* Check if it is just an LSA refresh */
1751 if ((CHECK_FLAG(attr->flags, LS_ATTR_METRIC)
1752 && (attr->metric == metric))) {
1753 edge->status = SYNC;
1754 return;
1755 }
718e3744 1756
f173deb3
OD
1757 /* Update metric value */
1758 attr->metric = metric;
1759 SET_FLAG(attr->flags, LS_ATTR_METRIC);
1760 if (edge->status != NEW)
1761 edge->status = UPDATE;
718e3744 1762
f173deb3
OD
1763 ote_debug(" |- %s Edge %pI4 with metric %d",
1764 edge->status == NEW ? "Add" : "Update", &attr->standard.local,
1765 attr->metric);
1766
1767 /* Export Link State Edge */
1768 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
1769 edge->status = SYNC;
718e3744 1770}
1771
f173deb3
OD
1772/**
1773 * Update Link State Subnet & Prefix from the given prefix and metric. This
1774 * function is called when parsing Router LSA.
1775 *
1776 * @param ted Link State Traffic Engineering Database
1777 * @param vertex Vertex where the Edge is attached as source
1778 * @param p Prefix associated to the Subnet
1779 * @param metric Standard metric attached to this Edge
1780 */
1781static void ospf_te_update_subnet(struct ls_ted *ted, struct ls_vertex *vertex,
b5894669 1782 struct prefix *p, uint8_t metric)
718e3744 1783{
f173deb3
OD
1784 struct ls_subnet *subnet;
1785 struct ls_prefix *ls_pref;
1786
1787 /* Search if there is a Subnet for this prefix */
1788 subnet = ls_find_subnet(ted, p);
1789
1790 /* If found a Subnet, check if it is attached to this Vertex */
1791 if (subnet) {
1792 /* Re-attach the subnet to the vertex if necessary */
1793 if (subnet->vertex != vertex) {
1794 subnet->vertex = vertex;
1795 listnode_add_sort_nodup(vertex->prefixes, subnet);
1796 }
1797 /* Check if it is a simple refresh */
1798 ls_pref = subnet->ls_pref;
1799 if ((CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
1800 && (ls_pref->metric == metric)) {
1801 subnet->status = SYNC;
1802 return;
1803 }
1804 ls_pref->metric = metric;
1805 SET_FLAG(ls_pref->flags, LS_PREF_METRIC);
1806 subnet->status = UPDATE;
1807 } else {
1808 /* Create new Link State Prefix */
1809 ls_pref = ls_prefix_new(vertex->node->adv, p);
1810 ls_pref->metric = metric;
1811 SET_FLAG(ls_pref->flags, LS_PREF_METRIC);
1812 /* and add it to the TED */
1813 subnet = ls_subnet_add(ted, ls_pref);
1814 }
718e3744 1815
f173deb3
OD
1816 ote_debug(" |- %s subnet %pFX with metric %d",
1817 subnet->status == NEW ? "Add" : "Update", &subnet->key,
1818 ls_pref->metric);
718e3744 1819
f173deb3
OD
1820 /* Export Link State Subnet */
1821 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
1822 subnet->status = SYNC;
718e3744 1823}
1824
f173deb3
OD
1825/**
1826 * Delete Subnet that correspond to the given IPv4 address and export deletion
936fbaef 1827 * information before removal. Prefix length is fixed to IPV4_MAX_BITLEN.
f173deb3
OD
1828 *
1829 * @param ted Links State Database
1830 * @param addr IPv4 address
1831 */
1832static void ospf_te_delete_subnet(struct ls_ted *ted, struct in_addr addr)
718e3744 1833{
f173deb3
OD
1834 struct prefix p;
1835 struct ls_subnet *subnet;
1836
1837 /* Search subnet that correspond to the address/32 as prefix */
1838 p.family = AF_INET;
936fbaef 1839 p.prefixlen = IPV4_MAX_BITLEN;
f173deb3 1840 p.u.prefix4 = addr;
b5894669 1841 subnet = ls_find_subnet(ted, &p);
f173deb3
OD
1842
1843 /* Remove subnet if found */
1844 if (subnet) {
1845 subnet->status = DELETE;
1846 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
1847 ls_subnet_del_all(ted, subnet);
1848 }
718e3744 1849}
1850
f173deb3
OD
1851/**
1852 * Parse Router LSA. This function will create or update corresponding Vertex,
1853 * Edge and Subnet. It also remove Edge and Subnet if they are marked as Orphan
1854 * once Router LSA is parsed.
1855 *
1856 * @param ted Link State Traffic Engineering Database
1857 * @param lsa OSPF Link State Advertisement
1858 *
1859 * @return 0 if success, -1 otherwise
1860 */
1861static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
718e3744 1862{
f173deb3
OD
1863 struct router_lsa *rl;
1864 enum ls_node_type type;
1865 struct ls_vertex *vertex;
1866 struct ls_edge *edge;
1867 struct ls_subnet *subnet;
1868 struct listnode *node;
8db278b5 1869 int len, links;
f173deb3
OD
1870
1871 /* Sanity Check */
1872 if (!ted || !lsa || !lsa->data)
1873 return -1;
1874
1875 ote_debug("MPLS-TE (%s): Parse Router LSA[%pI4] from Router[%pI4]",
1876 __func__, &lsa->data->id, &lsa->data->adv_router);
1877
1878 /* Get vertex from LSA Advertise Router ID */
1879 vertex = get_vertex(ted, lsa);
1880
1881 /* Set Node type information if it has changed */
1882 rl = (struct router_lsa *)lsa->data;
1883 if (IS_ROUTER_LSA_VIRTUAL(rl))
1884 type = PSEUDO;
1885 else if (IS_ROUTER_LSA_EXTERNAL(rl))
1886 type = ASBR;
1887 else if (IS_ROUTER_LSA_BORDER(rl))
1888 type = ABR;
1889 else
1890 type = STANDARD;
1891
1892 if (vertex->status == NEW) {
1893 vertex->node->type = type;
1894 SET_FLAG(vertex->node->flags, LS_NODE_TYPE);
1895 } else if (vertex->node->type != type) {
1896 vertex->node->type = type;
1897 vertex->status = UPDATE;
1898 }
718e3744 1899
f173deb3
OD
1900 /* Check if Vertex has been modified */
1901 if (vertex->status != SYNC) {
1902 ote_debug(" |- %s Vertex %pI4",
1903 vertex->status == NEW ? "Add" : "Update",
1904 &vertex->node->router_id);
718e3744 1905
f173deb3
OD
1906 /* Vertex is out of sync: export it */
1907 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
1908 vertex->status = SYNC;
1909 }
1910
1911 /* Mark outgoing Edge and Subnet as ORPHAN to detect deletion */
1912 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge))
1913 edge->status = ORPHAN;
1914
1915 for (ALL_LIST_ELEMENTS_RO(vertex->prefixes, node, subnet))
1916 subnet->status = ORPHAN;
1917
1918 /* Then, process Link Information */
8db278b5
OD
1919 len = lsa->size - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE;
1920 links = ntohs(rl->links);
1921 for (int i = 0; i < links && len > 0; len -= 12, i++) {
f173deb3
OD
1922 struct prefix p;
1923 uint32_t metric;
1924
1925 switch (rl->link[i].type) {
1926 case LSA_LINK_TYPE_POINTOPOINT:
1927 ospf_te_update_link(ted, vertex, rl->link[i].link_data,
1928 ntohs(rl->link[i].metric));
1929 /* Add corresponding subnet */
1930 p.family = AF_INET;
936fbaef 1931 p.prefixlen = IPV4_MAX_BITLEN;
f173deb3
OD
1932 p.u.prefix4 = rl->link[i].link_data;
1933 metric = ntohs(rl->link[i].metric);
b5894669 1934 ospf_te_update_subnet(ted, vertex, &p, metric);
f173deb3
OD
1935 break;
1936 case LSA_LINK_TYPE_STUB:
1937 /* Keep only /32 prefix */
1938 p.prefixlen = ip_masklen(rl->link[i].link_data);
936fbaef 1939 if (p.prefixlen == IPV4_MAX_BITLEN) {
f173deb3
OD
1940 p.family = AF_INET;
1941 p.u.prefix4 = rl->link[i].link_id;
1942 metric = ntohs(rl->link[i].metric);
b5894669 1943 ospf_te_update_subnet(ted, vertex, &p, metric);
f173deb3
OD
1944 }
1945 break;
1946 default:
1947 break;
1948 }
1949 }
1950 /* Clean remaining Orphan Edges or Subnets */
1951 if (OspfMplsTE.export)
1952 ls_vertex_clean(ted, vertex, zclient);
d62a17ae 1953 else
f173deb3 1954 ls_vertex_clean(ted, vertex, NULL);
718e3744 1955
f173deb3 1956 return 0;
718e3744 1957}
1958
f173deb3
OD
1959/**
1960 * Delete Vertex, Edge and Subnet associated to this Router LSA. This function
1961 * is called when the router received such LSA with MAX_AGE (Flush) or when the
1962 * router stop OSPF.
1963 *
1964 * @param ted Link State Traffic Engineering Database
1965 * @param lsa OSPF Link State Advertisement
1966 *
1967 * @return 0 if success, -1 otherwise
1968 */
1969static int ospf_te_delete_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
718e3744 1970{
f173deb3
OD
1971 struct ls_node_id lnid;
1972 struct ls_vertex *vertex;
718e3744 1973
f173deb3
OD
1974 /* Sanity Check */
1975 if (!ted || !lsa || !lsa->data)
1976 return -1;
718e3744 1977
f173deb3
OD
1978 /* Search Vertex that corresponds to this LSA */
1979 lnid.origin = OSPFv2;
1980 lnid.id.ip.addr = lsa->data->adv_router;
1981 lnid.id.ip.area_id = lsa->area->area_id;
1982 vertex = ls_find_vertex_by_id(ted, lnid);
1983 if (!vertex)
1984 return -1;
718e3744 1985
f173deb3
OD
1986 ote_debug("MPLS-TE (%s): Delete Vertex %pI4 from Router LSA[%pI4]",
1987 __func__, &vertex->node->router_id, &lsa->data->id);
718e3744 1988
f173deb3
OD
1989 /* Export deleted vertex ... */
1990 vertex->status = DELETE;
1991 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
16f1b9ee 1992
f173deb3
OD
1993 /* ... and remove Node & Vertex from Link State Date Base */
1994 ls_vertex_del_all(ted, vertex);
718e3744 1995
f173deb3 1996 return 0;
718e3744 1997}
1998
f173deb3
OD
1999/**
2000 * Create or update Remote Vertex that corresponds to the remote ASBR of the
2001 * foreign network if Edge is associated to an Inter-AS LSA (Type 6).
2002 *
2003 * @param ted Link State Traffic Engineering Database
2004 * @param edge Link State Edge
2005 */
2006static void ospf_te_update_remote_asbr(struct ls_ted *ted, struct ls_edge *edge)
718e3744 2007{
f173deb3
OD
2008 struct ls_node_id lnid;
2009 struct ls_vertex *vertex;
2010 struct ls_node *lnode;
2011 struct ls_attributes *attr;
2012 struct prefix p;
2013
2014 /* Sanity Check */
2015 if (!ted || !edge)
2016 return;
718e3744 2017
f173deb3
OD
2018 /* Search if a Link State Vertex already exist */
2019 attr = edge->attributes;
2020 lnid.origin = OSPFv2;
2021 lnid.id.ip.addr = attr->standard.remote_addr;
2022 lnid.id.ip.area_id = attr->adv.id.ip.area_id;
2023 vertex = ls_find_vertex_by_id(ted, lnid);
2024
2025 /* Create Node & Vertex in the Link State Date Base if not found */
2026 if (!vertex) {
2027 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
2028
2029 lnode = ls_node_new(lnid, inaddr_any, in6addr_any);
2030 snprintfrr(lnode->name, MAX_NAME_LENGTH, "%pI4",
2031 &lnid.id.ip.addr);
2032 vertex = ls_vertex_add(ted, lnode);
2033 }
16f1b9ee 2034
f173deb3
OD
2035 /* Update Node information */
2036 lnode = vertex->node;
2037 if (CHECK_FLAG(lnode->flags, LS_NODE_TYPE)) {
2038 if (lnode->type != RMT_ASBR) {
2039 lnode->type = RMT_ASBR;
2040 if (vertex->status != NEW)
2041 vertex->status = UPDATE;
2042 }
2043 } else {
2044 lnode->type = RMT_ASBR;
2045 SET_FLAG(lnode->flags, LS_NODE_TYPE);
2046 if (vertex->status != NEW)
2047 vertex->status = UPDATE;
2048 }
2049 if (CHECK_FLAG(lnode->flags, LS_NODE_AS_NUMBER)) {
2050 if (lnode->as_number != attr->standard.remote_as) {
2051 lnode->as_number = attr->standard.remote_as;
2052 if (vertex->status != NEW)
2053 vertex->status = UPDATE;
2054 }
2055 } else {
2056 lnode->as_number = attr->standard.remote_as;
2057 SET_FLAG(lnode->flags, LS_NODE_AS_NUMBER);
2058 if (vertex->status != NEW)
2059 vertex->status = UPDATE;
2060 }
16f1b9ee 2061
f173deb3
OD
2062 /* Export Link State Vertex if needed */
2063 if (vertex->status == NEW || vertex->status == UPDATE) {
2064 ote_debug(" |- %s Remote Vertex %pI4 for AS %u",
2065 vertex->status == NEW ? "Add" : "Update",
2066 &lnode->router_id, lnode->as_number);
2067 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
2068 vertex->status = SYNC;
2069 }
16f1b9ee 2070
f173deb3
OD
2071 /* Update corresponding Subnets */
2072 p.family = AF_INET;
936fbaef 2073 p.prefixlen = IPV4_MAX_BITLEN;
f173deb3 2074 p.u.prefix4 = attr->standard.local;
b5894669 2075 ospf_te_update_subnet(ted, edge->source, &p, attr->standard.te_metric);
f173deb3
OD
2076
2077 p.family = AF_INET;
936fbaef 2078 p.prefixlen = IPV4_MAX_BITLEN;
f173deb3 2079 p.u.prefix4 = attr->standard.remote_addr;
b5894669 2080 ospf_te_update_subnet(ted, vertex, &p, attr->standard.te_metric);
f173deb3
OD
2081
2082 /* Connect Edge to the remote Vertex */
2083 if (edge->destination == NULL) {
2084 edge->destination = vertex;
2085 listnode_add_sort_nodup(vertex->incoming_edges, edge);
2086 }
16f1b9ee 2087
f173deb3
OD
2088 /* Finally set type to ASBR the node that advertised this Edge ... */
2089 vertex = edge->source;
2090 lnode = vertex->node;
2091 if (CHECK_FLAG(lnode->flags, LS_NODE_TYPE)) {
2092 if (lnode->type != ASBR) {
2093 lnode->type = ASBR;
2094 if (vertex->status != NEW)
2095 vertex->status = UPDATE;
2096 }
d62a17ae 2097 } else {
f173deb3
OD
2098 lnode->type = ASBR;
2099 SET_FLAG(lnode->flags, LS_NODE_TYPE);
2100 if (vertex->status != NEW)
2101 vertex->status = UPDATE;
d62a17ae 2102 }
16f1b9ee 2103
f173deb3
OD
2104 /* ... and Export it if needed */
2105 if (vertex->status == NEW || vertex->status == UPDATE) {
2106 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
2107 vertex->status = SYNC;
2108 }
2109}
2110
2111/**
2112 * Parse Opaque Traffic Engineering LSA (Type 1) TLVs and create or update the
2113 * corresponding Link State Edge and Attributes. Vertex connections are also
2114 * updated if needed based on the remote IP address of the Edge and existing
2115 * reverse Edge.
2116 *
2117 * @param ted Link State Traffic Engineering Database
2118 * @param lsa OSPF Link State Advertisement
2119 *
2120 * @return 0 if success, -1 otherwise
2121 */
2122static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
2123{
2124 struct ls_edge *edge;
2125 struct ls_vertex *vertex;
2126 struct ls_attributes *old, attr = {};
2127 struct tlv_header *tlvh;
2128 void *value;
2129 uint16_t len, sum;
2130 uint8_t lsa_id;
2131
2132 /* Initialize Attribute */
2133 attr.adv.origin = OSPFv2;
2134 attr.adv.id.ip.addr = lsa->data->adv_router;
2135 if (lsa->data->type != OSPF_OPAQUE_AS_LSA)
2136 attr.adv.id.ip.area_id = lsa->area->area_id;
2137
2138 /* Initialize TLV browsing */
2139 tlvh = TLV_HDR_TOP(lsa->data);
8db278b5 2140 len = lsa->size - OSPF_LSA_HEADER_SIZE;
f173deb3 2141
8db278b5
OD
2142 /* Check if TE Router-ID TLV is present */
2143 if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) {
2144 /* if TE Router-ID is alone, we are done ... */
2145 if (len == TE_LINK_SUBTLV_DEF_SIZE)
2146 return 0;
23508fff 2147
8db278b5
OD
2148 /* ... otherwise, skip it */
2149 len -= TE_LINK_SUBTLV_DEF_SIZE + TLV_HDR_SIZE;
f173deb3 2150 tlvh = TLV_HDR_NEXT(tlvh);
8db278b5 2151 }
f173deb3 2152
8db278b5 2153 /* Check if we have a valid TE Link TLV */
f173deb3
OD
2154 if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK))
2155 return 0;
2156
e3db39db 2157 sum = sizeof(struct tlv_header);
f173deb3
OD
2158 /* Browse sub-TLV and fulfill Link State Attributes */
2159 for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
2160 uint32_t val32, tab32[2];
2161 float valf, tabf[8];
2162 struct in_addr addr;
2163
2164 value = TLV_DATA(tlvh);
2165 switch (ntohs(tlvh->type)) {
2166 case TE_LINK_SUBTLV_LCLIF_IPADDR:
2167 memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
2168 attr.standard.local = addr;
2169 SET_FLAG(attr.flags, LS_ATTR_LOCAL_ADDR);
2170 break;
2171 case TE_LINK_SUBTLV_RMTIF_IPADDR:
2172 memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
2173 attr.standard.remote = addr;
2174 SET_FLAG(attr.flags, LS_ATTR_NEIGH_ADDR);
2175 break;
2176 case TE_LINK_SUBTLV_TE_METRIC:
2177 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2178 attr.standard.te_metric = ntohl(val32);
2179 SET_FLAG(attr.flags, LS_ATTR_TE_METRIC);
2180 break;
2181 case TE_LINK_SUBTLV_MAX_BW:
2182 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2183 attr.standard.max_bw = ntohf(valf);
2184 SET_FLAG(attr.flags, LS_ATTR_MAX_BW);
2185 break;
2186 case TE_LINK_SUBTLV_MAX_RSV_BW:
2187 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2188 attr.standard.max_rsv_bw = ntohf(valf);
2189 SET_FLAG(attr.flags, LS_ATTR_MAX_RSV_BW);
2190 break;
2191 case TE_LINK_SUBTLV_UNRSV_BW:
2192 memcpy(tabf, value, TE_LINK_SUBTLV_UNRSV_SIZE);
2193 for (int i = 0; i < MAX_CLASS_TYPE; i++)
2194 attr.standard.unrsv_bw[i] = ntohf(tabf[i]);
2195 SET_FLAG(attr.flags, LS_ATTR_UNRSV_BW);
2196 break;
2197 case TE_LINK_SUBTLV_RSC_CLSCLR:
2198 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2199 attr.standard.admin_group = ntohl(val32);
2200 SET_FLAG(attr.flags, LS_ATTR_ADM_GRP);
2201 break;
2202 case TE_LINK_SUBTLV_LLRI:
2203 memcpy(tab32, value, TE_LINK_SUBTLV_LLRI_SIZE);
2204 attr.standard.local_id = ntohl(tab32[0]);
2205 attr.standard.remote_id = ntohl(tab32[1]);
2206 SET_FLAG(attr.flags, LS_ATTR_LOCAL_ID);
2207 SET_FLAG(attr.flags, LS_ATTR_NEIGH_ID);
2208 break;
2209 case TE_LINK_SUBTLV_RIP:
2210 memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
2211 attr.standard.remote_addr = addr;
2212 SET_FLAG(attr.flags, LS_ATTR_REMOTE_ADDR);
2213 break;
2214 case TE_LINK_SUBTLV_RAS:
2215 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2216 attr.standard.remote_as = ntohl(val32);
2217 SET_FLAG(attr.flags, LS_ATTR_REMOTE_AS);
2218 break;
2219 case TE_LINK_SUBTLV_AV_DELAY:
2220 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2221 attr.extended.delay = ntohl(val32);
2222 SET_FLAG(attr.flags, LS_ATTR_DELAY);
2223 break;
2224 case TE_LINK_SUBTLV_MM_DELAY:
2225 memcpy(tab32, value, TE_LINK_SUBTLV_MM_DELAY_SIZE);
2226 attr.extended.min_delay = ntohl(tab32[0]);
2227 attr.extended.max_delay = ntohl(tab32[1]);
2228 SET_FLAG(attr.flags, LS_ATTR_MIN_MAX_DELAY);
2229 break;
2230 case TE_LINK_SUBTLV_DELAY_VAR:
2231 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2232 attr.extended.jitter = ntohl(val32);
2233 SET_FLAG(attr.flags, LS_ATTR_JITTER);
2234 break;
2235 case TE_LINK_SUBTLV_PKT_LOSS:
2236 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2237 attr.extended.pkt_loss = ntohl(val32);
2238 SET_FLAG(attr.flags, LS_ATTR_PACKET_LOSS);
2239 break;
2240 case TE_LINK_SUBTLV_RES_BW:
2241 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2242 attr.extended.rsv_bw = ntohf(valf);
2243 SET_FLAG(attr.flags, LS_ATTR_RSV_BW);
2244 break;
2245 case TE_LINK_SUBTLV_AVA_BW:
2246 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2247 attr.extended.ava_bw = ntohf(valf);
2248 SET_FLAG(attr.flags, LS_ATTR_AVA_BW);
2249 break;
2250 case TE_LINK_SUBTLV_USE_BW:
2251 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2252 attr.extended.used_bw = ntohf(valf);
2253 SET_FLAG(attr.flags, LS_ATTR_USE_BW);
2254 break;
2255 default:
2256 break;
2257 }
2258 sum += TLV_SIZE(tlvh);
2259 }
2260
2261 /* Get corresponding Edge from Link State Data Base */
2262 edge = get_edge(ted, attr.adv, attr.standard.local);
2263 old = edge->attributes;
2264
2265 ote_debug(" |- Process Traffic Engineering LSA %pI4 for Edge %pI4",
2266 &lsa->data->id, &attr.standard.local);
2267
2268 /* Update standard fields */
2269 len = sizeof(struct ls_standard);
2270 if ((attr.flags & 0x0FFFF) == (old->flags & 0x0FFFF)) {
2271 if (memcmp(&attr.standard, &old->standard, len) != 0) {
2272 memcpy(&old->standard, &attr.standard, len);
2273 if (edge->status != NEW)
2274 edge->status = UPDATE;
2275 }
2276 } else {
2277 memcpy(&old->standard, &attr.standard, len);
2278 old->flags |= attr.flags & 0x0FFFF;
2279 if (edge->status != NEW)
2280 edge->status = UPDATE;
2281 }
2282 /* Update extended fields */
2283 len = sizeof(struct ls_extended);
2284 if ((attr.flags & 0x0FF0000) == (old->flags & 0x0FF0000)) {
2285 if (memcmp(&attr.extended, &old->extended, len) != 0) {
2286 memcpy(&old->extended, &attr.extended, len);
2287 if (edge->status != NEW)
2288 edge->status = UPDATE;
2289 }
2290 } else {
2291 memcpy(&old->extended, &attr.extended, len);
2292 old->flags |= attr.flags & 0x0FF0000;
2293 if (edge->status != NEW)
2294 edge->status = UPDATE;
2295 }
2296
2297 /* If LSA is an Opaque Inter-AS, Add Node and Subnet */
2298 lsa_id = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2299 if (lsa_id == OPAQUE_TYPE_INTER_AS_LSA)
2300 ospf_te_update_remote_asbr(ted, edge);
2301
2302 /* Update remote Link if remote IP addr is known */
2303 if (CHECK_FLAG(old->flags, LS_ATTR_NEIGH_ADDR)) {
2304 struct ls_edge *dst;
2305
2306 dst = ls_find_edge_by_destination(ted, old);
2307 /* Attach remote link if not set */
2308 if (dst && edge->source && dst->destination == NULL) {
2309 vertex = edge->source;
2310 if (vertex->incoming_edges)
2311 listnode_add_sort_nodup(vertex->incoming_edges,
2312 dst);
2313 dst->destination = vertex;
2314 }
2315 /* and destination vertex to this edge */
2316 if (dst && dst->source && edge->destination == NULL) {
2317 vertex = dst->source;
2318 if (vertex->incoming_edges)
2319 listnode_add_sort_nodup(vertex->incoming_edges,
2320 edge);
2321 edge->destination = vertex;
2322 }
2323 }
2324
2325 /* Export Link State Edge if needed */
2326 if (edge->status == NEW || edge->status == UPDATE) {
2327 ote_debug(" |- %s TE info. for Edge %pI4",
2328 edge->status == NEW ? "Add" : "Update",
2329 &edge->attributes->standard.local);
2330
2331 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2332 edge->status = SYNC;
2333 }
2334
2335 return 0;
2336}
2337
2338/**
2339 * Delete Link State Attributes information that correspond to the Opaque
2340 * Traffic Engineering LSA (Type 1) TLVs. Note that the Edge is not removed.
2341 *
2342 * @param ted Link State Traffic Engineering Database
2343 * @param lsa OSPF Link State Advertisement
2344 *
2345 * @return 0 if success, -1 otherwise
2346 */
2347static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
2348{
2349 struct ls_edge *edge;
2350 struct ls_attributes *attr;
2351 struct tlv_header *tlvh;
2352 struct in_addr addr;
2353 uint64_t key = 0;
2354 uint16_t len, sum;
2355 uint8_t lsa_id;
2356
2357 /* Initialize TLV browsing */
2358 tlvh = TLV_HDR_TOP(lsa->data);
2359 /* Skip Router TE ID if present */
2360 if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
2361 tlvh = TLV_HDR_NEXT(tlvh);
2362 len = TLV_BODY_SIZE(tlvh);
e3db39db 2363 sum = sizeof(struct tlv_header);
f173deb3
OD
2364
2365 /* Browse sub-TLV to find Link ID */
2366 for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
2367 if (ntohs(tlvh->type) == TE_LINK_SUBTLV_LCLIF_IPADDR) {
2368 memcpy(&addr, TLV_DATA(tlvh), TE_LINK_SUBTLV_DEF_SIZE);
2369 key = ((uint64_t)ntohl(addr.s_addr)) & 0xffffffff;
2370 break;
2371 }
2372 sum += TLV_SIZE(tlvh);
2373 }
2374 if (key == 0)
2375 return 0;
2376
2377 /* Search Edge that corresponds to the Link ID */
2378 edge = ls_find_edge_by_key(ted, key);
2379 if (!edge || !edge->attributes)
2380 return 0;
2381 attr = edge->attributes;
2382
2383 /* First, remove Remote ASBR and associated Edge & Subnet if any */
2384 lsa_id = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2385 if (lsa_id == OPAQUE_TYPE_INTER_AS_LSA) {
2386 ote_debug(" |- Delete remote ASBR, Edge and Subnet");
2387
2388 if (edge->destination) {
2389 edge->destination->status = DELETE;
2390 ospf_te_export(LS_MSG_TYPE_NODE, edge->destination);
2391 ls_vertex_del_all(ted, edge->destination);
2392 }
2393
2394 ospf_te_delete_subnet(ted, attr->standard.local);
2395
2396 edge->status = DELETE;
2397 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2398 ls_edge_del_all(ted, edge);
2399
2400 return 0;
2401 }
2402
2403 ote_debug(" |- Delete TE info. for Edge %pI4",
2404 &edge->attributes->standard.local);
2405
2406 /* Remove Link State Attributes TE information */
2407 memset(&attr->standard, 0, sizeof(struct ls_standard));
2408 attr->flags &= 0x0FFFF;
2409 memset(&attr->extended, 0, sizeof(struct ls_extended));
2410 attr->flags &= 0x0FF0000;
2411 ls_attributes_srlg_del(attr);
2412
2413 /* Export Edge that has been updated */
2414 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)
2415 || CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
2416 edge->status = UPDATE;
2417 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2418 edge->status = SYNC;
2419 } else {
2420 /* Remove completely the Edge if Segment Routing is not set */
2421 ospf_te_delete_subnet(ted, attr->standard.local);
2422 edge->status = DELETE;
2423 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2424 ls_edge_del_all(ted, edge);
2425 }
2426
2427 return 0;
2428}
2429
2430/**
2431 * Parse Opaque Router Information LSA (Type 4) TLVs and update the
2432 * corresponding Link State Vertex with these information (Segment Routing).
2433 *
2434 * @param ted Link State Traffic Engineering Database
2435 * @param lsa OSPF Link State Advertisement
2436 *
2437 * @return 0 if success, -1 otherwise
2438 */
2439static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
2440{
2441 struct ls_vertex *vertex;
2442 struct ls_node *node;
2443 struct lsa_header *lsah = lsa->data;
2444 struct tlv_header *tlvh;
2445 uint16_t len = 0, sum = 0;
2446
2447 /* Get vertex / Node from LSA Advertised Router ID */
2448 vertex = get_vertex(ted, lsa);
2449 node = vertex->node;
2450
2451 ote_debug(" |- Process Router Information LSA %pI4 for Vertex %pI4",
2452 &lsa->data->id, &node->router_id);
2453
2454 /* Initialize TLV browsing */
8db278b5
OD
2455 len = lsa->size - OSPF_LSA_HEADER_SIZE;
2456 for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;
2457 tlvh = TLV_HDR_NEXT(tlvh)) {
f173deb3
OD
2458 struct ri_sr_tlv_sr_algorithm *algo;
2459 struct ri_sr_tlv_sid_label_range *range;
2460 struct ri_sr_tlv_node_msd *msd;
2461 uint32_t size, lower;
2462
2463 switch (ntohs(tlvh->type)) {
2464 case RI_SR_TLV_SR_ALGORITHM:
2465 algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
2466
2467 for (int i = 0; i < ntohs(algo->header.length); i++) {
2468 if (CHECK_FLAG(node->flags, LS_NODE_SR)
2469 && (node->algo[i] == algo->value[i]))
2470 continue;
2471
2472 node->algo[i] = algo->value[i];
2473 SET_FLAG(node->flags, LS_NODE_SR);
2474 if (vertex->status != NEW)
2475 vertex->status = UPDATE;
2476 }
2477
2478 /* Reset other Algorithms */
2479 for (int i = ntohs(algo->header.length); i < 2; i++) {
2480 if (vertex->status != NEW
2481 && node->algo[i] != SR_ALGORITHM_UNSET)
2482 vertex->status = UPDATE;
2483 node->algo[i] = SR_ALGORITHM_UNSET;
2484 }
2485
2486 break;
2487
2488 case RI_SR_TLV_SRGB_LABEL_RANGE:
2489 range = (struct ri_sr_tlv_sid_label_range *)tlvh;
2490 size = GET_RANGE_SIZE(ntohl(range->size));
2491 lower = GET_LABEL(ntohl(range->lower.value));
2492 if ((CHECK_FLAG(node->flags, LS_NODE_SR))
2493 && ((node->srgb.range_size == size)
2494 && (node->srgb.lower_bound == lower)))
2495 break;
2496
2497 node->srgb.range_size = size;
2498 node->srgb.lower_bound = lower;
2499 SET_FLAG(node->flags, LS_NODE_SR);
2500 if (vertex->status != NEW)
2501 vertex->status = UPDATE;
2502
2503 break;
2504
2505 case RI_SR_TLV_SRLB_LABEL_RANGE:
2506 range = (struct ri_sr_tlv_sid_label_range *)tlvh;
2507 size = GET_RANGE_SIZE(ntohl(range->size));
2508 lower = GET_LABEL(ntohl(range->lower.value));
2509 if ((CHECK_FLAG(node->flags, LS_NODE_SRLB))
2510 && ((node->srlb.range_size == size)
2511 && (node->srlb.lower_bound == lower)))
2512 break;
2513
2514 node->srlb.range_size = size;
2515 node->srlb.lower_bound = lower;
2516 SET_FLAG(node->flags, LS_NODE_SRLB);
2517 if (vertex->status != NEW)
2518 vertex->status = UPDATE;
2519
2520 break;
2521
2522 case RI_SR_TLV_NODE_MSD:
2523 msd = (struct ri_sr_tlv_node_msd *)tlvh;
2524 if ((CHECK_FLAG(node->flags, LS_NODE_MSD))
2525 && (node->msd == msd->value))
2526 break;
2527
2528 node->msd = msd->value;
2529 SET_FLAG(node->flags, LS_NODE_MSD);
2530 if (vertex->status != NEW)
2531 vertex->status = UPDATE;
2532
2533 break;
2534
2535 default:
2536 break;
2537 }
2538 sum += TLV_SIZE(tlvh);
2539 }
2540
2541 /* Vertex has been created or updated: export it */
2542 if (vertex->status == NEW || vertex->status == UPDATE) {
2543 ote_debug(" |- %s SR info - SRGB[%d/%d] for Vertex %pI4",
2544 vertex->status == NEW ? "Add" : "Update",
2545 vertex->node->srgb.lower_bound,
2546 vertex->node->srgb.range_size,
2547 &vertex->node->router_id);
2548
2549 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
2550 vertex->status = SYNC;
2551 }
2552
2553 return 0;
2554}
2555
2556/**
2557 * Delete Link State Node information (Segment Routing) that correspond to the
2558 * Opaque Router Information LSA (Type 4) TLVs. Note that the Vertex is not
2559 * removed.
2560 *
2561 * @param ted Link State Traffic Engineering Database
2562 * @param lsa OSPF Link State Advertisement
2563 *
2564 * @return 0 if success, -1 otherwise
2565 */
2566static int ospf_te_delete_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
2567{
2568 struct ls_node_id lnid;
2569 struct ls_vertex *vertex;
2570 struct ls_node *node;
2571
2572 /* Search if a Link State Vertex already exist */
2573 lnid.origin = OSPFv2;
2574 lnid.id.ip.addr = lsa->data->adv_router;
2575 lnid.id.ip.area_id = lsa->area->area_id;
2576 vertex = ls_find_vertex_by_id(ted, lnid);
2577 if (!vertex)
2578 return -1;
2579
2580 /* Remove Segment Routing Information if any */
2581 node = vertex->node;
2582 UNSET_FLAG(node->flags, LS_NODE_SR);
2583 memset(&node->srgb, 0, sizeof(struct ls_srgb));
2584 node->algo[0] = SR_ALGORITHM_UNSET;
2585 node->algo[1] = SR_ALGORITHM_UNSET;
2586 UNSET_FLAG(node->flags, LS_NODE_SRLB);
2587 memset(&node->srlb, 0, sizeof(struct ls_srlb));
2588 UNSET_FLAG(node->flags, LS_NODE_MSD);
2589 node->msd = 0;
2590 vertex->status = UPDATE;
2591
2592 ote_debug(" |- Delete SR info. for Vertex %pI4",
2593 &vertex->node->router_id);
2594
2595 /* Vertex has been updated: export it */
2596 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
2597 vertex->status = SYNC;
2598
2599 return 0;
2600}
2601
2602/**
2603 * Parse Opaque Extended Prefix LSA (Type 7) TLVs and update the corresponding
2604 * Link State Subnet with these information (Segment Routing ID).
2605 *
2606 * @param ted Link State Traffic Engineering Database
2607 * @param lsa OSPF Link State Advertisement
2608 *
2609 * @return 0 if success, -1 otherwise
2610 */
2611static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
2612{
2613 struct ls_node_id lnid;
2614 struct ls_subnet *subnet;
2615 struct ls_prefix *ls_pref;
2616 struct prefix pref;
2617 struct ext_tlv_prefix *ext;
2618 struct ext_subtlv_prefix_sid *pref_sid;
2619 uint32_t label;
2620
2621 /* Get corresponding Subnet from Link State Data Base */
2622 ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data);
2623 pref.family = AF_INET;
2624 pref.prefixlen = ext->pref_length;
2625 pref.u.prefix4 = ext->address;
b5894669 2626 subnet = ls_find_subnet(ted, &pref);
f173deb3
OD
2627
2628 /* Create new Link State Prefix if not found */
2629 if (!subnet) {
2630 lnid.origin = OSPFv2;
2631 lnid.id.ip.addr = lsa->data->adv_router;
2632 lnid.id.ip.area_id = lsa->area->area_id;
b5894669 2633 ls_pref = ls_prefix_new(lnid, &pref);
f173deb3
OD
2634 /* and add it to the TED */
2635 subnet = ls_subnet_add(ted, ls_pref);
2636 }
2637
2638 ote_debug(" |- Process Extended Prefix LSA %pI4 for subnet %pFX",
2639 &lsa->data->id, &pref);
2640
2641 /* Initialize TLV browsing */
2642 ls_pref = subnet->ls_pref;
2643 pref_sid = (struct ext_subtlv_prefix_sid *)((char *)(ext) + TLV_HDR_SIZE
2644 + EXT_TLV_PREFIX_SIZE);
2645 label = CHECK_FLAG(pref_sid->flags, EXT_SUBTLV_PREFIX_SID_VFLG)
2646 ? GET_LABEL(ntohl(pref_sid->value))
2647 : ntohl(pref_sid->value);
2648
2649 /* Check if it is a simple refresh */
2650 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)
2651 && ls_pref->sr.algo == pref_sid->algorithm
2652 && ls_pref->sr.sid_flag == pref_sid->flags
2653 && ls_pref->sr.sid == label)
2654 return 0;
2655
2656 /* Fulfill SR information */
2657 ls_pref->sr.algo = pref_sid->algorithm;
2658 ls_pref->sr.sid_flag = pref_sid->flags;
2659 ls_pref->sr.sid = label;
2660 SET_FLAG(ls_pref->flags, LS_PREF_SR);
2661 if (subnet->status != NEW)
2662 subnet->status = UPDATE;
2663
2664 /* Export Subnet if needed */
2665 if (subnet->status == NEW || subnet->status == UPDATE) {
2666 ote_debug(" |- %s SID %d to subnet %pFX",
2667 subnet->status == NEW ? "Add" : "Update",
2668 ls_pref->sr.sid, &ls_pref->pref);
2669
2670 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
2671 subnet->status = SYNC;
2672 }
2673
2674 return 0;
2675}
2676
2677/**
2678 * Delete Link State Subnet information (Segment Routing ID) that correspond to
2679 * the Opaque Extended Prefix LSA (Type 7) TLVs. Note that the Subnet is not
2680 * removed.
2681 *
2682 * @param ted Link State Traffic Engineering Database
2683 * @param lsa OSPF Link State Advertisement
2684 *
2685 * @return 0 if success, -1 otherwise
2686 */
2687static int ospf_te_delete_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
2688{
2689 struct ls_subnet *subnet;
2690 struct ls_prefix *ls_pref;
2691 struct prefix pref;
2692 struct ext_tlv_prefix *ext;
2693
2694 /* Get corresponding Subnet from Link State Data Base */
2695 ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data);
2696 pref.family = AF_INET;
2697 pref.prefixlen = ext->pref_length;
2698 pref.u.prefix4 = ext->address;
b5894669 2699 subnet = ls_find_subnet(ted, &pref);
f173deb3
OD
2700
2701 /* Check if there is a corresponding subnet */
2702 if (!subnet)
2703 return -1;
2704
2705 ote_debug(" |- Delete SID %d to subnet %pFX", subnet->ls_pref->sr.sid,
2706 &subnet->ls_pref->pref);
2707
2708 /* Remove Segment Routing information */
2709 ls_pref = subnet->ls_pref;
2710 UNSET_FLAG(ls_pref->flags, LS_PREF_SR);
2711 memset(&ls_pref->sr, 0, sizeof(struct ls_sid));
2712 subnet->status = UPDATE;
2713
2714 /* Subnet has been updated: export it */
2715 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
2716 subnet->status = SYNC;
2717
2718 return 0;
2719}
2720
2721/**
2722 * Parse Opaque Extended Link LSA (Type 8) TLVs and update the corresponding
2723 * Link State Edge with these information (Segment Routing Adjacency).
2724 *
2725 * @param ted Link State Traffic Engineering Database
2726 * @param lsa OSPF Link State Advertisement
2727 *
2728 * @return 0 if success, -1 otherwise
2729 */
2730static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
2731{
2732 struct ls_node_id lnid;
2733 struct tlv_header *tlvh;
2734 struct ext_tlv_link *ext;
2735 struct ls_edge *edge;
2736 struct ls_attributes *atr;
2737 uint16_t len = 0, sum = 0, i;
2738 uint32_t label;
2739
2740 /* Get corresponding Edge from Link State Data Base */
2741 lnid.origin = OSPFv2;
2742 lnid.id.ip.addr = lsa->data->adv_router;
2743 lnid.id.ip.area_id = lsa->area->area_id;
2744 ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data);
2745 edge = get_edge(ted, lnid, ext->link_data);
2746 atr = edge->attributes;
2747
2748 ote_debug(" |- Process Extended Link LSA %pI4 for edge %pI4",
2749 &lsa->data->id, &edge->attributes->standard.local);
2750
2751 /* Initialize TLV browsing */
23508fff 2752 len = TLV_BODY_SIZE(&ext->header) - EXT_TLV_LINK_SIZE;
f173deb3
OD
2753 tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
2754 + EXT_TLV_LINK_SIZE);
2755 for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
2756 struct ext_subtlv_adj_sid *adj;
2757 struct ext_subtlv_lan_adj_sid *ladj;
2758 struct ext_subtlv_rmt_itf_addr *rmt;
2759
2760 switch (ntohs(tlvh->type)) {
2761 case EXT_SUBTLV_ADJ_SID:
2762 adj = (struct ext_subtlv_adj_sid *)tlvh;
2763 label = CHECK_FLAG(adj->flags,
2764 EXT_SUBTLV_LINK_ADJ_SID_VFLG)
2765 ? GET_LABEL(ntohl(adj->value))
2766 : ntohl(adj->value);
2767 i = CHECK_FLAG(adj->flags,
2768 EXT_SUBTLV_LINK_ADJ_SID_BFLG) ? 1 : 0;
2769 if (((i && CHECK_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID))
2770 || (!i && CHECK_FLAG(atr->flags, LS_ATTR_ADJ_SID)))
2771 && atr->adj_sid[i].flags == adj->flags
2772 && atr->adj_sid[i].sid == label
2773 && atr->adj_sid[i].weight == adj->weight)
2774 break;
2775
2776 atr->adj_sid[i].flags = adj->flags;
2777 atr->adj_sid[i].sid = label;
2778 atr->adj_sid[i].weight = adj->weight;
2779 if (i == 0)
2780 SET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
2781 else
2782 SET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
2783 if (edge->status != NEW)
2784 edge->status = UPDATE;
2785
2786 break;
2787 case EXT_SUBTLV_LAN_ADJ_SID:
2788 ladj = (struct ext_subtlv_lan_adj_sid *)tlvh;
2789 label = CHECK_FLAG(ladj->flags,
2790 EXT_SUBTLV_LINK_ADJ_SID_VFLG)
2791 ? GET_LABEL(ntohl(ladj->value))
2792 : ntohl(ladj->value);
2793 i = CHECK_FLAG(ladj->flags,
2794 EXT_SUBTLV_LINK_ADJ_SID_BFLG) ? 1 : 0;
2795 if (((i && CHECK_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID))
2796 || (!i && CHECK_FLAG(atr->flags, LS_ATTR_ADJ_SID)))
2797 && atr->adj_sid[i].flags == ladj->flags
2798 && atr->adj_sid[i].sid == label
2799 && atr->adj_sid[i].weight == ladj->weight
2800 && IPV4_ADDR_SAME(&atr->adj_sid[1].neighbor.addr,
2801 &ladj->neighbor_id))
2802 break;
2803
2804 atr->adj_sid[i].flags = ladj->flags;
2805 atr->adj_sid[i].sid = label;
2806 atr->adj_sid[i].weight = ladj->weight;
2807 atr->adj_sid[i].neighbor.addr = ladj->neighbor_id;
2808 if (i == 0)
2809 SET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
2810 else
2811 SET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
2812 if (edge->status != NEW)
2813 edge->status = UPDATE;
2814
2815 break;
2816 case EXT_SUBTLV_RMT_ITF_ADDR:
2817 rmt = (struct ext_subtlv_rmt_itf_addr *)tlvh;
2818 if (CHECK_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR)
2819 && IPV4_ADDR_SAME(&atr->standard.remote,
2820 &rmt->value))
2821 break;
2822
2823 atr->standard.remote = rmt->value;
2824 SET_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR);
2825 if (edge->status != NEW)
2826 edge->status = UPDATE;
2827
2828 break;
2829 default:
2830 break;
2831 }
2832 sum += TLV_SIZE(tlvh);
2833 }
2834
2835 /* Export Link State Edge if needed */
2836 if (edge->status == NEW || edge->status == UPDATE) {
2837 ote_debug(" |- %s Adj-SID %d & %d to edge %pI4",
2838 edge->status == NEW ? "Add" : "Update",
2839 edge->attributes->adj_sid[0].sid,
2840 edge->attributes->adj_sid[1].sid,
2841 &edge->attributes->standard.local);
2842
2843 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2844 edge->status = SYNC;
2845 }
2846
2847 return 0;
2848}
2849
2850/**
2851 * Delete Link State Edge information (Segment Routing Adjacency) that
2852 * correspond to the Opaque Extended Link LSA (Type 8) TLVs. Note that the Edge
2853 * is not removed.
2854 *
2855 * @param ted Link State Traffic Engineering Database
2856 * @param lsa OSPF Link State Advertisement
2857 *
2858 * @return 0 if success, -1 otherwise
2859 */
2860static int ospf_te_delete_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
2861{
2862 struct ls_edge *edge;
2863 struct ls_attributes *atr;
2864 struct ext_tlv_link *ext;
2865 uint64_t key;
2866
2867 /* Search for corresponding Edge from Link State Data Base */
2868 ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data);
2869 key = ((uint64_t)ntohl(ext->link_data.s_addr)) & 0xffffffff;
2870 edge = ls_find_edge_by_key(ted, key);
2871
2872 /* Check if there is a corresponding Edge */
2873 if (!edge)
2874 return -1;
2875
2876 ote_debug(" |- Delete Adj-SID %d to edge %pI4",
2877 edge->attributes->adj_sid[0].sid,
2878 &edge->attributes->standard.local);
2879
2880 /* Remove Segment Routing information */
2881 atr = edge->attributes;
2882 UNSET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
2883 UNSET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
2884 memset(atr->adj_sid, 0, 2 * sizeof(struct ls_sid));
2885 edge->status = UPDATE;
2886
2887 /* Edge has been updated: export it */
2888 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2889 edge->status = SYNC;
2890
2891 return 0;
2892}
2893
2894/**
2895 * Parse Opaque LSA Type and call corresponding parser.
2896 *
2897 * @param ted Link State Traffic Engineering Database
2898 * @param lsa OSPF Link State Advertisement
2899 *
2900 * @return 0 if success, -1 otherwise
2901 */
2902static int ospf_te_parse_opaque_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
2903{
2904 uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2905 int rc = -1;
2906
2907 ote_debug("MPLS-TE (%s): Parse Opaque LSA[%pI4] from Router[%pI4]",
2908 __func__, &lsa->data->id, &lsa->data->adv_router);
2909
2910 switch (key) {
2911 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
2912 case OPAQUE_TYPE_INTER_AS_LSA:
2913 rc = ospf_te_parse_te(ted, lsa);
2914 break;
2915 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
2916 rc = ospf_te_parse_ri(ted, lsa);
2917 break;
2918 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
2919 rc = ospf_te_parse_ext_pref(ted, lsa);
2920 break;
2921 case OPAQUE_TYPE_EXTENDED_LINK_LSA:
2922 rc = ospf_te_parse_ext_link(ted, lsa);
2923 break;
2924 default:
2925 break;
2926 }
2927
2928 return rc;
2929}
2930
2931/**
2932 * Parse Opaque LSA Type and call corresponding deletion function.
2933 *
2934 * @param ted Link State Traffic Engineering Database
2935 * @param lsa OSPF Link State Advertisement
2936 *
2937 * @return 0 if success, -1 otherwise
2938 */
2939static int ospf_te_delete_opaque_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
2940{
2941 uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2942 int rc = -1;
2943
2944 ote_debug("MPLS-TE (%s): Parse Opaque LSA[%pI4] from Router[%pI4]",
2945 __func__, &lsa->data->id, &lsa->data->adv_router);
2946
2947 switch (key) {
2948 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
2949 case OPAQUE_TYPE_INTER_AS_LSA:
2950 rc = ospf_te_delete_te(ted, lsa);
2951 break;
2952 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
2953 rc = ospf_te_delete_ri(ted, lsa);
2954 break;
2955 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
2956 rc = ospf_te_delete_ext_pref(ted, lsa);
2957 break;
2958 case OPAQUE_TYPE_EXTENDED_LINK_LSA:
2959 rc = ospf_te_delete_ext_link(ted, lsa);
2960 break;
2961 default:
2962 break;
2963 }
2964
2965 return rc;
2966}
2967
2968/**
2969 * Update Traffic Engineering Database Elements that correspond to the received
2970 * OSPF LSA. If LSA age is equal to MAX_AGE, call deletion function instead.
2971 *
2972 * @param lsa OSPF Link State Advertisement
2973 *
2974 * @return 0 if success, -1 otherwise
2975 */
2976static int ospf_mpls_te_lsa_update(struct ospf_lsa *lsa)
2977{
2978
2979 uint8_t rc;
2980
2981 /* Check that MPLS-TE is active */
2982 if (!OspfMplsTE.enabled || !OspfMplsTE.ted)
2983 return 0;
2984
2985 /* Sanity Check */
2986 if (lsa == NULL) {
2987 flog_warn(EC_OSPF_LSA_NULL, "TE (%s): Abort! LSA is NULL",
2988 __func__);
2989 return -1;
2990 }
2991
2992 /* If LSA is MAX_AGE, remove corresponding Link State element */
2993 if (IS_LSA_MAXAGE(lsa)) {
2994 switch (lsa->data->type) {
2995 case OSPF_ROUTER_LSA:
2996 rc = ospf_te_delete_router_lsa(OspfMplsTE.ted, lsa);
2997 break;
2998 case OSPF_OPAQUE_AREA_LSA:
2999 case OSPF_OPAQUE_AS_LSA:
3000 rc = ospf_te_delete_opaque_lsa(OspfMplsTE.ted, lsa);
3001 break;
3002 default:
3003 rc = 0;
3004 break;
3005 }
3006 } else {
3007 /* Parse LSA to Update corresponding Link State element */
3008 switch (lsa->data->type) {
3009 case OSPF_ROUTER_LSA:
3010 rc = ospf_te_parse_router_lsa(OspfMplsTE.ted, lsa);
3011 break;
3012 case OSPF_OPAQUE_AREA_LSA:
3013 case OSPF_OPAQUE_AS_LSA:
3014 rc = ospf_te_parse_opaque_lsa(OspfMplsTE.ted, lsa);
3015 break;
3016 default:
3017 rc = 0;
3018 break;
3019 }
3020 }
3021
3022 return rc;
3023}
3024
3025/**
3026 * Delete Traffic Engineering Database element from OSPF LSA. This function
3027 * process only self LSA (i.e. advertised by the router) which reach MAX_AGE
3028 * as LSA deleted by neighbor routers are Flushed (i.e. advertised with
3029 * age == MAX_AGE) and processed by ospf_mpls_te_lsa_update() function.
3030 *
3031 * @param lsa OSPF Link State Advertisement
3032 *
3033 * @return 0 if success, -1 otherwise
3034 */
3035static int ospf_mpls_te_lsa_delete(struct ospf_lsa *lsa)
3036{
3037
3038 uint8_t rc;
3039
3040 /* Check that MPLS-TE is active */
3041 if (!OspfMplsTE.enabled || !OspfMplsTE.ted)
3042 return 0;
3043
3044 /* Sanity Check */
3045 if (lsa == NULL) {
3046 flog_warn(EC_OSPF_LSA_NULL, "TE (%s): Abort! LSA is NULL",
3047 __func__);
3048 return -1;
3049 }
3050
3051 /*
3052 * Process only self LSAs that reach MAX_AGE. Indeed, when the router
3053 * need to update or refresh an LSA, it first removes the old LSA from
3054 * the LSDB and then insert the new one. Thus, to avoid removing
3055 * corresponding Link State element and loosing some parameters
3056 * instead of just updating it, only self LSAs that reach MAX_AGE are
3057 * processed here. Other LSAs are processed by ospf_mpls_te_lsa_update()
3058 * and eventually removed when LSA age is MAX_AGE i.e. LSA is flushed
3059 * by the originator.
3060 */
3061 if (!IS_LSA_SELF(lsa) || !IS_LSA_MAXAGE(lsa))
3062 return 0;
3063
3064 /* Parse Link State information */
3065 switch (lsa->data->type) {
3066 case OSPF_ROUTER_LSA:
3067 rc = ospf_te_delete_router_lsa(OspfMplsTE.ted, lsa);
3068 break;
3069 case OSPF_OPAQUE_AREA_LSA:
3070 case OSPF_OPAQUE_AS_LSA:
3071 rc = ospf_te_delete_opaque_lsa(OspfMplsTE.ted, lsa);
3072 break;
3073 default:
3074 rc = 0;
3075 break;
3076 }
3077
3078 return rc;
3079}
3080
3081/**
3082 * Send the whole Link State Traffic Engineering Database to the consumer that
3083 * request it through a ZAPI Link State Synchronous Opaque Message.
3084 *
3085 * @param info ZAPI Opaque message
3086 *
3087 * @return 0 if success, -1 otherwise
3088 */
3089int ospf_te_sync_ted(struct zapi_opaque_reg_info dst)
3090{
3091 int rc = -1;
3092
3093 /* Check that MPLS-TE and TE distribution are enabled */
3094 if (!OspfMplsTE.enabled || !OspfMplsTE.export)
3095 return rc;
3096
3097 rc = ls_sync_ted(OspfMplsTE.ted, zclient, &dst);
3098
3099 return rc;
3100}
3101
3102/**
3103 * Initialize Traffic Engineering Database from the various OSPF Link State
3104 * Database (LSDB).
3105 *
3106 * @param ted Link State Traffice Engineering Database
3107 * @param ospf OSPF main structure
3108 */
3109static void ospf_te_init_ted(struct ls_ted *ted, struct ospf *ospf)
3110{
3111 struct listnode *node, *nnode;
3112 struct route_node *rn;
3113 struct ospf_area *area;
3114 struct ospf_lsa *lsa;
3115
3116 /* Iterate over all areas. */
3117 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
3118 if (!area->lsdb)
3119 continue;
3120
3121 /* Parse all Router LSAs from the area LSDB */
3122 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
3123 ospf_te_parse_router_lsa(ted, lsa);
3124
3125 /* Parse all Opaque LSAs from the area LSDB */
3126 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
3127 ospf_te_parse_opaque_lsa(ted, lsa);
3128 }
3129
3130 /* Parse AS-external opaque LSAs from OSPF LSDB */
3131 if (ospf->lsdb) {
3132 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
3133 ospf_te_parse_opaque_lsa(ted, lsa);
3134 }
3135
3136}
3137
3138/*------------------------------------------------------------------------*
78dfa0c7 3139 * Following are vty session control functions.
f173deb3 3140 *------------------------------------------------------------------------*/
8db278b5
OD
3141#define check_tlv_size(size, msg) \
3142 do { \
3143 if (ntohs(tlvh->length) > size) { \
3144 if (vty != NULL) \
3145 vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
3146 msg, ntohs(tlvh->length), size); \
3147 else \
55370b95 3148 zlog_debug(" Wrong %s TLV size: %d(%d)", \
8db278b5
OD
3149 msg, ntohs(tlvh->length), size); \
3150 return size + TLV_HDR_SIZE; \
3151 } \
55370b95 3152 } while (0)
f173deb3
OD
3153
3154static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
3155{
3156 struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
3157
8db278b5
OD
3158 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Router Address");
3159
f173deb3
OD
3160 if (vty != NULL)
3161 vty_out(vty, " Router-Address: %pI4\n", &top->value);
3162 else
3163 zlog_debug(" Router-Address: %pI4", &top->value);
3164
3165 return TLV_SIZE(tlvh);
3166}
3167
8db278b5
OD
3168static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh,
3169 size_t buf_size)
f173deb3
OD
3170{
3171 struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
3172
8db278b5
OD
3173 if (TLV_SIZE(tlvh) > buf_size) {
3174 if (vty != NULL)
3175 vty_out(vty,
3176 " TLV size %d exceeds buffer size. Abort!",
3177 TLV_SIZE(tlvh));
3178 else
3179 zlog_debug(
3180 " TLV size %d exceeds buffer size. Abort!",
3181 TLV_SIZE(tlvh));
3182 return buf_size;
3183 }
3184
f173deb3
OD
3185 if (vty != NULL)
3186 vty_out(vty, " Link: %u octets of data\n",
3187 ntohs(top->header.length));
3188 else
3189 zlog_debug(" Link: %u octets of data",
3190 ntohs(top->header.length));
3191
3192 return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
3193}
3194
3195static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
3196 struct tlv_header *tlvh)
3197{
3198 struct te_link_subtlv_link_type *top;
3199 const char *cp = "Unknown";
3200
8db278b5
OD
3201 check_tlv_size(TE_LINK_SUBTLV_TYPE_SIZE, "Link Type");
3202
f173deb3
OD
3203 top = (struct te_link_subtlv_link_type *)tlvh;
3204 switch (top->link_type.value) {
3205 case LINK_TYPE_SUBTLV_VALUE_PTP:
3206 cp = "Point-to-point";
3207 break;
3208 case LINK_TYPE_SUBTLV_VALUE_MA:
3209 cp = "Multiaccess";
3210 break;
3211 default:
3212 break;
3213 }
3214
3215 if (vty != NULL)
3216 vty_out(vty, " Link-Type: %s (%u)\n", cp,
3217 top->link_type.value);
3218 else
3219 zlog_debug(" Link-Type: %s (%u)", cp, top->link_type.value);
3220
3221 return TLV_SIZE(tlvh);
3222}
3223
3224static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
3225 struct tlv_header *tlvh)
3226{
3227 struct te_link_subtlv_link_id *top;
3228
8db278b5
OD
3229 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link ID");
3230
f173deb3
OD
3231 top = (struct te_link_subtlv_link_id *)tlvh;
3232 if (vty != NULL)
3233 vty_out(vty, " Link-ID: %pI4\n", &top->value);
3234 else
3235 zlog_debug(" Link-ID: %pI4", &top->value);
3236
3237 return TLV_SIZE(tlvh);
3238}
3239
3240static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
8db278b5
OD
3241 struct tlv_header *tlvh,
3242 size_t buf_size)
f173deb3
OD
3243{
3244 struct te_link_subtlv_lclif_ipaddr *top;
3245 int i, n;
3246
8db278b5
OD
3247 if (TLV_SIZE(tlvh) > buf_size) {
3248 if (vty != NULL)
3249 vty_out(vty,
3250 " TLV size %d exceeds buffer size. Abort!",
3251 TLV_SIZE(tlvh));
3252 else
3253 zlog_debug(
3254 " TLV size %d exceeds buffer size. Abort!",
3255 TLV_SIZE(tlvh));
3256 return buf_size;
3257 }
3258
f173deb3
OD
3259 top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
3260 n = ntohs(tlvh->length) / sizeof(top->value[0]);
3261
3262 if (vty != NULL)
3263 vty_out(vty, " Local Interface IP Address(es): %d\n", n);
3264 else
3265 zlog_debug(" Local Interface IP Address(es): %d", n);
3266
3267 for (i = 0; i < n; i++) {
3268 if (vty != NULL)
3269 vty_out(vty, " #%d: %pI4\n", i, &top->value[i]);
3270 else
3271 zlog_debug(" #%d: %pI4", i, &top->value[i]);
3272 }
3273 return TLV_SIZE(tlvh);
3274}
3275
3276static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
8db278b5
OD
3277 struct tlv_header *tlvh,
3278 size_t buf_size)
f173deb3
OD
3279{
3280 struct te_link_subtlv_rmtif_ipaddr *top;
3281 int i, n;
3282
8db278b5
OD
3283 if (TLV_SIZE(tlvh) > buf_size) {
3284 if (vty != NULL)
3285 vty_out(vty,
3286 " TLV size %d exceeds buffer size. Abort!",
3287 TLV_SIZE(tlvh));
3288 else
3289 zlog_debug(
3290 " TLV size %d exceeds buffer size. Abort!",
3291 TLV_SIZE(tlvh));
3292 return buf_size;
3293 }
3294
f173deb3
OD
3295 top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
3296 n = ntohs(tlvh->length) / sizeof(top->value[0]);
3297 if (vty != NULL)
3298 vty_out(vty, " Remote Interface IP Address(es): %d\n", n);
3299 else
3300 zlog_debug(" Remote Interface IP Address(es): %d", n);
3301
3302 for (i = 0; i < n; i++) {
3303 if (vty != NULL)
3304 vty_out(vty, " #%d: %pI4\n", i, &top->value[i]);
3305 else
3306 zlog_debug(" #%d: %pI4", i, &top->value[i]);
3307 }
3308 return TLV_SIZE(tlvh);
3309}
3310
3311static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
3312 struct tlv_header *tlvh)
3313{
3314 struct te_link_subtlv_te_metric *top;
3315
8db278b5
OD
3316 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "TE Metric");
3317
f173deb3
OD
3318 top = (struct te_link_subtlv_te_metric *)tlvh;
3319 if (vty != NULL)
3320 vty_out(vty, " Traffic Engineering Metric: %u\n",
3321 (uint32_t)ntohl(top->value));
3322 else
3323 zlog_debug(" Traffic Engineering Metric: %u",
3324 (uint32_t)ntohl(top->value));
3325
3326 return TLV_SIZE(tlvh);
3327}
3328
3329static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
3330 struct tlv_header *tlvh)
3331{
3332 struct te_link_subtlv_max_bw *top;
3333 float fval;
3334
8db278b5
OD
3335 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Bandwidth");
3336
f173deb3
OD
3337 top = (struct te_link_subtlv_max_bw *)tlvh;
3338 fval = ntohf(top->value);
3339
3340 if (vty != NULL)
3341 vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval);
3342 else
3343 zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval);
3344
3345 return TLV_SIZE(tlvh);
3346}
3347
3348static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
3349 struct tlv_header *tlvh)
3350{
3351 struct te_link_subtlv_max_rsv_bw *top;
3352 float fval;
3353
8db278b5
OD
3354 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Reservable Bandwidth");
3355
f173deb3
OD
3356 top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
3357 fval = ntohf(top->value);
3358
3359 if (vty != NULL)
3360 vty_out(vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
3361 fval);
3362 else
3363 zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)",
3364 fval);
3365
3366 return TLV_SIZE(tlvh);
3367}
3368
3369static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
3370 struct tlv_header *tlvh)
3371{
3372 struct te_link_subtlv_unrsv_bw *top;
3373 float fval1, fval2;
3374 int i;
3375
8db278b5
OD
3376 check_tlv_size(TE_LINK_SUBTLV_UNRSV_SIZE, "Unreserved Bandwidth");
3377
f173deb3
OD
3378 top = (struct te_link_subtlv_unrsv_bw *)tlvh;
3379 if (vty != NULL)
3380 vty_out(vty,
3381 " Unreserved Bandwidth per Class Type in Byte/s:\n");
3382 else
3383 zlog_debug(
3384 " Unreserved Bandwidth per Class Type in Byte/s:");
3385 for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
3386 fval1 = ntohf(top->value[i]);
3387 fval2 = ntohf(top->value[i + 1]);
3388
3389 if (vty != NULL)
3390 vty_out(vty,
3391 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
3392 i, fval1, i + 1, fval2);
3393 else
3394 zlog_debug(
3395 " [%d]: %g (Bytes/sec), [%d]: %g (Bytes/sec)",
3396 i, fval1, i + 1, fval2);
3397 }
3398
3399 return TLV_SIZE(tlvh);
3400}
3401
3402static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
3403 struct tlv_header *tlvh)
3404{
3405 struct te_link_subtlv_rsc_clsclr *top;
3406
8db278b5
OD
3407 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Resource class/color");
3408
f173deb3
OD
3409 top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
3410 if (vty != NULL)
3411 vty_out(vty, " Resource class/color: 0x%x\n",
3412 (uint32_t)ntohl(top->value));
3413 else
3414 zlog_debug(" Resource Class/Color: 0x%x",
3415 (uint32_t)ntohl(top->value));
3416
3417 return TLV_SIZE(tlvh);
3418}
3419
3420static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
3421 struct tlv_header *tlvh)
3422{
3423 struct te_link_subtlv_lrrid *top;
3424
8db278b5
OD
3425 check_tlv_size(TE_LINK_SUBTLV_LRRID_SIZE, "Local/Remote Router ID");
3426
f173deb3
OD
3427 top = (struct te_link_subtlv_lrrid *)tlvh;
3428
3429 if (vty != NULL) {
3430 vty_out(vty, " Local TE Router ID: %pI4\n",
3431 &top->local);
3432 vty_out(vty, " Remote TE Router ID: %pI4\n",
3433 &top->remote);
3434 } else {
3435 zlog_debug(" Local TE Router ID: %pI4",
3436 &top->local);
3437 zlog_debug(" Remote TE Router ID: %pI4",
3438 &top->remote);
3439 }
3440
3441 return TLV_SIZE(tlvh);
16f1b9ee
OD
3442}
3443
d7c0a89a
QY
3444static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
3445 struct tlv_header *tlvh)
16f1b9ee 3446{
d62a17ae 3447 struct te_link_subtlv_llri *top;
16f1b9ee 3448
8db278b5
OD
3449 check_tlv_size(TE_LINK_SUBTLV_LLRI_SIZE, "Link Local/Remote ID");
3450
d62a17ae 3451 top = (struct te_link_subtlv_llri *)tlvh;
16f1b9ee 3452
d62a17ae 3453 if (vty != NULL) {
3454 vty_out(vty, " Link Local ID: %d\n",
d7c0a89a 3455 (uint32_t)ntohl(top->local));
d62a17ae 3456 vty_out(vty, " Link Remote ID: %d\n",
d7c0a89a 3457 (uint32_t)ntohl(top->remote));
d62a17ae 3458 } else {
3459 zlog_debug(" Link Local ID: %d",
d7c0a89a 3460 (uint32_t)ntohl(top->local));
d62a17ae 3461 zlog_debug(" Link Remote ID: %d",
d7c0a89a 3462 (uint32_t)ntohl(top->remote));
d62a17ae 3463 }
16f1b9ee 3464
d62a17ae 3465 return TLV_SIZE(tlvh);
16f1b9ee
OD
3466}
3467
d7c0a89a
QY
3468static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
3469 struct tlv_header *tlvh)
16f1b9ee 3470{
d62a17ae 3471 struct te_link_subtlv_rip *top;
16f1b9ee 3472
8db278b5
OD
3473 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote ASBR Address");
3474
d62a17ae 3475 top = (struct te_link_subtlv_rip *)tlvh;
16f1b9ee 3476
d62a17ae 3477 if (vty != NULL)
96b663a3
MS
3478 vty_out(vty, " Inter-AS TE Remote ASBR IP address: %pI4\n",
3479 &top->value);
d62a17ae 3480 else
96b663a3
MS
3481 zlog_debug(" Inter-AS TE Remote ASBR IP address: %pI4",
3482 &top->value);
16f1b9ee 3483
d62a17ae 3484 return TLV_SIZE(tlvh);
16f1b9ee
OD
3485}
3486
d7c0a89a
QY
3487static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
3488 struct tlv_header *tlvh)
16f1b9ee 3489{
d62a17ae 3490 struct te_link_subtlv_ras *top;
16f1b9ee 3491
8db278b5
OD
3492 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote AS number");
3493
d62a17ae 3494 top = (struct te_link_subtlv_ras *)tlvh;
16f1b9ee 3495
d62a17ae 3496 if (vty != NULL)
3497 vty_out(vty, " Inter-AS TE Remote AS number: %u\n",
3498 ntohl(top->value));
3499 else
3500 zlog_debug(" Inter-AS TE Remote AS number: %u",
3501 ntohl(top->value));
16f1b9ee 3502
d62a17ae 3503 return TLV_SIZE(tlvh);
16f1b9ee
OD
3504}
3505
d7c0a89a
QY
3506static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
3507 struct tlv_header *tlvh)
16f1b9ee 3508{
d62a17ae 3509 struct te_link_subtlv_av_delay *top;
d7c0a89a
QY
3510 uint32_t delay;
3511 uint32_t anomalous;
16f1b9ee 3512
8db278b5
OD
3513 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Average Link Delay");
3514
d62a17ae 3515 top = (struct te_link_subtlv_av_delay *)tlvh;
d7c0a89a
QY
3516 delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
3517 anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
16f1b9ee 3518
d62a17ae 3519 if (vty != NULL)
3520 vty_out(vty, " %s Average Link Delay: %d (micro-sec)\n",
3521 anomalous ? "Anomalous" : "Normal", delay);
3522 else
3523 zlog_debug(" %s Average Link Delay: %d (micro-sec)",
3524 anomalous ? "Anomalous" : "Normal", delay);
16f1b9ee 3525
d62a17ae 3526 return TLV_SIZE(tlvh);
16f1b9ee
OD
3527}
3528
d7c0a89a
QY
3529static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
3530 struct tlv_header *tlvh)
16f1b9ee 3531{
d62a17ae 3532 struct te_link_subtlv_mm_delay *top;
d7c0a89a
QY
3533 uint32_t low, high;
3534 uint32_t anomalous;
16f1b9ee 3535
8db278b5
OD
3536 check_tlv_size(TE_LINK_SUBTLV_MM_DELAY_SIZE, "Min/Max Link Delay");
3537
d62a17ae 3538 top = (struct te_link_subtlv_mm_delay *)tlvh;
d7c0a89a
QY
3539 low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
3540 anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
3541 high = (uint32_t)ntohl(top->high);
16f1b9ee 3542
d62a17ae 3543 if (vty != NULL)
3544 vty_out(vty, " %s Min/Max Link Delay: %d/%d (micro-sec)\n",
3545 anomalous ? "Anomalous" : "Normal", low, high);
3546 else
3547 zlog_debug(" %s Min/Max Link Delay: %d/%d (micro-sec)",
3548 anomalous ? "Anomalous" : "Normal", low, high);
16f1b9ee 3549
d62a17ae 3550 return TLV_SIZE(tlvh);
16f1b9ee
OD
3551}
3552
d7c0a89a
QY
3553static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
3554 struct tlv_header *tlvh)
16f1b9ee 3555{
d62a17ae 3556 struct te_link_subtlv_delay_var *top;
d7c0a89a 3557 uint32_t jitter;
16f1b9ee 3558
8db278b5
OD
3559 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Delay Variation");
3560
d62a17ae 3561 top = (struct te_link_subtlv_delay_var *)tlvh;
d7c0a89a 3562 jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
16f1b9ee 3563
d62a17ae 3564 if (vty != NULL)
3565 vty_out(vty, " Delay Variation: %d (micro-sec)\n", jitter);
3566 else
3567 zlog_debug(" Delay Variation: %d (micro-sec)", jitter);
16f1b9ee 3568
d62a17ae 3569 return TLV_SIZE(tlvh);
16f1b9ee
OD
3570}
3571
d7c0a89a
QY
3572static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
3573 struct tlv_header *tlvh)
16f1b9ee 3574{
d62a17ae 3575 struct te_link_subtlv_pkt_loss *top;
d7c0a89a
QY
3576 uint32_t loss;
3577 uint32_t anomalous;
d62a17ae 3578 float fval;
16f1b9ee 3579
8db278b5
OD
3580 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Loss");
3581
d62a17ae 3582 top = (struct te_link_subtlv_pkt_loss *)tlvh;
d7c0a89a 3583 loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
d62a17ae 3584 fval = (float)(loss * LOSS_PRECISION);
d7c0a89a 3585 anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
16f1b9ee 3586
d62a17ae 3587 if (vty != NULL)
3588 vty_out(vty, " %s Link Loss: %g (%%)\n",
3589 anomalous ? "Anomalous" : "Normal", fval);
3590 else
3591 zlog_debug(" %s Link Loss: %g (%%)",
3592 anomalous ? "Anomalous" : "Normal", fval);
16f1b9ee 3593
d62a17ae 3594 return TLV_SIZE(tlvh);
16f1b9ee
OD
3595}
3596
d7c0a89a
QY
3597static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
3598 struct tlv_header *tlvh)
16f1b9ee 3599{
d62a17ae 3600 struct te_link_subtlv_res_bw *top;
3601 float fval;
16f1b9ee 3602
8db278b5
OD
3603 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Residual Bandwidth");
3604
d62a17ae 3605 top = (struct te_link_subtlv_res_bw *)tlvh;
3606 fval = ntohf(top->value);
16f1b9ee 3607
d62a17ae 3608 if (vty != NULL)
3609 vty_out(vty,
3610 " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
3611 fval);
3612 else
3613 zlog_debug(
3614 " Unidirectional Residual Bandwidth: %g (Bytes/sec)",
3615 fval);
3616
3617 return TLV_SIZE(tlvh);
3618}
3619
d7c0a89a
QY
3620static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
3621 struct tlv_header *tlvh)
d62a17ae 3622{
3623 struct te_link_subtlv_ava_bw *top;
3624 float fval;
3625
8db278b5
OD
3626 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Available Bandwidth");
3627
d62a17ae 3628 top = (struct te_link_subtlv_ava_bw *)tlvh;
3629 fval = ntohf(top->value);
3630
3631 if (vty != NULL)
3632 vty_out(vty,
3633 " Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
3634 fval);
3635 else
3636 zlog_debug(
3637 " Unidirectional Available Bandwidth: %g (Bytes/sec)",
3638 fval);
3639
3640 return TLV_SIZE(tlvh);
3641}
3642
d7c0a89a
QY
3643static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
3644 struct tlv_header *tlvh)
d62a17ae 3645{
3646 struct te_link_subtlv_use_bw *top;
3647 float fval;
3648
8db278b5
OD
3649 check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Utilized Bandwidth");
3650
d62a17ae 3651 top = (struct te_link_subtlv_use_bw *)tlvh;
3652 fval = ntohf(top->value);
3653
3654 if (vty != NULL)
3655 vty_out(vty,
3656 " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
3657 fval);
3658 else
3659 zlog_debug(
3660 " Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
3661 fval);
3662
3663 return TLV_SIZE(tlvh);
3664}
3665
8db278b5
OD
3666static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
3667 size_t buf_size)
d62a17ae 3668{
8db278b5
OD
3669 if (TLV_SIZE(tlvh) > buf_size) {
3670 if (vty != NULL)
3671 vty_out(vty,
3672 " TLV size %d exceeds buffer size. Abort!",
3673 TLV_SIZE(tlvh));
3674 else
3675 zlog_debug(
3676 " TLV size %d exceeds buffer size. Abort!",
3677 TLV_SIZE(tlvh));
3678 return buf_size;
3679 }
3680
d62a17ae 3681 if (vty != NULL)
3682 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
3683 ntohs(tlvh->type), ntohs(tlvh->length));
3684 else
3685 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
3686 ntohs(tlvh->type), ntohs(tlvh->length));
3687
3688 return TLV_SIZE(tlvh);
3689}
3690
d7c0a89a
QY
3691static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
3692 struct tlv_header *tlvh0,
3693 uint16_t subtotal, uint16_t total)
d62a17ae 3694{
9df48e81 3695 struct tlv_header *tlvh;
d7c0a89a 3696 uint16_t sum = subtotal;
d62a17ae 3697
8db278b5 3698 for (tlvh = tlvh0; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 3699 switch (ntohs(tlvh->type)) {
3700 case TE_LINK_SUBTLV_LINK_TYPE:
3701 sum += show_vty_link_subtlv_link_type(vty, tlvh);
3702 break;
3703 case TE_LINK_SUBTLV_LINK_ID:
3704 sum += show_vty_link_subtlv_link_id(vty, tlvh);
3705 break;
3706 case TE_LINK_SUBTLV_LCLIF_IPADDR:
8db278b5
OD
3707 sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh,
3708 total - sum);
d62a17ae 3709 break;
3710 case TE_LINK_SUBTLV_RMTIF_IPADDR:
8db278b5
OD
3711 sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh,
3712 total - sum);
d62a17ae 3713 break;
3714 case TE_LINK_SUBTLV_TE_METRIC:
3715 sum += show_vty_link_subtlv_te_metric(vty, tlvh);
3716 break;
3717 case TE_LINK_SUBTLV_MAX_BW:
3718 sum += show_vty_link_subtlv_max_bw(vty, tlvh);
3719 break;
3720 case TE_LINK_SUBTLV_MAX_RSV_BW:
3721 sum += show_vty_link_subtlv_max_rsv_bw(vty, tlvh);
3722 break;
3723 case TE_LINK_SUBTLV_UNRSV_BW:
3724 sum += show_vty_link_subtlv_unrsv_bw(vty, tlvh);
3725 break;
3726 case TE_LINK_SUBTLV_RSC_CLSCLR:
3727 sum += show_vty_link_subtlv_rsc_clsclr(vty, tlvh);
3728 break;
3729 case TE_LINK_SUBTLV_LRRID:
3730 sum += show_vty_link_subtlv_lrrid(vty, tlvh);
3731 break;
3732 case TE_LINK_SUBTLV_LLRI:
3733 sum += show_vty_link_subtlv_llri(vty, tlvh);
3734 break;
3735 case TE_LINK_SUBTLV_RIP:
3736 sum += show_vty_link_subtlv_rip(vty, tlvh);
3737 break;
3738 case TE_LINK_SUBTLV_RAS:
3739 sum += show_vty_link_subtlv_ras(vty, tlvh);
3740 break;
3741 case TE_LINK_SUBTLV_AV_DELAY:
3742 sum += show_vty_link_subtlv_av_delay(vty, tlvh);
3743 break;
3744 case TE_LINK_SUBTLV_MM_DELAY:
3745 sum += show_vty_link_subtlv_mm_delay(vty, tlvh);
3746 break;
3747 case TE_LINK_SUBTLV_DELAY_VAR:
3748 sum += show_vty_link_subtlv_delay_var(vty, tlvh);
3749 break;
3750 case TE_LINK_SUBTLV_PKT_LOSS:
3751 sum += show_vty_link_subtlv_pkt_loss(vty, tlvh);
3752 break;
3753 case TE_LINK_SUBTLV_RES_BW:
3754 sum += show_vty_link_subtlv_res_bw(vty, tlvh);
3755 break;
3756 case TE_LINK_SUBTLV_AVA_BW:
3757 sum += show_vty_link_subtlv_ava_bw(vty, tlvh);
3758 break;
3759 case TE_LINK_SUBTLV_USE_BW:
3760 sum += show_vty_link_subtlv_use_bw(vty, tlvh);
3761 break;
3762 default:
8db278b5 3763 sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
d62a17ae 3764 break;
3765 }
3766 }
3767 return sum;
3768}
3769
3e63092b
RW
3770static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json,
3771 struct ospf_lsa *lsa)
d62a17ae 3772{
c4efd0f4 3773 struct lsa_header *lsah = lsa->data;
ead99d5f 3774 struct tlv_header *tlvh, *next;
d7c0a89a
QY
3775 uint16_t sum, total;
3776 uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
3777 uint16_t subtotal, uint16_t total) = NULL;
d62a17ae 3778
3e63092b
RW
3779 if (json)
3780 return;
3781
d62a17ae 3782 sum = 0;
8db278b5 3783 total = lsa->size - OSPF_LSA_HEADER_SIZE;
d62a17ae 3784
8db278b5 3785 for (tlvh = TLV_HDR_TOP(lsah); sum < total && tlvh;
d62a17ae 3786 tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
3787 if (subfunc != NULL) {
3788 sum = (*subfunc)(vty, tlvh, sum, total);
ead99d5f 3789 next = (struct tlv_header *)((char *)tlvh + sum);
d62a17ae 3790 subfunc = NULL;
3791 continue;
3792 }
3793
3794 next = NULL;
3795 switch (ntohs(tlvh->type)) {
3796 case TE_TLV_ROUTER_ADDR:
3797 sum += show_vty_router_addr(vty, tlvh);
3798 break;
3799 case TE_TLV_LINK:
8db278b5 3800 sum += show_vty_link_header(vty, tlvh, total - sum);
d62a17ae 3801 subfunc = ospf_mpls_te_show_link_subtlv;
5d0df50f 3802 next = TLV_DATA(tlvh);
d62a17ae 3803 break;
3804 default:
8db278b5 3805 sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
d62a17ae 3806 break;
3807 }
3808 }
3809 return;
3810}
3811
3812static void ospf_mpls_te_config_write_router(struct vty *vty)
3813{
3814
32ab5cf4 3815 if (OspfMplsTE.enabled) {
d62a17ae 3816 vty_out(vty, " mpls-te on\n");
96b663a3
MS
3817 vty_out(vty, " mpls-te router-address %pI4\n",
3818 &OspfMplsTE.router_addr.value);
d62a17ae 3819
f173deb3
OD
3820 if (OspfMplsTE.inter_as == AS)
3821 vty_out(vty, " mpls-te inter-as as\n");
3822 if (OspfMplsTE.inter_as == Area)
3823 vty_out(vty, " mpls-te inter-as area %pI4 \n",
3824 &OspfMplsTE.interas_areaid);
3825 if (OspfMplsTE.export)
3826 vty_out(vty, " mpls-te export\n");
3827 }
d62a17ae 3828 return;
718e3744 3829}
3830
3831/*------------------------------------------------------------------------*
78dfa0c7 3832 * Following are vty command functions.
718e3744 3833 *------------------------------------------------------------------------*/
3834
16f1b9ee
OD
3835DEFUN (ospf_mpls_te_on,
3836 ospf_mpls_te_on_cmd,
3837 "mpls-te on",
3838 MPLS_TE_STR
718e3744 3839 "Enable the MPLS-TE functionality\n")
3840{
a3d826f0 3841 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 3842 struct listnode *node;
3843 struct mpls_te_link *lp;
7c8ff89e 3844
32ab5cf4 3845 if (OspfMplsTE.enabled)
d62a17ae 3846 return CMD_SUCCESS;
718e3744 3847
30ce6361
OD
3848 /* Check that the OSPF is using default VRF */
3849 if (ospf->vrf_id != VRF_DEFAULT) {
3850 vty_out(vty, "MPLS TE is only supported in default VRF\n");
3851 return CMD_WARNING_CONFIG_FAILED;
3852 }
3853
fd3c7692 3854 ote_debug("MPLS-TE: OFF -> ON");
718e3744 3855
32ab5cf4 3856 OspfMplsTE.enabled = true;
718e3744 3857
d62a17ae 3858 /* Reoriginate RFC3630 & RFC6827 Links */
3859 ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
3860 REORIGINATE_THIS_LSA);
718e3744 3861
d62a17ae 3862 /* Reoriginate LSA if INTER-AS is always on */
ead99d5f 3863 if (OspfMplsTE.inter_as != Off) {
d62a17ae 3864 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) {
3865 if (IS_INTER_AS(lp->type)) {
3866 ospf_mpls_te_lsa_schedule(lp,
3867 REORIGINATE_THIS_LSA);
3868 }
3869 }
3870 }
718e3744 3871
f173deb3
OD
3872 /* Create TED and initialize it */
3873 OspfMplsTE.ted = ls_ted_new(1, "OSPF", 0);
3874 if (!OspfMplsTE.ted) {
3875 vty_out(vty, "Unable to create Link State Data Base\n");
3876 return CMD_WARNING;
3877 }
3878 ospf_te_init_ted(OspfMplsTE.ted, ospf);
3879
d62a17ae 3880 return CMD_SUCCESS;
718e3744 3881}
3882
16f1b9ee
OD
3883DEFUN (no_ospf_mpls_te,
3884 no_ospf_mpls_te_cmd,
3a2d747c 3885 "no mpls-te [on]",
718e3744 3886 NO_STR
3a2d747c 3887 MPLS_TE_STR
718e3744 3888 "Disable the MPLS-TE functionality\n")
3889{
a3d826f0 3890 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 3891 struct listnode *node, *nnode;
3892 struct mpls_te_link *lp;
718e3744 3893
32ab5cf4 3894 if (!OspfMplsTE.enabled)
d62a17ae 3895 return CMD_SUCCESS;
718e3744 3896
fd3c7692 3897 ote_debug("MPLS-TE: ON -> OFF");
718e3744 3898
f173deb3 3899 /* Remove TED */
aa5ced0a 3900 ls_ted_del_all(&OspfMplsTE.ted);
32ab5cf4 3901 OspfMplsTE.enabled = false;
718e3744 3902
f173deb3 3903 /* Flush all TE Opaque LSAs */
d62a17ae 3904 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
32ab5cf4
OD
3905 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
3906 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
718e3744 3907
d424f8d8
CG
3908 /*
3909 * This resets the OspfMplsTE.inter_as to its initial state.
3910 * This is to avoid having an inter-as value different from
3911 * Off when mpls-te gets restarted (after being removed)
3912 */
2efd7e2b 3913 OspfMplsTE.inter_as = Off;
d424f8d8 3914
d62a17ae 3915 return CMD_SUCCESS;
718e3744 3916}
3917
16f1b9ee
OD
3918DEFUN (ospf_mpls_te_router_addr,
3919 ospf_mpls_te_router_addr_cmd,
718e3744 3920 "mpls-te router-address A.B.C.D",
16f1b9ee 3921 MPLS_TE_STR
718e3744 3922 "Stable IP address of the advertising router\n"
3923 "MPLS-TE router address in IPv4 address format\n")
3924{
a3d826f0 3925 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 3926 int idx_ipv4 = 2;
3927 struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
3928 struct in_addr value;
3929
3930 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
3931 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
3932 return CMD_WARNING;
3933 }
3934
3935 if (ntohs(ra->header.type) == 0
3936 || ntohl(ra->value.s_addr) != ntohl(value.s_addr)) {
3937 struct listnode *node, *nnode;
3938 struct mpls_te_link *lp;
3939 int need_to_reoriginate = 0;
3940
3941 set_mpls_te_router_addr(value);
3942
32ab5cf4 3943 if (!OspfMplsTE.enabled)
ead99d5f 3944 return CMD_SUCCESS;
d62a17ae 3945
3946 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2efd7e2b 3947 if ((lp->area == NULL) || IS_FLOOD_AS(lp->flags))
d62a17ae 3948 continue;
3949
3950 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
3951 need_to_reoriginate = 1;
3952 break;
3953 }
3954 }
3955
3956 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2efd7e2b 3957 if ((lp->area == NULL) || IS_FLOOD_AS(lp->flags))
d62a17ae 3958 continue;
3959
3960 if (need_to_reoriginate)
3961 SET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
3962 else
3963 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
3964 }
3965
3966 if (need_to_reoriginate)
3967 ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
3968 REORIGINATE_THIS_LSA);
3969 }
ead99d5f 3970
d62a17ae 3971 return CMD_SUCCESS;
3972}
3973
3974static int set_inter_as_mode(struct vty *vty, const char *mode_name,
3975 const char *area_id)
3976{
3977 enum inter_as_mode mode;
3978 struct listnode *node;
3979 struct mpls_te_link *lp;
3980 int format;
3981
32ab5cf4 3982 if (OspfMplsTE.enabled) {
d62a17ae 3983
3984 /* Read and Check inter_as mode */
3985 if (strcmp(mode_name, "as") == 0)
3986 mode = AS;
3987 else if (strcmp(mode_name, "area") == 0) {
3988 mode = Area;
3989 VTY_GET_OSPF_AREA_ID(OspfMplsTE.interas_areaid, format,
3990 area_id);
3991 } else {
3992 vty_out(vty,
3993 "Unknown mode. Please choose between as or area\n");
3994 return CMD_WARNING;
3995 }
3996
fd3c7692
OD
3997 ote_debug(
3998 "MPLS-TE (%s): Inter-AS enable with %s flooding support",
3999 __func__, mode2text[mode]);
d62a17ae 4000
d62a17ae 4001 /* Enable mode and re-originate LSA if needed */
ead99d5f 4002 if ((OspfMplsTE.inter_as == Off)
d62a17ae 4003 && (mode != OspfMplsTE.inter_as)) {
4004 OspfMplsTE.inter_as = mode;
4005 /* Re-originate all InterAS-TEv2 LSA */
4006 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node,
4007 lp)) {
4008 if (IS_INTER_AS(lp->type)) {
4009 if (mode == AS)
2efd7e2b
OD
4010 SET_FLAG(lp->flags,
4011 LPFLG_LSA_FLOOD_AS);
d62a17ae 4012 else
2efd7e2b
OD
4013 UNSET_FLAG(lp->flags,
4014 LPFLG_LSA_FLOOD_AS);
d62a17ae 4015 ospf_mpls_te_lsa_schedule(
4016 lp, REORIGINATE_THIS_LSA);
4017 }
4018 }
4019 } else {
4020 vty_out(vty,
4021 "Please change Inter-AS support to disable first before going to mode %s\n",
4022 mode2text[mode]);
4023 return CMD_WARNING;
4024 }
4025 } else {
4026 vty_out(vty, "mpls-te has not been turned on\n");
4027 return CMD_WARNING;
4028 }
4029 return CMD_SUCCESS;
718e3744 4030}
4031
718e3744 4032
16f1b9ee
OD
4033DEFUN (ospf_mpls_te_inter_as_as,
4034 ospf_mpls_te_inter_as_cmd,
4035 "mpls-te inter-as as",
4036 MPLS_TE_STR
4037 "Configure MPLS-TE Inter-AS support\n"
4038 "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n")
4039{
d62a17ae 4040 return set_inter_as_mode(vty, "as", "");
718e3744 4041}
4042
16f1b9ee
OD
4043DEFUN (ospf_mpls_te_inter_as_area,
4044 ospf_mpls_te_inter_as_area_cmd,
6147e2c6 4045 "mpls-te inter-as area <A.B.C.D|(0-4294967295)>",
16f1b9ee
OD
4046 MPLS_TE_STR
4047 "Configure MPLS-TE Inter-AS support\n"
4048 "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n"
4049 "OSPF area ID in IP format\n"
4050 "OSPF area ID as decimal value\n")
718e3744 4051{
d62a17ae 4052 int idx_ipv4_number = 3;
4053 return set_inter_as_mode(vty, "area", argv[idx_ipv4_number]->arg);
718e3744 4054}
4055
16f1b9ee
OD
4056DEFUN (no_ospf_mpls_te_inter_as,
4057 no_ospf_mpls_te_inter_as_cmd,
4058 "no mpls-te inter-as",
4059 NO_STR
4060 MPLS_TE_STR
4061 "Disable MPLS-TE Inter-AS support\n")
718e3744 4062{
16f1b9ee 4063
d62a17ae 4064 struct listnode *node, *nnode;
4065 struct mpls_te_link *lp;
718e3744 4066
fd3c7692 4067 ote_debug("MPLS-TE: Inter-AS support OFF");
718e3744 4068
996c9314 4069 if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) {
d62a17ae 4070 /* Flush all Inter-AS LSA */
4071 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
4072 if (IS_INTER_AS(lp->type)
4073 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
4074 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
718e3744 4075
e790de41
DT
4076 OspfMplsTE.inter_as = Off;
4077 }
bcf4475e 4078
d62a17ae 4079 return CMD_SUCCESS;
718e3744 4080}
4081
f173deb3
OD
4082DEFUN (ospf_mpls_te_export,
4083 ospf_mpls_te_export_cmd,
4084 "mpls-te export",
4085 MPLS_TE_STR
4086 "Export the MPLS-TE information as Link State\n")
4087{
4088
4089 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
4090
4091 if (OspfMplsTE.enabled) {
4092 if (ls_register(zclient, true) != 0) {
4093 vty_out(vty, "Unable to register Link State\n");
4094 return CMD_WARNING;
4095 }
4096 OspfMplsTE.export = true;
4097 } else {
4098 vty_out(vty, "mpls-te has not been turned on\n");
4099 return CMD_WARNING;
4100 }
4101 return CMD_SUCCESS;
4102}
4103
4104
4105DEFUN (no_ospf_mpls_te_export,
4106 no_ospf_mpls_te_export_cmd,
4107 "no mpls-te export",
4108 NO_STR
4109 MPLS_TE_STR
4110 "Stop export of the MPLS-TE information as Link State\n")
4111{
4112
4113 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
4114
4115 if (OspfMplsTE.export) {
4116 if (ls_unregister(zclient, true) != 0) {
4117 vty_out(vty, "Unable to unregister Link State\n");
4118 return CMD_WARNING;
4119 }
4120 OspfMplsTE.export = false;
4121 }
4122 return CMD_SUCCESS;
4123}
4124
16f1b9ee
OD
4125DEFUN (show_ip_ospf_mpls_te_router,
4126 show_ip_ospf_mpls_te_router_cmd,
4127 "show ip ospf mpls-te router",
718e3744 4128 SHOW_STR
16f1b9ee
OD
4129 IP_STR
4130 OSPF_STR
718e3744 4131 "MPLS-TE information\n"
16f1b9ee 4132 "MPLS-TE Router parameters\n")
718e3744 4133{
32ab5cf4 4134 if (OspfMplsTE.enabled) {
d62a17ae 4135 vty_out(vty, "--- MPLS-TE router parameters ---\n");
4136
4137 if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
4138 show_vty_router_addr(vty,
4139 &OspfMplsTE.router_addr.header);
0af35d90 4140 else
f173deb3
OD
4141 vty_out(vty, " Router address is not set\n");
4142 vty_out(vty, " Link State distribution is %s\n",
4143 OspfMplsTE.export ? "Active" : "Inactive");
d62a17ae 4144 }
4145 return CMD_SUCCESS;
4146}
4147
4148static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
4149{
4150 struct mpls_te_link *lp;
4151
996c9314
LB
4152 if ((OspfMplsTE.enabled) && HAS_LINK_PARAMS(ifp) && !if_is_loopback(ifp)
4153 && if_is_up(ifp)
d62a17ae 4154 && ((lp = lookup_linkparams_by_ifp(ifp)) != NULL)) {
4155 /* Continue only if interface is not passive or support Inter-AS
4156 * TEv2 */
4157 if (!(ospf_oi_count(ifp) > 0)) {
4158 if (IS_INTER_AS(lp->type)) {
4159 vty_out(vty,
4160 "-- Inter-AS TEv2 link parameters for %s --\n",
4161 ifp->name);
4162 } else {
4163 /* MPLS-TE is not activate on this interface */
4164 /* or this interface is passive and Inter-AS
4165 * TEv2 is not activate */
4166 vty_out(vty,
4167 " %s: MPLS-TE is disabled on this interface\n",
4168 ifp->name);
4169 return;
4170 }
4171 } else {
4172 vty_out(vty, "-- MPLS-TE link parameters for %s --\n",
4173 ifp->name);
4174 }
4175
4176 if (TLV_TYPE(lp->link_type) != 0)
4177 show_vty_link_subtlv_link_type(vty,
4178 &lp->link_type.header);
4179 if (TLV_TYPE(lp->link_id) != 0)
4180 show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
4181 if (TLV_TYPE(lp->lclif_ipaddr) != 0)
4182 show_vty_link_subtlv_lclif_ipaddr(
8db278b5
OD
4183 vty, &lp->lclif_ipaddr.header,
4184 lp->lclif_ipaddr.header.length);
d62a17ae 4185 if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
4186 show_vty_link_subtlv_rmtif_ipaddr(
8db278b5
OD
4187 vty, &lp->rmtif_ipaddr.header,
4188 lp->rmtif_ipaddr.header.length);
d62a17ae 4189 if (TLV_TYPE(lp->rip) != 0)
4190 show_vty_link_subtlv_rip(vty, &lp->rip.header);
4191 if (TLV_TYPE(lp->ras) != 0)
4192 show_vty_link_subtlv_ras(vty, &lp->ras.header);
4193 if (TLV_TYPE(lp->te_metric) != 0)
4194 show_vty_link_subtlv_te_metric(vty,
4195 &lp->te_metric.header);
4196 if (TLV_TYPE(lp->max_bw) != 0)
4197 show_vty_link_subtlv_max_bw(vty, &lp->max_bw.header);
4198 if (TLV_TYPE(lp->max_rsv_bw) != 0)
4199 show_vty_link_subtlv_max_rsv_bw(vty,
4200 &lp->max_rsv_bw.header);
4201 if (TLV_TYPE(lp->unrsv_bw) != 0)
4202 show_vty_link_subtlv_unrsv_bw(vty,
4203 &lp->unrsv_bw.header);
4204 if (TLV_TYPE(lp->rsc_clsclr) != 0)
4205 show_vty_link_subtlv_rsc_clsclr(vty,
4206 &lp->rsc_clsclr.header);
4207 if (TLV_TYPE(lp->av_delay) != 0)
4208 show_vty_link_subtlv_av_delay(vty,
4209 &lp->av_delay.header);
4210 if (TLV_TYPE(lp->mm_delay) != 0)
4211 show_vty_link_subtlv_mm_delay(vty,
4212 &lp->mm_delay.header);
4213 if (TLV_TYPE(lp->delay_var) != 0)
4214 show_vty_link_subtlv_delay_var(vty,
4215 &lp->delay_var.header);
4216 if (TLV_TYPE(lp->pkt_loss) != 0)
4217 show_vty_link_subtlv_pkt_loss(vty,
4218 &lp->pkt_loss.header);
4219 if (TLV_TYPE(lp->res_bw) != 0)
4220 show_vty_link_subtlv_res_bw(vty, &lp->res_bw.header);
4221 if (TLV_TYPE(lp->ava_bw) != 0)
4222 show_vty_link_subtlv_ava_bw(vty, &lp->ava_bw.header);
4223 if (TLV_TYPE(lp->use_bw) != 0)
4224 show_vty_link_subtlv_use_bw(vty, &lp->use_bw.header);
4225 vty_out(vty, "---------------\n\n");
4226 } else {
4227 vty_out(vty, " %s: MPLS-TE is disabled on this interface\n",
4228 ifp->name);
4229 }
4230
4231 return;
718e3744 4232}
4233
16f1b9ee
OD
4234DEFUN (show_ip_ospf_mpls_te_link,
4235 show_ip_ospf_mpls_te_link_cmd,
30ce6361 4236 "show ip ospf mpls-te interface [INTERFACE]",
718e3744 4237 SHOW_STR
16f1b9ee
OD
4238 IP_STR
4239 OSPF_STR
718e3744 4240 "MPLS-TE information\n"
4241 "Interface information\n"
4242 "Interface name\n")
4243{
f4e14fdb 4244 struct vrf *vrf;
03ed9f02
PG
4245 int idx_interface = 0;
4246 struct interface *ifp = NULL;
b5a8894d
CS
4247 struct ospf *ospf = NULL;
4248
03ed9f02 4249 argv_find(argv, argc, "INTERFACE", &idx_interface);
30ce6361 4250 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
03ed9f02 4251 if (ospf == NULL || !ospf->oi_running)
b5a8894d 4252 return CMD_SUCCESS;
03ed9f02 4253
30ce6361 4254 vrf = vrf_lookup_by_id(VRF_DEFAULT);
03ed9f02
PG
4255 if (!vrf)
4256 return CMD_SUCCESS;
4257 if (idx_interface) {
30ce6361 4258 ifp = if_lookup_by_name(argv[idx_interface]->arg, VRF_DEFAULT);
03ed9f02
PG
4259 if (ifp == NULL) {
4260 vty_out(vty, "No such interface name in vrf %s\n",
4261 vrf->name);
4262 return CMD_SUCCESS;
43b8d1d8 4263 }
d62a17ae 4264 }
03ed9f02
PG
4265 if (!ifp) {
4266 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 4267 show_mpls_te_link_sub(vty, ifp);
03ed9f02 4268 return CMD_SUCCESS;
d62a17ae 4269 }
4270
03ed9f02 4271 show_mpls_te_link_sub(vty, ifp);
d62a17ae 4272 return CMD_SUCCESS;
4273}
4274
f173deb3
OD
4275DEFUN (show_ip_ospf_mpls_te_db,
4276 show_ip_ospf_mpls_te_db_cmd,
4277 "show ip ospf mpls-te database [<vertex [<self-originate|adv-router A.B.C.D>]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]",
4278 SHOW_STR
4279 IP_STR
4280 OSPF_STR
4281 "MPLS-TE information\n"
4282 "MPLS-TE database\n"
4283 "MPLS-TE Vertex\n"
4284 "Self-originated MPLS-TE router\n"
4285 "Advertised MPLS-TE router\n"
4286 "MPLS-TE router ID (as an IP address)\n"
4287 "MPLS-TE Edge\n"
4288 "MPLS-TE Edge ID (as an IP address)\n"
4289 "MPLS-TE Subnet\n"
4290 "MPLS-TE Subnet ID (as an IP prefix)\n"
4291 "Verbose output\n"
4292 JSON_STR)
4293{
4294 int idx = 0;
4295 struct in_addr ip_addr;
4296 struct prefix pref;
4297 struct ls_vertex *vertex;
4298 struct ls_edge *edge;
4299 struct ls_subnet *subnet;
4300 uint64_t key;
4301 bool verbose = false;
4302 bool uj = use_json(argc, argv);
4303 json_object *json = NULL;
4304
4305 if (!OspfMplsTE.enabled || !OspfMplsTE.ted) {
4306 vty_out(vty, "MPLS-TE database is not enabled\n");
4307 return CMD_WARNING;
4308 }
4309
4310 if (uj)
4311 json = json_object_new_object();
4312
4313 if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
4314 verbose = true;
4315
4316 idx = 5;
4317 if (argv_find(argv, argc, "vertex", &idx)) {
4318 /* Show Vertex */
4319 if (argv_find(argv, argc, "self-originate", &idx))
4320 vertex = OspfMplsTE.ted->self;
4321 else if (argv_find(argv, argc, "adv-router", &idx)) {
4322 if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
4323 vty_out(vty,
4324 "Specified Router ID %s is invalid\n",
4325 argv[idx + 1]->arg);
4326 return CMD_WARNING_CONFIG_FAILED;
4327 }
4328 /* Get the Vertex from the Link State Database */
4329 key = ((uint64_t)ntohl(ip_addr.s_addr)) & 0xffffffff;
4330 vertex = ls_find_vertex_by_key(OspfMplsTE.ted, key);
4331 if (!vertex) {
4332 vty_out(vty, "No vertex found for ID %pI4\n",
4333 &ip_addr);
4334 return CMD_WARNING;
4335 }
4336 } else
4337 vertex = NULL;
4338
4339 if (vertex)
4340 ls_show_vertex(vertex, vty, json, verbose);
4341 else
4342 ls_show_vertices(OspfMplsTE.ted, vty, json, verbose);
4343
4344 } else if (argv_find(argv, argc, "edge", &idx)) {
4345 /* Show Edge */
4346 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
4347 if (!inet_aton(argv[idx]->arg, &ip_addr)) {
4348 vty_out(vty,
4349 "Specified Edge ID %s is invalid\n",
4350 argv[idx]->arg);
4351 return CMD_WARNING_CONFIG_FAILED;
4352 }
4353 /* Get the Edge from the Link State Database */
4354 key = ((uint64_t)ntohl(ip_addr.s_addr)) & 0xffffffff;
4355 edge = ls_find_edge_by_key(OspfMplsTE.ted, key);
4356 if (!edge) {
4357 vty_out(vty, "No edge found for ID %pI4\n",
4358 &ip_addr);
4359 return CMD_WARNING;
4360 }
4361 } else
4362 edge = NULL;
4363
4364 if (edge)
4365 ls_show_edge(edge, vty, json, verbose);
4366 else
4367 ls_show_edges(OspfMplsTE.ted, vty, json, verbose);
4368
4369 } else if (argv_find(argv, argc, "subnet", &idx)) {
4370 /* Show Subnet */
4371 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
4372 if (!str2prefix(argv[idx]->arg, &pref)) {
4373 vty_out(vty, "Invalid prefix format %s\n",
4374 argv[idx]->arg);
4375 return CMD_WARNING_CONFIG_FAILED;
4376 }
4377 /* Get the Subnet from the Link State Database */
b5894669 4378 subnet = ls_find_subnet(OspfMplsTE.ted, &pref);
f173deb3
OD
4379 if (!subnet) {
4380 vty_out(vty, "No subnet found for ID %pFX\n",
4381 &pref);
4382 return CMD_WARNING;
4383 }
4384 } else
4385 subnet = NULL;
4386
4387 if (subnet)
4388 ls_show_subnet(subnet, vty, json, verbose);
4389 else
4390 ls_show_subnets(OspfMplsTE.ted, vty, json, verbose);
4391
4392 } else {
4393 /* Show the complete TED */
4394 ls_show_ted(OspfMplsTE.ted, vty, json, verbose);
4395 }
4396
c48349e3 4397 if (uj)
92ef0078 4398 vty_json(vty, json);
f173deb3
OD
4399 return CMD_SUCCESS;
4400}
4401
d62a17ae 4402static void ospf_mpls_te_register_vty(void)
4403{
4404 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
4405 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
f173deb3 4406 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_db_cmd);
d62a17ae 4407
4408 install_element(OSPF_NODE, &ospf_mpls_te_on_cmd);
4409 install_element(OSPF_NODE, &no_ospf_mpls_te_cmd);
4410 install_element(OSPF_NODE, &ospf_mpls_te_router_addr_cmd);
4411 install_element(OSPF_NODE, &ospf_mpls_te_inter_as_cmd);
4412 install_element(OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd);
4413 install_element(OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd);
f173deb3
OD
4414 install_element(OSPF_NODE, &ospf_mpls_te_export_cmd);
4415 install_element(OSPF_NODE, &no_ospf_mpls_te_export_cmd);
d62a17ae 4416
4417 return;
718e3744 4418}