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"
14 #include "ldp_session.h"
15 #include "ldp_inlabel.h"
16 #include "ldp_outlabel.h"
17 #include "ldp_global.h"
18 #include "ldp_label_mapping.h"
19 #include "ldp_label_request.h"
20 #include "ldp_label_abort.h"
21 #include "ldp_label_rel_with.h"
22 #include "mpls_mm_impl.h"
23 #include "mpls_policy_impl.h"
24 #include "mpls_trace_impl.h"
29 #include "mpls_mpls_impl.h"
32 mpls_return_enum
Recognize_New_Fec(ldp_global
* g
, mpls_fec
* f
)
34 ldp_session
*peer
= NULL
;
35 ldp_session
*nh_session
= NULL
;
36 ldp_attr
*ds_attr
= NULL
;
37 ldp_attr
*us_attr
= NULL
;
38 mpls_bool egress
= MPLS_BOOL_FALSE
;
42 LDP_ENTER(g
->user_data
, "Recognize_New_Fec");
45 * find the info about the next hop for this FEC
47 switch (ldp_get_next_hop_session_for_fec(g
, f
, &nh_addr
, &nh_session
)) {
52 * we found the route, but no next hop
54 egress
= MPLS_BOOL_TRUE
;
63 ds_attr
= ldp_attr_find_downstream_state(g
, nh_session
, f
,
64 LDP_LSP_STATE_MAP_RECV
);
65 if (ds_attr
&& !ds_attr
->outlabel
) {
66 out
= ldp_outlabel_create_complete(g
, nh_session
, nh_addr
, ds_attr
);
70 ds_attr
->outlabel
= out
;
75 * for every peer except the nh hop peer, check to see if we need to
78 peer
= MPLS_LIST_HEAD(&g
->session
);
79 while (peer
!= NULL
) { /* FEC.1 */
80 if ((peer
->state
!= LDP_STATE_OPERATIONAL
) ||
81 (nh_session
&& peer
->index
== nh_session
->index
)) {
84 /* have I already sent a mapping for FEC to peer */
85 if ((us_attr
= ldp_attr_find_upstream_state(g
, peer
, f
,
86 LDP_LSP_STATE_MAP_SENT
))) {
87 /* yep, don't send another */
89 if (ldp_inlabel_add_outlabel(g
, us_attr
->inlabel
,
90 ds_attr
->outlabel
) != MPLS_SUCCESS
) {
97 if (peer
->oper_distribution_mode
== LDP_DISTRIBUTION_UNSOLICITED
) {
98 if (g
->lsp_control_mode
== LDP_CONTROL_INDEPENDENT
) {
100 ldp_attr_find_upstream_state(g
, peer
, f
, LDP_LSP_STATE_REQ_RECV
);
103 if (ldp_label_mapping_with_xc(g
, peer
, f
, &us_attr
, ds_attr
) !=
105 if (!us_attr
->in_tree
) {
106 ldp_attr_remove_complete(g
, us_attr
, MPLS_BOOL_FALSE
);
115 if (ds_attr
|| egress
== MPLS_BOOL_TRUE
) { /* FEC.1.DUO2 */
116 if (!(us_attr
= ldp_attr_create(f
))) {
120 if ((egress
== MPLS_BOOL_TRUE
) && (mpls_policy_egress_check(
121 g
->user_data
, f
, &f
->nh
) == MPLS_BOOL_TRUE
)) {
125 if (ldp_label_mapping_with_xc(g
, peer
, f
, &us_attr
, ds_attr
) !=
133 peer
= MPLS_LIST_NEXT(&g
->session
, peer
, _global
);
136 if (ds_attr
) { /* FEC.2 */
137 if (ldp_label_mapping_process(g
, nh_session
, NULL
, NULL
, ds_attr
, f
) ==
138 MPLS_FAILURE
) { /* FEC.5 */
145 * LDP_DISTRIBUTION_ONDEMAND
149 nh_session
->oper_distribution_mode
== LDP_DISTRIBUTION_ONDEMAND
) {
150 /* assume we're always "request when needed" */
152 if (ldp_label_request_for_xc(g
, nh_session
, f
, NULL
, &ds_attr
) ==
153 MPLS_FAILURE
) { /* FEC.4 */
158 LDP_EXIT(g
->user_data
, "Recognize_New_Fec");
160 return MPLS_SUCCESS
; /* FEC.6 */
163 mpls_return_enum
Detect_Change_Fec_Next_Hop(ldp_global
* g
, mpls_fec
* f
,
164 ldp_session
* nh_old
)
166 ldp_session
*peer
= NULL
;
167 ldp_attr
*us_attr
= NULL
;
168 ldp_attr
*ds_attr
= NULL
;
169 ldp_session
*nh_session_new
= NULL
;
170 ldp_addr
*nh_new
= NULL
;
171 mpls_return_enum result
;
173 LDP_ENTER(g
->user_data
, "Detect_Change_Fec_Next_Hop");
175 result
= ldp_get_next_hop_session_for_fec(g
, f
, &nh_new
, &nh_session_new
);
178 * NH 1-5 decide if we need to release an existing mapping
181 ldp_attr_find_downstream_state(g
, nh_old
, f
, LDP_LSP_STATE_MAP_RECV
);
182 if (!ds_attr
) { /* NH.1 */
183 goto Detect_Change_Fec_Next_Hop_6
;
186 if (ds_attr
->ingress
== MPLS_BOOL_TRUE
) {
190 ftn
.outsegment_index
= ds_attr
->outlabel
->info
.handle
;
191 memcpy(&ftn
.fec
, f
, sizeof(mpls_fec
));
192 lsr_cfg_ftn_set2(g
->lsr_handle
, &ftn
, LSR_CFG_DEL
);
194 mpls_mpls_fec2out_del(g
->mpls_handle
, f
, &ds_attr
->outlabel
->info
);
196 ds_attr
->ingress
= MPLS_BOOL_FALSE
;
197 ds_attr
->outlabel
->merge_count
--;
200 if (g
->label_retention_mode
== LDP_RETENTION_LIBERAL
) { /* NH.3 */
202 us_attr
= MPLS_LIST_HEAD(&ds_attr
->us_attr_root
);
204 /* need to walk the list in such a way as not to
205 * "pull the rug out from under me self"
207 us_temp
= MPLS_LIST_NEXT(&ds_attr
->us_attr_root
, us_attr
, _ds_attr
);
208 if (us_attr
->state
== LDP_LSP_STATE_MAP_SENT
) {
209 ldp_inlabel_del_outlabel(g
, us_attr
->inlabel
); /* NH.2 */
210 ldp_attr_del_us2ds(us_attr
, ds_attr
);
214 goto Detect_Change_Fec_Next_Hop_6
;
217 ldp_label_release_send(g
, nh_old
, ds_attr
, LDP_NOTIF_NONE
); /* NH.4 */
218 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
); /* NH.2,5 */
220 Detect_Change_Fec_Next_Hop_6
:
223 * NH 6-9 decides is we need to send a label request abort
226 ldp_attr_find_downstream_state(g
, nh_old
, f
, LDP_LSP_STATE_REQ_SENT
);
227 if (ds_attr
) { /* NH.6 */
228 if (g
->label_retention_mode
!= LDP_RETENTION_CONSERVATIVE
) { /* NH.7 */
230 if (ldp_label_abort_send(g
, nh_old
, ds_attr
) != MPLS_SUCCESS
) {
237 * NH 10-12 decides if we can use a mapping from our database
239 if (result
!= MPLS_SUCCESS
) {
240 goto Detect_Change_Fec_Next_Hop_16
;
244 ldp_attr_find_downstream_state(g
, nh_session_new
, f
, LDP_LSP_STATE_MAP_RECV
);
245 if (!ds_attr
) { /* NH.11 */
246 goto Detect_Change_Fec_Next_Hop_13
;
249 if (ldp_label_mapping_process(g
, nh_session_new
, NULL
, NULL
, ds_attr
, f
) !=
250 MPLS_SUCCESS
) { /* NH.12 */
253 goto Detect_Change_Fec_Next_Hop_20
;
255 Detect_Change_Fec_Next_Hop_13
:
258 * NH 13-15 decides if we need to make a label request
260 if (nh_session_new
->oper_distribution_mode
== LDP_DISTRIBUTION_ONDEMAND
&&
261 g
->label_retention_mode
== LDP_RETENTION_CONSERVATIVE
) {
263 if (ldp_label_request_for_xc(g
, nh_session_new
, f
, NULL
, &ds_attr
) !=
268 goto Detect_Change_Fec_Next_Hop_20
;
270 Detect_Change_Fec_Next_Hop_16
:
272 peer
= MPLS_LIST_HEAD(&g
->session
);
274 if (peer
->state
== LDP_STATE_OPERATIONAL
) {
275 us_attr
= ldp_attr_find_upstream_state(g
, peer
, f
,
276 LDP_LSP_STATE_MAP_SENT
);
277 if (us_attr
) { /* NH.17 */
278 if (ldp_label_withdraw_send(g
, peer
, us_attr
, LDP_NOTIF_NONE
) !=
279 MPLS_SUCCESS
) { /* NH.18 */
280 ldp_attr_remove_complete(g
, us_attr
, MPLS_BOOL_FALSE
);
285 peer
= MPLS_LIST_NEXT(&g
->session
, peer
, _global
);
288 Detect_Change_Fec_Next_Hop_20
:
290 LDP_EXIT(g
->user_data
, "Detect_Change_Fec_Next_Hop");
295 ldp_fec
*ldp_fec_create()
297 ldp_fec
*fec
= (ldp_fec
*) mpls_malloc(sizeof(ldp_fec
));
300 memset(fec
, 0, sizeof(ldp_fec
));
301 MPLS_REFCNT_INIT(fec
, 0);
302 MPLS_LIST_ELEM_INIT(fec
, _global
);
303 MPLS_LIST_ELEM_INIT(fec
, _inlabel
);
304 MPLS_LIST_ELEM_INIT(fec
, _outlabel
);
305 MPLS_LIST_ELEM_INIT(fec
, _fec
);
306 MPLS_LIST_ELEM_INIT(fec
, _nh
);
307 MPLS_LIST_INIT(&fec
->fs_root_us
, ldp_fs
);
308 MPLS_LIST_INIT(&fec
->fs_root_ds
, ldp_fs
);
309 fec
->info
.type
= MPLS_FEC_NONE
;
310 fec
->info
.nh
.type
= MPLS_NH_NONE
;
311 fec
->info
.nh
.attached
= MPLS_BOOL_FALSE
;
316 void mpls_fec2ldp_fec(mpls_fec
* a
, ldp_fec
* b
)
318 memcpy(&b
->info
, a
, sizeof(mpls_fec
));
321 ldp_fec
*ldp_fec_create_host(mpls_inet_addr
* host
)
323 ldp_fec
*fec
= ldp_fec_create();
326 fec
->info
.type
= MPLS_FEC_HOST
;
327 memcpy(&fec
->info
.u
.host
, host
, sizeof(mpls_inet_addr
));
332 ldp_fec
*ldp_fec_create_prefix(mpls_inet_addr
* prefix
, int prefix_len
)
334 ldp_fec
*fec
= ldp_fec_create();
337 fec
->info
.type
= MPLS_FEC_PREFIX
;
338 memcpy(&fec
->info
.u
.prefix
.network
, prefix
, sizeof(mpls_inet_addr
));
339 fec
->info
.u
.prefix
.length
= prefix_len
;
344 void ldp_fec_delete(ldp_fec
* fec
)
349 void mpls_fec2fec_tlv(mpls_fec
* lf
, mplsLdpFecTlv_t
* tlv
, int i
)
351 tlv
->fecElArray
[i
].addressEl
.addressFam
= 1;
354 case MPLS_FEC_PREFIX
:
355 tlv
->fecElArray
[i
].addressEl
.type
= MPLS_PREFIX_FEC
;
356 tlv
->fecElArray
[i
].addressEl
.preLen
= lf
->u
.prefix
.length
;
357 tlv
->fecElArray
[i
].addressEl
.address
= lf
->u
.prefix
.network
.u
.ipv4
;
358 tlv
->fecElemTypes
[i
] = MPLS_PREFIX_FEC
;
361 tlv
->fecElArray
[i
].addressEl
.type
= MPLS_HOSTADR_FEC
;
362 tlv
->fecElArray
[i
].addressEl
.preLen
= MPLS_IPv4LEN
;
363 tlv
->fecElArray
[i
].addressEl
.address
= lf
->u
.host
.u
.ipv4
;
364 tlv
->fecElemTypes
[i
] = MPLS_HOSTADR_FEC
;
371 void fec_tlv2mpls_fec(mplsLdpFecTlv_t
* tlv
, int i
, mpls_fec
* lf
) {
372 switch (tlv
->fecElemTypes
[i
]) {
373 case MPLS_PREFIX_FEC
:
374 lf
->type
= MPLS_FEC_PREFIX
;
375 lf
->u
.prefix
.length
= tlv
->fecElArray
[i
].addressEl
.preLen
;
376 lf
->u
.prefix
.network
.u
.ipv4
= tlv
->fecElArray
[i
].addressEl
.address
;
377 lf
->u
.prefix
.network
.type
= MPLS_FAMILY_IPV4
;
379 case MPLS_HOSTADR_FEC
:
380 lf
->type
= MPLS_FEC_HOST
;
381 lf
->u
.host
.u
.ipv4
= tlv
->fecElArray
[i
].addressEl
.address
;
382 lf
->u
.host
.type
= MPLS_FAMILY_IPV4
;