3 * Copyright (C) James R. Leu 2000
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
10 #include "ldp_struct.h"
11 #include "ldp_notif.h"
13 #include "ldp_entity.h"
15 #include "ldp_pdu_setup.h"
16 #include "ldp_label_request.h"
17 #include "ldp_label_mapping.h"
20 #include "mpls_trace_impl.h"
21 #include "mpls_timer_impl.h"
23 void ldp_notif_prepare_msg(ldp_mesg
* msg
, uint32_t msgid
, ldp_attr
* r_attr
,
24 ldp_notif_status status
)
26 mplsLdpNotifMsg_t
*notif
= NULL
;
27 int error
, forward
= 0;
28 uint32_t msg_type
= 0;
31 ldp_mesg_prepare(msg
, MPLS_NOT_MSGTYPE
, msgid
);
32 notif
= &msg
->u
.notif
;
34 notif
->statusTlvExists
= 1;
36 /* we have to pass two more parameters one is F bit and other is E bit
37 E = 1 if it is a fatal error, 0 is for advisory notification
38 F = 1 then notification has to be forwarded. */
40 /* check to set the E bit */
41 if (status
== LDP_NOTIF_SUCCESS
||
42 status
== LDP_NOTIF_UNKNOWN_MESG
||
43 status
== LDP_NOTIF_UNKNOWN_TVL
||
44 status
== LDP_NOTIF_LOOP_DETECTED
||
45 status
== LDP_NOTIF_UNKNOWN_FEC
||
46 status
== LDP_NOTIF_NO_ROUTE
||
47 status
== LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE
||
48 status
== LDP_NOTIF_LABEL_RESOURCES_AVAILABLE
||
49 status
== LDP_NOTIF_LABEL_ABORT
||
50 status
== LDP_NOTIF_MISSING_MSG_PARAMS
|| status
== LDP_NOTIF_UNSUPORTED_AF
) {
56 /* check to set the F bit */
57 if (status
== LDP_NOTIF_LOOP_DETECTED
||
58 status
== LDP_NOTIF_UNKNOWN_FEC
|| status
== LDP_NOTIF_NO_ROUTE
) {
65 switch (r_attr
->state
) {
66 case LDP_LSP_STATE_ABORT_RECV
:
67 msg_type
= MPLS_LBLABORT_MSGTYPE
;
68 msg_id
= r_attr
->msg_id
;
74 notif
->baseMsg
.msgLength
+= setupStatusTlv(¬if
->status
, error
, forward
,
75 status
, msg_id
, msg_type
);
77 /* We have to insert other tlv's like retpdu,extended status, returned
79 notif->exStatusTlvExists = 1;
80 notif->retPduTlvExists = 1;
84 mpls_return_enum
ldp_notif_send(ldp_global
* g
, ldp_session
* s
,
85 ldp_attr
* r_attr
, ldp_notif_status status
)
87 LDP_ENTER(g
->user_data
, "ldp_notif_send");
89 ldp_notif_prepare_msg(s
->tx_message
, g
->message_identifier
++, r_attr
, status
);
91 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
92 "Notification Sent(%d)\n", s
->index
);
94 if (ldp_mesg_send_tcp(g
, s
, s
->tx_message
) == MPLS_FAILURE
) {
95 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ERROR
,
96 "Notification Send failed\n");
97 goto ldp_notif_send_error
;
100 LDP_EXIT(g
->user_data
, "ldp_notif_send");
103 ldp_notif_send_error
:
105 LDP_EXIT(g
->user_data
, "ldp_notif_send_error");
109 void not2attr(mplsLdpNotifMsg_t
* not, ldp_attr
* attr
, uint32_t flag
)
111 attr
->msg_id
= not->baseMsg
.msgId
;
113 if (not->statusTlvExists
&& flag
& LDP_ATTR_STATUS
) {
114 memcpy(&attr
->statusTlv
, ¬->status
, sizeof(mplsLdpStatusTlv_t
));
115 attr
->statusTlvExists
= 1;
117 if (not->lspidTlvExists
&& flag
& LDP_ATTR_LSPID
) {
118 memcpy(&attr
->lspidTlv
, ¬->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
119 attr
->lspidTlvExists
= 1;
122 if (not->retMsgTlvExists
&& flag
& LDP_ATTR_MSGID
) {
123 memcpy(&attr
->retMsgTlv
, ¬->retMsg
, sizeof(mplsLdpLblMsgIdTlv_t
));
124 attr
->retMsgTlvExists
= 1;
126 /* Attribute types are not defined in ldp_attr.h file need to
127 define these optional Tlv types */
129 /*if(not->exStatusTlvExists && flag & LDP_ATTR_HOPCOUNT) {
130 memcpy(&attr->exStatus,¬->exStatus,sizeof(mplsLdpHopTlv_t));
131 attr->exStatusTlvExists = 1;
133 if(not->retPduTlvExists && flag & LDP_ATTR_PATH) {
134 memcpy(&attr->retPdu,¬->retPdu,sizeof(mplsLdpPathTlv_t));
135 attr->retPduTlvExists = 1;
139 mpls_return_enum
ldp_notif_process(ldp_global
* g
, ldp_session
* s
,
140 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* r_attr
)
142 mpls_return_enum retval
= MPLS_SUCCESS
;
145 LDP_ENTER(g
->user_data
, "ldp_notif_process");
147 status
= r_attr
->statusTlv
.flags
.flags
.status
;
150 case LDP_NOTIF_LABEL_ABORT
:
151 retval
= ldp_notif_label_request_aborted(g
, s
, r_attr
);
153 case LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE
:
154 retval
= ldp_notif_no_label_resources(g
, s
, r_attr
);
156 case LDP_NOTIF_NO_ROUTE
:
157 case LDP_NOTIF_LOOP_DETECTED
:
158 retval
= ldp_notif_no_route(g
, s
, e
, r_attr
);
160 case LDP_NOTIF_LABEL_RESOURCES_AVAILABLE
:
161 retval
= ldp_notif_label_resources_available(g
, s
, r_attr
);
163 case LDP_NOTIF_SUCCESS
:
164 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SUCCESS:\n");
166 case LDP_NOTIF_BAD_LDP_ID
:
167 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_LDP_ID:\n");
169 case LDP_NOTIF_BAD_PROTO
:
170 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_PROTO:\n");
172 case LDP_NOTIF_BAD_PDU_LEN
:
173 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_PDU_LEN:\n");
175 case LDP_NOTIF_UNKNOWN_MESG
:
176 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_MESG:\n");
178 case LDP_NOTIF_BAD_MESG_LEN
:
179 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_MESG_LEN:\n");
181 case LDP_NOTIF_UNKNOWN_TVL
:
182 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_TVL:\n");
184 case LDP_NOTIF_BAD_TLV_LEN
:
185 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_TLV_LEN:\n");
187 case LDP_NOTIF_MALFORMED_TLV
:
188 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_MALFORMED_TLV:\n");
190 case LDP_NOTIF_HOLD_TIMER_EXPIRED
:
191 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_HOLD_TIMER_EXPIRED:\n");
193 case LDP_NOTIF_SHUTDOWN
:
194 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SHUTDOWN:\n");
196 case LDP_NOTIF_UNKNOWN_FEC
:
197 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_FEC:\n");
199 case LDP_NOTIF_SESSION_REJECTED_NO_HELLO
:
200 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_NO_HELLO:\n");
202 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE
:
203 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE:\n");
205 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_MAX_PDU_LEN
:
206 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_MAX_PDU_LEN:\n");
208 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE
:
209 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE:\n");
211 case LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED
:
212 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED:\n");
214 case LDP_NOTIF_MISSING_MSG_PARAMS
:
215 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_MISSING_MSG_PARAMS:\n");
217 case LDP_NOTIF_UNSUPORTED_AF
:
218 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNSUPORTED_AF:\n");
220 case LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME
:
221 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME:\n");
223 case LDP_NOTIF_INTERNAL_ERROR
:
224 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_INTERNAL_ERROR\n");
227 LDP_TRACE_OUT(g
->user_data
, "Receive an unknown notification: %08x\n",
229 retval
= MPLS_SUCCESS
;
233 LDP_EXIT(g
->user_data
, "ldp_notif_process");
237 mpls_return_enum
ldp_notif_label_request_aborted(ldp_global
* g
, ldp_session
* s
,
240 ldp_attr
*ds_attr
= NULL
;
242 LDP_ENTER(g
->user_data
, "ldp_notif_label_request_aborted");
244 ds_attr
= MPLS_LIST_HEAD(&s
->attr_root
);
245 while (ds_attr
!= NULL
) {
246 if (ds_attr
->state
== LDP_LSP_STATE_ABORT_SENT
&&
247 ds_attr
->msg_id
== r_attr
->msg_id
) {
250 ds_attr
= MPLS_LIST_NEXT(&s
->attr_root
, ds_attr
, _fs
);
253 if (ds_attr
) { /* LRqA.1 */
254 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
); /* LRqA.2 */
256 LDP_EXIT(g
->user_data
, "ldp_notif_label_request_aborted");
260 LDP_EXIT(g
->user_data
, "ldp_notif_label_request_abort_error");
264 mpls_return_enum
ldp_notif_no_label_resources(ldp_global
* g
, ldp_session
* s
,
267 ldp_attr_list
*ds_list
= NULL
;
268 ldp_attr
*ds_attr
= NULL
;
271 LDP_ENTER(g
->user_data
, "ldp_notif_no_label_resources");
273 fec_tlv2mpls_fec(&s_attr
->fecTlv
, 0, &nfec
);
274 /* NoRes.1 do not actually remove from tree, just change it's state */
276 if ((ds_list
= ldp_attr_find_downstream_all(g
, s
, &nfec
))) {
277 ds_attr
= MPLS_LIST_HEAD(&s
->attr_root
);
279 if (ds_attr
->state
== LDP_LSP_STATE_REQ_SENT
) {
280 ds_attr
->state
= LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV
; /* NoRes.2 */
282 ds_attr
= MPLS_LIST_NEXT(&s
->attr_root
, ds_attr
, _fs
);
286 s
->no_label_resource_recv
= MPLS_BOOL_TRUE
; /* NoRes.3 */
288 LDP_EXIT(g
->user_data
, "ldp_notif_no_label_resource_error");
292 mpls_return_enum
ldp_notif_no_route(ldp_global
* g
, ldp_session
* s
,
293 ldp_entity
* e
, ldp_attr
* s_attr
)
295 ldp_attr
*ds_attr
= NULL
;
296 ldp_attr_list
*ds_list
= NULL
;
298 mpls_return_enum retval
= MPLS_FAILURE
;
300 LDP_ENTER(g
->user_data
, "ldp_notif_no_route\n");
302 fec_tlv2mpls_fec(&s_attr
->fecTlv
, 0, &nfec
);
304 if ((ds_list
= ldp_attr_find_downstream_all(g
, s
, &nfec
))) {
305 ds_attr
= MPLS_LIST_HEAD(&s
->attr_root
);
307 if (ds_attr
->state
== LDP_LSP_STATE_REQ_SENT
) {
308 if (e
->label_request_count
) {
309 if (ds_attr
->attempt_count
< e
->label_request_count
) {
310 if (mpls_timer_handle_verify(g
->timer_handle
,
311 ds_attr
->action_timer
) == MPLS_BOOL_FALSE
) {
312 ds_attr
->action_timer
=
313 mpls_timer_create(g
->timer_handle
, MPLS_UNIT_SEC
,
314 s
->cfg_label_request_timer
, (void *)ds_attr
, g
,
315 ldp_attr_action_callback
);
317 mpls_timer_start(g
->timer_handle
, ds_attr
->action_timer
,
320 retval
= MPLS_SUCCESS
;
322 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
);
323 retval
= MPLS_FAILURE
;
326 ds_attr
= MPLS_LIST_NEXT(&s
->attr_root
, ds_attr
, _fs
);
330 LDP_EXIT(g
->user_data
, "ldp_notif_no_route\n");
334 /* IV. Receive Notification/ Loop Detected */
336 /* Algo: Same as receive Notification/No Route */
338 mpls_return_enum
ldp_notif_label_resources_available(ldp_global
* g
,
339 ldp_session
* s
, ldp_attr
* r_attr
)
341 ldp_attr
*ds_attr
= NULL
;
342 ldp_session
*nh_session
= NULL
;
343 ldp_addr
*nh_addr
= NULL
;
345 mpls_return_enum result
;
347 LDP_ENTER(g
->user_data
, "ldp_notif_loop_detected\n");
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 fec_tlv2mpls_fec(&ds_attr
->fecTlv
, 0, &nfec
);
357 ldp_get_next_hop_session_for_fec(g
, &nfec
, &nh_addr
, &nh_session
);
361 if (nh_session
->index
== s
->index
) {
362 if (ldp_label_request_send(g
, s
, ds_attr
, NULL
) == MPLS_SUCCESS
) { /* Res.4 */
369 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
); /* Res.5 */
375 ds_attr
= MPLS_LIST_NEXT(&s
->attr_root
, ds_attr
, _fs
);
378 LDP_EXIT(g
->user_data
, "Notification label resources available");