]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_te.c
Merge pull request #7639 from qlyoung/frr-lua
[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"
718e3744 46
47#include "ospfd/ospfd.h"
48#include "ospfd/ospf_interface.h"
49#include "ospfd/ospf_ism.h"
50#include "ospfd/ospf_asbr.h"
51#include "ospfd/ospf_lsa.h"
52#include "ospfd/ospf_lsdb.h"
53#include "ospfd/ospf_neighbor.h"
54#include "ospfd/ospf_nsm.h"
55#include "ospfd/ospf_flood.h"
56#include "ospfd/ospf_packet.h"
57#include "ospfd/ospf_spf.h"
58#include "ospfd/ospf_dump.h"
59#include "ospfd/ospf_route.h"
60#include "ospfd/ospf_ase.h"
61#include "ospfd/ospf_zebra.h"
62#include "ospfd/ospf_te.h"
16f1b9ee 63#include "ospfd/ospf_vty.h"
85c9b439 64#include "ospfd/ospf_errors.h"
718e3744 65
66/*
67 * Global variable to manage Opaque-LSA/MPLS-TE on this node.
68 * Note that all parameter values are stored in network byte order.
69 */
16f1b9ee 70struct ospf_mpls_te OspfMplsTE;
718e3744 71
2b64873d 72static const char *const mode2text[] = {"Off", "AS", "Area"};
718e3744 73
74/*------------------------------------------------------------------------*
75 * Followings are initialize/terminate functions for MPLS-TE handling.
76 *------------------------------------------------------------------------*/
77
d62a17ae 78static int ospf_mpls_te_new_if(struct interface *ifp);
79static int ospf_mpls_te_del_if(struct interface *ifp);
80static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status);
81static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status);
82static void ospf_mpls_te_config_write_router(struct vty *vty);
83static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa);
84static int ospf_mpls_te_lsa_originate_area(void *arg);
85static int ospf_mpls_te_lsa_originate_as(void *arg);
86static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa);
87
88static void del_mpls_te_link(void *val);
89static void ospf_mpls_te_register_vty(void);
90
91int ospf_mpls_te_init(void)
92{
93 int rc;
94
95 rc = ospf_register_opaque_functab(
96 OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
97 ospf_mpls_te_new_if, ospf_mpls_te_del_if,
98 ospf_mpls_te_ism_change, ospf_mpls_te_nsm_change,
718e3744 99 ospf_mpls_te_config_write_router,
d62a17ae 100 NULL, /*ospf_mpls_te_config_write_if */
101 NULL, /* ospf_mpls_te_config_write_debug */
102 ospf_mpls_te_show_info, ospf_mpls_te_lsa_originate_area,
103 ospf_mpls_te_lsa_refresh, NULL, /* ospf_mpls_te_new_lsa_hook */
718e3744 104 NULL /* ospf_mpls_te_del_lsa_hook */);
d62a17ae 105 if (rc != 0) {
ade6974d 106 flog_warn(
cf444bcf 107 EC_OSPF_OPAQUE_REGISTRATION,
ade6974d 108 "ospf_mpls_te_init: Failed to register Traffic Engineering functions");
ead99d5f 109 return rc;
d62a17ae 110 }
718e3744 111
d62a17ae 112 memset(&OspfMplsTE, 0, sizeof(struct ospf_mpls_te));
32ab5cf4 113 OspfMplsTE.enabled = false;
ead99d5f 114 OspfMplsTE.inter_as = Off;
d62a17ae 115 OspfMplsTE.iflist = list_new();
116 OspfMplsTE.iflist->del = del_mpls_te_link;
718e3744 117
d62a17ae 118 ospf_mpls_te_register_vty();
718e3744 119
d62a17ae 120 return rc;
718e3744 121}
122
16f1b9ee 123/* Additional register for RFC5392 support */
d62a17ae 124static int ospf_mpls_te_register(enum inter_as_mode mode)
16f1b9ee 125{
ead99d5f 126 int rc = 0;
d7c0a89a 127 uint8_t scope;
16f1b9ee 128
ead99d5f
OD
129 if (OspfMplsTE.inter_as != Off)
130 return rc;
16f1b9ee 131
d62a17ae 132 if (mode == AS)
133 scope = OSPF_OPAQUE_AS_LSA;
134 else
135 scope = OSPF_OPAQUE_AREA_LSA;
16f1b9ee 136
d62a17ae 137 rc = ospf_register_opaque_functab(scope, OPAQUE_TYPE_INTER_AS_LSA, NULL,
138 NULL, NULL, NULL, NULL, NULL, NULL,
139 ospf_mpls_te_show_info,
140 ospf_mpls_te_lsa_originate_as,
141 ospf_mpls_te_lsa_refresh, NULL, NULL);
16f1b9ee 142
d62a17ae 143 if (rc != 0) {
ade6974d 144 flog_warn(
cf444bcf 145 EC_OSPF_OPAQUE_REGISTRATION,
ade6974d 146 "ospf_router_info_init: Failed to register Inter-AS functions");
d62a17ae 147 return rc;
148 }
16f1b9ee 149
ead99d5f 150 return rc;
16f1b9ee
OD
151}
152
4d762f26 153static int ospf_mpls_te_unregister(void)
bcf4475e 154{
d7c0a89a 155 uint8_t scope;
bcf4475e
OD
156
157 if (OspfMplsTE.inter_as == Off)
158 return 0;
159
160 if (OspfMplsTE.inter_as == AS)
161 scope = OSPF_OPAQUE_AS_LSA;
162 else
163 scope = OSPF_OPAQUE_AREA_LSA;
164
165 ospf_delete_opaque_functab(scope, OPAQUE_TYPE_INTER_AS_LSA);
166
167 return 0;
168}
169
d62a17ae 170void ospf_mpls_te_term(void)
718e3744 171{
6a154c88 172 list_delete(&OspfMplsTE.iflist);
718e3744 173
bcf4475e
OD
174 ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
175 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
176
32ab5cf4 177 OspfMplsTE.enabled = false;
16f1b9ee 178
bcf4475e 179 ospf_mpls_te_unregister();
ead99d5f 180 OspfMplsTE.inter_as = Off;
16f1b9ee 181
d62a17ae 182 return;
718e3744 183}
184
bcf4475e
OD
185void ospf_mpls_te_finish(void)
186{
187 // list_delete_all_node(OspfMplsTE.iflist);
188
189 OspfMplsTE.enabled = false;
d424f8d8 190 ospf_mpls_te_unregister();
bcf4475e
OD
191 OspfMplsTE.inter_as = Off;
192}
193
718e3744 194/*------------------------------------------------------------------------*
195 * Followings are control functions for MPLS-TE parameters management.
196 *------------------------------------------------------------------------*/
197
d62a17ae 198static void del_mpls_te_link(void *val)
718e3744 199{
d62a17ae 200 XFREE(MTYPE_OSPF_MPLS_TE, val);
201 return;
718e3744 202}
203
d7c0a89a 204static uint32_t get_mpls_te_instance_value(void)
718e3744 205{
d7c0a89a 206 static uint32_t seqno = 0;
718e3744 207
d62a17ae 208 if (seqno < MAX_LEGAL_TE_INSTANCE_NUM)
209 seqno += 1;
210 else
211 seqno = 1; /* Avoid zero. */
718e3744 212
d62a17ae 213 return seqno;
718e3744 214}
215
d62a17ae 216static struct mpls_te_link *lookup_linkparams_by_ifp(struct interface *ifp)
718e3744 217{
d62a17ae 218 struct listnode *node, *nnode;
219 struct mpls_te_link *lp;
718e3744 220
d62a17ae 221 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
222 if (lp->ifp == ifp)
223 return lp;
718e3744 224
d62a17ae 225 return NULL;
718e3744 226}
227
d62a17ae 228static struct mpls_te_link *lookup_linkparams_by_instance(struct ospf_lsa *lsa)
718e3744 229{
d62a17ae 230 struct listnode *node;
231 struct mpls_te_link *lp;
232 unsigned int key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr));
718e3744 233
d62a17ae 234 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
235 if (lp->instance == key)
236 return lp;
718e3744 237
2c72cf2a 238 zlog_info("lookup_linkparams_by_instance: Entry not found: key(%x)",
d62a17ae 239 key);
240 return NULL;
718e3744 241}
242
996c9314
LB
243static void ospf_mpls_te_foreach_area(
244 void (*func)(struct mpls_te_link *lp, enum lsa_opcode sched_opcode),
245 enum lsa_opcode sched_opcode)
718e3744 246{
d62a17ae 247 struct listnode *node, *nnode;
248 struct listnode *node2;
249 struct mpls_te_link *lp;
250 struct ospf_area *area;
718e3744 251
d62a17ae 252 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
253 /* Skip Inter-AS TEv2 Links */
254 if (IS_INTER_AS(lp->type))
255 continue;
256 if ((area = lp->area) == NULL)
257 continue;
32ab5cf4
OD
258 if (CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE))
259 continue;
718e3744 260
d62a17ae 261 if (func != NULL)
262 (*func)(lp, sched_opcode);
718e3744 263
d62a17ae 264 for (node2 = listnextnode(node); node2;
265 node2 = listnextnode(node2))
266 if ((lp = listgetdata(node2)) != NULL)
267 if (lp->area != NULL)
268 if (IPV4_ADDR_SAME(&lp->area->area_id,
269 &area->area_id))
270 SET_FLAG(lp->flags,
271 LPFLG_LOOKUP_DONE);
272 }
718e3744 273
d62a17ae 274 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp))
275 if (lp->area != NULL)
276 UNSET_FLAG(lp->flags, LPFLG_LOOKUP_DONE);
718e3744 277
d62a17ae 278 return;
718e3744 279}
280
d62a17ae 281static void set_mpls_te_router_addr(struct in_addr ipv4)
718e3744 282{
d62a17ae 283 OspfMplsTE.router_addr.header.type = htons(TE_TLV_ROUTER_ADDR);
284 OspfMplsTE.router_addr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
285 OspfMplsTE.router_addr.value = ipv4;
286 return;
718e3744 287}
288
d62a17ae 289static void set_linkparams_link_header(struct mpls_te_link *lp)
718e3744 290{
d7c0a89a 291 uint16_t length = 0;
718e3744 292
d62a17ae 293 /* TE_LINK_SUBTLV_LINK_TYPE */
294 if (ntohs(lp->link_type.header.type) != 0)
295 length += TLV_SIZE(&lp->link_type.header);
718e3744 296
d62a17ae 297 /* TE_LINK_SUBTLV_LINK_ID */
298 if (ntohs(lp->link_id.header.type) != 0)
299 length += TLV_SIZE(&lp->link_id.header);
718e3744 300
d62a17ae 301 /* TE_LINK_SUBTLV_LCLIF_IPADDR */
302 if (lp->lclif_ipaddr.header.type != 0)
303 length += TLV_SIZE(&lp->lclif_ipaddr.header);
718e3744 304
d62a17ae 305 /* TE_LINK_SUBTLV_RMTIF_IPADDR */
306 if (lp->rmtif_ipaddr.header.type != 0)
307 length += TLV_SIZE(&lp->rmtif_ipaddr.header);
718e3744 308
d62a17ae 309 /* TE_LINK_SUBTLV_TE_METRIC */
310 if (ntohs(lp->te_metric.header.type) != 0)
311 length += TLV_SIZE(&lp->te_metric.header);
718e3744 312
d62a17ae 313 /* TE_LINK_SUBTLV_MAX_BW */
314 if (ntohs(lp->max_bw.header.type) != 0)
315 length += TLV_SIZE(&lp->max_bw.header);
718e3744 316
d62a17ae 317 /* TE_LINK_SUBTLV_MAX_RSV_BW */
318 if (ntohs(lp->max_rsv_bw.header.type) != 0)
319 length += TLV_SIZE(&lp->max_rsv_bw.header);
718e3744 320
d62a17ae 321 /* TE_LINK_SUBTLV_UNRSV_BW */
322 if (ntohs(lp->unrsv_bw.header.type) != 0)
323 length += TLV_SIZE(&lp->unrsv_bw.header);
718e3744 324
d62a17ae 325 /* TE_LINK_SUBTLV_RSC_CLSCLR */
326 if (ntohs(lp->rsc_clsclr.header.type) != 0)
327 length += TLV_SIZE(&lp->rsc_clsclr.header);
328
329 /* TE_LINK_SUBTLV_LLRI */
330 if (ntohs(lp->llri.header.type) != 0)
331 length += TLV_SIZE(&lp->llri.header);
332
333 /* TE_LINK_SUBTLV_RIP */
334 if (ntohs(lp->rip.header.type) != 0)
335 length += TLV_SIZE(&lp->rip.header);
336
337 /* TE_LINK_SUBTLV_RAS */
338 if (ntohs(lp->ras.header.type) != 0)
339 length += TLV_SIZE(&lp->ras.header);
340
341 /* TE_LINK_SUBTLV_LRRID */
342 if (ntohs(lp->lrrid.header.type) != 0)
343 length += TLV_SIZE(&lp->lrrid.header);
344
345 /* TE_LINK_SUBTLV_AV_DELAY */
346 if (ntohs(lp->av_delay.header.type) != 0)
347 length += TLV_SIZE(&lp->av_delay.header);
348
349 /* TE_LINK_SUBTLV_MM_DELAY */
350 if (ntohs(lp->mm_delay.header.type) != 0)
351 length += TLV_SIZE(&lp->mm_delay.header);
352
353 /* TE_LINK_SUBTLV_DELAY_VAR */
354 if (ntohs(lp->delay_var.header.type) != 0)
355 length += TLV_SIZE(&lp->delay_var.header);
356
357 /* TE_LINK_SUBTLV_PKT_LOSS */
358 if (ntohs(lp->pkt_loss.header.type) != 0)
359 length += TLV_SIZE(&lp->pkt_loss.header);
360
361 /* TE_LINK_SUBTLV_RES_BW */
362 if (ntohs(lp->res_bw.header.type) != 0)
363 length += TLV_SIZE(&lp->res_bw.header);
364
365 /* TE_LINK_SUBTLV_AVA_BW */
366 if (ntohs(lp->ava_bw.header.type) != 0)
367 length += TLV_SIZE(&lp->ava_bw.header);
368
369 /* TE_LINK_SUBTLV_USE_BW */
370 if (ntohs(lp->use_bw.header.type) != 0)
371 length += TLV_SIZE(&lp->use_bw.header);
718e3744 372
d62a17ae 373 lp->link_header.header.type = htons(TE_TLV_LINK);
374 lp->link_header.header.length = htons(length);
375
376 return;
718e3744 377}
d62a17ae 378
379static void set_linkparams_link_type(struct ospf_interface *oi,
380 struct mpls_te_link *lp)
381{
382 lp->link_type.header.type = htons(TE_LINK_SUBTLV_LINK_TYPE);
383 lp->link_type.header.length = htons(TE_LINK_SUBTLV_TYPE_SIZE);
384
385 switch (oi->type) {
386 case OSPF_IFTYPE_POINTOPOINT:
387 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
388 break;
389 case OSPF_IFTYPE_BROADCAST:
390 case OSPF_IFTYPE_NBMA:
391 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
392 break;
393 default:
394 /* Not supported yet. */ /* XXX */
395 lp->link_type.header.type = htons(0);
396 break;
397 }
398 return;
718e3744 399}
d62a17ae 400
01c9b80a
OD
401static void set_linkparams_link_id(struct mpls_te_link *lp,
402 struct in_addr link_id)
718e3744 403{
718e3744 404
d62a17ae 405 lp->link_id.header.type = htons(TE_LINK_SUBTLV_LINK_ID);
406 lp->link_id.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
01c9b80a 407 lp->link_id.value = link_id;
d62a17ae 408 return;
718e3744 409}
410
d62a17ae 411static void set_linkparams_lclif_ipaddr(struct mpls_te_link *lp,
412 struct in_addr lclif)
16f1b9ee
OD
413{
414
d62a17ae 415 lp->lclif_ipaddr.header.type = htons(TE_LINK_SUBTLV_LCLIF_IPADDR);
416 lp->lclif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
417 lp->lclif_ipaddr.value[0] = lclif;
418 return;
16f1b9ee
OD
419}
420
d62a17ae 421static void set_linkparams_rmtif_ipaddr(struct mpls_te_link *lp,
422 struct in_addr rmtif)
16f1b9ee
OD
423{
424
d62a17ae 425 lp->rmtif_ipaddr.header.type = htons(TE_LINK_SUBTLV_RMTIF_IPADDR);
426 lp->rmtif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
427 lp->rmtif_ipaddr.value[0] = rmtif;
428 return;
16f1b9ee
OD
429}
430
d62a17ae 431static void set_linkparams_te_metric(struct mpls_te_link *lp,
d7c0a89a 432 uint32_t te_metric)
718e3744 433{
d62a17ae 434 lp->te_metric.header.type = htons(TE_LINK_SUBTLV_TE_METRIC);
435 lp->te_metric.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
436 lp->te_metric.value = htonl(te_metric);
437 return;
718e3744 438}
439
d62a17ae 440static void set_linkparams_max_bw(struct mpls_te_link *lp, float fp)
718e3744 441{
d62a17ae 442 lp->max_bw.header.type = htons(TE_LINK_SUBTLV_MAX_BW);
443 lp->max_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
444 lp->max_bw.value = htonf(fp);
445 return;
718e3744 446}
447
d62a17ae 448static void set_linkparams_max_rsv_bw(struct mpls_te_link *lp, float fp)
718e3744 449{
d62a17ae 450 lp->max_rsv_bw.header.type = htons(TE_LINK_SUBTLV_MAX_RSV_BW);
451 lp->max_rsv_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
452 lp->max_rsv_bw.value = htonf(fp);
453 return;
718e3744 454}
455
d62a17ae 456static void set_linkparams_unrsv_bw(struct mpls_te_link *lp, int priority,
457 float fp)
718e3744 458{
d62a17ae 459 /* Note that TLV-length field is the size of array. */
460 lp->unrsv_bw.header.type = htons(TE_LINK_SUBTLV_UNRSV_BW);
461 lp->unrsv_bw.header.length = htons(TE_LINK_SUBTLV_UNRSV_SIZE);
462 lp->unrsv_bw.value[priority] = htonf(fp);
463 return;
718e3744 464}
465
d62a17ae 466static void set_linkparams_rsc_clsclr(struct mpls_te_link *lp,
d7c0a89a 467 uint32_t classcolor)
718e3744 468{
d62a17ae 469 lp->rsc_clsclr.header.type = htons(TE_LINK_SUBTLV_RSC_CLSCLR);
470 lp->rsc_clsclr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
471 lp->rsc_clsclr.value = htonl(classcolor);
472 return;
718e3744 473}
474
d62a17ae 475static void set_linkparams_inter_as(struct mpls_te_link *lp,
d7c0a89a 476 struct in_addr addr, uint32_t as)
16f1b9ee
OD
477{
478
d62a17ae 479 /* Set the Remote ASBR IP address and then the associated AS number */
480 lp->rip.header.type = htons(TE_LINK_SUBTLV_RIP);
481 lp->rip.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
482 lp->rip.value = addr;
16f1b9ee 483
d62a17ae 484 lp->ras.header.type = htons(TE_LINK_SUBTLV_RAS);
485 lp->ras.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
486 lp->ras.value = htonl(as);
16f1b9ee
OD
487}
488
d62a17ae 489static void unset_linkparams_inter_as(struct mpls_te_link *lp)
16f1b9ee
OD
490{
491
d62a17ae 492 /* Reset the Remote ASBR IP address and then the associated AS number */
493 lp->rip.header.type = htons(0);
494 lp->rip.header.length = htons(0);
495 lp->rip.value.s_addr = htonl(0);
16f1b9ee 496
d62a17ae 497 lp->ras.header.type = htons(0);
498 lp->ras.header.length = htons(0);
499 lp->ras.value = htonl(0);
16f1b9ee
OD
500}
501
d7c0a89a
QY
502void set_linkparams_llri(struct mpls_te_link *lp, uint32_t local,
503 uint32_t remote)
16f1b9ee
OD
504{
505
d62a17ae 506 lp->llri.header.type = htons(TE_LINK_SUBTLV_LLRI);
507 lp->llri.header.length = htons(TE_LINK_SUBTLV_LLRI_SIZE);
508 lp->llri.local = htonl(local);
509 lp->llri.remote = htonl(remote);
16f1b9ee
OD
510}
511
d62a17ae 512void set_linkparams_lrrid(struct mpls_te_link *lp, struct in_addr local,
513 struct in_addr remote)
16f1b9ee
OD
514{
515
d62a17ae 516 lp->lrrid.header.type = htons(TE_LINK_SUBTLV_LRRID);
517 lp->lrrid.header.length = htons(TE_LINK_SUBTLV_LRRID_SIZE);
518 lp->lrrid.local.s_addr = local.s_addr;
519 lp->lrrid.remote.s_addr = remote.s_addr;
16f1b9ee
OD
520}
521
d7c0a89a
QY
522static void set_linkparams_av_delay(struct mpls_te_link *lp, uint32_t delay,
523 uint8_t anormal)
16f1b9ee 524{
d7c0a89a 525 uint32_t tmp;
d62a17ae 526 /* Note that TLV-length field is the size of array. */
527 lp->av_delay.header.type = htons(TE_LINK_SUBTLV_AV_DELAY);
528 lp->av_delay.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
529 tmp = delay & TE_EXT_MASK;
530 if (anormal)
531 tmp |= TE_EXT_ANORMAL;
532 lp->av_delay.value = htonl(tmp);
533 return;
16f1b9ee
OD
534}
535
d7c0a89a
QY
536static void set_linkparams_mm_delay(struct mpls_te_link *lp, uint32_t low,
537 uint32_t high, uint8_t anormal)
16f1b9ee 538{
d7c0a89a 539 uint32_t tmp;
d62a17ae 540 /* Note that TLV-length field is the size of array. */
541 lp->mm_delay.header.type = htons(TE_LINK_SUBTLV_MM_DELAY);
542 lp->mm_delay.header.length = htons(TE_LINK_SUBTLV_MM_DELAY_SIZE);
543 tmp = low & TE_EXT_MASK;
544 if (anormal)
545 tmp |= TE_EXT_ANORMAL;
546 lp->mm_delay.low = htonl(tmp);
547 lp->mm_delay.high = htonl(high);
548 return;
16f1b9ee
OD
549}
550
d7c0a89a 551static void set_linkparams_delay_var(struct mpls_te_link *lp, uint32_t jitter)
16f1b9ee 552{
d62a17ae 553 /* Note that TLV-length field is the size of array. */
554 lp->delay_var.header.type = htons(TE_LINK_SUBTLV_DELAY_VAR);
555 lp->delay_var.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
556 lp->delay_var.value = htonl(jitter & TE_EXT_MASK);
557 return;
16f1b9ee
OD
558}
559
d7c0a89a
QY
560static void set_linkparams_pkt_loss(struct mpls_te_link *lp, uint32_t loss,
561 uint8_t anormal)
16f1b9ee 562{
d7c0a89a 563 uint32_t tmp;
d62a17ae 564 /* Note that TLV-length field is the size of array. */
565 lp->pkt_loss.header.type = htons(TE_LINK_SUBTLV_PKT_LOSS);
566 lp->pkt_loss.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
567 tmp = loss & TE_EXT_MASK;
568 if (anormal)
569 tmp |= TE_EXT_ANORMAL;
570 lp->pkt_loss.value = htonl(tmp);
571 return;
16f1b9ee
OD
572}
573
d62a17ae 574static void set_linkparams_res_bw(struct mpls_te_link *lp, float fp)
16f1b9ee 575{
d62a17ae 576 /* Note that TLV-length field is the size of array. */
577 lp->res_bw.header.type = htons(TE_LINK_SUBTLV_RES_BW);
578 lp->res_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
579 lp->res_bw.value = htonf(fp);
580 return;
16f1b9ee
OD
581}
582
d62a17ae 583static void set_linkparams_ava_bw(struct mpls_te_link *lp, float fp)
16f1b9ee 584{
d62a17ae 585 /* Note that TLV-length field is the size of array. */
586 lp->ava_bw.header.type = htons(TE_LINK_SUBTLV_AVA_BW);
587 lp->ava_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
588 lp->ava_bw.value = htonf(fp);
589 return;
16f1b9ee
OD
590}
591
d62a17ae 592static void set_linkparams_use_bw(struct mpls_te_link *lp, float fp)
16f1b9ee 593{
d62a17ae 594 /* Note that TLV-length field is the size of array. */
595 lp->use_bw.header.type = htons(TE_LINK_SUBTLV_USE_BW);
596 lp->use_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE);
597 lp->use_bw.value = htonf(fp);
598 return;
16f1b9ee
OD
599}
600
601/* Update TE parameters from Interface */
d62a17ae 602static void update_linkparams(struct mpls_te_link *lp)
603{
604 int i;
605 struct interface *ifp;
606
607 /* Get the Interface structure */
608 if ((ifp = lp->ifp) == NULL) {
609 if (IS_DEBUG_OSPF_TE)
610 zlog_debug(
611 "OSPF MPLS-TE: Abort update TE parameters: no interface associated to Link Parameters");
612 return;
613 }
614 if (!HAS_LINK_PARAMS(ifp)) {
615 if (IS_DEBUG_OSPF_TE)
616 zlog_debug(
617 "OSPF MPLS-TE: Abort update TE parameters: no Link Parameters for interface");
618 return;
619 }
620
621 /* RFC3630 metrics */
622 if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
623 set_linkparams_rsc_clsclr(lp, ifp->link_params->admin_grp);
624 else
625 TLV_TYPE(lp->rsc_clsclr) = 0;
626
627 if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
628 set_linkparams_max_bw(lp, ifp->link_params->max_bw);
629 else
630 TLV_TYPE(lp->max_bw) = 0;
631
632 if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
633 set_linkparams_max_rsv_bw(lp, ifp->link_params->max_rsv_bw);
634 else
635 TLV_TYPE(lp->max_rsv_bw) = 0;
636
637 if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
638 for (i = 0; i < MAX_CLASS_TYPE; i++)
639 set_linkparams_unrsv_bw(lp, i,
640 ifp->link_params->unrsv_bw[i]);
641 else
642 TLV_TYPE(lp->unrsv_bw) = 0;
643
644 if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
645 set_linkparams_te_metric(lp, ifp->link_params->te_metric);
646 else
647 TLV_TYPE(lp->te_metric) = 0;
648
649 /* TE metric Extensions */
650 if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
651 set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0);
652 else
653 TLV_TYPE(lp->av_delay) = 0;
654
655 if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
656 set_linkparams_mm_delay(lp, ifp->link_params->min_delay,
657 ifp->link_params->max_delay, 0);
658 else
659 TLV_TYPE(lp->mm_delay) = 0;
660
661 if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
662 set_linkparams_delay_var(lp, ifp->link_params->delay_var);
663 else
664 TLV_TYPE(lp->delay_var) = 0;
665
666 if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
667 set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0);
668 else
669 TLV_TYPE(lp->pkt_loss) = 0;
670
671 if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
672 set_linkparams_res_bw(lp, ifp->link_params->res_bw);
673 else
674 TLV_TYPE(lp->res_bw) = 0;
675
676 if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
677 set_linkparams_ava_bw(lp, ifp->link_params->ava_bw);
678 else
679 TLV_TYPE(lp->ava_bw) = 0;
680
681 if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
682 set_linkparams_use_bw(lp, ifp->link_params->use_bw);
683 else
684 TLV_TYPE(lp->use_bw) = 0;
685
686 /* RFC5392 */
687 if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) {
688 /* Flush LSA if it engaged and was previously a STD_TE one */
689 if (IS_STD_TE(lp->type)
690 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
691 if (IS_DEBUG_OSPF_TE)
692 zlog_debug(
693 "OSPF MPLS-TE Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]",
694 ifp->name, lp->flags, lp->type);
695
696 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
697 /* Then, switch it to INTER-AS */
698 if (OspfMplsTE.inter_as == AS)
699 lp->flags = INTER_AS | FLOOD_AS;
700 else {
701 lp->flags = INTER_AS | FLOOD_AREA;
702 lp->area = ospf_area_lookup_by_area_id(
b5a8894d 703 ospf_lookup_by_vrf_id(VRF_DEFAULT),
d62a17ae 704 OspfMplsTE.interas_areaid);
705 }
706 }
707 set_linkparams_inter_as(lp, ifp->link_params->rmt_ip,
708 ifp->link_params->rmt_as);
709 } else {
710 if (IS_DEBUG_OSPF_TE)
711 zlog_debug(
712 "OSPF MPLS-TE Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]",
713 ifp->name, lp->flags, lp->type);
714
715 /* reset inter-as TE params */
716 /* Flush LSA if it engaged and was previously an INTER_AS one */
717 if (IS_INTER_AS(lp->type)
718 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
719 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
720 /* Then, switch it to Standard TE */
721 lp->flags = STD_TE | FLOOD_AREA;
722 }
723 unset_linkparams_inter_as(lp);
724 }
725}
726
727static void initialize_linkparams(struct mpls_te_link *lp)
728{
729 struct interface *ifp = lp->ifp;
ead99d5f
OD
730 struct ospf_interface *oi = NULL;
731 struct route_node *rn;
d62a17ae 732
733 if (IS_DEBUG_OSPF_TE)
734 zlog_debug(
735 "MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s",
736 ifp->name);
737
ead99d5f 738 /* Search OSPF Interface parameters for this interface */
996c9314 739 for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
ead99d5f
OD
740
741 if ((oi = rn->info) == NULL)
742 continue;
743
744 if (oi->ifp == ifp)
745 break;
746 }
747
748 if ((oi == NULL) || (oi->ifp != ifp)) {
d62a17ae 749 if (IS_DEBUG_OSPF_TE)
2c72cf2a 750 zlog_debug(
d62a17ae 751 "MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s",
752 ifp->name);
753 return;
754 }
755
756 /*
757 * Try to set initial values those can be derived from
758 * zebra-interface information.
759 */
760 set_linkparams_link_type(oi, lp);
761
762 /* Set local IP addr */
763 set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
764
765 /* Set Remote IP addr if Point to Point Interface */
ead99d5f 766 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
d62a17ae 767 struct prefix *pref = CONNECTED_PREFIX(oi->connected);
768 if (pref != NULL)
769 set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4);
770 }
771
772 /* Keep Area information in combination with link parameters. */
773 lp->area = oi->area;
774
775 return;
776}
777
778static int is_mandated_params_set(struct mpls_te_link *lp)
779{
780 int rc = 0;
781
782 if (ntohs(OspfMplsTE.router_addr.header.type) == 0) {
ade6974d 783 flog_warn(
cf444bcf 784 EC_OSPF_TE_UNEXPECTED,
ade6974d 785 "MPLS-TE(is_mandated_params_set) Missing Router Address");
ead99d5f 786 return rc;
d62a17ae 787 }
788
789 if (ntohs(lp->link_type.header.type) == 0) {
cf444bcf 790 flog_warn(EC_OSPF_TE_UNEXPECTED,
2c72cf2a 791 "MPLS-TE(is_mandated_params_set) Missing Link Type");
ead99d5f 792 return rc;
d62a17ae 793 }
794
795 if (!IS_INTER_AS(lp->type) && (ntohs(lp->link_id.header.type) == 0)) {
cf444bcf 796 flog_warn(EC_OSPF_TE_UNEXPECTED,
2c72cf2a 797 "MPLS-TE(is_mandated_params_set) Missing Link ID");
ead99d5f 798 return rc;
d62a17ae 799 }
800
801 rc = 1;
d62a17ae 802 return rc;
718e3744 803}
804
805/*------------------------------------------------------------------------*
806 * Followings are callback functions against generic Opaque-LSAs handling.
807 *------------------------------------------------------------------------*/
808
d62a17ae 809static int ospf_mpls_te_new_if(struct interface *ifp)
718e3744 810{
d62a17ae 811 struct mpls_te_link *new;
718e3744 812
d62a17ae 813 if (IS_DEBUG_OSPF_TE)
814 zlog_debug(
815 "MPLS-TE(ospf_mpls_te_new_if) Add new %s interface %s to MPLS-TE list",
816 ifp->link_params ? "Active" : "Inactive", ifp->name);
16f1b9ee 817
2c72cf2a
DS
818 if (lookup_linkparams_by_ifp(ifp) != NULL)
819 return 0;
718e3744 820
d62a17ae 821 new = XCALLOC(MTYPE_OSPF_MPLS_TE, sizeof(struct mpls_te_link));
718e3744 822
d62a17ae 823 new->instance = get_mpls_te_instance_value();
824 new->ifp = ifp;
825 /* By default TE-Link is RFC3630 compatible flooding in Area and not
826 * active */
827 /* This default behavior will be adapted with call to
828 * ospf_mpls_te_update_if() */
829 new->type = STD_TE | FLOOD_AREA;
830 new->flags = LPFLG_LSA_INACTIVE;
16f1b9ee 831
d62a17ae 832 /* Initialize Link Parameters from Interface */
833 initialize_linkparams(new);
718e3744 834
d62a17ae 835 /* Set TE Parameters from Interface */
836 update_linkparams(new);
718e3744 837
d62a17ae 838 /* Add Link Parameters structure to the list */
839 listnode_add(OspfMplsTE.iflist, new);
718e3744 840
d62a17ae 841 if (IS_DEBUG_OSPF_TE)
842 zlog_debug(
843 "OSPF MPLS-TE New IF: Add new LP context for %s[%d/%d]",
844 ifp->name, new->flags, new->type);
16f1b9ee 845
d62a17ae 846 /* Schedule Opaque-LSA refresh. */ /* XXX */
2c72cf2a 847 return 0;
718e3744 848}
849
d62a17ae 850static int ospf_mpls_te_del_if(struct interface *ifp)
718e3744 851{
d62a17ae 852 struct mpls_te_link *lp;
853 int rc = -1;
718e3744 854
d62a17ae 855 if ((lp = lookup_linkparams_by_ifp(ifp)) != NULL) {
856 struct list *iflist = OspfMplsTE.iflist;
718e3744 857
d62a17ae 858 /* Dequeue listnode entry from the list. */
859 listnode_delete(iflist, lp);
718e3744 860
d62a17ae 861 XFREE(MTYPE_OSPF_MPLS_TE, lp);
862 }
718e3744 863
d62a17ae 864 /* Schedule Opaque-LSA refresh. */ /* XXX */
718e3744 865
d62a17ae 866 rc = 0;
d62a17ae 867 return rc;
718e3744 868}
869
16f1b9ee
OD
870/* Main initialization / update function of the MPLS TE Link context */
871
872/* Call when interface TE Link parameters are modified */
d62a17ae 873void ospf_mpls_te_update_if(struct interface *ifp)
874{
875 struct mpls_te_link *lp;
876
877 if (IS_DEBUG_OSPF_TE)
878 zlog_debug(
879 "OSPF MPLS-TE: Update LSA parameters for interface %s [%s]",
880 ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF");
881
882 /* Get Link context from interface */
883 if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) {
ade6974d 884 flog_warn(
cf444bcf 885 EC_OSPF_TE_UNEXPECTED,
ade6974d
QY
886 "OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s",
887 ifp->name);
d62a17ae 888 return;
889 }
890
891 /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */
892 if (HAS_LINK_PARAMS(ifp)) {
893 SET_FLAG(lp->flags, LPFLG_LSA_ACTIVE);
894
895 /* Update TE parameters */
896 update_linkparams(lp);
897
898 /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is
899 * enabled */
32ab5cf4 900 if (OspfMplsTE.enabled)
d62a17ae 901 if (lp->area != NULL) {
32ab5cf4 902 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
996c9314
LB
903 ospf_mpls_te_lsa_schedule(
904 lp, REFRESH_THIS_LSA);
32ab5cf4 905 else
996c9314
LB
906 ospf_mpls_te_lsa_schedule(
907 lp, REORIGINATE_THIS_LSA);
d62a17ae 908 }
909 } else {
910 /* If MPLS TE is disable on this interface, flush LSA if it is
911 * already engaged */
32ab5cf4
OD
912 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
913 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
d62a17ae 914 else
915 /* Reset Activity flag */
916 lp->flags = LPFLG_LSA_INACTIVE;
917 }
918
919 return;
920}
921
01c9b80a
OD
922/*
923 * Just add interface and set available information. Other information
924 * and flooding of LSA will be done later when adjacency will be up
925 * See ospf_mpls_te_nsm_change() after
926 */
d62a17ae 927static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state)
928{
01c9b80a 929
d62a17ae 930 struct mpls_te_link *lp;
931
01c9b80a
OD
932 lp = lookup_linkparams_by_ifp(oi->ifp);
933 if (lp == NULL) {
ade6974d 934 flog_warn(
cf444bcf 935 EC_OSPF_TE_UNEXPECTED,
01c9b80a
OD
936 "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
937 __func__, IF_NAME(oi));
ead99d5f 938 return;
d62a17ae 939 }
940
941 if (oi->area == NULL || oi->area->ospf == NULL) {
ade6974d 942 flog_warn(
cf444bcf 943 EC_OSPF_TE_UNEXPECTED,
01c9b80a
OD
944 "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
945 __func__, IF_NAME(oi));
ead99d5f 946 return;
d62a17ae 947 }
01c9b80a 948
d62a17ae 949 /* Keep Area information in combination with linkparams. */
950 lp->area = oi->area;
951
952 /* Keep interface MPLS-TE status */
953 lp->flags = HAS_LINK_PARAMS(oi->ifp);
954
955 switch (oi->state) {
956 case ISM_PointToPoint:
957 case ISM_DROther:
958 case ISM_Backup:
959 case ISM_DR:
01c9b80a 960 /* Set Link type and Local IP addr */
d62a17ae 961 set_linkparams_link_type(oi, lp);
d62a17ae 962 set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4);
963
d62a17ae 964 break;
965 default:
01c9b80a 966 /* State is undefined: Flush LSA if engaged */
32ab5cf4
OD
967 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
968 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
d62a17ae 969 break;
970 }
718e3744 971
01c9b80a
OD
972 if (IS_DEBUG_OSPF_TE)
973 zlog_debug(
974 "MPLS-TE(%s): Update Link parameters for interface %s",
975 __func__, IF_NAME(oi));
976
d62a17ae 977 return;
718e3744 978}
979
01c9b80a
OD
980/*
981 * Complete TE info and schedule LSA flooding
982 * Link-ID and Remote IP address must be set with neighbor info
983 * which are only valid once NSM state is FULL
984 */
d62a17ae 985static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state)
718e3744 986{
01c9b80a
OD
987 struct ospf_interface *oi = nbr->oi;
988 struct mpls_te_link *lp;
989
990 /* Process Neighbor only when its state is NSM Full */
991 if (nbr->state != NSM_Full)
992 return;
993
994 /* Get interface information for Traffic Engineering */
995 lp = lookup_linkparams_by_ifp(oi->ifp);
996 if (lp == NULL) {
997 flog_warn(
998 EC_OSPF_TE_UNEXPECTED,
999 "MPLS-TE (%s): Cannot get linkparams from OI(%s)?",
1000 __func__, IF_NAME(oi));
1001 return;
1002 }
1003
1004 if (oi->area == NULL || oi->area->ospf == NULL) {
1005 flog_warn(
1006 EC_OSPF_TE_UNEXPECTED,
1007 "MPLS-TE (%s): Cannot refer to OSPF from OI(%s)?",
1008 __func__, IF_NAME(oi));
1009 return;
1010 }
1011
1012 /* Keep Area information in combination with SR info. */
1013 lp->area = oi->area;
1014
1015 /* Keep interface MPLS-TE status */
1016 lp->flags = HAS_LINK_PARAMS(oi->ifp);
1017
1018 /*
1019 * The Link ID is identical to the contents of the Link ID field
1020 * in the Router LSA for these link types.
1021 */
1022 switch (oi->state) {
1023 case ISM_PointToPoint:
1024 /* Set Link ID with neighbor Router ID */
1025 set_linkparams_link_id(lp, nbr->router_id);
1026 /* Set Remote IP address */
1027 set_linkparams_rmtif_ipaddr(lp, nbr->address.u.prefix4);
1028 break;
1029
1030 case ISM_DR:
1031 case ISM_DROther:
1032 case ISM_Backup:
1033 /* Set Link ID with the Designated Router ID */
1034 set_linkparams_link_id(lp, DR(oi));
1035 break;
1036
1037 default:
1038 /* State is undefined: Flush LSA if engaged */
1039 if (OspfMplsTE.enabled &&
1040 CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
1041 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
1042 return;
1043 }
1044
1045 if (IS_DEBUG_OSPF_TE)
1046 zlog_debug(
96b663a3
MS
1047 "MPLS-TE (%s): Add Link-ID %pI4 for interface %s ",
1048 __func__, &lp->link_id.value, oi->ifp->name);
01c9b80a
OD
1049
1050 /* Try to Schedule LSA */
1051 if (OspfMplsTE.enabled) {
1052 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
1053 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
1054 else
1055 ospf_mpls_te_lsa_schedule(lp, REORIGINATE_THIS_LSA);
1056 }
d62a17ae 1057 return;
718e3744 1058}
1059
1060/*------------------------------------------------------------------------*
1061 * Followings are OSPF protocol processing functions for MPLS-TE.
1062 *------------------------------------------------------------------------*/
1063
ead99d5f 1064static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
d62a17ae 1065{
ead99d5f 1066 stream_put(s, tlvh, sizeof(struct tlv_header));
d62a17ae 1067 return;
1068}
1069
1070static void build_router_tlv(struct stream *s)
1071{
ead99d5f 1072 struct tlv_header *tlvh = &OspfMplsTE.router_addr.header;
d62a17ae 1073 if (ntohs(tlvh->type) != 0) {
1074 build_tlv_header(s, tlvh);
5d0df50f 1075 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
d62a17ae 1076 }
1077 return;
1078}
1079
ead99d5f 1080static void build_link_subtlv(struct stream *s, struct tlv_header *tlvh)
d62a17ae 1081{
1082
1083 if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) {
1084 build_tlv_header(s, tlvh);
5d0df50f 1085 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
d62a17ae 1086 }
1087 return;
1088}
1089
1090static void build_link_tlv(struct stream *s, struct mpls_te_link *lp)
1091{
1092 set_linkparams_link_header(lp);
1093 build_tlv_header(s, &lp->link_header.header);
1094
1095 build_link_subtlv(s, &lp->link_type.header);
1096 build_link_subtlv(s, &lp->link_id.header);
1097 build_link_subtlv(s, &lp->lclif_ipaddr.header);
1098 build_link_subtlv(s, &lp->rmtif_ipaddr.header);
1099 build_link_subtlv(s, &lp->te_metric.header);
1100 build_link_subtlv(s, &lp->max_bw.header);
1101 build_link_subtlv(s, &lp->max_rsv_bw.header);
1102 build_link_subtlv(s, &lp->unrsv_bw.header);
1103 build_link_subtlv(s, &lp->rsc_clsclr.header);
1104 build_link_subtlv(s, &lp->lrrid.header);
1105 build_link_subtlv(s, &lp->llri.header);
1106 build_link_subtlv(s, &lp->rip.header);
1107 build_link_subtlv(s, &lp->ras.header);
1108 build_link_subtlv(s, &lp->av_delay.header);
1109 build_link_subtlv(s, &lp->mm_delay.header);
1110 build_link_subtlv(s, &lp->delay_var.header);
1111 build_link_subtlv(s, &lp->pkt_loss.header);
1112 build_link_subtlv(s, &lp->res_bw.header);
1113 build_link_subtlv(s, &lp->ava_bw.header);
1114 build_link_subtlv(s, &lp->use_bw.header);
1115
1116 return;
1117}
1118
1119static void ospf_mpls_te_lsa_body_set(struct stream *s, struct mpls_te_link *lp)
1120{
1121 /*
1122 * The router address TLV is type 1, and ...
1123 * It must appear in exactly one
1124 * Traffic Engineering LSA originated by a router.
1125 */
1126 build_router_tlv(s);
1127
1128 /*
1129 * Only one Link TLV shall be carried in each LSA, allowing for fine
1130 * granularity changes in topology.
1131 */
1132 build_link_tlv(s, lp);
1133 return;
718e3744 1134}
1135
1136/* Create new opaque-LSA. */
b5a8894d
CS
1137static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
1138 struct ospf_area *area,
d62a17ae 1139 struct mpls_te_link *lp)
1140{
1141 struct stream *s;
1142 struct lsa_header *lsah;
1143 struct ospf_lsa *new = NULL;
d7c0a89a 1144 uint8_t options, lsa_type = 0;
d62a17ae 1145 struct in_addr lsa_id;
d7c0a89a
QY
1146 uint32_t tmp;
1147 uint16_t length;
d62a17ae 1148
1149 /* Create a stream for LSA. */
266469eb 1150 s = stream_new(OSPF_MAX_LSA_SIZE);
d62a17ae 1151 lsah = (struct lsa_header *)STREAM_DATA(s);
1152
1153 options = OSPF_OPTION_O; /* Don't forget this :-) */
1154
1155 /* Set opaque-LSA header fields depending of the type of RFC */
1156 if (IS_INTER_AS(lp->type)) {
72c03801
QY
1157 if (IS_FLOOD_AS(lp->type)) {
1158 /* Enable AS external as we flood Inter-AS with Opaque
1159 * Type 11
1160 */
1161 options |= OSPF_OPTION_E;
1162 lsa_type = OSPF_OPAQUE_AS_LSA;
1163 } else {
d62a17ae 1164 options |= LSA_OPTIONS_GET(
1165 area); /* Get area default option */
1166 options |= LSA_OPTIONS_NSSA_GET(area);
1167 lsa_type = OSPF_OPAQUE_AREA_LSA;
1168 }
1169 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1170 lsa_id.s_addr = htonl(tmp);
1171
0760d3c9
DS
1172 if (!ospf) {
1173 stream_free(s);
b5a8894d 1174 return NULL;
0760d3c9 1175 }
d62a17ae 1176
b5a8894d 1177 lsa_header_set(s, options, lsa_type, lsa_id, ospf->router_id);
d62a17ae 1178 } else {
1179 options |= LSA_OPTIONS_GET(area); /* Get area default option */
1180 options |= LSA_OPTIONS_NSSA_GET(area);
1181 lsa_type = OSPF_OPAQUE_AREA_LSA;
1182 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
1183 lp->instance);
1184 lsa_id.s_addr = htonl(tmp);
1185 lsa_header_set(s, options, lsa_type, lsa_id,
1186 area->ospf->router_id);
1187 }
1188
1189 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
1190 zlog_debug(
96b663a3
MS
1191 "LSA[Type%d:%pI4]: Create an Opaque-LSA/MPLS-TE instance",
1192 lsa_type, &lsa_id);
d62a17ae 1193
1194 /* Set opaque-LSA body fields. */
1195 ospf_mpls_te_lsa_body_set(s, lp);
1196
1197 /* Set length. */
1198 length = stream_get_endp(s);
1199 lsah->length = htons(length);
1200
1201 /* Now, create an OSPF LSA instance. */
5b3d4186 1202 new = ospf_lsa_new_and_data(length);
d62a17ae 1203
b5a8894d
CS
1204 new->vrf_id = ospf->vrf_id;
1205 if (area && area->ospf)
1206 new->vrf_id = area->ospf->vrf_id;
d62a17ae 1207 new->area = area;
1208 SET_FLAG(new->flags, OSPF_LSA_SELF);
1209 memcpy(new->data, lsah, length);
1210 stream_free(s);
718e3744 1211
d62a17ae 1212 return new;
1213}
1214
1215static int ospf_mpls_te_lsa_originate1(struct ospf_area *area,
1216 struct mpls_te_link *lp)
1217{
b5a8894d 1218 struct ospf_lsa *new = NULL;
d62a17ae 1219 int rc = -1;
1220
1221 /* Create new Opaque-LSA/MPLS-TE instance. */
b5a8894d
CS
1222 new = ospf_mpls_te_lsa_new(area->ospf, area, lp);
1223 if (new == NULL) {
ade6974d 1224 flog_warn(
cf444bcf 1225 EC_OSPF_TE_UNEXPECTED,
ade6974d 1226 "ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
ead99d5f 1227 return rc;
d62a17ae 1228 }
1229
1230 /* Install this LSA into LSDB. */
1231 if (ospf_lsa_install(area->ospf, NULL /*oi*/, new) == NULL) {
cf444bcf 1232 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
2c72cf2a 1233 "ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
d62a17ae 1234 ospf_lsa_unlock(&new);
ead99d5f 1235 return rc;
d62a17ae 1236 }
1237
1238 /* Now this link-parameter entry has associated LSA. */
1239 SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
1240 /* Update new LSA origination count. */
1241 area->ospf->lsa_originate_count++;
1242
1243 /* Flood new LSA through area. */
1244 ospf_flood_through_area(area, NULL /*nbr*/, new);
1245
1246 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
d62a17ae 1247 zlog_debug(
96b663a3
MS
1248 "LSA[Type%d:%pI4]: Originate Opaque-LSA/MPLS-TE: Area(%pI4), Link(%s)",
1249 new->data->type, &new->data->id, &area->area_id,
d62a17ae 1250 lp->ifp->name);
1251 ospf_lsa_header_dump(new->data);
1252 }
1253
1254 rc = 0;
d62a17ae 1255 return rc;
1256}
1257
1258static int ospf_mpls_te_lsa_originate_area(void *arg)
1259{
1260 struct ospf_area *area = (struct ospf_area *)arg;
1261 struct listnode *node, *nnode;
1262 struct mpls_te_link *lp;
1263 int rc = -1;
1264
32ab5cf4 1265 if (!OspfMplsTE.enabled) {
d62a17ae 1266 zlog_info(
1267 "ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now.");
1268 rc = 0; /* This is not an error case. */
ead99d5f 1269 return rc;
d62a17ae 1270 }
1271
1272 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
1273 /* Process only enabled LSA with area scope flooding */
1274 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
1275 || IS_FLOOD_AS(lp->type))
1276 continue;
1277
1278 if (lp->area == NULL)
1279 continue;
1280
1281 if (!IPV4_ADDR_SAME(&lp->area->area_id, &area->area_id))
1282 continue;
1283
32ab5cf4
OD
1284 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
1285 if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
1286 UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
266469eb 1287 zlog_info(
32ab5cf4
OD
1288 "OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate");
1289 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
d62a17ae 1290 }
32ab5cf4
OD
1291 continue;
1292 }
1293
d62a17ae 1294 if (!is_mandated_params_set(lp)) {
266469eb 1295 zlog_info(
d62a17ae 1296 "ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.",
1297 lp->ifp ? lp->ifp->name : "?");
1298 continue;
1299 }
1300
1301 /* Ok, let's try to originate an LSA for this area and Link. */
1302 if (IS_DEBUG_OSPF_TE)
1303 zlog_debug(
96b663a3
MS
1304 "MPLS-TE(ospf_mpls_te_lsa_originate_area) Let's finally reoriginate the LSA %d through the Area %pI4 for Link %s",
1305 lp->instance, &area->area_id,
d62a17ae 1306 lp->ifp ? lp->ifp->name : "?");
1307 if (ospf_mpls_te_lsa_originate1(area, lp) != 0)
ead99d5f 1308 return rc;
d62a17ae 1309 }
1310
1311 rc = 0;
d62a17ae 1312 return rc;
1313}
718e3744 1314
d62a17ae 1315static int ospf_mpls_te_lsa_originate2(struct ospf *top,
1316 struct mpls_te_link *lp)
1317{
1318 struct ospf_lsa *new;
1319 int rc = -1;
1320
1321 /* Create new Opaque-LSA/Inter-AS instance. */
b5a8894d
CS
1322 new = ospf_mpls_te_lsa_new(top, NULL, lp);
1323 if (new == NULL) {
ade6974d 1324 flog_warn(
cf444bcf 1325 EC_OSPF_LSA_UNEXPECTED,
ade6974d 1326 "ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?");
ead99d5f 1327 return rc;
d62a17ae 1328 }
b5a8894d 1329 new->vrf_id = top->vrf_id;
d62a17ae 1330
1331 /* Install this LSA into LSDB. */
1332 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
cf444bcf 1333 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
2c72cf2a 1334 "ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?");
d62a17ae 1335 ospf_lsa_unlock(&new);
ead99d5f 1336 return rc;
d62a17ae 1337 }
1338
1339 /* Now this Router Info parameter entry has associated LSA. */
1340 SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
1341 /* Update new LSA origination count. */
1342 top->lsa_originate_count++;
1343
1344 /* Flood new LSA through AS. */
1345 ospf_flood_through_as(top, NULL /*nbr */, new);
1346
1347 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1348 zlog_debug(
96b663a3
MS
1349 "LSA[Type%d:%pI4]: Originate Opaque-LSA/MPLS-TE Inter-AS",
1350 new->data->type, &new->data->id);
d62a17ae 1351 ospf_lsa_header_dump(new->data);
1352 }
1353
1354 rc = 0;
d62a17ae 1355 return rc;
1356}
1357
1358static int ospf_mpls_te_lsa_originate_as(void *arg)
1359{
1360 struct ospf *top;
1361 struct ospf_area *area;
1362 struct listnode *node, *nnode;
1363 struct mpls_te_link *lp;
1364 int rc = -1;
1365
996c9314 1366 if ((!OspfMplsTE.enabled) || (OspfMplsTE.inter_as == Off)) {
d62a17ae 1367 zlog_info(
1368 "ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now.");
1369 rc = 0; /* This is not an error case. */
ead99d5f 1370 return rc;
d62a17ae 1371 }
1372
1373 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
1374 /* Process only enabled INTER_AS Links or Pseudo-Links */
1375 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)
1376 || !IS_INTER_AS(lp->type))
1377 continue;
1378
32ab5cf4
OD
1379 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
1380 if (CHECK_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH)) {
996c9314 1381 UNSET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
32ab5cf4 1382 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
d62a17ae 1383 }
32ab5cf4
OD
1384 continue;
1385 }
1386
d62a17ae 1387 if (!is_mandated_params_set(lp)) {
ade6974d 1388 flog_warn(
cf444bcf 1389 EC_OSPF_TE_UNEXPECTED,
ade6974d
QY
1390 "ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.",
1391 lp->ifp ? lp->ifp->name : "?");
d62a17ae 1392 continue;
1393 }
1394
1395 /* Ok, let's try to originate an LSA for this AS and Link. */
1396 if (IS_DEBUG_OSPF_TE)
1397 zlog_debug(
1398 "MPLS-TE(ospf_mpls_te_lsa_originate_as) Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s",
1399 lp->instance,
1400 IS_FLOOD_AS(lp->type) ? "AS" : "Area",
1401 lp->ifp ? lp->ifp->name : "Unknown");
1402
1403 if (IS_FLOOD_AS(lp->type)) {
1404 top = (struct ospf *)arg;
1405 ospf_mpls_te_lsa_originate2(top, lp);
1406 } else {
1407 area = (struct ospf_area *)arg;
1408 ospf_mpls_te_lsa_originate1(area, lp);
1409 }
1410 }
1411
1412 rc = 0;
d62a17ae 1413 return rc;
1414}
1415
1416static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa)
1417{
1418 struct mpls_te_link *lp;
1419 struct ospf_area *area = lsa->area;
1420 struct ospf *top;
1421 struct ospf_lsa *new = NULL;
1422
32ab5cf4 1423 if (!OspfMplsTE.enabled) {
d62a17ae 1424 /*
1425 * This LSA must have flushed before due to MPLS-TE status
1426 * change.
1427 * It seems a slip among routers in the routing domain.
1428 */
1429 zlog_info("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
1430 lsa->data->ls_age =
1431 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1432 }
1433
1434 /* At first, resolve lsa/lp relationship. */
1435 if ((lp = lookup_linkparams_by_instance(lsa)) == NULL) {
cf444bcf 1436 flog_warn(EC_OSPF_TE_UNEXPECTED,
2c72cf2a 1437 "ospf_mpls_te_lsa_refresh: Invalid parameter?");
d62a17ae 1438 lsa->data->ls_age =
1439 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
20a7c80c
DS
1440 ospf_opaque_lsa_flush_schedule(lsa);
1441 return NULL;
d62a17ae 1442 }
1443
1444 /* Check if lp was not disable in the interval */
1445 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)) {
ade6974d 1446 flog_warn(
cf444bcf 1447 EC_OSPF_TE_UNEXPECTED,
ade6974d 1448 "ospf_mpls_te_lsa_refresh: lp was disabled: Flush it!");
d62a17ae 1449 lsa->data->ls_age =
1450 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1451 }
1452
1453 /* If the lsa's age reached to MaxAge, start flushing procedure. */
1454 if (IS_LSA_MAXAGE(lsa)) {
20a7c80c 1455 UNSET_FLAG(lp->flags, LPFLG_LSA_ENGAGED);
d62a17ae 1456 ospf_opaque_lsa_flush_schedule(lsa);
ead99d5f 1457 return NULL;
d62a17ae 1458 }
b5a8894d 1459 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
d62a17ae 1460 /* Create new Opaque-LSA/MPLS-TE instance. */
b5a8894d
CS
1461 new = ospf_mpls_te_lsa_new(top, area, lp);
1462 if (new == NULL) {
cf444bcf 1463 flog_warn(EC_OSPF_TE_UNEXPECTED,
2c72cf2a 1464 "ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
ead99d5f 1465 return NULL;
d62a17ae 1466 }
1467 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1468
1469 /* Install this LSA into LSDB. */
1470 /* Given "lsa" will be freed in the next function. */
1471 /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use
1472 * ospf_lookup() to get ospf instance */
1473 if (area)
1474 top = area->ospf;
d62a17ae 1475
1476 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
cf444bcf 1477 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
2c72cf2a 1478 "ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
d62a17ae 1479 ospf_lsa_unlock(&new);
ead99d5f 1480 return NULL;
d62a17ae 1481 }
1482
1483 /* Flood updated LSA through AS or Area depending of the RFC of the link
1484 */
1485 if (IS_FLOOD_AS(lp->type))
1486 ospf_flood_through_as(top, NULL, new);
1487 else
1488 ospf_flood_through_area(area, NULL /*nbr*/, new);
1489
1490 /* Debug logging. */
1491 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
96b663a3
MS
1492 zlog_debug("LSA[Type%d:%pI4]: Refresh Opaque-LSA/MPLS-TE",
1493 new->data->type, &new->data->id);
d62a17ae 1494 ospf_lsa_header_dump(new->data);
1495 }
1496
d62a17ae 1497 return new;
1498}
1499
2a39170c 1500void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, enum lsa_opcode opcode)
d62a17ae 1501{
1502 struct ospf_lsa lsa;
1503 struct lsa_header lsah;
1504 struct ospf *top;
d7c0a89a 1505 uint32_t tmp;
d62a17ae 1506
1507 memset(&lsa, 0, sizeof(lsa));
1508 memset(&lsah, 0, sizeof(lsah));
b5a8894d 1509 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 1510
1511 /* Check if the pseudo link is ready to flood */
1512 if (!(CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE))
1513 || !(IS_FLOOD_AREA(lp->type) || IS_FLOOD_AS(lp->type))) {
1514 return;
1515 }
1516
1517 lsa.area = lp->area;
1518 lsa.data = &lsah;
1519 if (IS_FLOOD_AS(lp->type)) {
1520 lsah.type = OSPF_OPAQUE_AS_LSA;
1521 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance);
1522 lsah.id.s_addr = htonl(tmp);
1523 } else {
1524 lsah.type = OSPF_OPAQUE_AREA_LSA;
1525 if (IS_INTER_AS(lp->type)) {
1526 /* Set the area context if not know */
1527 if (lp->area == NULL)
1528 lp->area = ospf_area_lookup_by_area_id(
1529 top, OspfMplsTE.interas_areaid);
1530 /* Unable to set the area context. Abort! */
1531 if (lp->area == NULL) {
ade6974d 1532 flog_warn(
cf444bcf 1533 EC_OSPF_TE_UNEXPECTED,
ade6974d 1534 "MPLS-TE(ospf_mpls_te_lsa_schedule) Area context is null. Abort !");
d62a17ae 1535 return;
1536 }
1537 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA,
1538 lp->instance);
1539 } else
1540 tmp = SET_OPAQUE_LSID(
1541 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
1542 lp->instance);
1543 lsah.id.s_addr = htonl(tmp);
1544 }
1545
1546 switch (opcode) {
1547 case REORIGINATE_THIS_LSA:
1548 if (IS_FLOOD_AS(lp->type)) {
1549 ospf_opaque_lsa_reoriginate_schedule(
1550 (void *)top, OSPF_OPAQUE_AS_LSA,
1551 OPAQUE_TYPE_INTER_AS_LSA);
1552 break;
1553 }
1554
1555 if (IS_FLOOD_AREA(lp->type)) {
1556 if (IS_INTER_AS(lp->type))
1557 ospf_opaque_lsa_reoriginate_schedule(
1558 (void *)lp->area, OSPF_OPAQUE_AREA_LSA,
1559 OPAQUE_TYPE_INTER_AS_LSA);
1560 else
1561 ospf_opaque_lsa_reoriginate_schedule(
1562 (void *)lp->area, OSPF_OPAQUE_AREA_LSA,
1563 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
1564 break;
1565 }
1566 break;
1567 case REFRESH_THIS_LSA:
1568 ospf_opaque_lsa_refresh_schedule(&lsa);
1569 break;
1570 case FLUSH_THIS_LSA:
1571 /* Reset Activity flag */
1572 lp->flags = LPFLG_LSA_INACTIVE;
1573 ospf_opaque_lsa_flush_schedule(&lsa);
1574 break;
1575 default:
cf444bcf 1576 flog_warn(EC_OSPF_TE_UNEXPECTED,
2c72cf2a 1577 "ospf_mpls_te_lsa_schedule: Unknown opcode (%u)",
d62a17ae 1578 opcode);
1579 break;
1580 }
1581
1582 return;
718e3744 1583}
1584
16f1b9ee 1585
718e3744 1586/*------------------------------------------------------------------------*
1587 * Followings are vty session control functions.
1588 *------------------------------------------------------------------------*/
1589
d7c0a89a 1590static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
718e3744 1591{
d62a17ae 1592 struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
718e3744 1593
d62a17ae 1594 if (vty != NULL)
96b663a3 1595 vty_out(vty, " Router-Address: %pI4\n", &top->value);
d62a17ae 1596 else
96b663a3 1597 zlog_debug(" Router-Address: %pI4", &top->value);
718e3744 1598
d62a17ae 1599 return TLV_SIZE(tlvh);
718e3744 1600}
1601
d7c0a89a 1602static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh)
718e3744 1603{
d62a17ae 1604 struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
718e3744 1605
d62a17ae 1606 if (vty != NULL)
1607 vty_out(vty, " Link: %u octets of data\n",
1608 ntohs(top->header.length));
1609 else
1610 zlog_debug(" Link: %u octets of data",
1611 ntohs(top->header.length));
718e3744 1612
d62a17ae 1613 return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
718e3744 1614}
1615
d7c0a89a
QY
1616static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
1617 struct tlv_header *tlvh)
718e3744 1618{
d62a17ae 1619 struct te_link_subtlv_link_type *top;
1620 const char *cp = "Unknown";
718e3744 1621
d62a17ae 1622 top = (struct te_link_subtlv_link_type *)tlvh;
1623 switch (top->link_type.value) {
1624 case LINK_TYPE_SUBTLV_VALUE_PTP:
1625 cp = "Point-to-point";
1626 break;
1627 case LINK_TYPE_SUBTLV_VALUE_MA:
1628 cp = "Multiaccess";
1629 break;
1630 default:
1631 break;
1632 }
718e3744 1633
d62a17ae 1634 if (vty != NULL)
1635 vty_out(vty, " Link-Type: %s (%u)\n", cp,
1636 top->link_type.value);
1637 else
1638 zlog_debug(" Link-Type: %s (%u)", cp, top->link_type.value);
718e3744 1639
d62a17ae 1640 return TLV_SIZE(tlvh);
718e3744 1641}
1642
d7c0a89a
QY
1643static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
1644 struct tlv_header *tlvh)
718e3744 1645{
d62a17ae 1646 struct te_link_subtlv_link_id *top;
718e3744 1647
d62a17ae 1648 top = (struct te_link_subtlv_link_id *)tlvh;
1649 if (vty != NULL)
96b663a3 1650 vty_out(vty, " Link-ID: %pI4\n", &top->value);
d62a17ae 1651 else
96b663a3 1652 zlog_debug(" Link-ID: %pI4", &top->value);
718e3744 1653
d62a17ae 1654 return TLV_SIZE(tlvh);
718e3744 1655}
1656
d7c0a89a
QY
1657static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
1658 struct tlv_header *tlvh)
718e3744 1659{
d62a17ae 1660 struct te_link_subtlv_lclif_ipaddr *top;
1661 int i, n;
718e3744 1662
d62a17ae 1663 top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
1664 n = ntohs(tlvh->length) / sizeof(top->value[0]);
718e3744 1665
d62a17ae 1666 if (vty != NULL)
1667 vty_out(vty, " Local Interface IP Address(es): %d\n", n);
1668 else
1669 zlog_debug(" Local Interface IP Address(es): %d", n);
718e3744 1670
d62a17ae 1671 for (i = 0; i < n; i++) {
1672 if (vty != NULL)
96b663a3 1673 vty_out(vty, " #%d: %pI4\n", i, &top->value[i]);
d62a17ae 1674 else
96b663a3 1675 zlog_debug(" #%d: %pI4", i, &top->value[i]);
d62a17ae 1676 }
1677 return TLV_SIZE(tlvh);
718e3744 1678}
1679
d7c0a89a
QY
1680static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
1681 struct tlv_header *tlvh)
718e3744 1682{
d62a17ae 1683 struct te_link_subtlv_rmtif_ipaddr *top;
1684 int i, n;
718e3744 1685
d62a17ae 1686 top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
1687 n = ntohs(tlvh->length) / sizeof(top->value[0]);
1688 if (vty != NULL)
1689 vty_out(vty, " Remote Interface IP Address(es): %d\n", n);
1690 else
1691 zlog_debug(" Remote Interface IP Address(es): %d", n);
718e3744 1692
d62a17ae 1693 for (i = 0; i < n; i++) {
1694 if (vty != NULL)
96b663a3 1695 vty_out(vty, " #%d: %pI4\n", i, &top->value[i]);
d62a17ae 1696 else
96b663a3 1697 zlog_debug(" #%d: %pI4", i, &top->value[i]);
d62a17ae 1698 }
1699 return TLV_SIZE(tlvh);
718e3744 1700}
1701
d7c0a89a
QY
1702static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
1703 struct tlv_header *tlvh)
718e3744 1704{
d62a17ae 1705 struct te_link_subtlv_te_metric *top;
718e3744 1706
d62a17ae 1707 top = (struct te_link_subtlv_te_metric *)tlvh;
1708 if (vty != NULL)
1709 vty_out(vty, " Traffic Engineering Metric: %u\n",
d7c0a89a 1710 (uint32_t)ntohl(top->value));
d62a17ae 1711 else
1712 zlog_debug(" Traffic Engineering Metric: %u",
d7c0a89a 1713 (uint32_t)ntohl(top->value));
718e3744 1714
d62a17ae 1715 return TLV_SIZE(tlvh);
718e3744 1716}
1717
d7c0a89a
QY
1718static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
1719 struct tlv_header *tlvh)
718e3744 1720{
d62a17ae 1721 struct te_link_subtlv_max_bw *top;
1722 float fval;
718e3744 1723
d62a17ae 1724 top = (struct te_link_subtlv_max_bw *)tlvh;
1725 fval = ntohf(top->value);
718e3744 1726
d62a17ae 1727 if (vty != NULL)
1728 vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval);
1729 else
1730 zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval);
718e3744 1731
d62a17ae 1732 return TLV_SIZE(tlvh);
718e3744 1733}
1734
d7c0a89a
QY
1735static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
1736 struct tlv_header *tlvh)
718e3744 1737{
d62a17ae 1738 struct te_link_subtlv_max_rsv_bw *top;
1739 float fval;
718e3744 1740
d62a17ae 1741 top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
1742 fval = ntohf(top->value);
718e3744 1743
d62a17ae 1744 if (vty != NULL)
1745 vty_out(vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
1746 fval);
1747 else
1748 zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)",
1749 fval);
718e3744 1750
d62a17ae 1751 return TLV_SIZE(tlvh);
718e3744 1752}
1753
d7c0a89a
QY
1754static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
1755 struct tlv_header *tlvh)
718e3744 1756{
d62a17ae 1757 struct te_link_subtlv_unrsv_bw *top;
1758 float fval1, fval2;
1759 int i;
718e3744 1760
d62a17ae 1761 top = (struct te_link_subtlv_unrsv_bw *)tlvh;
1762 if (vty != NULL)
1763 vty_out(vty,
1764 " Unreserved Bandwidth per Class Type in Byte/s:\n");
1765 else
1766 zlog_debug(
1767 " Unreserved Bandwidth per Class Type in Byte/s:");
1768 for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
1769 fval1 = ntohf(top->value[i]);
1770 fval2 = ntohf(top->value[i + 1]);
16f1b9ee 1771
d62a17ae 1772 if (vty != NULL)
1773 vty_out(vty,
1774 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
1775 i, fval1, i + 1, fval2);
1776 else
1777 zlog_debug(
d6951e5e 1778 " [%d]: %g (Bytes/sec), [%d]: %g (Bytes/sec)",
d62a17ae 1779 i, fval1, i + 1, fval2);
1780 }
718e3744 1781
d62a17ae 1782 return TLV_SIZE(tlvh);
718e3744 1783}
1784
d7c0a89a
QY
1785static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
1786 struct tlv_header *tlvh)
718e3744 1787{
d62a17ae 1788 struct te_link_subtlv_rsc_clsclr *top;
718e3744 1789
d62a17ae 1790 top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
1791 if (vty != NULL)
1792 vty_out(vty, " Resource class/color: 0x%x\n",
d7c0a89a 1793 (uint32_t)ntohl(top->value));
d62a17ae 1794 else
1795 zlog_debug(" Resource Class/Color: 0x%x",
d7c0a89a 1796 (uint32_t)ntohl(top->value));
16f1b9ee 1797
d62a17ae 1798 return TLV_SIZE(tlvh);
16f1b9ee
OD
1799}
1800
d7c0a89a
QY
1801static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
1802 struct tlv_header *tlvh)
16f1b9ee 1803{
d62a17ae 1804 struct te_link_subtlv_lrrid *top;
16f1b9ee 1805
d62a17ae 1806 top = (struct te_link_subtlv_lrrid *)tlvh;
16f1b9ee 1807
d62a17ae 1808 if (vty != NULL) {
96b663a3
MS
1809 vty_out(vty, " Local TE Router ID: %pI4\n",
1810 &top->local);
1811 vty_out(vty, " Remote TE Router ID: %pI4\n",
1812 &top->remote);
d62a17ae 1813 } else {
96b663a3
MS
1814 zlog_debug(" Local TE Router ID: %pI4",
1815 &top->local);
1816 zlog_debug(" Remote TE Router ID: %pI4",
1817 &top->remote);
d62a17ae 1818 }
16f1b9ee 1819
d62a17ae 1820 return TLV_SIZE(tlvh);
16f1b9ee
OD
1821}
1822
d7c0a89a
QY
1823static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
1824 struct tlv_header *tlvh)
16f1b9ee 1825{
d62a17ae 1826 struct te_link_subtlv_llri *top;
16f1b9ee 1827
d62a17ae 1828 top = (struct te_link_subtlv_llri *)tlvh;
16f1b9ee 1829
d62a17ae 1830 if (vty != NULL) {
1831 vty_out(vty, " Link Local ID: %d\n",
d7c0a89a 1832 (uint32_t)ntohl(top->local));
d62a17ae 1833 vty_out(vty, " Link Remote ID: %d\n",
d7c0a89a 1834 (uint32_t)ntohl(top->remote));
d62a17ae 1835 } else {
1836 zlog_debug(" Link Local ID: %d",
d7c0a89a 1837 (uint32_t)ntohl(top->local));
d62a17ae 1838 zlog_debug(" Link Remote ID: %d",
d7c0a89a 1839 (uint32_t)ntohl(top->remote));
d62a17ae 1840 }
16f1b9ee 1841
d62a17ae 1842 return TLV_SIZE(tlvh);
16f1b9ee
OD
1843}
1844
d7c0a89a
QY
1845static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
1846 struct tlv_header *tlvh)
16f1b9ee 1847{
d62a17ae 1848 struct te_link_subtlv_rip *top;
16f1b9ee 1849
d62a17ae 1850 top = (struct te_link_subtlv_rip *)tlvh;
16f1b9ee 1851
d62a17ae 1852 if (vty != NULL)
96b663a3
MS
1853 vty_out(vty, " Inter-AS TE Remote ASBR IP address: %pI4\n",
1854 &top->value);
d62a17ae 1855 else
96b663a3
MS
1856 zlog_debug(" Inter-AS TE Remote ASBR IP address: %pI4",
1857 &top->value);
16f1b9ee 1858
d62a17ae 1859 return TLV_SIZE(tlvh);
16f1b9ee
OD
1860}
1861
d7c0a89a
QY
1862static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
1863 struct tlv_header *tlvh)
16f1b9ee 1864{
d62a17ae 1865 struct te_link_subtlv_ras *top;
16f1b9ee 1866
d62a17ae 1867 top = (struct te_link_subtlv_ras *)tlvh;
16f1b9ee 1868
d62a17ae 1869 if (vty != NULL)
1870 vty_out(vty, " Inter-AS TE Remote AS number: %u\n",
1871 ntohl(top->value));
1872 else
1873 zlog_debug(" Inter-AS TE Remote AS number: %u",
1874 ntohl(top->value));
16f1b9ee 1875
d62a17ae 1876 return TLV_SIZE(tlvh);
16f1b9ee
OD
1877}
1878
d7c0a89a
QY
1879static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
1880 struct tlv_header *tlvh)
16f1b9ee 1881{
d62a17ae 1882 struct te_link_subtlv_av_delay *top;
d7c0a89a
QY
1883 uint32_t delay;
1884 uint32_t anomalous;
16f1b9ee 1885
d62a17ae 1886 top = (struct te_link_subtlv_av_delay *)tlvh;
d7c0a89a
QY
1887 delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
1888 anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
16f1b9ee 1889
d62a17ae 1890 if (vty != NULL)
1891 vty_out(vty, " %s Average Link Delay: %d (micro-sec)\n",
1892 anomalous ? "Anomalous" : "Normal", delay);
1893 else
1894 zlog_debug(" %s Average Link Delay: %d (micro-sec)",
1895 anomalous ? "Anomalous" : "Normal", delay);
16f1b9ee 1896
d62a17ae 1897 return TLV_SIZE(tlvh);
16f1b9ee
OD
1898}
1899
d7c0a89a
QY
1900static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
1901 struct tlv_header *tlvh)
16f1b9ee 1902{
d62a17ae 1903 struct te_link_subtlv_mm_delay *top;
d7c0a89a
QY
1904 uint32_t low, high;
1905 uint32_t anomalous;
16f1b9ee 1906
d62a17ae 1907 top = (struct te_link_subtlv_mm_delay *)tlvh;
d7c0a89a
QY
1908 low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
1909 anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
1910 high = (uint32_t)ntohl(top->high);
16f1b9ee 1911
d62a17ae 1912 if (vty != NULL)
1913 vty_out(vty, " %s Min/Max Link Delay: %d/%d (micro-sec)\n",
1914 anomalous ? "Anomalous" : "Normal", low, high);
1915 else
1916 zlog_debug(" %s Min/Max Link Delay: %d/%d (micro-sec)",
1917 anomalous ? "Anomalous" : "Normal", low, high);
16f1b9ee 1918
d62a17ae 1919 return TLV_SIZE(tlvh);
16f1b9ee
OD
1920}
1921
d7c0a89a
QY
1922static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
1923 struct tlv_header *tlvh)
16f1b9ee 1924{
d62a17ae 1925 struct te_link_subtlv_delay_var *top;
d7c0a89a 1926 uint32_t jitter;
16f1b9ee 1927
d62a17ae 1928 top = (struct te_link_subtlv_delay_var *)tlvh;
d7c0a89a 1929 jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
16f1b9ee 1930
d62a17ae 1931 if (vty != NULL)
1932 vty_out(vty, " Delay Variation: %d (micro-sec)\n", jitter);
1933 else
1934 zlog_debug(" Delay Variation: %d (micro-sec)", jitter);
16f1b9ee 1935
d62a17ae 1936 return TLV_SIZE(tlvh);
16f1b9ee
OD
1937}
1938
d7c0a89a
QY
1939static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
1940 struct tlv_header *tlvh)
16f1b9ee 1941{
d62a17ae 1942 struct te_link_subtlv_pkt_loss *top;
d7c0a89a
QY
1943 uint32_t loss;
1944 uint32_t anomalous;
d62a17ae 1945 float fval;
16f1b9ee 1946
d62a17ae 1947 top = (struct te_link_subtlv_pkt_loss *)tlvh;
d7c0a89a 1948 loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
d62a17ae 1949 fval = (float)(loss * LOSS_PRECISION);
d7c0a89a 1950 anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
16f1b9ee 1951
d62a17ae 1952 if (vty != NULL)
1953 vty_out(vty, " %s Link Loss: %g (%%)\n",
1954 anomalous ? "Anomalous" : "Normal", fval);
1955 else
1956 zlog_debug(" %s Link Loss: %g (%%)",
1957 anomalous ? "Anomalous" : "Normal", fval);
16f1b9ee 1958
d62a17ae 1959 return TLV_SIZE(tlvh);
16f1b9ee
OD
1960}
1961
d7c0a89a
QY
1962static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
1963 struct tlv_header *tlvh)
16f1b9ee 1964{
d62a17ae 1965 struct te_link_subtlv_res_bw *top;
1966 float fval;
16f1b9ee 1967
d62a17ae 1968 top = (struct te_link_subtlv_res_bw *)tlvh;
1969 fval = ntohf(top->value);
16f1b9ee 1970
d62a17ae 1971 if (vty != NULL)
1972 vty_out(vty,
1973 " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
1974 fval);
1975 else
1976 zlog_debug(
1977 " Unidirectional Residual Bandwidth: %g (Bytes/sec)",
1978 fval);
1979
1980 return TLV_SIZE(tlvh);
1981}
1982
d7c0a89a
QY
1983static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
1984 struct tlv_header *tlvh)
d62a17ae 1985{
1986 struct te_link_subtlv_ava_bw *top;
1987 float fval;
1988
1989 top = (struct te_link_subtlv_ava_bw *)tlvh;
1990 fval = ntohf(top->value);
1991
1992 if (vty != NULL)
1993 vty_out(vty,
1994 " Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
1995 fval);
1996 else
1997 zlog_debug(
1998 " Unidirectional Available Bandwidth: %g (Bytes/sec)",
1999 fval);
2000
2001 return TLV_SIZE(tlvh);
2002}
2003
d7c0a89a
QY
2004static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
2005 struct tlv_header *tlvh)
d62a17ae 2006{
2007 struct te_link_subtlv_use_bw *top;
2008 float fval;
2009
2010 top = (struct te_link_subtlv_use_bw *)tlvh;
2011 fval = ntohf(top->value);
2012
2013 if (vty != NULL)
2014 vty_out(vty,
2015 " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
2016 fval);
2017 else
2018 zlog_debug(
2019 " Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
2020 fval);
2021
2022 return TLV_SIZE(tlvh);
2023}
2024
d7c0a89a 2025static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
d62a17ae 2026{
2027 if (vty != NULL)
2028 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
2029 ntohs(tlvh->type), ntohs(tlvh->length));
2030 else
2031 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
2032 ntohs(tlvh->type), ntohs(tlvh->length));
2033
2034 return TLV_SIZE(tlvh);
2035}
2036
d7c0a89a
QY
2037static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
2038 struct tlv_header *tlvh0,
2039 uint16_t subtotal, uint16_t total)
d62a17ae 2040{
9df48e81 2041 struct tlv_header *tlvh;
d7c0a89a 2042 uint16_t sum = subtotal;
d62a17ae 2043
2044 for (tlvh = tlvh0; sum < total;
9df48e81 2045 tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 2046 switch (ntohs(tlvh->type)) {
2047 case TE_LINK_SUBTLV_LINK_TYPE:
2048 sum += show_vty_link_subtlv_link_type(vty, tlvh);
2049 break;
2050 case TE_LINK_SUBTLV_LINK_ID:
2051 sum += show_vty_link_subtlv_link_id(vty, tlvh);
2052 break;
2053 case TE_LINK_SUBTLV_LCLIF_IPADDR:
2054 sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh);
2055 break;
2056 case TE_LINK_SUBTLV_RMTIF_IPADDR:
2057 sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh);
2058 break;
2059 case TE_LINK_SUBTLV_TE_METRIC:
2060 sum += show_vty_link_subtlv_te_metric(vty, tlvh);
2061 break;
2062 case TE_LINK_SUBTLV_MAX_BW:
2063 sum += show_vty_link_subtlv_max_bw(vty, tlvh);
2064 break;
2065 case TE_LINK_SUBTLV_MAX_RSV_BW:
2066 sum += show_vty_link_subtlv_max_rsv_bw(vty, tlvh);
2067 break;
2068 case TE_LINK_SUBTLV_UNRSV_BW:
2069 sum += show_vty_link_subtlv_unrsv_bw(vty, tlvh);
2070 break;
2071 case TE_LINK_SUBTLV_RSC_CLSCLR:
2072 sum += show_vty_link_subtlv_rsc_clsclr(vty, tlvh);
2073 break;
2074 case TE_LINK_SUBTLV_LRRID:
2075 sum += show_vty_link_subtlv_lrrid(vty, tlvh);
2076 break;
2077 case TE_LINK_SUBTLV_LLRI:
2078 sum += show_vty_link_subtlv_llri(vty, tlvh);
2079 break;
2080 case TE_LINK_SUBTLV_RIP:
2081 sum += show_vty_link_subtlv_rip(vty, tlvh);
2082 break;
2083 case TE_LINK_SUBTLV_RAS:
2084 sum += show_vty_link_subtlv_ras(vty, tlvh);
2085 break;
2086 case TE_LINK_SUBTLV_AV_DELAY:
2087 sum += show_vty_link_subtlv_av_delay(vty, tlvh);
2088 break;
2089 case TE_LINK_SUBTLV_MM_DELAY:
2090 sum += show_vty_link_subtlv_mm_delay(vty, tlvh);
2091 break;
2092 case TE_LINK_SUBTLV_DELAY_VAR:
2093 sum += show_vty_link_subtlv_delay_var(vty, tlvh);
2094 break;
2095 case TE_LINK_SUBTLV_PKT_LOSS:
2096 sum += show_vty_link_subtlv_pkt_loss(vty, tlvh);
2097 break;
2098 case TE_LINK_SUBTLV_RES_BW:
2099 sum += show_vty_link_subtlv_res_bw(vty, tlvh);
2100 break;
2101 case TE_LINK_SUBTLV_AVA_BW:
2102 sum += show_vty_link_subtlv_ava_bw(vty, tlvh);
2103 break;
2104 case TE_LINK_SUBTLV_USE_BW:
2105 sum += show_vty_link_subtlv_use_bw(vty, tlvh);
2106 break;
2107 default:
2108 sum += show_vty_unknown_tlv(vty, tlvh);
2109 break;
2110 }
2111 }
2112 return sum;
2113}
2114
2115static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
2116{
c4efd0f4 2117 struct lsa_header *lsah = lsa->data;
ead99d5f 2118 struct tlv_header *tlvh, *next;
d7c0a89a
QY
2119 uint16_t sum, total;
2120 uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
2121 uint16_t subtotal, uint16_t total) = NULL;
d62a17ae 2122
2123 sum = 0;
2124 total = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
2125
2126 for (tlvh = TLV_HDR_TOP(lsah); sum < total;
2127 tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
2128 if (subfunc != NULL) {
2129 sum = (*subfunc)(vty, tlvh, sum, total);
ead99d5f 2130 next = (struct tlv_header *)((char *)tlvh + sum);
d62a17ae 2131 subfunc = NULL;
2132 continue;
2133 }
2134
2135 next = NULL;
2136 switch (ntohs(tlvh->type)) {
2137 case TE_TLV_ROUTER_ADDR:
2138 sum += show_vty_router_addr(vty, tlvh);
2139 break;
2140 case TE_TLV_LINK:
2141 sum += show_vty_link_header(vty, tlvh);
2142 subfunc = ospf_mpls_te_show_link_subtlv;
5d0df50f 2143 next = TLV_DATA(tlvh);
d62a17ae 2144 break;
2145 default:
2146 sum += show_vty_unknown_tlv(vty, tlvh);
2147 break;
2148 }
2149 }
2150 return;
2151}
2152
2153static void ospf_mpls_te_config_write_router(struct vty *vty)
2154{
2155
32ab5cf4 2156 if (OspfMplsTE.enabled) {
d62a17ae 2157 vty_out(vty, " mpls-te on\n");
96b663a3
MS
2158 vty_out(vty, " mpls-te router-address %pI4\n",
2159 &OspfMplsTE.router_addr.value);
d62a17ae 2160 }
2161
2162 if (OspfMplsTE.inter_as == AS)
2163 vty_out(vty, " mpls-te inter-as as\n");
2164 if (OspfMplsTE.inter_as == Area)
96b663a3
MS
2165 vty_out(vty, " mpls-te inter-as area %pI4 \n",
2166 &OspfMplsTE.interas_areaid);
d62a17ae 2167
2168 return;
718e3744 2169}
2170
2171/*------------------------------------------------------------------------*
2172 * Followings are vty command functions.
2173 *------------------------------------------------------------------------*/
2174
16f1b9ee
OD
2175DEFUN (ospf_mpls_te_on,
2176 ospf_mpls_te_on_cmd,
2177 "mpls-te on",
2178 MPLS_TE_STR
718e3744 2179 "Enable the MPLS-TE functionality\n")
2180{
a3d826f0 2181 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 2182 struct listnode *node;
2183 struct mpls_te_link *lp;
7c8ff89e 2184
32ab5cf4 2185 if (OspfMplsTE.enabled)
d62a17ae 2186 return CMD_SUCCESS;
718e3744 2187
d62a17ae 2188 if (IS_DEBUG_OSPF_EVENT)
2189 zlog_debug("MPLS-TE: OFF -> ON");
718e3744 2190
32ab5cf4 2191 OspfMplsTE.enabled = true;
718e3744 2192
d62a17ae 2193 /* Reoriginate RFC3630 & RFC6827 Links */
2194 ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
2195 REORIGINATE_THIS_LSA);
718e3744 2196
d62a17ae 2197 /* Reoriginate LSA if INTER-AS is always on */
ead99d5f 2198 if (OspfMplsTE.inter_as != Off) {
d62a17ae 2199 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) {
2200 if (IS_INTER_AS(lp->type)) {
2201 ospf_mpls_te_lsa_schedule(lp,
2202 REORIGINATE_THIS_LSA);
2203 }
2204 }
2205 }
718e3744 2206
d62a17ae 2207 return CMD_SUCCESS;
718e3744 2208}
2209
16f1b9ee
OD
2210DEFUN (no_ospf_mpls_te,
2211 no_ospf_mpls_te_cmd,
3a2d747c 2212 "no mpls-te [on]",
718e3744 2213 NO_STR
3a2d747c 2214 MPLS_TE_STR
718e3744 2215 "Disable the MPLS-TE functionality\n")
2216{
a3d826f0 2217 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 2218 struct listnode *node, *nnode;
2219 struct mpls_te_link *lp;
718e3744 2220
32ab5cf4 2221 if (!OspfMplsTE.enabled)
d62a17ae 2222 return CMD_SUCCESS;
718e3744 2223
d62a17ae 2224 if (IS_DEBUG_OSPF_EVENT)
2225 zlog_debug("MPLS-TE: ON -> OFF");
718e3744 2226
32ab5cf4 2227 OspfMplsTE.enabled = false;
718e3744 2228
d62a17ae 2229 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
32ab5cf4
OD
2230 if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
2231 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
718e3744 2232
d424f8d8
CG
2233 /*
2234 * This resets the OspfMplsTE.inter_as to its initial state.
2235 * This is to avoid having an inter-as value different from
2236 * Off when mpls-te gets restarted (after being removed)
2237 */
2238 if (OspfMplsTE.inter_as != Off) {
2239 /* Deregister the Callbacks for Inter-AS support */
2240 ospf_mpls_te_unregister();
2241 OspfMplsTE.inter_as = Off;
2242 }
2243
d62a17ae 2244 return CMD_SUCCESS;
718e3744 2245}
2246
813d4307 2247
16f1b9ee
OD
2248DEFUN (ospf_mpls_te_router_addr,
2249 ospf_mpls_te_router_addr_cmd,
718e3744 2250 "mpls-te router-address A.B.C.D",
16f1b9ee 2251 MPLS_TE_STR
718e3744 2252 "Stable IP address of the advertising router\n"
2253 "MPLS-TE router address in IPv4 address format\n")
2254{
a3d826f0 2255 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
d62a17ae 2256 int idx_ipv4 = 2;
2257 struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
2258 struct in_addr value;
2259
2260 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
2261 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
2262 return CMD_WARNING;
2263 }
2264
2265 if (ntohs(ra->header.type) == 0
2266 || ntohl(ra->value.s_addr) != ntohl(value.s_addr)) {
2267 struct listnode *node, *nnode;
2268 struct mpls_te_link *lp;
2269 int need_to_reoriginate = 0;
2270
2271 set_mpls_te_router_addr(value);
2272
32ab5cf4 2273 if (!OspfMplsTE.enabled)
ead99d5f 2274 return CMD_SUCCESS;
d62a17ae 2275
2276 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2277 if ((lp->area == NULL) || IS_FLOOD_AS(lp->type))
2278 continue;
2279
2280 if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) {
2281 need_to_reoriginate = 1;
2282 break;
2283 }
2284 }
2285
2286 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) {
2287 if ((lp->area == NULL) || IS_FLOOD_AS(lp->type))
2288 continue;
2289
2290 if (need_to_reoriginate)
2291 SET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH);
2292 else
2293 ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA);
2294 }
2295
2296 if (need_to_reoriginate)
2297 ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule,
2298 REORIGINATE_THIS_LSA);
2299 }
ead99d5f 2300
d62a17ae 2301 return CMD_SUCCESS;
2302}
2303
2304static int set_inter_as_mode(struct vty *vty, const char *mode_name,
2305 const char *area_id)
2306{
2307 enum inter_as_mode mode;
2308 struct listnode *node;
2309 struct mpls_te_link *lp;
2310 int format;
2311
32ab5cf4 2312 if (OspfMplsTE.enabled) {
d62a17ae 2313
2314 /* Read and Check inter_as mode */
2315 if (strcmp(mode_name, "as") == 0)
2316 mode = AS;
2317 else if (strcmp(mode_name, "area") == 0) {
2318 mode = Area;
2319 VTY_GET_OSPF_AREA_ID(OspfMplsTE.interas_areaid, format,
2320 area_id);
2321 } else {
2322 vty_out(vty,
2323 "Unknown mode. Please choose between as or area\n");
2324 return CMD_WARNING;
2325 }
2326
2327 if (IS_DEBUG_OSPF_EVENT)
2328 zlog_debug(
2329 "MPLS-TE: Inter-AS enable with %s flooding support",
2330 mode2text[mode]);
2331
2332 /* Register new callbacks regarding the flooding scope (AS or
2333 * Area) */
2334 if (ospf_mpls_te_register(mode) < 0) {
2335 vty_out(vty,
2336 "Internal error: Unable to register Inter-AS functions\n");
2337 return CMD_WARNING;
2338 }
2339
2340 /* Enable mode and re-originate LSA if needed */
ead99d5f 2341 if ((OspfMplsTE.inter_as == Off)
d62a17ae 2342 && (mode != OspfMplsTE.inter_as)) {
2343 OspfMplsTE.inter_as = mode;
2344 /* Re-originate all InterAS-TEv2 LSA */
2345 for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node,
2346 lp)) {
2347 if (IS_INTER_AS(lp->type)) {
2348 if (mode == AS)
2349 lp->type |= FLOOD_AS;
2350 else
2351 lp->type |= FLOOD_AREA;
2352 ospf_mpls_te_lsa_schedule(
2353 lp, REORIGINATE_THIS_LSA);
2354 }
2355 }
2356 } else {
2357 vty_out(vty,
2358 "Please change Inter-AS support to disable first before going to mode %s\n",
2359 mode2text[mode]);
2360 return CMD_WARNING;
2361 }
2362 } else {
2363 vty_out(vty, "mpls-te has not been turned on\n");
2364 return CMD_WARNING;
2365 }
2366 return CMD_SUCCESS;
718e3744 2367}
2368
718e3744 2369
16f1b9ee
OD
2370DEFUN (ospf_mpls_te_inter_as_as,
2371 ospf_mpls_te_inter_as_cmd,
2372 "mpls-te inter-as as",
2373 MPLS_TE_STR
2374 "Configure MPLS-TE Inter-AS support\n"
2375 "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n")
2376{
d62a17ae 2377 return set_inter_as_mode(vty, "as", "");
718e3744 2378}
2379
16f1b9ee
OD
2380DEFUN (ospf_mpls_te_inter_as_area,
2381 ospf_mpls_te_inter_as_area_cmd,
6147e2c6 2382 "mpls-te inter-as area <A.B.C.D|(0-4294967295)>",
16f1b9ee
OD
2383 MPLS_TE_STR
2384 "Configure MPLS-TE Inter-AS support\n"
2385 "AREA native mode self originate INTER_AS LSA with Type 10 (area flooding scope)\n"
2386 "OSPF area ID in IP format\n"
2387 "OSPF area ID as decimal value\n")
718e3744 2388{
d62a17ae 2389 int idx_ipv4_number = 3;
2390 return set_inter_as_mode(vty, "area", argv[idx_ipv4_number]->arg);
718e3744 2391}
2392
16f1b9ee
OD
2393DEFUN (no_ospf_mpls_te_inter_as,
2394 no_ospf_mpls_te_inter_as_cmd,
2395 "no mpls-te inter-as",
2396 NO_STR
2397 MPLS_TE_STR
2398 "Disable MPLS-TE Inter-AS support\n")
718e3744 2399{
16f1b9ee 2400
d62a17ae 2401 struct listnode *node, *nnode;
2402 struct mpls_te_link *lp;
718e3744 2403
d62a17ae 2404 if (IS_DEBUG_OSPF_EVENT)
2405 zlog_debug("MPLS-TE: Inter-AS support OFF");
718e3744 2406
996c9314 2407 if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) {
d62a17ae 2408 /* Flush all Inter-AS LSA */
2409 for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp))
2410 if (IS_INTER_AS(lp->type)
2411 && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
2412 ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
718e3744 2413
e790de41
DT
2414 /* Deregister the Callbacks for Inter-AS support */
2415 ospf_mpls_te_unregister();
2416 OspfMplsTE.inter_as = Off;
2417 }
bcf4475e 2418
d62a17ae 2419 return CMD_SUCCESS;
718e3744 2420}
2421
16f1b9ee
OD
2422DEFUN (show_ip_ospf_mpls_te_router,
2423 show_ip_ospf_mpls_te_router_cmd,
2424 "show ip ospf mpls-te router",
718e3744 2425 SHOW_STR
16f1b9ee
OD
2426 IP_STR
2427 OSPF_STR
718e3744 2428 "MPLS-TE information\n"
16f1b9ee 2429 "MPLS-TE Router parameters\n")
718e3744 2430{
32ab5cf4 2431 if (OspfMplsTE.enabled) {
d62a17ae 2432 vty_out(vty, "--- MPLS-TE router parameters ---\n");
2433
2434 if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
2435 show_vty_router_addr(vty,
2436 &OspfMplsTE.router_addr.header);
0af35d90 2437 else
d62a17ae 2438 vty_out(vty, " N/A\n");
2439 }
2440 return CMD_SUCCESS;
2441}
2442
2443static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
2444{
2445 struct mpls_te_link *lp;
2446
996c9314
LB
2447 if ((OspfMplsTE.enabled) && HAS_LINK_PARAMS(ifp) && !if_is_loopback(ifp)
2448 && if_is_up(ifp)
d62a17ae 2449 && ((lp = lookup_linkparams_by_ifp(ifp)) != NULL)) {
2450 /* Continue only if interface is not passive or support Inter-AS
2451 * TEv2 */
2452 if (!(ospf_oi_count(ifp) > 0)) {
2453 if (IS_INTER_AS(lp->type)) {
2454 vty_out(vty,
2455 "-- Inter-AS TEv2 link parameters for %s --\n",
2456 ifp->name);
2457 } else {
2458 /* MPLS-TE is not activate on this interface */
2459 /* or this interface is passive and Inter-AS
2460 * TEv2 is not activate */
2461 vty_out(vty,
2462 " %s: MPLS-TE is disabled on this interface\n",
2463 ifp->name);
2464 return;
2465 }
2466 } else {
2467 vty_out(vty, "-- MPLS-TE link parameters for %s --\n",
2468 ifp->name);
2469 }
2470
2471 if (TLV_TYPE(lp->link_type) != 0)
2472 show_vty_link_subtlv_link_type(vty,
2473 &lp->link_type.header);
2474 if (TLV_TYPE(lp->link_id) != 0)
2475 show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
2476 if (TLV_TYPE(lp->lclif_ipaddr) != 0)
2477 show_vty_link_subtlv_lclif_ipaddr(
2478 vty, &lp->lclif_ipaddr.header);
2479 if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
2480 show_vty_link_subtlv_rmtif_ipaddr(
2481 vty, &lp->rmtif_ipaddr.header);
2482 if (TLV_TYPE(lp->rip) != 0)
2483 show_vty_link_subtlv_rip(vty, &lp->rip.header);
2484 if (TLV_TYPE(lp->ras) != 0)
2485 show_vty_link_subtlv_ras(vty, &lp->ras.header);
2486 if (TLV_TYPE(lp->te_metric) != 0)
2487 show_vty_link_subtlv_te_metric(vty,
2488 &lp->te_metric.header);
2489 if (TLV_TYPE(lp->max_bw) != 0)
2490 show_vty_link_subtlv_max_bw(vty, &lp->max_bw.header);
2491 if (TLV_TYPE(lp->max_rsv_bw) != 0)
2492 show_vty_link_subtlv_max_rsv_bw(vty,
2493 &lp->max_rsv_bw.header);
2494 if (TLV_TYPE(lp->unrsv_bw) != 0)
2495 show_vty_link_subtlv_unrsv_bw(vty,
2496 &lp->unrsv_bw.header);
2497 if (TLV_TYPE(lp->rsc_clsclr) != 0)
2498 show_vty_link_subtlv_rsc_clsclr(vty,
2499 &lp->rsc_clsclr.header);
2500 if (TLV_TYPE(lp->av_delay) != 0)
2501 show_vty_link_subtlv_av_delay(vty,
2502 &lp->av_delay.header);
2503 if (TLV_TYPE(lp->mm_delay) != 0)
2504 show_vty_link_subtlv_mm_delay(vty,
2505 &lp->mm_delay.header);
2506 if (TLV_TYPE(lp->delay_var) != 0)
2507 show_vty_link_subtlv_delay_var(vty,
2508 &lp->delay_var.header);
2509 if (TLV_TYPE(lp->pkt_loss) != 0)
2510 show_vty_link_subtlv_pkt_loss(vty,
2511 &lp->pkt_loss.header);
2512 if (TLV_TYPE(lp->res_bw) != 0)
2513 show_vty_link_subtlv_res_bw(vty, &lp->res_bw.header);
2514 if (TLV_TYPE(lp->ava_bw) != 0)
2515 show_vty_link_subtlv_ava_bw(vty, &lp->ava_bw.header);
2516 if (TLV_TYPE(lp->use_bw) != 0)
2517 show_vty_link_subtlv_use_bw(vty, &lp->use_bw.header);
2518 vty_out(vty, "---------------\n\n");
2519 } else {
2520 vty_out(vty, " %s: MPLS-TE is disabled on this interface\n",
2521 ifp->name);
2522 }
2523
2524 return;
718e3744 2525}
2526
16f1b9ee
OD
2527DEFUN (show_ip_ospf_mpls_te_link,
2528 show_ip_ospf_mpls_te_link_cmd,
b5a8894d 2529 "show ip ospf [vrf <NAME|all>] mpls-te interface [INTERFACE]",
718e3744 2530 SHOW_STR
16f1b9ee
OD
2531 IP_STR
2532 OSPF_STR
b5a8894d
CS
2533 VRF_CMD_HELP_STR
2534 "All VRFs\n"
718e3744 2535 "MPLS-TE information\n"
2536 "Interface information\n"
2537 "Interface name\n")
2538{
f4e14fdb 2539 struct vrf *vrf;
03ed9f02
PG
2540 int idx_interface = 0;
2541 struct interface *ifp = NULL;
f4e14fdb 2542 struct listnode *node;
b5a8894d 2543 char *vrf_name = NULL;
8da59e56 2544 bool all_vrf = false;
b5a8894d
CS
2545 int inst = 0;
2546 int idx_vrf = 0;
2547 struct ospf *ospf = NULL;
2548
2549 if (argv_find(argv, argc, "vrf", &idx_vrf)) {
2550 vrf_name = argv[idx_vrf + 1]->arg;
2551 all_vrf = strmatch(vrf_name, "all");
2552 }
03ed9f02 2553 argv_find(argv, argc, "INTERFACE", &idx_interface);
b5a8894d
CS
2554 /* vrf input is provided could be all or specific vrf*/
2555 if (vrf_name) {
2556 if (all_vrf) {
f4e14fdb 2557 for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
b5a8894d
CS
2558 if (!ospf->oi_running)
2559 continue;
f4e14fdb 2560 vrf = vrf_lookup_by_id(ospf->vrf_id);
451fda4f 2561 FOR_ALL_INTERFACES (vrf, ifp)
b5a8894d
CS
2562 show_mpls_te_link_sub(vty, ifp);
2563 }
2564 return CMD_SUCCESS;
2565 }
996c9314 2566 ospf = ospf_lookup_by_inst_name(inst, vrf_name);
03ed9f02
PG
2567 } else
2568 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
2569 if (ospf == NULL || !ospf->oi_running)
b5a8894d 2570 return CMD_SUCCESS;
03ed9f02
PG
2571
2572 vrf = vrf_lookup_by_id(ospf->vrf_id);
2573 if (!vrf)
2574 return CMD_SUCCESS;
2575 if (idx_interface) {
2576 ifp = if_lookup_by_name(
2577 argv[idx_interface]->arg,
a36898e7 2578 ospf->vrf_id);
03ed9f02
PG
2579 if (ifp == NULL) {
2580 vty_out(vty, "No such interface name in vrf %s\n",
2581 vrf->name);
2582 return CMD_SUCCESS;
43b8d1d8 2583 }
d62a17ae 2584 }
03ed9f02
PG
2585 if (!ifp) {
2586 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 2587 show_mpls_te_link_sub(vty, ifp);
03ed9f02 2588 return CMD_SUCCESS;
d62a17ae 2589 }
2590
03ed9f02 2591 show_mpls_te_link_sub(vty, ifp);
d62a17ae 2592 return CMD_SUCCESS;
2593}
2594
2595static void ospf_mpls_te_register_vty(void)
2596{
2597 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd);
2598 install_element(VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd);
2599
2600 install_element(OSPF_NODE, &ospf_mpls_te_on_cmd);
2601 install_element(OSPF_NODE, &no_ospf_mpls_te_cmd);
2602 install_element(OSPF_NODE, &ospf_mpls_te_router_addr_cmd);
2603 install_element(OSPF_NODE, &ospf_mpls_te_inter_as_cmd);
2604 install_element(OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd);
2605 install_element(OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd);
2606
2607 return;
718e3744 2608}