mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 05:58:17 +00:00
zebra: Create zebra_static.[ch] to isolate code
Isolate the zebra static_XXX functions from zebra_rib.c This is the first in a series of changes to clean up the zebra code a bit more. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
a782e613dd
commit
28f6dde859
@ -31,19 +31,19 @@ zebra_SOURCES = \
|
|||||||
redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \
|
redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \
|
||||||
irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \
|
irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \
|
||||||
$(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
|
$(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
|
||||||
zebra_ns.c zebra_vrf.c
|
zebra_ns.c zebra_vrf.c zebra_static.c
|
||||||
|
|
||||||
testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \
|
testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \
|
||||||
zebra_vty.c zebra_ptm.c zebra_routemap.c zebra_ns.c zebra_vrf.c \
|
zebra_vty.c zebra_ptm.c zebra_routemap.c zebra_ns.c zebra_vrf.c \
|
||||||
kernel_null.c redistribute_null.c ioctl_null.c misc_null.c zebra_rnh_null.c \
|
kernel_null.c redistribute_null.c ioctl_null.c misc_null.c zebra_rnh_null.c \
|
||||||
zebra_ptm_null.c rtadv_null.c if_null.c zserv_null.c
|
zebra_ptm_null.c rtadv_null.c if_null.c zserv_null.c zebra_static.c
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
|
connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
|
||||||
interface.h ipforward.h irdp.h router-id.h kernel_socket.h \
|
interface.h ipforward.h irdp.h router-id.h kernel_socket.h \
|
||||||
rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \
|
rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \
|
||||||
zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \
|
zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \
|
||||||
zebra_ns.h zebra_vrf.h ioctl_solaris.h
|
zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h
|
||||||
|
|
||||||
zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP)
|
zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP)
|
||||||
|
|
||||||
|
75
zebra/rib.h
75
zebra/rib.h
@ -175,51 +175,6 @@ typedef struct rib_dest_t_
|
|||||||
#define RNODE_FOREACH_RIB_SAFE(rn, rib, next) \
|
#define RNODE_FOREACH_RIB_SAFE(rn, rib, next) \
|
||||||
RIB_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), rib, next)
|
RIB_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), rib, next)
|
||||||
|
|
||||||
/* Static route information. */
|
|
||||||
struct static_route
|
|
||||||
{
|
|
||||||
/* For linked list. */
|
|
||||||
struct static_route *prev;
|
|
||||||
struct static_route *next;
|
|
||||||
|
|
||||||
/* VRF identifier. */
|
|
||||||
vrf_id_t vrf_id;
|
|
||||||
|
|
||||||
/* Administrative distance. */
|
|
||||||
u_char distance;
|
|
||||||
|
|
||||||
/* Tag */
|
|
||||||
u_short tag;
|
|
||||||
|
|
||||||
/* Flag for this static route's type. */
|
|
||||||
u_char type;
|
|
||||||
#define STATIC_IFINDEX 1
|
|
||||||
#define STATIC_IPV4_GATEWAY 2
|
|
||||||
#define STATIC_IPV4_BLACKHOLE 3
|
|
||||||
#define STATIC_IPV6_GATEWAY 4
|
|
||||||
#define STATIC_IPV6_GATEWAY_IFINDEX 5
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Nexthop value.
|
|
||||||
*
|
|
||||||
* Under IPv4 addr and ifindex are
|
|
||||||
* used independentyly.
|
|
||||||
* STATIC_IPV4_GATEWAY uses addr
|
|
||||||
* STATIC_IFINDEX uses ifindex
|
|
||||||
*/
|
|
||||||
union g_addr addr;
|
|
||||||
ifindex_t ifindex;
|
|
||||||
|
|
||||||
char ifname[INTERFACE_NAMSIZ + 1];
|
|
||||||
|
|
||||||
/* bit flags */
|
|
||||||
u_char flags;
|
|
||||||
/*
|
|
||||||
see ZEBRA_FLAG_REJECT
|
|
||||||
ZEBRA_FLAG_BLACKHOLE
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The following for loop allows to iterate over the nexthop
|
/* The following for loop allows to iterate over the nexthop
|
||||||
* structure of routes.
|
* structure of routes.
|
||||||
*
|
*
|
||||||
@ -365,6 +320,7 @@ extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *,
|
|||||||
#define ZEBRA_RIB_FOUND_CONNECTED 2
|
#define ZEBRA_RIB_FOUND_CONNECTED 2
|
||||||
#define ZEBRA_RIB_NOTFOUND 3
|
#define ZEBRA_RIB_NOTFOUND 3
|
||||||
|
|
||||||
|
extern void rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop);
|
||||||
extern struct nexthop *rib_nexthop_ipv6_add (struct rib *, struct in6_addr *);
|
extern struct nexthop *rib_nexthop_ipv6_add (struct rib *, struct in6_addr *);
|
||||||
extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib,
|
extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib,
|
||||||
struct in6_addr *ipv6,
|
struct in6_addr *ipv6,
|
||||||
@ -374,6 +330,11 @@ extern int is_zebra_valid_kernel_table(u_int32_t table_id);
|
|||||||
extern int is_zebra_main_routing_table(u_int32_t table_id);
|
extern int is_zebra_main_routing_table(u_int32_t table_id);
|
||||||
extern int zebra_check_addr (struct prefix *p);
|
extern int zebra_check_addr (struct prefix *p);
|
||||||
|
|
||||||
|
extern void rib_addnode (struct route_node *rn, struct rib *rib, int process);
|
||||||
|
extern void rib_delnode (struct route_node *rn, struct rib *rib);
|
||||||
|
extern int rib_install_kernel (struct route_node *rn, struct rib *rib, int update);
|
||||||
|
extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib);
|
||||||
|
|
||||||
/* NOTE:
|
/* NOTE:
|
||||||
* All rib_add_ipv[46]* functions will not just add prefix into RIB, but
|
* All rib_add_ipv[46]* functions will not just add prefix into RIB, but
|
||||||
* also implicitly withdraw equal prefix of same type. */
|
* also implicitly withdraw equal prefix of same type. */
|
||||||
@ -404,20 +365,6 @@ extern void rib_init (void);
|
|||||||
extern unsigned long rib_score_proto (u_char proto, u_short instance);
|
extern unsigned long rib_score_proto (u_char proto, u_short instance);
|
||||||
extern void rib_queue_add (struct route_node *rn);
|
extern void rib_queue_add (struct route_node *rn);
|
||||||
|
|
||||||
extern void
|
|
||||||
static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
|
|
||||||
extern void
|
|
||||||
static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
|
|
||||||
|
|
||||||
extern int
|
|
||||||
static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
|
||||||
const char *ifname, u_char flags, u_short tag,
|
|
||||||
u_char distance, struct zebra_vrf *zvrf);
|
|
||||||
|
|
||||||
extern int
|
|
||||||
static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
|
||||||
u_short tag, u_char distance, struct zebra_vrf *zvrf);
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
|
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
|
||||||
struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id,
|
struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id,
|
||||||
@ -435,20 +382,10 @@ extern struct rib *rib_match_ipv6 (struct in6_addr *, vrf_id_t);
|
|||||||
|
|
||||||
extern struct route_table *rib_table_ipv6;
|
extern struct route_table *rib_table_ipv6;
|
||||||
|
|
||||||
extern int
|
|
||||||
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
|
||||||
ifindex_t ifindex, const char *ifname, u_char flags,
|
|
||||||
u_short tag, u_char distance, struct zebra_vrf *zvrf);
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t,
|
rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t,
|
||||||
ifindex_t);
|
ifindex_t);
|
||||||
|
|
||||||
extern int
|
|
||||||
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
|
||||||
ifindex_t ifindex, u_short tag, u_char distance,
|
|
||||||
struct zebra_vrf *zvrf);
|
|
||||||
|
|
||||||
extern int rib_gc_dest (struct route_node *rn);
|
extern int rib_gc_dest (struct route_node *rn);
|
||||||
extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter);
|
extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter);
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ rib_copy_nexthops (struct rib *rib, struct nexthop *nh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Delete specified nexthop from the list. */
|
/* Delete specified nexthop from the list. */
|
||||||
static void
|
void
|
||||||
rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop)
|
rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop)
|
||||||
{
|
{
|
||||||
if (nexthop->next)
|
if (nexthop->next)
|
||||||
@ -1248,7 +1248,7 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
|
|||||||
/* Update flag indicates whether this is a "replace" or not. Currently, this
|
/* Update flag indicates whether this is a "replace" or not. Currently, this
|
||||||
* is only used for IPv4.
|
* is only used for IPv4.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
|
rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1303,7 +1303,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Uninstall the route from kernel. */
|
/* Uninstall the route from kernel. */
|
||||||
static int
|
int
|
||||||
rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
|
rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1555,7 +1555,6 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn,
|
|||||||
for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
|
for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
|
||||||
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update for redistribution. */
|
/* Update for redistribution. */
|
||||||
@ -2324,7 +2323,7 @@ rib_link (struct route_node *rn, struct rib *rib, int process)
|
|||||||
rib_queue_add (rn);
|
rib_queue_add (rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
rib_addnode (struct route_node *rn, struct rib *rib, int process)
|
rib_addnode (struct route_node *rn, struct rib *rib, int process)
|
||||||
{
|
{
|
||||||
/* RIB node has been un-removed before route-node is processed.
|
/* RIB node has been un-removed before route-node is processed.
|
||||||
@ -2379,7 +2378,7 @@ rib_unlink (struct route_node *rn, struct rib *rib)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
rib_delnode (struct route_node *rn, struct rib *rib)
|
rib_delnode (struct route_node *rn, struct rib *rib)
|
||||||
{
|
{
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
@ -2910,440 +2909,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Install static route into rib. */
|
|
||||||
void
|
|
||||||
static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
|
|
||||||
{
|
|
||||||
struct rib *rib;
|
|
||||||
struct route_node *rn;
|
|
||||||
struct route_table *table;
|
|
||||||
struct prefix nh_p;
|
|
||||||
|
|
||||||
/* Lookup table. */
|
|
||||||
table = zebra_vrf_table (afi, safi, si->vrf_id);
|
|
||||||
if (! table)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Lookup existing route */
|
|
||||||
rn = route_node_get (table, p);
|
|
||||||
RNODE_FOREACH_RIB (rn, rib)
|
|
||||||
{
|
|
||||||
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rib)
|
|
||||||
{
|
|
||||||
/* if tag value changed , update old value in RIB */
|
|
||||||
if (rib->tag != si->tag)
|
|
||||||
rib->tag = si->tag;
|
|
||||||
|
|
||||||
/* Same distance static route is there. Update it with new
|
|
||||||
nexthop. */
|
|
||||||
route_unlock_node (rn);
|
|
||||||
switch (si->type)
|
|
||||||
{
|
|
||||||
case STATIC_IPV4_GATEWAY:
|
|
||||||
rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
|
||||||
nh_p.family = AF_INET;
|
|
||||||
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
|
||||||
nh_p.u.prefix4 = si->addr.ipv4;
|
|
||||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
|
||||||
break;
|
|
||||||
case STATIC_IFINDEX:
|
|
||||||
rib_nexthop_ifindex_add (rib, si->ifindex);
|
|
||||||
break;
|
|
||||||
case STATIC_IPV4_BLACKHOLE:
|
|
||||||
rib_nexthop_blackhole_add (rib);
|
|
||||||
break;
|
|
||||||
case STATIC_IPV6_GATEWAY:
|
|
||||||
rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
|
||||||
nh_p.family = AF_INET6;
|
|
||||||
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
|
||||||
nh_p.u.prefix6 = si->addr.ipv6;
|
|
||||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
|
||||||
break;
|
|
||||||
case STATIC_IPV6_GATEWAY_IFINDEX:
|
|
||||||
rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
|
||||||
{
|
|
||||||
char buf[INET6_ADDRSTRLEN];
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
|
||||||
{
|
|
||||||
inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
|
|
||||||
zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
|
|
||||||
si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Schedule route for processing or invoke NHT, as appropriate. */
|
|
||||||
if (si->type == STATIC_IPV4_GATEWAY ||
|
|
||||||
si->type == STATIC_IPV6_GATEWAY)
|
|
||||||
zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p);
|
|
||||||
else
|
|
||||||
rib_queue_add (rn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is new static route. */
|
|
||||||
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
|
|
||||||
|
|
||||||
rib->type = ZEBRA_ROUTE_STATIC;
|
|
||||||
rib->instance = 0;
|
|
||||||
rib->distance = si->distance;
|
|
||||||
rib->metric = 0;
|
|
||||||
rib->mtu = 0;
|
|
||||||
rib->vrf_id = si->vrf_id;
|
|
||||||
rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default;
|
|
||||||
rib->nexthop_num = 0;
|
|
||||||
rib->tag = si->tag;
|
|
||||||
|
|
||||||
switch (si->type)
|
|
||||||
{
|
|
||||||
case STATIC_IPV4_GATEWAY:
|
|
||||||
rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
|
||||||
nh_p.family = AF_INET;
|
|
||||||
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
|
||||||
nh_p.u.prefix4 = si->addr.ipv4;
|
|
||||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
|
||||||
break;
|
|
||||||
case STATIC_IFINDEX:
|
|
||||||
rib_nexthop_ifindex_add (rib, si->ifindex);
|
|
||||||
break;
|
|
||||||
case STATIC_IPV4_BLACKHOLE:
|
|
||||||
rib_nexthop_blackhole_add (rib);
|
|
||||||
break;
|
|
||||||
case STATIC_IPV6_GATEWAY:
|
|
||||||
rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
|
||||||
nh_p.family = AF_INET6;
|
|
||||||
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
|
||||||
nh_p.u.prefix6 = si->addr.ipv6;
|
|
||||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
|
||||||
break;
|
|
||||||
case STATIC_IPV6_GATEWAY_IFINDEX:
|
|
||||||
rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the flags of this static routes (reject, blackhole) */
|
|
||||||
rib->flags = si->flags;
|
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
|
||||||
{
|
|
||||||
char buf[INET6_ADDRSTRLEN];
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
|
||||||
{
|
|
||||||
inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
|
|
||||||
zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)",
|
|
||||||
si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Link this rib to the tree. Schedule for processing or invoke NHT,
|
|
||||||
* as appropriate.
|
|
||||||
*/
|
|
||||||
if (si->type == STATIC_IPV4_GATEWAY ||
|
|
||||||
si->type == STATIC_IPV6_GATEWAY)
|
|
||||||
{
|
|
||||||
rib_addnode (rn, rib, 0);
|
|
||||||
zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rib_addnode (rn, rib, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
|
|
||||||
{
|
|
||||||
if (nexthop->type == NEXTHOP_TYPE_IPV4
|
|
||||||
&& si->type == STATIC_IPV4_GATEWAY
|
|
||||||
&& IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
|
|
||||||
return 1;
|
|
||||||
if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|
|
||||||
&& si->type == STATIC_IFINDEX
|
|
||||||
&& nexthop->ifindex == si->ifindex)
|
|
||||||
return 1;
|
|
||||||
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
|
|
||||||
&& si->type == STATIC_IPV4_BLACKHOLE)
|
|
||||||
return 1;
|
|
||||||
if (nexthop->type == NEXTHOP_TYPE_IPV6
|
|
||||||
&& si->type == STATIC_IPV6_GATEWAY
|
|
||||||
&& IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
|
|
||||||
return 1;
|
|
||||||
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
|
|
||||||
&& si->type == STATIC_IPV6_GATEWAY_IFINDEX
|
|
||||||
&& IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
|
|
||||||
&& nexthop->ifindex == si->ifindex)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Uninstall static route from RIB. */
|
|
||||||
void
|
|
||||||
static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
|
|
||||||
{
|
|
||||||
struct route_node *rn;
|
|
||||||
struct rib *rib;
|
|
||||||
struct nexthop *nexthop;
|
|
||||||
struct route_table *table;
|
|
||||||
struct prefix nh_p;
|
|
||||||
|
|
||||||
/* Lookup table. */
|
|
||||||
table = zebra_vrf_table (afi, safi, si->vrf_id);
|
|
||||||
if (! table)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Lookup existing route with type and distance. */
|
|
||||||
rn = route_node_lookup (table, p);
|
|
||||||
if (! rn)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RNODE_FOREACH_RIB (rn, rib)
|
|
||||||
{
|
|
||||||
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance &&
|
|
||||||
rib->tag == si->tag)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! rib)
|
|
||||||
{
|
|
||||||
route_unlock_node (rn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lookup nexthop. */
|
|
||||||
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
|
|
||||||
if (static_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);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Mark this nexthop as inactive and reinstall the route. Then, delete
|
|
||||||
* the nexthop. There is no need to re-evaluate the route for this
|
|
||||||
* scenario.
|
|
||||||
*/
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
|
||||||
{
|
|
||||||
char buf[INET6_ADDRSTRLEN];
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
|
||||||
{
|
|
||||||
inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
|
|
||||||
zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
|
|
||||||
si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
|
||||||
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
|
|
||||||
{
|
|
||||||
/* If there are other active nexthops, do an update. */
|
|
||||||
if (rib->nexthop_active_num > 1)
|
|
||||||
{
|
|
||||||
rib_install_kernel (rn, rib, 1);
|
|
||||||
redistribute_update (&rn->p, rib, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
redistribute_delete (&rn->p, rib);
|
|
||||||
rib_uninstall_kernel (rn, rib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (afi == AFI_IP)
|
|
||||||
{
|
|
||||||
/* Delete the nexthop and dereg from NHT */
|
|
||||||
nh_p.family = AF_INET;
|
|
||||||
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
|
||||||
nh_p.u.prefix4 = nexthop->gate.ipv4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nh_p.family = AF_INET6;
|
|
||||||
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
|
||||||
nh_p.u.prefix6 = nexthop->gate.ipv6;
|
|
||||||
}
|
|
||||||
rib_nexthop_delete (rib, nexthop);
|
|
||||||
zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
|
||||||
nexthop_free (nexthop);
|
|
||||||
}
|
|
||||||
/* Unlock node. */
|
|
||||||
route_unlock_node (rn);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
|
||||||
const char *ifname, u_char flags, u_short tag,
|
|
||||||
u_char distance, struct zebra_vrf *zvrf)
|
|
||||||
{
|
|
||||||
u_char type = 0;
|
|
||||||
struct route_node *rn;
|
|
||||||
struct static_route *si;
|
|
||||||
struct static_route *pp;
|
|
||||||
struct static_route *cp;
|
|
||||||
struct static_route *update = NULL;
|
|
||||||
struct route_table *stable = zvrf->stable[AFI_IP][safi];
|
|
||||||
|
|
||||||
if (! stable)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Lookup static route prefix. */
|
|
||||||
rn = route_node_get (stable, p);
|
|
||||||
|
|
||||||
/* Make flags. */
|
|
||||||
if (gate)
|
|
||||||
type = STATIC_IPV4_GATEWAY;
|
|
||||||
else if (ifindex)
|
|
||||||
type = STATIC_IFINDEX;
|
|
||||||
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->addr.ipv4))
|
|
||||||
&& (! ifindex || ifindex == si->ifindex))
|
|
||||||
{
|
|
||||||
if ((distance == si->distance) && (tag == si->tag))
|
|
||||||
{
|
|
||||||
route_unlock_node (rn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
update = si;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Distance or tag changed. */
|
|
||||||
if (update)
|
|
||||||
static_delete_ipv4 (safi, p, gate, ifindex, update->tag, update->distance, zvrf);
|
|
||||||
|
|
||||||
/* Make new static route structure. */
|
|
||||||
si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
|
|
||||||
|
|
||||||
si->type = type;
|
|
||||||
si->distance = distance;
|
|
||||||
si->flags = flags;
|
|
||||||
si->tag = tag;
|
|
||||||
si->vrf_id = zvrf->vrf_id;
|
|
||||||
si->ifindex = ifindex;
|
|
||||||
if (si->ifindex)
|
|
||||||
strcpy(si->ifname, ifname);
|
|
||||||
|
|
||||||
if (gate)
|
|
||||||
si->addr.ipv4 = *gate;
|
|
||||||
|
|
||||||
/* 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->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
|
|
||||||
break;
|
|
||||||
if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.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_route (AFI_IP, safi, p, si);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
|
||||||
u_short tag, u_char distance, struct zebra_vrf *zvrf)
|
|
||||||
{
|
|
||||||
u_char type = 0;
|
|
||||||
struct route_node *rn;
|
|
||||||
struct static_route *si;
|
|
||||||
struct route_table *stable;
|
|
||||||
|
|
||||||
/* Lookup table. */
|
|
||||||
stable = zebra_vrf_static_table (AFI_IP, safi, zvrf);
|
|
||||||
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 (ifindex)
|
|
||||||
type = STATIC_IFINDEX;
|
|
||||||
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->addr.ipv4))
|
|
||||||
&& (! ifindex || ifindex == si->ifindex)
|
|
||||||
&& (! tag || (tag == si->tag)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Can't find static route. */
|
|
||||||
if (! si)
|
|
||||||
{
|
|
||||||
route_unlock_node (rn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Install into rib. */
|
|
||||||
static_uninstall_route (AFI_IP, safi, 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;
|
|
||||||
route_unlock_node (rn);
|
|
||||||
|
|
||||||
/* Free static route configuration. */
|
|
||||||
XFREE (MTYPE_STATIC_ROUTE, si);
|
|
||||||
|
|
||||||
route_unlock_node (rn);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
|
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
|
||||||
@ -3707,155 +3273,6 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add static route into static route configuration. */
|
|
||||||
int
|
|
||||||
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
|
||||||
ifindex_t ifindex, const char *ifname, u_char flags,
|
|
||||||
u_short tag, u_char distance, struct zebra_vrf *zvrf)
|
|
||||||
{
|
|
||||||
struct route_node *rn;
|
|
||||||
struct static_route *si;
|
|
||||||
struct static_route *pp;
|
|
||||||
struct static_route *cp;
|
|
||||||
struct static_route *update = NULL;
|
|
||||||
struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
|
|
||||||
|
|
||||||
if (! stable)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!gate &&
|
|
||||||
(type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFINDEX))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!ifindex &&
|
|
||||||
(type == STATIC_IPV6_GATEWAY_IFINDEX || type == STATIC_IFINDEX))
|
|
||||||
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 (type == si->type
|
|
||||||
&& (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
|
|
||||||
&& (! ifindex || ifindex == si->ifindex))
|
|
||||||
{
|
|
||||||
if ((distance == si->distance) && (tag == si->tag))
|
|
||||||
{
|
|
||||||
route_unlock_node (rn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
update = si;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Distance or tag changed. */
|
|
||||||
if (update)
|
|
||||||
static_delete_ipv6 (p, type, gate, ifindex, update->tag, update->distance, zvrf);
|
|
||||||
|
|
||||||
/* Make new static route structure. */
|
|
||||||
si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
|
|
||||||
|
|
||||||
si->type = type;
|
|
||||||
si->distance = distance;
|
|
||||||
si->flags = flags;
|
|
||||||
si->tag = tag;
|
|
||||||
si->vrf_id = zvrf->vrf_id;
|
|
||||||
si->ifindex = ifindex;
|
|
||||||
if (si->ifindex)
|
|
||||||
strcpy (si->ifname, ifname);
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case STATIC_IPV6_GATEWAY:
|
|
||||||
si->addr.ipv6 = *gate;
|
|
||||||
break;
|
|
||||||
case STATIC_IPV6_GATEWAY_IFINDEX:
|
|
||||||
si->addr.ipv6 = *gate;
|
|
||||||
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_route (AFI_IP6, SAFI_UNICAST, p, si);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete static route from static route configuration. */
|
|
||||||
int
|
|
||||||
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
|
||||||
ifindex_t ifindex, u_short tag, u_char distance,
|
|
||||||
struct zebra_vrf *zvrf)
|
|
||||||
{
|
|
||||||
struct route_node *rn;
|
|
||||||
struct static_route *si;
|
|
||||||
struct route_table *stable;
|
|
||||||
|
|
||||||
/* Lookup table. */
|
|
||||||
stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, zvrf);
|
|
||||||
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->addr.ipv6))
|
|
||||||
&& (! ifindex || ifindex == si->ifindex)
|
|
||||||
&& (! tag || (tag == si->tag)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Can't find static route. */
|
|
||||||
if (! si)
|
|
||||||
{
|
|
||||||
route_unlock_node (rn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Install into rib. */
|
|
||||||
static_uninstall_route (AFI_IP6, SAFI_UNICAST, 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_ROUTE, si);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Schedule routes of a particular table (address-family) based on event. */
|
/* Schedule routes of a particular table (address-family) based on event. */
|
||||||
static void
|
static void
|
||||||
rib_update_table (struct route_table *table, rib_update_event_t event)
|
rib_update_table (struct route_table *table, rib_update_event_t event)
|
||||||
|
617
zebra/zebra_static.c
Normal file
617
zebra/zebra_static.c
Normal file
@ -0,0 +1,617 @@
|
|||||||
|
/*
|
||||||
|
* Static Routing Information code
|
||||||
|
* Copyright (C) 2016 Cumulus Networks
|
||||||
|
* Donald Sharp
|
||||||
|
*
|
||||||
|
* This file is part of Quagga.
|
||||||
|
*
|
||||||
|
* Quagga 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.
|
||||||
|
*
|
||||||
|
* Quagga 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 Quagga; 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 <lib/nexthop.h>
|
||||||
|
#include <lib/memory.h>
|
||||||
|
|
||||||
|
#include "zebra/debug.h"
|
||||||
|
#include "zebra/rib.h"
|
||||||
|
#include "zebra/zserv.h"
|
||||||
|
#include "zebra/zebra_vrf.h"
|
||||||
|
#include "zebra/zebra_static.h"
|
||||||
|
#include "zebra/zebra_rnh.h"
|
||||||
|
#include "zebra/redistribute.h"
|
||||||
|
|
||||||
|
/* Install static route into rib. */
|
||||||
|
void
|
||||||
|
static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
|
||||||
|
{
|
||||||
|
struct rib *rib;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct route_table *table;
|
||||||
|
struct prefix nh_p;
|
||||||
|
|
||||||
|
/* Lookup table. */
|
||||||
|
table = zebra_vrf_table (afi, safi, si->vrf_id);
|
||||||
|
if (! table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Lookup existing route */
|
||||||
|
rn = route_node_get (table, p);
|
||||||
|
RNODE_FOREACH_RIB (rn, rib)
|
||||||
|
{
|
||||||
|
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rib)
|
||||||
|
{
|
||||||
|
/* if tag value changed , update old value in RIB */
|
||||||
|
if (rib->tag != si->tag)
|
||||||
|
rib->tag = si->tag;
|
||||||
|
|
||||||
|
/* Same distance static route is there. Update it with new
|
||||||
|
nexthop. */
|
||||||
|
route_unlock_node (rn);
|
||||||
|
switch (si->type)
|
||||||
|
{
|
||||||
|
case STATIC_IPV4_GATEWAY:
|
||||||
|
rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
||||||
|
nh_p.family = AF_INET;
|
||||||
|
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
||||||
|
nh_p.u.prefix4 = si->addr.ipv4;
|
||||||
|
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||||
|
break;
|
||||||
|
case STATIC_IFINDEX:
|
||||||
|
rib_nexthop_ifindex_add (rib, si->ifindex);
|
||||||
|
break;
|
||||||
|
case STATIC_IPV4_BLACKHOLE:
|
||||||
|
rib_nexthop_blackhole_add (rib);
|
||||||
|
break;
|
||||||
|
case STATIC_IPV6_GATEWAY:
|
||||||
|
rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
||||||
|
nh_p.family = AF_INET6;
|
||||||
|
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
||||||
|
nh_p.u.prefix6 = si->addr.ipv6;
|
||||||
|
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||||
|
break;
|
||||||
|
case STATIC_IPV6_GATEWAY_IFINDEX:
|
||||||
|
rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
|
{
|
||||||
|
char buf[INET6_ADDRSTRLEN];
|
||||||
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
|
{
|
||||||
|
inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
|
||||||
|
zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
|
||||||
|
si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Schedule route for processing or invoke NHT, as appropriate. */
|
||||||
|
if (si->type == STATIC_IPV4_GATEWAY ||
|
||||||
|
si->type == STATIC_IPV6_GATEWAY)
|
||||||
|
zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p);
|
||||||
|
else
|
||||||
|
rib_queue_add (rn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is new static route. */
|
||||||
|
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
|
||||||
|
|
||||||
|
rib->type = ZEBRA_ROUTE_STATIC;
|
||||||
|
rib->instance = 0;
|
||||||
|
rib->distance = si->distance;
|
||||||
|
rib->metric = 0;
|
||||||
|
rib->mtu = 0;
|
||||||
|
rib->vrf_id = si->vrf_id;
|
||||||
|
rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default;
|
||||||
|
rib->nexthop_num = 0;
|
||||||
|
rib->tag = si->tag;
|
||||||
|
|
||||||
|
switch (si->type)
|
||||||
|
{
|
||||||
|
case STATIC_IPV4_GATEWAY:
|
||||||
|
rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
||||||
|
nh_p.family = AF_INET;
|
||||||
|
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
||||||
|
nh_p.u.prefix4 = si->addr.ipv4;
|
||||||
|
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||||
|
break;
|
||||||
|
case STATIC_IFINDEX:
|
||||||
|
rib_nexthop_ifindex_add (rib, si->ifindex);
|
||||||
|
break;
|
||||||
|
case STATIC_IPV4_BLACKHOLE:
|
||||||
|
rib_nexthop_blackhole_add (rib);
|
||||||
|
break;
|
||||||
|
case STATIC_IPV6_GATEWAY:
|
||||||
|
rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
||||||
|
nh_p.family = AF_INET6;
|
||||||
|
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
||||||
|
nh_p.u.prefix6 = si->addr.ipv6;
|
||||||
|
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||||
|
break;
|
||||||
|
case STATIC_IPV6_GATEWAY_IFINDEX:
|
||||||
|
rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the flags of this static routes (reject, blackhole) */
|
||||||
|
rib->flags = si->flags;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
|
{
|
||||||
|
char buf[INET6_ADDRSTRLEN];
|
||||||
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
|
{
|
||||||
|
inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
|
||||||
|
zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)",
|
||||||
|
si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Link this rib to the tree. Schedule for processing or invoke NHT,
|
||||||
|
* as appropriate.
|
||||||
|
*/
|
||||||
|
if (si->type == STATIC_IPV4_GATEWAY ||
|
||||||
|
si->type == STATIC_IPV6_GATEWAY)
|
||||||
|
{
|
||||||
|
rib_addnode (rn, rib, 0);
|
||||||
|
zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rib_addnode (rn, rib, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int
|
||||||
|
static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
|
||||||
|
{
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_IPV4
|
||||||
|
&& si->type == STATIC_IPV4_GATEWAY
|
||||||
|
&& IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
|
||||||
|
return 1;
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|
||||||
|
&& si->type == STATIC_IFINDEX
|
||||||
|
&& nexthop->ifindex == si->ifindex)
|
||||||
|
return 1;
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
|
||||||
|
&& si->type == STATIC_IPV4_BLACKHOLE)
|
||||||
|
return 1;
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_IPV6
|
||||||
|
&& si->type == STATIC_IPV6_GATEWAY
|
||||||
|
&& IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
|
||||||
|
return 1;
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
|
||||||
|
&& si->type == STATIC_IPV6_GATEWAY_IFINDEX
|
||||||
|
&& IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
|
||||||
|
&& nexthop->ifindex == si->ifindex)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Uninstall static route from RIB. */
|
||||||
|
void
|
||||||
|
static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
struct rib *rib;
|
||||||
|
struct nexthop *nexthop;
|
||||||
|
struct route_table *table;
|
||||||
|
struct prefix nh_p;
|
||||||
|
|
||||||
|
/* Lookup table. */
|
||||||
|
table = zebra_vrf_table (afi, safi, si->vrf_id);
|
||||||
|
if (! table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Lookup existing route with type and distance. */
|
||||||
|
rn = route_node_lookup (table, p);
|
||||||
|
if (! rn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RNODE_FOREACH_RIB (rn, rib)
|
||||||
|
{
|
||||||
|
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance &&
|
||||||
|
rib->tag == si->tag)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! rib)
|
||||||
|
{
|
||||||
|
route_unlock_node (rn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lookup nexthop. */
|
||||||
|
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
|
||||||
|
if (static_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);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Mark this nexthop as inactive and reinstall the route. Then, delete
|
||||||
|
* the nexthop. There is no need to re-evaluate the route for this
|
||||||
|
* scenario.
|
||||||
|
*/
|
||||||
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
|
{
|
||||||
|
char buf[INET6_ADDRSTRLEN];
|
||||||
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
|
{
|
||||||
|
inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
|
||||||
|
zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
|
||||||
|
si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||||
|
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
|
||||||
|
{
|
||||||
|
/* If there are other active nexthops, do an update. */
|
||||||
|
if (rib->nexthop_active_num > 1)
|
||||||
|
{
|
||||||
|
rib_install_kernel (rn, rib, 1);
|
||||||
|
redistribute_update (&rn->p, rib, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
redistribute_delete (&rn->p, rib);
|
||||||
|
rib_uninstall_kernel (rn, rib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (afi == AFI_IP)
|
||||||
|
{
|
||||||
|
/* Delete the nexthop and dereg from NHT */
|
||||||
|
nh_p.family = AF_INET;
|
||||||
|
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
||||||
|
nh_p.u.prefix4 = nexthop->gate.ipv4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nh_p.family = AF_INET6;
|
||||||
|
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
||||||
|
nh_p.u.prefix6 = nexthop->gate.ipv6;
|
||||||
|
}
|
||||||
|
rib_nexthop_delete (rib, nexthop);
|
||||||
|
zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||||
|
nexthop_free (nexthop);
|
||||||
|
}
|
||||||
|
/* Unlock node. */
|
||||||
|
route_unlock_node (rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
||||||
|
const char *ifname, u_char flags, u_short tag,
|
||||||
|
u_char distance, struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
u_char type = 0;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct static_route *si;
|
||||||
|
struct static_route *pp;
|
||||||
|
struct static_route *cp;
|
||||||
|
struct static_route *update = NULL;
|
||||||
|
struct route_table *stable = zvrf->stable[AFI_IP][safi];
|
||||||
|
|
||||||
|
if (! stable)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Lookup static route prefix. */
|
||||||
|
rn = route_node_get (stable, p);
|
||||||
|
|
||||||
|
/* Make flags. */
|
||||||
|
if (gate)
|
||||||
|
type = STATIC_IPV4_GATEWAY;
|
||||||
|
else if (ifindex)
|
||||||
|
type = STATIC_IFINDEX;
|
||||||
|
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->addr.ipv4))
|
||||||
|
&& (! ifindex || ifindex == si->ifindex))
|
||||||
|
{
|
||||||
|
if ((distance == si->distance) && (tag == si->tag))
|
||||||
|
{
|
||||||
|
route_unlock_node (rn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
update = si;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Distance or tag changed. */
|
||||||
|
if (update)
|
||||||
|
static_delete_ipv4 (safi, p, gate, ifindex, update->tag, update->distance, zvrf);
|
||||||
|
|
||||||
|
/* Make new static route structure. */
|
||||||
|
si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
|
||||||
|
|
||||||
|
si->type = type;
|
||||||
|
si->distance = distance;
|
||||||
|
si->flags = flags;
|
||||||
|
si->tag = tag;
|
||||||
|
si->vrf_id = zvrf->vrf_id;
|
||||||
|
si->ifindex = ifindex;
|
||||||
|
if (si->ifindex)
|
||||||
|
strcpy(si->ifname, ifname);
|
||||||
|
|
||||||
|
if (gate)
|
||||||
|
si->addr.ipv4 = *gate;
|
||||||
|
|
||||||
|
/* 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->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
|
||||||
|
break;
|
||||||
|
if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.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_route (AFI_IP, safi, p, si);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
||||||
|
u_short tag, u_char distance, struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
u_char type = 0;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct static_route *si;
|
||||||
|
struct route_table *stable;
|
||||||
|
|
||||||
|
/* Lookup table. */
|
||||||
|
stable = zebra_vrf_static_table (AFI_IP, safi, zvrf);
|
||||||
|
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 (ifindex)
|
||||||
|
type = STATIC_IFINDEX;
|
||||||
|
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->addr.ipv4))
|
||||||
|
&& (! ifindex || ifindex == si->ifindex)
|
||||||
|
&& (! tag || (tag == si->tag)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Can't find static route. */
|
||||||
|
if (! si)
|
||||||
|
{
|
||||||
|
route_unlock_node (rn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Install into rib. */
|
||||||
|
static_uninstall_route (AFI_IP, safi, 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;
|
||||||
|
route_unlock_node (rn);
|
||||||
|
|
||||||
|
/* Free static route configuration. */
|
||||||
|
XFREE (MTYPE_STATIC_ROUTE, si);
|
||||||
|
|
||||||
|
route_unlock_node (rn);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add static route into static route configuration. */
|
||||||
|
int
|
||||||
|
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
||||||
|
ifindex_t ifindex, const char *ifname, u_char flags,
|
||||||
|
u_short tag, u_char distance, struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
struct static_route *si;
|
||||||
|
struct static_route *pp;
|
||||||
|
struct static_route *cp;
|
||||||
|
struct static_route *update = NULL;
|
||||||
|
struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
|
||||||
|
|
||||||
|
if (! stable)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!gate &&
|
||||||
|
(type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFINDEX))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!ifindex &&
|
||||||
|
(type == STATIC_IPV6_GATEWAY_IFINDEX || type == STATIC_IFINDEX))
|
||||||
|
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 (type == si->type
|
||||||
|
&& (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
|
||||||
|
&& (! ifindex || ifindex == si->ifindex))
|
||||||
|
{
|
||||||
|
if ((distance == si->distance) && (tag == si->tag))
|
||||||
|
{
|
||||||
|
route_unlock_node (rn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
update = si;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Distance or tag changed. */
|
||||||
|
if (update)
|
||||||
|
static_delete_ipv6 (p, type, gate, ifindex, update->tag, update->distance, zvrf);
|
||||||
|
|
||||||
|
/* Make new static route structure. */
|
||||||
|
si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
|
||||||
|
|
||||||
|
si->type = type;
|
||||||
|
si->distance = distance;
|
||||||
|
si->flags = flags;
|
||||||
|
si->tag = tag;
|
||||||
|
si->vrf_id = zvrf->vrf_id;
|
||||||
|
si->ifindex = ifindex;
|
||||||
|
if (si->ifindex)
|
||||||
|
strcpy (si->ifname, ifname);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case STATIC_IPV6_GATEWAY:
|
||||||
|
si->addr.ipv6 = *gate;
|
||||||
|
break;
|
||||||
|
case STATIC_IPV6_GATEWAY_IFINDEX:
|
||||||
|
si->addr.ipv6 = *gate;
|
||||||
|
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_route (AFI_IP6, SAFI_UNICAST, p, si);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete static route from static route configuration. */
|
||||||
|
int
|
||||||
|
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
||||||
|
ifindex_t ifindex, u_short tag, u_char distance,
|
||||||
|
struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
struct static_route *si;
|
||||||
|
struct route_table *stable;
|
||||||
|
|
||||||
|
/* Lookup table. */
|
||||||
|
stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, zvrf);
|
||||||
|
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->addr.ipv6))
|
||||||
|
&& (! ifindex || ifindex == si->ifindex)
|
||||||
|
&& (! tag || (tag == si->tag)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Can't find static route. */
|
||||||
|
if (! si)
|
||||||
|
{
|
||||||
|
route_unlock_node (rn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Install into rib. */
|
||||||
|
static_uninstall_route (AFI_IP6, SAFI_UNICAST, 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_ROUTE, si);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
95
zebra/zebra_static.h
Normal file
95
zebra/zebra_static.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Static Routing Information header
|
||||||
|
* Copyright (C) 2016 Cumulus Networks
|
||||||
|
* Donald Sharp
|
||||||
|
*
|
||||||
|
* This file is part of Quagga.
|
||||||
|
*
|
||||||
|
* Quagga 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.
|
||||||
|
*
|
||||||
|
* Quagga 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 Quagga; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __ZEBRA_STATIC_H__
|
||||||
|
#define __ZEBRA_STATIC_H__
|
||||||
|
|
||||||
|
/* Static route information. */
|
||||||
|
struct static_route
|
||||||
|
{
|
||||||
|
/* For linked list. */
|
||||||
|
struct static_route *prev;
|
||||||
|
struct static_route *next;
|
||||||
|
|
||||||
|
/* VRF identifier. */
|
||||||
|
vrf_id_t vrf_id;
|
||||||
|
|
||||||
|
/* Administrative distance. */
|
||||||
|
u_char distance;
|
||||||
|
|
||||||
|
/* Tag */
|
||||||
|
u_short tag;
|
||||||
|
|
||||||
|
/* Flag for this static route's type. */
|
||||||
|
u_char type;
|
||||||
|
#define STATIC_IFINDEX 1
|
||||||
|
#define STATIC_IPV4_GATEWAY 2
|
||||||
|
#define STATIC_IPV4_BLACKHOLE 3
|
||||||
|
#define STATIC_IPV6_GATEWAY 4
|
||||||
|
#define STATIC_IPV6_GATEWAY_IFINDEX 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nexthop value.
|
||||||
|
*
|
||||||
|
* Under IPv4 addr and ifindex are
|
||||||
|
* used independentyly.
|
||||||
|
* STATIC_IPV4_GATEWAY uses addr
|
||||||
|
* STATIC_IFINDEX uses ifindex
|
||||||
|
*/
|
||||||
|
union g_addr addr;
|
||||||
|
ifindex_t ifindex;
|
||||||
|
|
||||||
|
char ifname[INTERFACE_NAMSIZ + 1];
|
||||||
|
|
||||||
|
/* bit flags */
|
||||||
|
u_char flags;
|
||||||
|
/*
|
||||||
|
see ZEBRA_FLAG_REJECT
|
||||||
|
ZEBRA_FLAG_BLACKHOLE
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void
|
||||||
|
static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
|
||||||
|
extern void
|
||||||
|
static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
||||||
|
const char *ifname, u_char flags, u_short tag,
|
||||||
|
u_char distance, struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, ifindex_t ifindex,
|
||||||
|
u_short tag, u_char distance, struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
||||||
|
ifindex_t ifindex, const char *ifname, u_char flags,
|
||||||
|
u_short tag, u_char distance, struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
|
||||||
|
ifindex_t ifindex, u_short tag, u_char distance,
|
||||||
|
struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
|
#endif
|
@ -29,6 +29,7 @@
|
|||||||
#include "zebra/rib.h"
|
#include "zebra/rib.h"
|
||||||
#include "zebra/zebra_vrf.h"
|
#include "zebra/zebra_vrf.h"
|
||||||
#include "zebra/router-id.h"
|
#include "zebra/router-id.h"
|
||||||
|
#include "zebra/zebra_static.h"
|
||||||
|
|
||||||
extern struct zebra_t zebrad;
|
extern struct zebra_t zebrad;
|
||||||
struct list *zvrf_list;
|
struct list *zvrf_list;
|
||||||
|
@ -29,13 +29,14 @@
|
|||||||
#include "rib.h"
|
#include "rib.h"
|
||||||
#include "nexthop.h"
|
#include "nexthop.h"
|
||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
|
#include "lib/json.h"
|
||||||
|
|
||||||
#include "zebra/zserv.h"
|
#include "zebra/zserv.h"
|
||||||
#include "zebra/zebra_vrf.h"
|
#include "zebra/zebra_vrf.h"
|
||||||
#include "zebra/zebra_rnh.h"
|
#include "zebra/zebra_rnh.h"
|
||||||
#include "zebra/redistribute.h"
|
#include "zebra/redistribute.h"
|
||||||
#include "zebra/zebra_routemap.h"
|
#include "zebra/zebra_routemap.h"
|
||||||
#include "lib/json.h"
|
#include "zebra/zebra_static.h"
|
||||||
|
|
||||||
extern int allow_delete;
|
extern int allow_delete;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user