Convertion to a ECMP capable infrastructure compiles (no testing
[mpls-ldp-portable.git] / ldp / ldp_attr.c
blob2fa4b1e42045df261b35d21a890c7b897e04f268
2 /*
3 * Copyright (C) James R. Leu 2000
4 * jleu@mindspring.com
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
8 */
10 #include "ldp_struct.h"
11 #include "ldp_label_mapping.h"
12 #include "ldp_attr.h"
13 #include "ldp_if.h"
14 #include "ldp_addr.h"
15 #include "ldp_fec.h"
16 #include "ldp_global.h"
17 #include "ldp_inlabel.h"
18 #include "ldp_outlabel.h"
19 #include "ldp_session.h"
20 #include "mpls_refcnt.h"
21 #include "mpls_mm_impl.h"
22 #include "mpls_tree_impl.h"
23 #include "mpls_trace_impl.h"
25 #if MPLS_USE_LSR
26 #include "lsr_cfg.h"
27 #else
28 #include "mpls_mpls_impl.h"
29 #endif
31 static ldp_fec *_ldp_attr_get_fec2(ldp_global * g, mpls_fec * f, mpls_bool flag);
32 static ldp_fec *_ldp_attr_get_fec(ldp_global * g, ldp_attr * a, mpls_bool flag);
33 static ldp_fs *_ldp_fec_add_fs_ds(ldp_fec * fec, ldp_session * s);
34 static ldp_fs *_ldp_fec_add_fs_us(ldp_fec * fec, ldp_session * s);
35 static ldp_fs *_ldp_fec_find_fs_us(ldp_fec * fec, ldp_session * s,
36 mpls_bool flag);
37 static ldp_fs *_ldp_fec_find_fs_ds(ldp_fec * fec, ldp_session * s,
38 mpls_bool flag);
39 static void _ldp_fec_del_fs_us(ldp_fec * fec, ldp_fs * fs);
40 static void _ldp_fec_del_fs_ds(ldp_fec * fec, ldp_fs * fs);
41 static ldp_fs *_ldp_fs_create(ldp_session * s);
42 static void _ldp_fs_delete(ldp_fs * fs);
43 static ldp_attr *_ldp_fs_find_attr(ldp_fs * fs, ldp_attr * a);
44 static mpls_return_enum _ldp_fs_add_attr(ldp_fs * fs, ldp_attr * a);
45 static mpls_bool _ldp_fs_del_attr(ldp_fs * fs, ldp_attr * a);
46 static uint32_t _ldp_attr_get_next_index();
48 static uint32_t _ldp_attr_next_index = 1;
50 int ldp_attr_num_us2ds(ldp_attr * ds)
52 ldp_attr *attr = NULL;
53 int count = 0;
55 attr = MPLS_LIST_HEAD(&ds->us_attr_root);
56 while (attr) {
57 count++;
58 attr = MPLS_LIST_NEXT(&ds->us_attr_root, attr, _ds_attr);
60 return count;
63 mpls_bool ldp_attr_us_partof_ds(ldp_attr * us, ldp_attr * ds)
65 if (us->ds_attr == ds) {
66 return MPLS_BOOL_TRUE;
68 return MPLS_BOOL_FALSE;
71 void ldp_attr_del_us2ds(ldp_attr * us, ldp_attr * ds)
73 if (!us || !ds) {
74 return;
76 if (ldp_attr_us_partof_ds(us, ds) == MPLS_BOOL_TRUE) {
77 us->ds_attr = NULL;
78 MPLS_REFCNT_RELEASE(ds, ldp_attr_delete);
79 MPLS_LIST_REMOVE(&ds->us_attr_root, us, _ds_attr);
80 MPLS_REFCNT_RELEASE(us, ldp_attr_delete);
81 } else {
82 MPLS_ASSERT(0);
86 void ldp_attr_add_fec(ldp_attr *a, ldp_fec *fec) {
87 MPLS_ASSERT(a && fec);
88 MPLS_REFCNT_HOLD(fec);
89 a->fec = fec;
92 void ldp_attr_del_fec(ldp_attr *a) {
93 MPLS_ASSERT(a);
94 if (a->fec) {
95 MPLS_REFCNT_RELEASE(a->fec, ldp_fec_delete);
96 a->fec = NULL;
100 void ldp_attr_add_us2ds(ldp_attr * us, ldp_attr * ds)
103 if (!us || !ds) {
104 return;
106 if (ldp_attr_us_partof_ds(us, ds) == MPLS_BOOL_TRUE) {
107 return;
109 MPLS_REFCNT_HOLD(us);
110 MPLS_LIST_ADD_TAIL(&ds->us_attr_root, us, _ds_attr, ldp_attr);
111 MPLS_REFCNT_HOLD(ds);
112 us->ds_attr = ds;
115 void ldp_attr_action_callback(mpls_timer_handle timer, void *extra,
116 mpls_cfg_handle g)
120 ldp_attr *ldp_attr_find_downstream_state_any2(ldp_global * g, ldp_fec * f,
121 ldp_lsp_state state)
123 ldp_attr *attr = NULL;
124 ldp_fs *fs = NULL;
126 fs = MPLS_LIST_HEAD(&f->fs_root_ds);
127 while (fs != NULL) {
128 attr = MPLS_LIST_HEAD(&fs->attr_root);
129 while (attr != NULL) {
130 if (attr->state == state) {
131 return attr;
133 attr = MPLS_LIST_NEXT(&fs->attr_root, attr, _fs);
135 fs = MPLS_LIST_NEXT(&f->fs_root_ds, fs, _fec);
137 return NULL;
140 ldp_attr *ldp_attr_find_downstream_state_any(ldp_global * g, mpls_fec * f,
141 ldp_lsp_state state)
143 ldp_fec *fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE);
145 if (!fnode) {
146 return NULL;
149 return ldp_attr_find_downstream_state_any2(g, fnode, state);
152 ldp_attr *ldp_attr_find_upstream_state_any2(ldp_global * g, ldp_fec * f,
153 ldp_lsp_state state)
155 ldp_attr *attr = NULL;
156 ldp_fs *fs = NULL;
158 fs = MPLS_LIST_HEAD(&f->fs_root_us);
159 while (fs != NULL) {
160 attr = MPLS_LIST_HEAD(&fs->attr_root);
161 while (attr != NULL) {
162 if (attr->state == state) {
163 return attr;
165 attr = MPLS_LIST_NEXT(&fs->attr_root, attr, _fs);
167 fs = MPLS_LIST_NEXT(&f->fs_root_us, fs, _fec);
169 return NULL;
172 ldp_attr *ldp_attr_find_upstream_state_any(ldp_global * g, mpls_fec * f,
173 ldp_lsp_state state)
175 ldp_fec *fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE);
177 if (!fnode) {
178 return NULL;
181 return ldp_attr_find_upstream_state_any2(g, fnode, state);
184 static ldp_attr *_ldp_attr_find_downstream_state(ldp_attr_list *ds_list,
185 ldp_lsp_state state)
187 if (ds_list != NULL) {
188 ldp_attr *ds_attr = MPLS_LIST_HEAD(ds_list);
190 while (ds_attr != NULL) {
191 if (ds_attr->state == state) {
192 return ds_attr;
194 ds_attr = MPLS_LIST_NEXT(ds_list, ds_attr, _fs);
197 return NULL;
200 ldp_attr *ldp_attr_find_downstream_state2(ldp_global * g, ldp_session * s,
201 ldp_fec * f, ldp_lsp_state state)
203 ldp_attr_list *ds_list = ldp_attr_find_downstream_all2(g, s, f);
204 return _ldp_attr_find_downstream_state(ds_list, state);
207 ldp_attr *ldp_attr_find_downstream_state(ldp_global * g, ldp_session * s,
208 mpls_fec * f, ldp_lsp_state state)
210 ldp_attr_list *ds_list = ldp_attr_find_downstream_all(g, s, f);
211 return _ldp_attr_find_downstream_state(ds_list, state);
214 static ldp_attr *_ldp_attr_find_upstream_state(ldp_attr_list *us_list,
215 ldp_lsp_state state)
217 if (us_list != NULL) {
218 ldp_attr *us_attr = MPLS_LIST_HEAD(us_list);
220 while (us_attr != NULL) {
221 if (us_attr->state == state) {
222 return us_attr;
224 us_attr = MPLS_LIST_NEXT(us_list, us_attr, _fs);
227 return NULL;
230 ldp_attr *ldp_attr_find_upstream_state2(ldp_global * g, ldp_session * s,
231 ldp_fec * f, ldp_lsp_state state)
233 ldp_attr_list *us_list = ldp_attr_find_upstream_all2(g, s, f);
234 return _ldp_attr_find_upstream_state(us_list, state);
237 ldp_attr *ldp_attr_find_upstream_state(ldp_global * g, ldp_session * s,
238 mpls_fec * f, ldp_lsp_state state)
240 ldp_attr_list *us_list = ldp_attr_find_upstream_all(g, s, f);
241 return _ldp_attr_find_upstream_state(us_list, state);
244 void ldp_attr_remove_complete(ldp_global * g, ldp_attr * attr,
245 mpls_bool complete)
247 ldp_session *session = attr->session;
248 ldp_outlabel *out = NULL;
249 ldp_inlabel *in = NULL;
250 ldp_attr *us_temp = NULL;
251 mpls_fec fec;
252 int i;
254 switch (attr->state) {
255 case LDP_LSP_STATE_MAP_RECV:
256 if (attr->ingress == MPLS_BOOL_TRUE) {
257 out = attr->outlabel;
258 MPLS_ASSERT(out != NULL);
259 while ((in = MPLS_LIST_HEAD(&out->inlabel_root)) != NULL) {
260 ldp_inlabel_del_outlabel(g, in);
263 if (out->merge_count > 0) {
264 for (i = 0; i < attr->fecTlv.numberFecElements; i++) {
265 fec_tlv2mpls_fec(&attr->fecTlv, i, &fec);
266 out->merge_count--;
267 #if MPLS_USE_LSR
269 lsr_ftn ftn;
270 memcpy(&ftn.fec, &fec, sizeof(mpls_fec));
271 ftn.outsegment_index = out->info.handle;
272 lsr_cfg_ftn_set2(g->lsr_handle, &ftn, LSR_CFG_DEL);
274 #else
275 mpls_mpls_fec2out_del(g->mpls_handle, &fec, &out->info);
276 #endif
279 MPLS_ASSERT(out->merge_count == 0);
280 ldp_attr_del_outlabel(attr);
281 ldp_session_del_outlabel(session, out);
282 _ldp_global_del_outlabel(g, out);
284 while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
285 ldp_attr_del_us2ds(us_temp, attr);
287 ldp_attr_delete_downstream(g, session, attr);
288 break;
289 case LDP_LSP_STATE_MAP_SENT:
290 in = attr->inlabel;
291 out = in->outlabel;
293 if (out != NULL) {
294 if (in->reuse_count == 1) {
295 ldp_inlabel_del_outlabel(g, in);
299 ldp_attr_del_inlabel(attr);
300 ldp_attr_delete_upstream(g, session, attr);
301 ldp_attr_del_us2ds(attr, attr->ds_attr);
302 ldp_session_del_inlabel(session, in);
304 if (in->reuse_count == 0) {
305 _ldp_global_del_inlabel(g, in);
307 break;
308 case LDP_LSP_STATE_ABORT_SENT:
309 case LDP_LSP_STATE_NOTIF_SENT:
310 case LDP_LSP_STATE_REQ_RECV:
311 case LDP_LSP_STATE_WITH_SENT:
312 case LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT:
314 ldp_attr_del_us2ds(attr, attr->ds_attr);
315 ldp_attr_delete_upstream(g, session, attr);
316 break;
318 case LDP_LSP_STATE_ABORT_RECV:
319 case LDP_LSP_STATE_NOTIF_RECV:
320 case LDP_LSP_STATE_REQ_SENT:
321 case LDP_LSP_STATE_WITH_RECV:
322 case LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV:
324 while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
325 ldp_attr_del_us2ds(us_temp, attr);
327 ldp_attr_delete_downstream(g, session, attr);
328 break;
333 ldp_attr *ldp_attr_create(mpls_fec * fec)
335 ldp_attr *a = (ldp_attr *) mpls_malloc(sizeof(ldp_attr));
337 if (a != NULL) {
338 memset(a, 0, sizeof(ldp_attr));
339 MPLS_LIST_ELEM_INIT(a, _session);
340 MPLS_LIST_ELEM_INIT(a, _global);
341 MPLS_LIST_ELEM_INIT(a, _fs);
342 MPLS_LIST_INIT(&a->us_attr_root, ldp_attr);
343 MPLS_REFCNT_INIT(a, 0);
344 a->index = _ldp_attr_get_next_index();
345 a->in_tree = MPLS_BOOL_FALSE;
346 a->ingress = MPLS_BOOL_FALSE;
347 a->filtered = MPLS_BOOL_FALSE;
349 if (fec != NULL) {
350 mpls_fec2fec_tlv(fec, &a->fecTlv, 0);
351 a->fecTlv.numberFecElements = 1;
352 a->fecTlvExists = 1;
355 return a;
358 void ldp_attr_delete(ldp_attr * a)
360 LDP_PRINT(g->user_data,"attr delete\n");
361 MPLS_ASSERT(a->in_tree == MPLS_BOOL_FALSE);
362 mpls_free(a);
365 void ldp_attr2ldp_attr(ldp_attr * a, ldp_attr * b, uint32_t flag)
367 if (a->fecTlvExists && flag & LDP_ATTR_FEC) {
368 memcpy(&b->fecTlv, &a->fecTlv, sizeof(mplsLdpFecTlv_t));
369 b->fecTlvExists = 1;
371 if (a->genLblTlvExists && flag & LDP_ATTR_LABEL) {
372 memcpy(&b->genLblTlv, &a->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
373 b->genLblTlvExists = 1;
374 } else if (a->atmLblTlvExists && flag & LDP_ATTR_LABEL) {
375 memcpy(&b->atmLblTlv, &a->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
376 b->atmLblTlvExists = 1;
377 } else if (a->frLblTlvExists && flag & LDP_ATTR_LABEL) {
378 memcpy(&b->frLblTlv, &a->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
379 b->frLblTlvExists = 1;
381 if (a->hopCountTlvExists && flag & LDP_ATTR_HOPCOUNT) {
382 memcpy(&b->hopCountTlv, &a->hopCountTlv, sizeof(mplsLdpHopTlv_t));
383 b->hopCountTlvExists = 1;
385 if (a->pathVecTlvExists && flag & LDP_ATTR_PATH) {
386 memcpy(&b->pathVecTlv, &a->pathVecTlv, sizeof(mplsLdpPathTlv_t));
387 b->pathVecTlvExists = 1;
389 if (a->lblMsgIdTlvExists && flag & LDP_ATTR_MSGID) {
390 memcpy(&b->lblMsgIdTlv, &a->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
391 b->lblMsgIdTlvExists = 1;
393 if (a->lspidTlvExists && flag & LDP_ATTR_LSPID) {
394 memcpy(&b->lspidTlv, &a->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
395 b->lspidTlvExists = 1;
397 if (a->trafficTlvExists && flag & LDP_ATTR_TRAFFIC) {
398 memcpy(&b->trafficTlv, &a->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
399 b->trafficTlvExists = 1;
403 mpls_return_enum ldp_attr_add_inlabel(ldp_attr * a, ldp_inlabel * i)
405 if (a && i) {
406 MPLS_REFCNT_HOLD(i);
407 a->inlabel = i;
408 _ldp_inlabel_add_attr(i, a);
409 return MPLS_SUCCESS;
411 return MPLS_FAILURE;
414 mpls_return_enum ldp_attr_del_inlabel(ldp_attr * a)
416 if (a && a->inlabel) {
417 _ldp_inlabel_del_attr(a->inlabel, a);
418 MPLS_REFCNT_RELEASE(a->inlabel, ldp_inlabel_delete);
419 a->inlabel = NULL;
420 return MPLS_SUCCESS;
422 return MPLS_FAILURE;
425 mpls_return_enum ldp_attr_add_outlabel(ldp_attr * a, ldp_outlabel * o)
427 if (a && o) {
428 MPLS_REFCNT_HOLD(o);
429 a->outlabel = o;
430 _ldp_outlabel_add_attr(o, a);
431 return MPLS_SUCCESS;
433 return MPLS_FAILURE;
436 mpls_return_enum ldp_attr_del_outlabel(ldp_attr * a)
438 if (a && a->outlabel) {
439 _ldp_outlabel_del_attr(a->outlabel);
440 MPLS_REFCNT_RELEASE(a->outlabel, ldp_outlabel_delete);
441 a->outlabel = NULL;
442 return MPLS_SUCCESS;
444 return MPLS_FAILURE;
447 mpls_return_enum ldp_attr_add_session(ldp_attr * a, ldp_session * s)
449 if (a && s) {
450 MPLS_REFCNT_HOLD(s);
451 a->session = s;
452 _ldp_session_add_attr(s, a);
453 return MPLS_SUCCESS;
455 return MPLS_FAILURE;
458 mpls_return_enum ldp_attr_del_session(ldp_attr * a)
460 if (a && a->session) {
461 _ldp_session_del_attr(a->session, a);
462 MPLS_REFCNT_RELEASE(a->session, ldp_session_delete);
463 a->session = NULL;
464 return MPLS_SUCCESS;
466 return MPLS_FAILURE;
469 mpls_bool ldp_attr_is_equal(ldp_attr * a, ldp_attr * b, uint32_t flag)
471 if (flag & LDP_ATTR_LABEL) {
472 if (a->genLblTlvExists && b->genLblTlvExists) {
473 if (a->genLblTlv.label != b->genLblTlv.label) {
474 return MPLS_BOOL_FALSE;
476 } else if (a->atmLblTlvExists && b->atmLblTlvExists) {
477 if (a->atmLblTlv.flags.flags.vpi != b->atmLblTlv.flags.flags.vpi ||
478 a->atmLblTlv.vci != b->atmLblTlv.vci) {
479 return MPLS_BOOL_FALSE;
481 } else if (a->frLblTlvExists && b->frLblTlvExists) {
482 if (a->frLblTlv.flags.flags.len != b->frLblTlv.flags.flags.len ||
483 a->frLblTlv.flags.flags.dlci != b->frLblTlv.flags.flags.dlci) {
484 return MPLS_BOOL_FALSE;
486 } else {
487 return MPLS_BOOL_FALSE;
490 if (flag & LDP_ATTR_HOPCOUNT) {
491 if (a->hopCountTlvExists && b->hopCountTlvExists) {
492 if (a->hopCountTlv.hcValue != b->hopCountTlv.hcValue) {
493 return MPLS_BOOL_FALSE;
495 } else {
496 if (a->hopCountTlvExists != b->hopCountTlvExists) {
497 return MPLS_BOOL_FALSE;
501 if (flag & LDP_ATTR_PATH) {
502 int i;
504 if (a->pathVecTlvExists && b->pathVecTlvExists) {
505 for (i = 0; i < MPLS_MAXHOPSNUMBER; i++) {
506 if (a->pathVecTlv.lsrId[i] != b->pathVecTlv.lsrId[i]) {
507 return MPLS_BOOL_FALSE;
510 } else {
511 if (a->hopCountTlvExists != b->hopCountTlvExists) {
512 return MPLS_BOOL_FALSE;
516 if (flag & LDP_ATTR_FEC) {
517 int i;
519 if (a->fecTlvExists && b->fecTlvExists) {
520 if (a->fecTlv.numberFecElements != b->fecTlv.numberFecElements) {
521 return MPLS_BOOL_FALSE;
523 for (i = 0; i < a->fecTlv.numberFecElements; i++) {
524 if (a->fecTlv.fecElemTypes[i] != b->fecTlv.fecElemTypes[i]) {
525 return MPLS_BOOL_FALSE;
527 switch (a->fecTlv.fecElemTypes[i]) {
528 case MPLS_CRLSP_FEC:
529 case MPLS_WC_FEC:
530 /* nothing of interest to compare */
531 break;
532 case MPLS_PREFIX_FEC:
533 case MPLS_HOSTADR_FEC:
534 if (a->fecTlv.fecElArray[i].addressEl.addressFam !=
535 b->fecTlv.fecElArray[i].addressEl.addressFam ||
536 a->fecTlv.fecElArray[i].addressEl.preLen !=
537 b->fecTlv.fecElArray[i].addressEl.preLen ||
538 a->fecTlv.fecElArray[i].addressEl.address !=
539 b->fecTlv.fecElArray[i].addressEl.address) {
540 return MPLS_BOOL_FALSE;
542 break;
543 default:
544 MPLS_ASSERT(0);
547 } else {
548 return MPLS_BOOL_FALSE;
551 if (flag & LDP_ATTR_MSGID) {
552 if (a->lblMsgIdTlvExists && b->lblMsgIdTlvExists) {
553 if (a->lblMsgIdTlv.msgId != b->lblMsgIdTlv.msgId) {
554 return MPLS_BOOL_FALSE;
556 } else {
557 return MPLS_BOOL_FALSE;
560 if (flag & LDP_ATTR_LSPID) {
561 if (a->lspidTlvExists && b->lspidTlvExists) {
562 if (a->lspidTlv.localCrlspId != b->lspidTlv.localCrlspId ||
563 a->lspidTlv.routerId != b->lspidTlv.routerId) {
564 return MPLS_BOOL_FALSE;
566 } else {
567 return MPLS_BOOL_FALSE;
570 if (flag & LDP_ATTR_TRAFFIC) {
572 return MPLS_BOOL_TRUE;
575 mpls_return_enum ldp_attr_insert_upstream2(ldp_global * g, ldp_session * s,
576 ldp_attr * a, ldp_fec *f)
578 ldp_fs *fs = NULL;
579 mpls_return_enum retval;
581 MPLS_ASSERT(g && s && a && (a->in_tree == MPLS_BOOL_FALSE) && f);
583 /* find the upstream fs for this session */
584 if ((fs = _ldp_fec_find_fs_us(f, s, MPLS_BOOL_TRUE)) == NULL) {
585 /* this session isn't in the list and cannot be added */
586 return MPLS_FAILURE;
589 ldp_attr_add_session(a, s);
590 ldp_attr_add_fec(a, f);
592 retval = _ldp_fs_add_attr(fs, a);
593 _ldp_global_add_attr(g, a);
594 a->in_tree = MPLS_BOOL_TRUE;
595 return retval;
598 mpls_return_enum ldp_attr_insert_upstream(ldp_global * g, ldp_session * s,
599 ldp_attr * a)
601 ldp_fec *fnode = NULL;
603 MPLS_ASSERT(g && s && a && (a->in_tree == MPLS_BOOL_FALSE));
605 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_TRUE)) == NULL) {
606 /* we couldn't get/add a node from/to the tree! */
607 return MPLS_FAILURE;
610 return ldp_attr_insert_upstream2(g, s, a, fnode);
613 mpls_return_enum ldp_attr_insert_downstream2(ldp_global * g, ldp_session * s,
614 ldp_attr * a, ldp_fec *f)
616 ldp_fs *fs = NULL;
617 mpls_return_enum retval;
619 MPLS_ASSERT(g && s && a && (a->in_tree == MPLS_BOOL_FALSE) && f);
621 /* find the downstream fs for this session */
622 if ((fs = _ldp_fec_find_fs_ds(f, s, MPLS_BOOL_TRUE)) == NULL) {
623 /* this session isn't in the list and cannot be added */
624 return MPLS_FAILURE;
627 ldp_attr_add_session(a, s);
628 ldp_attr_add_fec(a, f);
630 retval = _ldp_fs_add_attr(fs, a);
631 _ldp_global_add_attr(g, a);
632 a->in_tree = MPLS_BOOL_TRUE;
633 return retval;
636 mpls_return_enum ldp_attr_insert_downstream(ldp_global * g, ldp_session * s,
637 ldp_attr * a)
639 ldp_fec *fnode = NULL;
641 MPLS_ASSERT(g && s && a && (a->in_tree == MPLS_BOOL_FALSE));
643 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_TRUE)) == NULL) {
644 /* we couldn't get/add a node from/to the tree! */
645 return MPLS_FAILURE;
648 return ldp_attr_insert_downstream2(g, s, a, fnode);
651 ldp_attr_list *ldp_attr_find_upstream_all2(ldp_global * g, ldp_session * s,
652 ldp_fec * f)
654 ldp_fs *fs = NULL;
656 MPLS_ASSERT(s && f && g);
658 /* find the upstream fs for this session */
659 if ((fs = _ldp_fec_find_fs_us(f, s, MPLS_BOOL_FALSE)) == NULL) {
660 /* this session isn't in the list */
661 return NULL;
663 return &fs->attr_root;
666 ldp_attr_list *ldp_attr_find_upstream_all(ldp_global * g, ldp_session * s,
667 mpls_fec * f)
669 ldp_fec *fnode = NULL;
671 MPLS_ASSERT(s && f && g);
673 if ((fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE)) == NULL) {
674 /* we couldn't get the node from the tree! */
675 return NULL;
678 return ldp_attr_find_upstream_all2(g, s, fnode);
681 ldp_attr_list *ldp_attr_find_downstream_all2(ldp_global * g, ldp_session * s,
682 ldp_fec * f)
684 ldp_fs *fs = NULL;
686 MPLS_ASSERT(s && f && g);
688 /* find the downstream fs for this session */
689 if ((fs = _ldp_fec_find_fs_ds(f, s, MPLS_BOOL_FALSE)) == NULL) {
690 /* this session isn't in the list */
691 return NULL;
693 return &fs->attr_root;
696 ldp_attr_list *ldp_attr_find_downstream_all(ldp_global * g, ldp_session * s,
697 mpls_fec * f)
699 ldp_fec *fnode = NULL;
701 MPLS_ASSERT(s && f && g);
703 if ((fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE)) == NULL) {
704 /* we couldn't get the node from the tree! */
705 return NULL;
708 return ldp_attr_find_downstream_all2(g, s, fnode);
711 void ldp_attr_delete_upstream(ldp_global * g, ldp_session * s, ldp_attr * a)
713 ldp_fec *fnode = NULL;
714 ldp_fs *fs = NULL;
716 MPLS_ASSERT(a->in_tree == MPLS_BOOL_TRUE);
718 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_FALSE)) == NULL) {
719 /* we couldn't get the node from the tree! */
720 return;
723 /* find the upstream fs for this session */
724 if ((fs = _ldp_fec_find_fs_us(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
725 /* this session isn't in the list */
726 return;
729 ldp_attr_del_session(a);
730 ldp_attr_del_fec(a);
732 if (_ldp_fs_del_attr(fs, a) == MPLS_BOOL_TRUE) {
733 _ldp_fec_del_fs_us(fnode, fs);
735 a->in_tree = MPLS_BOOL_FALSE;
736 _ldp_global_del_attr(g, a);
738 if (ldp_fec_empty(fnode)) {
739 ldp_nexthop *nh;
740 while ((nh = MPLS_LIST_HEAD(&fnode->nh_root))) {
741 ldp_fec_del_nexthop(fnode, nh);
743 ldp_fec_remove(g, &fnode->info);
744 _ldp_global_del_fec(g, fnode);
748 void ldp_attr_delete_downstream(ldp_global * g, ldp_session * s, ldp_attr * a)
750 ldp_fec *fnode = NULL;
751 ldp_fs *fs = NULL;
753 MPLS_ASSERT(a->in_tree == MPLS_BOOL_TRUE);
755 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_FALSE)) == NULL) {
756 /* we couldn't get the node from the tree! */
757 return;
760 /* find the downstream fs for this session */
761 if ((fs = _ldp_fec_find_fs_ds(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
762 /* this session isn't in the list */
763 return;
766 ldp_attr_del_session(a);
767 ldp_attr_del_fec(a);
769 if (_ldp_fs_del_attr(fs, a) == MPLS_BOOL_TRUE) {
770 _ldp_fec_del_fs_ds(fnode, fs);
772 a->in_tree = MPLS_BOOL_FALSE;
773 _ldp_global_del_attr(g, a);
775 if (ldp_fec_empty(fnode)) {
776 ldp_nexthop *nh;
777 while ((nh = MPLS_LIST_HEAD(&fnode->nh_root))) {
778 ldp_fec_del_nexthop(fnode, nh);
780 ldp_fec_remove(g, &fnode->info);
781 _ldp_global_del_fec(g, fnode);
785 void ldp_attr2mpls_label_struct(ldp_attr * a, mpls_label_struct * l)
787 if (a->genLblTlvExists) {
788 l->type = MPLS_LABEL_TYPE_GENERIC;
789 l->u.gen = a->genLblTlv.label;
790 } else if (a->atmLblTlvExists) {
791 l->type = MPLS_LABEL_TYPE_ATM;
792 l->u.atm.vpi = a->atmLblTlv.flags.flags.vpi;
793 l->u.atm.vci = a->atmLblTlv.vci;
794 } else if (a->frLblTlvExists) {
795 l->type = MPLS_LABEL_TYPE_FR;
796 l->u.fr.len = a->frLblTlv.flags.flags.len;
797 l->u.fr.dlci = a->frLblTlv.flags.flags.dlci;
798 } else {
799 MPLS_ASSERT(0);
803 void mpls_label_struct2ldp_attr(mpls_label_struct * l, ldp_attr * a)
805 switch (l->type) {
806 case MPLS_LABEL_TYPE_GENERIC:
807 a->genLblTlvExists = 1;
808 a->atmLblTlvExists = 0;
809 a->frLblTlvExists = 0;
810 a->genLblTlv.label = l->u.gen;
811 break;
812 case MPLS_LABEL_TYPE_ATM:
813 a->genLblTlvExists = 0;
814 a->atmLblTlvExists = 1;
815 a->frLblTlvExists = 0;
816 a->atmLblTlv.flags.flags.vpi = l->u.atm.vpi;
817 a->atmLblTlv.vci = l->u.atm.vci;
818 case MPLS_LABEL_TYPE_FR:
819 a->genLblTlvExists = 0;
820 a->atmLblTlvExists = 0;
821 a->frLblTlvExists = 1;
822 a->frLblTlv.flags.flags.len = l->u.fr.len;
823 a->frLblTlv.flags.flags.dlci = l->u.fr.dlci;
824 default:
825 MPLS_ASSERT(0);
829 #if 0
830 void ldp_attr2ldp_attr(ldp_attr * src, ldp_attr * dst, u_int32 flag)
832 if (flag & LDP_ATTR_FEC) {
833 memcpy(&dst->fecTlv, &src->fecTlv, sizeof(mplsLdpFecTlv_t));
834 dst->fecTlvExists = src->fecTlvExists;
836 if (flag & LDP_ATTR_LABEL) {
837 memcpy(&dst->genLblTlv, &src->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
838 memcpy(&dst->atmLblTlv, &src->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
839 memcpy(&dst->frLblTlv, &src->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
840 dst->genLblTlvExists = src->genLblTlvExists
841 dst->atmLblTlvExists = src->atmLblTlvExists
842 dst->frLblTlvExists = src->frLblTlvExists}
843 if (flag & LDP_ATTR_HOPCOUNT) {
844 memcpy(&dst->hopCountTlv, &src->hopCountTlv, sizeof(mplsLdpHopTlv_t));
845 dst->hopCountTlvExists = src->hopCountTlvExists;
847 if (flag & LDP_ATTR_PATH) {
848 memcpy(&dst->pathVecTlv, &src->pathVecTlv, sizeof(mplsLdpPathTlv_t));
849 dst->pathVecTlvExists = src->pathVecTlvExists;
851 if (flag & LDP_ATTR_MSGID) {
852 memcpy(&dst->lblMsgIdTlv, &src->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
853 dst->lblMsgIdTlvExists = src->lblMsgIdTlvExists;
855 if (flag & LDP_ATTR_LSPID) {
856 memcpy(&dst->lspidTlv, &src->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
857 dst->lspidTlvExists = src->lspidTlvExists;
859 if (flag & LDP_ATTR_TRAFFIC) {
860 memcpy(&dst->trafficTlv, &src->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
861 dst->trafficTlvExists = src->trafficTlvExists;
864 #endif
866 ldp_fec *_ldp_attr_get_fec2(ldp_global * g, mpls_fec * f, mpls_bool flag)
868 ldp_fec *fnode = NULL;
870 if (!(fnode = ldp_fec_find(g,f))) {
871 if (flag == MPLS_BOOL_FALSE) {
872 return NULL;
875 /* this FEC doesn't exist in the tree yet, create one ... */
876 if (!(fnode = ldp_fec_insert(g, f))) {
877 /* insert failed */
878 return NULL;
880 _ldp_global_add_fec(g, fnode);
882 return fnode;
885 static ldp_fec *_ldp_attr_get_fec(ldp_global * g, ldp_attr * a, mpls_bool flag)
887 mpls_fec fec;
889 /* get FEC from attr */
890 fec_tlv2mpls_fec(&a->fecTlv, 0, &fec);
891 return _ldp_attr_get_fec2(g, &fec, flag);
894 static ldp_fs *_ldp_fec_add_fs_ds(ldp_fec * fec, ldp_session * s)
896 ldp_fs *fs = _ldp_fec_find_fs_ds(fec, s, MPLS_BOOL_FALSE);
898 if (fs == NULL) {
899 fs = _ldp_fs_create(s);
900 if (fs == NULL) {
901 return NULL;
903 MPLS_LIST_ADD_HEAD(&fec->fs_root_ds, fs, _fec, ldp_fs);
905 return fs;
908 static ldp_fs *_ldp_fec_add_fs_us(ldp_fec * fec, ldp_session * s)
910 ldp_fs *fs = _ldp_fec_find_fs_us(fec, s, MPLS_BOOL_FALSE);
912 if (fs == NULL) {
913 fs = _ldp_fs_create(s);
914 if (fs == NULL) {
915 return NULL;
917 MPLS_LIST_ADD_HEAD(&fec->fs_root_us, fs, _fec, ldp_fs);
919 return fs;
922 static ldp_fs *_ldp_fec_find_fs_us(ldp_fec * fec, ldp_session * s,
923 mpls_bool flag)
925 ldp_fs *fs = MPLS_LIST_HEAD(&fec->fs_root_us);
927 while (fs != NULL) {
928 if (fs->session->index == s->index) {
929 return fs;
931 fs = MPLS_LIST_NEXT(&fec->fs_root_us, fs, _fec);
933 if (flag == MPLS_BOOL_FALSE) {
934 return NULL;
936 return _ldp_fec_add_fs_us(fec, s);
939 static ldp_fs *_ldp_fec_find_fs_ds(ldp_fec * fec, ldp_session * s,
940 mpls_bool flag)
942 ldp_fs *fs = MPLS_LIST_HEAD(&fec->fs_root_ds);
944 while (fs != NULL) {
945 if (fs->session->index == s->index) {
946 return fs;
948 fs = MPLS_LIST_NEXT(&fec->fs_root_ds, fs, _fec);
950 if (flag == MPLS_BOOL_FALSE) {
951 return NULL;
953 return _ldp_fec_add_fs_ds(fec, s);
956 static void _ldp_fec_del_fs_us(ldp_fec * fec, ldp_fs * fs)
958 if (fs == NULL) {
959 return;
961 MPLS_LIST_REMOVE(&fec->fs_root_us, fs, _fec);
962 _ldp_fs_delete(fs);
965 static void _ldp_fec_del_fs_ds(ldp_fec * fec, ldp_fs * fs)
967 if (fs == NULL) {
968 return;
970 MPLS_LIST_REMOVE(&fec->fs_root_ds, fs, _fec);
971 _ldp_fs_delete(fs);
974 static ldp_fs *_ldp_fs_create(ldp_session * s)
976 ldp_fs *fs = (ldp_fs *) mpls_malloc(sizeof(ldp_fs));
978 if (fs != NULL) {
979 memset(fs, 0, sizeof(ldp_fs));
980 MPLS_LIST_INIT(&fs->attr_root, ldp_attr);
981 MPLS_LIST_ELEM_INIT(fs, _fec);
982 if (s != NULL) {
983 MPLS_REFCNT_HOLD(s);
984 fs->session = s;
987 return fs;
990 static void _ldp_fs_delete(ldp_fs * fs)
992 LDP_PRINT(g->user_data,"fs delete\n");
993 if (fs->session != NULL) {
994 MPLS_REFCNT_RELEASE(fs->session, ldp_session_delete);
996 mpls_free(fs);
999 static ldp_attr *_ldp_fs_find_attr(ldp_fs * fs, ldp_attr * a)
1001 ldp_attr *ptr = MPLS_LIST_HEAD(&fs->attr_root);
1003 while (ptr != NULL) {
1004 if (ldp_attr_is_equal(a, ptr, LDP_ATTR_LABEL | LDP_ATTR_FEC) == MPLS_BOOL_TRUE) {
1005 return ptr;
1007 ptr = MPLS_LIST_NEXT(&fs->attr_root, ptr, _fs);
1009 return NULL;
1012 static mpls_return_enum _ldp_fs_add_attr(ldp_fs * fs, ldp_attr * a)
1014 ldp_attr *ptr = _ldp_fs_find_attr(fs, a);
1016 MPLS_ASSERT(ptr == NULL);
1017 MPLS_REFCNT_HOLD(a);
1018 MPLS_LIST_ADD_HEAD(&fs->attr_root, a, _fs, ldp_attr);
1019 return MPLS_SUCCESS;
1022 static mpls_bool _ldp_fs_del_attr(ldp_fs * fs, ldp_attr * a)
1024 ldp_attr *ptr = _ldp_fs_find_attr(fs, a);
1026 if (ptr != NULL) {
1027 MPLS_LIST_REMOVE(&fs->attr_root, ptr, _fs);
1028 MPLS_REFCNT_RELEASE(ptr, ldp_attr_delete);
1030 if (MPLS_LIST_HEAD(&fs->attr_root) == NULL)
1031 return MPLS_BOOL_TRUE;
1032 return MPLS_BOOL_FALSE;
1035 static uint32_t _ldp_attr_get_next_index()
1037 uint32_t retval = _ldp_attr_next_index;
1039 _ldp_attr_next_index++;
1040 if (retval > _ldp_attr_next_index) {
1041 _ldp_attr_next_index = 1;
1043 return retval;