From: Vasu Dasari <vdasari@gmail.com>
[mpls-ldp-portable.git] / ldp / ldp_inlabel.c
blob0457eb5c7c5dd1225df8aceada02be160648c61e
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 <stdlib.h>
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"
16 #include "ldp_attr.h"
17 #include "ldp_global.h"
19 #include "mpls_assert.h"
20 #include "mpls_mm_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 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
43 * porting layer
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));
51 if (i) {
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;
61 return i;
64 ldp_inlabel *ldp_inlabel_create_complete(ldp_global * g, ldp_session * s,
65 ldp_attr * a)
67 ldp_inlabel *in = ldp_inlabel_create(g);
68 mpls_return_enum result;
70 if (in != NULL) {
72 in->info.labelspace = s->cfg_label_space;
73 in->info.npop = 1;
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);
83 return NULL;
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 */
89 return NULL;
92 mpls_label_struct2ldp_attr(&in->info.label, a);
93 ldp_attr_add_inlabel(g, a, in);
95 return 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,
107 ldp_outlabel *o) {
108 mpls_return_enum result;
110 MPLS_ASSERT(i && o);
111 MPLS_ASSERT(i->outlabel == NULL);
113 #if MPLS_USE_LSR
115 lsr_xconnect xcon;
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);
123 #else
124 result = mpls_mpls_xconnect_add(g->mpls_handle, &i->info, &o->info);
125 #endif
126 if (result == MPLS_SUCCESS) {
127 MPLS_REFCNT_HOLD(o);
128 i->outlabel = o;
129 _ldp_outlabel_add_inlabel(o, i);
131 return result;
134 mpls_return_enum ldp_inlabel_del_outlabel(ldp_global *g, ldp_inlabel * i)
136 MPLS_ASSERT(i && i->outlabel);
138 #if MPLS_USE_LSR
139 lsr_xconnect xcon;
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);
143 #else
144 mpls_mpls_xconnect_del(g->mpls_handle, &i->info, &i->outlabel->info);
145 #endif
146 _ldp_outlabel_del_inlabel(g, i->outlabel, i);
147 MPLS_REFCNT_RELEASE2(g, i->outlabel, ldp_outlabel_delete);
148 i->outlabel = NULL;
150 return MPLS_SUCCESS;
153 mpls_return_enum _ldp_inlabel_add_attr(ldp_global *g, ldp_inlabel * i, ldp_attr * a)
155 MPLS_ASSERT(i && a);
157 MPLS_REFCNT_HOLD(a);
158 if (mpls_link_list_add_tail(&i->attr_root, a) == MPLS_SUCCESS) {
159 i->reuse_count++;
160 return MPLS_SUCCESS;
162 MPLS_REFCNT_RELEASE2(g, a, ldp_attr_delete);
163 return MPLS_FAILURE;
166 void _ldp_inlabel_del_attr(ldp_global *g, ldp_inlabel * i, ldp_attr * a)
168 MPLS_ASSERT(i && a);
169 mpls_link_list_remove_data(&i->attr_root, a);
170 MPLS_REFCNT_RELEASE2(g, a, ldp_attr_delete);
171 i->reuse_count--;
174 mpls_return_enum _ldp_inlabel_add_session(ldp_inlabel * i, ldp_session * s)
176 MPLS_ASSERT(i && s);
178 MPLS_REFCNT_HOLD(s);
179 if (mpls_link_list_add_tail(&i->session_root, s) == MPLS_SUCCESS) {
180 return MPLS_SUCCESS;
182 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
183 return MPLS_FAILURE;
186 void _ldp_inlabel_del_session(ldp_inlabel * i, ldp_session * s)
188 MPLS_ASSERT(i && 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;
201 return retval;