Add mpls_socket_get_local_name and mpls_socket_get_remote_name
[mpls-ldp-portable.git] / ldp / ldp_label_request.c
blobfd8e6758d4346d11a8d689a2b379273ae351d9e1
2 /*
3 * Copyright (C) James R. Leu 2000
4 * jleu@mindspring.com
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
8 */
10 #include "ldp_struct.h"
11 #include "ldp_attr.h"
12 #include "ldp_fec.h"
13 #include "ldp_mesg.h"
14 #include "ldp_pdu_setup.h"
15 #include "ldp_notif.h"
16 #include "ldp_session.h"
17 #include "ldp_entity.h"
18 #include "ldp_label_mapping.h"
19 #include "ldp_label_request.h"
21 #include "mpls_timer_impl.h"
22 #include "mpls_policy_impl.h"
23 #include "mpls_tree_impl.h"
24 #include "mpls_trace_impl.h"
25 #include "mpls_fib_impl.h"
26 #include "mpls_lock_impl.h"
28 mpls_return_enum ldp_label_request_for_xc(ldp_global * g, ldp_session * s,
29 mpls_fec * fec, ldp_attr * us_attr, ldp_attr ** ds_attr)
32 LDP_ENTER(g->user_data, "ldp_label_request_for_xc");
34 if (!(*ds_attr)) {
35 if (!((*ds_attr) = ldp_attr_create(g, fec))) {
36 return MPLS_FATAL;
38 MPLS_REFCNT_HOLD((*ds_attr));
40 Prepare_Label_Request_Attributes(g, s, fec, (*ds_attr), us_attr);
41 (*ds_attr)->state = LDP_LSP_STATE_REQ_SENT;
42 if (ldp_label_request_send(g, s, us_attr, ds_attr) != MPLS_SUCCESS) {
43 return MPLS_FAILURE;
46 LDP_EXIT(g->user_data, "ldp_label_request_for_xc");
48 return MPLS_SUCCESS;
51 void ldp_label_request_prepare_msg(ldp_mesg * msg, uint32_t msgid,
52 ldp_attr * s_attr)
54 mplsLdpLblReqMsg_t *req = NULL;
55 int i;
57 ldp_mesg_prepare(msg, MPLS_LBLREQ_MSGTYPE, msgid);
58 req = &msg->u.request;
60 if (s_attr->fecTlvExists) {
61 req->fecTlvExists = 1;
62 req->baseMsg.msgLength += setupFecTlv(&req->fecTlv);
63 req->baseMsg.msgLength += addFecElem2FecTlv(&req->fecTlv,
64 &s_attr->fecTlv.fecElArray[0]);
66 if (s_attr->hopCountTlvExists) {
67 req->hopCountTlvExists = 1;
68 req->baseMsg.msgLength += setupHopCountTlv(&req->hopCountTlv,
69 s_attr->hopCountTlv.hcValue);
71 if (s_attr->pathVecTlvExists) {
72 req->pathVecTlvExists = 1;
73 req->baseMsg.msgLength += setupPathTlv(&req->pathVecTlv);
74 for (i = 0; i < MPLS_MAXHOPSNUMBER; i++) {
75 if (s_attr->pathVecTlv.lsrId[i]) {
76 req->baseMsg.msgLength += addLsrId2PathTlv(&req->pathVecTlv,
77 s_attr->pathVecTlv.lsrId[i]);
83 mpls_return_enum ldp_label_request_send(ldp_global * g, ldp_session * s,
84 ldp_attr * us_attr, ldp_attr ** ds_attr)
86 ldp_attr *ds_temp;
87 mpls_fec fec;
89 LDP_ENTER(g->user_data, "ldp_label_request_send");
90 MPLS_ASSERT(ds_attr && *ds_attr);
92 fec_tlv2mpls_fec(&((*ds_attr)->fecTlv), 0, &fec);
94 if ((ds_temp = ldp_attr_find_downstream_state(g, s, &fec,
95 LDP_LSP_STATE_REQ_SENT)) != NULL) { /* SLRq.1 */
97 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
98 "Label Request Send: request already pending(%d)\n", ds_temp->index);
100 ldp_attr_add_us2ds(us_attr, ds_temp);
102 /* we do not need the one passed in, but make sure that the caller
103 is using this one from here forth */
104 ldp_attr_remove_complete(g, *ds_attr, MPLS_BOOL_TRUE);
105 *ds_attr = ds_temp;
106 return MPLS_SUCCESS;
109 if (s->no_label_resource_recv == MPLS_BOOL_TRUE) { /* SLRq.2 */
110 goto ldp_label_request_send_error;
113 (*ds_attr)->msg_id = g->message_identifier++;
114 ldp_label_request_prepare_msg(s->tx_message, (*ds_attr)->msg_id, *ds_attr);
116 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
117 "Label Request Sent: session(%d)\n", s->index);
119 if (ldp_mesg_send_tcp(g, s, s->tx_message) == MPLS_FAILURE) { /* SLRq.3 */
120 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ERROR,
121 "Label Request send failed\n");
122 goto ldp_label_request_send_error;
125 (*ds_attr)->state = LDP_LSP_STATE_REQ_SENT;
126 if (ldp_attr_insert_downstream(g, s, (*ds_attr)) == MPLS_FAILURE) { /* SLRq.4 */
127 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ERROR,
128 "Couldn't insert sent attributes in tree\n");
129 goto ldp_label_request_send_error;
131 if (us_attr) {
132 ldp_attr_add_us2ds(us_attr, *ds_attr);
135 LDP_EXIT(g->user_data, "ldp_label_request_send");
137 return MPLS_SUCCESS; /* SLRq.5 */
139 ldp_label_request_send_error:
141 LDP_PRINT(g->user_data, "SLRq.6\n");
142 (*ds_attr)->state = LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT;
143 ldp_attr_insert_downstream(g, s, (*ds_attr)); /* SLRq.6 */
145 LDP_EXIT(g->user_data, "ldp_label_request_send-error");
147 return MPLS_FAILURE; /* SLRq.7 */
150 void req2attr(mplsLdpLblReqMsg_t * req, ldp_attr * attr, uint32_t flag)
152 attr->msg_id = req->baseMsg.msgId;
154 if (req->fecTlvExists && flag & LDP_ATTR_FEC) {
155 memcpy(&attr->fecTlv, &req->fecTlv, sizeof(mplsLdpFecTlv_t));
156 attr->fecTlvExists = 1;
158 if (req->hopCountTlvExists && flag & LDP_ATTR_HOPCOUNT) {
159 memcpy(&attr->hopCountTlv, &req->hopCountTlv, sizeof(mplsLdpHopTlv_t));
160 attr->hopCountTlvExists = 1;
162 if (req->pathVecTlvExists && flag & LDP_ATTR_PATH) {
163 memcpy(&attr->pathVecTlv, &req->pathVecTlv, sizeof(mplsLdpPathTlv_t));
164 attr->pathVecTlvExists = 1;
166 if (req->lblMsgIdTlvExists && flag & LDP_ATTR_MSGID) {
167 memcpy(&attr->lblMsgIdTlv, &req->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
168 attr->lblMsgIdTlvExists = 1;
170 if (req->lspidTlvExists && flag & LDP_ATTR_LSPID) {
171 memcpy(&attr->lspidTlv, &req->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
172 attr->lspidTlvExists = 1;
174 if (req->trafficTlvExists && flag & LDP_ATTR_TRAFFIC) {
175 memcpy(&attr->trafficTlv, &req->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
176 attr->trafficTlvExists = 1;
180 void ldp_label_request_initial_callback(mpls_timer_handle timer, void *extra,
181 mpls_cfg_handle handle)
183 ldp_session *s = (ldp_session *)extra;
184 ldp_global *g = (ldp_global*)handle;
185 ldp_nexthop *nh = NULL;
186 ldp_fec *f = NULL;
188 ldp_session *nh_session = NULL;
189 mpls_bool done = MPLS_BOOL_FALSE;
191 ldp_attr *attr = NULL;
192 ldp_fs *fs = NULL;
193 ldp_attr *ds_attr = NULL;
195 LDP_ENTER(g->user_data, "ldp_label_request_initial_callback");
197 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_TIMER,
198 "Initial Label Request Callback fired: session(%d)\n", s->index);
200 mpls_lock_get(g->global_lock);
202 mpls_timer_stop(g->timer_handle, timer);
204 if ((f = MPLS_LIST_HEAD(&g->fec))) {
205 do {
206 if ((nh = MPLS_LIST_HEAD(&f->nh_root))) {
207 do {
208 switch (f->info.type) {
209 case MPLS_FEC_PREFIX:
210 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
211 LDP_TRACE_FLAG_ROUTE, "Processing prefix FEC: %08x/%d ",
212 f->info.u.prefix.network.u.ipv4, f->info.u.prefix.length);
213 break;
214 case MPLS_FEC_HOST:
215 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
216 LDP_TRACE_FLAG_ROUTE, "Processing host FEC: %08x ",
217 f->info.u.host.u.ipv4);
218 break;
219 case MPLS_FEC_L2CC:
220 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
221 LDP_TRACE_FLAG_ROUTE, "Processing L2CC FEC: %d %d %d ",
222 f->info.u.l2cc.connection_id, f->info.u.l2cc.group_id,
223 f->info.u.l2cc.type);
224 break;
225 default:
226 MPLS_ASSERT(0);
229 if (nh->info.type & MPLS_NH_IP) {
230 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
231 LDP_TRACE_FLAG_ROUTE, "via %08x\n", nh->addr->address.u.ipv4);
233 if (nh->info.type & MPLS_NH_IF) {
234 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
235 LDP_TRACE_FLAG_ROUTE, "via %p\n", nh->iff->handle);
238 /* check to see if export policy allows us to 'see' this route */
239 if (mpls_policy_export_check(g->user_data, &f->info, &nh->info)
240 == MPLS_BOOL_FALSE) {
241 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
242 LDP_TRACE_FLAG_DEBUG, "Rejected by export policy\n");
243 continue;
246 /* find the next hop session corresponding to this FEC */
247 nh_session = ldp_session_for_nexthop(nh);
249 /* do we have a valid next hop session, and is the nexp hop session
250 * this session? */
251 if ((!nh_session) || (nh_session->index != s->index)) {
252 continue;
255 /* have we already sent a label request to this peer for this FEC? */
256 if (ldp_attr_find_downstream_state(g, s, &f->info,
257 LDP_LSP_STATE_REQ_SENT)) {
258 continue;
261 /* clear out info from the last FEC */
262 ds_attr = NULL;
264 /* jleu: duplicate code from ldp_attr_find_upstream_state_any */
265 fs = MPLS_LIST_HEAD(&f->fs_root_us);
266 while (fs) {
267 attr = MPLS_LIST_HEAD(&fs->attr_root);
268 while (attr) {
269 if (attr->state == LDP_LSP_STATE_REQ_RECV ||
270 attr->state == LDP_LSP_STATE_MAP_SENT) {
271 if (!ds_attr) {
272 /* this is not neccessarily going to be XC'd to something */
273 ldp_label_request_for_xc(g, s, &f->info, attr, &ds_attr);
276 attr = MPLS_LIST_NEXT(&fs->attr_root, attr, _fs);
278 fs = MPLS_LIST_NEXT(&f->fs_root_us, fs, _fec);
281 if (!ds_attr) {
283 * we did not find any received requests or sent mappings so
284 * send a request and xc it to nothing
286 ldp_label_request_for_xc(g, s, &f->info, NULL, &ds_attr);
288 } while ((nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec)));
290 } while ((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
291 done = MPLS_BOOL_TRUE;
294 if (done == MPLS_BOOL_TRUE) {
295 mpls_timer_delete(g->timer_handle, timer);
296 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
297 s->initial_distribution_timer = (mpls_timer_handle) 0;
298 } else {
299 mpls_timer_start(g->timer_handle, timer, MPLS_TIMER_ONESHOT);
300 /* need to mark the session with where it left off */
303 mpls_lock_release(g->global_lock);
305 LDP_EXIT(g->user_data, "ldp_label_request_initial_callback");
308 void Prepare_Label_Request_Attributes(ldp_global * g, ldp_session * s,
309 mpls_fec * fec, ldp_attr * r_attr, ldp_attr * s_attr)
311 int i;
313 MPLS_ASSERT(s && r_attr);
315 if (!(s->oper_loop_detection == LDP_LOOP_HOPCOUNT ||
316 s->oper_loop_detection == LDP_LOOP_HOPCOUNT_PATHVECTOR ||
317 r_attr->hopCountTlvExists)) { /* PRqA.1 */
318 return;
321 /* is this LSR allowed to be an LER for FEC? *//* PRqA.2 */
322 /* some policy gunk needs to be checked here */
323 /* if not goto PRqA.6 */
325 s_attr->hopCountTlvExists = 1; /* PRqA.3 */
326 s_attr->hopCountTlv.hcValue = 1;
328 if (s->oper_loop_detection == LDP_LOOP_NONE) { /* PRqA.4 */
329 return;
332 if (g->label_merge == MPLS_BOOL_TRUE) { /* PRqA.5 */
333 return;
335 goto Prepare_Label_Request_Attributes_13;
337 if (r_attr && r_attr->hopCountTlvExists) { /* PRqA.6 */
338 s_attr->hopCountTlvExists = 1; /* PRqA.7 */
339 s_attr->hopCountTlv.hcValue = (r_attr->hopCountTlv.hcValue) ?
340 (r_attr->hopCountTlv.hcValue + 1) : 0;
341 } else {
342 s_attr->hopCountTlvExists = 1; /* PRqA.8 */
343 s_attr->hopCountTlv.hcValue = 0;
346 if (s->oper_loop_detection == LDP_LOOP_NONE) { /* PRqA.9 */
347 return;
350 if (r_attr && r_attr->pathVecTlvExists) { /* PRqA.10 */
351 goto Prepare_Label_Request_Attributes_12;
354 if (g->label_merge == MPLS_BOOL_TRUE) { /* PRqA.11 */
355 return;
357 goto Prepare_Label_Request_Attributes_13;
359 Prepare_Label_Request_Attributes_12:
360 /* we only get to PRqA.12 if we have verified we have a r_attr */
361 s_attr->pathVecTlvExists = 1;
362 s_attr->pathVecTlv.lsrId[0] = g->lsr_identifier.u.ipv4;
363 for (i = 1; i < (MPLS_MAXHOPSNUMBER - 1); i++) {
364 if (r_attr->pathVecTlv.lsrId[i - 1]) {
365 s_attr->pathVecTlv.lsrId[i] = r_attr->pathVecTlv.lsrId[i - 1];
368 return;
370 Prepare_Label_Request_Attributes_13:
371 s_attr->pathVecTlvExists = 1;
372 s_attr->pathVecTlv.lsrId[0] = g->lsr_identifier.u.ipv4;
375 mpls_return_enum ldp_label_request_process(ldp_global * g, ldp_session * s,
376 ldp_adj * a, ldp_entity * e, ldp_attr * us_attr, ldp_fec * f)
378 ldp_session *nh_session = NULL;
379 ldp_nexthop *nh = NULL;
380 ldp_attr_list *us_list = NULL;
381 mpls_bool egress = MPLS_BOOL_FALSE;
382 mpls_bool egress_flag = MPLS_BOOL_FALSE;
383 ldp_attr *ds_attr = NULL;
384 ldp_attr *us_temp = NULL;
386 if (Check_Received_Attributes(g, s, us_attr, MPLS_LBLREQ_MSGTYPE) !=
387 MPLS_SUCCESS) { /* LRp.1 */
388 goto LRq_13;
391 if (f == NULL) {
392 ldp_notif_send(g, s, us_attr, LDP_NOTIF_NO_ROUTE); /* LRq.5 */
393 goto LRq_13;
396 /* just find one valid nexthop session for now */
397 nh = MPLS_LIST_HEAD(&f->nh_root);
398 while (nh) {
399 if (!nh_session) {
400 nh_session = ldp_session_for_nexthop(nh);
402 if (egress_flag == MPLS_BOOL_FALSE) {
403 egress_flag = mpls_policy_egress_check(g->user_data, &f->info, &nh->info);
405 nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec);
408 if ((!nh_session) && (egress_flag == MPLS_BOOL_TRUE)) {
409 egress = MPLS_BOOL_TRUE;
411 if (nh_session != NULL && s->index == nh_session->index) { /* LRq.3 */
412 ldp_notif_send(g, s, us_attr, LDP_NOTIF_LOOP_DETECTED); /* LRq.4 */
413 goto LRq_13;
416 if ((us_list = ldp_attr_find_upstream_all2(g, s, f)) != NULL) {
417 us_temp = MPLS_LIST_HEAD(us_list);
418 while (us_temp != NULL) {
419 if (us_temp->state == LDP_LSP_STATE_REQ_RECV && /* LRq.6 */
420 us_temp->msg_id == us_attr->msg_id) { /* LRq.7 */
421 goto LRq_13;
423 us_temp = MPLS_LIST_NEXT(us_list, us_temp, _fs);
427 us_attr->state = LDP_LSP_STATE_REQ_RECV; /* LRq.8 */
429 if (ldp_attr_insert_upstream2(g, s, us_attr, f) != MPLS_SUCCESS) {
430 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_ERROR,
431 "Couldn't insert recv attributes in tree\n");
432 goto ldp_label_request_process_error;
435 if (nh_session) {
436 ds_attr = ldp_attr_find_downstream_state2(g, nh_session, f,
437 LDP_LSP_STATE_MAP_RECV);
438 } else {
439 ds_attr = NULL;
442 if (g->lsp_control_mode == LDP_CONTROL_INDEPENDENT) { /* LRq.9 */
443 if (ldp_label_mapping_with_xc(g, s, f, &us_attr, ds_attr) != MPLS_SUCCESS) {
444 goto ldp_label_request_process_error;
447 if (egress == MPLS_BOOL_TRUE || ds_attr) {
448 goto LRq_11;
450 } else {
451 if ((!(egress == MPLS_BOOL_TRUE || ds_attr)) ||
452 (g->label_merge == MPLS_BOOL_FALSE)) {
453 goto LRq_10;
456 if (ldp_label_mapping_with_xc(g, s, f, &us_attr, ds_attr) != MPLS_SUCCESS) {
457 goto ldp_label_request_process_error;
459 goto LRq_11;
462 LRq_10:
463 ds_attr = NULL;
464 if (ldp_label_request_for_xc(g, nh_session, &f->info, us_attr, &ds_attr) !=
465 MPLS_SUCCESS) {
466 goto ldp_label_request_process_error;
469 LRq_11:
470 /* the work done by LRq_11 is handled in ldp_label_mapping_with_xc() */
471 LRq_13:
472 if (ds_attr != NULL && ds_attr->in_tree == MPLS_BOOL_FALSE) {
473 ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE);
475 return MPLS_SUCCESS;
477 ldp_label_request_process_error:
478 return MPLS_FAILURE;