Changed the relationship between entity-adj-sessios (again)
[mpls-ldp-portable.git] / ldp / ldp_attr.c
blobbb7eed711a13cc7c4a9b5f4925c179d5c69d4db3
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_fec2(ldp_global * g, mpls_fec * f, mpls_bool flag);
30 static ldp_fec *_ldp_attr_get_fec(ldp_global * g, ldp_attr * a, mpls_bool flag);
31 static ldp_fs *_ldp_fec_add_fs_ds(ldp_fec * fec, ldp_session * s);
32 static ldp_fs *_ldp_fec_add_fs_us(ldp_fec * fec, ldp_session * s);
33 static ldp_fs *_ldp_fec_find_fs_us(ldp_fec * fec, ldp_session * s,
34 mpls_bool flag);
35 static ldp_fs *_ldp_fec_find_fs_ds(ldp_fec * fec, ldp_session * s,
36 mpls_bool flag);
37 static void _ldp_fec_del_fs_us(ldp_fec * fec, ldp_fs * fs);
38 static void _ldp_fec_del_fs_ds(ldp_fec * fec, ldp_fs * fs);
39 static ldp_fs *_ldp_fs_create(ldp_session * s);
40 static void _ldp_fs_delete(ldp_fs * fs);
41 static ldp_attr *_ldp_fs_find_attr(ldp_fs * fs, ldp_attr * a);
42 static mpls_return_enum _ldp_fs_add_attr(ldp_fs * fs, ldp_attr * a);
43 static mpls_bool _ldp_fs_del_attr(ldp_fs * fs, ldp_attr * a);
44 static uint32_t _ldp_attr_get_next_index();
46 static uint32_t _ldp_attr_next_index = 1;
48 int ldp_attr_num_us2ds(ldp_attr * ds)
50 ldp_attr *attr = NULL;
51 int count = 0;
53 attr = MPLS_LIST_HEAD(&ds->us_attr_root);
54 while (attr) {
55 count++;
56 attr = MPLS_LIST_NEXT(&ds->us_attr_root, attr, _ds_attr);
58 return count;
61 mpls_bool ldp_attr_us_partof_ds(ldp_attr * us, ldp_attr * ds)
63 if (us->ds_attr == ds) {
64 return MPLS_BOOL_TRUE;
66 return MPLS_BOOL_FALSE;
69 void ldp_attr_del_us2ds(ldp_attr * us, ldp_attr * ds)
71 if (!us || !ds) {
72 return;
74 if (ldp_attr_us_partof_ds(us, ds) == MPLS_BOOL_TRUE) {
75 us->ds_attr = NULL;
76 MPLS_REFCNT_RELEASE(ds, ldp_attr_delete);
77 MPLS_LIST_REMOVE(&ds->us_attr_root, us, _ds_attr);
78 MPLS_REFCNT_RELEASE(us, ldp_attr_delete);
79 } else {
80 MPLS_ASSERT(0);
84 void ldp_attr_add_us2ds(ldp_attr * us, ldp_attr * ds)
87 if (!us || !ds) {
88 return;
90 if (ldp_attr_us_partof_ds(us, ds) == MPLS_BOOL_TRUE) {
91 return;
93 MPLS_REFCNT_HOLD(us);
94 MPLS_LIST_ADD_TAIL(&ds->us_attr_root, us, _ds_attr, ldp_attr);
95 MPLS_REFCNT_HOLD(ds);
96 us->ds_attr = ds;
99 void ldp_attr_action_callback(mpls_timer_handle timer, void *extra,
100 mpls_cfg_handle g)
104 ldp_attr *ldp_attr_find_downstream_state_any(ldp_global * g, mpls_fec * f,
105 ldp_lsp_state state)
107 ldp_fec *fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE);
108 ldp_attr *attr = NULL;
109 ldp_fs *fs = NULL;
111 if (!fnode) {
112 return NULL;
115 fs = MPLS_LIST_HEAD(&fnode->fs_root_ds);
116 while (fs != NULL) {
117 attr = MPLS_LIST_HEAD(&fs->attr_root);
118 while (attr != NULL) {
119 if (attr->state == state) {
120 return attr;
122 attr = MPLS_LIST_NEXT(&fs->attr_root, attr, _fs);
124 fs = MPLS_LIST_NEXT(&fnode->fs_root_ds, fs, _fec);
126 return NULL;
129 ldp_attr *ldp_attr_find_upstream_state_any(ldp_global * g, mpls_fec * f,
130 ldp_lsp_state state)
132 ldp_fec *fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE);
133 ldp_attr *attr = NULL;
134 ldp_fs *fs = NULL;
136 if (!fnode) {
137 return NULL;
140 fs = MPLS_LIST_HEAD(&fnode->fs_root_us);
141 while (fs != NULL) {
142 attr = MPLS_LIST_HEAD(&fs->attr_root);
143 while (attr != NULL) {
144 if (attr->state == state) {
145 return attr;
147 attr = MPLS_LIST_NEXT(&fs->attr_root, attr, _fs);
149 fs = MPLS_LIST_NEXT(&fnode->fs_root_us, fs, _fec);
151 return NULL;
154 ldp_attr *ldp_attr_find_downstream_state(ldp_global * g, ldp_session * s,
155 mpls_fec * f, ldp_lsp_state state)
157 ldp_attr_list *ds_list = ldp_attr_find_downstream_all(g, s, f);
159 if (ds_list != NULL) {
160 ldp_attr *ds_attr = MPLS_LIST_HEAD(ds_list);
162 while (ds_attr != NULL) {
163 if (ds_attr->state == state) {
164 return ds_attr;
166 ds_attr = MPLS_LIST_NEXT(ds_list, ds_attr, _fs);
169 return NULL;
172 ldp_attr *ldp_attr_find_upstream_state(ldp_global * g, ldp_session * s,
173 mpls_fec * f, ldp_lsp_state state)
175 ldp_attr_list *us_list = ldp_attr_find_upstream_all(g, s, f);
177 if (us_list != NULL) {
178 ldp_attr *us_attr = MPLS_LIST_HEAD(us_list);
180 while (us_attr != NULL) {
181 if (us_attr->state == state) {
182 return us_attr;
184 us_attr = MPLS_LIST_NEXT(us_list, us_attr, _fs);
187 return NULL;
190 void ldp_attr_remove_complete(ldp_global * g, ldp_attr * attr,
191 mpls_bool complete)
193 ldp_session *session = attr->session;
194 ldp_outlabel *out = NULL;
195 ldp_inlabel *in = NULL;
196 ldp_attr *us_temp = NULL;
197 mpls_fec fec;
198 int i;
200 switch (attr->state) {
201 case LDP_LSP_STATE_MAP_RECV:
202 if (attr->ingress == MPLS_BOOL_TRUE) {
203 out = attr->outlabel;
204 MPLS_ASSERT(out != NULL);
205 while ((in = MPLS_LIST_HEAD(&out->inlabel_root)) != NULL) {
206 ldp_inlabel_del_outlabel(g, in);
209 if (out->merge_count > 0) {
210 for (i = 0; i < attr->fecTlv.numberFecElements; i++) {
211 fec_tlv2mpls_fec(&attr->fecTlv, i, &fec);
212 out->merge_count--;
213 #if MPLS_USE_LSR
215 lsr_ftn ftn;
216 memcpy(&ftn.fec, &fec, sizeof(mpls_fec));
217 ftn.outsegment_index = out->info.handle;
218 lsr_cfg_ftn_set2(g->lsr_handle, &ftn, LSR_CFG_DEL);
220 #else
221 mpls_mpls_fec2out_del(g->mpls_handle, &fec, &out->info);
222 #endif
225 MPLS_ASSERT(out->merge_count == 0);
226 ldp_attr_del_outlabel(attr);
227 ldp_session_del_outlabel(session, out);
228 _ldp_global_del_outlabel(g, out);
230 while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
231 ldp_attr_del_us2ds(us_temp, attr);
233 ldp_attr_delete_downstream(g, session, attr);
234 break;
235 case LDP_LSP_STATE_MAP_SENT:
236 in = attr->inlabel;
237 out = in->outlabel;
239 if (out != NULL) {
240 if (in->reuse_count == 1) {
241 ldp_inlabel_del_outlabel(g, in);
245 ldp_attr_del_inlabel(attr);
246 ldp_attr_delete_upstream(g, session, attr);
247 ldp_attr_del_us2ds(attr, attr->ds_attr);
248 ldp_session_del_inlabel(session, in);
250 if (in->reuse_count == 0) {
251 _ldp_global_del_inlabel(g, in);
253 break;
254 case LDP_LSP_STATE_ABORT_SENT:
255 case LDP_LSP_STATE_NOTIF_SENT:
256 case LDP_LSP_STATE_REQ_RECV:
257 case LDP_LSP_STATE_WITH_SENT:
258 case LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT:
260 ldp_attr_del_us2ds(attr, attr->ds_attr);
261 ldp_attr_delete_upstream(g, session, attr);
262 break;
264 case LDP_LSP_STATE_ABORT_RECV:
265 case LDP_LSP_STATE_NOTIF_RECV:
266 case LDP_LSP_STATE_REQ_SENT:
267 case LDP_LSP_STATE_WITH_RECV:
268 case LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV:
270 while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
271 ldp_attr_del_us2ds(us_temp, attr);
273 ldp_attr_delete_downstream(g, session, attr);
274 break;
279 ldp_attr *ldp_attr_create(mpls_fec * fec)
281 ldp_attr *a = (ldp_attr *) mpls_malloc(sizeof(ldp_attr));
283 if (a != NULL) {
284 memset(a, 0, sizeof(ldp_attr));
285 MPLS_LIST_ELEM_INIT(a, _session);
286 MPLS_LIST_ELEM_INIT(a, _global);
287 MPLS_LIST_ELEM_INIT(a, _fs);
288 MPLS_LIST_INIT(&a->us_attr_root, ldp_attr);
289 MPLS_REFCNT_INIT(a, 0);
290 a->index = _ldp_attr_get_next_index();
291 a->in_tree = MPLS_BOOL_FALSE;
292 a->ingress = MPLS_BOOL_FALSE;
293 a->filtered = MPLS_BOOL_FALSE;
295 if (fec != NULL) {
296 mpls_fec2fec_tlv(fec, &a->fecTlv, 0);
297 a->fecTlv.numberFecElements = 1;
298 a->fecTlvExists = 1;
301 return a;
304 void ldp_attr_delete(ldp_attr * a)
306 LDP_PRINT(g->user_data,"attr delete\n");
307 MPLS_ASSERT(a->in_tree == MPLS_BOOL_FALSE);
308 mpls_free(a);
311 void ldp_attr2ldp_attr(ldp_attr * a, ldp_attr * b, uint32_t flag)
313 if (a->fecTlvExists && flag & LDP_ATTR_FEC) {
314 memcpy(&b->fecTlv, &a->fecTlv, sizeof(mplsLdpFecTlv_t));
315 b->fecTlvExists = 1;
317 if (a->genLblTlvExists && flag & LDP_ATTR_LABEL) {
318 memcpy(&b->genLblTlv, &a->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
319 b->genLblTlvExists = 1;
320 } else if (a->atmLblTlvExists && flag & LDP_ATTR_LABEL) {
321 memcpy(&b->atmLblTlv, &a->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
322 b->atmLblTlvExists = 1;
323 } else if (a->frLblTlvExists && flag & LDP_ATTR_LABEL) {
324 memcpy(&b->frLblTlv, &a->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
325 b->frLblTlvExists = 1;
327 if (a->hopCountTlvExists && flag & LDP_ATTR_HOPCOUNT) {
328 memcpy(&b->hopCountTlv, &a->hopCountTlv, sizeof(mplsLdpHopTlv_t));
329 b->hopCountTlvExists = 1;
331 if (a->pathVecTlvExists && flag & LDP_ATTR_PATH) {
332 memcpy(&b->pathVecTlv, &a->pathVecTlv, sizeof(mplsLdpPathTlv_t));
333 b->pathVecTlvExists = 1;
335 if (a->lblMsgIdTlvExists && flag & LDP_ATTR_MSGID) {
336 memcpy(&b->lblMsgIdTlv, &a->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
337 b->lblMsgIdTlvExists = 1;
339 if (a->lspidTlvExists && flag & LDP_ATTR_LSPID) {
340 memcpy(&b->lspidTlv, &a->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
341 b->lspidTlvExists = 1;
343 if (a->trafficTlvExists && flag & LDP_ATTR_TRAFFIC) {
344 memcpy(&b->trafficTlv, &a->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
345 b->trafficTlvExists = 1;
349 mpls_return_enum ldp_attr_add_inlabel(ldp_attr * a, ldp_inlabel * i)
351 if (a && i) {
352 MPLS_REFCNT_HOLD(i);
353 a->inlabel = i;
354 _ldp_inlabel_add_attr(i, a);
355 return MPLS_SUCCESS;
357 return MPLS_FAILURE;
360 mpls_return_enum ldp_attr_del_inlabel(ldp_attr * a)
362 if (a && a->inlabel) {
363 _ldp_inlabel_del_attr(a->inlabel, a);
364 MPLS_REFCNT_RELEASE(a->inlabel, ldp_inlabel_delete);
365 a->inlabel = NULL;
366 return MPLS_SUCCESS;
368 return MPLS_FAILURE;
371 mpls_return_enum ldp_attr_add_outlabel(ldp_attr * a, ldp_outlabel * o)
373 if (a && o) {
374 MPLS_REFCNT_HOLD(o);
375 a->outlabel = o;
376 _ldp_outlabel_add_attr(o, a);
377 return MPLS_SUCCESS;
379 return MPLS_FAILURE;
382 mpls_return_enum ldp_attr_del_outlabel(ldp_attr * a)
384 if (a && a->outlabel) {
385 _ldp_outlabel_del_attr(a->outlabel);
386 MPLS_REFCNT_RELEASE(a->outlabel, ldp_outlabel_delete);
387 a->outlabel = NULL;
388 return MPLS_SUCCESS;
390 return MPLS_FAILURE;
393 mpls_return_enum ldp_attr_add_session(ldp_attr * a, ldp_session * s)
395 if (a && s) {
396 MPLS_REFCNT_HOLD(s);
397 a->session = s;
398 _ldp_session_add_attr(s, a);
399 return MPLS_SUCCESS;
401 return MPLS_FAILURE;
404 mpls_return_enum ldp_attr_del_session(ldp_attr * a)
406 if (a && a->session) {
407 _ldp_session_del_attr(a->session, a);
408 MPLS_REFCNT_RELEASE(a->session, ldp_session_delete);
409 a->session = NULL;
410 return MPLS_SUCCESS;
412 return MPLS_FAILURE;
415 mpls_bool ldp_attr_is_equal(ldp_attr * a, ldp_attr * b, uint32_t flag)
417 if (flag & LDP_ATTR_LABEL) {
418 if (a->genLblTlvExists && b->genLblTlvExists) {
419 if (a->genLblTlv.label != b->genLblTlv.label) {
420 return MPLS_BOOL_FALSE;
422 } else if (a->atmLblTlvExists && b->atmLblTlvExists) {
423 if (a->atmLblTlv.flags.flags.vpi != b->atmLblTlv.flags.flags.vpi ||
424 a->atmLblTlv.vci != b->atmLblTlv.vci) {
425 return MPLS_BOOL_FALSE;
427 } else if (a->frLblTlvExists && b->frLblTlvExists) {
428 if (a->frLblTlv.flags.flags.len != b->frLblTlv.flags.flags.len ||
429 a->frLblTlv.flags.flags.dlci != b->frLblTlv.flags.flags.dlci) {
430 return MPLS_BOOL_FALSE;
432 } else {
433 return MPLS_BOOL_FALSE;
436 if (flag & LDP_ATTR_HOPCOUNT) {
437 if (a->hopCountTlvExists && b->hopCountTlvExists) {
438 if (a->hopCountTlv.hcValue != b->hopCountTlv.hcValue) {
439 return MPLS_BOOL_FALSE;
441 } else {
442 if (a->hopCountTlvExists != b->hopCountTlvExists) {
443 return MPLS_BOOL_FALSE;
447 if (flag & LDP_ATTR_PATH) {
448 int i;
450 if (a->pathVecTlvExists && b->pathVecTlvExists) {
451 for (i = 0; i < MPLS_MAXHOPSNUMBER; i++) {
452 if (a->pathVecTlv.lsrId[i] != b->pathVecTlv.lsrId[i]) {
453 return MPLS_BOOL_FALSE;
456 } else {
457 if (a->hopCountTlvExists != b->hopCountTlvExists) {
458 return MPLS_BOOL_FALSE;
462 if (flag & LDP_ATTR_FEC) {
463 int i;
465 if (a->fecTlvExists && b->fecTlvExists) {
466 if (a->fecTlv.numberFecElements != b->fecTlv.numberFecElements) {
467 return MPLS_BOOL_FALSE;
469 for (i = 0; i < a->fecTlv.numberFecElements; i++) {
470 if (a->fecTlv.fecElemTypes[i] != b->fecTlv.fecElemTypes[i]) {
471 return MPLS_BOOL_FALSE;
473 switch (a->fecTlv.fecElemTypes[i]) {
474 case MPLS_CRLSP_FEC:
475 case MPLS_WC_FEC:
476 /* nothing of interest to compare */
477 break;
478 case MPLS_PREFIX_FEC:
479 case MPLS_HOSTADR_FEC:
480 if (a->fecTlv.fecElArray[i].addressEl.addressFam !=
481 b->fecTlv.fecElArray[i].addressEl.addressFam ||
482 a->fecTlv.fecElArray[i].addressEl.preLen !=
483 b->fecTlv.fecElArray[i].addressEl.preLen ||
484 a->fecTlv.fecElArray[i].addressEl.address !=
485 b->fecTlv.fecElArray[i].addressEl.address) {
486 return MPLS_BOOL_FALSE;
488 break;
489 default:
490 MPLS_ASSERT(0);
493 } else {
494 return MPLS_BOOL_FALSE;
497 if (flag & LDP_ATTR_MSGID) {
498 if (a->lblMsgIdTlvExists && b->lblMsgIdTlvExists) {
499 if (a->lblMsgIdTlv.msgId != b->lblMsgIdTlv.msgId) {
500 return MPLS_BOOL_FALSE;
502 } else {
503 return MPLS_BOOL_FALSE;
506 if (flag & LDP_ATTR_LSPID) {
507 if (a->lspidTlvExists && b->lspidTlvExists) {
508 if (a->lspidTlv.localCrlspId != b->lspidTlv.localCrlspId ||
509 a->lspidTlv.routerId != b->lspidTlv.routerId) {
510 return MPLS_BOOL_FALSE;
512 } else {
513 return MPLS_BOOL_FALSE;
516 if (flag & LDP_ATTR_TRAFFIC) {
518 return MPLS_BOOL_TRUE;
521 mpls_return_enum ldp_attr_insert_upstream(ldp_global * g, ldp_session * s,
522 ldp_attr * a)
524 ldp_fec *fnode = NULL;
525 ldp_fs *fs = NULL;
526 mpls_return_enum retval;
528 MPLS_ASSERT(a->in_tree == MPLS_BOOL_FALSE);
530 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_TRUE)) == NULL) {
531 /* we couldn't get/add a node from/to the tree! */
532 return MPLS_FAILURE;
535 /* find the upstream fs for this session */
536 if ((fs = _ldp_fec_find_fs_us(fnode, s, MPLS_BOOL_TRUE)) == NULL) {
537 /* this session isn't in the list and cannot be added */
538 return MPLS_FAILURE;
541 ldp_attr_add_session(a, s);
543 retval = _ldp_fs_add_attr(fs, a);
544 _ldp_global_add_attr(g, a);
545 a->in_tree = MPLS_BOOL_TRUE;
546 return retval;
549 mpls_return_enum ldp_attr_insert_downstream(ldp_global * g, ldp_session * s,
550 ldp_attr * a)
552 ldp_fec *fnode = NULL;
553 ldp_fs *fs = NULL;
554 mpls_return_enum retval;
556 MPLS_ASSERT(a->in_tree == MPLS_BOOL_FALSE);
558 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_TRUE)) == NULL) {
559 /* we couldn't get/add a node from/to the tree! */
560 return MPLS_FAILURE;
563 /* find the downstream fs for this session */
564 if ((fs = _ldp_fec_find_fs_ds(fnode, s, MPLS_BOOL_TRUE)) == NULL) {
565 /* this session isn't in the list and cannot be added */
566 return MPLS_FAILURE;
569 ldp_attr_add_session(a, s);
571 retval = _ldp_fs_add_attr(fs, a);
572 _ldp_global_add_attr(g, a);
573 a->in_tree = MPLS_BOOL_TRUE;
574 return retval;
577 ldp_attr_list *ldp_attr_find_upstream_all(ldp_global * g, ldp_session * s,
578 mpls_fec * f)
580 ldp_fec *fnode = NULL;
581 ldp_fs *fs = NULL;
583 MPLS_ASSERT(s && f && g);
585 if ((fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE)) == NULL) {
586 /* we couldn't get the node from the tree! */
587 return NULL;
590 /* find the upstream fs for this session */
591 if ((fs = _ldp_fec_find_fs_us(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
592 /* this session isn't in the list */
593 return NULL;
595 return &fs->attr_root;
598 ldp_attr_list *ldp_attr_find_downstream_all(ldp_global * g, ldp_session * s,
599 mpls_fec * f)
601 ldp_fec *fnode = NULL;
602 ldp_fs *fs = NULL;
604 MPLS_ASSERT(s && f && g);
606 if ((fnode = _ldp_attr_get_fec2(g, f, MPLS_BOOL_FALSE)) == NULL) {
607 /* we couldn't get the node from the tree! */
608 return NULL;
611 /* find the downstream fs for this session */
612 if ((fs = _ldp_fec_find_fs_ds(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
613 /* this session isn't in the list */
614 return NULL;
616 return &fs->attr_root;
619 void ldp_attr_delete_upstream(ldp_global * g, ldp_session * s, ldp_attr * a)
621 ldp_fec *fnode = NULL;
622 ldp_fs *fs = NULL;
624 MPLS_ASSERT(a->in_tree == MPLS_BOOL_TRUE);
626 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_FALSE)) == NULL) {
627 /* we couldn't get the node from the tree! */
628 return;
631 /* find the upstream fs for this session */
632 if ((fs = _ldp_fec_find_fs_us(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
633 /* this session isn't in the list */
634 return;
637 ldp_attr_del_session(a);
639 if (_ldp_fs_del_attr(fs, a) == MPLS_BOOL_TRUE) {
640 _ldp_fec_del_fs_us(fnode, fs);
642 a->in_tree = MPLS_BOOL_FALSE;
643 _ldp_global_del_attr(g, a);
646 void ldp_attr_delete_downstream(ldp_global * g, ldp_session * s, ldp_attr * a)
648 ldp_fec *fnode = NULL;
649 ldp_fs *fs = NULL;
651 MPLS_ASSERT(a->in_tree == MPLS_BOOL_TRUE);
653 if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_FALSE)) == NULL) {
654 /* we couldn't get the node from the tree! */
655 return;
658 /* find the downstream fs for this session */
659 if ((fs = _ldp_fec_find_fs_ds(fnode, s, MPLS_BOOL_FALSE)) == NULL) {
660 /* this session isn't in the list */
661 return;
664 ldp_attr_del_session(a);
666 if (_ldp_fs_del_attr(fs, a) == MPLS_BOOL_TRUE) {
667 _ldp_fec_del_fs_ds(fnode, fs);
669 a->in_tree = MPLS_BOOL_FALSE;
670 _ldp_global_del_attr(g, a);
673 void ldp_attr2mpls_label_struct(ldp_attr * a, mpls_label_struct * l)
675 if (a->genLblTlvExists) {
676 l->type = MPLS_LABEL_TYPE_GENERIC;
677 l->u.gen = a->genLblTlv.label;
678 } else if (a->atmLblTlvExists) {
679 l->type = MPLS_LABEL_TYPE_ATM;
680 l->u.atm.vpi = a->atmLblTlv.flags.flags.vpi;
681 l->u.atm.vci = a->atmLblTlv.vci;
682 } else if (a->frLblTlvExists) {
683 l->type = MPLS_LABEL_TYPE_FR;
684 l->u.fr.len = a->frLblTlv.flags.flags.len;
685 l->u.fr.dlci = a->frLblTlv.flags.flags.dlci;
686 } else {
687 MPLS_ASSERT(0);
691 void mpls_label_struct2ldp_attr(mpls_label_struct * l, ldp_attr * a)
693 switch (l->type) {
694 case MPLS_LABEL_TYPE_GENERIC:
695 a->genLblTlvExists = 1;
696 a->atmLblTlvExists = 0;
697 a->frLblTlvExists = 0;
698 a->genLblTlv.label = l->u.gen;
699 break;
700 case MPLS_LABEL_TYPE_ATM:
701 a->genLblTlvExists = 0;
702 a->atmLblTlvExists = 1;
703 a->frLblTlvExists = 0;
704 a->atmLblTlv.flags.flags.vpi = l->u.atm.vpi;
705 a->atmLblTlv.vci = l->u.atm.vci;
706 case MPLS_LABEL_TYPE_FR:
707 a->genLblTlvExists = 0;
708 a->atmLblTlvExists = 0;
709 a->frLblTlvExists = 1;
710 a->frLblTlv.flags.flags.len = l->u.fr.len;
711 a->frLblTlv.flags.flags.dlci = l->u.fr.dlci;
712 default:
713 MPLS_ASSERT(0);
717 #if 0
718 void ldp_attr2ldp_attr(ldp_attr * src, ldp_attr * dst, u_int32 flag)
720 if (flag & LDP_ATTR_FEC) {
721 memcpy(&dst->fecTlv, &src->fecTlv, sizeof(mplsLdpFecTlv_t));
722 dst->fecTlvExists = src->fecTlvExists;
724 if (flag & LDP_ATTR_LABEL) {
725 memcpy(&dst->genLblTlv, &src->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
726 memcpy(&dst->atmLblTlv, &src->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
727 memcpy(&dst->frLblTlv, &src->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
728 dst->genLblTlvExists = src->genLblTlvExists
729 dst->atmLblTlvExists = src->atmLblTlvExists
730 dst->frLblTlvExists = src->frLblTlvExists}
731 if (flag & LDP_ATTR_HOPCOUNT) {
732 memcpy(&dst->hopCountTlv, &src->hopCountTlv, sizeof(mplsLdpHopTlv_t));
733 dst->hopCountTlvExists = src->hopCountTlvExists;
735 if (flag & LDP_ATTR_PATH) {
736 memcpy(&dst->pathVecTlv, &src->pathVecTlv, sizeof(mplsLdpPathTlv_t));
737 dst->pathVecTlvExists = src->pathVecTlvExists;
739 if (flag & LDP_ATTR_MSGID) {
740 memcpy(&dst->lblMsgIdTlv, &src->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
741 dst->lblMsgIdTlvExists = src->lblMsgIdTlvExists;
743 if (flag & LDP_ATTR_LSPID) {
744 memcpy(&dst->lspidTlv, &src->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
745 dst->lspidTlvExists = src->lspidTlvExists;
747 if (flag & LDP_ATTR_TRAFFIC) {
748 memcpy(&dst->trafficTlv, &src->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
749 dst->trafficTlvExists = src->trafficTlvExists;
752 #endif
754 static ldp_fec *_ldp_attr_get_fec2(ldp_global * g, mpls_fec * f, mpls_bool flag)
756 ldp_fec *fnode = NULL;
757 uint32_t key;
758 uint8_t len;
760 switch(f->type) {
761 case MPLS_FEC_PREFIX:
762 key = f->u.prefix.network.u.ipv4;
763 len = f->u.prefix.length;
764 break;
765 case MPLS_FEC_HOST:
766 key = f->u.host.u.ipv4;
767 len = 32;
768 default:
769 return NULL;
772 if (mpls_tree_get(g->fec_tree, key, len, (void **)&fnode) ==
773 MPLS_FAILURE || fnode == NULL) {
775 if (flag == MPLS_BOOL_FALSE) {
776 return NULL;
779 /* this FEC doesn't exist in the tree yet, create one ... */
780 fnode = ldp_fec_create();
781 mpls_fec2ldp_fec(f, fnode);
782 MPLS_REFCNT_HOLD(fnode);
784 /* ... add it to the tree ... */
785 if (mpls_tree_insert(g->fec_tree,key,len,(void *)fnode) == MPLS_FAILURE) {
786 /* insert failed, by releasing our refcnt it will be deleted */
787 MPLS_REFCNT_RELEASE(fnode, ldp_fec_delete);
788 return NULL;
791 return fnode;
794 static ldp_fec *_ldp_attr_get_fec(ldp_global * g, ldp_attr * a, mpls_bool flag)
796 mpls_fec fec;
798 /* get FEC from attr */
799 fec_tlv2mpls_fec(&a->fecTlv, 0, &fec);
800 return _ldp_attr_get_fec2(g, &fec, flag);
803 static ldp_fs *_ldp_fec_add_fs_ds(ldp_fec * fec, ldp_session * s)
805 ldp_fs *fs = _ldp_fec_find_fs_ds(fec, s, MPLS_BOOL_FALSE);
807 if (fs == NULL) {
808 fs = _ldp_fs_create(s);
809 if (fs == NULL) {
810 return NULL;
812 MPLS_LIST_ADD_HEAD(&fec->fs_root_ds, fs, _fec, ldp_fs);
814 return fs;
817 static ldp_fs *_ldp_fec_add_fs_us(ldp_fec * fec, ldp_session * s)
819 ldp_fs *fs = _ldp_fec_find_fs_us(fec, s, MPLS_BOOL_FALSE);
821 if (fs == NULL) {
822 fs = _ldp_fs_create(s);
823 if (fs == NULL) {
824 return NULL;
826 MPLS_LIST_ADD_HEAD(&fec->fs_root_us, fs, _fec, ldp_fs);
828 return fs;
831 static ldp_fs *_ldp_fec_find_fs_us(ldp_fec * fec, ldp_session * s,
832 mpls_bool flag)
834 ldp_fs *fs = MPLS_LIST_HEAD(&fec->fs_root_us);
836 while (fs != NULL) {
837 if (fs->session->index == s->index) {
838 return fs;
840 fs = MPLS_LIST_NEXT(&fec->fs_root_us, fs, _fec);
842 if (flag == MPLS_BOOL_FALSE) {
843 return NULL;
845 return _ldp_fec_add_fs_us(fec, s);
848 static ldp_fs *_ldp_fec_find_fs_ds(ldp_fec * fec, ldp_session * s,
849 mpls_bool flag)
851 ldp_fs *fs = MPLS_LIST_HEAD(&fec->fs_root_ds);
853 while (fs != NULL) {
854 if (fs->session->index == s->index) {
855 return fs;
857 fs = MPLS_LIST_NEXT(&fec->fs_root_ds, fs, _fec);
859 if (flag == MPLS_BOOL_FALSE) {
860 return NULL;
862 return _ldp_fec_add_fs_ds(fec, s);
865 static void _ldp_fec_del_fs_us(ldp_fec * fec, ldp_fs * fs)
867 if (fs == NULL) {
868 return;
870 MPLS_LIST_REMOVE(&fec->fs_root_us, fs, _fec);
871 _ldp_fs_delete(fs);
874 static void _ldp_fec_del_fs_ds(ldp_fec * fec, ldp_fs * fs)
876 if (fs == NULL) {
877 return;
879 MPLS_LIST_REMOVE(&fec->fs_root_ds, fs, _fec);
880 _ldp_fs_delete(fs);
883 static ldp_fs *_ldp_fs_create(ldp_session * s)
885 ldp_fs *fs = (ldp_fs *) mpls_malloc(sizeof(ldp_fs));
887 if (fs != NULL) {
888 memset(fs, 0, sizeof(ldp_fs));
889 MPLS_LIST_INIT(&fs->attr_root, ldp_attr);
890 MPLS_LIST_ELEM_INIT(fs, _fec);
891 if (s != NULL) {
892 MPLS_REFCNT_HOLD(s);
893 fs->session = s;
896 return fs;
899 static void _ldp_fs_delete(ldp_fs * fs)
901 LDP_PRINT(g->user_data,"fs delete\n");
902 if (fs->session != NULL) {
903 MPLS_REFCNT_RELEASE(fs->session, ldp_session_delete);
905 mpls_free(fs);
908 static ldp_attr *_ldp_fs_find_attr(ldp_fs * fs, ldp_attr * a)
910 ldp_attr *ptr = MPLS_LIST_HEAD(&fs->attr_root);
912 while (ptr != NULL) {
913 if (ldp_attr_is_equal(a, ptr, LDP_ATTR_LABEL | LDP_ATTR_FEC) == MPLS_BOOL_TRUE) {
914 return ptr;
916 ptr = MPLS_LIST_NEXT(&fs->attr_root, ptr, _fs);
918 return NULL;
921 static mpls_return_enum _ldp_fs_add_attr(ldp_fs * fs, ldp_attr * a)
923 ldp_attr *ptr = _ldp_fs_find_attr(fs, a);
925 MPLS_ASSERT(ptr == NULL);
926 MPLS_REFCNT_HOLD(a);
927 MPLS_LIST_ADD_HEAD(&fs->attr_root, a, _fs, ldp_attr);
928 return MPLS_SUCCESS;
931 static mpls_bool _ldp_fs_del_attr(ldp_fs * fs, ldp_attr * a)
933 ldp_attr *ptr = _ldp_fs_find_attr(fs, a);
935 if (ptr != NULL) {
936 MPLS_LIST_REMOVE(&fs->attr_root, ptr, _fs);
937 MPLS_REFCNT_RELEASE(ptr, ldp_attr_delete);
939 if (MPLS_LIST_HEAD(&fs->attr_root) == NULL)
940 return MPLS_BOOL_TRUE;
941 return MPLS_BOOL_FALSE;
944 static uint32_t _ldp_attr_get_next_index()
946 uint32_t retval = _ldp_attr_next_index;
948 _ldp_attr_next_index++;
949 if (retval > _ldp_attr_next_index) {
950 _ldp_attr_next_index = 1;
952 return retval;