📄 zebra_rib.c
字号:
/* Process this route node. */ rib_process (rn, same); /* Free implicit route.*/ if (same) newrib_free (same); return 0;}intrib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct in_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]; /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return 0; /* Apply mask. */ apply_mask_ipv4 (p); /* 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_INET, &p->prefix, buf1, BUFSIZ), p->prefixlen, inet_ntop (AF_INET, gate, buf2, BUFSIZ), ifindex); else zlog_info ("route %s/%d ifindex %d doesn't exist in rib", inet_ntop (AF_INET, &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_INET, &p->prefix, buf1, BUFSIZ), p->prefixlen, inet_ntop (AF_INET, gate, buf2, BUFSIZ), ifindex, type); else zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib", inet_ntop (AF_INET, &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_ipv4 (struct prefix *p, struct static_ipv4 *si){ struct rib *rib; struct route_node *rn; struct route_table *table; /* Lookup table. */ table = vrf_table (AFI_IP, 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_IPV4_GATEWAY: nexthop_ipv4_add (rib, &si->gate.ipv4); break; case STATIC_IPV4_IFNAME: nexthop_ifname_add (rib, si->gate.ifname); break; case STATIC_IPV4_BLACKHOLE: nexthop_blackhole_add (rib); 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_IPV4_GATEWAY: nexthop_ipv4_add (rib, &si->gate.ipv4); break; case STATIC_IPV4_IFNAME: nexthop_ifname_add (rib, si->gate.ifname); break; case STATIC_IPV4_BLACKHOLE: nexthop_blackhole_add (rib); break; } /* Link this rib to the tree. */ rib_addnode (rn, rib); /* Process this prefix. */ rib_process (rn, NULL); }}intstatic_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si){ if (nexthop->type == NEXTHOP_TYPE_IPV4 && si->type == STATIC_IPV4_GATEWAY && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4)) return 1; if (nexthop->type == NEXTHOP_TYPE_IFNAME && si->type == STATIC_IPV4_IFNAME && strcmp (nexthop->ifname, si->gate.ifname) == 0) return 1; if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE && si->type == STATIC_IPV4_BLACKHOLE) return 1; return 0;;}/* Uninstall static route from RIB. */voidstatic_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si){ struct route_node *rn; struct rib *rib; struct nexthop *nexthop; struct route_table *table; /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return; /* Lookup existing route with type and distance. */ rn = route_node_lookup (table, 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_ipv4_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_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname, u_char distance, u_int32_t vrf_id){ u_char type = 0; struct route_node *rn; struct static_ipv4 *si; struct static_ipv4 *pp; struct static_ipv4 *cp; struct static_ipv4 *update = NULL; struct route_table *stable; /* Lookup table. */ stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; /* Lookup static route prefix. */ rn = route_node_get (stable, p); /* Make flags. */ if (gate) type = STATIC_IPV4_GATEWAY; else if (ifname) type = STATIC_IPV4_IFNAME; else type = STATIC_IPV4_BLACKHOLE; /* Do nothing if there is a same static route. */ for (si = rn->info; si; si = si->next) { if (type == si->type && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4)) && (! ifname || strcmp (ifname, si->gate.ifname) == 0)) { if (distance == si->distance) { route_unlock_node (rn); return 0; } else update = si; } } /* Distance chaged. */ if (update) static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id); /* Make new static route structure. */ si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4)); memset (si, 0, sizeof (struct static_ipv4)); si->type = type; si->distance = distance; if (gate) si->gate.ipv4 = *gate; if (ifname) si->gate.ifname = XSTRDUP (0, ifname); /* 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; if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) { if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr)) break; if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr)) 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_ipv4 (p, si); return 1;}/* Delete static route from static route configuration. */intstatic_delete_ipv4 (struct prefix *p, struct in_addr *gate, char *ifname, u_char distance, u_int32_t vrf_id){ u_char type = 0; struct route_node *rn; struct static_ipv4 *si; struct route_table *stable; /* Lookup table. */ stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; /* Lookup static route prefix. */ rn = route_node_lookup (stable, p); if (! rn) return 0; /* Make flags. */ if (gate) type = STATIC_IPV4_GATEWAY; else if (ifname) type = STATIC_IPV4_IFNAME; else type = STATIC_IPV4_BLACKHOLE; /* Find same static route is the tree */ for (si = rn->info; si; si = si->next) if (type == si->type && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4)) && (! ifname || strcmp (ifname, si->gate.ifname) == 0)) break; /* Can't find static route. */ if (! si) { route_unlock_node (rn); return 0; } /* Install into rib. */ static_uninstall_ipv4 (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_IPV4, si); return 1;}#ifdef HAVE_IPV6intrib_bogus_ipv6 (int type, struct prefix_ipv6 *p, struct in6_addr *gate, unsigned int ifindex, int table){ if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) return 1; if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate)) { kernel_delete_ipv6_old (p, gate, ifindex, 0, table); return 1; } return 0;}intrib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p, struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id){ struct rib *rib; struct rib *same = NULL; struct route_table *table; struct route_node *rn; struct nexthop *nexthop; int distance; u_int32_t metric = 0; /* Lookup table. */ table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); if (! table) return 0; /* Make sure mask is applied. */ apply_mask_ipv6 (p); /* Set default distance by route type. */ distance = route_info[type].distance; if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) distance = 200; /* Filter bogus route. */ if (rib_bogus_ipv6 (type, p, gate, ifindex, 0)) return 0; /* 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; 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_ipv6_ifindex_add (rib, gate, ifindex); else nexthop_ipv6_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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -