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_nexthop.h"
14 #include "ldp_entity.h"
16 #include "ldp_pdu_setup.h"
17 #include "ldp_label_request.h"
18 #include "ldp_label_mapping.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;
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
) {
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
) {
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
;
75 notif
->baseMsg
.msgLength
+= setupStatusTlv(¬if
->status
, error
, forward
,
76 status
, msg_id
, msg_type
);
78 /* We have to insert other tlv's like retpdu,extended status, returned
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");
104 ldp_notif_send_error
:
106 LDP_EXIT(g
->user_data
, "ldp_notif_send_error");
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
, ¬->status
, sizeof(mplsLdpStatusTlv_t
));
116 attr
->statusTlvExists
= 1;
118 if (not->lspidTlvExists
&& flag
& LDP_ATTR_LSPID
) {
119 memcpy(&attr
->lspidTlv
, ¬->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
120 attr
->lspidTlvExists
= 1;
123 if (not->retMsgTlvExists
&& flag
& LDP_ATTR_MSGID
) {
124 memcpy(&attr
->retMsgTlv
, ¬->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,¬->exStatus,sizeof(mplsLdpHopTlv_t));
132 attr->exStatusTlvExists = 1;
134 if(not->retPduTlvExists && flag & LDP_ATTR_PATH) {
135 memcpy(&attr->retPdu,¬->retPdu,sizeof(mplsLdpPathTlv_t));
136 attr->retPduTlvExists = 1;
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
;
146 LDP_ENTER(g
->user_data
, "ldp_notif_process");
148 status
= r_attr
->statusTlv
.flags
.flags
.status
;
151 case LDP_NOTIF_LABEL_ABORT
:
152 retval
= ldp_notif_label_request_aborted(g
, s
, r_attr
);
154 case LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE
:
155 retval
= ldp_notif_no_label_resources(g
, s
, r_attr
);
157 case LDP_NOTIF_NO_ROUTE
:
158 case LDP_NOTIF_LOOP_DETECTED
:
159 retval
= ldp_notif_no_route(g
, s
, e
, r_attr
);
161 case LDP_NOTIF_LABEL_RESOURCES_AVAILABLE
:
162 retval
= ldp_notif_label_resources_available(g
, s
, r_attr
);
164 case LDP_NOTIF_SUCCESS
:
165 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SUCCESS:\n");
167 case LDP_NOTIF_BAD_LDP_ID
:
168 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_LDP_ID:\n");
170 case LDP_NOTIF_BAD_PROTO
:
171 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_PROTO:\n");
173 case LDP_NOTIF_BAD_PDU_LEN
:
174 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_PDU_LEN:\n");
176 case LDP_NOTIF_UNKNOWN_MESG
:
177 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_MESG:\n");
179 case LDP_NOTIF_BAD_MESG_LEN
:
180 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_MESG_LEN:\n");
182 case LDP_NOTIF_UNKNOWN_TVL
:
183 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_TVL:\n");
185 case LDP_NOTIF_BAD_TLV_LEN
:
186 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_BAD_TLV_LEN:\n");
188 case LDP_NOTIF_MALFORMED_TLV
:
189 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_MALFORMED_TLV:\n");
191 case LDP_NOTIF_HOLD_TIMER_EXPIRED
:
192 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_HOLD_TIMER_EXPIRED:\n");
194 case LDP_NOTIF_SHUTDOWN
:
195 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SHUTDOWN:\n");
197 case LDP_NOTIF_UNKNOWN_FEC
:
198 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNKNOWN_FEC:\n");
200 case LDP_NOTIF_SESSION_REJECTED_NO_HELLO
:
201 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_NO_HELLO:\n");
203 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE
:
204 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_ADVERTISEMENT_MODE:\n");
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");
209 case LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE
:
210 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_PARAMETERS_LABEL_RANGE:\n");
212 case LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED
:
213 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_KEEPALIVE_TIMER_EXPIRED:\n");
215 case LDP_NOTIF_MISSING_MSG_PARAMS
:
216 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_MISSING_MSG_PARAMS:\n");
218 case LDP_NOTIF_UNSUPORTED_AF
:
219 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_UNSUPORTED_AF:\n");
221 case LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME
:
222 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_SESSION_REJECTED_BAD_KEEPALIVE_TIME:\n");
224 case LDP_NOTIF_INTERNAL_ERROR
:
225 LDP_TRACE_OUT(g
->user_data
, "LDP_NOTIF_INTERNAL_ERROR\n");
228 LDP_TRACE_OUT(g
->user_data
, "Receive an unknown notification: %08x\n",
230 retval
= MPLS_SUCCESS
;
234 LDP_EXIT(g
->user_data
, "ldp_notif_process");
238 mpls_return_enum
ldp_notif_label_request_aborted(ldp_global
* g
, ldp_session
* s
,
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
) {
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");
261 LDP_EXIT(g
->user_data
, "ldp_notif_label_request_abort_error");
265 mpls_return_enum
ldp_notif_no_label_resources(ldp_global
* g
, ldp_session
* s
,
268 ldp_attr_list
*ds_list
= NULL
;
269 ldp_attr
*ds_attr
= NULL
;
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
);
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");
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
;
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
);
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
,
321 retval
= MPLS_SUCCESS
;
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");
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
;
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
) {
355 nh
= MPLS_LIST_HEAD(&f
->nh_root
);
357 nh_session
= ldp_session_for_nexthop(nh
);
358 if (nh_session
&& (nh_session
->index
== s
->index
)) {
360 if (ldp_label_request_send(g
, s
, ds_attr
, NULL
) != MPLS_SUCCESS
) {
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
);
372 LDP_EXIT(g
->user_data
, "ldp_notif_label_resources_available");