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