]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_te.c
Merge pull request #8358 from idryzhov/fix-nb-vrf-crash
[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
2156 /* Skip TE Router-ID if present */
2157 if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
2158 tlvh = TLV_HDR_NEXT(tlvh);
2159
2160 /* Check if we have a TE Link TLV */
2161 len = TLV_BODY_SIZE(tlvh);
2162 if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK))
2163 return 0;
2164
2165 sum = 0;
2166 /* Browse sub-TLV and fulfill Link State Attributes */
2167 for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
2168 uint32_t val32, tab32[2];
2169 float valf, tabf[8];
2170 struct in_addr addr;
2171
2172 value = TLV_DATA(tlvh);
2173 switch (ntohs(tlvh->type)) {
2174 case TE_LINK_SUBTLV_LCLIF_IPADDR:
2175 memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
2176 attr.standard.local = addr;
2177 SET_FLAG(attr.flags, LS_ATTR_LOCAL_ADDR);
2178 break;
2179 case TE_LINK_SUBTLV_RMTIF_IPADDR:
2180 memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
2181 attr.standard.remote = addr;
2182 SET_FLAG(attr.flags, LS_ATTR_NEIGH_ADDR);
2183 break;
2184 case TE_LINK_SUBTLV_TE_METRIC:
2185 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2186 attr.standard.te_metric = ntohl(val32);
2187 SET_FLAG(attr.flags, LS_ATTR_TE_METRIC);
2188 break;
2189 case TE_LINK_SUBTLV_MAX_BW:
2190 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2191 attr.standard.max_bw = ntohf(valf);
2192 SET_FLAG(attr.flags, LS_ATTR_MAX_BW);
2193 break;
2194 case TE_LINK_SUBTLV_MAX_RSV_BW:
2195 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2196 attr.standard.max_rsv_bw = ntohf(valf);
2197 SET_FLAG(attr.flags, LS_ATTR_MAX_RSV_BW);
2198 break;
2199 case TE_LINK_SUBTLV_UNRSV_BW:
2200 memcpy(tabf, value, TE_LINK_SUBTLV_UNRSV_SIZE);
2201 for (int i = 0; i < MAX_CLASS_TYPE; i++)
2202 attr.standard.unrsv_bw[i] = ntohf(tabf[i]);
2203 SET_FLAG(attr.flags, LS_ATTR_UNRSV_BW);
2204 break;
2205 case TE_LINK_SUBTLV_RSC_CLSCLR:
2206 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2207 attr.standard.admin_group = ntohl(val32);
2208 SET_FLAG(attr.flags, LS_ATTR_ADM_GRP);
2209 break;
2210 case TE_LINK_SUBTLV_LLRI:
2211 memcpy(tab32, value, TE_LINK_SUBTLV_LLRI_SIZE);
2212 attr.standard.local_id = ntohl(tab32[0]);
2213 attr.standard.remote_id = ntohl(tab32[1]);
2214 SET_FLAG(attr.flags, LS_ATTR_LOCAL_ID);
2215 SET_FLAG(attr.flags, LS_ATTR_NEIGH_ID);
2216 break;
2217 case TE_LINK_SUBTLV_RIP:
2218 memcpy(&addr, value, TE_LINK_SUBTLV_DEF_SIZE);
2219 attr.standard.remote_addr = addr;
2220 SET_FLAG(attr.flags, LS_ATTR_REMOTE_ADDR);
2221 break;
2222 case TE_LINK_SUBTLV_RAS:
2223 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2224 attr.standard.remote_as = ntohl(val32);
2225 SET_FLAG(attr.flags, LS_ATTR_REMOTE_AS);
2226 break;
2227 case TE_LINK_SUBTLV_AV_DELAY:
2228 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2229 attr.extended.delay = ntohl(val32);
2230 SET_FLAG(attr.flags, LS_ATTR_DELAY);
2231 break;
2232 case TE_LINK_SUBTLV_MM_DELAY:
2233 memcpy(tab32, value, TE_LINK_SUBTLV_MM_DELAY_SIZE);
2234 attr.extended.min_delay = ntohl(tab32[0]);
2235 attr.extended.max_delay = ntohl(tab32[1]);
2236 SET_FLAG(attr.flags, LS_ATTR_MIN_MAX_DELAY);
2237 break;
2238 case TE_LINK_SUBTLV_DELAY_VAR:
2239 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2240 attr.extended.jitter = ntohl(val32);
2241 SET_FLAG(attr.flags, LS_ATTR_JITTER);
2242 break;
2243 case TE_LINK_SUBTLV_PKT_LOSS:
2244 memcpy(&val32, value, TE_LINK_SUBTLV_DEF_SIZE);
2245 attr.extended.pkt_loss = ntohl(val32);
2246 SET_FLAG(attr.flags, LS_ATTR_PACKET_LOSS);
2247 break;
2248 case TE_LINK_SUBTLV_RES_BW:
2249 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2250 attr.extended.rsv_bw = ntohf(valf);
2251 SET_FLAG(attr.flags, LS_ATTR_RSV_BW);
2252 break;
2253 case TE_LINK_SUBTLV_AVA_BW:
2254 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2255 attr.extended.ava_bw = ntohf(valf);
2256 SET_FLAG(attr.flags, LS_ATTR_AVA_BW);
2257 break;
2258 case TE_LINK_SUBTLV_USE_BW:
2259 memcpy(&valf, value, TE_LINK_SUBTLV_DEF_SIZE);
2260 attr.extended.used_bw = ntohf(valf);
2261 SET_FLAG(attr.flags, LS_ATTR_USE_BW);
2262 break;
2263 default:
2264 break;
2265 }
2266 sum += TLV_SIZE(tlvh);
2267 }
2268
2269 /* Get corresponding Edge from Link State Data Base */
2270 edge = get_edge(ted, attr.adv, attr.standard.local);
2271 old = edge->attributes;
2272
2273 ote_debug(" |- Process Traffic Engineering LSA %pI4 for Edge %pI4",
2274 &lsa->data->id, &attr.standard.local);
2275
2276 /* Update standard fields */
2277 len = sizeof(struct ls_standard);
2278 if ((attr.flags & 0x0FFFF) == (old->flags & 0x0FFFF)) {
2279 if (memcmp(&attr.standard, &old->standard, len) != 0) {
2280 memcpy(&old->standard, &attr.standard, len);
2281 if (edge->status != NEW)
2282 edge->status = UPDATE;
2283 }
2284 } else {
2285 memcpy(&old->standard, &attr.standard, len);
2286 old->flags |= attr.flags & 0x0FFFF;
2287 if (edge->status != NEW)
2288 edge->status = UPDATE;
2289 }
2290 /* Update extended fields */
2291 len = sizeof(struct ls_extended);
2292 if ((attr.flags & 0x0FF0000) == (old->flags & 0x0FF0000)) {
2293 if (memcmp(&attr.extended, &old->extended, len) != 0) {
2294 memcpy(&old->extended, &attr.extended, len);
2295 if (edge->status != NEW)
2296 edge->status = UPDATE;
2297 }
2298 } else {
2299 memcpy(&old->extended, &attr.extended, len);
2300 old->flags |= attr.flags & 0x0FF0000;
2301 if (edge->status != NEW)
2302 edge->status = UPDATE;
2303 }
2304
2305 /* If LSA is an Opaque Inter-AS, Add Node and Subnet */
2306 lsa_id = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2307 if (lsa_id == OPAQUE_TYPE_INTER_AS_LSA)
2308 ospf_te_update_remote_asbr(ted, edge);
2309
2310 /* Update remote Link if remote IP addr is known */
2311 if (CHECK_FLAG(old->flags, LS_ATTR_NEIGH_ADDR)) {
2312 struct ls_edge *dst;
2313
2314 dst = ls_find_edge_by_destination(ted, old);
2315 /* Attach remote link if not set */
2316 if (dst && edge->source && dst->destination == NULL) {
2317 vertex = edge->source;
2318 if (vertex->incoming_edges)
2319 listnode_add_sort_nodup(vertex->incoming_edges,
2320 dst);
2321 dst->destination = vertex;
2322 }
2323 /* and destination vertex to this edge */
2324 if (dst && dst->source && edge->destination == NULL) {
2325 vertex = dst->source;
2326 if (vertex->incoming_edges)
2327 listnode_add_sort_nodup(vertex->incoming_edges,
2328 edge);
2329 edge->destination = vertex;
2330 }
2331 }
2332
2333 /* Export Link State Edge if needed */
2334 if (edge->status == NEW || edge->status == UPDATE) {
2335 ote_debug(" |- %s TE info. for Edge %pI4",
2336 edge->status == NEW ? "Add" : "Update",
2337 &edge->attributes->standard.local);
2338
2339 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2340 edge->status = SYNC;
2341 }
2342
2343 return 0;
2344}
2345
2346/**
2347 * Delete Link State Attributes information that correspond to the Opaque
2348 * Traffic Engineering LSA (Type 1) TLVs. Note that the Edge is not removed.
2349 *
2350 * @param ted Link State Traffic Engineering Database
2351 * @param lsa OSPF Link State Advertisement
2352 *
2353 * @return 0 if success, -1 otherwise
2354 */
2355static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
2356{
2357 struct ls_edge *edge;
2358 struct ls_attributes *attr;
2359 struct tlv_header *tlvh;
2360 struct in_addr addr;
2361 uint64_t key = 0;
2362 uint16_t len, sum;
2363 uint8_t lsa_id;
2364
2365 /* Initialize TLV browsing */
2366 tlvh = TLV_HDR_TOP(lsa->data);
2367 /* Skip Router TE ID if present */
2368 if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
2369 tlvh = TLV_HDR_NEXT(tlvh);
2370 len = TLV_BODY_SIZE(tlvh);
2371 sum = 0;
2372
2373 /* Browse sub-TLV to find Link ID */
2374 for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
2375 if (ntohs(tlvh->type) == TE_LINK_SUBTLV_LCLIF_IPADDR) {
2376 memcpy(&addr, TLV_DATA(tlvh), TE_LINK_SUBTLV_DEF_SIZE);
2377 key = ((uint64_t)ntohl(addr.s_addr)) & 0xffffffff;
2378 break;
2379 }
2380 sum += TLV_SIZE(tlvh);
2381 }
2382 if (key == 0)
2383 return 0;
2384
2385 /* Search Edge that corresponds to the Link ID */
2386 edge = ls_find_edge_by_key(ted, key);
2387 if (!edge || !edge->attributes)
2388 return 0;
2389 attr = edge->attributes;
2390
2391 /* First, remove Remote ASBR and associated Edge & Subnet if any */
2392 lsa_id = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2393 if (lsa_id == OPAQUE_TYPE_INTER_AS_LSA) {
2394 ote_debug(" |- Delete remote ASBR, Edge and Subnet");
2395
2396 if (edge->destination) {
2397 edge->destination->status = DELETE;
2398 ospf_te_export(LS_MSG_TYPE_NODE, edge->destination);
2399 ls_vertex_del_all(ted, edge->destination);
2400 }
2401
2402 ospf_te_delete_subnet(ted, attr->standard.local);
2403
2404 edge->status = DELETE;
2405 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2406 ls_edge_del_all(ted, edge);
2407
2408 return 0;
2409 }
2410
2411 ote_debug(" |- Delete TE info. for Edge %pI4",
2412 &edge->attributes->standard.local);
2413
2414 /* Remove Link State Attributes TE information */
2415 memset(&attr->standard, 0, sizeof(struct ls_standard));
2416 attr->flags &= 0x0FFFF;
2417 memset(&attr->extended, 0, sizeof(struct ls_extended));
2418 attr->flags &= 0x0FF0000;
2419 ls_attributes_srlg_del(attr);
2420
2421 /* Export Edge that has been updated */
2422 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)
2423 || CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
2424 edge->status = UPDATE;
2425 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2426 edge->status = SYNC;
2427 } else {
2428 /* Remove completely the Edge if Segment Routing is not set */
2429 ospf_te_delete_subnet(ted, attr->standard.local);
2430 edge->status = DELETE;
2431 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2432 ls_edge_del_all(ted, edge);
2433 }
2434
2435 return 0;
2436}
2437
2438/**
2439 * Parse Opaque Router Information LSA (Type 4) TLVs and update the
2440 * corresponding Link State Vertex with these information (Segment Routing).
2441 *
2442 * @param ted Link State Traffic Engineering Database
2443 * @param lsa OSPF Link State Advertisement
2444 *
2445 * @return 0 if success, -1 otherwise
2446 */
2447static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
2448{
2449 struct ls_vertex *vertex;
2450 struct ls_node *node;
2451 struct lsa_header *lsah = lsa->data;
2452 struct tlv_header *tlvh;
2453 uint16_t len = 0, sum = 0;
2454
2455 /* Get vertex / Node from LSA Advertised Router ID */
2456 vertex = get_vertex(ted, lsa);
2457 node = vertex->node;
2458
2459 ote_debug(" |- Process Router Information LSA %pI4 for Vertex %pI4",
2460 &lsa->data->id, &node->router_id);
2461
2462 /* Initialize TLV browsing */
2463 len = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
2464 for (tlvh = TLV_HDR_TOP(lsah); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
2465 struct ri_sr_tlv_sr_algorithm *algo;
2466 struct ri_sr_tlv_sid_label_range *range;
2467 struct ri_sr_tlv_node_msd *msd;
2468 uint32_t size, lower;
2469
2470 switch (ntohs(tlvh->type)) {
2471 case RI_SR_TLV_SR_ALGORITHM:
2472 algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
2473
2474 for (int i = 0; i < ntohs(algo->header.length); i++) {
2475 if (CHECK_FLAG(node->flags, LS_NODE_SR)
2476 && (node->algo[i] == algo->value[i]))
2477 continue;
2478
2479 node->algo[i] = algo->value[i];
2480 SET_FLAG(node->flags, LS_NODE_SR);
2481 if (vertex->status != NEW)
2482 vertex->status = UPDATE;
2483 }
2484
2485 /* Reset other Algorithms */
2486 for (int i = ntohs(algo->header.length); i < 2; i++) {
2487 if (vertex->status != NEW
2488 && node->algo[i] != SR_ALGORITHM_UNSET)
2489 vertex->status = UPDATE;
2490 node->algo[i] = SR_ALGORITHM_UNSET;
2491 }
2492
2493 break;
2494
2495 case RI_SR_TLV_SRGB_LABEL_RANGE:
2496 range = (struct ri_sr_tlv_sid_label_range *)tlvh;
2497 size = GET_RANGE_SIZE(ntohl(range->size));
2498 lower = GET_LABEL(ntohl(range->lower.value));
2499 if ((CHECK_FLAG(node->flags, LS_NODE_SR))
2500 && ((node->srgb.range_size == size)
2501 && (node->srgb.lower_bound == lower)))
2502 break;
2503
2504 node->srgb.range_size = size;
2505 node->srgb.lower_bound = lower;
2506 SET_FLAG(node->flags, LS_NODE_SR);
2507 if (vertex->status != NEW)
2508 vertex->status = UPDATE;
2509
2510 break;
2511
2512 case RI_SR_TLV_SRLB_LABEL_RANGE:
2513 range = (struct ri_sr_tlv_sid_label_range *)tlvh;
2514 size = GET_RANGE_SIZE(ntohl(range->size));
2515 lower = GET_LABEL(ntohl(range->lower.value));
2516 if ((CHECK_FLAG(node->flags, LS_NODE_SRLB))
2517 && ((node->srlb.range_size == size)
2518 && (node->srlb.lower_bound == lower)))
2519 break;
2520
2521 node->srlb.range_size = size;
2522 node->srlb.lower_bound = lower;
2523 SET_FLAG(node->flags, LS_NODE_SRLB);
2524 if (vertex->status != NEW)
2525 vertex->status = UPDATE;
2526
2527 break;
2528
2529 case RI_SR_TLV_NODE_MSD:
2530 msd = (struct ri_sr_tlv_node_msd *)tlvh;
2531 if ((CHECK_FLAG(node->flags, LS_NODE_MSD))
2532 && (node->msd == msd->value))
2533 break;
2534
2535 node->msd = msd->value;
2536 SET_FLAG(node->flags, LS_NODE_MSD);
2537 if (vertex->status != NEW)
2538 vertex->status = UPDATE;
2539
2540 break;
2541
2542 default:
2543 break;
2544 }
2545 sum += TLV_SIZE(tlvh);
2546 }
2547
2548 /* Vertex has been created or updated: export it */
2549 if (vertex->status == NEW || vertex->status == UPDATE) {
2550 ote_debug(" |- %s SR info - SRGB[%d/%d] for Vertex %pI4",
2551 vertex->status == NEW ? "Add" : "Update",
2552 vertex->node->srgb.lower_bound,
2553 vertex->node->srgb.range_size,
2554 &vertex->node->router_id);
2555
2556 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
2557 vertex->status = SYNC;
2558 }
2559
2560 return 0;
2561}
2562
2563/**
2564 * Delete Link State Node information (Segment Routing) that correspond to the
2565 * Opaque Router Information LSA (Type 4) TLVs. Note that the Vertex is not
2566 * removed.
2567 *
2568 * @param ted Link State Traffic Engineering Database
2569 * @param lsa OSPF Link State Advertisement
2570 *
2571 * @return 0 if success, -1 otherwise
2572 */
2573static int ospf_te_delete_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
2574{
2575 struct ls_node_id lnid;
2576 struct ls_vertex *vertex;
2577 struct ls_node *node;
2578
2579 /* Search if a Link State Vertex already exist */
2580 lnid.origin = OSPFv2;
2581 lnid.id.ip.addr = lsa->data->adv_router;
2582 lnid.id.ip.area_id = lsa->area->area_id;
2583 vertex = ls_find_vertex_by_id(ted, lnid);
2584 if (!vertex)
2585 return -1;
2586
2587 /* Remove Segment Routing Information if any */
2588 node = vertex->node;
2589 UNSET_FLAG(node->flags, LS_NODE_SR);
2590 memset(&node->srgb, 0, sizeof(struct ls_srgb));
2591 node->algo[0] = SR_ALGORITHM_UNSET;
2592 node->algo[1] = SR_ALGORITHM_UNSET;
2593 UNSET_FLAG(node->flags, LS_NODE_SRLB);
2594 memset(&node->srlb, 0, sizeof(struct ls_srlb));
2595 UNSET_FLAG(node->flags, LS_NODE_MSD);
2596 node->msd = 0;
2597 vertex->status = UPDATE;
2598
2599 ote_debug(" |- Delete SR info. for Vertex %pI4",
2600 &vertex->node->router_id);
2601
2602 /* Vertex has been updated: export it */
2603 ospf_te_export(LS_MSG_TYPE_NODE, vertex);
2604 vertex->status = SYNC;
2605
2606 return 0;
2607}
2608
2609/**
2610 * Parse Opaque Extended Prefix LSA (Type 7) TLVs and update the corresponding
2611 * Link State Subnet with these information (Segment Routing ID).
2612 *
2613 * @param ted Link State Traffic Engineering Database
2614 * @param lsa OSPF Link State Advertisement
2615 *
2616 * @return 0 if success, -1 otherwise
2617 */
2618static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
2619{
2620 struct ls_node_id lnid;
2621 struct ls_subnet *subnet;
2622 struct ls_prefix *ls_pref;
2623 struct prefix pref;
2624 struct ext_tlv_prefix *ext;
2625 struct ext_subtlv_prefix_sid *pref_sid;
2626 uint32_t label;
2627
2628 /* Get corresponding Subnet from Link State Data Base */
2629 ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data);
2630 pref.family = AF_INET;
2631 pref.prefixlen = ext->pref_length;
2632 pref.u.prefix4 = ext->address;
2633 subnet = ls_find_subnet(ted, pref);
2634
2635 /* Create new Link State Prefix if not found */
2636 if (!subnet) {
2637 lnid.origin = OSPFv2;
2638 lnid.id.ip.addr = lsa->data->adv_router;
2639 lnid.id.ip.area_id = lsa->area->area_id;
2640 ls_pref = ls_prefix_new(lnid, pref);
2641 /* and add it to the TED */
2642 subnet = ls_subnet_add(ted, ls_pref);
2643 }
2644
2645 ote_debug(" |- Process Extended Prefix LSA %pI4 for subnet %pFX",
2646 &lsa->data->id, &pref);
2647
2648 /* Initialize TLV browsing */
2649 ls_pref = subnet->ls_pref;
2650 pref_sid = (struct ext_subtlv_prefix_sid *)((char *)(ext) + TLV_HDR_SIZE
2651 + EXT_TLV_PREFIX_SIZE);
2652 label = CHECK_FLAG(pref_sid->flags, EXT_SUBTLV_PREFIX_SID_VFLG)
2653 ? GET_LABEL(ntohl(pref_sid->value))
2654 : ntohl(pref_sid->value);
2655
2656 /* Check if it is a simple refresh */
2657 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)
2658 && ls_pref->sr.algo == pref_sid->algorithm
2659 && ls_pref->sr.sid_flag == pref_sid->flags
2660 && ls_pref->sr.sid == label)
2661 return 0;
2662
2663 /* Fulfill SR information */
2664 ls_pref->sr.algo = pref_sid->algorithm;
2665 ls_pref->sr.sid_flag = pref_sid->flags;
2666 ls_pref->sr.sid = label;
2667 SET_FLAG(ls_pref->flags, LS_PREF_SR);
2668 if (subnet->status != NEW)
2669 subnet->status = UPDATE;
2670
2671 /* Export Subnet if needed */
2672 if (subnet->status == NEW || subnet->status == UPDATE) {
2673 ote_debug(" |- %s SID %d to subnet %pFX",
2674 subnet->status == NEW ? "Add" : "Update",
2675 ls_pref->sr.sid, &ls_pref->pref);
2676
2677 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
2678 subnet->status = SYNC;
2679 }
2680
2681 return 0;
2682}
2683
2684/**
2685 * Delete Link State Subnet information (Segment Routing ID) that correspond to
2686 * the Opaque Extended Prefix LSA (Type 7) TLVs. Note that the Subnet is not
2687 * removed.
2688 *
2689 * @param ted Link State Traffic Engineering Database
2690 * @param lsa OSPF Link State Advertisement
2691 *
2692 * @return 0 if success, -1 otherwise
2693 */
2694static int ospf_te_delete_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
2695{
2696 struct ls_subnet *subnet;
2697 struct ls_prefix *ls_pref;
2698 struct prefix pref;
2699 struct ext_tlv_prefix *ext;
2700
2701 /* Get corresponding Subnet from Link State Data Base */
2702 ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data);
2703 pref.family = AF_INET;
2704 pref.prefixlen = ext->pref_length;
2705 pref.u.prefix4 = ext->address;
2706 subnet = ls_find_subnet(ted, pref);
2707
2708 /* Check if there is a corresponding subnet */
2709 if (!subnet)
2710 return -1;
2711
2712 ote_debug(" |- Delete SID %d to subnet %pFX", subnet->ls_pref->sr.sid,
2713 &subnet->ls_pref->pref);
2714
2715 /* Remove Segment Routing information */
2716 ls_pref = subnet->ls_pref;
2717 UNSET_FLAG(ls_pref->flags, LS_PREF_SR);
2718 memset(&ls_pref->sr, 0, sizeof(struct ls_sid));
2719 subnet->status = UPDATE;
2720
2721 /* Subnet has been updated: export it */
2722 ospf_te_export(LS_MSG_TYPE_PREFIX, subnet);
2723 subnet->status = SYNC;
2724
2725 return 0;
2726}
2727
2728/**
2729 * Parse Opaque Extended Link LSA (Type 8) TLVs and update the corresponding
2730 * Link State Edge with these information (Segment Routing Adjacency).
2731 *
2732 * @param ted Link State Traffic Engineering Database
2733 * @param lsa OSPF Link State Advertisement
2734 *
2735 * @return 0 if success, -1 otherwise
2736 */
2737static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
2738{
2739 struct ls_node_id lnid;
2740 struct tlv_header *tlvh;
2741 struct ext_tlv_link *ext;
2742 struct ls_edge *edge;
2743 struct ls_attributes *atr;
2744 uint16_t len = 0, sum = 0, i;
2745 uint32_t label;
2746
2747 /* Get corresponding Edge from Link State Data Base */
2748 lnid.origin = OSPFv2;
2749 lnid.id.ip.addr = lsa->data->adv_router;
2750 lnid.id.ip.area_id = lsa->area->area_id;
2751 ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data);
2752 edge = get_edge(ted, lnid, ext->link_data);
2753 atr = edge->attributes;
2754
2755 ote_debug(" |- Process Extended Link LSA %pI4 for edge %pI4",
2756 &lsa->data->id, &edge->attributes->standard.local);
2757
2758 /* Initialize TLV browsing */
2759 len = TLV_BODY_SIZE(&ext->header);
2760 tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
2761 + EXT_TLV_LINK_SIZE);
2762 for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
2763 struct ext_subtlv_adj_sid *adj;
2764 struct ext_subtlv_lan_adj_sid *ladj;
2765 struct ext_subtlv_rmt_itf_addr *rmt;
2766
2767 switch (ntohs(tlvh->type)) {
2768 case EXT_SUBTLV_ADJ_SID:
2769 adj = (struct ext_subtlv_adj_sid *)tlvh;
2770 label = CHECK_FLAG(adj->flags,
2771 EXT_SUBTLV_LINK_ADJ_SID_VFLG)
2772 ? GET_LABEL(ntohl(adj->value))
2773 : ntohl(adj->value);
2774 i = CHECK_FLAG(adj->flags,
2775 EXT_SUBTLV_LINK_ADJ_SID_BFLG) ? 1 : 0;
2776 if (((i && CHECK_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID))
2777 || (!i && CHECK_FLAG(atr->flags, LS_ATTR_ADJ_SID)))
2778 && atr->adj_sid[i].flags == adj->flags
2779 && atr->adj_sid[i].sid == label
2780 && atr->adj_sid[i].weight == adj->weight)
2781 break;
2782
2783 atr->adj_sid[i].flags = adj->flags;
2784 atr->adj_sid[i].sid = label;
2785 atr->adj_sid[i].weight = adj->weight;
2786 if (i == 0)
2787 SET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
2788 else
2789 SET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
2790 if (edge->status != NEW)
2791 edge->status = UPDATE;
2792
2793 break;
2794 case EXT_SUBTLV_LAN_ADJ_SID:
2795 ladj = (struct ext_subtlv_lan_adj_sid *)tlvh;
2796 label = CHECK_FLAG(ladj->flags,
2797 EXT_SUBTLV_LINK_ADJ_SID_VFLG)
2798 ? GET_LABEL(ntohl(ladj->value))
2799 : ntohl(ladj->value);
2800 i = CHECK_FLAG(ladj->flags,
2801 EXT_SUBTLV_LINK_ADJ_SID_BFLG) ? 1 : 0;
2802 if (((i && CHECK_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID))
2803 || (!i && CHECK_FLAG(atr->flags, LS_ATTR_ADJ_SID)))
2804 && atr->adj_sid[i].flags == ladj->flags
2805 && atr->adj_sid[i].sid == label
2806 && atr->adj_sid[i].weight == ladj->weight
2807 && IPV4_ADDR_SAME(&atr->adj_sid[1].neighbor.addr,
2808 &ladj->neighbor_id))
2809 break;
2810
2811 atr->adj_sid[i].flags = ladj->flags;
2812 atr->adj_sid[i].sid = label;
2813 atr->adj_sid[i].weight = ladj->weight;
2814 atr->adj_sid[i].neighbor.addr = ladj->neighbor_id;
2815 if (i == 0)
2816 SET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
2817 else
2818 SET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
2819 if (edge->status != NEW)
2820 edge->status = UPDATE;
2821
2822 break;
2823 case EXT_SUBTLV_RMT_ITF_ADDR:
2824 rmt = (struct ext_subtlv_rmt_itf_addr *)tlvh;
2825 if (CHECK_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR)
2826 && IPV4_ADDR_SAME(&atr->standard.remote,
2827 &rmt->value))
2828 break;
2829
2830 atr->standard.remote = rmt->value;
2831 SET_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR);
2832 if (edge->status != NEW)
2833 edge->status = UPDATE;
2834
2835 break;
2836 default:
2837 break;
2838 }
2839 sum += TLV_SIZE(tlvh);
2840 }
2841
2842 /* Export Link State Edge if needed */
2843 if (edge->status == NEW || edge->status == UPDATE) {
2844 ote_debug(" |- %s Adj-SID %d & %d to edge %pI4",
2845 edge->status == NEW ? "Add" : "Update",
2846 edge->attributes->adj_sid[0].sid,
2847 edge->attributes->adj_sid[1].sid,
2848 &edge->attributes->standard.local);
2849
2850 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2851 edge->status = SYNC;
2852 }
2853
2854 return 0;
2855}
2856
2857/**
2858 * Delete Link State Edge information (Segment Routing Adjacency) that
2859 * correspond to the Opaque Extended Link LSA (Type 8) TLVs. Note that the Edge
2860 * is not removed.
2861 *
2862 * @param ted Link State Traffic Engineering Database
2863 * @param lsa OSPF Link State Advertisement
2864 *
2865 * @return 0 if success, -1 otherwise
2866 */
2867static int ospf_te_delete_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
2868{
2869 struct ls_edge *edge;
2870 struct ls_attributes *atr;
2871 struct ext_tlv_link *ext;
2872 uint64_t key;
2873
2874 /* Search for corresponding Edge from Link State Data Base */
2875 ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data);
2876 key = ((uint64_t)ntohl(ext->link_data.s_addr)) & 0xffffffff;
2877 edge = ls_find_edge_by_key(ted, key);
2878
2879 /* Check if there is a corresponding Edge */
2880 if (!edge)
2881 return -1;
2882
2883 ote_debug(" |- Delete Adj-SID %d to edge %pI4",
2884 edge->attributes->adj_sid[0].sid,
2885 &edge->attributes->standard.local);
2886
2887 /* Remove Segment Routing information */
2888 atr = edge->attributes;
2889 UNSET_FLAG(atr->flags, LS_ATTR_ADJ_SID);
2890 UNSET_FLAG(atr->flags, LS_ATTR_BCK_ADJ_SID);
2891 memset(atr->adj_sid, 0, 2 * sizeof(struct ls_sid));
2892 edge->status = UPDATE;
2893
2894 /* Edge has been updated: export it */
2895 ospf_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
2896 edge->status = SYNC;
2897
2898 return 0;
2899}
2900
2901/**
2902 * Parse Opaque LSA Type and call corresponding parser.
2903 *
2904 * @param ted Link State Traffic Engineering Database
2905 * @param lsa OSPF Link State Advertisement
2906 *
2907 * @return 0 if success, -1 otherwise
2908 */
2909static int ospf_te_parse_opaque_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
2910{
2911 uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2912 int rc = -1;
2913
2914 ote_debug("MPLS-TE (%s): Parse Opaque LSA[%pI4] from Router[%pI4]",
2915 __func__, &lsa->data->id, &lsa->data->adv_router);
2916
2917 switch (key) {
2918 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
2919 case OPAQUE_TYPE_INTER_AS_LSA:
2920 rc = ospf_te_parse_te(ted, lsa);
2921 break;
2922 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
2923 rc = ospf_te_parse_ri(ted, lsa);
2924 break;
2925 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
2926 rc = ospf_te_parse_ext_pref(ted, lsa);
2927 break;
2928 case OPAQUE_TYPE_EXTENDED_LINK_LSA:
2929 rc = ospf_te_parse_ext_link(ted, lsa);
2930 break;
2931 default:
2932 break;
2933 }
2934
2935 return rc;
2936}
2937
2938/**
2939 * Parse Opaque LSA Type and call corresponding deletion function.
2940 *
2941 * @param ted Link State Traffic Engineering Database
2942 * @param lsa OSPF Link State Advertisement
2943 *
2944 * @return 0 if success, -1 otherwise
2945 */
2946static int ospf_te_delete_opaque_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
2947{
2948 uint8_t key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr));
2949 int rc = -1;
2950
2951 ote_debug("MPLS-TE (%s): Parse Opaque LSA[%pI4] from Router[%pI4]",
2952 __func__, &lsa->data->id, &lsa->data->adv_router);
2953
2954 switch (key) {
2955 case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
2956 case OPAQUE_TYPE_INTER_AS_LSA:
2957 rc = ospf_te_delete_te(ted, lsa);
2958 break;
2959 case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
2960 rc = ospf_te_delete_ri(ted, lsa);
2961 break;
2962 case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
2963 rc = ospf_te_delete_ext_pref(ted, lsa);
2964 break;
2965 case OPAQUE_TYPE_EXTENDED_LINK_LSA:
2966 rc = ospf_te_delete_ext_link(ted, lsa);
2967 break;
2968 default:
2969 break;
2970 }
2971
2972 return rc;
2973}
2974
2975/**
2976 * Update Traffic Engineering Database Elements that correspond to the received
2977 * OSPF LSA. If LSA age is equal to MAX_AGE, call deletion function instead.
2978 *
2979 * @param lsa OSPF Link State Advertisement
2980 *
2981 * @return 0 if success, -1 otherwise
2982 */
2983static int ospf_mpls_te_lsa_update(struct ospf_lsa *lsa)
2984{
2985
2986 uint8_t rc;
2987
2988 /* Check that MPLS-TE is active */
2989 if (!OspfMplsTE.enabled || !OspfMplsTE.ted)
2990 return 0;
2991
2992 /* Sanity Check */
2993 if (lsa == NULL) {
2994 flog_warn(EC_OSPF_LSA_NULL, "TE (%s): Abort! LSA is NULL",
2995 __func__);
2996 return -1;
2997 }
2998
2999 /* If LSA is MAX_AGE, remove corresponding Link State element */
3000 if (IS_LSA_MAXAGE(lsa)) {
3001 switch (lsa->data->type) {
3002 case OSPF_ROUTER_LSA:
3003 rc = ospf_te_delete_router_lsa(OspfMplsTE.ted, lsa);
3004 break;
3005 case OSPF_OPAQUE_AREA_LSA:
3006 case OSPF_OPAQUE_AS_LSA:
3007 rc = ospf_te_delete_opaque_lsa(OspfMplsTE.ted, lsa);
3008 break;
3009 default:
3010 rc = 0;
3011 break;
3012 }
3013 } else {
3014 /* Parse LSA to Update corresponding Link State element */
3015 switch (lsa->data->type) {
3016 case OSPF_ROUTER_LSA:
3017 rc = ospf_te_parse_router_lsa(OspfMplsTE.ted, lsa);
3018 break;
3019 case OSPF_OPAQUE_AREA_LSA:
3020 case OSPF_OPAQUE_AS_LSA:
3021 rc = ospf_te_parse_opaque_lsa(OspfMplsTE.ted, lsa);
3022 break;
3023 default:
3024 rc = 0;
3025 break;
3026 }
3027 }
3028
3029 return rc;
3030}
3031
3032/**
3033 * Delete Traffic Engineering Database element from OSPF LSA. This function
3034 * process only self LSA (i.e. advertised by the router) which reach MAX_AGE
3035 * as LSA deleted by neighbor routers are Flushed (i.e. advertised with
3036 * age == MAX_AGE) and processed by ospf_mpls_te_lsa_update() function.
3037 *
3038 * @param lsa OSPF Link State Advertisement
3039 *
3040 * @return 0 if success, -1 otherwise
3041 */
3042static int ospf_mpls_te_lsa_delete(struct ospf_lsa *lsa)
3043{
3044
3045 uint8_t rc;
3046
3047 /* Check that MPLS-TE is active */
3048 if (!OspfMplsTE.enabled || !OspfMplsTE.ted)
3049 return 0;
3050
3051 /* Sanity Check */
3052 if (lsa == NULL) {
3053 flog_warn(EC_OSPF_LSA_NULL, "TE (%s): Abort! LSA is NULL",
3054 __func__);
3055 return -1;
3056 }
3057
3058 /*
3059 * Process only self LSAs that reach MAX_AGE. Indeed, when the router
3060 * need to update or refresh an LSA, it first removes the old LSA from
3061 * the LSDB and then insert the new one. Thus, to avoid removing
3062 * corresponding Link State element and loosing some parameters
3063 * instead of just updating it, only self LSAs that reach MAX_AGE are
3064 * processed here. Other LSAs are processed by ospf_mpls_te_lsa_update()
3065 * and eventually removed when LSA age is MAX_AGE i.e. LSA is flushed
3066 * by the originator.
3067 */
3068 if (!IS_LSA_SELF(lsa) || !IS_LSA_MAXAGE(lsa))
3069 return 0;
3070
3071 /* Parse Link State information */
3072 switch (lsa->data->type) {
3073 case OSPF_ROUTER_LSA:
3074 rc = ospf_te_delete_router_lsa(OspfMplsTE.ted, lsa);
3075 break;
3076 case OSPF_OPAQUE_AREA_LSA:
3077 case OSPF_OPAQUE_AS_LSA:
3078 rc = ospf_te_delete_opaque_lsa(OspfMplsTE.ted, lsa);
3079 break;
3080 default:
3081 rc = 0;
3082 break;
3083 }
3084
3085 return rc;
3086}
3087
3088/**
3089 * Send the whole Link State Traffic Engineering Database to the consumer that
3090 * request it through a ZAPI Link State Synchronous Opaque Message.
3091 *
3092 * @param info ZAPI Opaque message
3093 *
3094 * @return 0 if success, -1 otherwise
3095 */
3096int ospf_te_sync_ted(struct zapi_opaque_reg_info dst)
3097{
3098 int rc = -1;
3099
3100 /* Check that MPLS-TE and TE distribution are enabled */
3101 if (!OspfMplsTE.enabled || !OspfMplsTE.export)
3102 return rc;
3103
3104 rc = ls_sync_ted(OspfMplsTE.ted, zclient, &dst);
3105
3106 return rc;
3107}
3108
3109/**
3110 * Initialize Traffic Engineering Database from the various OSPF Link State
3111 * Database (LSDB).
3112 *
3113 * @param ted Link State Traffice Engineering Database
3114 * @param ospf OSPF main structure
3115 */
3116static void ospf_te_init_ted(struct ls_ted *ted, struct ospf *ospf)
3117{
3118 struct listnode *node, *nnode;
3119 struct route_node *rn;
3120 struct ospf_area *area;
3121 struct ospf_lsa *lsa;
3122
3123 /* Iterate over all areas. */
3124 for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
3125 if (!area->lsdb)
3126 continue;
3127
3128 /* Parse all Router LSAs from the area LSDB */
3129 LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
3130 ospf_te_parse_router_lsa(ted, lsa);
3131
3132 /* Parse all Opaque LSAs from the area LSDB */
3133 LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
3134 ospf_te_parse_opaque_lsa(ted, lsa);
3135 }
3136
3137 /* Parse AS-external opaque LSAs from OSPF LSDB */
3138 if (ospf->lsdb) {
3139 LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
3140 ospf_te_parse_opaque_lsa(ted, lsa);
3141 }
3142
3143}
3144
3145/*------------------------------------------------------------------------*
3146 * Followings are vty session control functions.
3147 *------------------------------------------------------------------------*/
3148
3149static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
3150{
3151 struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
3152
3153 if (vty != NULL)
3154 vty_out(vty, " Router-Address: %pI4\n", &top->value);
3155 else
3156 zlog_debug(" Router-Address: %pI4", &top->value);
3157
3158 return TLV_SIZE(tlvh);
3159}
3160
3161static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh)
3162{
3163 struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
3164
3165 if (vty != NULL)
3166 vty_out(vty, " Link: %u octets of data\n",
3167 ntohs(top->header.length));
3168 else
3169 zlog_debug(" Link: %u octets of data",
3170 ntohs(top->header.length));
3171
3172 return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
3173}
3174
3175static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
3176 struct tlv_header *tlvh)
3177{
3178 struct te_link_subtlv_link_type *top;
3179 const char *cp = "Unknown";
3180
3181 top = (struct te_link_subtlv_link_type *)tlvh;
3182 switch (top->link_type.value) {
3183 case LINK_TYPE_SUBTLV_VALUE_PTP:
3184 cp = "Point-to-point";
3185 break;
3186 case LINK_TYPE_SUBTLV_VALUE_MA:
3187 cp = "Multiaccess";
3188 break;
3189 default:
3190 break;
3191 }
3192
3193 if (vty != NULL)
3194 vty_out(vty, " Link-Type: %s (%u)\n", cp,
3195 top->link_type.value);
3196 else
3197 zlog_debug(" Link-Type: %s (%u)", cp, top->link_type.value);
3198
3199 return TLV_SIZE(tlvh);
3200}
3201
3202static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
3203 struct tlv_header *tlvh)
3204{
3205 struct te_link_subtlv_link_id *top;
3206
3207 top = (struct te_link_subtlv_link_id *)tlvh;
3208 if (vty != NULL)
3209 vty_out(vty, " Link-ID: %pI4\n", &top->value);
3210 else
3211 zlog_debug(" Link-ID: %pI4", &top->value);
3212
3213 return TLV_SIZE(tlvh);
3214}
3215
3216static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
3217 struct tlv_header *tlvh)
3218{
3219 struct te_link_subtlv_lclif_ipaddr *top;
3220 int i, n;
3221
3222 top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
3223 n = ntohs(tlvh->length) / sizeof(top->value[0]);
3224
3225 if (vty != NULL)
3226 vty_out(vty, " Local Interface IP Address(es): %d\n", n);
3227 else
3228 zlog_debug(" Local Interface IP Address(es): %d", n);
3229
3230 for (i = 0; i < n; i++) {
3231 if (vty != NULL)
3232 vty_out(vty, " #%d: %pI4\n", i, &top->value[i]);
3233 else
3234 zlog_debug(" #%d: %pI4", i, &top->value[i]);
3235 }
3236 return TLV_SIZE(tlvh);
3237}
3238
3239static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
3240 struct tlv_header *tlvh)
3241{
3242 struct te_link_subtlv_rmtif_ipaddr *top;
3243 int i, n;
3244
3245 top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
3246 n = ntohs(tlvh->length) / sizeof(top->value[0]);
3247 if (vty != NULL)
3248 vty_out(vty, " Remote Interface IP Address(es): %d\n", n);
3249 else
3250 zlog_debug(" Remote Interface IP Address(es): %d", n);
3251
3252 for (i = 0; i < n; i++) {
3253 if (vty != NULL)
3254 vty_out(vty, " #%d: %pI4\n", i, &top->value[i]);
3255 else
3256 zlog_debug(" #%d: %pI4", i, &top->value[i]);
3257 }
3258 return TLV_SIZE(tlvh);
3259}
3260
3261static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
3262 struct tlv_header *tlvh)
3263{
3264 struct te_link_subtlv_te_metric *top;
3265
3266 top = (struct te_link_subtlv_te_metric *)tlvh;
3267 if (vty != NULL)
3268 vty_out(vty, " Traffic Engineering Metric: %u\n",
3269 (uint32_t)ntohl(top->value));
3270 else
3271 zlog_debug(" Traffic Engineering Metric: %u",
3272 (uint32_t)ntohl(top->value));
3273
3274 return TLV_SIZE(tlvh);
3275}
3276
3277static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
3278 struct tlv_header *tlvh)
3279{
3280 struct te_link_subtlv_max_bw *top;
3281 float fval;
3282
3283 top = (struct te_link_subtlv_max_bw *)tlvh;
3284 fval = ntohf(top->value);
3285
3286 if (vty != NULL)
3287 vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval);
3288 else
3289 zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval);
3290
3291 return TLV_SIZE(tlvh);
3292}
3293
3294static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
3295 struct tlv_header *tlvh)
3296{
3297 struct te_link_subtlv_max_rsv_bw *top;
3298 float fval;
3299
3300 top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
3301 fval = ntohf(top->value);
3302
3303 if (vty != NULL)
3304 vty_out(vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
3305 fval);
3306 else
3307 zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)",
3308 fval);
3309
3310 return TLV_SIZE(tlvh);
3311}
3312
3313static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
3314 struct tlv_header *tlvh)
3315{
3316 struct te_link_subtlv_unrsv_bw *top;
3317 float fval1, fval2;
3318 int i;
3319
3320 top = (struct te_link_subtlv_unrsv_bw *)tlvh;
3321 if (vty != NULL)
3322 vty_out(vty,
3323 " Unreserved Bandwidth per Class Type in Byte/s:\n");
3324 else
3325 zlog_debug(
3326 " Unreserved Bandwidth per Class Type in Byte/s:");
3327 for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
3328 fval1 = ntohf(top->value[i]);
3329 fval2 = ntohf(top->value[i + 1]);
3330
3331 if (vty != NULL)
3332 vty_out(vty,
3333 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
3334 i, fval1, i + 1, fval2);
3335 else
3336 zlog_debug(
3337 " [%d]: %g (Bytes/sec), [%d]: %g (Bytes/sec)",
3338 i, fval1, i + 1, fval2);
3339 }
3340
3341 return TLV_SIZE(tlvh);
3342}
3343
3344static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
3345 struct tlv_header *tlvh)
3346{
3347 struct te_link_subtlv_rsc_clsclr *top;
3348
3349 top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
3350 if (vty != NULL)
3351 vty_out(vty, " Resource class/color: 0x%x\n",
3352 (uint32_t)ntohl(top->value));
3353 else
3354 zlog_debug(" Resource Class/Color: 0x%x",
3355 (uint32_t)ntohl(top->value));
3356
3357 return TLV_SIZE(tlvh);
3358}
3359
3360static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
3361 struct tlv_header *tlvh)
3362{
3363 struct te_link_subtlv_lrrid *top;
3364
3365 top = (struct te_link_subtlv_lrrid *)tlvh;
3366
3367 if (vty != NULL) {
3368 vty_out(vty, " Local TE Router ID: %pI4\n",
3369 &top->local);
3370 vty_out(vty, " Remote TE Router ID: %pI4\n",
3371 &top->remote);
3372 } else {
3373 zlog_debug(" Local TE Router ID: %pI4",
3374 &top->local);
3375 zlog_debug(" Remote TE Router ID: %pI4",
3376 &top->remote);
3377 }
3378
3379 return TLV_SIZE(tlvh);
16f1b9ee
OD
3380}
3381
d7c0a89a
QY
3382static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
3383 struct tlv_header *tlvh)
16f1b9ee 3384{
d62a17ae 3385 struct te_link_subtlv_llri *top;
16f1b9ee 3386
d62a17ae 3387 top = (struct te_link_subtlv_llri *)tlvh;
16f1b9ee 3388
d62a17ae 3389 if (vty != NULL) {
3390 vty_out(vty, " Link Local ID: %d\n",
d7c0a89a 3391 (uint32_t)ntohl(top->local));
d62a17ae 3392 vty_out(vty, " Link Remote ID: %d\n",
d7c0a89a 3393 (uint32_t)ntohl(top->remote));
d62a17ae 3394 } else {
3395 zlog_debug(" Link Local ID: %d",
d7c0a89a 3396 (uint32_t)ntohl(top->local));
d62a17ae 3397 zlog_debug(" Link Remote ID: %d",
d7c0a89a 3398 (uint32_t)ntohl(top->remote));
d62a17ae 3399 }
16f1b9ee 3400
d62a17ae 3401 return TLV_SIZE(tlvh);
16f1b9ee
OD
3402}
3403
d7c0a89a
QY
3404static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
3405 struct tlv_header *tlvh)
16f1b9ee 3406{
d62a17ae 3407 struct te_link_subtlv_rip *top;
16f1b9ee 3408
d62a17ae 3409 top = (struct te_link_subtlv_rip *)tlvh;
16f1b9ee 3410
d62a17ae 3411 if (vty != NULL)
96b663a3
MS
3412 vty_out(vty, " Inter-AS TE Remote ASBR IP address: %pI4\n",
3413 &top->value);
d62a17ae 3414 else
96b663a3
MS
3415 zlog_debug(" Inter-AS TE Remote ASBR IP address: %pI4",
3416 &top->value);
16f1b9ee 3417
d62a17ae 3418 return TLV_SIZE(tlvh);
16f1b9ee
OD
3419}
3420
d7c0a89a
QY
3421static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
3422 struct tlv_header *tlvh)
16f1b9ee 3423{
d62a17ae 3424 struct te_link_subtlv_ras *top;
16f1b9ee 3425
d62a17ae 3426 top = (struct te_link_subtlv_ras *)tlvh;
16f1b9ee 3427
d62a17ae 3428 if (vty != NULL)
3429 vty_out(vty, " Inter-AS TE Remote AS number: %u\n",
3430 ntohl(top->value));
3431 else
3432 zlog_debug(" Inter-AS TE Remote AS number: %u",
3433 ntohl(top->value));
16f1b9ee 3434
d62a17ae 3435 return TLV_SIZE(tlvh);
16f1b9ee
OD
3436}
3437
d7c0a89a
QY
3438static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
3439 struct tlv_header *tlvh)
16f1b9ee 3440{
d62a17ae 3441 struct te_link_subtlv_av_delay *top;
d7c0a89a
QY
3442 uint32_t delay;
3443 uint32_t anomalous;
16f1b9ee 3444
d62a17ae 3445 top = (struct te_link_subtlv_av_delay *)tlvh;
d7c0a89a
QY
3446 delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
3447 anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
16f1b9ee 3448
d62a17ae 3449 if (vty != NULL)
3450 vty_out(vty, " %s Average Link Delay: %d (micro-sec)\n",
3451 anomalous ? "Anomalous" : "Normal", delay);
3452 else
3453 zlog_debug(" %s Average Link Delay: %d (micro-sec)",
3454 anomalous ? "Anomalous" : "Normal", delay);
16f1b9ee 3455
d62a17ae 3456 return TLV_SIZE(tlvh);
16f1b9ee
OD
3457}
3458
d7c0a89a
QY
3459static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
3460 struct tlv_header *tlvh)
16f1b9ee 3461{
d62a17ae 3462 struct te_link_subtlv_mm_delay *top;
d7c0a89a
QY
3463 uint32_t low, high;
3464 uint32_t anomalous;
16f1b9ee 3465
d62a17ae 3466 top = (struct te_link_subtlv_mm_delay *)tlvh;
d7c0a89a
QY
3467 low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
3468 anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
3469 high = (uint32_t)ntohl(top->high);
16f1b9ee 3470
d62a17ae 3471 if (vty != NULL)
3472 vty_out(vty, " %s Min/Max Link Delay: %d/%d (micro-sec)\n",
3473 anomalous ? "Anomalous" : "Normal", low, high);
3474 else
3475 zlog_debug(" %s Min/Max Link Delay: %d/%d (micro-sec)",
3476 anomalous ? "Anomalous" : "Normal", low, high);
16f1b9ee 3477
d62a17ae 3478 return TLV_SIZE(tlvh);
16f1b9ee
OD
3479}
3480
d7c0a89a
QY
3481static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
3482 struct tlv_header *tlvh)
16f1b9ee 3483{
d62a17ae 3484 struct te_link_subtlv_delay_var *top;
d7c0a89a 3485 uint32_t jitter;
16f1b9ee 3486
d62a17ae 3487 top = (struct te_link_subtlv_delay_var *)tlvh;
d7c0a89a 3488 jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
16f1b9ee 3489
d62a17ae 3490 if (vty != NULL)
3491 vty_out(vty, " Delay Variation: %d (micro-sec)\n", jitter);
3492 else
3493 zlog_debug(" Delay Variation: %d (micro-sec)", jitter);
16f1b9ee 3494
d62a17ae 3495 return TLV_SIZE(tlvh);
16f1b9ee
OD
3496}
3497
d7c0a89a
QY
3498static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
3499 struct tlv_header *tlvh)
16f1b9ee 3500{
d62a17ae 3501 struct te_link_subtlv_pkt_loss *top;
d7c0a89a
QY
3502 uint32_t loss;
3503 uint32_t anomalous;
d62a17ae 3504 float fval;
16f1b9ee 3505
d62a17ae 3506 top = (struct te_link_subtlv_pkt_loss *)tlvh;
d7c0a89a 3507 loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
d62a17ae 3508 fval = (float)(loss * LOSS_PRECISION);
d7c0a89a 3509 anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
16f1b9ee 3510
d62a17ae 3511 if (vty != NULL)
3512 vty_out(vty, " %s Link Loss: %g (%%)\n",
3513 anomalous ? "Anomalous" : "Normal", fval);
3514 else
3515 zlog_debug(" %s Link Loss: %g (%%)",
3516 anomalous ? "Anomalous" : "Normal", fval);
16f1b9ee 3517
d62a17ae 3518 return TLV_SIZE(tlvh);
16f1b9ee
OD
3519}
3520
d7c0a89a
QY
3521static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
3522 struct tlv_header *tlvh)
16f1b9ee 3523{
d62a17ae 3524 struct te_link_subtlv_res_bw *top;
3525 float fval;
16f1b9ee 3526
d62a17ae 3527 top = (struct te_link_subtlv_res_bw *)tlvh;
3528 fval = ntohf(top->value);
16f1b9ee 3529
d62a17ae 3530 if (vty != NULL)
3531 vty_out(vty,
3532 " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
3533 fval);
3534 else
3535 zlog_debug(
3536 " Unidirectional Residual Bandwidth: %g (Bytes/sec)",
3537 fval);
3538
3539 return TLV_SIZE(tlvh);
3540}
3541
d7c0a89a
QY
3542static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
3543 struct tlv_header *tlvh)
d62a17ae 3544{
3545 struct te_link_subtlv_ava_bw *top;
3546 float fval;
3547
3548 top = (struct te_link_subtlv_ava_bw *)tlvh;
3549 fval = ntohf(top->value);
3550
3551 if (vty != NULL)
3552 vty_out(vty,
3553 " Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
3554 fval);
3555 else
3556 zlog_debug(
3557 " Unidirectional Available Bandwidth: %g (Bytes/sec)",
3558 fval);
3559
3560 return TLV_SIZE(tlvh);
3561}
3562
d7c0a89a
QY
3563static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
3564 struct tlv_header *tlvh)
d62a17ae 3565{
3566 struct te_link_subtlv_use_bw *top;
3567 float fval;
3568
3569 top = (struct te_link_subtlv_use_bw *)tlvh;
3570 fval = ntohf(top->value);
3571
3572 if (vty != NULL)
3573 vty_out(vty,
3574 " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
3575 fval);
3576 else
3577 zlog_debug(
3578 " Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
3579 fval);
3580
3581 return TLV_SIZE(tlvh);
3582}
3583
d7c0a89a 3584static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
d62a17ae 3585{
3586 if (vty != NULL)
3587 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
3588 ntohs(tlvh->type), ntohs(tlvh->length));
3589 else
3590 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
3591 ntohs(tlvh->type), ntohs(tlvh->length));
3592
3593 return TLV_SIZE(tlvh);
3594}
3595
d7c0a89a
QY
3596static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
3597 struct tlv_header *tlvh0,
3598 uint16_t subtotal, uint16_t total)
d62a17ae 3599{
9df48e81 3600 struct tlv_header *tlvh;
d7c0a89a 3601 uint16_t sum = subtotal;
d62a17ae 3602
3603 for (tlvh = tlvh0; sum < total;
9df48e81 3604 tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 3605 switch (ntohs(tlvh->type)) {
3606 case TE_LINK_SUBTLV_LINK_TYPE:
3607 sum += show_vty_link_subtlv_link_type(vty, tlvh);
3608 break;
3609 case TE_LINK_SUBTLV_LINK_ID:
3610 sum += show_vty_link_subtlv_link_id(vty, tlvh);
3611 break;
3612 case TE_LINK_SUBTLV_LCLIF_IPADDR:
3613 sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh);
3614 break;
3615 case TE_LINK_SUBTLV_RMTIF_IPADDR:
3616 sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh);
3617 break;
3618 case TE_LINK_SUBTLV_TE_METRIC:
3619 sum += show_vty_link_subtlv_te_metric(vty, tlvh);
3620 break;
3621 case TE_LINK_SUBTLV_MAX_BW:
3622 sum += show_vty_link_subtlv_max_bw(vty, tlvh);
3623 break;
3624 case TE_LINK_SUBTLV_MAX_RSV_BW:
3625 sum += show_vty_link_subtlv_max_rsv_bw(vty, tlvh);
3626 break;
3627 case TE_LINK_SUBTLV_UNRSV_BW:
3628 sum += show_vty_link_subtlv_unrsv_bw(vty, tlvh);
3629 break;
3630 case TE_LINK_SUBTLV_RSC_CLSCLR:
3631 sum += show_vty_link_subtlv_rsc_clsclr(vty, tlvh);
3632 break;
3633 case TE_LINK_SUBTLV_LRRID:
3634 sum += show_vty_link_subtlv_lrrid(vty, tlvh);
3635 break;
3636 case TE_LINK_SUBTLV_LLRI:
3637 sum += show_vty_link_subtlv_llri(vty, tlvh);
3638 break;
3639 case TE_LINK_SUBTLV_RIP:
3640 sum += show_vty_link_subtlv_rip(vty, tlvh);
3641 break;
3642 case TE_LINK_SUBTLV_RAS:
3643 sum += show_vty_link_subtlv_ras(vty, tlvh);
3644 break;
3645 case TE_LINK_SUBTLV_AV_DELAY:
3646 sum += show_vty_link_subtlv_av_delay(vty, tlvh);
3647 break;
3648 case TE_LINK_SUBTLV_MM_DELAY:
3649 sum += show_vty_link_subtlv_mm_delay(vty, tlvh);
3650 break;
3651 case TE_LINK_SUBTLV_DELAY_VAR:
3652 sum += show_vty_link_subtlv_delay_var(vty, tlvh);
3653 break;
3654 case TE_LINK_SUBTLV_PKT_LOSS:
3655 sum += show_vty_link_subtlv_pkt_loss(vty, tlvh);
3656 break;
3657 case TE_LINK_SUBTLV_RES_BW:
3658 sum += show_vty_link_subtlv_res_bw(vty, tlvh);
3659 break;
3660 case TE_LINK_SUBTLV_AVA_BW:
3661 sum += show_vty_link_subtlv_ava_bw(vty, tlvh);
3662 break;
3663 case TE_LINK_SUBTLV_USE_BW:
3664 sum += show_vty_link_subtlv_use_bw(vty, tlvh);
3665 break;
3666 default:
3667 sum += show_vty_unknown_tlv(vty, tlvh);
3668 break;
3669 }
3670 }
3671 return sum;
3672}
3673
3674static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
3675{
c4efd0f4 3676 struct lsa_header *lsah = lsa->data;
ead99d5f 3677 struct tlv_header *tlvh, *next;
d7c0a89a
QY
3678 uint16_t sum, total;
3679 uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
3680 uint16_t subtotal, uint16_t total) = NULL;
d62a17ae 3681
3682 sum = 0;
3683 total = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
3684
3685 for (tlvh = TLV_HDR_TOP(lsah); sum < total;
3686 tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
3687 if (subfunc != NULL) {
3688 sum = (*subfunc)(vty, tlvh, sum, total);
ead99d5f 3689 next = (struct tlv_header *)((char *)tlvh + sum);
d62a17ae 3690 subfunc = NULL;
3691 continue;
3692 }
3693
3694 next = NULL;
3695 switch (ntohs(tlvh->type)) {
3696 case TE_TLV_ROUTER_ADDR:
3697 sum += show_vty_router_addr(vty, tlvh);
3698 break;
3699 case TE_TLV_LINK:
3700 sum += show_vty_link_header(vty, tlvh);
3701 subfunc = ospf_mpls_te_show_link_subtlv;
5d0df50f 3702 next = TLV_DATA(tlvh);
d62a17ae 3703 break;
3704 default:
3705 sum += show_vty_unknown_tlv(vty, tlvh);
3706 break;
3707 }
3708 }
3709 return;
3710}
3711
3712static void ospf_mpls_te_config_write_router(struct vty *vty)
3713{
3714
32ab5cf4 3715 if (OspfMplsTE.enabled) {
d62a17ae 3716 vty_out(vty, " mpls-te on\n");
96b663a3
MS
3717 vty_out(vty, " mpls-te router-address %pI4\n",
3718 &OspfMplsTE.router_addr.value);
d62a17ae 3719
f173deb3
OD
3720 if (OspfMplsTE.inter_as == AS)
3721 vty_out(vty, " mpls-te inter-as as\n");
3722 if (OspfMplsTE.inter_as == Area)
3723 vty_out(vty, " mpls-te inter-as area %pI4 \n",
3724 &OspfMplsTE.interas_areaid);
3725 if (OspfMplsTE.export)
3726 vty_out(vty, " mpls-te export\n");
3727 }
d62a17ae 3728 return;
718e3744 3729}
3730
3731/*------------------------------------------------------------------------*
3732 * Followings are vty command functions.
3733 *------------------------------------------------------------------------*/
3734
16f1b9ee
OD
3735DEFUN (ospf_mpls_te_on,
3736 ospf_mpls_te_on_cmd,
3737 "mpls-te on",
3738 MPLS_TE_STR
718e3744 3739 "Enable the MPLS-TE functionality\n")
3740{
a3d826f0 3741 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 3742 struct listnode *node;
3743 struct mpls_te_link *lp;
7c8ff89e 3744
32ab5cf4 3745 if (OspfMplsTE.enabled)
d62a17ae 3746 return CMD_SUCCESS;
718e3744 3747
fd3c7692 3748 ote_debug("MPLS-TE: OFF -> ON");
718e3744 3749
32ab5cf4 3750 OspfMplsTE.enabled = true;
718e3744 3751
d62a17ae 3752 /* Reoriginate RFC3630 & RFC6827 Links */
3753 ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
3754 REORIGINATE_THIS_LSA);
718e3744 3755
d62a17ae 3756 /* Reoriginate LSA if INTER-AS is always on */
ead99d5f 3757 if (OspfMplsTE.inter_as != Off) {
d62a17ae 3758 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) {
3759 if (IS_INTER_AS(lp->type)) {
3760 ospf_mpls_te_lsa_schedule(lp,
3761 REORIGINATE_THIS_LSA);
3762 }
3763 }
3764 }
718e3744 3765
f173deb3
OD
3766 /* Create TED and initialize it */
3767 OspfMplsTE.ted = ls_ted_new(1, "OSPF", 0);
3768 if (!OspfMplsTE.ted) {
3769 vty_out(vty, "Unable to create Link State Data Base\n");
3770 return CMD_WARNING;
3771 }
3772 ospf_te_init_ted(OspfMplsTE.ted, ospf);
3773
d62a17ae 3774 return CMD_SUCCESS;
718e3744 3775}
3776
16f1b9ee
OD
3777DEFUN (no_ospf_mpls_te,
3778 no_ospf_mpls_te_cmd,
3a2d747c 3779 "no mpls-te [on]",
718e3744 3780 NO_STR
3a2d747c 3781 MPLS_TE_STR
718e3744 3782 "Disable the MPLS-TE functionality\n")
3783{
a3d826f0 3784 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 3785 struct listnode *node, *nnode;
3786 struct mpls_te_link *lp;
718e3744 3787
32ab5cf4 3788 if (!OspfMplsTE.enabled)
d62a17ae 3789 return CMD_SUCCESS;
718e3744 3790
fd3c7692 3791 ote_debug("MPLS-TE: ON -> OFF");
718e3744 3792
f173deb3
OD
3793 /* Remove TED */
3794 ls_ted_del_all(OspfMplsTE.ted);
32ab5cf4 3795 OspfMplsTE.enabled = false;
718e3744 3796
f173deb3 3797 /* Flush all TE Opaque LSAs */
d62a17ae 3798 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
32ab5cf4
OD
3799 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
3800 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
718e3744 3801
d424f8d8
CG
3802 /*
3803 * This resets the OspfMplsTE.inter_as to its initial state.
3804 * This is to avoid having an inter-as value different from
3805 * Off when mpls-te gets restarted (after being removed)
3806 */
2efd7e2b 3807 OspfMplsTE.inter_as = Off;
d424f8d8 3808
d62a17ae 3809 return CMD_SUCCESS;
718e3744 3810}
3811
16f1b9ee
OD
3812DEFUN (ospf_mpls_te_router_addr,
3813 ospf_mpls_te_router_addr_cmd,
718e3744 3814 "mpls-te router-address A.B.C.D",
16f1b9ee 3815 MPLS_TE_STR
718e3744 3816 "Stable IP address of the advertising router\n"
3817 "MPLS-TE router address in IPv4 address format\n")
3818{
a3d826f0 3819 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 3820 int idx_ipv4 = 2;
3821 struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
3822 struct in_addr value;
3823
3824 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
3825 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
3826 return CMD_WARNING;
3827 }
3828
3829 if (ntohs(ra->header.type) == 0
3830 || ntohl(ra->value.s_addr) != ntohl(value.s_addr)) {
3831 struct listnode *node, *nnode;
3832 struct mpls_te_link *lp;
3833 int need_to_reoriginate = 0;
3834
3835 set_mpls_te_router_addr(value);
3836
32ab5cf4 3837 if (!OspfMplsTE.enabled)
ead99d5f 3838 return CMD_SUCCESS;
d62a17ae 3839
3840 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2efd7e2b 3841 if ((lp->area == NULL) || IS_FLOOD_AS(lp->flags))
d62a17ae 3842 continue;
3843
3844 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
3845 need_to_reoriginate = 1;
3846 break;
3847 }
3848 }
3849
3850 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2efd7e2b 3851 if ((lp->area == NULL) || IS_FLOOD_AS(lp->flags))
d62a17ae 3852 continue;
3853
3854 if (need_to_reoriginate)
3855 SET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
3856 else
3857 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
3858 }
3859
3860 if (need_to_reoriginate)
3861 ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
3862 REORIGINATE_THIS_LSA);
3863 }
ead99d5f 3864
d62a17ae 3865 return CMD_SUCCESS;
3866}
3867
3868static int set_inter_as_mode(struct vty *vty, const char *mode_name,
3869 const char *area_id)
3870{
3871 enum inter_as_mode mode;
3872 struct listnode *node;
3873 struct mpls_te_link *lp;
3874 int format;
3875
32ab5cf4 3876 if (OspfMplsTE.enabled) {
d62a17ae 3877
3878 /* Read and Check inter_as mode */
3879 if (strcmp(mode_name, "as") == 0)
3880 mode = AS;
3881 else if (strcmp(mode_name, "area") == 0) {
3882 mode = Area;
3883 VTY_GET_OSPF_AREA_ID(OspfMplsTE.interas_areaid, format,
3884 area_id);
3885 } else {
3886 vty_out(vty,
3887 "Unknown mode. Please choose between as or area\n");
3888 return CMD_WARNING;
3889 }
3890
fd3c7692
OD
3891 ote_debug(
3892 "MPLS-TE (%s): Inter-AS enable with %s flooding support",
3893 __func__, mode2text[mode]);
d62a17ae 3894
d62a17ae 3895 /* Enable mode and re-originate LSA if needed */
ead99d5f 3896 if ((OspfMplsTE.inter_as == Off)
d62a17ae 3897 && (mode != OspfMplsTE.inter_as)) {
3898 OspfMplsTE.inter_as = mode;
3899 /* Re-originate all InterAS-TEv2 LSA */
3900 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node,
3901 lp)) {
3902 if (IS_INTER_AS(lp->type)) {
3903 if (mode == AS)
2efd7e2b
OD
3904 SET_FLAG(lp->flags,
3905 LPFLG_LSA_FLOOD_AS);
d62a17ae 3906 else
2efd7e2b
OD
3907 UNSET_FLAG(lp->flags,
3908 LPFLG_LSA_FLOOD_AS);
d62a17ae 3909 ospf_mpls_te_lsa_schedule(
3910 lp, REORIGINATE_THIS_LSA);
3911 }
3912 }
3913 } else {
3914 vty_out(vty,
3915 "Please change Inter-AS support to disable first before going to mode %s\n",
3916 mode2text[mode]);
3917 return CMD_WARNING;
3918 }
3919 } else {
3920 vty_out(vty, "mpls-te has not been turned on\n");
3921 return CMD_WARNING;
3922 }
3923 return CMD_SUCCESS;
718e3744 3924}
3925
718e3744 3926
16f1b9ee
OD
3927DEFUN (ospf_mpls_te_inter_as_as,
3928 ospf_mpls_te_inter_as_cmd,
3929 "mpls-te inter-as as",
3930 MPLS_TE_STR
3931 "Configure MPLS-TE Inter-AS support\n"
3932 "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n")
3933{
d62a17ae 3934 return set_inter_as_mode(vty, "as", "");
718e3744 3935}
3936
16f1b9ee
OD
3937DEFUN (ospf_mpls_te_inter_as_area,
3938 ospf_mpls_te_inter_as_area_cmd,
6147e2c6 3939 "mpls-te inter-as area <A.B.C.D|(0-4294967295)>",
16f1b9ee
OD
3940 MPLS_TE_STR
3941 "Configure MPLS-TE Inter-AS support\n"
3942 "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n"
3943 "OSPF area ID in IP format\n"
3944 "OSPF area ID as decimal value\n")
718e3744 3945{
d62a17ae 3946 int idx_ipv4_number = 3;
3947 return set_inter_as_mode(vty, "area", argv[idx_ipv4_number]->arg);
718e3744 3948}
3949
16f1b9ee
OD
3950DEFUN (no_ospf_mpls_te_inter_as,
3951 no_ospf_mpls_te_inter_as_cmd,
3952 "no mpls-te inter-as",
3953 NO_STR
3954 MPLS_TE_STR
3955 "Disable MPLS-TE Inter-AS support\n")
718e3744 3956{
16f1b9ee 3957
d62a17ae 3958 struct listnode *node, *nnode;
3959 struct mpls_te_link *lp;
718e3744 3960
fd3c7692 3961 ote_debug("MPLS-TE: Inter-AS support OFF");
718e3744 3962
996c9314 3963 if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) {
d62a17ae 3964 /* Flush all Inter-AS LSA */
3965 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
3966 if (IS_INTER_AS(lp->type)
3967 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
3968 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
718e3744 3969
e790de41
DT
3970 OspfMplsTE.inter_as = Off;
3971 }
bcf4475e 3972
d62a17ae 3973 return CMD_SUCCESS;
718e3744 3974}
3975
f173deb3
OD
3976DEFUN (ospf_mpls_te_export,
3977 ospf_mpls_te_export_cmd,
3978 "mpls-te export",
3979 MPLS_TE_STR
3980 "Export the MPLS-TE information as Link State\n")
3981{
3982
3983 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
3984
3985 if (OspfMplsTE.enabled) {
3986 if (ls_register(zclient, true) != 0) {
3987 vty_out(vty, "Unable to register Link State\n");
3988 return CMD_WARNING;
3989 }
3990 OspfMplsTE.export = true;
3991 } else {
3992 vty_out(vty, "mpls-te has not been turned on\n");
3993 return CMD_WARNING;
3994 }
3995 return CMD_SUCCESS;
3996}
3997
3998
3999DEFUN (no_ospf_mpls_te_export,
4000 no_ospf_mpls_te_export_cmd,
4001 "no mpls-te export",
4002 NO_STR
4003 MPLS_TE_STR
4004 "Stop export of the MPLS-TE information as Link State\n")
4005{
4006
4007 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
4008
4009 if (OspfMplsTE.export) {
4010 if (ls_unregister(zclient, true) != 0) {
4011 vty_out(vty, "Unable to unregister Link State\n");
4012 return CMD_WARNING;
4013 }
4014 OspfMplsTE.export = false;
4015 }
4016 return CMD_SUCCESS;
4017}
4018
16f1b9ee
OD
4019DEFUN (show_ip_ospf_mpls_te_router,
4020 show_ip_ospf_mpls_te_router_cmd,
4021 "show ip ospf mpls-te router",
718e3744 4022 SHOW_STR
16f1b9ee
OD
4023 IP_STR
4024 OSPF_STR
718e3744 4025 "MPLS-TE information\n"
16f1b9ee 4026 "MPLS-TE Router parameters\n")
718e3744 4027{
32ab5cf4 4028 if (OspfMplsTE.enabled) {
d62a17ae 4029 vty_out(vty, "--- MPLS-TE router parameters ---\n");
4030
4031 if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
4032 show_vty_router_addr(vty,
4033 &OspfMplsTE.router_addr.header);
0af35d90 4034 else
f173deb3
OD
4035 vty_out(vty, " Router address is not set\n");
4036 vty_out(vty, " Link State distribution is %s\n",
4037 OspfMplsTE.export ? "Active" : "Inactive");
d62a17ae 4038 }
4039 return CMD_SUCCESS;
4040}
4041
4042static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
4043{
4044 struct mpls_te_link *lp;
4045
996c9314
LB
4046 if ((OspfMplsTE.enabled) && HAS_LINK_PARAMS(ifp) && !if_is_loopback(ifp)
4047 && if_is_up(ifp)
d62a17ae 4048 && ((lp = lookup_linkparams_by_ifp(ifp)) != NULL)) {
4049 /* Continue only if interface is not passive or support Inter-AS
4050 * TEv2 */
4051 if (!(ospf_oi_count(ifp) > 0)) {
4052 if (IS_INTER_AS(lp->type)) {
4053 vty_out(vty,
4054 "-- Inter-AS TEv2 link parameters for %s --\n",
4055 ifp->name);
4056 } else {
4057 /* MPLS-TE is not activate on this interface */
4058 /* or this interface is passive and Inter-AS
4059 * TEv2 is not activate */
4060 vty_out(vty,
4061 " %s: MPLS-TE is disabled on this interface\n",
4062 ifp->name);
4063 return;
4064 }
4065 } else {
4066 vty_out(vty, "-- MPLS-TE link parameters for %s --\n",
4067 ifp->name);
4068 }
4069
4070 if (TLV_TYPE(lp->link_type) != 0)
4071 show_vty_link_subtlv_link_type(vty,
4072 &lp->link_type.header);
4073 if (TLV_TYPE(lp->link_id) != 0)
4074 show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
4075 if (TLV_TYPE(lp->lclif_ipaddr) != 0)
4076 show_vty_link_subtlv_lclif_ipaddr(
4077 vty, &lp->lclif_ipaddr.header);
4078 if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
4079 show_vty_link_subtlv_rmtif_ipaddr(
4080 vty, &lp->rmtif_ipaddr.header);
4081 if (TLV_TYPE(lp->rip) != 0)
4082 show_vty_link_subtlv_rip(vty, &lp->rip.header);
4083 if (TLV_TYPE(lp->ras) != 0)
4084 show_vty_link_subtlv_ras(vty, &lp->ras.header);
4085 if (TLV_TYPE(lp->te_metric) != 0)
4086 show_vty_link_subtlv_te_metric(vty,
4087 &lp->te_metric.header);
4088 if (TLV_TYPE(lp->max_bw) != 0)
4089 show_vty_link_subtlv_max_bw(vty, &lp->max_bw.header);
4090 if (TLV_TYPE(lp->max_rsv_bw) != 0)
4091 show_vty_link_subtlv_max_rsv_bw(vty,
4092 &lp->max_rsv_bw.header);
4093 if (TLV_TYPE(lp->unrsv_bw) != 0)
4094 show_vty_link_subtlv_unrsv_bw(vty,
4095 &lp->unrsv_bw.header);
4096 if (TLV_TYPE(lp->rsc_clsclr) != 0)
4097 show_vty_link_subtlv_rsc_clsclr(vty,
4098 &lp->rsc_clsclr.header);
4099 if (TLV_TYPE(lp->av_delay) != 0)
4100 show_vty_link_subtlv_av_delay(vty,
4101 &lp->av_delay.header);
4102 if (TLV_TYPE(lp->mm_delay) != 0)
4103 show_vty_link_subtlv_mm_delay(vty,
4104 &lp->mm_delay.header);
4105 if (TLV_TYPE(lp->delay_var) != 0)
4106 show_vty_link_subtlv_delay_var(vty,
4107 &lp->delay_var.header);
4108 if (TLV_TYPE(lp->pkt_loss) != 0)
4109 show_vty_link_subtlv_pkt_loss(vty,
4110 &lp->pkt_loss.header);
4111 if (TLV_TYPE(lp->res_bw) != 0)
4112 show_vty_link_subtlv_res_bw(vty, &lp->res_bw.header);
4113 if (TLV_TYPE(lp->ava_bw) != 0)
4114 show_vty_link_subtlv_ava_bw(vty, &lp->ava_bw.header);
4115 if (TLV_TYPE(lp->use_bw) != 0)
4116 show_vty_link_subtlv_use_bw(vty, &lp->use_bw.header);
4117 vty_out(vty, "---------------\n\n");
4118 } else {
4119 vty_out(vty, " %s: MPLS-TE is disabled on this interface\n",
4120 ifp->name);
4121 }
4122
4123 return;
718e3744 4124}
4125
16f1b9ee
OD
4126DEFUN (show_ip_ospf_mpls_te_link,
4127 show_ip_ospf_mpls_te_link_cmd,
b5a8894d 4128 "show ip ospf [vrf <NAME|all>] mpls-te interface [INTERFACE]",
718e3744 4129 SHOW_STR
16f1b9ee
OD
4130 IP_STR
4131 OSPF_STR
b5a8894d
CS
4132 VRF_CMD_HELP_STR
4133 "All VRFs\n"
718e3744 4134 "MPLS-TE information\n"
4135 "Interface information\n"
4136 "Interface name\n")
4137{
f4e14fdb 4138 struct vrf *vrf;
03ed9f02
PG
4139 int idx_interface = 0;
4140 struct interface *ifp = NULL;
f4e14fdb 4141 struct listnode *node;
b5a8894d 4142 char *vrf_name = NULL;
8da59e56 4143 bool all_vrf = false;
b5a8894d
CS
4144 int inst = 0;
4145 int idx_vrf = 0;
4146 struct ospf *ospf = NULL;
4147
4148 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
4149 vrf_name = argv[idx_vrf + 1]->arg;
4150 all_vrf = strmatch(vrf_name, "all");
4151 }
03ed9f02 4152 argv_find(argv, argc, "INTERFACE", &idx_interface);
b5a8894d
CS
4153 /* vrf input is provided could be all or specific vrf*/
4154 if (vrf_name) {
4155 if (all_vrf) {
f4e14fdb 4156 for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
b5a8894d
CS
4157 if (!ospf->oi_running)
4158 continue;
f4e14fdb 4159 vrf = vrf_lookup_by_id(ospf->vrf_id);
451fda4f 4160 FOR_ALL_INTERFACES (vrf, ifp)
b5a8894d
CS
4161 show_mpls_te_link_sub(vty, ifp);
4162 }
4163 return CMD_SUCCESS;
4164 }
996c9314 4165 ospf = ospf_lookup_by_inst_name(inst, vrf_name);
03ed9f02
PG
4166 } else
4167 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
4168 if (ospf == NULL || !ospf->oi_running)
b5a8894d 4169 return CMD_SUCCESS;
03ed9f02
PG
4170
4171 vrf = vrf_lookup_by_id(ospf->vrf_id);
4172 if (!vrf)
4173 return CMD_SUCCESS;
4174 if (idx_interface) {
4175 ifp = if_lookup_by_name(
4176 argv[idx_interface]->arg,
a36898e7 4177 ospf->vrf_id);
03ed9f02
PG
4178 if (ifp == NULL) {
4179 vty_out(vty, "No such interface name in vrf %s\n",
4180 vrf->name);
4181 return CMD_SUCCESS;
43b8d1d8 4182 }
d62a17ae 4183 }
03ed9f02
PG
4184 if (!ifp) {
4185 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 4186 show_mpls_te_link_sub(vty, ifp);
03ed9f02 4187 return CMD_SUCCESS;
d62a17ae 4188 }
4189
03ed9f02 4190 show_mpls_te_link_sub(vty, ifp);
d62a17ae 4191 return CMD_SUCCESS;
4192}
4193
f173deb3
OD
4194DEFUN (show_ip_ospf_mpls_te_db,
4195 show_ip_ospf_mpls_te_db_cmd,
4196 "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]",
4197 SHOW_STR
4198 IP_STR
4199 OSPF_STR
4200 "MPLS-TE information\n"
4201 "MPLS-TE database\n"
4202 "MPLS-TE Vertex\n"
4203 "Self-originated MPLS-TE router\n"
4204 "Advertised MPLS-TE router\n"
4205 "MPLS-TE router ID (as an IP address)\n"
4206 "MPLS-TE Edge\n"
4207 "MPLS-TE Edge ID (as an IP address)\n"
4208 "MPLS-TE Subnet\n"
4209 "MPLS-TE Subnet ID (as an IP prefix)\n"
4210 "Verbose output\n"
4211 JSON_STR)
4212{
4213 int idx = 0;
4214 struct in_addr ip_addr;
4215 struct prefix pref;
4216 struct ls_vertex *vertex;
4217 struct ls_edge *edge;
4218 struct ls_subnet *subnet;
4219 uint64_t key;
4220 bool verbose = false;
4221 bool uj = use_json(argc, argv);
4222 json_object *json = NULL;
4223
4224 if (!OspfMplsTE.enabled || !OspfMplsTE.ted) {
4225 vty_out(vty, "MPLS-TE database is not enabled\n");
4226 return CMD_WARNING;
4227 }
4228
4229 if (uj)
4230 json = json_object_new_object();
4231
4232 if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
4233 verbose = true;
4234
4235 idx = 5;
4236 if (argv_find(argv, argc, "vertex", &idx)) {
4237 /* Show Vertex */
4238 if (argv_find(argv, argc, "self-originate", &idx))
4239 vertex = OspfMplsTE.ted->self;
4240 else if (argv_find(argv, argc, "adv-router", &idx)) {
4241 if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
4242 vty_out(vty,
4243 "Specified Router ID %s is invalid\n",
4244 argv[idx + 1]->arg);
4245 return CMD_WARNING_CONFIG_FAILED;
4246 }
4247 /* Get the Vertex from the Link State Database */
4248 key = ((uint64_t)ntohl(ip_addr.s_addr)) & 0xffffffff;
4249 vertex = ls_find_vertex_by_key(OspfMplsTE.ted, key);
4250 if (!vertex) {
4251 vty_out(vty, "No vertex found for ID %pI4\n",
4252 &ip_addr);
4253 return CMD_WARNING;
4254 }
4255 } else
4256 vertex = NULL;
4257
4258 if (vertex)
4259 ls_show_vertex(vertex, vty, json, verbose);
4260 else
4261 ls_show_vertices(OspfMplsTE.ted, vty, json, verbose);
4262
4263 } else if (argv_find(argv, argc, "edge", &idx)) {
4264 /* Show Edge */
4265 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
4266 if (!inet_aton(argv[idx]->arg, &ip_addr)) {
4267 vty_out(vty,
4268 "Specified Edge ID %s is invalid\n",
4269 argv[idx]->arg);
4270 return CMD_WARNING_CONFIG_FAILED;
4271 }
4272 /* Get the Edge from the Link State Database */
4273 key = ((uint64_t)ntohl(ip_addr.s_addr)) & 0xffffffff;
4274 edge = ls_find_edge_by_key(OspfMplsTE.ted, key);
4275 if (!edge) {
4276 vty_out(vty, "No edge found for ID %pI4\n",
4277 &ip_addr);
4278 return CMD_WARNING;
4279 }
4280 } else
4281 edge = NULL;
4282
4283 if (edge)
4284 ls_show_edge(edge, vty, json, verbose);
4285 else
4286 ls_show_edges(OspfMplsTE.ted, vty, json, verbose);
4287
4288 } else if (argv_find(argv, argc, "subnet", &idx)) {
4289 /* Show Subnet */
4290 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
4291 if (!str2prefix(argv[idx]->arg, &pref)) {
4292 vty_out(vty, "Invalid prefix format %s\n",
4293 argv[idx]->arg);
4294 return CMD_WARNING_CONFIG_FAILED;
4295 }
4296 /* Get the Subnet from the Link State Database */
4297 subnet = ls_find_subnet(OspfMplsTE.ted, pref);
4298 if (!subnet) {
4299 vty_out(vty, "No subnet found for ID %pFX\n",
4300 &pref);
4301 return CMD_WARNING;
4302 }
4303 } else
4304 subnet = NULL;
4305
4306 if (subnet)
4307 ls_show_subnet(subnet, vty, json, verbose);
4308 else
4309 ls_show_subnets(OspfMplsTE.ted, vty, json, verbose);
4310
4311 } else {
4312 /* Show the complete TED */
4313 ls_show_ted(OspfMplsTE.ted, vty, json, verbose);
4314 }
4315
4316 if (uj) {
4317 vty_out(vty, "%s\n",
4318 json_object_to_json_string_ext(
4319 json, JSON_C_TO_STRING_PRETTY));
4320 json_object_free(json);
4321 }
4322 return CMD_SUCCESS;
4323}
4324
d62a17ae 4325static void ospf_mpls_te_register_vty(void)
4326{
4327 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
4328 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
f173deb3 4329 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_db_cmd);
d62a17ae 4330
4331 install_element(OSPF_NODE, &ospf_mpls_te_on_cmd);
4332 install_element(OSPF_NODE, &no_ospf_mpls_te_cmd);
4333 install_element(OSPF_NODE, &ospf_mpls_te_router_addr_cmd);
4334 install_element(OSPF_NODE, &ospf_mpls_te_inter_as_cmd);
4335 install_element(OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd);
4336 install_element(OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd);
f173deb3
OD
4337 install_element(OSPF_NODE, &ospf_mpls_te_export_cmd);
4338 install_element(OSPF_NODE, &no_ospf_mpls_te_export_cmd);
d62a17ae 4339
4340 return;
718e3744 4341}