void isis_spftree_adj_del (struct isis_spftree *spftree, struct isis_adjacency *adj) { struct listnode *node; if (!adj) return; for (node = listhead (spftree->tents); node; node = listnextnode (node)) isis_vertex_adj_del (listgetdata (node), adj); for (node = listhead (spftree->paths); node; node = listnextnode (node)) isis_vertex_adj_del (listgetdata (node), adj); return; }
mpls_return_enum mpls_ifmgr_getnext_address(mpls_ifmgr_handle ifmgr_handle, mpls_if_handle *handle, mpls_inet_addr *addr) { struct connected *ifc; struct listnode *node; int next = 0; while ((*handle)) { for (node = listhead((*handle)->connected); node; listnextnode(node)) { ifc = listgetdata(node); if (ifc->address->family == AF_INET && ifc->address->u.prefix4.s_addr != htonl(INADDR_LOOPBACK)) { if (next) { addr->type = MPLS_FAMILY_IPV4; addr->u.ipv4 = ntohl(ifc->address->u.prefix4.s_addr); return MPLS_SUCCESS; } else if (addr->u.ipv4 == ntohl(ifc->address->u.prefix4.s_addr)) { next = 1; } } } (*handle) = if_getnext(*handle); next = 1; } return MPLS_END_OF_LIST; }
static void isis_vertex_adj_del (struct isis_vertex *vertex, struct isis_adjacency *adj) { struct listnode *node, *nextnode; if (!vertex) return; for (node = listhead (vertex->Adj_N); node; node = nextnode) { nextnode = listnextnode(node); if (listgetdata(node) == adj) list_delete_node(vertex->Adj_N, node); } return; }
/******************************************************************************* 函数名称 : bgp_info_mpath_update 功能描述 : mpath队列更新 输入参数 : 输出参数 : 返 回 值 : 无 -------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者 : 修改目的 : 新添加函数 修改日期 : 2012-8-15 *******************************************************************************/ void bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, struct bgp_info *old_best, struct list *mp_list, struct bgp_maxpaths_cfg *mpath_cfg) { u16 maxpaths, mpath_count, old_mpath_count; struct listnode *mp_node, *mp_next_node; struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; s32 mpath_changed; mpath_changed = 0; maxpaths = BGP_DEFAULT_MAXPATHS; mpath_count = 0; cur_mpath = NULL; old_mpath_count = 0; prev_mpath = new_best; mp_node = listhead (mp_list); if (new_best) { mpath_count++; if (new_best != old_best) { bgp_info_mpath_dequeue (new_best); } maxpaths = (peer_sort (new_best->peer) == BGP_PEER_IBGP) ? mpath_cfg->maxpaths_ibgp : mpath_cfg->maxpaths_ebgp; } if (old_best) { cur_mpath = bgp_info_mpath_first (old_best); old_mpath_count = bgp_info_mpath_count (old_best); bgp_info_mpath_count_set (old_best, 0); bgp_info_mpath_dequeue (old_best); } while (mp_node || cur_mpath) { if (!cur_mpath && (mpath_count >= maxpaths)) { break; } mp_next_node = mp_node ? listnextnode (mp_node) : NULL; next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL; if (mp_node && (listgetdata (mp_node) == cur_mpath)) { list_delete_node (mp_list, mp_node); bgp_info_mpath_dequeue (cur_mpath); if ((mpath_count < maxpaths) && bgp_info_nexthop_cmp (prev_mpath, cur_mpath)) { bgp_info_mpath_enqueue (prev_mpath, cur_mpath); prev_mpath = cur_mpath; mpath_count++; } else { mpath_changed = 1; } mp_node = mp_next_node; cur_mpath = next_mpath; continue; } if (cur_mpath && (!mp_node || (bgp_info_mpath_cmp (cur_mpath, listgetdata (mp_node)) < 0))) { bgp_info_mpath_dequeue (cur_mpath); mpath_changed = 1; cur_mpath = next_mpath; } else { new_mpath = listgetdata (mp_node); list_delete_node (mp_list, mp_node); if ((mpath_count < maxpaths) && (new_mpath != new_best) && bgp_info_nexthop_cmp (prev_mpath, new_mpath)) { if (new_mpath == next_mpath) { next_mpath = bgp_info_mpath_next (new_mpath); } bgp_info_mpath_dequeue (new_mpath); bgp_info_mpath_enqueue (prev_mpath, new_mpath); prev_mpath = new_mpath; mpath_changed = 1; mpath_count++; } mp_node = mp_next_node; } } if (new_best) { bgp_info_mpath_count_set (new_best, mpath_count-1); if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count)) { SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG); } } }
/* * Add a vertex to TENT sorted by cost and by vertextype on tie break situation */ static struct isis_vertex * isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, void *id, struct isis_adjacency *adj, u_int32_t cost, int depth, int family) { struct isis_vertex *vertex, *v; struct listnode *node; #ifdef EXTREME_DEBUG u_char buff[BUFSIZ]; #endif vertex = isis_vertex_new (id, vtype); vertex->d_N = cost; vertex->depth = depth; if (adj) listnode_add (vertex->Adj_N, adj); #ifdef EXTREME_DEBUG zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d", vtype2string (vertex->type), vid2string (vertex, buff), vertex->depth, vertex->d_N); #endif /* EXTREME_DEBUG */ listnode_add (spftree->tents, vertex); if (list_isempty (spftree->tents)) { listnode_add (spftree->tents, vertex); return vertex; } /* XXX: This cant use the standard ALL_LIST_ELEMENT macro */ for (node = listhead (spftree->tents); node; node = listnextnode (node)) { v = listgetdata (node); if (v->d_N > vertex->d_N) { list_add_node_prev (spftree->tents, node, vertex); break; } else if (v->d_N == vertex->d_N) { /* Tie break, add according to type */ while (v && v->d_N == vertex->d_N && v->type > vertex->type) { if (v->type > vertex->type) { break; } /* XXX: this seems dubious, node is the loop iterator */ node = listnextnode (node); (node) ? (v = listgetdata (node)) : (v = NULL); } list_add_node_prev (spftree->tents, node, vertex); break; } else if (node->next == NULL) { list_add_node_next (spftree->tents, node, vertex); break; } } return vertex; }
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, struct list *ifconnected) { struct listnode *node; uint16_t option_len = 0; uint8_t *curr; node = listhead(ifconnected); /* Empty address list ? */ if (!node) { return buf; } /* Skip first address (primary) */ node = listnextnode(node); /* Scan secondary address list */ curr = buf + 4; /* skip T and L */ for (; node; node = listnextnode(node)) { struct connected *ifc = listgetdata(node); struct prefix *p = ifc->address; if (p->family != AF_INET) continue; if ((curr + ucast_ipv4_encoding_len) > buf_pastend) { zlog_warn("%s: buffer overflow: left=%zd needed=%zu", __PRETTY_FUNCTION__, buf_pastend - curr, ucast_ipv4_encoding_len); return 0; } /* Write encoded unicast IPv4 address */ *(uint8_t *) curr = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ ++curr; *(uint8_t *) curr = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */ ++curr; memcpy(curr, &p->u.prefix4, sizeof(struct in_addr)); curr += sizeof(struct in_addr); option_len += ucast_ipv4_encoding_len; } if (PIM_DEBUG_PIM_TRACE) { zlog_warn("%s: number of encoded secondary unicast IPv4 addresses: %zu", __PRETTY_FUNCTION__, option_len / ucast_ipv4_encoding_len); } if (option_len < 1) { /* Empty secondary unicast IPv4 address list */ return buf; } /* * Write T and L */ *(uint16_t *) buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST); *(uint16_t *) (buf + 2) = htons(option_len); return curr; }