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