📄 zebra_rib.c
字号:
/* Routing Information Base. * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */#include <zebra.h>#include "prefix.h"#include "table.h"#include "memory.h"#include "str.h"#include "command.h"#include "if.h"#include "log.h"#include "sockunion.h"#include "zebra/rib.h"#include "zebra/rt.h"#include "zebra/zserv.h"#include "zebra/redistribute.h"#include "zebra/debug.h"/* Default rtm_table for all clients */extern int rtm_table_default;/* Each route type's string and default distance value. */struct{ int key; int distance;} route_info[] ={ {ZEBRA_ROUTE_SYSTEM, 0}, {ZEBRA_ROUTE_KERNEL, 0}, {ZEBRA_ROUTE_CONNECT, 0}, {ZEBRA_ROUTE_STATIC, 1}, {ZEBRA_ROUTE_RIP, 120}, {ZEBRA_ROUTE_RIPNG, 120}, {ZEBRA_ROUTE_OSPF, 110}, {ZEBRA_ROUTE_OSPF6, 110}, {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}};/* Vector for routing table. */vector vrf_vector;/* Allocate new VRF. */struct vrf *vrf_alloc (char *name){ struct vrf *vrf; vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); /* Put name. */ if (name) vrf->name = XSTRDUP (MTYPE_VRF_NAME, name); /* Allocate routing table and static table. */ vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init (); vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init (); vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init (); vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init (); return vrf;}/* Free VRF. */voidvrf_free (struct vrf *vrf){ if (vrf->name) XFREE (MTYPE_VRF_NAME, vrf->name); XFREE (MTYPE_VRF, vrf);}/* Lookup VRF by identifier. */struct vrf *vrf_lookup (u_int32_t id){ return vector_lookup (vrf_vector, id);}/* Lookup VRF by name. */struct vrf *vrf_lookup_by_name (char *name){ int i; struct vrf *vrf; for (i = 0; i < vector_max (vrf_vector); i++) if ((vrf = vector_slot (vrf_vector, i)) != NULL) if (vrf->name && name && strcmp (vrf->name, name) == 0) return vrf; return NULL;}/* Initialize VRF. */voidvrf_init (){ struct vrf *default_table; /* Allocate VRF vector. */ vrf_vector = vector_init (1); /* Allocate default main table. */ default_table = vrf_alloc ("Default-IP-Routing-Table"); /* Default table index must be 0. */ vector_set_index (vrf_vector, 0, default_table);}/* Lookup route table. */struct route_table *vrf_table (afi_t afi, safi_t safi, u_int32_t id){ struct vrf *vrf; vrf = vrf_lookup (id); if (! vrf) return NULL; return vrf->table[afi][safi];}/* Lookup static route table. */struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t id){ struct vrf *vrf; vrf = vrf_lookup (id); if (! vrf) return NULL; return vrf->stable[afi][safi];}/* Add nexthop to the end of the list. */voidnexthop_add (struct rib *rib, struct nexthop *nexthop){ struct nexthop *last; for (last = rib->nexthop; last && last->next; last = last->next) ; if (last) last->next = nexthop; else rib->nexthop = nexthop; nexthop->prev = last; rib->nexthop_num++;}/* Delete specified nexthop from the list. */voidnexthop_delete (struct rib *rib, struct nexthop *nexthop){ if (nexthop->next) nexthop->next->prev = nexthop->prev; if (nexthop->prev) nexthop->prev->next = nexthop->next; else rib->nexthop = nexthop->next; rib->nexthop_num--;}/* Free nexthop. */voidnexthop_free (struct nexthop *nexthop){ if (nexthop->type == NEXTHOP_TYPE_IFNAME && nexthop->ifname) free (nexthop->ifname); XFREE (MTYPE_NEXTHOP, nexthop);}struct nexthop *nexthop_ifindex_add (struct rib *rib, unsigned int ifindex){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IFINDEX; nexthop->ifindex = ifindex; nexthop_add (rib, nexthop); return nexthop;}struct nexthop *nexthop_ifname_add (struct rib *rib, char *ifname){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IFNAME; nexthop->ifname = strdup (ifname); nexthop_add (rib, nexthop); return nexthop;}struct nexthop *nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV4; nexthop->gate.ipv4 = *ipv4; nexthop_add (rib, nexthop); return nexthop;}struct nexthop *nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, unsigned int ifindex){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; nexthop->gate.ipv4 = *ipv4; nexthop->ifindex = ifindex; nexthop_add (rib, nexthop); return nexthop;}#ifdef HAVE_IPV6struct nexthop *nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV6; nexthop->gate.ipv6 = *ipv6; nexthop_add (rib, nexthop); return nexthop;}struct nexthop *nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6, char *ifname){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME; nexthop->gate.ipv6 = *ipv6; nexthop->ifname = XSTRDUP (0, ifname); nexthop_add (rib, nexthop); return nexthop;}struct nexthop *nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6, unsigned int ifindex){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; nexthop->gate.ipv6 = *ipv6; nexthop->ifindex = ifindex; nexthop_add (rib, nexthop); return nexthop;}#endif /* HAVE_IPV6 */struct nexthop *nexthop_blackhole_add (struct rib *rib){ struct nexthop *nexthop; nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); memset (nexthop, 0, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_BLACKHOLE; SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE); nexthop_add (rib, nexthop); return nexthop;}/* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */intnexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, struct route_node *top){ struct prefix_ipv4 p; struct route_table *table; struct route_node *rn; struct rib *match; struct nexthop *newhop; if (nexthop->type == NEXTHOP_TYPE_IPV4) nexthop->ifindex = 0; if (set) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); /* Make lookup prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefix = nexthop->gate.ipv4; /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return 0; rn = route_node_match (table, (struct prefix *) &p); while (rn) { route_unlock_node (rn); /* If lookup self prefix return immidiately. */ if (rn == top) return 0; /* 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. */ newhop = match->nexthop; if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4) nexthop->ifindex = newhop->ifindex; return 1; } else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) { if (set) { SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); nexthop->rtype = newhop->type; if (newhop->type == NEXTHOP_TYPE_IPV4 || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) nexthop->rgate.ipv4 = newhop->gate.ipv4; if (newhop->type == NEXTHOP_TYPE_IFINDEX || newhop->type == NEXTHOP_TYPE_IFNAME || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) nexthop->rifindex = newhop->ifindex; } return 1; } return 0; } else { return 0; } } } return 0;}#ifdef HAVE_IPV6/* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */intnexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, struct route_node *top){ struct prefix_ipv6 p; struct route_table *table; struct route_node *rn; struct rib *match; struct nexthop *newhop; if (nexthop->type == NEXTHOP_TYPE_IPV6) nexthop->ifindex = 0; if (set) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); /* Make lookup prefix. */ memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = IPV6_MAX_PREFIXLEN; p.prefix = nexthop->gate.ipv6; /* Lookup table. */ table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); if (! table) return 0; rn = route_node_match (table, (struct prefix *) &p); while (rn) { route_unlock_node (rn); /* If lookup self prefix return immidiately. */ if (rn == top) return 0; /* 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. */ newhop = match->nexthop; if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6) nexthop->ifindex = newhop->ifindex; return 1; } else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) { if (set) { SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); nexthop->rtype = newhop->type; if (newhop->type == NEXTHOP_TYPE_IPV6 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME) nexthop->rgate.ipv6 = newhop->gate.ipv6; if (newhop->type == NEXTHOP_TYPE_IFINDEX || newhop->type == NEXTHOP_TYPE_IFNAME || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME) nexthop->rifindex = newhop->ifindex; } return 1; } return 0; } else { return 0; } } } return 0;}#endif /* HAVE_IPV6 */struct rib *rib_match_ipv4 (struct in_addr addr){ struct prefix_ipv4 p; struct route_table *table; struct route_node *rn; struct rib *match; struct nexthop *newhop; /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return 0; memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -