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_nexthop.h"
19 #include "ldp_label_mapping.h"
22 #include "ldp_pdu_setup.h"
24 #include "mpls_trace_impl.h"
26 mpls_bool
rel_with2attr(mplsLdpLbl_W_R_Msg_t
* rw
, ldp_attr
* attr
)
28 mpls_bool retval
= MPLS_BOOL_FALSE
;
30 if (rw
->fecTlvExists
) {
31 memcpy(&attr
->fecTlv
, &rw
->fecTlv
, sizeof(mplsLdpFecTlv_t
));
32 attr
->fecTlvExists
= 1;
34 if (rw
->genLblTlvExists
) {
35 retval
= MPLS_BOOL_TRUE
;
36 memcpy(&attr
->genLblTlv
, &rw
->genLblTlv
, sizeof(mplsLdpGenLblTlv_t
));
37 attr
->genLblTlvExists
= 1;
38 } else if (rw
->atmLblTlvExists
) {
39 retval
= MPLS_BOOL_TRUE
;
40 memcpy(&attr
->atmLblTlv
, &rw
->atmLblTlv
, sizeof(mplsLdpAtmLblTlv_t
));
41 attr
->atmLblTlvExists
= 1;
42 } else if (rw
->frLblTlvExists
) {
43 retval
= MPLS_BOOL_TRUE
;
44 memcpy(&attr
->frLblTlv
, &rw
->frLblTlv
, sizeof(mplsLdpFrLblTlv_t
));
45 attr
->frLblTlvExists
= 1;
50 void ldp_label_rel_with_prepare_msg(ldp_mesg
* msg
, uint32_t msgid
,
51 ldp_attr
* a
, ldp_notif_status status
, uint16_t type
)
53 mplsLdpLbl_W_R_Msg_t
*rw
= NULL
;
55 ldp_mesg_prepare(msg
, type
, msgid
);
57 if (a
->fecTlvExists
) {
59 rw
->baseMsg
.msgLength
+= setupFecTlv(&rw
->fecTlv
);
60 rw
->baseMsg
.msgLength
+= addFecElem2FecTlv(&rw
->fecTlv
,
61 &a
->fecTlv
.fecElArray
[0]);
63 if (a
->genLblTlvExists
) {
64 rw
->genLblTlvExists
= 1;
65 rw
->baseMsg
.msgLength
+= setupGenLblTlv(&rw
->genLblTlv
, a
->genLblTlv
.label
);
67 if (a
->atmLblTlvExists
) {
68 rw
->atmLblTlvExists
= 1;
69 rw
->baseMsg
.msgLength
+= setupAtmLblTlv(&rw
->atmLblTlv
, 0, 0,
70 a
->atmLblTlv
.flags
.flags
.vpi
, a
->atmLblTlv
.vci
);
72 if (a
->frLblTlvExists
) {
73 rw
->frLblTlvExists
= 1;
74 rw
->baseMsg
.msgLength
+= setupFrLblTlv(&rw
->frLblTlv
, 0,
75 a
->frLblTlv
.flags
.flags
.len
, a
->frLblTlv
.flags
.flags
.dlci
);
77 if (a
->lspidTlvExists
) {
78 rw
->lspidTlvExists
= 1;
79 rw
->baseMsg
.msgLength
+= setupLspidTlv(&rw
->lspidTlv
, 0,
80 a
->lspidTlv
.localCrlspId
, a
->lspidTlv
.routerId
);
84 mpls_return_enum
ldp_label_rel_with_send(ldp_global
* g
, ldp_session
* s
,
85 ldp_attr
* a
, ldp_notif_status status
, uint16_t type
)
87 LDP_ENTER(g
->user_data
, "ldp_label_rel_with_send");
89 ldp_label_rel_with_prepare_msg(s
->tx_message
, g
->message_identifier
++, a
,
92 ldp_mesg_send_tcp(g
, s
, s
->tx_message
);
94 LDP_EXIT(g
->user_data
, "ldp_label_rel_with_send");
99 mpls_return_enum
ldp_label_release_send(ldp_global
* g
, ldp_session
* s
,
100 ldp_attr
* a
, ldp_notif_status status
)
103 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
104 "Release Sent: session(%d)\n", s
->index
);
106 return ldp_label_rel_with_send(g
, s
, a
, status
, MPLS_LBLREL_MSGTYPE
);
109 mpls_return_enum
ldp_label_withdraw_send(ldp_global
* g
, ldp_session
* s
,
110 ldp_attr
* us_attr
, ldp_notif_status status
)
113 us_attr
->state
= LDP_LSP_STATE_WITH_SENT
;
114 if (ldp_label_rel_with_send(g
, s
, us_attr
, status
, MPLS_LBLWITH_MSGTYPE
) ==
119 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
120 "Withdraw Sent: session(%d)\n", s
->index
);
125 mpls_return_enum
ldp_label_release_process(ldp_global
* g
, ldp_session
* s
,
126 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* r_attr
, ldp_fec
* f
)
128 mpls_bool label_exists
= MPLS_BOOL_FALSE
;
129 ldp_attr
*us_attr
= NULL
;
130 ldp_attr
*ds_attr
= NULL
;
131 mpls_return_enum retval
= MPLS_SUCCESS
;
133 LDP_ENTER(g
->user_data
, "ldp_label_release_process");
135 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_LABEL
,
136 "Release Recv from %s\n", s
->session_name
);
138 if (r_attr
->genLblTlvExists
|| r_attr
->atmLblTlvExists
139 || r_attr
->frLblTlvExists
) {
140 label_exists
= MPLS_BOOL_TRUE
;
144 /* LRl.1 is accomplished at LRl.10 */
145 us_attr
= ldp_attr_find_upstream_state2(g
, s
, f
, LDP_LSP_STATE_MAP_SENT
);
148 ldp_attr_find_upstream_state2(g
, s
, f
, LDP_LSP_STATE_WITH_SENT
);
149 if (!us_attr
) { /* LRl.2 */
152 /* LRl.3 is accomplished at LRl.10 */
155 if (g
->label_merge
== MPLS_BOOL_FALSE
) { /* LR1.4 */
159 if (ldp_attr_find_upstream_state_any2(g
, f
, LDP_LSP_STATE_MAP_SENT
)) {
164 /* we can only propogate a release to the downstream attached to
165 the upstream we found up top */
167 if (us_attr
->ds_attr
&& us_attr
->ds_attr
->state
== LDP_LSP_STATE_MAP_RECV
) {
168 ds_attr
= us_attr
->ds_attr
;
173 if (g
->propagate_release
== MPLS_BOOL_FALSE
) { /* LRl.8 */
177 if (ldp_label_release_send(g
, ds_attr
->session
, ds_attr
,
178 LDP_NOTIF_NONE
) != MPLS_SUCCESS
) { /* LRl.9 */
179 retval
= MPLS_FAILURE
;
181 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
);
184 ldp_attr_remove_complete(g
, us_attr
, MPLS_BOOL_FALSE
); /* LRl.10,11 */
187 LDP_PRINT(g
->user_data
, "No FEC in release, need to implement\n");
192 LDP_EXIT(g
->user_data
, "ldp_label_release_process");
196 mpls_return_enum
ldp_label_withdraw_process(ldp_global
* g
, ldp_session
* s
,
197 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* r_attr
, ldp_fec
* f
)
199 mpls_bool label_exists
= MPLS_BOOL_FALSE
;
200 ldp_attr_list
*ds_list
= NULL
;
201 ldp_attr
*ds_attr
= NULL
;
202 ldp_attr
*ds_temp
= NULL
;
203 ldp_attr
*us_temp
= NULL
;
204 ldp_nexthop
*nh
= NULL
;
205 mpls_return_enum retval
= MPLS_SUCCESS
;
207 LDP_ENTER(g
->user_data
, "ldp_label_withdraw_process");
209 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_LABEL
,
210 "Withdraw Recv for %s\n", s
->session_name
);
212 if (r_attr
->genLblTlvExists
|| r_attr
->atmLblTlvExists
213 || r_attr
->frLblTlvExists
) {
214 label_exists
= MPLS_BOOL_TRUE
;
220 if ((ds_list
= ldp_attr_find_downstream_all2(g
, s
, f
)) != NULL
) {
221 ds_temp
= MPLS_LIST_HEAD(ds_list
);
223 if (ds_temp
->state
== LDP_LSP_STATE_MAP_RECV
) { /* LWd.3 */
224 if (ldp_attr_is_equal(r_attr
, ds_temp
, LDP_ATTR_LABEL
)) {
229 ds_temp
= MPLS_LIST_NEXT(ds_list
, ds_temp
, _fs
);
234 retval
= MPLS_FAILURE
;
235 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_LABEL
,
236 "Withdraw Recv for a non-existant mapping from %s\n",s
->session_name
);
241 * we want to remove it from the tree, but not delete it yet
242 * so hold a refcnt, we will release that refcnt at the end, thus
243 * deleting it if no one else it holding a refcnt
245 MPLS_REFCNT_HOLD(ds_attr
);
246 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
); /* LWd.4 */
249 if (ldp_label_release_send(g
, s
, ds_attr
, LDP_NOTIF_NONE
) != MPLS_SUCCESS
) {
254 if (g
->lsp_control_mode
== LDP_CONTROL_ORDERED
) { /* LWd.5 */
258 if (s
->oper_distribution_mode
!= LDP_DISTRIBUTION_ONDEMAND
) { /* LWd.6 */
262 MPLS_ASSERT((nh
= ldp_nexthop_for_fec_session(f
, s
)));
263 retval
= ldp_fec_process_add(g
, f
, nh
, s
); /* LWd.7 */
267 /* I can only propogate a label withdraw to the upstreams attached
268 to the downstream found above */
270 us_temp
= MPLS_LIST_HEAD(&ds_attr
->us_attr_root
);
272 if (us_temp
->state
== LDP_LSP_STATE_MAP_SENT
) {
273 if (ldp_label_withdraw_send(g
, us_temp
->session
, us_temp
,
274 LDP_NOTIF_NONE
) != MPLS_SUCCESS
) { /* LWd.11 */
279 us_temp
= MPLS_LIST_NEXT(&ds_attr
->us_attr_root
, us_temp
, _ds_attr
);
282 /* JLEU: process wildcard FEC stuff here */
288 MPLS_REFCNT_RELEASE2(g
, ds_attr
, ldp_attr_delete
);
291 LDP_EXIT(g
->user_data
, "ldp_label_withdraw_process");