Convertion to a ECMP capable infrastructure compiles (no testing
[mpls-ldp-portable.git] / ldp / ldp_notif.c
blobfb1eab1c1c7414e6423eeae40cb92cf300103eff
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_notif.h"
12 #include "ldp_attr.h"
13 #include "ldp_nexthop.h"
14 #include "ldp_entity.h"
15 #include "ldp_mesg.h"
16 #include "ldp_pdu_setup.h"
17 #include "ldp_label_request.h"
18 #include "ldp_label_mapping.h"
19 #include "ldp_fec.h"
21 #include "mpls_trace_impl.h"
22 #include "mpls_timer_impl.h"
24 void ldp_notif_prepare_msg(ldp_mesg * msg, uint32_t msgid, ldp_attr * r_attr,
25 ldp_notif_status status)
27 mplsLdpNotifMsg_t *notif = NULL;
28 int error, forward = 0;
29 uint32_t msg_type = 0;
30 uint32_t msg_id = 0;
32 ldp_mesg_prepare(msg, MPLS_NOT_MSGTYPE, msgid);
33 notif = &msg->u.notif;
35 notif->statusTlvExists = 1;
37 /* we have to pass two more parameters one is F bit and other is E bit
38 E = 1 if it is a fatal error, 0 is for advisory notification
39 F = 1 then notification has to be forwarded. */
41 /* check to set the E bit */
42 if (status == LDP_NOTIF_SUCCESS ||
43 status == LDP_NOTIF_UNKNOWN_MESG ||
44 status == LDP_NOTIF_UNKNOWN_TVL ||
45 status == LDP_NOTIF_LOOP_DETECTED ||
46 status == LDP_NOTIF_UNKNOWN_FEC ||
47 status == LDP_NOTIF_NO_ROUTE ||
48 status == LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE ||
49 status == LDP_NOTIF_LABEL_RESOURCES_AVAILABLE ||
50 status == LDP_NOTIF_LABEL_ABORT ||
51 status == LDP_NOTIF_MISSING_MSG_PARAMS || status == LDP_NOTIF_UNSUPORTED_AF) {
52 error = 0;
53 } else {
54 error = 1;
57 /* check to set the F bit */
58 if (status == LDP_NOTIF_LOOP_DETECTED ||
59 status == LDP_NOTIF_UNKNOWN_FEC || status == LDP_NOTIF_NO_ROUTE) {
60 forward = 1;
61 } else {
62 forward = 0;
65 if (r_attr) {
66 switch (r_attr->state) {
67 case LDP_LSP_STATE_ABORT_RECV:
68 msg_type = MPLS_LBLABORT_MSGTYPE;
69 msg_id = r_attr->msg_id;
70 break;
71 default:
72 msg_type = 0;
75 notif->baseMsg.msgLength += setupStatusTlv(&notif->status, error, forward,
76 status, msg_id, msg_type);
78 /* We have to insert other tlv's like retpdu,extended status, returned
79 message
80 notif->exStatusTlvExists = 1;
81 notif->retPduTlvExists = 1;
85 mpls_return_enum ldp_notif_send(ldp_global * g, ldp_session * s,
86 ldp_attr * r_attr, ldp_notif_status status)
88 LDP_ENTER(g->user_data, "ldp_notif_send");
90 ldp_notif_prepare_msg(s->tx_message, g->message_identifier++, r_attr, status);
92 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
93 "Notification Sent(%d)\n", s->index);
95 if (ldp_mesg_send_tcp(g, s, s->tx_message) == MPLS_FAILURE) {
96 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ERROR,
97 "Notification Send failed\n");
98 goto ldp_notif_send_error;
101 LDP_EXIT(g->user_data, "ldp_notif_send");
102 return MPLS_SUCCESS;
104 ldp_notif_send_error:
106 LDP_EXIT(g->user_data, "ldp_notif_send_error");
107 return MPLS_FAILURE;
110 void not2attr(mplsLdpNotifMsg_t * not, ldp_attr * attr, uint32_t flag)
112 attr->msg_id = not->baseMsg.msgId;
114 if (not->statusTlvExists && flag & LDP_ATTR_STATUS) {
115 memcpy(&attr->statusTlv, &not->status, sizeof(mplsLdpStatusTlv_t));
116 attr->statusTlvExists = 1;
118 if (not->lspidTlvExists && flag & LDP_ATTR_LSPID) {
119 memcpy(&attr->lspidTlv, &not->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
120 attr->lspidTlvExists = 1;
123 if (not->retMsgTlvExists && flag & LDP_ATTR_MSGID) {
124 memcpy(&attr->retMsgTlv, &not->retMsg, sizeof(mplsLdpLblMsgIdTlv_t));
125 attr->retMsgTlvExists = 1;
127 /* Attribute types are not defined in ldp_attr.h file need to
128 define these optional Tlv types */
130 /*if(not->exStatusTlvExists && flag & LDP_ATTR_HOPCOUNT) {
131 memcpy(&attr->exStatus,&not->exStatus,sizeof(mplsLdpHopTlv_t));
132 attr->exStatusTlvExists = 1;
134 if(not->retPduTlvExists && flag & LDP_ATTR_PATH) {
135 memcpy(&attr->retPdu,&not->retPdu,sizeof(mplsLdpPathTlv_t));
136 attr->retPduTlvExists = 1;
137 } */
140 mpls_return_enum ldp_notif_process(ldp_global * g, ldp_session * s,
141 ldp_adj * a, ldp_entity * e, ldp_attr * r_attr)
143 mpls_return_enum retval = MPLS_SUCCESS;
144 int status;
146 LDP_ENTER(g->user_data, "ldp_notif_process");
148 status = r_attr->statusTlv.flags.flags.status;
150 switch (status) {
151 case LDP_NOTIF_LABEL_ABORT:
152 retval = ldp_notif_label_request_aborted(g, s, r_attr);
153 break;
154 case LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE:
155 retval = ldp_notif_no_label_resources(g, s, r_attr);
156 break;
157 case LDP_NOTIF_NO_ROUTE:
158 case LDP_NOTIF_LOOP_DETECTED:
159 retval = ldp_notif_no_route(g, s, e, r_attr);
160 break;
161 case LDP_NOTIF_LABEL_RESOURCES_AVAILABLE:
162 retval = ldp_notif_label_resources_available(g, s, r_attr);
163 break;
164 case LDP_NOTIF_SUCCESS:
165 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SUCCESS:\n");
166 break;
167 case LDP_NOTIF_BAD_LDP_ID:
168 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_LDP_ID:\n");
169 break;
170 case LDP_NOTIF_BAD_PROTO:
171 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_PROTO:\n");
172 break;
173 case LDP_NOTIF_BAD_PDU_LEN:
174 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_PDU_LEN:\n");
175 break;
176 case LDP_NOTIF_UNKNOWN_MESG:
177 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNKNOWN_MESG:\n");
178 break;
179 case LDP_NOTIF_BAD_MESG_LEN:
180 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_MESG_LEN:\n");
181 break;
182 case LDP_NOTIF_UNKNOWN_TVL:
183 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNKNOWN_TVL:\n");
184 break;
185 case LDP_NOTIF_BAD_TLV_LEN:
186 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_TLV_LEN:\n");
187 break;
188 case LDP_NOTIF_MALFORMED_TLV:
189 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_MALFORMED_TLV:\n");
190 break;
191 case LDP_NOTIF_HOLD_TIMER_EXPIRED:
192 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_HOLD_TIMER_EXPIRED:\n");
193 break;
194 case LDP_NOTIF_SHUTDOWN:
195 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SHUTDOWN:\n");
196 break;
197 case LDP_NOTIF_UNKNOWN_FEC:
198 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNKNOWN_FEC:\n");
199 break;
200 case LDP_NOTIF_SESSION_REJECTED_NO_HELLO:
201 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_NO_HELLO:\n");
202 break;
203 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE:
204 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE:\n");
205 break;
206 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_MAX_PDU_LEN:
207 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_MAX_PDU_LEN:\n");
208 break;
209 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE:
210 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE:\n");
211 break;
212 case LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED:
213 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED:\n");
214 break;
215 case LDP_NOTIF_MISSING_MSG_PARAMS:
216 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_MISSING_MSG_PARAMS:\n");
217 break;
218 case LDP_NOTIF_UNSUPORTED_AF:
219 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNSUPORTED_AF:\n");
220 break;
221 case LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME:
222 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME:\n");
223 break;
224 case LDP_NOTIF_INTERNAL_ERROR:
225 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_INTERNAL_ERROR\n");
226 break;
227 default:
228 LDP_TRACE_OUT(g->user_data, "Receive an unknown notification: %08x\n",
229 status);
230 retval = MPLS_SUCCESS;
231 break;
234 LDP_EXIT(g->user_data, "ldp_notif_process");
235 return retval;
238 mpls_return_enum ldp_notif_label_request_aborted(ldp_global * g, ldp_session * s,
239 ldp_attr * r_attr)
241 ldp_attr *ds_attr = NULL;
243 LDP_ENTER(g->user_data, "ldp_notif_label_request_aborted");
245 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
246 while (ds_attr != NULL) {
247 if (ds_attr->state == LDP_LSP_STATE_ABORT_SENT &&
248 ds_attr->msg_id == r_attr->msg_id) {
249 break;
251 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
254 if (ds_attr) { /* LRqA.1 */
255 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE); /* LRqA.2 */
257 LDP_EXIT(g->user_data, "ldp_notif_label_request_aborted");
258 return MPLS_SUCCESS;
261 LDP_EXIT(g->user_data, "ldp_notif_label_request_abort_error");
262 return MPLS_FAILURE;
265 mpls_return_enum ldp_notif_no_label_resources(ldp_global * g, ldp_session * s,
266 ldp_attr * s_attr)
268 ldp_attr_list *ds_list = NULL;
269 ldp_attr *ds_attr = NULL;
270 mpls_fec nfec;
272 LDP_ENTER(g->user_data, "ldp_notif_no_label_resources");
274 fec_tlv2mpls_fec(&s_attr->fecTlv, 0, &nfec);
275 /* NoRes.1 do not actually remove from tree, just change it's state */
277 if ((ds_list = ldp_attr_find_downstream_all(g, s, &nfec))) {
278 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
279 while (ds_attr) {
280 if (ds_attr->state == LDP_LSP_STATE_REQ_SENT) {
281 ds_attr->state = LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV; /* NoRes.2 */
283 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
287 s->no_label_resource_recv = MPLS_BOOL_TRUE; /* NoRes.3 */
289 LDP_EXIT(g->user_data, "ldp_notif_no_label_resource_error");
290 return MPLS_SUCCESS;
293 mpls_return_enum ldp_notif_no_route(ldp_global * g, ldp_session * s,
294 ldp_entity * e, ldp_attr * s_attr)
296 ldp_attr *ds_attr = NULL;
297 ldp_attr_list *ds_list = NULL;
298 mpls_fec nfec;
299 mpls_return_enum retval = MPLS_FAILURE;
301 LDP_ENTER(g->user_data, "ldp_notif_no_route\n");
303 fec_tlv2mpls_fec(&s_attr->fecTlv, 0, &nfec);
305 if ((ds_list = ldp_attr_find_downstream_all(g, s, &nfec))) {
306 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
307 while (ds_attr) {
308 if (ds_attr->state == LDP_LSP_STATE_REQ_SENT) {
309 if (e->label_request_count) {
310 if (ds_attr->attempt_count < e->label_request_count) {
311 if (mpls_timer_handle_verify(g->timer_handle,
312 ds_attr->action_timer) == MPLS_BOOL_FALSE) {
313 ds_attr->action_timer =
314 mpls_timer_create(g->timer_handle, MPLS_UNIT_SEC,
315 s->cfg_label_request_timer, (void *)ds_attr, g,
316 ldp_attr_action_callback);
318 mpls_timer_start(g->timer_handle, ds_attr->action_timer,
319 MPLS_TIMER_ONESHOT);
321 retval = MPLS_SUCCESS;
322 } else {
323 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE);
324 retval = MPLS_FAILURE;
327 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
331 LDP_EXIT(g->user_data, "ldp_notif_no_route\n");
332 return retval;
335 /* IV. Receive Notification/ Loop Detected */
337 /* Algo: Same as receive Notification/No Route */
339 mpls_return_enum ldp_notif_label_resources_available(ldp_global * g,
340 ldp_session * s, ldp_attr * r_attr)
342 ldp_session *nh_session = NULL;
343 ldp_attr *ds_attr = NULL;
344 ldp_nexthop *nh = NULL;
345 ldp_fec *f = NULL;
347 LDP_ENTER(g->user_data, "ldp_notif_label_resources_available");
349 s->no_label_resource_recv = MPLS_BOOL_FALSE; /* Res.1 */
351 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
352 while (ds_attr != NULL) { /* Res.2 */
353 if (ds_attr->state == LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV) {
354 f = ds_attr->fec;
355 nh = MPLS_LIST_HEAD(&f->nh_root);
356 while (nh) {
357 nh_session = ldp_session_for_nexthop(nh);
358 if (nh_session && (nh_session->index == s->index)) {
359 /* Res.4 */
360 if (ldp_label_request_send(g, s, ds_attr, NULL) != MPLS_SUCCESS) {
361 MPLS_ASSERT(0);
363 } else {
364 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE);/* Res.5 */
366 nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec);
369 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
370 } /* Res.6 */
372 LDP_EXIT(g->user_data, "ldp_notif_label_resources_available");
373 return MPLS_SUCCESS;