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