From: Vasu Dasari <vdasari@gmail.com>
[mpls-ldp-portable.git] / ldp / ldp_label_rel_with.c
blob7c67ad4e59d68be8382d2a905d38ba481f6a9224
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 "ldp_struct.h"
11 #include "ldp_attr.h"
12 #include "ldp_session.h"
13 #include "ldp_global.h"
14 #include "ldp_inlabel.h"
15 #include "ldp_entity.h"
16 #include "ldp_outlabel.h"
17 #include "ldp_label_rel_with.h"
18 #include "ldp_nexthop.h"
19 #include "ldp_label_mapping.h"
20 #include "ldp_fec.h"
21 #include "ldp_mesg.h"
22 #include "ldp_pdu_setup.h"
24 #include "mpls_trace_impl.h"
26 mpls_bool rel_with2attr(mplsLdpLbl_W_R_Msg_t * rw, ldp_attr * attr)
28 mpls_bool retval = MPLS_BOOL_FALSE;
30 if (rw->fecTlvExists) {
31 memcpy(&attr->fecTlv, &rw->fecTlv, sizeof(mplsLdpFecTlv_t));
32 attr->fecTlvExists = 1;
34 if (rw->genLblTlvExists) {
35 retval = MPLS_BOOL_TRUE;
36 memcpy(&attr->genLblTlv, &rw->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
37 attr->genLblTlvExists = 1;
38 } else if (rw->atmLblTlvExists) {
39 retval = MPLS_BOOL_TRUE;
40 memcpy(&attr->atmLblTlv, &rw->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
41 attr->atmLblTlvExists = 1;
42 } else if (rw->frLblTlvExists) {
43 retval = MPLS_BOOL_TRUE;
44 memcpy(&attr->frLblTlv, &rw->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
45 attr->frLblTlvExists = 1;
47 return retval;
50 void ldp_label_rel_with_prepare_msg(ldp_mesg * msg, uint32_t msgid,
51 ldp_attr * a, ldp_notif_status status, uint16_t type)
53 mplsLdpLbl_W_R_Msg_t *rw = NULL;
55 ldp_mesg_prepare(msg, type, msgid);
56 rw = &msg->u.release;
57 if (a->fecTlvExists) {
58 rw->fecTlvExists = 1;
59 rw->baseMsg.msgLength += setupFecTlv(&rw->fecTlv);
60 rw->baseMsg.msgLength += addFecElem2FecTlv(&rw->fecTlv,
61 &a->fecTlv.fecElArray[0]);
63 if (a->genLblTlvExists) {
64 rw->genLblTlvExists = 1;
65 rw->baseMsg.msgLength += setupGenLblTlv(&rw->genLblTlv, a->genLblTlv.label);
67 if (a->atmLblTlvExists) {
68 rw->atmLblTlvExists = 1;
69 rw->baseMsg.msgLength += setupAtmLblTlv(&rw->atmLblTlv, 0, 0,
70 a->atmLblTlv.flags.flags.vpi, a->atmLblTlv.vci);
72 if (a->frLblTlvExists) {
73 rw->frLblTlvExists = 1;
74 rw->baseMsg.msgLength += setupFrLblTlv(&rw->frLblTlv, 0,
75 a->frLblTlv.flags.flags.len, a->frLblTlv.flags.flags.dlci);
77 if (a->lspidTlvExists) {
78 rw->lspidTlvExists = 1;
79 rw->baseMsg.msgLength += setupLspidTlv(&rw->lspidTlv, 0,
80 a->lspidTlv.localCrlspId, a->lspidTlv.routerId);
84 mpls_return_enum ldp_label_rel_with_send(ldp_global * g, ldp_session * s,
85 ldp_attr * a, ldp_notif_status status, uint16_t type)
87 LDP_ENTER(g->user_data, "ldp_label_rel_with_send");
89 ldp_label_rel_with_prepare_msg(s->tx_message, g->message_identifier++, a,
90 status, type);
92 ldp_mesg_send_tcp(g, s, s->tx_message);
94 LDP_EXIT(g->user_data, "ldp_label_rel_with_send");
96 return MPLS_SUCCESS;
99 mpls_return_enum ldp_label_release_send(ldp_global * g, ldp_session * s,
100 ldp_attr * a, ldp_notif_status status)
103 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
104 "Release Sent: session(%d)\n", s->index);
106 return ldp_label_rel_with_send(g, s, a, status, MPLS_LBLREL_MSGTYPE);
109 mpls_return_enum ldp_label_withdraw_send(ldp_global * g, ldp_session * s,
110 ldp_attr * us_attr, ldp_notif_status status)
113 us_attr->state = LDP_LSP_STATE_WITH_SENT;
114 if (ldp_label_rel_with_send(g, s, us_attr, status, MPLS_LBLWITH_MSGTYPE) ==
115 MPLS_FAILURE) {
116 return MPLS_FAILURE;
119 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
120 "Withdraw Sent: session(%d)\n", s->index);
122 return MPLS_SUCCESS;
125 mpls_return_enum ldp_label_release_process(ldp_global * g, ldp_session * s,
126 ldp_adj * a, ldp_entity * e, ldp_attr * r_attr, ldp_fec * f)
128 mpls_bool label_exists = MPLS_BOOL_FALSE;
129 ldp_attr *us_attr = NULL;
130 ldp_attr *ds_attr = NULL;
131 mpls_return_enum retval = MPLS_SUCCESS;
133 LDP_ENTER(g->user_data, "ldp_label_release_process");
135 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
136 "Release Recv from %s\n", s->session_name);
138 if (r_attr->genLblTlvExists || r_attr->atmLblTlvExists
139 || r_attr->frLblTlvExists) {
140 label_exists = MPLS_BOOL_TRUE;
143 if (f) {
144 /* LRl.1 is accomplished at LRl.10 */
145 us_attr = ldp_attr_find_upstream_state2(g, s, f, LDP_LSP_STATE_MAP_SENT);
146 if (!us_attr) {
147 us_attr =
148 ldp_attr_find_upstream_state2(g, s, f, LDP_LSP_STATE_WITH_SENT);
149 if (!us_attr) { /* LRl.2 */
150 goto LRl_13;
152 /* LRl.3 is accomplished at LRl.10 */
155 if (g->label_merge == MPLS_BOOL_FALSE) { /* LR1.4 */
156 goto LRl_6;
158 /* LR1.5 */
159 if (ldp_attr_find_upstream_state_any2(g, f, LDP_LSP_STATE_MAP_SENT)) {
160 goto LRl_10;
163 LRl_6:
164 /* we can only propogate a release to the downstream attached to
165 the upstream we found up top */
166 /* LRl.6,7 */
167 if (us_attr->ds_attr && us_attr->ds_attr->state == LDP_LSP_STATE_MAP_RECV) {
168 ds_attr = us_attr->ds_attr;
169 } else {
170 goto LRl_10;
173 if (g->propagate_release == MPLS_BOOL_FALSE) { /* LRl.8 */
174 goto LRl_10;
177 if (ldp_label_release_send(g, ds_attr->session, ds_attr,
178 LDP_NOTIF_NONE) != MPLS_SUCCESS) { /* LRl.9 */
179 retval = MPLS_FAILURE;
181 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE);
183 LRl_10:
184 ldp_attr_remove_complete(g, us_attr, MPLS_BOOL_FALSE); /* LRl.10,11 */
186 } else {
187 LDP_PRINT(g->user_data, "No FEC in release, need to implement\n");
188 MPLS_ASSERT(0);
191 LRl_13:
192 LDP_EXIT(g->user_data, "ldp_label_release_process");
193 return retval;
196 mpls_return_enum ldp_label_withdraw_process(ldp_global * g, ldp_session * s,
197 ldp_adj * a, ldp_entity * e, ldp_attr * r_attr, ldp_fec * f)
199 mpls_bool label_exists = MPLS_BOOL_FALSE;
200 ldp_attr_list *ds_list = NULL;
201 ldp_attr *ds_attr = NULL;
202 ldp_attr *ds_temp = NULL;
203 ldp_attr *us_temp = NULL;
204 ldp_nexthop *nh = NULL;
205 mpls_return_enum retval = MPLS_SUCCESS;
207 LDP_ENTER(g->user_data, "ldp_label_withdraw_process");
209 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
210 "Withdraw Recv for %s\n", s->session_name);
212 if (r_attr->genLblTlvExists || r_attr->atmLblTlvExists
213 || r_attr->frLblTlvExists) {
214 label_exists = MPLS_BOOL_TRUE;
215 } else {
216 MPLS_ASSERT(0);
219 if (f) {
220 if ((ds_list = ldp_attr_find_downstream_all2(g, s, f)) != NULL) {
221 ds_temp = MPLS_LIST_HEAD(ds_list);
222 while (ds_temp) {
223 if (ds_temp->state == LDP_LSP_STATE_MAP_RECV) { /* LWd.3 */
224 if (ldp_attr_is_equal(r_attr, ds_temp, LDP_ATTR_LABEL)) {
225 ds_attr = ds_temp;
226 break;
229 ds_temp = MPLS_LIST_NEXT(ds_list, ds_temp, _fs);
233 if (!ds_attr) {
234 retval = MPLS_FAILURE;
235 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
236 "Withdraw Recv for a non-existant mapping from %s\n",s->session_name);
237 goto LWd_13;
241 * we want to remove it from the tree, but not delete it yet
242 * so hold a refcnt, we will release that refcnt at the end, thus
243 * deleting it if no one else it holding a refcnt
245 MPLS_REFCNT_HOLD(ds_attr);
246 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE); /* LWd.4 */
248 /* LWd.2 */
249 if (ldp_label_release_send(g, s, ds_attr, LDP_NOTIF_NONE) != MPLS_SUCCESS) {
250 retval = MPLS_FATAL;
251 goto LWd_13;
254 if (g->lsp_control_mode == LDP_CONTROL_ORDERED) { /* LWd.5 */
255 goto LWd_8;
258 if (s->oper_distribution_mode != LDP_DISTRIBUTION_ONDEMAND) { /* LWd.6 */
259 goto LWd_13;
262 MPLS_ASSERT((nh = ldp_nexthop_for_fec_session(f, s)));
263 retval = ldp_fec_process_add(g, f, nh, s); /* LWd.7 */
264 goto LWd_13;
266 LWd_8:
267 /* I can only propogate a label withdraw to the upstreams attached
268 to the downstream found above */
270 us_temp = MPLS_LIST_HEAD(&ds_attr->us_attr_root);
271 while (us_temp) {
272 if (us_temp->state == LDP_LSP_STATE_MAP_SENT) {
273 if (ldp_label_withdraw_send(g, us_temp->session, us_temp,
274 LDP_NOTIF_NONE) != MPLS_SUCCESS) { /* LWd.11 */
275 retval = MPLS_FATAL;
276 goto LWd_13;
279 us_temp = MPLS_LIST_NEXT(&ds_attr->us_attr_root, us_temp, _ds_attr);
281 } else {
282 /* JLEU: process wildcard FEC stuff here */
283 MPLS_ASSERT(0);
286 LWd_13:
287 if (ds_attr) {
288 MPLS_REFCNT_RELEASE2(g, ds_attr, ldp_attr_delete);
291 LDP_EXIT(g->user_data, "ldp_label_withdraw_process");
293 return retval;