Create a ldp_nexthop which mirrors the functionality of
[mpls-ldp-portable.git] / ldp / ldp_attr.c
blobb0d2a13f365c192c81e7ae7dcc2cb47a1427745f
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_fec.h"
14 #include "ldp_global.h"
15 #include "ldp_inlabel.h"
16 #include "ldp_outlabel.h"
17 #include "ldp_session.h"
18 #include "mpls_refcnt.h"
19 #include "mpls_mm_impl.h"
20 #include "mpls_tree_impl.h"
21 #include "mpls_trace_impl.h"
23 #if MPLS_USE_LSR
24 #include "lsr_cfg.h"
25 #else
26 #include "mpls_mpls_impl.h"
27 #endif
29 static ldp_fec *_ldp_attr_get_fec(ldp_global * g, ldp_attr * a, mpls_bool flag);
30 static ldp_fs *_ldp_fec_add_fs_ds(ldp_fec * fec, ldp_session * s);
31 static ldp_fs *_ldp_fec_add_fs_us(ldp_fec * fec, ldp_session * s);
32 static ldp_fs *_ldp_fec_find_fs_us(ldp_fec * fec, ldp_session * s,
33 mpls_bool flag);
34 static ldp_fs *_ldp_fec_find_fs_ds(ldp_fec * fec, ldp_session * s,
35 mpls_bool flag);
36 static void _ldp_fec_del_fs_us(ldp_fec * fec, ldp_fs * fs);
37 static void _ldp_fec_del_fs_ds(ldp_fec * fec, ldp_fs * fs);
38 static ldp_fs *_ldp_fs_create(ldp_session * s);
39 static void _ldp_fs_delete(ldp_fs * fs);
40 static ldp_attr *_ldp_fs_find_attr(ldp_fs * fs, ldp_attr * a);
41 static mpls_return_enum _ldp_fs_add_attr(ldp_fs * fs, ldp_attr * a);
42 static mpls_bool _ldp_fs_del_attr(ldp_fs * fs, ldp_attr * a);
43 static uint32_t _ldp_attr_get_next_index();
45 static uint32_t _ldp_attr_next_index = 1;
47 int ldp_attr_num_us2ds(ldp_attr * ds)
49 ldp_attr *attr = NULL;
50 int count = 0;
52 attr = MPLS_LIST_HEAD(&ds->us_attr_root);
53 while (attr) {
54 count++;
55 attr = MPLS_LIST_NEXT(&ds->us_attr_root, attr, _ds_attr);
57 return count;
60 mpls_bool ldp_attr_us_partof_ds(ldp_attr * us, ldp_attr * ds)
62 if (us->ds_attr == ds) {
63 return MPLS_BOOL_TRUE;
65 return MPLS_BOOL_FALSE;
68 void ldp_attr_del_us2ds(ldp_attr * us, ldp_attr * ds)
70 if (!us || !ds) {
71 return;
73 if (ldp_attr_us_partof_ds(us, ds) == MPLS_BOOL_TRUE) {
74 us->ds_attr = NULL;
75 MPLS_REFCNT_RELEASE(ds, ldp_attr_delete);
76 MPLS_LIST_REMOVE(&ds->us_attr_root, us, _ds_attr);
77 MPLS_REFCNT_RELEASE(us, ldp_attr_delete);
78 } else {
79 MPLS_ASSERT(0);
83 void ldp_attr_add_fec(ldp_attr *a, ldp_fec *fec) {
84 MPLS_ASSERT(a && fec);
85 MPLS_REFCNT_HOLD(fec);
86 a->fec = fec;
89 void ldp_attr_del_fec(ldp_attr *a) {
90 MPLS_ASSERT(a);
91 if (a->fec) {
92 MPLS_REFCNT_RELEASE(a->fec, ldp_fec_delete);
93 a->fec = NULL;
97 void ldp_attr_add_us2ds(ldp_attr * us, ldp_attr * ds)
100 if (!us || !ds) {
101 return;
103 if (ldp_attr_us_partof_ds(us, ds) == MPLS_BOOL_TRUE) {
104 return;
106 MPLS_REFCNT_HOLD(us);
107 MPLS_LIST_ADD_TAIL(&ds->us_attr_root, us, _ds_attr, ldp_attr);
108 MPLS_REFCNT_HOLD(ds);
109 us->ds_attr = ds;
112 void ldp_attr_action_callback(mpls_timer_handle timer, void *extra,
113 mpls_cfg_handle g)
117 ldp_attr *ldp_attr_find_downstream_state_any(ldp_global * g, mpls_fec * f,
118 ldp_lsp_state state)
120 ldp_fec *fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE);
121 ldp_attr *attr = NULL;
122 ldp_fs *fs = NULL;
124 if (!fnode) {
125 return NULL;
128 fs = MPLS_LIST_HEAD(&fnode->fs_root_ds);
129 while (fs != NULL) {
130 attr = MPLS_LIST_HEAD(&fs->attr_root);
131 while (attr != NULL) {
132 if (attr->state == state) {
133 return attr;
135 attr = MPLS_LIST_NEXT(&fs->attr_root, attr, _fs);
137 fs = MPLS_LIST_NEXT(&fnode->fs_root_ds, fs, _fec);
139 return NULL;
142 ldp_attr *ldp_attr_find_upstream_state_any(ldp_global * g, mpls_fec * f,
143 ldp_lsp_state state)
145 ldp_fec *fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE);
146 ldp_attr *attr = NULL;
147 ldp_fs *fs = NULL;
149 if (!fnode) {
150 return NULL;
153 fs = MPLS_LIST_HEAD(&fnode->fs_root_us);
154 while (fs != NULL) {
155 attr = MPLS_LIST_HEAD(&fs->attr_root);
156 while (attr != NULL) {
157 if (attr->state == state) {
158 return attr;
160 attr = MPLS_LIST_NEXT(&fs->attr_root, attr, _fs);
162 fs = MPLS_LIST_NEXT(&fnode->fs_root_us, fs, _fec);
164 return NULL;
167 ldp_attr *ldp_attr_find_downstream_state(ldp_global * g, ldp_session * s,
168 mpls_fec * f, ldp_lsp_state state)
170 ldp_attr_list *ds_list = ldp_attr_find_downstream_all(g, s, f);
172 if (ds_list != NULL) {
173 ldp_attr *ds_attr = MPLS_LIST_HEAD(ds_list);
175 while (ds_attr != NULL) {
176 if (ds_attr->state == state) {
177 return ds_attr;
179 ds_attr = MPLS_LIST_NEXT(ds_list, ds_attr, _fs);
182 return NULL;
185 ldp_attr *ldp_attr_find_upstream_state(ldp_global * g, ldp_session * s,
186 mpls_fec * f, ldp_lsp_state state)
188 ldp_attr_list *us_list = ldp_attr_find_upstream_all(g, s, f);
190 if (us_list != NULL) {
191 ldp_attr *us_attr = MPLS_LIST_HEAD(us_list);
193 while (us_attr != NULL) {
194 if (us_attr->state == state) {
195 return us_attr;
197 us_attr = MPLS_LIST_NEXT(us_list, us_attr, _fs);
200 return NULL;
203 void ldp_attr_remove_complete(ldp_global * g, ldp_attr * attr,
204 mpls_bool complete)
206 ldp_session *session = attr->session;
207 ldp_outlabel *out = NULL;
208 ldp_inlabel *in = NULL;
209 ldp_attr *us_temp = NULL;
210 mpls_fec fec;
211 int i;
213 switch (attr->state) {
214 case LDP_LSP_STATE_MAP_RECV:
215 if (attr->ingress == MPLS_BOOL_TRUE) {
216 out = attr->outlabel;
217 MPLS_ASSERT(out != NULL);
218 while ((in = MPLS_LIST_HEAD(&out->inlabel_root)) != NULL) {
219 ldp_inlabel_del_outlabel(g, in);
222 if (out->merge_count > 0) {
223 for (i = 0; i < attr->fecTlv.numberFecElements; i++) {
224 fec_tlv2mpls_fec(&attr->fecTlv, i, &fec);
225 out->merge_count--;
226 #if MPLS_USE_LSR
228 lsr_ftn ftn;
229 memcpy(&ftn.fec, &fec, sizeof(mpls_fec));
230 ftn.outsegment_index = out->info.handle;
231 lsr_cfg_ftn_set2(g->lsr_handle, &ftn, LSR_CFG_DEL);
233 #else
234 mpls_mpls_fec2out_del(g->mpls_handle, &fec, &out->info);
235 #endif
238 MPLS_ASSERT(out->merge_count == 0);
239 ldp_attr_del_outlabel(attr);
240 ldp_session_del_outlabel(session, out);
241 _ldp_global_del_outlabel(g, out);
243 while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
244 ldp_attr_del_us2ds(us_temp, attr);
246 ldp_attr_delete_downstream(g, session, attr);
247 break;
248 case LDP_LSP_STATE_MAP_SENT:
249 in = attr->inlabel;
250 out = in->outlabel;
252 if (out != NULL) {
253 if (in->reuse_count == 1) {
254 ldp_inlabel_del_outlabel(g, in);
258 ldp_attr_del_inlabel(attr);
259 ldp_attr_delete_upstream(g, session, attr);
260 ldp_attr_del_us2ds(attr, attr->ds_attr);
261 ldp_session_del_inlabel(session, in);
263 if (in->reuse_count == 0) {
264 _ldp_global_del_inlabel(g, in);
266 break;
267 case LDP_LSP_STATE_ABORT_SENT:
268 case LDP_LSP_STATE_NOTIF_SENT:
269 case LDP_LSP_STATE_REQ_RECV:
270 case LDP_LSP_STATE_WITH_SENT:
271 case LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT:
273 ldp_attr_del_us2ds(attr, attr->ds_attr);
274 ldp_attr_delete_upstream(g, session, attr);
275 break;
277 case LDP_LSP_STATE_ABORT_RECV:
278 case LDP_LSP_STATE_NOTIF_RECV:
279 case LDP_LSP_STATE_REQ_SENT:
280 case LDP_LSP_STATE_WITH_RECV:
281 case LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV:
283 while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
284 ldp_attr_del_us2ds(us_temp, attr);
286 ldp_attr_delete_downstream(g, session, attr);
287 break;
292 ldp_attr *ldp_attr_create(mpls_fec * fec)
294 ldp_attr *a = (ldp_attr *) mpls_malloc(sizeof(ldp_attr));
296 if (a != NULL) {
297 memset(a, 0, sizeof(ldp_attr));
298 MPLS_LIST_ELEM_INIT(a, _session);
299 MPLS_LIST_ELEM_INIT(a, _global);
300 MPLS_LIST_ELEM_INIT(a, _fs);
301 MPLS_LIST_INIT(&a->us_attr_root, ldp_attr);
302 MPLS_REFCNT_INIT(a, 0);
303 a->index = _ldp_attr_get_next_index();
304 a->in_tree = MPLS_BOOL_FALSE;
305 a->ingress = MPLS_BOOL_FALSE;
306 a->filtered = MPLS_BOOL_FALSE;
308 if (fec != NULL) {
309 mpls_fec2fec_tlv(fec, &a->fecTlv, 0);
310 a->fecTlv.numberFecElements = 1;
311 a->fecTlvExists = 1;
314 return a;
317 void ldp_attr_delete(ldp_attr * a)
319 LDP_PRINT(g->user_data,"attr delete\n");
320 MPLS_ASSERT(a->in_tree == MPLS_BOOL_FALSE);
321 mpls_free(a);
324 void ldp_attr2ldp_attr(ldp_attr * a, ldp_attr * b, uint32_t flag)
326 if (a->fecTlvExists && flag & LDP_ATTR_FEC) {
327 memcpy(&b->fecTlv, &a->fecTlv, sizeof(mplsLdpFecTlv_t));
328 b->fecTlvExists = 1;
330 if (a->genLblTlvExists && flag & LDP_ATTR_LABEL) {
331 memcpy(&b->genLblTlv, &a->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
332 b->genLblTlvExists = 1;
333 } else if (a->atmLblTlvExists && flag & LDP_ATTR_LABEL) {
334 memcpy(&b->atmLblTlv, &a->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
335 b->atmLblTlvExists = 1;
336 } else if (a->frLblTlvExists && flag & LDP_ATTR_LABEL) {
337 memcpy(&b->frLblTlv, &a->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
338 b->frLblTlvExists = 1;
340 if (a->hopCountTlvExists && flag & LDP_ATTR_HOPCOUNT) {
341 memcpy(&b->hopCountTlv, &a->hopCountTlv, sizeof(mplsLdpHopTlv_t));
342 b->hopCountTlvExists = 1;
344 if (a->pathVecTlvExists && flag & LDP_ATTR_PATH) {
345 memcpy(&b->pathVecTlv, &a->pathVecTlv, sizeof(mplsLdpPathTlv_t));
346 b->pathVecTlvExists = 1;
348 if (a->lblMsgIdTlvExists && flag & LDP_ATTR_MSGID) {
349 memcpy(&b->lblMsgIdTlv, &a->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
350 b->lblMsgIdTlvExists = 1;
352 if (a->lspidTlvExists && flag & LDP_ATTR_LSPID) {
353 memcpy(&b->lspidTlv, &a->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
354 b->lspidTlvExists = 1;
356 if (a->trafficTlvExists && flag & LDP_ATTR_TRAFFIC) {
357 memcpy(&b->trafficTlv, &a->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
358 b->trafficTlvExists = 1;
362 mpls_return_enum ldp_attr_add_inlabel(ldp_attr * a, ldp_inlabel * i)
364 if (a && i) {
365 MPLS_REFCNT_HOLD(i);
366 a->inlabel = i;
367 _ldp_inlabel_add_attr(i, a);
368 return MPLS_SUCCESS;
370 return MPLS_FAILURE;
373 mpls_return_enum ldp_attr_del_inlabel(ldp_attr * a)
375 if (a && a->inlabel) {
376 _ldp_inlabel_del_attr(a->inlabel, a);
377 MPLS_REFCNT_RELEASE(a->inlabel, ldp_inlabel_delete);
378 a->inlabel = NULL;
379 return MPLS_SUCCESS;
381 return MPLS_FAILURE;
384 mpls_return_enum ldp_attr_add_outlabel(ldp_attr * a, ldp_outlabel * o)
386 if (a && o) {
387 MPLS_REFCNT_HOLD(o);
388 a->outlabel = o;
389 _ldp_outlabel_add_attr(o, a);
390 return MPLS_SUCCESS;
392 return MPLS_FAILURE;
395 mpls_return_enum ldp_attr_del_outlabel(ldp_attr * a)
397 if (a && a->outlabel) {
398 _ldp_outlabel_del_attr(a->outlabel);
399 MPLS_REFCNT_RELEASE(a->outlabel, ldp_outlabel_delete);
400 a->outlabel = NULL;
401 return MPLS_SUCCESS;
403 return MPLS_FAILURE;
406 mpls_return_enum ldp_attr_add_session(ldp_attr * a, ldp_session * s)
408 if (a && s) {
409 MPLS_REFCNT_HOLD(s);
410 a->session = s;
411 _ldp_session_add_attr(s, a);
412 return MPLS_SUCCESS;
414 return MPLS_FAILURE;
417 mpls_return_enum ldp_attr_del_session(ldp_attr * a)
419 if (a && a->session) {
420 _ldp_session_del_attr(a->session, a);
421 MPLS_REFCNT_RELEASE(a->session, ldp_session_delete);
422 a->session = NULL;
423 return MPLS_SUCCESS;
425 return MPLS_FAILURE;
428 mpls_bool ldp_attr_is_equal(ldp_attr * a, ldp_attr * b, uint32_t flag)
430 if (flag & LDP_ATTR_LABEL) {
431 if (a->genLblTlvExists && b->genLblTlvExists) {
432 if (a->genLblTlv.label != b->genLblTlv.label) {
433 return MPLS_BOOL_FALSE;
435 } else if (a->atmLblTlvExists && b->atmLblTlvExists) {
436 if (a->atmLblTlv.flags.flags.vpi != b->atmLblTlv.flags.flags.vpi ||
437 a->atmLblTlv.vci != b->atmLblTlv.vci) {
438 return MPLS_BOOL_FALSE;
440 } else if (a->frLblTlvExists && b->frLblTlvExists) {
441 if (a->frLblTlv.flags.flags.len != b->frLblTlv.flags.flags.len ||
442 a->frLblTlv.flags.flags.dlci != b->frLblTlv.flags.flags.dlci) {
443 return MPLS_BOOL_FALSE;
445 } else {
446 return MPLS_BOOL_FALSE;
449 if (flag & LDP_ATTR_HOPCOUNT) {
450 if (a->hopCountTlvExists && b->hopCountTlvExists) {
451 if (a->hopCountTlv.hcValue != b->hopCountTlv.hcValue) {
452 return MPLS_BOOL_FALSE;
454 } else {
455 if (a->hopCountTlvExists != b->hopCountTlvExists) {
456 return MPLS_BOOL_FALSE;
460 if (flag & LDP_ATTR_PATH) {
461 int i;
463 if (a->pathVecTlvExists && b->pathVecTlvExists) {
464 for (i = 0; i < MPLS_MAXHOPSNUMBER; i++) {
465 if (a->pathVecTlv.lsrId[i] != b->pathVecTlv.lsrId[i]) {
466 return MPLS_BOOL_FALSE;
469 } else {
470 if (a->hopCountTlvExists != b->hopCountTlvExists) {
471 return MPLS_BOOL_FALSE;
475 if (flag & LDP_ATTR_FEC) {
476 int i;
478 if (a->fecTlvExists && b->fecTlvExists) {
479 if (a->fecTlv.numberFecElements != b->fecTlv.numberFecElements) {
480 return MPLS_BOOL_FALSE;
482 for (i = 0; i < a->fecTlv.numberFecElements; i++) {
483 if (a->fecTlv.fecElemTypes[i] != b->fecTlv.fecElemTypes[i]) {
484 return MPLS_BOOL_FALSE;
486 switch (a->fecTlv.fecElemTypes[i]) {
487 case MPLS_CRLSP_FEC:
488 case MPLS_WC_FEC:
489 /* nothing of interest to compare */
490 break;
491 case MPLS_PREFIX_FEC:
492 case MPLS_HOSTADR_FEC:
493 if (a->fecTlv.fecElArray[i].addressEl.addressFam !=
494 b->fecTlv.fecElArray[i].addressEl.addressFam ||
495 a->fecTlv.fecElArray[i].addressEl.preLen !=
496 b->fecTlv.fecElArray[i].addressEl.preLen ||
497 a->fecTlv.fecElArray[i].addressEl.address !=
498 b->fecTlv.fecElArray[i].addressEl.address) {
499 return MPLS_BOOL_FALSE;
501 break;
502 default:
503 MPLS_ASSERT(0);
506 } else {
507 return MPLS_BOOL_FALSE;
510 if (flag & LDP_ATTR_MSGID) {
511 if (a->lblMsgIdTlvExists && b->lblMsgIdTlvExists) {
512 if (a->lblMsgIdTlv.msgId != b->lblMsgIdTlv.msgId) {
513 return MPLS_BOOL_FALSE;
515 } else {
516 return MPLS_BOOL_FALSE;
519 if (flag & LDP_ATTR_LSPID) {
520 if (a->lspidTlvExists && b->lspidTlvExists) {
521 if (a->lspidTlv.localCrlspId != b->lspidTlv.localCrlspId ||
522 a->lspidTlv.routerId != b->lspidTlv.routerId) {
523 return MPLS_BOOL_FALSE;
525 } else {
526 return MPLS_BOOL_FALSE;
529 if (flag & LDP_ATTR_TRAFFIC) {
531 return MPLS_BOOL_TRUE;
534 mpls_return_enum ldp_attr_insert_upstream(ldp_global * g, ldp_session * s,
535 ldp_attr * a)
537 ldp_fec *fnode = NULL;
538 ldp_fs *fs = NULL;
539 mpls_return_enum retval;
541 MPLS_ASSERT(a->in_tree == MPLS_BOOL_FALSE);
543 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_TRUE)) == NULL) {
544 /* we couldn't get/add a node from/to the tree! */
545 return MPLS_FAILURE;
548 /* find the upstream fs for this session */
549 if ((fs = _ldp_fec_find_fs_us(fnode, s, MPLS_BOOL_TRUE)) == NULL) {
550 /* this session isn't in the list and cannot be added */
551 return MPLS_FAILURE;
554 ldp_attr_add_session(a, s);
555 ldp_attr_add_fec(a, fnode);
557 retval = _ldp_fs_add_attr(fs, a);
558 _ldp_global_add_attr(g, a);
559 a->in_tree = MPLS_BOOL_TRUE;
560 return retval;
563 mpls_return_enum ldp_attr_insert_downstream(ldp_global * g, ldp_session * s,
564 ldp_attr * a)
566 ldp_fec *fnode = NULL;
567 ldp_fs *fs = NULL;
568 mpls_return_enum retval;
570 MPLS_ASSERT(a->in_tree == MPLS_BOOL_FALSE);
572 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_TRUE)) == NULL) {
573 /* we couldn't get/add a node from/to the tree! */
574 return MPLS_FAILURE;
577 /* find the downstream fs for this session */
578 if ((fs = _ldp_fec_find_fs_ds(fnode, s, MPLS_BOOL_TRUE)) == NULL) {
579 /* this session isn't in the list and cannot be added */
580 return MPLS_FAILURE;
583 ldp_attr_add_session(a, s);
584 ldp_attr_add_fec(a, fnode);
586 retval = _ldp_fs_add_attr(fs, a);
587 _ldp_global_add_attr(g, a);
588 a->in_tree = MPLS_BOOL_TRUE;
589 return retval;
592 ldp_attr_list *ldp_attr_find_upstream_all(ldp_global * g, ldp_session * s,
593 mpls_fec * f)
595 ldp_fec *fnode = NULL;
596 ldp_fs *fs = NULL;
598 MPLS_ASSERT(s && f && g);
600 if ((fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE)) == NULL) {
601 /* we couldn't get the node from the tree! */
602 return NULL;
605 /* find the upstream fs for this session */
606 if ((fs = _ldp_fec_find_fs_us(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
607 /* this session isn't in the list */
608 return NULL;
610 return &fs->attr_root;
613 ldp_attr_list *ldp_attr_find_downstream_all(ldp_global * g, ldp_session * s,
614 mpls_fec * f)
616 ldp_fec *fnode = NULL;
617 ldp_fs *fs = NULL;
619 MPLS_ASSERT(s && f && g);
621 if ((fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE)) == NULL) {
622 /* we couldn't get the node from the tree! */
623 return NULL;
626 /* find the downstream fs for this session */
627 if ((fs = _ldp_fec_find_fs_ds(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
628 /* this session isn't in the list */
629 return NULL;
631 return &fs->attr_root;
634 void ldp_attr_delete_upstream(ldp_global * g, ldp_session * s, ldp_attr * a)
636 ldp_fec *fnode = NULL;
637 ldp_fs *fs = NULL;
639 MPLS_ASSERT(a->in_tree == MPLS_BOOL_TRUE);
641 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_FALSE)) == NULL) {
642 /* we couldn't get the node from the tree! */
643 return;
646 /* find the upstream fs for this session */
647 if ((fs = _ldp_fec_find_fs_us(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
648 /* this session isn't in the list */
649 return;
652 ldp_attr_del_session(a);
653 ldp_attr_del_fec(a);
655 if (_ldp_fs_del_attr(fs, a) == MPLS_BOOL_TRUE) {
656 _ldp_fec_del_fs_us(fnode, fs);
658 a->in_tree = MPLS_BOOL_FALSE;
659 _ldp_global_del_attr(g, a);
662 void ldp_attr_delete_downstream(ldp_global * g, ldp_session * s, ldp_attr * a)
664 ldp_fec *fnode = NULL;
665 ldp_fs *fs = NULL;
667 MPLS_ASSERT(a->in_tree == MPLS_BOOL_TRUE);
669 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_FALSE)) == NULL) {
670 /* we couldn't get the node from the tree! */
671 return;
674 /* find the downstream fs for this session */
675 if ((fs = _ldp_fec_find_fs_ds(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
676 /* this session isn't in the list */
677 return;
680 ldp_attr_del_session(a);
681 ldp_attr_del_fec(a);
683 if (_ldp_fs_del_attr(fs, a) == MPLS_BOOL_TRUE) {
684 _ldp_fec_del_fs_ds(fnode, fs);
686 a->in_tree = MPLS_BOOL_FALSE;
687 _ldp_global_del_attr(g, a);
690 void ldp_attr2mpls_label_struct(ldp_attr * a, mpls_label_struct * l)
692 if (a->genLblTlvExists) {
693 l->type = MPLS_LABEL_TYPE_GENERIC;
694 l->u.gen = a->genLblTlv.label;
695 } else if (a->atmLblTlvExists) {
696 l->type = MPLS_LABEL_TYPE_ATM;
697 l->u.atm.vpi = a->atmLblTlv.flags.flags.vpi;
698 l->u.atm.vci = a->atmLblTlv.vci;
699 } else if (a->frLblTlvExists) {
700 l->type = MPLS_LABEL_TYPE_FR;
701 l->u.fr.len = a->frLblTlv.flags.flags.len;
702 l->u.fr.dlci = a->frLblTlv.flags.flags.dlci;
703 } else {
704 MPLS_ASSERT(0);
708 void mpls_label_struct2ldp_attr(mpls_label_struct * l, ldp_attr * a)
710 switch (l->type) {
711 case MPLS_LABEL_TYPE_GENERIC:
712 a->genLblTlvExists = 1;
713 a->atmLblTlvExists = 0;
714 a->frLblTlvExists = 0;
715 a->genLblTlv.label = l->u.gen;
716 break;
717 case MPLS_LABEL_TYPE_ATM:
718 a->genLblTlvExists = 0;
719 a->atmLblTlvExists = 1;
720 a->frLblTlvExists = 0;
721 a->atmLblTlv.flags.flags.vpi = l->u.atm.vpi;
722 a->atmLblTlv.vci = l->u.atm.vci;
723 case MPLS_LABEL_TYPE_FR:
724 a->genLblTlvExists = 0;
725 a->atmLblTlvExists = 0;
726 a->frLblTlvExists = 1;
727 a->frLblTlv.flags.flags.len = l->u.fr.len;
728 a->frLblTlv.flags.flags.dlci = l->u.fr.dlci;
729 default:
730 MPLS_ASSERT(0);
734 #if 0
735 void ldp_attr2ldp_attr(ldp_attr * src, ldp_attr * dst, u_int32 flag)
737 if (flag & LDP_ATTR_FEC) {
738 memcpy(&dst->fecTlv, &src->fecTlv, sizeof(mplsLdpFecTlv_t));
739 dst->fecTlvExists = src->fecTlvExists;
741 if (flag & LDP_ATTR_LABEL) {
742 memcpy(&dst->genLblTlv, &src->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
743 memcpy(&dst->atmLblTlv, &src->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
744 memcpy(&dst->frLblTlv, &src->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
745 dst->genLblTlvExists = src->genLblTlvExists
746 dst->atmLblTlvExists = src->atmLblTlvExists
747 dst->frLblTlvExists = src->frLblTlvExists}
748 if (flag & LDP_ATTR_HOPCOUNT) {
749 memcpy(&dst->hopCountTlv, &src->hopCountTlv, sizeof(mplsLdpHopTlv_t));
750 dst->hopCountTlvExists = src->hopCountTlvExists;
752 if (flag & LDP_ATTR_PATH) {
753 memcpy(&dst->pathVecTlv, &src->pathVecTlv, sizeof(mplsLdpPathTlv_t));
754 dst->pathVecTlvExists = src->pathVecTlvExists;
756 if (flag & LDP_ATTR_MSGID) {
757 memcpy(&dst->lblMsgIdTlv, &src->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
758 dst->lblMsgIdTlvExists = src->lblMsgIdTlvExists;
760 if (flag & LDP_ATTR_LSPID) {
761 memcpy(&dst->lspidTlv, &src->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
762 dst->lspidTlvExists = src->lspidTlvExists;
764 if (flag & LDP_ATTR_TRAFFIC) {
765 memcpy(&dst->trafficTlv, &src->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
766 dst->trafficTlvExists = src->trafficTlvExists;
769 #endif
771 ldp_fec *_ldp_attr_get_fec2(ldp_global * g, mpls_fec * f, mpls_bool flag)
773 ldp_fec *fnode = NULL;
774 uint32_t key;
775 uint8_t len;
777 switch(f->type) {
778 case MPLS_FEC_PREFIX:
779 key = f->u.prefix.network.u.ipv4;
780 len = f->u.prefix.length;
781 break;
782 case MPLS_FEC_HOST:
783 key = f->u.host.u.ipv4;
784 len = 32;
785 default:
786 return NULL;
789 if (mpls_tree_get(g->fec_tree, key, len, (void **)&fnode) ==
790 MPLS_FAILURE || fnode == NULL) {
792 if (flag == MPLS_BOOL_FALSE) {
793 return NULL;
796 /* this FEC doesn't exist in the tree yet, create one ... */
797 fnode = ldp_fec_create();
798 mpls_fec2ldp_fec(f, fnode);
799 if (f->nh.type & MPLS_NH_IP) {
800 fnode->nh.addr = NULL;
801 mpls_tree_get(g->addr_tree, f->nh.ip.u.ipv4, 32, (void**)&fnode->nh.addr);
802 if (fnode->nh.addr) {
803 fnode->nh.type |= MPLS_NH_IP;
806 if (f->nh.type & MPLS_NH_IF) {
807 fnode->nh.iff = ldp_global_find_if_handle(g, f->nh.if_handle);
808 if (fnode->nh.iff) {
809 fnode->nh.type |= MPLS_NH_IF;
812 if (f->nh.type & MPLS_NH_OUTSEGMENT) {
813 fnode->nh.outlabel = ldp_global_find_outlabel_handle(g,
814 f->nh.outsegment_handle);
815 if (fnode->nh.outlabel) {
816 fnode->nh.type |= MPLS_NH_OUTSEGMENT;
819 MPLS_REFCNT_HOLD(fnode);
821 /* ... add it to the tree ... */
822 if (mpls_tree_insert(g->fec_tree,key,len,(void *)fnode) == MPLS_FAILURE) {
823 /* insert failed, by releasing our refcnt it will be deleted */
824 MPLS_REFCNT_RELEASE(fnode, ldp_fec_delete);
825 return NULL;
828 return fnode;
831 static ldp_fec *_ldp_attr_get_fec(ldp_global * g, ldp_attr * a, mpls_bool flag)
833 mpls_fec fec;
835 /* get FEC from attr */
836 fec_tlv2mpls_fec(&a->fecTlv, 0, &fec);
837 return _ldp_attr_get_fec2(g, &fec, flag);
840 static ldp_fs *_ldp_fec_add_fs_ds(ldp_fec * fec, ldp_session * s)
842 ldp_fs *fs = _ldp_fec_find_fs_ds(fec, s, MPLS_BOOL_FALSE);
844 if (fs == NULL) {
845 fs = _ldp_fs_create(s);
846 if (fs == NULL) {
847 return NULL;
849 MPLS_LIST_ADD_HEAD(&fec->fs_root_ds, fs, _fec, ldp_fs);
851 return fs;
854 static ldp_fs *_ldp_fec_add_fs_us(ldp_fec * fec, ldp_session * s)
856 ldp_fs *fs = _ldp_fec_find_fs_us(fec, s, MPLS_BOOL_FALSE);
858 if (fs == NULL) {
859 fs = _ldp_fs_create(s);
860 if (fs == NULL) {
861 return NULL;
863 MPLS_LIST_ADD_HEAD(&fec->fs_root_us, fs, _fec, ldp_fs);
865 return fs;
868 static ldp_fs *_ldp_fec_find_fs_us(ldp_fec * fec, ldp_session * s,
869 mpls_bool flag)
871 ldp_fs *fs = MPLS_LIST_HEAD(&fec->fs_root_us);
873 while (fs != NULL) {
874 if (fs->session->index == s->index) {
875 return fs;
877 fs = MPLS_LIST_NEXT(&fec->fs_root_us, fs, _fec);
879 if (flag == MPLS_BOOL_FALSE) {
880 return NULL;
882 return _ldp_fec_add_fs_us(fec, s);
885 static ldp_fs *_ldp_fec_find_fs_ds(ldp_fec * fec, ldp_session * s,
886 mpls_bool flag)
888 ldp_fs *fs = MPLS_LIST_HEAD(&fec->fs_root_ds);
890 while (fs != NULL) {
891 if (fs->session->index == s->index) {
892 return fs;
894 fs = MPLS_LIST_NEXT(&fec->fs_root_ds, fs, _fec);
896 if (flag == MPLS_BOOL_FALSE) {
897 return NULL;
899 return _ldp_fec_add_fs_ds(fec, s);
902 static void _ldp_fec_del_fs_us(ldp_fec * fec, ldp_fs * fs)
904 if (fs == NULL) {
905 return;
907 MPLS_LIST_REMOVE(&fec->fs_root_us, fs, _fec);
908 _ldp_fs_delete(fs);
911 static void _ldp_fec_del_fs_ds(ldp_fec * fec, ldp_fs * fs)
913 if (fs == NULL) {
914 return;
916 MPLS_LIST_REMOVE(&fec->fs_root_ds, fs, _fec);
917 _ldp_fs_delete(fs);
920 static ldp_fs *_ldp_fs_create(ldp_session * s)
922 ldp_fs *fs = (ldp_fs *) mpls_malloc(sizeof(ldp_fs));
924 if (fs != NULL) {
925 memset(fs, 0, sizeof(ldp_fs));
926 MPLS_LIST_INIT(&fs->attr_root, ldp_attr);
927 MPLS_LIST_ELEM_INIT(fs, _fec);
928 if (s != NULL) {
929 MPLS_REFCNT_HOLD(s);
930 fs->session = s;
933 return fs;
936 static void _ldp_fs_delete(ldp_fs * fs)
938 LDP_PRINT(g->user_data,"fs delete\n");
939 if (fs->session != NULL) {
940 MPLS_REFCNT_RELEASE(fs->session, ldp_session_delete);
942 mpls_free(fs);
945 static ldp_attr *_ldp_fs_find_attr(ldp_fs * fs, ldp_attr * a)
947 ldp_attr *ptr = MPLS_LIST_HEAD(&fs->attr_root);
949 while (ptr != NULL) {
950 if (ldp_attr_is_equal(a, ptr, LDP_ATTR_LABEL | LDP_ATTR_FEC) == MPLS_BOOL_TRUE) {
951 return ptr;
953 ptr = MPLS_LIST_NEXT(&fs->attr_root, ptr, _fs);
955 return NULL;
958 static mpls_return_enum _ldp_fs_add_attr(ldp_fs * fs, ldp_attr * a)
960 ldp_attr *ptr = _ldp_fs_find_attr(fs, a);
962 MPLS_ASSERT(ptr == NULL);
963 MPLS_REFCNT_HOLD(a);
964 MPLS_LIST_ADD_HEAD(&fs->attr_root, a, _fs, ldp_attr);
965 return MPLS_SUCCESS;
968 static mpls_bool _ldp_fs_del_attr(ldp_fs * fs, ldp_attr * a)
970 ldp_attr *ptr = _ldp_fs_find_attr(fs, a);
972 if (ptr != NULL) {
973 MPLS_LIST_REMOVE(&fs->attr_root, ptr, _fs);
974 MPLS_REFCNT_RELEASE(ptr, ldp_attr_delete);
976 if (MPLS_LIST_HEAD(&fs->attr_root) == NULL)
977 return MPLS_BOOL_TRUE;
978 return MPLS_BOOL_FALSE;
981 static uint32_t _ldp_attr_get_next_index()
983 uint32_t retval = _ldp_attr_next_index;
985 _ldp_attr_next_index++;
986 if (retval > _ldp_attr_next_index) {
987 _ldp_attr_next_index = 1;
989 return retval;