Fixed next hop processing
[mpls-ldp-portable.git] / ldp / ldp_label_rel_with.c
blob038e50f033e840a252694464e699e5a2fb6823c7
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_label_mapping.h"
19 #include "ldp_fec.h"
20 #include "ldp_mesg.h"
21 #include "ldp_pdu_setup.h"
23 #include "mpls_trace_impl.h"
25 mpls_bool rel_with2attr(mplsLdpLbl_W_R_Msg_t * rw, ldp_attr * attr)
27 mpls_bool retval = MPLS_BOOL_FALSE;
29 if (rw->fecTlvExists) {
30 memcpy(&attr->fecTlv, &rw->fecTlv, sizeof(mplsLdpFecTlv_t));
31 attr->fecTlvExists = 1;
33 if (rw->genLblTlvExists) {
34 retval = MPLS_BOOL_TRUE;
35 memcpy(&attr->genLblTlv, &rw->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
36 attr->genLblTlvExists = 1;
37 } else if (rw->atmLblTlvExists) {
38 retval = MPLS_BOOL_TRUE;
39 memcpy(&attr->atmLblTlv, &rw->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
40 attr->atmLblTlvExists = 1;
41 } else if (rw->frLblTlvExists) {
42 retval = MPLS_BOOL_TRUE;
43 memcpy(&attr->frLblTlv, &rw->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
44 attr->frLblTlvExists = 1;
46 return retval;
49 void ldp_label_rel_with_prepare_msg(ldp_mesg * msg, uint32_t msgid,
50 ldp_attr * a, ldp_notif_status status, uint16_t type)
52 mplsLdpLbl_W_R_Msg_t *rw = NULL;
54 ldp_mesg_prepare(msg, type, msgid);
55 rw = &msg->u.release;
56 if (a->fecTlvExists) {
57 rw->fecTlvExists = 1;
58 rw->baseMsg.msgLength += setupFecTlv(&rw->fecTlv);
59 rw->baseMsg.msgLength += addFecElem2FecTlv(&rw->fecTlv,
60 &a->fecTlv.fecElArray[0]);
62 if (a->genLblTlvExists) {
63 rw->genLblTlvExists = 1;
64 rw->baseMsg.msgLength += setupGenLblTlv(&rw->genLblTlv, a->genLblTlv.label);
66 if (a->atmLblTlvExists) {
67 rw->atmLblTlvExists = 1;
68 rw->baseMsg.msgLength += setupAtmLblTlv(&rw->atmLblTlv, 0, 0,
69 a->atmLblTlv.flags.flags.vpi, a->atmLblTlv.vci);
71 if (a->frLblTlvExists) {
72 rw->frLblTlvExists = 1;
73 rw->baseMsg.msgLength += setupFrLblTlv(&rw->frLblTlv, 0,
74 a->frLblTlv.flags.flags.len, a->frLblTlv.flags.flags.dlci);
76 if (a->lspidTlvExists) {
77 rw->lspidTlvExists = 1;
78 rw->baseMsg.msgLength += setupLspidTlv(&rw->lspidTlv, 0,
79 a->lspidTlv.localCrlspId, a->lspidTlv.routerId);
83 mpls_return_enum ldp_label_rel_with_send(ldp_global * g, ldp_session * s,
84 ldp_attr * a, ldp_notif_status status, uint16_t type)
86 LDP_ENTER(g->user_data, "ldp_label_rel_with_send");
88 ldp_label_rel_with_prepare_msg(s->tx_message, g->message_identifier++, a,
89 status, type);
91 ldp_mesg_send_tcp(g, s, s->tx_message);
93 LDP_EXIT(g->user_data, "ldp_label_rel_with_send");
95 return MPLS_SUCCESS;
98 mpls_return_enum ldp_label_release_send(ldp_global * g, ldp_session * s,
99 ldp_attr * a, ldp_notif_status status)
102 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
103 "Release Sent: session(%d)\n", s->index);
105 return ldp_label_rel_with_send(g, s, a, status, MPLS_LBLREL_MSGTYPE);
108 mpls_return_enum ldp_label_withdraw_send(ldp_global * g, ldp_session * s,
109 ldp_attr * us_attr, ldp_notif_status status)
112 us_attr->state = LDP_LSP_STATE_WITH_SENT;
113 if (ldp_label_rel_with_send(g, s, us_attr, status, MPLS_LBLWITH_MSGTYPE) ==
114 MPLS_FAILURE) {
115 return MPLS_FAILURE;
118 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
119 "Withdraw Sent: session(%d)\n", s->index);
121 return MPLS_SUCCESS;
124 mpls_return_enum ldp_label_release_process(ldp_global * g, ldp_session * s,
125 ldp_adj * a, ldp_entity * e, ldp_attr * r_attr, mpls_fec * fec)
127 mpls_bool label_exists = MPLS_BOOL_FALSE;
128 ldp_attr *us_attr = NULL;
129 ldp_attr *ds_attr = NULL;
130 mpls_return_enum retval = MPLS_SUCCESS;
132 LDP_ENTER(g->user_data, "ldp_label_release_process");
134 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
135 "Release Recv from %s\n", s->session_name);
137 if (r_attr->genLblTlvExists || r_attr->atmLblTlvExists
138 || r_attr->frLblTlvExists) {
139 label_exists = MPLS_BOOL_TRUE;
142 if (fec) {
143 /* LRl.1 is accomplished at LRl.10 */
144 us_attr = ldp_attr_find_upstream_state(g, s, fec, LDP_LSP_STATE_MAP_SENT);
145 if (!us_attr) {
146 us_attr =
147 ldp_attr_find_upstream_state(g, s, fec, LDP_LSP_STATE_WITH_SENT);
148 if (!us_attr) { /* LRl.2 */
149 goto LRl_13;
151 /* LRl.3 is accomplished at LRl.10 */
154 if (g->label_merge == MPLS_BOOL_FALSE) { /* LR1.4 */
155 goto LRl_6;
157 /* LR1.5 */
158 if (ldp_attr_find_upstream_state_any(g, fec, LDP_LSP_STATE_MAP_SENT)) {
159 goto LRl_10;
162 LRl_6:
163 /* we can only propogate a release to the downstream attached to
164 the upstream we found up top */
165 /* LRl.6,7 */
166 if (us_attr->ds_attr && us_attr->ds_attr->state == LDP_LSP_STATE_MAP_RECV) {
167 ds_attr = us_attr->ds_attr;
168 } else {
169 goto LRl_10;
172 if (g->propagate_release == MPLS_BOOL_FALSE) { /* LRl.8 */
173 goto LRl_10;
176 if (ldp_label_release_send(g, ds_attr->session, ds_attr, LDP_NOTIF_NONE) != MPLS_SUCCESS) { /* LRl.9 */
177 retval = MPLS_FAILURE;
179 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE);
181 LRl_10:
182 ldp_attr_remove_complete(g, us_attr, MPLS_BOOL_FALSE); /* LRl.10,11 */
184 } else {
185 LDP_PRINT(g->user_data, "No FEC in release, need to implement\n");
186 MPLS_ASSERT(0);
189 LRl_13:
190 LDP_EXIT(g->user_data, "ldp_label_release_process");
191 return retval;
194 mpls_return_enum ldp_label_withdraw_process(ldp_global * g, ldp_session * s,
195 ldp_adj * a, ldp_entity * e, ldp_attr * r_attr, mpls_fec * fec)
197 mpls_bool label_exists = MPLS_BOOL_FALSE;
198 ldp_attr_list *ds_list = NULL;
199 ldp_attr *ds_attr = NULL;
200 ldp_attr *ds_temp = NULL;
201 ldp_attr *us_temp = NULL;
202 mpls_return_enum retval = MPLS_SUCCESS;
204 LDP_ENTER(g->user_data, "ldp_label_withdraw_process");
206 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
207 "Withdraw Recv for %s\n", s->session_name);
209 if (r_attr->genLblTlvExists || r_attr->atmLblTlvExists
210 || r_attr->frLblTlvExists) {
211 label_exists = MPLS_BOOL_TRUE;
212 } else {
213 MPLS_ASSERT(0);
216 if (fec) {
217 if ((ds_list = ldp_attr_find_downstream_all(g, s, fec)) != NULL) {
218 ds_temp = MPLS_LIST_HEAD(ds_list);
219 while (ds_temp) {
220 if (ds_temp->state == LDP_LSP_STATE_MAP_RECV) { /* LWd.3 */
221 if (ldp_attr_is_equal(r_attr, ds_temp, LDP_ATTR_LABEL)) {
222 ds_attr = ds_temp;
225 ds_temp = MPLS_LIST_NEXT(ds_list, ds_temp, _fs);
229 if (!ds_attr) {
230 retval = MPLS_FAILURE;
231 goto LWd_13;
234 if (ldp_label_release_send(g, s, ds_attr, LDP_NOTIF_NONE) != MPLS_SUCCESS) {
235 retval = MPLS_FAILURE;
236 goto LWd_13;
239 if (g->lsp_control_mode == LDP_CONTROL_ORDERED) { /* LWd.5 */
240 goto LWd_8;
243 if (s->oper_distribution_mode != LDP_DISTRIBUTION_ONDEMAND) { /* LWd.6 */
244 goto LWd_13;
247 Detect_Change_Fec_Next_Hop(g, fec, s); /* LWd.7 */
248 goto LWd_13;
250 LWd_8:
251 /* I can only propogate a label withdraw to the upstreams attached
252 to the downstream found above */
254 us_temp = MPLS_LIST_HEAD(&ds_attr->us_attr_root);
255 while (us_temp) {
256 if (us_temp->state == LDP_LSP_STATE_MAP_SENT) {
257 if (ldp_label_withdraw_send(g, us_temp->session, us_temp,
258 LDP_NOTIF_NONE) != MPLS_SUCCESS) { /* LWd.11 */
259 retval = MPLS_FAILURE;
260 goto LWd_13;
263 us_temp = MPLS_LIST_NEXT(&ds_attr->us_attr_root, us_temp, _ds_attr);
265 } else {
266 /* JLEU: process wildcard FEC stuff here */
267 MPLS_ASSERT(0);
270 LWd_13:
272 if (ds_attr) {
273 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE); /* LWd.4 */
275 LDP_EXIT(g->user_data, "ldp_label_withdraw_process");
277 return retval;