📄 zebra_rib.c
字号:
/* Free implicit route.*/ if (same) newrib_free (same); return 0;}intrib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id){ struct route_table *table; struct route_node *rn; struct rib *rib; struct rib *fib = NULL; struct rib *same = NULL; struct nexthop *nexthop; char buf1[BUFSIZ]; char buf2[BUFSIZ]; /* Apply mask. */ apply_mask_ipv6 (p); /* Lookup table. */ table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); if (! table) return 0; /* Lookup route node. */ rn = route_node_lookup (table, (struct prefix *) p); if (! rn) { if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib", inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ), p->prefixlen, inet_ntop (AF_INET6, gate, buf2, BUFSIZ), ifindex); else zlog_info ("route %s/%d ifindex %d doesn't exist in rib", inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ), p->prefixlen, ifindex); } return ZEBRA_ERR_RTNOEXIST; } /* Lookup same type route. */ for (rib = rn->info; rib; rib = rib->next) { if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) fib = rib; if (rib->type == ZEBRA_ROUTE_CONNECT) { nexthop = rib->nexthop; if (rib->type == type && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) { if (rib->refcnt) { rib->refcnt--; route_unlock_node (rn); route_unlock_node (rn); return 0; } same = rib; break; } } else { if (rib->type == type) { same = rib; break; } } } /* If same type of route can't be found and this message is from kernel. */ if (! same) { if (fib && type == ZEBRA_ROUTE_KERNEL) { /* Unset flags. */ for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED); } else { if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib", inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ), p->prefixlen, inet_ntop (AF_INET6, gate, buf2, BUFSIZ), ifindex, type); else zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib", inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ), p->prefixlen, ifindex, type); } route_unlock_node (rn); return ZEBRA_ERR_RTNOEXIST; } } if (same) rib_delnode (rn, same); /* Process changes. */ rib_process (rn, same); if (same) { newrib_free (same); route_unlock_node (rn); } route_unlock_node (rn); return 0;}/* Install static route into rib. */voidstatic_install_ipv6 (struct prefix *p, struct static_ipv6 *si){ struct rib *rib; struct route_table *table; struct route_node *rn; /* Lookup table. */ table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); if (! table) return; /* Lookup existing route */ rn = route_node_get (table, p); for (rib = rn->info; rib; rib = rib->next) if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) break; if (rib) { /* Same distance static route is there. Update it with new nexthop. */ rib_uninstall (rn, rib); route_unlock_node (rn); switch (si->type) { case STATIC_IPV6_GATEWAY: nexthop_ipv6_add (rib, &si->ipv6); break; case STATIC_IPV6_IFNAME: nexthop_ifname_add (rib, si->ifname); break; case STATIC_IPV6_GATEWAY_IFNAME: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname); break; } rib_process (rn, NULL); } else { /* This is new static route. */ rib = XMALLOC (MTYPE_RIB, sizeof (struct rib)); memset (rib, 0, sizeof (struct rib)); rib->type = ZEBRA_ROUTE_STATIC; rib->distance = si->distance; rib->metric = 0; rib->nexthop_num = 0; switch (si->type) { case STATIC_IPV6_GATEWAY: nexthop_ipv6_add (rib, &si->ipv6); break; case STATIC_IPV6_IFNAME: nexthop_ifname_add (rib, si->ifname); break; case STATIC_IPV6_GATEWAY_IFNAME: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname); break; } /* Link this rib to the tree. */ rib_addnode (rn, rib); /* Process this prefix. */ rib_process (rn, NULL); }}intstatic_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si){ if (nexthop->type == NEXTHOP_TYPE_IPV6 && si->type == STATIC_IPV6_GATEWAY && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)) return 1; if (nexthop->type == NEXTHOP_TYPE_IFNAME && si->type == STATIC_IPV6_IFNAME && strcmp (nexthop->ifname, si->ifname) == 0) return 1; if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME && si->type == STATIC_IPV6_GATEWAY_IFNAME && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6) && strcmp (nexthop->ifname, si->ifname) == 0) return 1; return 0;;}voidstatic_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si){ struct route_table *table; struct route_node *rn; struct rib *rib; struct nexthop *nexthop; /* Lookup table. */ table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); if (! table) return; /* Lookup existing route with type and distance. */ rn = route_node_lookup (table, (struct prefix *) p); if (! rn) return; for (rib = rn->info; rib; rib = rib->next) if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) break; if (! rib) { route_unlock_node (rn); return; } /* Lookup nexthop. */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) if (static_ipv6_nexthop_same (nexthop, si)) break; /* Can't find nexthop. */ if (! nexthop) { route_unlock_node (rn); return; } /* Check nexthop. */ if (rib->nexthop_num == 1) { rib_delnode (rn, rib); rib_process (rn, rib); newrib_free (rib); route_unlock_node (rn); } else { rib_uninstall (rn, rib); nexthop_delete (rib, nexthop); nexthop_free (nexthop); rib_process (rn, rib); } /* Unlock node. */ route_unlock_node (rn);}/* Add static route into static route configuration. */intstatic_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, char *ifname, u_char distance, u_int32_t vrf_id){ struct route_node *rn; struct static_ipv6 *si; struct static_ipv6 *pp; struct static_ipv6 *cp; struct route_table *stable; /* Lookup table. */ stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; /* Lookup static route prefix. */ rn = route_node_get (stable, p); /* Do nothing if there is a same static route. */ for (si = rn->info; si; si = si->next) { if (distance == si->distance && type == si->type && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6)) && (! ifname || strcmp (ifname, si->ifname) == 0)) { route_unlock_node (rn); return 0; } } /* Make new static route structure. */ si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6)); memset (si, 0, sizeof (struct static_ipv6)); si->type = type; si->distance = distance; switch (type) { case STATIC_IPV6_GATEWAY: si->ipv6 = *gate; break; case STATIC_IPV6_IFNAME: si->ifname = XSTRDUP (0, ifname); break; case STATIC_IPV6_GATEWAY_IFNAME: si->ipv6 = *gate; si->ifname = XSTRDUP (0, ifname); break; } /* Add new static route information to the tree with sort by distance value and gateway address. */ for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) { if (si->distance < cp->distance) break; if (si->distance > cp->distance) continue; } /* Make linked list. */ if (pp) pp->next = si; else rn->info = si; if (cp) cp->prev = si; si->prev = pp; si->next = cp; /* Install into rib. */ static_install_ipv6 (p, si); return 1;}/* Delete static route from static route configuration. */intstatic_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, char *ifname, u_char distance, u_int32_t vrf_id){ struct route_node *rn; struct static_ipv6 *si; struct route_table *stable; /* Lookup table. */ stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; /* Lookup static route prefix. */ rn = route_node_lookup (stable, p); if (! rn) return 0; /* Find same static route is the tree */ for (si = rn->info; si; si = si->next) if (distance == si->distance && type == si->type && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6)) && (! ifname || strcmp (ifname, si->ifname) == 0)) break; /* Can't find static route. */ if (! si) { route_unlock_node (rn); return 0; } /* Install into rib. */ static_uninstall_ipv6 (p, si); /* Unlink static route from linked list. */ if (si->prev) si->prev->next = si->next; else rn->info = si->next; if (si->next) si->next->prev = si->prev; /* Free static route configuration. */ XFREE (MTYPE_STATIC_IPV6, si); return 1;}#endif /* HAVE_IPV6 *//* RIB update function. */voidrib_update (){ struct route_node *rn; struct route_table *table; table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) rib_process (rn, NULL); table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) rib_process (rn, NULL);}/* Interface goes up. */voidrib_if_up (struct interface *ifp){ rib_update ();}/* Interface goes down. */voidrib_if_down (struct interface *ifp){ rib_update ();}/* Remove all routes which comes from non main table. */voidrib_weed_table (struct route_table *table){ struct route_node *rn; struct rib *rib; struct rib *next; if (table) for (rn = route_top (table); rn; rn = route_next (rn)) for (rib = rn->info; rib; rib = next) { next = rib->next; if (rib->table != rtm_table_default && rib->table != RT_TABLE_MAIN) { rib_delnode (rn, rib); newrib_free (rib); route_unlock_node (rn); } }}/* Delete all routes from non main table. */voidrib_weed_tables (){ rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));}/* Delete self installed routes after zebra is relaunched. */voidrib_sweep_table (struct route_table *table){ struct route_node *rn; struct rib *rib; struct rib *next; int ret = 0; if (table) for (rn = route_top (table); rn; rn = route_next (rn)) for (rib = rn->info; rib; rib = next) { next = rib->next; if (rib->type == ZEBRA_ROUTE_KERNEL && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE)) { ret = rib_uninstall_kernel (rn, rib); if (! ret) { rib_delnode (rn, rib); newrib_free (rib); route_unlock_node (rn); } } }}/* Sweep all RIB tables. */voidrib_sweep_route (){ rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));}/* Close RIB and clean up kernel routes. */voidrib_close_table (struct route_table *table){ struct route_node *rn; struct rib *rib; if (table) for (rn = route_top (table); rn; rn = route_next (rn)) for (rib = rn->info; rib; rib = rib->next) if (! RIB_SYSTEM_ROUTE (rib) && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) rib_uninstall_kernel (rn, rib);}/* Close all RIB tables. */voidrib_close (){ rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));}/* Routing information base initialize. */voidrib_init (){ /* VRF initialization. */ vrf_init ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -