Updated label mapping to better support the new fec -> nh relationship
[mpls-ldp-portable.git] / ldp / ldp_notif.c
blob6827b8f86df2b7cde4f5c59cb548bc5ff3de3eb2
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_session.h"
14 #include "ldp_nexthop.h"
15 #include "ldp_entity.h"
16 #include "ldp_mesg.h"
17 #include "ldp_pdu_setup.h"
18 #include "ldp_label_request.h"
19 #include "ldp_label_mapping.h"
20 #include "ldp_fec.h"
22 #include "mpls_trace_impl.h"
23 #include "mpls_timer_impl.h"
25 void ldp_notif_prepare_msg(ldp_mesg * msg, uint32_t msgid, ldp_attr * r_attr,
26 ldp_notif_status status)
28 mplsLdpNotifMsg_t *notif = NULL;
29 int error, forward = 0;
30 uint32_t msg_type = 0;
31 uint32_t msg_id = 0;
33 ldp_mesg_prepare(msg, MPLS_NOT_MSGTYPE, msgid);
34 notif = &msg->u.notif;
36 notif->statusTlvExists = 1;
38 /* we have to pass two more parameters one is F bit and other is E bit
39 E = 1 if it is a fatal error, 0 is for advisory notification
40 F = 1 then notification has to be forwarded. */
42 /* check to set the E bit */
43 if (status == LDP_NOTIF_SUCCESS ||
44 status == LDP_NOTIF_UNKNOWN_MESG ||
45 status == LDP_NOTIF_UNKNOWN_TVL ||
46 status == LDP_NOTIF_LOOP_DETECTED ||
47 status == LDP_NOTIF_UNKNOWN_FEC ||
48 status == LDP_NOTIF_NO_ROUTE ||
49 status == LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE ||
50 status == LDP_NOTIF_LABEL_RESOURCES_AVAILABLE ||
51 status == LDP_NOTIF_LABEL_ABORT ||
52 status == LDP_NOTIF_MISSING_MSG_PARAMS || status == LDP_NOTIF_UNSUPORTED_AF) {
53 error = 0;
54 } else {
55 error = 1;
58 /* check to set the F bit */
59 if (status == LDP_NOTIF_LOOP_DETECTED ||
60 status == LDP_NOTIF_UNKNOWN_FEC || status == LDP_NOTIF_NO_ROUTE) {
61 forward = 1;
62 } else {
63 forward = 0;
66 if (r_attr) {
67 switch (r_attr->state) {
68 case LDP_LSP_STATE_ABORT_RECV:
69 msg_type = MPLS_LBLABORT_MSGTYPE;
70 msg_id = r_attr->msg_id;
71 break;
72 default:
73 msg_type = 0;
76 notif->baseMsg.msgLength += setupStatusTlv(&notif->status, error, forward,
77 status, msg_id, msg_type);
79 /* We have to insert other tlv's like retpdu,extended status, returned
80 message
81 notif->exStatusTlvExists = 1;
82 notif->retPduTlvExists = 1;
86 mpls_return_enum ldp_notif_send(ldp_global * g, ldp_session * s,
87 ldp_attr * r_attr, ldp_notif_status status)
89 LDP_ENTER(g->user_data, "ldp_notif_send");
91 ldp_notif_prepare_msg(s->tx_message, g->message_identifier++, r_attr, status);
93 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
94 "Notification Sent(%d)\n", s->index);
96 if (ldp_mesg_send_tcp(g, s, s->tx_message) == MPLS_FAILURE) {
97 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ERROR,
98 "Notification Send failed\n");
99 goto ldp_notif_send_error;
102 LDP_EXIT(g->user_data, "ldp_notif_send");
103 return MPLS_SUCCESS;
105 ldp_notif_send_error:
107 LDP_EXIT(g->user_data, "ldp_notif_send_error");
108 return MPLS_FAILURE;
111 void not2attr(mplsLdpNotifMsg_t * not, ldp_attr * attr, uint32_t flag)
113 attr->msg_id = not->baseMsg.msgId;
115 if (not->statusTlvExists && flag & LDP_ATTR_STATUS) {
116 memcpy(&attr->statusTlv, &not->status, sizeof(mplsLdpStatusTlv_t));
117 attr->statusTlvExists = 1;
119 if (not->lspidTlvExists && flag & LDP_ATTR_LSPID) {
120 memcpy(&attr->lspidTlv, &not->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
121 attr->lspidTlvExists = 1;
124 if (not->retMsgTlvExists && flag & LDP_ATTR_MSGID) {
125 memcpy(&attr->retMsgTlv, &not->retMsg, sizeof(mplsLdpLblMsgIdTlv_t));
126 attr->retMsgTlvExists = 1;
128 /* Attribute types are not defined in ldp_attr.h file need to
129 define these optional Tlv types */
131 /*if(not->exStatusTlvExists && flag & LDP_ATTR_HOPCOUNT) {
132 memcpy(&attr->exStatus,&not->exStatus,sizeof(mplsLdpHopTlv_t));
133 attr->exStatusTlvExists = 1;
135 if(not->retPduTlvExists && flag & LDP_ATTR_PATH) {
136 memcpy(&attr->retPdu,&not->retPdu,sizeof(mplsLdpPathTlv_t));
137 attr->retPduTlvExists = 1;
138 } */
141 mpls_return_enum ldp_notif_process(ldp_global * g, ldp_session * s,
142 ldp_adj * a, ldp_entity * e, ldp_attr * r_attr)
144 mpls_return_enum retval = MPLS_SUCCESS;
145 int status;
147 LDP_ENTER(g->user_data, "ldp_notif_process");
149 status = r_attr->statusTlv.flags.flags.status;
151 switch (status) {
152 case LDP_NOTIF_LABEL_ABORT:
153 retval = ldp_notif_label_request_aborted(g, s, r_attr);
154 break;
155 case LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE:
156 retval = ldp_notif_no_label_resources(g, s, r_attr);
157 break;
158 case LDP_NOTIF_NO_ROUTE:
159 case LDP_NOTIF_LOOP_DETECTED:
160 retval = ldp_notif_no_route(g, s, e, r_attr);
161 break;
162 case LDP_NOTIF_LABEL_RESOURCES_AVAILABLE:
163 retval = ldp_notif_label_resources_available(g, s, r_attr);
164 break;
165 case LDP_NOTIF_SUCCESS:
166 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SUCCESS:\n");
167 break;
168 case LDP_NOTIF_BAD_LDP_ID:
169 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_LDP_ID:\n");
170 break;
171 case LDP_NOTIF_BAD_PROTO:
172 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_PROTO:\n");
173 break;
174 case LDP_NOTIF_BAD_PDU_LEN:
175 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_PDU_LEN:\n");
176 break;
177 case LDP_NOTIF_UNKNOWN_MESG:
178 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNKNOWN_MESG:\n");
179 break;
180 case LDP_NOTIF_BAD_MESG_LEN:
181 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_MESG_LEN:\n");
182 break;
183 case LDP_NOTIF_UNKNOWN_TVL:
184 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNKNOWN_TVL:\n");
185 break;
186 case LDP_NOTIF_BAD_TLV_LEN:
187 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_BAD_TLV_LEN:\n");
188 break;
189 case LDP_NOTIF_MALFORMED_TLV:
190 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_MALFORMED_TLV:\n");
191 break;
192 case LDP_NOTIF_HOLD_TIMER_EXPIRED:
193 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_HOLD_TIMER_EXPIRED:\n");
194 break;
195 case LDP_NOTIF_SHUTDOWN:
196 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SHUTDOWN:\n");
197 break;
198 case LDP_NOTIF_UNKNOWN_FEC:
199 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNKNOWN_FEC:\n");
200 break;
201 case LDP_NOTIF_SESSION_REJECTED_NO_HELLO:
202 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_NO_HELLO:\n");
203 break;
204 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE:
205 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE:\n");
206 break;
207 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_MAX_PDU_LEN:
208 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_MAX_PDU_LEN:\n");
209 break;
210 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE:
211 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE:\n");
212 break;
213 case LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED:
214 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED:\n");
215 break;
216 case LDP_NOTIF_MISSING_MSG_PARAMS:
217 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_MISSING_MSG_PARAMS:\n");
218 break;
219 case LDP_NOTIF_UNSUPORTED_AF:
220 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_UNSUPORTED_AF:\n");
221 break;
222 case LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME:
223 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME:\n");
224 break;
225 case LDP_NOTIF_INTERNAL_ERROR:
226 LDP_TRACE_OUT(g->user_data, "LDP_NOTIF_INTERNAL_ERROR\n");
227 break;
228 default:
229 LDP_TRACE_OUT(g->user_data, "Receive an unknown notification: %08x\n",
230 status);
231 retval = MPLS_SUCCESS;
232 break;
235 LDP_EXIT(g->user_data, "ldp_notif_process");
236 return retval;
239 mpls_return_enum ldp_notif_label_request_aborted(ldp_global * g, ldp_session * s,
240 ldp_attr * r_attr)
242 ldp_attr *ds_attr = NULL;
244 LDP_ENTER(g->user_data, "ldp_notif_label_request_aborted");
246 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
247 while (ds_attr != NULL) {
248 if (ds_attr->state == LDP_LSP_STATE_ABORT_SENT &&
249 ds_attr->msg_id == r_attr->msg_id) {
250 break;
252 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
255 if (ds_attr) { /* LRqA.1 */
256 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE); /* LRqA.2 */
258 LDP_EXIT(g->user_data, "ldp_notif_label_request_aborted");
259 return MPLS_SUCCESS;
262 LDP_EXIT(g->user_data, "ldp_notif_label_request_abort_error");
263 return MPLS_FAILURE;
266 mpls_return_enum ldp_notif_no_label_resources(ldp_global * g, ldp_session * s,
267 ldp_attr * s_attr)
269 ldp_attr_list *ds_list = NULL;
270 ldp_attr *ds_attr = NULL;
271 mpls_fec nfec;
273 LDP_ENTER(g->user_data, "ldp_notif_no_label_resources");
275 fec_tlv2mpls_fec(&s_attr->fecTlv, 0, &nfec);
276 /* NoRes.1 do not actually remove from tree, just change it's state */
278 if ((ds_list = ldp_attr_find_downstream_all(g, s, &nfec))) {
279 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
280 while (ds_attr) {
281 if (ds_attr->state == LDP_LSP_STATE_REQ_SENT) {
282 ds_attr->state = LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV; /* NoRes.2 */
284 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
288 s->no_label_resource_recv = MPLS_BOOL_TRUE; /* NoRes.3 */
290 LDP_EXIT(g->user_data, "ldp_notif_no_label_resource_error");
291 return MPLS_SUCCESS;
294 mpls_return_enum ldp_notif_no_route(ldp_global * g, ldp_session * s,
295 ldp_entity * e, ldp_attr * s_attr)
297 ldp_attr *ds_attr = NULL;
298 ldp_attr_list *ds_list = NULL;
299 mpls_fec nfec;
300 mpls_return_enum retval = MPLS_FAILURE;
302 LDP_ENTER(g->user_data, "ldp_notif_no_route\n");
304 fec_tlv2mpls_fec(&s_attr->fecTlv, 0, &nfec);
306 if ((ds_list = ldp_attr_find_downstream_all(g, s, &nfec))) {
307 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
308 while (ds_attr) {
309 if (ds_attr->state == LDP_LSP_STATE_REQ_SENT) {
310 if (e->label_request_count) {
311 if (ds_attr->attempt_count < e->label_request_count) {
312 if (mpls_timer_handle_verify(g->timer_handle,
313 ds_attr->action_timer) == MPLS_BOOL_FALSE) {
314 ds_attr->action_timer =
315 mpls_timer_create(g->timer_handle, MPLS_UNIT_SEC,
316 s->cfg_label_request_timer, (void *)ds_attr, g,
317 ldp_attr_action_callback);
319 mpls_timer_start(g->timer_handle, ds_attr->action_timer,
320 MPLS_TIMER_ONESHOT);
322 retval = MPLS_SUCCESS;
323 } else {
324 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE);
325 retval = MPLS_FAILURE;
328 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
332 LDP_EXIT(g->user_data, "ldp_notif_no_route\n");
333 return retval;
336 /* IV. Receive Notification/ Loop Detected */
338 /* Algo: Same as receive Notification/No Route */
340 mpls_return_enum ldp_notif_label_resources_available(ldp_global * g,
341 ldp_session * s, ldp_attr * r_attr)
343 ldp_session *nh_session = NULL;
344 ldp_attr *ds_attr = NULL;
345 ldp_nexthop *nh = NULL;
346 ldp_fec *f = NULL;
348 LDP_ENTER(g->user_data, "ldp_notif_label_resources_available");
350 s->no_label_resource_recv = MPLS_BOOL_FALSE; /* Res.1 */
352 ds_attr = MPLS_LIST_HEAD(&s->attr_root);
353 while (ds_attr != NULL) { /* Res.2 */
354 if (ds_attr->state == LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV) {
355 f = ds_attr->fec;
356 nh = MPLS_LIST_HEAD(&f->nh_root);
357 while (nh) {
358 nh_session = ldp_session_for_nexthop(nh);
359 if (nh_session && (nh_session->index == s->index)) {
360 /* Res.4 */
361 if (ldp_label_request_send(g, s, ds_attr, NULL) != MPLS_SUCCESS) {
362 MPLS_ASSERT(0);
364 } else {
365 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE);/* Res.5 */
367 nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec);
370 ds_attr = MPLS_LIST_NEXT(&s->attr_root, ds_attr, _fs);
371 } /* Res.6 */
373 LDP_EXIT(g->user_data, "ldp_notif_label_resources_available");
374 return MPLS_SUCCESS;