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