In the case of a route being and there is not an alternate
[mpls-ldp-portable.git] / ldp / ldp_outlabel.c
blob490a5435c0a70638e70b51e30d601887bfba834f
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(g, out);
83 void _ldp_outlabel_add_inlabel(ldp_outlabel * o, ldp_inlabel * i)
85 MPLS_ASSERT(o && i);
86 MPLS_REFCNT_HOLD(i);
87 o->merge_count++;
88 MPLS_LIST_ADD_HEAD(&o->inlabel_root, i, _outlabel, ldp_inlabel);
91 void _ldp_outlabel_del_inlabel(ldp_outlabel * o, ldp_inlabel * i)
93 MPLS_ASSERT(o && i);
94 MPLS_LIST_REMOVE(&o->inlabel_root, i, _outlabel);
95 o->merge_count--;
96 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
99 void _ldp_outlabel_add_attr(ldp_outlabel * o, ldp_attr * a)
101 MPLS_ASSERT(o && a);
102 MPLS_REFCNT_HOLD(a);
103 o->attr = a;
106 void _ldp_outlabel_del_attr(ldp_outlabel * o)
108 MPLS_ASSERT(o && o->attr);
109 MPLS_REFCNT_RELEASE(o->attr, ldp_attr_delete);
110 o->attr = NULL;
114 * We do not hold a ref to the nexthop. The nexthop holds a ref to the
115 * outlabel. Nexthop creation calls ldp_outlabel_add_nexthop, nexthop
116 * deletion calls ldp_outlabel_del_nexthop. There is no way a nexthop can
117 * be deleted without removing the outlabels ref to the nexthop.
119 void ldp_outlabel_add_nexthop(ldp_outlabel * o, ldp_nexthop * nh)
121 ldp_nexthop *np = NULL;
123 MPLS_ASSERT(o && nh);
125 ldp_nexthop_add_outlabel(nh,o);
127 np = MPLS_LIST_HEAD(&o->nh_root);
128 while (np != NULL) {
129 if (np->index > nh->index) {
130 MPLS_LIST_INSERT_BEFORE(&o->nh_root, np, nh, _outlabel);
131 return;
133 np = MPLS_LIST_NEXT(&o->nh_root, np, _outlabel);
135 MPLS_LIST_ADD_TAIL(&o->nh_root, nh, _outlabel, ldp_nexthop);
138 void ldp_outlabel_del_nexthop(ldp_global *g, ldp_outlabel * o, ldp_nexthop * nh)
140 MPLS_ASSERT(o && nh);
141 MPLS_LIST_REMOVE(&o->nh_root, nh, _outlabel);
142 ldp_nexthop_del_outlabel(nh);
145 void ldp_outlabel_add_nexthop2(ldp_outlabel * o, ldp_nexthop * nh)
147 MPLS_ASSERT(o && nh);
148 MPLS_REFCNT_HOLD(nh);
149 o->nh = nh;
150 ldp_nexthop_add_outlabel2(nh, o);
153 void ldp_outlabel_del_nexthop2(ldp_global *g, ldp_outlabel * o)
155 MPLS_ASSERT(o);
156 ldp_nexthop_del_outlabel2(g, o->nh, o);
157 MPLS_REFCNT_RELEASE2(g, o->nh, ldp_nexthop_delete);
158 o->nh = NULL;
161 void _ldp_outlabel_add_session(ldp_outlabel * o, ldp_session * s)
163 MPLS_ASSERT(o && s);
164 MPLS_REFCNT_HOLD(s);
165 o->session = s;
168 void _ldp_outlabel_del_session(ldp_outlabel * o)
170 MPLS_ASSERT(o && o->session);
171 MPLS_REFCNT_RELEASE(o->session, ldp_session_delete);
172 o->session = NULL;
175 void _ldp_outlabel_add_tunnel(ldp_outlabel * o, ldp_tunnel * t)
177 MPLS_ASSERT(o && t);
178 MPLS_REFCNT_HOLD(t);
179 o->merge_count++;
180 MPLS_LIST_ADD_HEAD(&o->tunnel_root, t, _outlabel, ldp_tunnel);
183 void _ldp_outlabel_del_tunnel(ldp_outlabel * o, ldp_tunnel * t)
185 MPLS_ASSERT(o && t);
186 MPLS_LIST_REMOVE(&o->tunnel_root, t, _outlabel);
187 o->merge_count--;
188 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
191 uint32_t _ldp_outlabel_get_next_index()
193 uint32_t retval = _ldp_outlabel_next_index;
195 _ldp_outlabel_next_index++;
196 if (retval > _ldp_outlabel_next_index) {
197 _ldp_outlabel_next_index = 1;
199 return retval;