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