Convert to a generic FEC handling architecture. Part of this change
[mpls-ldp-portable.git] / ldp / ldp_outlabel.c
blob26e0bc1641220539d9d6447a39ce1ed44e2220e6
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_addr.h"
13 #include "ldp_if.h"
14 #include "ldp_attr.h"
15 #include "ldp_fec.h"
16 #include "ldp_outlabel.h"
17 #include "ldp_inlabel.h"
18 #include "ldp_session.h"
19 #include "ldp_tunnel.h"
20 #include "ldp_global.h"
22 #include "mpls_mm_impl.h"
23 #include "mpls_trace_impl.h"
25 static uint32_t _ldp_outlabel_next_index = 1;
27 ldp_outlabel *ldp_outlabel_create()
29 ldp_outlabel *o = (ldp_outlabel *) mpls_malloc(sizeof(ldp_outlabel));
31 if (o) {
32 memset(o, 0, sizeof(ldp_outlabel));
33 MPLS_REFCNT_INIT(o, 0);
34 MPLS_LIST_INIT(&o->inlabel_root, ldp_inlabel);
35 MPLS_LIST_INIT(&o->tunnel_root, ldp_tunnel);
36 MPLS_LIST_INIT(&o->fec_outlabel_root, ldp_fec);
37 MPLS_LIST_ELEM_INIT(o, _global);
38 MPLS_LIST_ELEM_INIT(o, _session);
39 o->index = _ldp_outlabel_get_next_index();
40 o->info.label.type = MPLS_LABEL_TYPE_NONE;
41 o->switching = MPLS_BOOL_FALSE;
43 return o;
46 ldp_outlabel *ldp_outlabel_create_complete(ldp_global * g, ldp_session * s,
47 ldp_attr * a)
49 ldp_outlabel *out = ldp_outlabel_create();
51 if (out != NULL) {
52 ldp_outlabel_add_nexthop(out, &a->fec->nh);
53 ldp_session_add_outlabel(s, out);
55 out->info.push_label = MPLS_BOOL_TRUE;
56 out->info.owner = MPLS_OWNER_LDP;
58 ldp_attr2mpls_label_struct(a, &out->info.label);
59 _ldp_global_add_outlabel(g, out);
60 ldp_attr_add_outlabel(a, out);
62 return out;
65 void ldp_outlabel_delete(ldp_outlabel * o)
67 LDP_PRINT(g->user_data,"outlabel delete\n");
68 MPLS_REFCNT_ASSERT(o, 0);
69 mpls_free(o);
72 void ldp_outlabel_delete_complete(ldp_global * g, ldp_outlabel * out)
74 ldp_attr_del_outlabel(out->attr);
75 if (out->session) {
76 ldp_session_del_outlabel(out->session, out);
78 _ldp_global_del_outlabel(g, out);
79 ldp_outlabel_del_nexthop(out);
82 mpls_return_enum _ldp_outlabel_add_inlabel(ldp_outlabel * o, ldp_inlabel * i)
84 if (o && i) {
85 MPLS_REFCNT_HOLD(i);
86 o->merge_count++;
87 MPLS_LIST_ADD_HEAD(&o->inlabel_root, i, _outlabel, ldp_inlabel);
88 return MPLS_SUCCESS;
90 return MPLS_FAILURE;
93 mpls_return_enum _ldp_outlabel_del_inlabel(ldp_outlabel * o, ldp_inlabel * i)
95 if (o && i) {
96 MPLS_LIST_REMOVE(&o->inlabel_root, i, _outlabel);
97 o->merge_count--;
98 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
99 return MPLS_SUCCESS;
101 return MPLS_FAILURE;
104 mpls_return_enum _ldp_outlabel_add_attr(ldp_outlabel * o, ldp_attr * a)
106 if (o && a) {
107 MPLS_REFCNT_HOLD(a);
108 o->attr = a;
109 return MPLS_SUCCESS;
111 return MPLS_FAILURE;
114 mpls_return_enum _ldp_outlabel_del_attr(ldp_outlabel * o)
116 if (o && o->attr) {
117 MPLS_REFCNT_RELEASE(o->attr, ldp_attr_delete);
118 o->attr = NULL;
119 return MPLS_SUCCESS;
121 return MPLS_FAILURE;
124 void ldp_outlabel_add_fec(ldp_outlabel * o, ldp_fec * f)
126 ldp_fec *fp = NULL;
128 MPLS_ASSERT(o && f);
129 MPLS_REFCNT_HOLD(f);
131 ldp_fec_add_outlabel(f,o);
133 fp = MPLS_LIST_HEAD(&o->fec_outlabel_root);
134 while (fp != NULL) {
135 if (fp->index > f->index) {
136 MPLS_LIST_INSERT_BEFORE(&o->fec_outlabel_root, fp, f, _if);
137 return;
139 fp = MPLS_LIST_NEXT(&o->fec_outlabel_root, fp, _if);
141 MPLS_LIST_ADD_TAIL(&o->fec_outlabel_root, f, _if, ldp_fec);
144 void ldp_outlabel_del_fec(ldp_outlabel * o, ldp_fec * f)
146 MPLS_ASSERT(o && f);
147 MPLS_LIST_REMOVE(&o->fec_outlabel_root, f, _if);
148 ldp_fec_del_outlabel(f);
149 MPLS_REFCNT_RELEASE(f, ldp_fec_delete);
152 void ldp_outlabel_add_nexthop(ldp_outlabel * o, ldp_nexthop * nh)
154 MPLS_ASSERT(o && nh);
156 if (nh->type & MPLS_NH_IP) {
157 MPLS_REFCNT_HOLD(nh->addr);
158 o->nh.addr = nh->addr;
159 o->nh.type |= MPLS_NH_IP;
160 memcpy(&o->info.nexthop.ip, &nh->addr->address, sizeof(mpls_inet_addr));
161 o->info.nexthop.type |= MPLS_NH_IP;
163 if (nh->type & MPLS_NH_IF) {
164 MPLS_REFCNT_HOLD(nh->iff);
165 o->nh.iff = nh->iff;
166 o->nh.type |= MPLS_NH_IF;
167 memcpy(&o->info.nexthop.if_handle, &nh->iff->handle,
168 sizeof(mpls_if_handle));
169 o->info.nexthop.type |= MPLS_NH_IF;
171 if (nh->type & MPLS_NH_OUTSEGMENT) {
172 MPLS_REFCNT_HOLD(nh->outlabel);
173 o->nh.outlabel = nh->outlabel;
174 o->nh.type |= MPLS_NH_OUTSEGMENT;
175 memcpy(&o->info.nexthop.outsegment_handle, &nh->outlabel->info.handle,
176 sizeof(mpls_outsegment_handle));
177 o->info.nexthop.type |= MPLS_NH_OUTSEGMENT;
181 void ldp_outlabel_del_nexthop(ldp_outlabel * o)
183 MPLS_ASSERT(o);
184 if (o->nh.type & MPLS_NH_IP) {
185 MPLS_REFCNT_RELEASE(o->nh.addr, ldp_addr_delete);
186 o->nh.addr = NULL;
187 o->nh.type &= ~MPLS_NH_IP;
189 if (o->nh.type & MPLS_NH_IF) {
190 MPLS_REFCNT_RELEASE(o->nh.iff, ldp_if_delete);
191 o->nh.iff = NULL;
192 o->nh.type &= ~MPLS_NH_IF;
194 if (o->nh.type & MPLS_NH_OUTSEGMENT) {
195 MPLS_REFCNT_RELEASE(o->nh.outlabel, ldp_outlabel_delete);
196 o->nh.outlabel = NULL;
197 o->nh.type &= ~MPLS_NH_OUTSEGMENT;
201 mpls_return_enum _ldp_outlabel_add_session(ldp_outlabel * o, ldp_session * s)
203 if (o && s) {
204 MPLS_REFCNT_HOLD(s);
205 o->session = s;
206 return MPLS_SUCCESS;
208 return MPLS_FAILURE;
211 mpls_return_enum _ldp_outlabel_del_session(ldp_outlabel * o)
213 if (o && o->session) {
214 MPLS_REFCNT_RELEASE(o->session, ldp_session_delete);
215 o->session = NULL;
216 return MPLS_SUCCESS;
218 return MPLS_FAILURE;
221 uint32_t _ldp_outlabel_get_next_index()
223 uint32_t retval = _ldp_outlabel_next_index;
225 _ldp_outlabel_next_index++;
226 if (retval > _ldp_outlabel_next_index) {
227 _ldp_outlabel_next_index = 1;
229 return retval;
232 mpls_return_enum _ldp_outlabel_add_tunnel(ldp_outlabel * o, ldp_tunnel * t)
234 if (o && t) {
235 MPLS_REFCNT_HOLD(t);
236 o->merge_count++;
237 MPLS_LIST_ADD_HEAD(&o->tunnel_root, t, _outlabel, ldp_tunnel);
238 return MPLS_SUCCESS;
240 return MPLS_FAILURE;
243 mpls_return_enum _ldp_outlabel_del_tunnel(ldp_outlabel * o, ldp_tunnel * t)
245 if (o && t) {
246 MPLS_LIST_REMOVE(&o->tunnel_root, t, _outlabel);
247 o->merge_count--;
248 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
249 return MPLS_SUCCESS;
251 return MPLS_FAILURE;