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"
12 #include "ldp_session.h"
13 #include "ldp_global.h"
14 #include "ldp_inlabel.h"
15 #include "ldp_entity.h"
16 #include "ldp_outlabel.h"
17 #include "ldp_label_rel_with.h"
18 #include "ldp_label_mapping.h"
21 #include "ldp_pdu_setup.h"
23 #include "mpls_trace_impl.h"
25 mpls_bool
rel_with2attr(mplsLdpLbl_W_R_Msg_t
* rw
, ldp_attr
* attr
)
27 mpls_bool retval
= MPLS_BOOL_FALSE
;
29 if (rw
->fecTlvExists
) {
30 memcpy(&attr
->fecTlv
, &rw
->fecTlv
, sizeof(mplsLdpFecTlv_t
));
31 attr
->fecTlvExists
= 1;
33 if (rw
->genLblTlvExists
) {
34 retval
= MPLS_BOOL_TRUE
;
35 memcpy(&attr
->genLblTlv
, &rw
->genLblTlv
, sizeof(mplsLdpGenLblTlv_t
));
36 attr
->genLblTlvExists
= 1;
37 } else if (rw
->atmLblTlvExists
) {
38 retval
= MPLS_BOOL_TRUE
;
39 memcpy(&attr
->atmLblTlv
, &rw
->atmLblTlv
, sizeof(mplsLdpAtmLblTlv_t
));
40 attr
->atmLblTlvExists
= 1;
41 } else if (rw
->frLblTlvExists
) {
42 retval
= MPLS_BOOL_TRUE
;
43 memcpy(&attr
->frLblTlv
, &rw
->frLblTlv
, sizeof(mplsLdpFrLblTlv_t
));
44 attr
->frLblTlvExists
= 1;
49 void ldp_label_rel_with_prepare_msg(ldp_mesg
* msg
, uint32_t msgid
,
50 ldp_attr
* a
, ldp_notif_status status
, uint16_t type
)
52 mplsLdpLbl_W_R_Msg_t
*rw
= NULL
;
54 ldp_mesg_prepare(msg
, type
, msgid
);
56 if (a
->fecTlvExists
) {
58 rw
->baseMsg
.msgLength
+= setupFecTlv(&rw
->fecTlv
);
59 rw
->baseMsg
.msgLength
+= addFecElem2FecTlv(&rw
->fecTlv
,
60 &a
->fecTlv
.fecElArray
[0]);
62 if (a
->genLblTlvExists
) {
63 rw
->genLblTlvExists
= 1;
64 rw
->baseMsg
.msgLength
+= setupGenLblTlv(&rw
->genLblTlv
, a
->genLblTlv
.label
);
66 if (a
->atmLblTlvExists
) {
67 rw
->atmLblTlvExists
= 1;
68 rw
->baseMsg
.msgLength
+= setupAtmLblTlv(&rw
->atmLblTlv
, 0, 0,
69 a
->atmLblTlv
.flags
.flags
.vpi
, a
->atmLblTlv
.vci
);
71 if (a
->frLblTlvExists
) {
72 rw
->frLblTlvExists
= 1;
73 rw
->baseMsg
.msgLength
+= setupFrLblTlv(&rw
->frLblTlv
, 0,
74 a
->frLblTlv
.flags
.flags
.len
, a
->frLblTlv
.flags
.flags
.dlci
);
76 if (a
->lspidTlvExists
) {
77 rw
->lspidTlvExists
= 1;
78 rw
->baseMsg
.msgLength
+= setupLspidTlv(&rw
->lspidTlv
, 0,
79 a
->lspidTlv
.localCrlspId
, a
->lspidTlv
.routerId
);
83 mpls_return_enum
ldp_label_rel_with_send(ldp_global
* g
, ldp_session
* s
,
84 ldp_attr
* a
, ldp_notif_status status
, uint16_t type
)
86 LDP_ENTER(g
->user_data
, "ldp_label_rel_with_send");
88 ldp_label_rel_with_prepare_msg(s
->tx_message
, g
->message_identifier
++, a
,
91 ldp_mesg_send_tcp(g
, s
, s
->tx_message
);
93 LDP_EXIT(g
->user_data
, "ldp_label_rel_with_send");
98 mpls_return_enum
ldp_label_release_send(ldp_global
* g
, ldp_session
* s
,
99 ldp_attr
* a
, ldp_notif_status status
)
102 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
103 "Release Sent: session(%d)\n", s
->index
);
105 return ldp_label_rel_with_send(g
, s
, a
, status
, MPLS_LBLREL_MSGTYPE
);
108 mpls_return_enum
ldp_label_withdraw_send(ldp_global
* g
, ldp_session
* s
,
109 ldp_attr
* us_attr
, ldp_notif_status status
)
112 us_attr
->state
= LDP_LSP_STATE_WITH_SENT
;
113 if (ldp_label_rel_with_send(g
, s
, us_attr
, status
, MPLS_LBLWITH_MSGTYPE
) ==
118 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
119 "Withdraw Sent: session(%d)\n", s
->index
);
124 mpls_return_enum
ldp_label_release_process(ldp_global
* g
, ldp_session
* s
,
125 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* r_attr
, mpls_fec
* fec
)
127 mpls_bool label_exists
= MPLS_BOOL_FALSE
;
128 ldp_attr
*us_attr
= NULL
;
129 ldp_attr
*ds_attr
= NULL
;
130 mpls_return_enum retval
= MPLS_SUCCESS
;
132 LDP_ENTER(g
->user_data
, "ldp_label_release_process");
134 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_LABEL
,
135 "Release Recv from %s\n", s
->session_name
);
137 if (r_attr
->genLblTlvExists
|| r_attr
->atmLblTlvExists
138 || r_attr
->frLblTlvExists
) {
139 label_exists
= MPLS_BOOL_TRUE
;
143 /* LRl.1 is accomplished at LRl.10 */
144 us_attr
= ldp_attr_find_upstream_state(g
, s
, fec
, LDP_LSP_STATE_MAP_SENT
);
147 ldp_attr_find_upstream_state(g
, s
, fec
, LDP_LSP_STATE_WITH_SENT
);
148 if (!us_attr
) { /* LRl.2 */
151 /* LRl.3 is accomplished at LRl.10 */
154 if (g
->label_merge
== MPLS_BOOL_FALSE
) { /* LR1.4 */
158 if (ldp_attr_find_upstream_state_any(g
, fec
, LDP_LSP_STATE_MAP_SENT
)) {
163 /* we can only propogate a release to the downstream attached to
164 the upstream we found up top */
166 if (us_attr
->ds_attr
&& us_attr
->ds_attr
->state
== LDP_LSP_STATE_MAP_RECV
) {
167 ds_attr
= us_attr
->ds_attr
;
172 if (g
->propagate_release
== MPLS_BOOL_FALSE
) { /* LRl.8 */
176 if (ldp_label_release_send(g
, ds_attr
->session
, ds_attr
, LDP_NOTIF_NONE
) != MPLS_SUCCESS
) { /* LRl.9 */
177 retval
= MPLS_FAILURE
;
179 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
);
182 ldp_attr_remove_complete(g
, us_attr
, MPLS_BOOL_FALSE
); /* LRl.10,11 */
185 LDP_PRINT(g
->user_data
, "No FEC in release, need to implement\n");
190 LDP_EXIT(g
->user_data
, "ldp_label_release_process");
194 mpls_return_enum
ldp_label_withdraw_process(ldp_global
* g
, ldp_session
* s
,
195 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* r_attr
, mpls_fec
* fec
)
197 mpls_bool label_exists
= MPLS_BOOL_FALSE
;
198 ldp_attr_list
*ds_list
= NULL
;
199 ldp_attr
*ds_attr
= NULL
;
200 ldp_attr
*ds_temp
= NULL
;
201 ldp_attr
*us_temp
= NULL
;
202 mpls_return_enum retval
= MPLS_SUCCESS
;
204 LDP_ENTER(g
->user_data
, "ldp_label_withdraw_process");
206 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_LABEL
,
207 "Withdraw Recv for %s\n", s
->session_name
);
209 if (r_attr
->genLblTlvExists
|| r_attr
->atmLblTlvExists
210 || r_attr
->frLblTlvExists
) {
211 label_exists
= MPLS_BOOL_TRUE
;
217 if ((ds_list
= ldp_attr_find_downstream_all(g
, s
, fec
)) != NULL
) {
218 ds_temp
= MPLS_LIST_HEAD(ds_list
);
220 if (ds_temp
->state
== LDP_LSP_STATE_MAP_RECV
) { /* LWd.3 */
221 if (ldp_attr_is_equal(r_attr
, ds_temp
, LDP_ATTR_LABEL
)) {
225 ds_temp
= MPLS_LIST_NEXT(ds_list
, ds_temp
, _fs
);
230 retval
= MPLS_FAILURE
;
234 if (ldp_label_release_send(g
, s
, ds_attr
, LDP_NOTIF_NONE
) != MPLS_SUCCESS
) {
235 retval
= MPLS_FAILURE
;
239 if (g
->lsp_control_mode
== LDP_CONTROL_ORDERED
) { /* LWd.5 */
243 if (s
->oper_distribution_mode
!= LDP_DISTRIBUTION_ONDEMAND
) { /* LWd.6 */
247 Detect_Change_Fec_Next_Hop(g
, fec
, s
); /* LWd.7 */
251 /* I can only propogate a label withdraw to the upstreams attached
252 to the downstream found above */
254 us_temp
= MPLS_LIST_HEAD(&ds_attr
->us_attr_root
);
256 if (us_temp
->state
== LDP_LSP_STATE_MAP_SENT
) {
257 if (ldp_label_withdraw_send(g
, us_temp
->session
, us_temp
,
258 LDP_NOTIF_NONE
) != MPLS_SUCCESS
) { /* LWd.11 */
259 retval
= MPLS_FAILURE
;
263 us_temp
= MPLS_LIST_NEXT(&ds_attr
->us_attr_root
, us_temp
, _ds_attr
);
266 /* JLEU: process wildcard FEC stuff here */
273 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
); /* LWd.4 */
275 LDP_EXIT(g
->user_data
, "ldp_label_withdraw_process");