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_session.h"
14 #include "ldp_nexthop.h"
15 #include "ldp_entity.h"
17 #include "ldp_pdu_setup.h"
18 #include "ldp_label_request.h"
19 #include "ldp_label_mapping.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;
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
) {
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
) {
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
;
76 notif
->baseMsg
.msgLength
+= setupStatusTlv(¬if
->status
, error
, forward
,
77 status
, msg_id
, msg_type
);
79 /* We have to insert other tlv's like retpdu,extended status, returned
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");
105 ldp_notif_send_error
:
107 LDP_EXIT(g
->user_data
, "ldp_notif_send_error");
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
, ¬->status
, sizeof(mplsLdpStatusTlv_t
));
117 attr
->statusTlvExists
= 1;
119 if (not->lspidTlvExists
&& flag
& LDP_ATTR_LSPID
) {
120 memcpy(&attr
->lspidTlv
, ¬->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
121 attr
->lspidTlvExists
= 1;
124 if (not->retMsgTlvExists
&& flag
& LDP_ATTR_MSGID
) {
125 memcpy(&attr
->retMsgTlv
, ¬->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,¬->exStatus,sizeof(mplsLdpHopTlv_t));
133 attr->exStatusTlvExists = 1;
135 if(not->retPduTlvExists && flag & LDP_ATTR_PATH) {
136 memcpy(&attr->retPdu,¬->retPdu,sizeof(mplsLdpPathTlv_t));
137 attr->retPduTlvExists = 1;
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
;
147 LDP_ENTER(g
->user_data
, "ldp_notif_process");
149 status
= r_attr
->statusTlv
.flags
.flags
.status
;
152 case LDP_NOTIF_LABEL_ABORT
:
153 retval
= ldp_notif_label_request_aborted(g
, s
, r_attr
);
155 case LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE
:
156 retval
= ldp_notif_no_label_resources(g
, s
, r_attr
);
158 case LDP_NOTIF_NO_ROUTE
:
159 case LDP_NOTIF_LOOP_DETECTED
:
160 retval
= ldp_notif_no_route(g
, s
, e
, r_attr
);
162 case LDP_NOTIF_LABEL_RESOURCES_AVAILABLE
:
163 retval
= ldp_notif_label_resources_available(g
, s
, r_attr
);
165 case LDP_NOTIF_SUCCESS
:
166 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SUCCESS:\n");
168 case LDP_NOTIF_BAD_LDP_ID
:
169 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_LDP_ID:\n");
171 case LDP_NOTIF_BAD_PROTO
:
172 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_PROTO:\n");
174 case LDP_NOTIF_BAD_PDU_LEN
:
175 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_PDU_LEN:\n");
177 case LDP_NOTIF_UNKNOWN_MESG
:
178 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_MESG:\n");
180 case LDP_NOTIF_BAD_MESG_LEN
:
181 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_MESG_LEN:\n");
183 case LDP_NOTIF_UNKNOWN_TVL
:
184 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_TVL:\n");
186 case LDP_NOTIF_BAD_TLV_LEN
:
187 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_TLV_LEN:\n");
189 case LDP_NOTIF_MALFORMED_TLV
:
190 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_MALFORMED_TLV:\n");
192 case LDP_NOTIF_HOLD_TIMER_EXPIRED
:
193 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_HOLD_TIMER_EXPIRED:\n");
195 case LDP_NOTIF_SHUTDOWN
:
196 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SHUTDOWN:\n");
198 case LDP_NOTIF_UNKNOWN_FEC
:
199 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_FEC:\n");
201 case LDP_NOTIF_SESSION_REJECTED_NO_HELLO
:
202 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_NO_HELLO:\n");
204 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE
:
205 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE:\n");
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");
210 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE
:
211 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE:\n");
213 case LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED
:
214 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED:\n");
216 case LDP_NOTIF_MISSING_MSG_PARAMS
:
217 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_MISSING_MSG_PARAMS:\n");
219 case LDP_NOTIF_UNSUPORTED_AF
:
220 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNSUPORTED_AF:\n");
222 case LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME
:
223 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME:\n");
225 case LDP_NOTIF_INTERNAL_ERROR
:
226 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_INTERNAL_ERROR\n");
229 LDP_TRACE_OUT(g
->user_data
, "Receive an unknown notification: %08x\n",
231 retval
= MPLS_SUCCESS
;
235 LDP_EXIT(g
->user_data
, "ldp_notif_process");
239 mpls_return_enum
ldp_notif_label_request_aborted(ldp_global
* g
, ldp_session
* s
,
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
) {
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");
262 LDP_EXIT(g
->user_data
, "ldp_notif_label_request_abort_error");
266 mpls_return_enum
ldp_notif_no_label_resources(ldp_global
* g
, ldp_session
* s
,
269 ldp_attr_list
*ds_list
= NULL
;
270 ldp_attr
*ds_attr
= NULL
;
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
);
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");
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
;
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
);
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
,
322 retval
= MPLS_SUCCESS
;
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");
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
;
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
) {
356 nh
= MPLS_LIST_HEAD(&f
->nh_root
);
358 nh_session
= ldp_session_for_nexthop(nh
);
359 if (nh_session
&& (nh_session
->index
== s
->index
)) {
361 if (ldp_label_request_send(g
, s
, ds_attr
, NULL
) != MPLS_SUCCESS
) {
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
);
373 LDP_EXIT(g
->user_data
, "ldp_notif_label_resources_available");