📄 zebra_rib.c
字号:
/* If there is no selected route or matched route is EGP, go up tree. */ if (! match || match->type == ZEBRA_ROUTE_BGP) { do { rn = rn->parent; } while (rn && rn->info == NULL); if (rn) route_lock_node (rn); } else { if (match->type == ZEBRA_ROUTE_CONNECT) /* Directly point connected route. */ return match; else { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) return match; return NULL; } } } return NULL;}struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *p){ struct route_table *table; struct route_node *rn; struct rib *match; struct nexthop *nexthop; /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return 0; rn = route_node_lookup (table, (struct prefix *) p); /* No route for this prefix. */ if (! rn) return NULL; /* Unlock node. */ route_unlock_node (rn); /* Pick up selected route. */ for (match = rn->info; match; match = match->next) if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) break; if (! match || match->type == ZEBRA_ROUTE_BGP) return NULL; if (match->type == ZEBRA_ROUTE_CONNECT) return match; for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next) if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) return match; return NULL;}#ifdef HAVE_IPV6struct rib *rib_match_ipv6 (struct in6_addr *addr){ struct prefix_ipv6 p; struct route_table *table; struct route_node *rn; struct rib *match; struct nexthop *newhop; /* Lookup table. */ table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); if (! table) return 0; memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = IPV6_MAX_PREFIXLEN; IPV6_ADDR_COPY (&p.prefix, addr); rn = route_node_match (table, (struct prefix *) &p); while (rn) { route_unlock_node (rn); /* Pick up selected route. */ for (match = rn->info; match; match = match->next) if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) break; /* If there is no selected route or matched route is EGP, go up tree. */ if (! match || match->type == ZEBRA_ROUTE_BGP) { do { rn = rn->parent; } while (rn && rn->info == NULL); if (rn) route_lock_node (rn); } else { if (match->type == ZEBRA_ROUTE_CONNECT) /* Directly point connected route. */ return match; else { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) return match; return NULL; } } } return NULL;}#endif /* HAVE_IPV6 */intnexthop_active_check (struct route_node *rn, struct rib *rib, struct nexthop *nexthop, int set){ struct interface *ifp; switch (nexthop->type) { case NEXTHOP_TYPE_IFINDEX: ifp = if_lookup_by_index (nexthop->ifindex); if (ifp && if_is_up (ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); break; case NEXTHOP_TYPE_IFNAME: case NEXTHOP_TYPE_IPV6_IFNAME: ifp = if_lookup_by_name (nexthop->ifname); if (ifp && if_is_up (ifp)) { if (set) nexthop->ifindex = ifp->ifindex; SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); } else { if (set) nexthop->ifindex = 0; UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); } break; case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: if (nexthop_active_ipv4 (rib, nexthop, set, rn)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); break;#ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: if (nexthop_active_ipv6 (rib, nexthop, set, rn)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); break; case NEXTHOP_TYPE_IPV6_IFINDEX: if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) { ifp = if_lookup_by_index (nexthop->ifindex); if (ifp && if_is_up (ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); } else { if (nexthop_active_ipv6 (rib, nexthop, set, rn)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); } break;#endif /* HAVE_IPV6 */ case NEXTHOP_TYPE_BLACKHOLE: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); break; default: break; } return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);}intnexthop_active_update (struct route_node *rn, struct rib *rib, int set){ struct nexthop *nexthop; int active; rib->nexthop_active_num = 0; UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); rib->nexthop_active_num += nexthop_active_check (rn, rib, nexthop, set); if (active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); } return rib->nexthop_active_num;}#define RIB_SYSTEM_ROUTE(R) \ ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)voidnewrib_free (struct rib *rib){ struct nexthop *nexthop; struct nexthop *next; for (nexthop = rib->nexthop; nexthop; nexthop = next) { next = nexthop->next; nexthop_free (nexthop); } XFREE (MTYPE_RIB, rib);}voidrib_install_kernel (struct route_node *rn, struct rib *rib){ int ret = 0; struct nexthop *nexthop; switch (PREFIX_FAMILY (&rn->p)) { case AF_INET: ret = kernel_add_ipv4 (&rn->p, rib); break;#ifdef HAVE_IPV6 case AF_INET6: ret = kernel_add_ipv6 (&rn->p, rib); break;#endif /* HAVE_IPV6 */ } if (ret < 0) { for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); }}/* Uninstall the route from kernel. */intrib_uninstall_kernel (struct route_node *rn, struct rib *rib){ int ret = 0; struct nexthop *nexthop; switch (PREFIX_FAMILY (&rn->p)) { case AF_INET: ret = kernel_delete_ipv4 (&rn->p, rib); break;#ifdef HAVE_IPV6 case AF_INET6: ret = kernel_delete_ipv6 (&rn->p, rib); break;#endif /* HAVE_IPV6 */ } for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); return ret;}/* Uninstall the route from kernel. */voidrib_uninstall (struct route_node *rn, struct rib *rib){ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) { redistribute_delete (&rn->p, rib); if (! RIB_SYSTEM_ROUTE (rib)) rib_uninstall_kernel (rn, rib); UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED); }}/* Core function for processing routing information base. */voidrib_process (struct route_node *rn, struct rib *del){ struct rib *rib; struct rib *next; struct rib *fib = NULL; struct rib *select = NULL; for (rib = rn->info; rib; rib = next) { next = rib->next; /* Currently installed rib. */ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) fib = rib; /* Skip unreachable nexthop. */ if (! nexthop_active_update (rn, rib, 0)) continue; /* Infinit distance. */ if (rib->distance == DISTANCE_INFINITY) continue; /* Newly selected rib. */ if (! select || rib->distance < select->distance || rib->type == ZEBRA_ROUTE_CONNECT) select = rib; } /* Deleted route check. */ if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED)) fib = del; /* Same route is selected. */ if (select && select == fib) { if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) { redistribute_delete (&rn->p, select); if (! RIB_SYSTEM_ROUTE (select)) rib_uninstall_kernel (rn, select); /* Set real nexthop. */ nexthop_active_update (rn, select, 1); if (! RIB_SYSTEM_ROUTE (select)) rib_install_kernel (rn, select); redistribute_add (&rn->p, select); } return; } /* Uninstall old rib from forwarding table. */ if (fib) { redistribute_delete (&rn->p, fib); if (! RIB_SYSTEM_ROUTE (fib)) rib_uninstall_kernel (rn, fib); UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED); /* Set real nexthop. */ nexthop_active_update (rn, fib, 1); } /* Install new rib into forwarding table. */ if (select) { /* Set real nexthop. */ nexthop_active_update (rn, select, 1); if (! RIB_SYSTEM_ROUTE (select)) rib_install_kernel (rn, select); SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); redistribute_add (&rn->p, select); }}/* Add RIB to head of the route node. */voidrib_addnode (struct route_node *rn, struct rib *rib){ struct rib *head; head = rn->info; if (head) head->prev = rib; rib->next = head; rn->info = rib;}voidrib_delnode (struct route_node *rn, struct rib *rib){ if (rib->next) rib->next->prev = rib->prev; if (rib->prev) rib->prev->next = rib->next; else rn->info = rib->next;}intrib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, u_int32_t metric, u_char distance){ struct rib *rib; struct rib *same = NULL; struct route_table *table; struct route_node *rn; struct nexthop *nexthop; /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return 0; /* Make it sure prefixlen is applied to the prefix. */ apply_mask_ipv4 (p); /* Set default distance by route type. */ if (distance == 0) { distance = route_info[type].distance; /* iBGP distance is 200. */ if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) distance = 200; } /* Lookup route node.*/ rn = route_node_get (table, (struct prefix *) p); /* If same type of route are installed, treat it as a implicit withdraw. */ for (rib = rn->info; rib; rib = rib->next) { if (rib->type == ZEBRA_ROUTE_CONNECT) { nexthop = rib->nexthop; /* Duplicate connected route comes in. */ if (rib->type == type && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) { rib->refcnt++; return 0 ; } } else if (rib->type == type) { same = rib; rib_delnode (rn, same); route_unlock_node (rn); break; } } /* Allocate new rib structure. */ rib = XMALLOC (MTYPE_RIB, sizeof (struct rib)); memset (rib, 0, sizeof (struct rib)); rib->type = type; rib->distance = distance; rib->flags = flags; rib->metric = metric; rib->nexthop_num = 0; rib->uptime = time (NULL); /* Nexthop settings. */ if (gate) { if (ifindex) nexthop_ipv4_ifindex_add (rib, gate, ifindex); else nexthop_ipv4_add (rib, gate); } else nexthop_ifindex_add (rib, ifindex); /* If this route is kernel route, set FIB flag to the route. */ if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); /* Link new rib to node.*/ rib_addnode (rn, rib); /* Process this route node. */ rib_process (rn, same); /* Free implicit route.*/ if (same) newrib_free (same); return 0;}intrib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib){ struct route_table *table; struct route_node *rn; struct rib *same; struct nexthop *nexthop; /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return 0; /* Make it sure prefixlen is applied to the prefix. */ apply_mask_ipv4 (p); /* Set default distance by route type. */ if (rib->distance == 0) { rib->distance = route_info[rib->type].distance; /* iBGP distance is 200. */ if (rib->type == ZEBRA_ROUTE_BGP && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP)) rib->distance = 200; } /* Lookup route node.*/ rn = route_node_get (table, (struct prefix *) p); /* If same type of route are installed, treat it as a implicit withdraw. */ for (same = rn->info; same; same = same->next) { if (same->type == rib->type && same->table == rib->table && same->type != ZEBRA_ROUTE_CONNECT) { rib_delnode (rn, same); route_unlock_node (rn); break; } } /* If this route is kernel route, set FIB flag to the route. */ if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT) for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); /* Link new rib to node.*/ rib_addnode (rn, rib);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -