Convertion to a ECMP capable infrastructure compiles (no testing
[mpls-ldp-portable.git] / ldp / ldp_outlabel.c
blob02f7e59135390702faa5e32f3cedabf12942cbb8
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_nexthop.h"
17 #include "ldp_outlabel.h"
18 #include "ldp_inlabel.h"
19 #include "ldp_session.h"
20 #include "ldp_tunnel.h"
21 #include "ldp_global.h"
23 #include "mpls_mm_impl.h"
24 #include "mpls_trace_impl.h"
26 static uint32_t _ldp_outlabel_next_index = 1;
28 ldp_outlabel *ldp_outlabel_create()
30 ldp_outlabel *o = (ldp_outlabel *) mpls_malloc(sizeof(ldp_outlabel));
32 if (o) {
33 memset(o, 0, sizeof(ldp_outlabel));
34 MPLS_REFCNT_INIT(o, 0);
35 MPLS_LIST_INIT(&o->inlabel_root, ldp_inlabel);
36 MPLS_LIST_INIT(&o->tunnel_root, ldp_tunnel);
37 MPLS_LIST_INIT(&o->nh_root, ldp_nexthop);
38 MPLS_LIST_ELEM_INIT(o, _global);
39 MPLS_LIST_ELEM_INIT(o, _session);
40 o->index = _ldp_outlabel_get_next_index();
41 o->info.label.type = MPLS_LABEL_TYPE_NONE;
42 o->switching = MPLS_BOOL_FALSE;
44 return o;
47 ldp_outlabel *ldp_outlabel_create_complete(ldp_global * g, ldp_session * s,
48 ldp_attr * a, ldp_nexthop *nh)
50 ldp_outlabel *out = ldp_outlabel_create();
52 if (out != NULL) {
53 ldp_outlabel_add_nexthop2(out, nh);
54 ldp_session_add_outlabel(s, out);
56 out->info.push_label = MPLS_BOOL_TRUE;
57 out->info.owner = MPLS_OWNER_LDP;
59 ldp_attr2mpls_label_struct(a, &out->info.label);
60 _ldp_global_add_outlabel(g, out);
61 ldp_attr_add_outlabel(a, out);
63 return out;
66 void ldp_outlabel_delete(ldp_outlabel * o)
68 LDP_PRINT(g->user_data,"outlabel delete\n");
69 MPLS_REFCNT_ASSERT(o, 0);
70 mpls_free(o);
73 void ldp_outlabel_delete_complete(ldp_global * g, ldp_outlabel * out)
75 ldp_attr_del_outlabel(out->attr);
76 if (out->session) {
77 ldp_session_del_outlabel(out->session, out);
79 _ldp_global_del_outlabel(g, out);
80 ldp_outlabel_del_nexthop2(out);
83 mpls_return_enum _ldp_outlabel_add_inlabel(ldp_outlabel * o, ldp_inlabel * i)
85 if (o && i) {
86 MPLS_REFCNT_HOLD(i);
87 o->merge_count++;
88 MPLS_LIST_ADD_HEAD(&o->inlabel_root, i, _outlabel, ldp_inlabel);
89 return MPLS_SUCCESS;
91 return MPLS_FAILURE;
94 mpls_return_enum _ldp_outlabel_del_inlabel(ldp_outlabel * o, ldp_inlabel * i)
96 if (o && i) {
97 MPLS_LIST_REMOVE(&o->inlabel_root, i, _outlabel);
98 o->merge_count--;
99 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
100 return MPLS_SUCCESS;
102 return MPLS_FAILURE;
105 mpls_return_enum _ldp_outlabel_add_attr(ldp_outlabel * o, ldp_attr * a)
107 if (o && a) {
108 MPLS_REFCNT_HOLD(a);
109 o->attr = a;
110 return MPLS_SUCCESS;
112 return MPLS_FAILURE;
115 mpls_return_enum _ldp_outlabel_del_attr(ldp_outlabel * o)
117 if (o && o->attr) {
118 MPLS_REFCNT_RELEASE(o->attr, ldp_attr_delete);
119 o->attr = NULL;
120 return MPLS_SUCCESS;
122 return MPLS_FAILURE;
125 void ldp_outlabel_add_nexthop(ldp_outlabel * o, ldp_nexthop * nh)
127 ldp_nexthop *np = NULL;
129 MPLS_ASSERT(o && nh);
130 MPLS_REFCNT_HOLD(nh);
132 ldp_nexthop_add_outlabel(nh,o);
134 np = MPLS_LIST_HEAD(&o->nh_root);
135 while (np != NULL) {
136 if (np->index > nh->index) {
137 MPLS_LIST_INSERT_BEFORE(&o->nh_root, np, nh, _outlabel);
138 return;
140 np = MPLS_LIST_NEXT(&o->nh_root, np, _outlabel);
142 MPLS_LIST_ADD_TAIL(&o->nh_root, nh, _outlabel, ldp_nexthop);
145 void ldp_outlabel_del_nexthop(ldp_outlabel * o, ldp_nexthop * nh)
147 MPLS_ASSERT(o && nh);
148 MPLS_LIST_REMOVE(&o->nh_root, nh, _outlabel);
149 ldp_nexthop_del_outlabel(nh);
150 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);
153 void ldp_outlabel_add_nexthop2(ldp_outlabel * o, ldp_nexthop * nh)
155 MPLS_ASSERT(o && nh);
157 if (nh->type & MPLS_NH_IP) {
158 MPLS_REFCNT_HOLD(nh->addr);
159 o->nh.addr = nh->addr;
160 o->nh.type |= MPLS_NH_IP;
161 memcpy(&o->info.nexthop.ip, &nh->addr->address, sizeof(mpls_inet_addr));
162 o->info.nexthop.type |= MPLS_NH_IP;
164 if (nh->type & MPLS_NH_IF) {
165 MPLS_REFCNT_HOLD(nh->iff);
166 o->nh.iff = nh->iff;
167 o->nh.type |= MPLS_NH_IF;
168 memcpy(&o->info.nexthop.if_handle, &nh->iff->handle,
169 sizeof(mpls_if_handle));
170 o->info.nexthop.type |= MPLS_NH_IF;
172 if (nh->type & MPLS_NH_OUTSEGMENT) {
173 MPLS_REFCNT_HOLD(nh->outlabel);
174 o->nh.outlabel = nh->outlabel;
175 o->nh.type |= MPLS_NH_OUTSEGMENT;
176 memcpy(&o->info.nexthop.outsegment_handle, &nh->outlabel->info.handle,
177 sizeof(mpls_outsegment_handle));
178 o->info.nexthop.type |= MPLS_NH_OUTSEGMENT;
182 void ldp_outlabel_del_nexthop2(ldp_outlabel * o)
184 MPLS_ASSERT(o);
185 if (o->nh.type & MPLS_NH_IP) {
186 MPLS_REFCNT_RELEASE(o->nh.addr, ldp_addr_delete);
187 o->nh.addr = NULL;
188 o->nh.type &= ~MPLS_NH_IP;
190 if (o->nh.type & MPLS_NH_IF) {
191 MPLS_REFCNT_RELEASE(o->nh.iff, ldp_if_delete);
192 o->nh.iff = NULL;
193 o->nh.type &= ~MPLS_NH_IF;
195 if (o->nh.type & MPLS_NH_OUTSEGMENT) {
196 MPLS_REFCNT_RELEASE(o->nh.outlabel, ldp_outlabel_delete);
197 o->nh.outlabel = NULL;
198 o->nh.type &= ~MPLS_NH_OUTSEGMENT;
202 mpls_return_enum _ldp_outlabel_add_session(ldp_outlabel * o, ldp_session * s)
204 if (o && s) {
205 MPLS_REFCNT_HOLD(s);
206 o->session = s;
207 return MPLS_SUCCESS;
209 return MPLS_FAILURE;
212 mpls_return_enum _ldp_outlabel_del_session(ldp_outlabel * o)
214 if (o && o->session) {
215 MPLS_REFCNT_RELEASE(o->session, ldp_session_delete);
216 o->session = NULL;
217 return MPLS_SUCCESS;
219 return MPLS_FAILURE;
222 uint32_t _ldp_outlabel_get_next_index()
224 uint32_t retval = _ldp_outlabel_next_index;
226 _ldp_outlabel_next_index++;
227 if (retval > _ldp_outlabel_next_index) {
228 _ldp_outlabel_next_index = 1;
230 return retval;
233 mpls_return_enum _ldp_outlabel_add_tunnel(ldp_outlabel * o, ldp_tunnel * t)
235 if (o && t) {
236 MPLS_REFCNT_HOLD(t);
237 o->merge_count++;
238 MPLS_LIST_ADD_HEAD(&o->tunnel_root, t, _outlabel, ldp_tunnel);
239 return MPLS_SUCCESS;
241 return MPLS_FAILURE;
244 mpls_return_enum _ldp_outlabel_del_tunnel(ldp_outlabel * o, ldp_tunnel * t)
246 if (o && t) {
247 MPLS_LIST_REMOVE(&o->tunnel_root, t, _outlabel);
248 o->merge_count--;
249 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
250 return MPLS_SUCCESS;
252 return MPLS_FAILURE;