[prev in list] [next in list] [prev in thread] [next in thread]
List: quagga-dev
Subject: [quagga-dev 3603] [PATCH] take safi into account in zebra_rib.c,
From: Hugo Santos <hsantos () av ! it ! pt>
Date: 2005-08-21 20:50:12
Message-ID: 20050821205012.GC5697 () innerghost ! net
[Download RAW message or body]
Hi,
The attached patch merges all v4/v6 RIB handling functions into common
afi/safi independent ones (version 2 arrives after Paul and Hasso's
comments in IRC). All calls in zebra were updated to use this new
interface. The following bugs are also fixed:
- the ipv6 static route node was not being properly on static_delete
- the metric and distance specified by other daemons via
ZEBRA_ROUTE_IPV6_ADD was not being taken into account by zebra when
the route was added to the RIB (only bgpd supplied metric
information though)
The following zebra/Changelog additions are proposed related to this
patch:
2005-08-21 Hugo Santos <hsantos@av.it.pt>
* zebra_rib.c: (rib_{add,delete,match,lookup}_{ipv4,ipv6})
functions merged into single afi/safi independent versions.
* connected.c: (connected_{up,down}_{ipv4,ipv6}) updated to use
new zebra_rib functions.
* kernel_socket.c: (rtm_read) ditto.
* rt_netlink.c: (netlink_routing_table, netlink_routing_change)
ditto.
* rtread_getmsg.c: (handle_route_entry) ditto.
* rtread_proc.c: (proc_route_read, proc_ipv6_route_read) ditto.
* zebra_vty.c: (zebra_static_ipv4, static_ipv6_func) ditto.
* zserv.c: (zsend_{ipv4,ipv6}_nexthop_lookup,
zsend_ipv4_import_lookup, zread_{ipv4,ipv6}_{read,delete}):
ditto.
* zserv.c: (zread_ipv6_read) take metric into account when
adding entry to rib.
Please review, any comments are welcome.
Hugo Santos
["zebra-rib-2.diff" (text/plain)]
Index: zebra/connected.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/connected.c,v
retrieving revision 1.14
diff -u -p -w -b -r1.14 connected.c
--- zebra/connected.c 28 Jun 2005 17:17:12 -0000 1.14
+++ zebra/connected.c 21 Aug 2005 20:29:41 -0000
@@ -81,7 +81,8 @@ connected_up_ipv4 (struct interface *ifp
if (prefix_ipv4_any (&p))
return;
- rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
+ rib_add (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_CONNECT, 0,
+ (struct prefix *)&p, NULL, ifp->ifindex, 0, 0, 0);
rib_update ();
}
@@ -219,7 +220,8 @@ connected_down_ipv4 (struct interface *i
if (prefix_ipv4_any (&p))
return;
- rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
+ rib_delete (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_CONNECT, 0,
+ (struct prefix *)&p, NULL, ifp->ifindex, 0);
rib_update ();
}
@@ -303,12 +305,13 @@ connected_up_ipv6 (struct interface *ifp
apply_mask_ipv6 (&p);
#if ! defined (MUSICA) && ! defined (LINUX)
- /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
+ /* XXX: It is already done by rib_bogus_ipv6 within rib_add */
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
return;
#endif
- rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
+ rib_add (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_CONNECT, 0,
+ (struct prefix *)&p, NULL, ifp->ifindex, 0, 0, 0);
rib_update ();
}
@@ -397,7 +400,8 @@ connected_down_ipv6 (struct interface *i
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
return;
- rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
+ rib_delete (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_CONNECT, 0,
+ (struct prefix *)&p, NULL, ifp->ifindex, 0);
rib_update ();
}
Index: zebra/kernel_socket.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/kernel_socket.c,v
retrieving revision 1.27
diff -u -p -w -b -r1.27 kernel_socket.c
--- zebra/kernel_socket.c 29 Jul 2005 14:36:00 -0000 1.27
+++ zebra/kernel_socket.c 21 Aug 2005 20:29:41 -0000
@@ -625,11 +625,11 @@ rtm_read (struct rt_msghdr *rtm)
p.prefixlen = ip_masklen (mask.sin.sin_addr);
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin.sin_addr, 0, 0, 0, 0);
+ rib_add (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, zebra_flags,
+ (struct prefix *)&p, &gate.sin.sin_addr, 0, 0, 0, 0);
else
- rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin.sin_addr, 0, 0);
+ rib_delete (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, zebra_flags,
+ (struct prefix *)&p, &gate.sin.sin_addr, 0, 0);
}
#ifdef HAVE_IPV6
if (dest.sa.sa_family == AF_INET6)
@@ -653,11 +653,11 @@ rtm_read (struct rt_msghdr *rtm)
#endif /* KAME */
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
- rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin6.sin6_addr, ifindex, 0);
+ rib_add (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, zebra_flags,
+ (struct prefix *)&p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0);
else
- rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin6.sin6_addr, ifindex, 0);
+ rib_delete (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, zebra_flags,
+ (struct prefix *)&p, &gate.sin6.sin6_addr, ifindex, 0);
}
#endif /* HAVE_IPV6 */
}
Index: zebra/rib.h
===================================================================
RCS file: /var/cvsroot/quagga/zebra/rib.h,v
retrieving revision 1.7
diff -u -p -w -b -r1.7 rib.h
--- zebra/rib.h 28 Jun 2005 17:17:12 -0000 1.7
+++ zebra/rib.h 21 Aug 2005 20:29:41 -0000
@@ -66,6 +66,27 @@ struct rib
};
/* Static route information. */
+struct static_route_info
+{
+ /* For linked list. */
+ struct static_route_info *prev;
+ struct static_route_info *next;
+
+ /* Administrative distance. */
+ u_char distance;
+
+ /* Flag for this static route's type */
+ u_char type;
+
+ /* bit flags */
+ u_char flags;
+/*
+ see ZEBRA_FLAG_REJECT
+ ZEBRA_FLAG_BLACKHOLE
+ */
+};
+
+/* Static route information. */
struct static_ipv4
{
/* For linked list. */
@@ -81,19 +102,15 @@ struct static_ipv4
#define STATIC_IPV4_IFNAME 2
#define STATIC_IPV4_BLACKHOLE 3
+ /* bit flags */
+ u_char flags;
+
/* Nexthop value. */
union
{
struct in_addr ipv4;
char *ifname;
} gate;
-
- /* bit flags */
- u_char flags;
-/*
- see ZEBRA_FLAG_REJECT
- ZEBRA_FLAG_BLACKHOLE
- */
};
#ifdef HAVE_IPV6
@@ -113,16 +130,12 @@ struct static_ipv6
#define STATIC_IPV6_GATEWAY_IFNAME 2
#define STATIC_IPV6_IFNAME 3
+ /* bit flags */
+ u_char flags;
+
/* Nexthop value. */
struct in6_addr ipv6;
char *ifname;
-
- /* bit flags */
- u_char flags;
-/*
- see ZEBRA_FLAG_REJECT
- ZEBRA_FLAG_BLACKHOLE
- */
};
#endif /* HAVE_IPV6 */
@@ -213,58 +226,32 @@ extern struct vrf *vrf_lookup (u_int32_t
extern struct route_table *vrf_table (afi_t afi, safi_t safi, u_int32_t id);
extern struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t id);
-extern int rib_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, u_char);
-
-extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *);
-
-extern int rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
- struct in_addr *gate, unsigned int ifindex,
- u_int32_t);
-
-extern struct rib *rib_match_ipv4 (struct in_addr);
-
-extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *);
+extern int rib_add (afi_t afi, safi_t safi, int type, int flags,
+ struct prefix *p, void *gate, unsigned int ifindex,
+ u_int32_t vrf_id, u_int32_t metric, u_char distance);
+extern int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *,
+ struct rib *, u_int32_t vrf_id);
+extern int rib_delete (afi_t afi, safi_t safi, int type, int flags,
+ struct prefix *p, void *gate,
+ unsigned int ifindex, u_int32_t);
+
+extern int static_add (afi_t afi, safi_t safi, struct prefix *,
+ u_char type, void *gate, const char *ifname,
+ u_char flags, u_char distance, u_int32_t);
+extern int static_delete (afi_t afi, safi_t safi, struct prefix *,
+ u_char type, void *gate, const char *ifname,
+ u_char distance, u_int32_t);
+
+
+extern struct rib *rib_lookup (afi_t afi, safi_t safi,
+ struct prefix *, u_int32_t vrf_id);
+extern struct rib *rib_match (afi_t afi, safi_t safi,
+ void *addr, u_int32_t vrf_id);
extern void rib_update (void);
extern void rib_weed_tables (void);
extern void rib_sweep_route (void);
extern void rib_close (void);
extern void rib_init (void);
-
-extern int
-static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
- u_char flags, u_char distance, u_int32_t vrf_id);
-
-extern int
-static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
- u_char distance, u_int32_t vrf_id);
-
-#ifdef HAVE_IPV6
-extern int
-rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id);
-
-extern int
-rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id);
-
-extern struct rib *rib_lookup_ipv6 (struct in6_addr *);
-
-extern struct rib *rib_match_ipv6 (struct in6_addr *);
-
-extern struct route_table *rib_table_ipv6;
-
-extern int
-static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- const char *ifname, u_char flags, u_char distance,
- u_int32_t vrf_id);
-
-extern int
-static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- const char *ifname, u_char distance, u_int32_t vrf_id);
-
-#endif /* HAVE_IPV6 */
#endif /*_ZEBRA_RIB_H */
Index: zebra/rt_netlink.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/rt_netlink.c,v
retrieving revision 1.37
diff -u -p -w -b -r1.37 rt_netlink.c
--- zebra/rt_netlink.c 12 Jun 2005 11:28:18 -0000 1.37
+++ zebra/rt_netlink.c 21 Aug 2005 20:29:43 -0000
@@ -783,7 +783,8 @@ netlink_routing_table (struct sockaddr_n
memcpy (&p.prefix, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, metric, 0);
+ rib_add (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, flags,
+ (struct prefix *)&p, gate, index, table, metric, 0);
}
#ifdef HAVE_IPV6
if (rtm->rtm_family == AF_INET6)
@@ -793,7 +794,9 @@ netlink_routing_table (struct sockaddr_n
memcpy (&p.prefix, dest, 16);
p.prefixlen = rtm->rtm_dst_len;
- rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
+ /* XXX original call didn't use metric here, but probably we should */
+ rib_add (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, flags,
+ (struct prefix *)&p, gate, index, table, 0, 0);
}
#endif /* HAVE_IPV6 */
@@ -915,9 +918,11 @@ netlink_route_change (struct sockaddr_nl
}
if (h->nlmsg_type == RTM_NEWROUTE)
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
+ rib_add (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, 0,
+ (struct prefix *)&p, gate, index, table, 0, 0);
else
- rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
+ rib_delete (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, 0,
+ (struct prefix *)&p, gate, index, table);
}
#ifdef HAVE_IPV6
@@ -943,9 +948,11 @@ netlink_route_change (struct sockaddr_nl
}
if (h->nlmsg_type == RTM_NEWROUTE)
- rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
+ rib_add (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, 0,
+ (struct prefix *)&p, gate, index, 0, 0, 0);
else
- rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
+ rib_delete (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, 0,
+ (struct prefix *)&p, gate, index, 0);
}
#endif /* HAVE_IPV6 */
Index: zebra/rtread_getmsg.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/rtread_getmsg.c,v
retrieving revision 1.2
diff -u -p -w -b -r1.2 rtread_getmsg.c
--- zebra/rtread_getmsg.c 20 Nov 2004 02:07:07 -0000 1.2
+++ zebra/rtread_getmsg.c 21 Aug 2005 20:29:43 -0000
@@ -87,8 +87,8 @@ void handle_route_entry (mib2_ipRouteEnt
gateway.s_addr = routeEntry->ipRouteNextHop;
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &prefix,
- &gateway, 0, 0, 0, 0);
+ rib_add (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, zebra_flags,
+ (struct prefix *)&prefix, &gateway, 0, 0, 0, 0);
}
void route_read ()
Index: zebra/rtread_proc.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/rtread_proc.c,v
retrieving revision 1.4
diff -u -p -w -b -r1.4 rtread_proc.c
--- zebra/rtread_proc.c 28 Jun 2005 17:17:12 -0000 1.4
+++ zebra/rtread_proc.c 21 Aug 2005 20:29:43 -0000
@@ -96,7 +96,8 @@ proc_route_read (void)
p.prefixlen = ip_masklen (tmpmask);
sscanf (gate, "%lX", (unsigned long *)&gateway);
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, 0, 0, 0, 0);
+ rib_add (AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, zebra_flags,
+ (struct prefix *)&p, &gateway, 0, 0, 0, 0);
}
fclose (fp);
@@ -156,7 +157,8 @@ proc_ipv6_route_read ()
str2in6_addr (gate, &gateway);
p.prefixlen = dest_plen;
- rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, 0, 0);
+ rib_add (AFI_IP6, SAFI_UNICAST, ZEBRA_ROUTE_KERNEL, zebra_flags,
+ (struct prefix *)&p, &gateway, 0, 0, 0, 0);
}
fclose (fp);
Index: zebra/zebra_rib.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/zebra_rib.c,v
retrieving revision 1.21
diff -u -p -w -b -r1.21 zebra_rib.c
--- zebra/zebra_rib.c 28 Jun 2005 17:17:12 -0000 1.21
+++ zebra/zebra_rib.c 21 Aug 2005 20:29:44 -0000
@@ -315,6 +315,33 @@ nexthop_ipv6_ifindex_add (struct rib *ri
}
#endif /* HAVE_IPV6 */
+static struct nexthop *
+nexthop_afi_ifindex_add (afi_t afi, struct rib *rib, void *gate,
+ unsigned int ifindex)
+{
+ if (afi == AFI_IP)
+ return nexthop_ipv4_ifindex_add(rib, (struct in_addr *)gate, ifindex);
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
+ return nexthop_ipv6_ifindex_add(rib, (struct in6_addr *)gate, ifindex);
+#endif /* HAVE_IPV6 */
+
+ return NULL;
+}
+
+static struct nexthop *
+nexthop_afi_add (afi_t afi, struct rib *rib, void *gate)
+{
+ if (afi == AFI_IP)
+ return nexthop_ipv4_add(rib, (struct in_addr *)gate);
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
+ return nexthop_ipv6_add(rib, (struct in6_addr *)gate);
+#endif /* HAVE_IPV6 */
+
+ return NULL;
+}
+
struct nexthop *
nexthop_blackhole_add (struct rib *rib)
{
@@ -330,133 +357,84 @@ nexthop_blackhole_add (struct rib *rib)
return nexthop;
}
+static void
+prefix_fill(afi_t afi, struct prefix *p, void *addr)
+{
+ memset (p, 0, sizeof (struct prefix));
+ p->family = afi2family(afi);
+
+ if (afi == AFI_IP)
+ {
+ p->prefixlen = IPV4_MAX_PREFIXLEN;
+ p->u.prefix4 = *(struct in_addr *)addr;
+ }
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
+ {
+ p->prefixlen = IPV6_MAX_PREFIXLEN;
+ p->u.prefix6 = *(struct in6_addr *)addr;
+ }
+#endif /* HAVE_IPV6 */
+}
+
+static void
+copy_address_afi(afi_t afi, void *dst, void *src)
+{
+ if (afi == AFI_IP)
+ *((struct in_addr *)dst) = *(struct in_addr *)src;
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
+ *((struct in6_addr *)dst) = *(struct in6_addr *)src;
+#endif /* HAVE_IPV6 */
+}
+
/* If force flag is not set, do not modify falgs at all for uninstall
the route from FIB. */
static int
-nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
- struct route_node *top)
+nexthop_active (afi_t afi, safi_t safi, struct rib *rib,
+ struct nexthop *nexthop, int set,
+ struct route_node *top, u_int32_t vrf_id)
{
- struct prefix_ipv4 p;
+ struct prefix 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;
+ u_char type, type_if, type_ifname;
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (afi, safi, vrf_id);
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 (afi == AFI_IP)
{
- 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;
+ type = NEXTHOP_TYPE_IPV4;
+ type_if = NEXTHOP_TYPE_IPV4_IFINDEX;
+ type_ifname = NEXTHOP_TYPE_IPV4_IFNAME;
}
- 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)
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
{
- 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;
+ type = NEXTHOP_TYPE_IPV6;
+ type_if = NEXTHOP_TYPE_IPV6_IFINDEX;
+ type_ifname = NEXTHOP_TYPE_IPV6_IFNAME;
}
+#endif /* HAVE_IPV6 */
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. */
-static int
-nexthop_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)
+ if (nexthop->type == type)
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;
+ prefix_fill(afi, &p, &nexthop->gate);
- rn = route_node_match (table, (struct prefix *) &p);
+ rn = route_node_match (table, &p);
while (rn)
{
route_unlock_node (rn);
@@ -487,8 +465,7 @@ nexthop_active_ipv6 (struct rib *rib, st
{
/* Directly point connected route. */
newhop = match->nexthop;
-
- if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
+ if (newhop && nexthop->type == type)
nexthop->ifindex = newhop->ifindex;
return 1;
@@ -503,14 +480,14 @@ nexthop_active_ipv6 (struct rib *rib, st
{
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 == type
+ || newhop->type == type_if
+ || newhop->type == type_ifname)
+ copy_address_afi(afi, &nexthop->rgate, &newhop->gate);
if (newhop->type == NEXTHOP_TYPE_IFINDEX
|| newhop->type == NEXTHOP_TYPE_IFNAME
- || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
- || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
+ || newhop->type == type_if
+ || newhop->type == type_ifname)
nexthop->rifindex = newhop->ifindex;
}
return 1;
@@ -525,163 +502,44 @@ nexthop_active_ipv6 (struct rib *rib, st
}
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)
+/* If force flag is not set, do not modify falgs at all for uninstall
+ the route from FIB. */
+static int
+nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
+ struct route_node *top)
{
- 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;
+ return nexthop_active (AFI_IP, SAFI_UNICAST, rib, nexthop, set, top, 0);
+}
- /* If there is no selected route or matched route is EGP, go up
- tree. */
- if (! match
- || match->type == ZEBRA_ROUTE_BGP)
+#ifdef HAVE_IPV6
+/* If force flag is not set, do not modify falgs at all for uninstall
+ the route from FIB. */
+static int
+nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
+ struct route_node *top)
{
- do {
- rn = rn->parent;
- } while (rn && rn->info == NULL);
- if (rn)
- route_lock_node (rn);
+ return nexthop_active (AFI_IP6, SAFI_UNICAST, rib, nexthop, set, top, 0);
}
- else
- {
- if (match->type == ZEBRA_ROUTE_CONNECT)
- /* Directly point connected route. */
- return match;
- else
+#endif /* HAVE_IPV6 */
+
+struct rib *
+rib_match_ipv4 (struct in_addr addr)
{
- for (newhop = match->nexthop; newhop; newhop = newhop->next)
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
- return match;
- return NULL;
- }
- }
- }
- return NULL;
+ return rib_match (AFI_IP, SAFI_UNICAST, &addr, 0);
}
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;
+ return rib_lookup (AFI_IP, SAFI_UNICAST, (struct prefix *)p, 0);
}
#ifdef HAVE_IPV6
struct 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;
+ return rib_match (AFI_IP6, SAFI_UNICAST, addr, 0);
}
#endif /* HAVE_IPV6 */
@@ -1121,24 +979,47 @@ rib_delnode (struct route_node *rn, stru
route_unlock_node (rn);
}
-int
-rib_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;
+#ifdef HAVE_IPV6
+static int
+rib_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)) {
+#if defined (MUSICA) || defined (LINUX)
+ /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
+ if (p->prefixlen == 96)
+ return 0;
+#endif /* MUSICA */
+ 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;
+}
+#endif /* HAVE_IPV6 */
+
+int
+rib_add (afi_t afi, safi_t safi, int type, int flags, struct prefix *p,
+ void *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);
+ table = vrf_table (afi, safi, vrf_id);
if (! table)
return 0;
/* Make it sure prefixlen is applied to the prefix. */
- apply_mask_ipv4 (p);
+ apply_mask (p);
/* Set default distance by route type. */
if (distance == 0)
@@ -1150,8 +1031,14 @@ rib_add_ipv4 (int type, int flags, struc
distance = 200;
}
+#ifdef HAVE_IPV6
+ if (rib_bogus_ipv6 (type, (struct prefix_ipv6 *)p,
+ (struct in6_addr *)gate, ifindex, 0))
+ return 0;
+#endif /* HAVE_IPV6 */
+
/* Lookup route node.*/
- rn = route_node_get (table, (struct prefix *) p);
+ rn = route_node_get (table, p);
/* If same type of route are installed, treat it as a implicit
withdraw. */
@@ -1191,9 +1078,9 @@ rib_add_ipv4 (int type, int flags, struc
if (gate)
{
if (ifindex)
- nexthop_ipv4_ifindex_add (rib, gate, ifindex);
+ nexthop_afi_ifindex_add (afi, rib, gate, ifindex);
else
- nexthop_ipv4_add (rib, gate);
+ nexthop_afi_add (afi, rib, gate);
}
else
nexthop_ifindex_add (rib, ifindex);
@@ -1218,7 +1105,8 @@ rib_add_ipv4 (int type, int flags, struc
}
int
-rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
+rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p,
+ struct rib *rib, u_int32_t vrf_id)
{
struct route_table *table;
struct route_node *rn;
@@ -1226,11 +1114,12 @@ rib_add_ipv4_multipath (struct prefix_ip
struct nexthop *nexthop;
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (afi, safi, vrf_id);
if (! table)
return 0;
+
/* Make it sure prefixlen is applied to the prefix. */
- apply_mask_ipv4 (p);
+ apply_mask (p);
/* Set default distance by route type. */
if (rib->distance == 0)
@@ -1244,7 +1133,7 @@ rib_add_ipv4_multipath (struct prefix_ip
}
/* Lookup route node.*/
- rn = route_node_get (table, (struct prefix *) p);
+ rn = route_node_get (table, p);
/* If same type of route are installed, treat it as a implicit
withdraw. */
@@ -1275,8 +1164,8 @@ rib_add_ipv4_multipath (struct prefix_ip
}
int
-rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
- struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
+rib_delete (afi_t afi, safi_t safi, int type, int flags, struct prefix *p,
+ void *gate, unsigned int ifindex, u_int32_t vrf_id)
{
struct route_table *table;
struct route_node *rn;
@@ -1286,37 +1175,38 @@ rib_delete_ipv4 (int type, int flags, st
struct nexthop *nexthop;
char buf1[BUFSIZ];
char buf2[BUFSIZ];
+ int family = afi2family(afi);
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (afi, safi, vrf_id);
if (! table)
return 0;
/* Apply mask. */
- apply_mask_ipv4 (p);
+ apply_mask (p);
if (IS_ZEBRA_DEBUG_KERNEL && gate)
- zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+ zlog_debug ("rib_delete(): route delete %s/%d via %s ifindex %d",
+ inet_ntop (family, &p->u.prefix, buf1, BUFSIZ),
p->prefixlen,
- inet_ntoa (*gate),
+ inet_ntop (family, gate, buf2, BUFSIZ),
ifindex);
/* Lookup route node. */
- rn = route_node_lookup (table, (struct prefix *) p);
+ rn = route_node_lookup (table, p);
if (! rn)
{
if (IS_ZEBRA_DEBUG_KERNEL)
{
if (gate)
zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+ inet_ntop (family, &p->u.prefix, buf1, BUFSIZ),
p->prefixlen,
- inet_ntop (AF_INET, gate, buf2, BUFSIZ),
+ inet_ntop (family, gate, buf2, BUFSIZ),
ifindex);
else
zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+ inet_ntop (family, &p->u.prefix, buf1, BUFSIZ),
p->prefixlen,
ifindex);
}
@@ -1348,15 +1238,17 @@ rib_delete_ipv4 (int type, int flags, st
break;
}
}
- else if (gate)
+ else if (gate && afi == AFI_IP)
{
+ /* This behaviour existed only in rib_delete_ipv4 */
+
nexthop = rib->nexthop;
/* Make sure that the route found has the same gateway. */
if (rib->type == type
&& nexthop &&
- (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
- IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)) )
+ (IPV4_ADDR_SAME (&nexthop->gate.ipv4, (struct in_addr *)gate) ||
+ IPV4_ADDR_SAME (&nexthop->rgate.ipv4, (struct in_addr *)gate)) )
{
same = rib;
break;
@@ -1390,14 +1282,14 @@ rib_delete_ipv4 (int type, int flags, st
{
if (gate)
zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+ inet_ntop (family, &p->u.prefix, buf1, BUFSIZ),
p->prefixlen,
- inet_ntop (AF_INET, gate, buf2, BUFSIZ),
+ inet_ntop (family, gate, buf2, BUFSIZ),
ifindex,
type);
else
zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
- inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+ inet_ntop (family, &p->u.prefix, buf1, BUFSIZ),
p->prefixlen,
ifindex,
type);
@@ -1417,54 +1309,105 @@ rib_delete_ipv4 (int type, int flags, st
return 0;
}
-/* Install static route into rib. */
-static void
-static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
+struct rib *
+rib_lookup (afi_t afi, safi_t safi, struct prefix *p, u_int32_t vrf_id)
{
- struct rib *rib;
- struct route_node *rn;
struct route_table *table;
+ struct route_node *rn;
+ struct rib *match;
+ struct nexthop *nexthop;
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (afi, safi, vrf_id);
if (! table)
- return;
+ return 0;
- /* 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)
+ rn = route_node_lookup (table, 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 (rib)
+ 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;
+}
+
+struct rib *
+rib_match (afi_t afi, safi_t safi, void *addr, u_int32_t vrf_id)
{
- /* Same distance static route is there. Update it with new
- nexthop. */
- route_unlock_node (rn);
- switch (si->type)
+ struct prefix p;
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *match;
+ struct nexthop *newhop;
+
+ /* Lookup table. */
+ table = vrf_table (afi, safi, vrf_id);
+ if (! table)
+ return 0;
+
+ /* Make lookup prefix. */
+ prefix_fill(afi, &p, addr);
+
+ rn = route_node_match (table, &p);
+
+ while (rn)
{
- 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);
+ 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;
- }
- rib_queue_add (&zebrad, rn, NULL);
+
+ /* 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
{
- /* This is new static route. */
- rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
-
- rib->type = ZEBRA_ROUTE_STATIC;
- rib->distance = si->distance;
- rib->metric = 0;
- rib->nexthop_num = 0;
+ 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;
+}
+static void
+nexthop_apply_static_ipv4 (struct rib *rib, struct static_ipv4 *si)
+{
switch (si->type)
{
case STATIC_IPV4_GATEWAY:
@@ -1477,16 +1420,6 @@ static_install_ipv4 (struct prefix *p, s
nexthop_blackhole_add (rib);
break;
}
-
- /* Save the flags of this static routes (reject, blackhole) */
- rib->flags = si->flags;
-
- /* Link this rib to the tree. */
- rib_addnode (rn, rib);
-
- /* Process this prefix. */
- rib_queue_add (&zebrad, rn, NULL);
- }
}
static int
@@ -1503,582 +1436,326 @@ static_ipv4_nexthop_same (struct nexthop
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
&& si->type == STATIC_IPV4_BLACKHOLE)
return 1;
- return 0;;
+ return 0;
}
-/* Uninstall static route from RIB. */
+#ifdef HAVE_IPV6
static void
-static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
+nexthop_apply_static_ipv6 (struct rib *rib, struct static_ipv6 *si)
+{
+ 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;
+ }
+}
+
+static int
+static_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;
+}
+#endif /* HAVE_IPV6 */
+
+/* Helper macros to use with static_route_info */
+#define STATICV4(x) ((struct static_ipv4 *)(x))
+#define STATICV6(x) ((struct static_ipv6 *)(x))
+
+static inline void
+nexthop_apply_static (afi_t afi, struct rib *rib, void *si)
+{
+ if (afi == AFI_IP)
+ nexthop_apply_static_ipv4 (rib, STATICV4 (si));
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
+ nexthop_apply_static_ipv6 (rib, STATICV6 (si));
+#endif /* HAVE_IPV6 */
+}
+
+static inline int
+static_nexthop_same (afi_t afi, struct nexthop *nexthop,
+ struct static_route_info *si)
+{
+ if (afi == AFI_IP)
+ return static_ipv4_nexthop_same (nexthop, STATICV4 (si));
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
+ return static_ipv6_nexthop_same (nexthop, STATICV6 (si));
+#endif /* HAVE_IPV6 */
+
+ return 0;
+}
+
+/* Install static route into rib. */
+static void
+static_install (afi_t afi, safi_t safi, struct prefix *p,
+ struct static_route_info *si, u_int32_t vrf_id)
{
- struct route_node *rn;
struct rib *rib;
- struct nexthop *nexthop;
+ struct route_node *rn;
struct route_table *table;
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (afi, safi, vrf_id);
if (! table)
return;
- /* Lookup existing route with type and distance. */
- rn = route_node_lookup (table, p);
- if (! rn)
- 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)
+ if (rib)
{
+ /* Same distance static route is there. Update it with new
+ nexthop. */
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;
- }
+ nexthop_apply_static (afi, rib, si);
- /* Check nexthop. */
- if (rib->nexthop_num == 1)
- {
- rib_queue_add (&zebrad, rn, rib);
- rib_delnode (rn, rib);
+ rib_queue_add (&zebrad, rn, NULL);
}
else
{
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
- rib_uninstall (rn, rib);
- rib_queue_add (&zebrad, rn, rib);
- }
- /* Unlock node. */
- route_unlock_node (rn);
-}
+ /* This is new static route. */
+ rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
-/* Add static route into static route configuration. */
-int
-static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
- u_char flags, 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;
+ rib->type = ZEBRA_ROUTE_STATIC;
+ rib->distance = si->distance;
+ rib->metric = 0;
+ rib->nexthop_num = 0;
- /* Lookup table. */
- stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
- if (! stable)
- return -1;
+ nexthop_apply_static (afi, rib, si);
- /* Lookup static route prefix. */
- rn = route_node_get (stable, p);
+ /* Save the flags of this static routes (reject, blackhole) */
+ rib->flags = si->flags;
- /* Make flags. */
- if (gate)
- type = STATIC_IPV4_GATEWAY;
- else if (ifname)
- type = STATIC_IPV4_IFNAME;
- else
- type = STATIC_IPV4_BLACKHOLE;
+ /* Link this rib to the tree. */
+ rib_addnode (rn, rib);
- /* 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;
+ /* Process this prefix. */
+ rib_queue_add (&zebrad, rn, NULL);
}
}
- /* Distance chaged. */
- if (update)
- static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
+static struct static_route_info *
+static_route_info_alloc (afi_t afi, u_char type, void *gate,
+ const char *ifname, u_char flags,
+ u_char distance)
+{
+ struct static_route_info *si = NULL;
- /* Make new static route structure. */
+ if (afi == AFI_IP)
+ {
si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
memset (si, 0, sizeof (struct static_ipv4));
- si->type = type;
- si->distance = distance;
- si->flags = flags;
-
if (gate)
- si->gate.ipv4 = *gate;
- if (ifname)
- si->gate.ifname = XSTRDUP (0, ifname);
+ STATICV4(si)->gate.ipv4 = *(struct in_addr *)gate;
+ else if (ifname)
+ STATICV4(si)->gate.ifname = XSTRDUP (0, ifname);
+ }
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
+ {
+ si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
+ memset(si, 0, sizeof (struct static_ipv6));
- /* 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)
+ switch (type)
{
- if (si->distance < cp->distance)
+ case STATIC_IPV6_GATEWAY:
+ STATICV6(si)->ipv6 = *(struct in6_addr *)gate;
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))
+ case STATIC_IPV6_IFNAME:
+ STATICV6(si)->ifname = XSTRDUP (0, ifname);
+ break;
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ STATICV6(si)->ipv6 = *(struct in6_addr *)gate;
+ STATICV6(si)->ifname = XSTRDUP (0, ifname);
break;
- if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
- continue;
}
}
+#endif /* HAVE_IPV6 */
- /* 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);
+ si->type = type;
+ si->distance = distance;
+ si->flags = flags;
- return 1;
+ return si;
}
-/* Delete static route from static route configuration. */
-int
-static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
- u_char distance, u_int32_t vrf_id)
+static int
+static_route_info_compare(afi_t afi, struct static_route_info *si,
+ void *gate, const char *ifname)
{
- 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)
+ if (afi == AFI_IP)
{
- 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;
- route_unlock_node (rn);
-
- /* Free static route configuration. */
- if (ifname)
- XFREE (0, si->gate.ifname);
- XFREE (MTYPE_STATIC_IPV4, si);
-
- route_unlock_node (rn);
-
- return 1;
+ return (!gate || IPV4_ADDR_SAME ((struct in_addr *)gate,
+ &STATICV4(si)->gate.ipv4))
+ && (!ifname || strcmp (ifname, STATICV4(si)->gate.ifname) == 0);
}
-
-
#ifdef HAVE_IPV6
-static int
-rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, int table)
+ else if (afi == AFI_IP6)
{
- if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
-#if defined (MUSICA) || defined (LINUX)
- /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
- if (p->prefixlen == 96)
- return 0;
-#endif /* MUSICA */
- return 1;
+ return (!gate || IPV6_ADDR_SAME ((struct in_addr *)gate,
+ &STATICV6(si)->ipv6))
+ && (!ifname || strcmp (ifname, STATICV6(si)->ifname) == 0);
}
- 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;
-}
-
-int
-rib_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;
+#endif /* HAVE_IPV6 */
- if (rib->type == type
- && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
- && nexthop->ifindex == ifindex)
- {
- rib->refcnt++;
return 0;
}
- }
- else if (rib->type == type)
- {
- same = rib;
- break;
- }
- }
-
- /* Allocate new rib structure. */
- rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
-
- rib->type = type;
- rib->distance = distance;
- rib->flags = flags;
- rib->metric = metric;
- rib->table = vrf_id;
- rib->nexthop_num = 0;
- rib->uptime = time (NULL);
- /* Nexthop settings. */
- if (gate)
+u_char static_ipv4_type (void *gate, const char *ifname)
{
- if (ifindex)
- nexthop_ipv6_ifindex_add (rib, gate, ifindex);
- else
- nexthop_ipv6_add (rib, gate);
- }
+ /* Make flags. */
+ if (gate)
+ return STATIC_IPV4_GATEWAY;
+ else if (ifname)
+ return STATIC_IPV4_IFNAME;
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_queue_add (&zebrad, rn, same);
-
- /* Free implicit route.*/
- if (same)
- rib_delnode (rn, same);
-
- route_unlock_node (rn);
- return 0;
+ return STATIC_IPV4_BLACKHOLE;
}
int
-rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
+static_add (afi_t afi, safi_t safi, struct prefix *p, u_char type,
+ void *gate, const char *ifname, u_char flags,
+ u_char distance, 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);
+ struct static_route_info *si;
+ struct static_route_info *pp;
+ struct static_route_info *cp;
+ struct static_route_info *update = NULL;
+ struct route_table *stable;
/* Lookup table. */
- table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
- if (! table)
- return 0;
+ stable = vrf_static_table (afi, safi, vrf_id);
+ if (! stable)
+ return -1;
- /* Lookup route node. */
- rn = route_node_lookup (table, (struct prefix *) p);
- if (! rn)
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
+ if (type == 0 && afi == AFI_IP)
{
- if (gate)
- zlog_debug ("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_debug ("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;
+ /* If type isn't given in IPv4, deduce it from args. */
+ type = static_ipv4_type (gate, ifname);
}
- /* 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;
+ /* Lookup static route prefix. */
+ rn = route_node_get (stable, p);
- 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)
+ /* Do nothing if there is a same static route. */
+ for (si = rn->info; si; si = si->next)
{
- same = rib;
- break;
- }
- }
- }
-
- /* If same type of route can't be found and this message is from
- kernel. */
- if (! same)
+ if (type == si->type
+ && static_route_info_compare(afi, si, gate, ifname))
{
- if (fib && type == ZEBRA_ROUTE_KERNEL)
+ if (distance != si->distance)
{
- /* Unset flags. */
- for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
+ /* Maintaining the previous behaviour, where
+ * static_add_ipv4 does updates to the distance
+ * and v6 doesn't. */
+ if (afi == AFI_IP)
+ update = si;
}
else
{
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (gate)
- zlog_debug ("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_debug ("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;
+ return 0;
}
}
-
- /* Process changes. */
- rib_queue_add (&zebrad, rn, same);
-
- if (same)
- rib_delnode (rn, same);
-
- route_unlock_node (rn);
- return 0;
}
-/* Install static route into rib. */
-static void
-static_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;
+ /* Distance changed. */
+ if (update)
+ static_delete (afi, safi, p, type, gate, ifname, update->distance, vrf_id);
- if (rib)
- {
- /* Same distance static route is there. Update it with new
- nexthop. */
- route_unlock_node (rn);
+ si = static_route_info_alloc (afi, type, gate, ifname, flags, distance);
- switch (si->type)
+ /* 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)
{
- 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);
+ if (si->distance < cp->distance)
break;
- }
- rib_queue_add (&zebrad, rn, NULL);
- }
- else
- {
- /* This is new static route. */
- rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
-
- rib->type = ZEBRA_ROUTE_STATIC;
- rib->distance = si->distance;
- rib->metric = 0;
- rib->nexthop_num = 0;
-
- switch (si->type)
+ if (si->distance > cp->distance)
+ continue;
+ /* Once again, we keep the v4 behaviour, although v6's
+ * comment said it sorted by gateway address, it really
+ * didn't */
+ if (afi == AFI_IP
+ && si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
{
- 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);
+ if (ntohl (STATICV4(si)->gate.ipv4.s_addr)
+ < ntohl (STATICV4(cp)->gate.ipv4.s_addr))
break;
+ if (ntohl (STATICV4(si)->gate.ipv4.s_addr)
+ > ntohl (STATICV4(cp)->gate.ipv4.s_addr))
+ continue;
+ }
}
- /* Save the flags of this static routes (reject, blackhole) */
- rib->flags = si->flags;
-
- /* Link this rib to the tree. */
- rib_addnode (rn, rib);
+ /* Make linked list. */
+ if (pp)
+ pp->next = si;
+ else
+ rn->info = si;
+ if (cp)
+ cp->prev = si;
+ si->prev = pp;
+ si->next = cp;
- /* Process this prefix. */
- rib_queue_add (&zebrad, rn, NULL);
- }
-}
+ /* Install into rib. */
+ static_install (afi, safi, p, si, vrf_id);
-static int
-static_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;;
}
+
+/* Uninstall static route from RIB. */
static void
-static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
+static_uninstall (afi_t afi, safi_t safi, struct prefix *p,
+ struct static_route_info *si, u_int32_t vrf_id)
{
- struct route_table *table;
struct route_node *rn;
struct rib *rib;
struct nexthop *nexthop;
+ struct route_table *table;
/* Lookup table. */
- table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
+ table = vrf_table (afi, safi, vrf_id);
if (! table)
return;
/* Lookup existing route with type and distance. */
- rn = route_node_lookup (table, (struct prefix *) p);
+ 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);
@@ -2087,7 +1764,7 @@ static_uninstall_ipv6 (struct prefix *p,
/* Lookup nexthop. */
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (static_ipv6_nexthop_same (nexthop, si))
+ if (static_nexthop_same (afi, nexthop, si))
break;
/* Can't find nexthop. */
@@ -2100,8 +1777,8 @@ static_uninstall_ipv6 (struct prefix *p,
/* Check nexthop. */
if (rib->nexthop_num == 1)
{
- rib_delnode (rn, rib);
rib_queue_add (&zebrad, rn, rib);
+ rib_delnode (rn, rib);
}
else
{
@@ -2113,101 +1790,46 @@ static_uninstall_ipv6 (struct prefix *p,
route_unlock_node (rn);
}
-/* Add static route into static route configuration. */
-int
-static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- const char *ifname, u_char flags, 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)
+static void
+static_route_info_release (afi_t afi, struct static_route_info *si)
{
- if (distance == si->distance
- && type == si->type
- && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
- && (! ifname || strcmp (ifname, si->ifname) == 0))
+ if (afi == AFI_IP)
{
- 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;
- si->flags = flags;
-
- 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;
+ if (STATICV4(si)->gate.ifname)
+ XFREE (0, STATICV4(si)->gate.ifname);
+ XFREE (MTYPE_STATIC_IPV4, si);
}
-
- /* 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)
+#ifdef HAVE_IPV6
+ else if (afi == AFI_IP6)
{
- if (si->distance < cp->distance)
- break;
- if (si->distance > cp->distance)
- continue;
+ if (STATICV6(si)->ifname)
+ XFREE (0, STATICV6(si)->ifname);
+ XFREE (MTYPE_STATIC_IPV6, si);
}
-
- /* 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;
+#endif /* HAVE_IPV6 */
}
/* Delete static route from static route configuration. */
int
-static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- const char *ifname, u_char distance, u_int32_t vrf_id)
+static_delete (afi_t afi, safi_t safi, struct prefix *p, u_char type,
+ void *gate, const char *ifname, u_char distance,
+ u_int32_t vrf_id)
{
struct route_node *rn;
- struct static_ipv6 *si;
+ struct static_route_info *si;
struct route_table *stable;
/* Lookup table. */
- stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
+ stable = vrf_static_table (afi, safi, vrf_id);
if (! stable)
return -1;
+ if (type == 0 && afi == AFI_IP)
+ {
+ /* If type isn't given in IPv4, deduce it from args. */
+ type = static_ipv4_type (gate, ifname);
+ }
+
/* Lookup static route prefix. */
rn = route_node_lookup (stable, p);
if (! rn)
@@ -2215,10 +1837,14 @@ static_delete_ipv6 (struct prefix *p, u_
/* 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))
+ if (type == si->type
+ /* In IPv4 the behaviour is different, the distance
+ * isn't taken into account since only one entry
+ * will exist for this type/gate/ifname, adding
+ * a new entry with different distance will result
+ * in an update */
+ && (afi == AFI_IP || distance == si->distance)
+ && static_route_info_compare(afi, si, gate, ifname))
break;
/* Can't find static route. */
@@ -2228,8 +1854,8 @@ static_delete_ipv6 (struct prefix *p, u_
return 0;
}
- /* Install into rib. */
- static_uninstall_ipv6 (p, si);
+ /* Uninstall into rib. */
+ static_uninstall (afi, safi, p, si, vrf_id);
/* Unlink static route from linked list. */
if (si->prev)
@@ -2239,33 +1865,35 @@ static_delete_ipv6 (struct prefix *p, u_
if (si->next)
si->next->prev = si->prev;
- /* Free static route configuration. */
- if (ifname)
- XFREE (0, si->ifname);
- XFREE (MTYPE_STATIC_IPV6, si);
+ /* Unlock node after lookup */
+ route_unlock_node (rn);
+
+ /* Release the static_{ipv4,ipv6} route configuration */
+ static_route_info_release (afi, si);
+
+ /* Unlock node, releasing from table */
+ route_unlock_node (rn);
return 1;
}
-#endif /* HAVE_IPV6 */
-/* RIB update function. */
-void
-rib_update (void)
+static void
+rib_update_run_table (struct route_table *table)
{
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))
if (rn->info)
rib_queue_add (&zebrad, rn, NULL);
+}
- table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
- if (table)
- for (rn = route_top (table); rn; rn = route_next (rn))
- if (rn->info)
- rib_queue_add (&zebrad, rn, NULL);
+/* RIB update function. */
+void
+rib_update (void)
+{
+ rib_update_run_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
+ rib_update_run_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
}
/* Interface goes up. */
Index: zebra/zebra_vty.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/zebra_vty.c,v
retrieving revision 1.11
diff -u -p -w -b -r1.11 zebra_vty.c
--- zebra/zebra_vty.c 28 Jun 2005 17:17:12 -0000 1.11
+++ zebra/zebra_vty.c 21 Aug 2005 20:29:45 -0000
@@ -142,9 +142,11 @@ zebra_static_ipv4 (struct vty *vty, int
return CMD_WARNING;
}
if (add_cmd)
- static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, distance, 0);
+ static_add (AFI_IP, SAFI_UNICAST, &p, 0, NULL, NULL,
+ ZEBRA_FLAG_BLACKHOLE, distance, 0);
else
- static_delete_ipv4 (&p, NULL, NULL, distance, 0);
+ static_delete (AFI_IP, SAFI_UNICAST, &p, 0, NULL, NULL,
+ distance, 0);
return CMD_SUCCESS;
}
@@ -168,9 +170,9 @@ zebra_static_ipv4 (struct vty *vty, int
if (gate_str == NULL)
{
if (add_cmd)
- static_add_ipv4 (&p, NULL, NULL, flag, distance, 0);
+ static_add (AFI_IP, SAFI_UNICAST, &p, 0, NULL, NULL, flag, distance, 0);
else
- static_delete_ipv4 (&p, NULL, NULL, distance, 0);
+ static_delete (AFI_IP, SAFI_UNICAST, &p, 0, NULL, NULL, distance, 0);
return CMD_SUCCESS;
}
@@ -184,9 +186,11 @@ zebra_static_ipv4 (struct vty *vty, int
ifname = gate_str;
if (add_cmd)
- static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0);
+ static_add (AFI_IP, SAFI_UNICAST, &p, 0,
+ ifname ? NULL : &gate, ifname, flag, distance, 0);
else
- static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0);
+ static_delete (AFI_IP, SAFI_UNICAST, &p, 0,
+ ifname ? NULL : &gate, ifname, distance, 0);
return CMD_SUCCESS;
}
@@ -1195,9 +1199,11 @@ static_ipv6_func (struct vty *vty, int a
}
if (add_cmd)
- static_add_ipv6 (&p, type, gate, ifname, flag, distance, table);
+ static_add (AFI_IP6, SAFI_UNICAST, &p, type, gate,
+ ifname, flag, distance, table);
else
- static_delete_ipv6 (&p, type, gate, ifname, distance, table);
+ static_delete (AFI_IP6, SAFI_UNICAST, &p, type, gate,
+ ifname, distance, table);
return CMD_SUCCESS;
}
Index: zebra/zserv.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/zserv.c,v
retrieving revision 1.33
diff -u -p -w -b -r1.33 zserv.c
--- zebra/zserv.c 29 Jul 2005 14:36:00 -0000 1.33
+++ zebra/zserv.c 21 Aug 2005 20:29:46 -0000
@@ -514,7 +514,7 @@ zsend_ipv6_nexthop_lookup (struct zserv
struct nexthop *nexthop;
/* Lookup nexthop. */
- rib = rib_match_ipv6 (addr);
+ rib = rib_match (AFI_IP6, SAFI_UNICAST, addr, 0);
/* Get output stream. */
s = client->obuf;
@@ -579,7 +579,7 @@ zsend_ipv4_nexthop_lookup (struct zserv
struct nexthop *nexthop;
/* Lookup nexthop. */
- rib = rib_match_ipv4 (addr);
+ rib = rib_match (AFI_IP, SAFI_UNICAST, &addr, 0);
/* Get output stream. */
s = client->obuf;
@@ -638,7 +638,7 @@ zsend_ipv4_import_lookup (struct zserv *
struct nexthop *nexthop;
/* Lookup nexthop. */
- rib = rib_lookup_ipv4 (p);
+ rib = rib_lookup (AFI_IP, SAFI_UNICAST, (struct prefix *)p, 0);
/* Get output stream. */
s = client->obuf;
@@ -838,7 +838,7 @@ zread_ipv4_add (struct zserv *client, u_
if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
rib->metric = stream_getl (s);
- rib_add_ipv4_multipath (&p, rib);
+ rib_add_multipath (AFI_IP, SAFI_UNICAST, (struct prefix *)&p, rib, 0);
return 0;
}
@@ -911,7 +911,8 @@ zread_ipv4_delete (struct zserv *client,
else
api.metric = 0;
- rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex,
+ rib_delete (AFI_IP, SAFI_UNICAST, api.type, api.flags,
+ (struct prefix *)&p, &nexthop, ifindex,
client->rtm_table);
return 0;
}
@@ -998,10 +999,9 @@ zread_ipv6_add (struct zserv *client, u_
else
api.metric = 0;
- if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
- rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0);
- else
- rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0);
+ rib_add (AFI_IP6, SAFI_UNICAST, api.type, api.flags, (struct prefix *)&p,
+ IN6_IS_ADDR_UNSPECIFIED(&nexthop) ? NULL : &nexthop,
+ ifindex, 0, api.metric, api.distance);
return 0;
}
@@ -1062,10 +1062,8 @@ zread_ipv6_delete (struct zserv *client,
else
api.metric = 0;
- if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
- rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0);
- else
- rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0);
+ rib_delete (AFI_IP6, SAFI_UNICAST, api.type, api.flags, (struct prefix *)&p,
+ IN6_IS_ADDR_UNSPECIFIED (&nexthop) ? NULL : &nexthop, ifindex, 0);
return 0;
}
_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
http://lists.quagga.net/mailman/listinfo/quagga-dev
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic