3 * Copyright (C) James R. Leu 2000
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
11 #include "ldp_struct.h"
12 #include "ldp_outlabel.h"
13 #include "ldp_inlabel.h"
14 #include "ldp_session.h"
15 #include "ldp_entity.h"
17 #include "ldp_global.h"
19 #include "mpls_assert.h"
20 #include "mpls_mm_impl.h"
21 #include "mpls_trace_impl.h"
26 #include "mpls_mpls_impl.h"
29 static uint32_t _ldp_inlabel_next_index
= 1;
32 * even through we're trying to mimic what FECs/addrs/interfaces are doing
33 * with respect to being added to the global list upon create and
34 * automagically be removed from the global list upon delete, we have to
35 * change thing up for inlabels. We want the global add/delete to call
36 * the porting layer to install the segments, but an inlabel needs more
37 * info then just being allocated before the porting layer can add it.
38 * so ldp_inlabel_create is not in charge of adding to the global list.
39 * Instead the only entrance to creating a inlabel is
40 * ldp_inlabel_create_complete which uses ldp_inlabel_create just to
41 * allocate and initialize the memory, then after all of the necessary info
42 * has been attached, it is added to the global list, which calls the
46 static ldp_inlabel
*ldp_inlabel_create(ldp_global
* g
)
48 ldp_inlabel
*i
= (ldp_inlabel
*) mpls_malloc(
49 MTYPE_LDP_INLABEL
, sizeof(ldp_inlabel
));
52 memset(i
, 0, sizeof(ldp_inlabel
));
53 MPLS_REFCNT_INIT(i
, 0);
54 mpls_link_list_init(&i
->session_root
);
55 mpls_link_list_init(&i
->attr_root
);
56 MPLS_LIST_ELEM_INIT(i
, _global
);
57 MPLS_LIST_ELEM_INIT(i
, _outlabel
);
58 i
->index
= _ldp_inlabel_get_next_index();
59 i
->info
.label
.type
= MPLS_LABEL_TYPE_NONE
;
64 ldp_inlabel
*ldp_inlabel_create_complete(ldp_global
* g
, ldp_session
* s
,
67 ldp_inlabel
*in
= ldp_inlabel_create(g
);
68 mpls_return_enum result
;
72 in
->info
.labelspace
= s
->cfg_label_space
;
74 in
->info
.family
= MPLS_FAMILY_IPV4
;
75 in
->info
.owner
= MPLS_OWNER_LDP
;
77 /* _ldp_global_add_inlabel must be here so the porting layer has all the
78 * info needed for installing the label */
79 result
= _ldp_global_add_inlabel(g
, in
);
81 if (result
== MPLS_FAILURE
) {
82 _ldp_global_del_inlabel(g
, in
);
86 if (ldp_session_add_inlabel(g
, s
, in
) == MPLS_FAILURE
) {
87 /* if ldp_session_add_inlabel fails its use of MPLS_HOLD and
88 * RELEASE2 will result in the inlabel being deleted */
92 mpls_label_struct2ldp_attr(&in
->info
.label
, a
);
93 ldp_attr_add_inlabel(g
, a
, in
);
98 void ldp_inlabel_delete(ldp_global
* g
, ldp_inlabel
* i
)
100 LDP_PRINT(g
->user_data
,"inlabel delete: %p", i
);
101 MPLS_REFCNT_ASSERT(i
, 0);
102 _ldp_global_del_inlabel(g
, i
);
103 mpls_free(MTYPE_LDP_INLABEL
, i
);
106 mpls_return_enum
ldp_inlabel_add_outlabel(ldp_global
*g
, ldp_inlabel
*i
,
108 mpls_return_enum result
;
111 MPLS_ASSERT(i
->outlabel
== NULL
);
116 xcon
.insegment_index
= i
->info
.handle
;
117 xcon
.outsegment_index
= o
->info
.handle
;
118 xcon
.info
.owner
= MPLS_OWNER_LDP
;
119 result
= lsr_cfg_xconnect_set2(g
->lsr_handle
, &xcon
, LSR_CFG_ADD
|
120 LSR_XCONNECT_CFG_OUTSEGMENT
|LSR_XCONNECT_CFG_INSEGMENT
|
121 LSR_XCONNECT_CFG_LSPID
|LSR_XCONNECT_CFG_OWNER
);
124 result
= mpls_mpls_xconnect_add(g
->mpls_handle
, &i
->info
, &o
->info
);
126 if (result
== MPLS_SUCCESS
) {
129 _ldp_outlabel_add_inlabel(o
, i
);
134 mpls_return_enum
ldp_inlabel_del_outlabel(ldp_global
*g
, ldp_inlabel
* i
)
136 MPLS_ASSERT(i
&& i
->outlabel
);
140 xcon
.insegment_index
= i
->info
.handle
;
141 xcon
.outsegment_index
= i
->outlabel
->info
.handle
;
142 lsr_cfg_xconnect_set2(g
->lsr_handle
, &xcon
, LSR_CFG_DEL
);
144 mpls_mpls_xconnect_del(g
->mpls_handle
, &i
->info
, &i
->outlabel
->info
);
146 _ldp_outlabel_del_inlabel(g
, i
->outlabel
, i
);
147 MPLS_REFCNT_RELEASE2(g
, i
->outlabel
, ldp_outlabel_delete
);
153 mpls_return_enum
_ldp_inlabel_add_attr(ldp_global
*g
, ldp_inlabel
* i
, ldp_attr
* a
)
158 if (mpls_link_list_add_tail(&i
->attr_root
, a
) == MPLS_SUCCESS
) {
162 MPLS_REFCNT_RELEASE2(g
, a
, ldp_attr_delete
);
166 void _ldp_inlabel_del_attr(ldp_global
*g
, ldp_inlabel
* i
, ldp_attr
* a
)
169 mpls_link_list_remove_data(&i
->attr_root
, a
);
170 MPLS_REFCNT_RELEASE2(g
, a
, ldp_attr_delete
);
174 mpls_return_enum
_ldp_inlabel_add_session(ldp_inlabel
* i
, ldp_session
* s
)
179 if (mpls_link_list_add_tail(&i
->session_root
, s
) == MPLS_SUCCESS
) {
182 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
186 void _ldp_inlabel_del_session(ldp_inlabel
* i
, ldp_session
* s
)
189 mpls_link_list_remove_data(&i
->session_root
, s
);
190 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
193 uint32_t _ldp_inlabel_get_next_index()
195 uint32_t retval
= _ldp_inlabel_next_index
;
197 _ldp_inlabel_next_index
++;
198 if (retval
> _ldp_inlabel_next_index
) {
199 _ldp_inlabel_next_index
= 1;