📄 ldp_fec.c
字号:
/* * Copyright (C) James R. Leu 2000 * jleu@mindspring.com * * This software is covered under the LGPL, for more * info check out http://www.gnu.org/copyleft/lgpl.html */#include "ldp_struct.h"#include "ldp_fec.h"#include "ldp_if.h"#include "ldp_attr.h"#include "ldp_addr.h"#include "ldp_nexthop.h"#include "ldp_session.h"#include "ldp_inlabel.h"#include "ldp_outlabel.h"#include "ldp_global.h"#include "ldp_label_mapping.h"#include "ldp_label_request.h"#include "ldp_label_abort.h"#include "ldp_label_rel_with.h"#include "mpls_assert.h"#include "mpls_compare.h"#include "mpls_mm_impl.h"#include "mpls_tree_impl.h"#include "mpls_policy_impl.h"#include "mpls_trace_impl.h"#if MPLS_USE_LSR#include "lsr_cfg.h"#else#include "mpls_mpls_impl.h"#endifstatic uint32_t _ldp_fec_next_index = 1;static mpls_return_enum ldp_fec_insert(ldp_global *g, ldp_fec * fec){ mpls_return_enum retval = MPLS_SUCCESS; uint32_t key; uint8_t len; MPLS_ASSERT(g && fec); LDP_ENTER(g->user_data, "ldp_fec_insert"); switch(fec->info.type) { case MPLS_FEC_PREFIX: key = fec->info.u.prefix.network.u.ipv4; len = fec->info.u.prefix.length; break; case MPLS_FEC_HOST: key = fec->info.u.host.u.ipv4; len = 32; break; case MPLS_FEC_L2CC: /* they had better insert it into the global list */ LDP_EXIT(g->user_data, "ldp_fec_insert: l2cc"); return MPLS_SUCCESS; default: MPLS_ASSERT(0); } LDP_PRINT(g->user_data, "ldp_fec_insert: 0x%08x/%d\n", key, len); if (mpls_tree_insert(g->fec_tree, key, len, (void *)fec) != MPLS_SUCCESS) { LDP_PRINT(g->user_data, "ldp_fec_insert: error adding fec\n"); retval = MPLS_FATAL; } LDP_EXIT(g->user_data, "ldp_fec_insert"); return retval;}static void ldp_fec_remove(ldp_global *g, mpls_fec *fec){ ldp_fec *f = NULL; uint32_t key; uint8_t len; MPLS_ASSERT(g && fec); LDP_ENTER(g->user_data, "ldp_fec_remove"); switch(fec->type) { case MPLS_FEC_PREFIX: key = fec->u.prefix.network.u.ipv4; len = fec->u.prefix.length; break; case MPLS_FEC_HOST: key = fec->u.host.u.ipv4; len = 32; break; case MPLS_FEC_L2CC: /* they had better remove it from the global list */ LDP_EXIT(g->user_data, "ldp_fec_remove"); return; default: MPLS_ASSERT(0); } LDP_PRINT(g->user_data, "ldp_fec_remove: 0x%08x/%d\n", key, len); mpls_tree_remove(g->fec_tree, key, len, (void **)&f); MPLS_ASSERT(f); LDP_EXIT(g->user_data, "ldp_fec_remove");}static uint32_t _ldp_fec_get_next_index(){ uint32_t retval = _ldp_fec_next_index; _ldp_fec_next_index++; if (retval > _ldp_fec_next_index) { _ldp_fec_next_index = 1; } return retval;}ldp_fec *ldp_fec_create(ldp_global *g, mpls_fec *f){ ldp_fec *fec = (ldp_fec *) mpls_malloc(sizeof(ldp_fec)); if (fec != NULL) { memset(fec, 0, sizeof(ldp_fec)); /* * note: this is init to 1 for a reason! * We're placing it in the global list, so this is our refcnt * when this refcnt gets to zero, it will be removed from the * global list and deleted */ /* * TESTING: jleu 6/7/2004, since I want the FEC to be cleaned up * when it no longer has a nexthop, addr, or label, the only things that * should increment the ref are those (nh, addr, label etc), not global * nor inserting into the tree. I also added this comment in * _ldp_global_add_fec() MPLS_REFCNT_INIT(fec, 1); */ MPLS_REFCNT_INIT(fec, 0); MPLS_LIST_ELEM_INIT(fec, _global); MPLS_LIST_ELEM_INIT(fec, _inlabel); MPLS_LIST_ELEM_INIT(fec, _outlabel); MPLS_LIST_ELEM_INIT(fec, _fec); MPLS_LIST_INIT(&fec->nh_root, ldp_nexthop); MPLS_LIST_INIT(&fec->fs_root_us, ldp_fs); MPLS_LIST_INIT(&fec->fs_root_ds, ldp_fs); fec->index = _ldp_fec_get_next_index(); fec->is_route = MPLS_BOOL_FALSE; mpls_fec2ldp_fec(f,fec); _ldp_global_add_fec(g, fec); ldp_fec_insert(g, fec); } return fec;}void ldp_fec_delete(ldp_global *g, ldp_fec * fec){ LDP_PRINT(g->user_data, "fec delete: %08x/%d", fec->info.u.prefix.network.u.ipv4, fec->info.u.prefix.length); ldp_fec_remove(g, &fec->info); _ldp_global_del_fec(g, fec); mpls_free(fec);}ldp_fec *ldp_fec_find(ldp_global *g, mpls_fec *fec){ ldp_fec *f = NULL; uint32_t key; uint8_t len; switch(fec->type) { case MPLS_FEC_PREFIX: key = fec->u.prefix.network.u.ipv4; len = fec->u.prefix.length; break; case MPLS_FEC_HOST: key = fec->u.host.u.ipv4; len = 32; break; case MPLS_FEC_L2CC: if (ldp_global_find_fec(g, fec, &f) == MPLS_SUCCESS) { return f; } return NULL; default: MPLS_ASSERT(0); } LDP_PRINT(g->user_data, "ldp_fec_find: 0x%08x/%d\n", key, len); if (mpls_tree_get(g->fec_tree, key, len, (void **)&f) != MPLS_SUCCESS) { return NULL; } return f;}ldp_fec *ldp_fec_find2(ldp_global *g, mpls_fec *fec){ ldp_fec *f = NULL; f = ldp_fec_find(g, fec); if (!f) { f = ldp_fec_create(g, fec); } return f;}ldp_nexthop *ldp_fec_nexthop_find(ldp_fec *f, mpls_nexthop *n){ ldp_nexthop *nh = NULL; MPLS_ASSERT(f && n); nh = MPLS_LIST_HEAD(&f->nh_root); while (nh) { if (!mpls_nexthop_compare(&nh->info, n)) { return nh; } nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec); } return NULL;}mpls_return_enum ldp_fec_find_nexthop_index(ldp_fec *f, int index, ldp_nexthop **n){ ldp_nexthop *nh = NULL; MPLS_ASSERT(f); if (index > 0) { /* because we sort our inserts by index, this lets us know if we've "walked" past the end of the list */ nh = MPLS_LIST_TAIL(&f->nh_root); if (!nh || nh->index < index) { *n = NULL; return MPLS_END_OF_LIST; } nh = MPLS_LIST_HEAD(&f->nh_root); do { if (nh->index == index) { *n = nh; return MPLS_SUCCESS; } } while((nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec))); } *n = NULL; return MPLS_FAILURE;}mpls_return_enum ldp_fec_add_nexthop(ldp_global *g, ldp_fec * f, ldp_nexthop * nh){ MPLS_ASSERT(f && nh); LDP_ENTER(g->user_data, "ldp_fec_add_nexthop"); MPLS_REFCNT_HOLD(nh); MPLS_LIST_ADD_HEAD(&f->nh_root, nh, _fec, ldp_nexthop); ldp_nexthop_add_fec(nh, f); LDP_EXIT(g->user_data, "ldp_fec_add_nexthop: success"); return MPLS_SUCCESS;ldp_fec_add_nexthop_error: ldp_fec_del_nexthop(g, f, nh); LDP_EXIT(g->user_data, "ldp_fec_add_nexthop: fail"); return MPLS_FATAL;}void ldp_fec_del_nexthop(ldp_global *g, ldp_fec * f, ldp_nexthop *nh){ MPLS_ASSERT(f && nh); MPLS_LIST_REMOVE(&f->nh_root, nh, _fec); ldp_nexthop_del_fec(g, nh); MPLS_REFCNT_RELEASE2(g, nh, ldp_nexthop_delete);}mpls_return_enum ldp_fec_process_add(ldp_global * g, ldp_fec * f, ldp_nexthop *nh, ldp_session *nh_session){ ldp_session *peer = NULL; ldp_attr *ds_attr = NULL; ldp_attr *us_attr = NULL; mpls_bool egress; ldp_outlabel *out; LDP_ENTER(g->user_data, "ldp_fec_process_add"); /* * find the info about the next hop for this FEC */ if (!nh_session) { nh_session = ldp_get_next_hop_session_for_fec2(f, nh); } if (nh_session) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -