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