From: Christian Franke Date: Mon, 5 Dec 2016 19:05:30 +0000 (+0100) Subject: zebra: add srcdest support to rib X-Git-Tag: frr-3.0-branchpoint~59^2~3 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=05737783711e7054ace797cea4f079f09193a8df;p=matthieu%2Ffrr.git zebra: add srcdest support to rib Add srcdest support to the zebra rib and to the kernel and redistribution interfaces. Signed-off-by: Christian Franke --- diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 896ca96b48..fea79ffe8c 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -32,7 +32,8 @@ #include "zebra/rt_netlink.h" #include "zebra/rib.h" -int kernel_route_rib (struct prefix *a, struct rib *old, struct rib *new) { return 0; } +int kernel_route_rib (struct prefix *a, struct prefix *b, + struct rib *old, struct rib *new) { return 0; } int kernel_address_add_ipv4 (struct interface *a, struct connected *b) { diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 435122cfe7..c7ed209d3c 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -31,6 +31,7 @@ #include "linklist.h" #include "log.h" #include "vrf.h" +#include "srcdest_table.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -98,7 +99,7 @@ zebra_redistribute_default (struct zserv *client, vrf_id_t vrf_id) RNODE_FOREACH_RIB (rn, newrib) if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) && newrib->distance != DISTANCE_INFINITY) - zsend_redistribute_route (1, client, &rn->p, newrib); + zsend_redistribute_route (1, client, &rn->p, NULL, newrib); route_unlock_node (rn); } @@ -122,12 +123,15 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, newrib) { + struct prefix *dst_p, *src_p; + srcdest_rnode_prefixes(rn, &dst_p, &src_p); + if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, " "zebra_check_addr=%d", __func__, CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), newrib->type, newrib->distance, - zebra_check_addr (&rn->p)); + zebra_check_addr (dst_p)); if (! CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)) continue; @@ -136,10 +140,10 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v continue; if (newrib->distance == DISTANCE_INFINITY) continue; - if (! zebra_check_addr (&rn->p)) + if (! zebra_check_addr (dst_p)) continue; - zsend_redistribute_route (1, client, &rn->p, newrib); + zsend_redistribute_route (1, client, dst_p, src_p, newrib); } } } @@ -147,7 +151,8 @@ zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t v /* Either advertise a route for redistribution to registered clients or */ /* withdraw redistribution if add cannot be done for client */ void -redistribute_update (struct prefix *p, struct rib *rib, struct rib *prev_rib) +redistribute_update (struct prefix *p, struct prefix *src_p, + struct rib *rib, struct rib *prev_rib) { struct listnode *node, *nnode; struct zserv *client; @@ -186,7 +191,7 @@ redistribute_update (struct prefix *p, struct rib *rib, struct rib *prev_rib) if (send_redistribute) { - zsend_redistribute_route (1, client, p, rib); + zsend_redistribute_route (1, client, p, src_p, rib); } else if (prev_rib && ((rib->instance && @@ -194,13 +199,13 @@ redistribute_update (struct prefix *p, struct rib *rib, struct rib *prev_rib) rib->instance)) || vrf_bitmap_check (client->redist[afi][prev_rib->type], rib->vrf_id))) { - zsend_redistribute_route (0, client, p, prev_rib); + zsend_redistribute_route (0, client, p, src_p, prev_rib); } } } void -redistribute_delete (struct prefix *p, struct rib *rib) +redistribute_delete (struct prefix *p, struct prefix *src_p, struct rib *rib) { struct listnode *node, *nnode; struct zserv *client; @@ -235,7 +240,7 @@ redistribute_delete (struct prefix *p, struct rib *rib) rib->instance)) || vrf_bitmap_check (client->redist[afi][rib->type], rib->vrf_id)) { - zsend_redistribute_route (0, client, p, rib); + zsend_redistribute_route (0, client, p, src_p, rib); } } } diff --git a/zebra/redistribute.h b/zebra/redistribute.h index e3bce7af46..06afc726d1 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -36,8 +36,9 @@ extern void zebra_redistribute_default_add (int, struct zserv *, int, extern void zebra_redistribute_default_delete (int, struct zserv *, int, struct zebra_vrf *zvrf); -extern void redistribute_update (struct prefix *, struct rib *, struct rib *); -extern void redistribute_delete (struct prefix *, struct rib *); +extern void redistribute_update (struct prefix *, struct prefix *, + struct rib *, struct rib *); +extern void redistribute_delete (struct prefix *, struct prefix *, struct rib *); extern void zebra_interface_up_update (struct interface *); extern void zebra_interface_down_update (struct interface *); diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c index 4446627dd3..ffde8ed773 100644 --- a/zebra/redistribute_null.c +++ b/zebra/redistribute_null.c @@ -39,9 +39,10 @@ void zebra_redistribute_default_delete (int a, struct zserv *b, int c, struct zebra_vrf *zvrf) { return; } -void redistribute_update (struct prefix *a, struct rib *b, struct rib *c) +void redistribute_update (struct prefix *a, struct prefix *b, + struct rib *c, struct rib *d) { return; } -void redistribute_delete (struct prefix *a, struct rib *b) +void redistribute_delete (struct prefix *a, struct prefix *b, struct rib *c) { return; } void zebra_interface_up_update (struct interface *a) diff --git a/zebra/rib.h b/zebra/rib.h index fceab93d1a..db56414416 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -32,6 +32,7 @@ #include "vrf.h" #include "if.h" #include "mpls.h" +#include "srcdest_table.h" #define DISTANCE_INFINITY 255 #define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */ @@ -311,8 +312,9 @@ extern enum multicast_mode multicast_mode_ipv4_get (void); extern int nexthop_has_fib_child(struct nexthop *); extern void rib_lookup_and_dump (struct prefix_ipv4 *, vrf_id_t); extern void rib_lookup_and_pushup (struct prefix_ipv4 *, vrf_id_t); -#define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib) +#define rib_dump(prefix, src, rib) _rib_dump(__func__, prefix, src, rib) extern void _rib_dump (const char *, + union prefix46constptr, union prefix46constptr, const struct rib *); extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, vrf_id_t); @@ -444,7 +446,7 @@ rib_dest_af (rib_dest_t *dest) static inline struct route_table * rib_dest_table (rib_dest_t *dest) { - return dest->rnode->table; + return srcdest_rnode_table(dest->rnode); } /* diff --git a/zebra/rt.h b/zebra/rt.h index 40beb6a45f..75d234ce83 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -29,7 +29,8 @@ #include "zebra/zebra_ns.h" #include "zebra/zebra_mpls.h" -extern int kernel_route_rib (struct prefix *, struct rib *, struct rib *); +extern int kernel_route_rib (struct prefix *, struct prefix *, + struct rib *, struct rib *); extern int kernel_address_add_ipv4 (struct interface *, struct connected *); extern int kernel_address_delete_ipv4 (struct interface *, struct connected *); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 585b80f979..17b5a6e6d8 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -134,18 +134,20 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, struct rtattr *tb[RTA_MAX + 1]; u_char flags = 0; struct prefix p; + struct prefix_ipv6 src_p; vrf_id_t vrf_id = VRF_DEFAULT; char anyaddr[16] = { 0 }; - int index; + int index = 0; int table; - int metric; + int metric = 0; u_int32_t mtu = 0; - void *dest; - void *gate; - void *src; + void *dest = NULL; + void *gate = NULL; + void *prefsrc = NULL; /* IPv4 preferred source host address */ + void *src = NULL; /* IPv6 srcdest source prefix */ rtm = NLMSG_DATA (h); @@ -168,9 +170,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_protocol == RTPROT_KERNEL) return 0; - if (rtm->rtm_src_len != 0) - return 0; - /* We don't care about change notifications for the MPLS table. */ /* TODO: Revisit this. */ if (rtm->rtm_family == AF_MPLS) @@ -195,12 +194,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_protocol == RTPROT_ZEBRA) flags |= ZEBRA_FLAG_SELFROUTE; - index = 0; - metric = 0; - dest = NULL; - gate = NULL; - src = NULL; - if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); @@ -209,8 +202,13 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, else dest = anyaddr; + if (tb[RTA_SRC]) + src = RTA_DATA (tb[RTA_SRC]); + else + src = anyaddr; + if (tb[RTA_PREFSRC]) - src = RTA_DATA (tb[RTA_PREFSRC]); + prefsrc = RTA_DATA (tb[RTA_PREFSRC]); if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); @@ -236,9 +234,12 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; + if (rtm->rtm_src_len != 0) + return 0; + if (!tb[RTA_MULTIPATH]) rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, NULL, gate, src, index, + 0, flags, &p, NULL, gate, prefsrc, index, table, metric, mtu, 0); else { @@ -280,9 +281,9 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (gate) { if (index) - rib_nexthop_ipv4_ifindex_add (rib, gate, src, index); + rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index); else - rib_nexthop_ipv4_add (rib, gate, src); + rib_nexthop_ipv4_add (rib, gate, prefsrc); } else rib_nexthop_ifindex_add (rib, index); @@ -305,8 +306,12 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, memcpy (&p.u.prefix6, dest, 16); p.prefixlen = rtm->rtm_dst_len; + src_p.family = AF_INET6; + memcpy (&src_p.prefix, src, 16); + src_p.prefixlen = rtm->rtm_src_len; + rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, NULL, gate, src, index, + 0, flags, &p, &src_p, gate, prefsrc, index, table, metric, mtu, 0); } @@ -326,14 +331,15 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, vrf_id_t vrf_id = VRF_DEFAULT; char anyaddr[16] = { 0 }; - int index; + int index = 0; int table; - int metric; + int metric = 0; u_int32_t mtu = 0; - void *dest; - void *gate; - void *src; + void *dest = NULL; + void *gate = NULL; + void *prefsrc = NULL; /* IPv4 preferred source host address */ + void *src = NULL; /* IPv6 srcdest source prefix */ rtm = NLMSG_DATA (h); @@ -354,12 +360,6 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_protocol == RTPROT_ZEBRA) SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE); - if (rtm->rtm_src_len != 0) - { - zlog_warn ("netlink_route_change(): no src len"); - return 0; - } - /* Table corresponding to route. */ if (tb[RTA_TABLE]) table = *(int *) RTA_DATA (tb[RTA_TABLE]); @@ -375,12 +375,6 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; } - index = 0; - metric = 0; - dest = NULL; - gate = NULL; - src = NULL; - if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); @@ -389,11 +383,16 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, else dest = anyaddr; + if (tb[RTA_SRC]) + src = RTA_DATA (tb[RTA_SRC]); + else + src = anyaddr; + if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); if (tb[RTA_PREFSRC]) - src = RTA_DATA (tb[RTA_PREFSRC]); + prefsrc = RTA_DATA (tb[RTA_PREFSRC]); if (h->nlmsg_type == RTM_NEWROUTE) { @@ -419,6 +418,13 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; + if (rtm->rtm_src_len != 0) + { + zlog_warn ("unsupported IPv4 sourcedest route (dest %s/%d)", + inet_ntoa (p.u.prefix4), p.prefixlen); + return 0; + } + if (IS_ZEBRA_DEBUG_KERNEL) { char buf[PREFIX_STRLEN]; @@ -431,8 +437,8 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, { if (!tb[RTA_MULTIPATH]) rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, 0, &p, NULL, gate, src, index, - table, metric, mtu, 0); + 0, 0, &p, NULL, gate, prefsrc, index, + table, metric, mtu, 0); else { /* This is a multipath route */ @@ -473,9 +479,9 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, if (gate) { if (index) - rib_nexthop_ipv4_ifindex_add (rib, gate, src, index); + rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index); else - rib_nexthop_ipv4_add (rib, gate, src); + rib_nexthop_ipv4_add (rib, gate, prefsrc); } else rib_nexthop_ifindex_add (rib, index); @@ -501,26 +507,35 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_family == AF_INET6) { struct prefix p; + struct prefix_ipv6 src_p; p.family = AF_INET6; memcpy (&p.u.prefix6, dest, 16); p.prefixlen = rtm->rtm_dst_len; + src_p.family = AF_INET6; + memcpy (&src_p.prefix, src, 16); + src_p.prefixlen = rtm->rtm_src_len; + if (IS_ZEBRA_DEBUG_KERNEL) { char buf[PREFIX_STRLEN]; - zlog_debug ("%s %s vrf %u", + char buf2[PREFIX_STRLEN]; + zlog_debug ("%s %s%s%s vrf %u", nl_msg_type_to_str (h->nlmsg_type), - prefix2str (&p, buf, sizeof(buf)), vrf_id); + prefix2str (&p, buf, sizeof(buf)), + src_p.prefixlen ? " from " : "", + src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", + vrf_id); } if (h->nlmsg_type == RTM_NEWROUTE) rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, 0, &p, NULL, gate, src, index, + 0, 0, &p, &src_p, gate, prefsrc, index, table, metric, mtu, 0); else rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, gate, index, table); + 0, zebra_flags, &p, &src_p, gate, index, table); } return 0; @@ -1233,8 +1248,8 @@ netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen /* Routing table change via netlink interface. */ /* Update flag indicates whether this is a "replace" or not. */ static int -netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, - int update) +netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, + struct rib *rib, int update) { int bytelen; struct sockaddr_nl snl; @@ -1268,6 +1283,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, req.n.nlmsg_type = cmd; req.r.rtm_family = family; req.r.rtm_dst_len = p->prefixlen; + req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; req.r.rtm_protocol = RTPROT_ZEBRA; req.r.rtm_scope = RT_SCOPE_UNIVERSE; @@ -1292,6 +1308,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, } addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); + if (src_p) + addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen); /* Metric. */ /* Hardcode the metric for all routes coming from zebra. Metric isn't used @@ -1559,14 +1577,15 @@ kernel_get_ipmr_sg_stats (void *in) } int -kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new) +kernel_route_rib (struct prefix *p, struct prefix *src_p, + struct rib *old, struct rib *new) { if (!old && new) - return netlink_route_multipath (RTM_NEWROUTE, p, new, 0); + return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0); if (old && !new) - return netlink_route_multipath (RTM_DELROUTE, p, old, 0); + return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0); - return netlink_route_multipath (RTM_NEWROUTE, p, new, 1); + return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1); } int diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index f65ec887dd..a4cc4eed06 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -182,7 +182,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib) { zlog_debug ("%s: %s: attention! gate not found for rib %p", __func__, prefix_buf, rib); - rib_dump (p, rib); + rib_dump (p, NULL, rib); } else inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); @@ -391,10 +391,17 @@ kernel_rtm (int cmd, struct prefix *p, struct rib *rib) } int -kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new) +kernel_route_rib (struct prefix *p, struct prefix *src_p, + struct rib *old, struct rib *new) { int route = 0; + if (src_p && src_p->prefixlen) + { + zlog (NULL, LOG_ERR, "route add: IPv6 sourcedest routes unsupported!"); + return 1; + } + if (zserv_privs.change(ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index d638ceab7f..b0b58b738c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -37,6 +37,7 @@ #include "nexthop.h" #include "vrf.h" #include "mpls.h" +#include "srcdest_table.h" #include "zebra/rib.h" #include "zebra/rt.h" @@ -88,7 +89,7 @@ static void __attribute__((format (printf, 5, 6))) _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int priority, const char *msgfmt, ...) { - char buf[PREFIX_STRLEN + 8]; + char buf[SRCDEST2STR_BUFFER + sizeof(" (MRIB)")]; char msgbuf[512]; va_list ap; @@ -98,9 +99,9 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int prior if (rn) { - rib_table_info_t *info = rn->table->info; + rib_table_info_t *info = srcdest_rnode_table_info (rn); + srcdest_rnode2str(rn, buf, sizeof(buf)); - prefix2str(&rn->p, buf, sizeof(buf)); if (info->safi == SAFI_MULTICAST) strcat(buf, " (MRIB)"); } @@ -1051,11 +1052,12 @@ static unsigned nexthop_active_check (struct route_node *rn, struct rib *rib, struct nexthop *nexthop, int set) { - rib_table_info_t *info = rn->table->info; struct interface *ifp; route_map_result_t ret = RMAP_MATCH; int family; - char buf[INET6_ADDRSTRLEN+1]; + char buf[SRCDEST2STR_BUFFER]; + struct prefix *p, *src_p; + srcdest_rnode_prefixes (rn, &p, &src_p); if (rn->p.family == AF_INET) family = AFI_IP; @@ -1119,8 +1121,8 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, /* XXX: What exactly do those checks do? Do we support * e.g. IPv4 routes with IPv6 nexthops or vice versa? */ if (RIB_SYSTEM_ROUTE(rib) || - (family == AFI_IP && rn->p.family != AF_INET) || - (family == AFI_IP6 && rn->p.family != AF_INET6)) + (family == AFI_IP && p->family != AF_INET) || + (family == AFI_IP6 && p->family != AF_INET6)) return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); /* The original code didn't determine the family correctly @@ -1130,20 +1132,25 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, * in every case. */ if (!family) - family = info->afi; + { + rib_table_info_t *info; + + info = srcdest_rnode_table_info(rn); + family = info->afi; + } memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); /* It'll get set if required inside */ - ret = zebra_route_map_check(family, rib->type, &rn->p, nexthop, rib->vrf_id, + ret = zebra_route_map_check(family, rib->type, p, nexthop, rib->vrf_id, rib->tag); if (ret == RMAP_DENYMATCH) { if (IS_ZEBRA_DEBUG_RIB) { - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)); - zlog_debug("%u:%s/%d: Filtering out with NH out %s due to route map", - rib->vrf_id, buf, rn->p.prefixlen, + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug("%u:%s: Filtering out with NH out %s due to route map", + rib->vrf_id, buf, ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); } UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -1216,8 +1223,11 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old) { int ret = 0; struct nexthop *nexthop, *tnexthop; - rib_table_info_t *info = rn->table->info; + rib_table_info_t *info = srcdest_rnode_table_info(rn); int recursing; + struct prefix *p, *src_p; + + srcdest_rnode_prefixes (rn, &p, &src_p); if (info->safi != SAFI_UNICAST) { @@ -1231,7 +1241,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old) * the kernel. */ zfpm_trigger_update (rn, "installing in kernel"); - ret = kernel_route_rib (&rn->p, old, rib); + ret = kernel_route_rib (p, src_p, old, rib); /* If install succeeds, update FIB flag for nexthops. */ if (!ret) @@ -1257,8 +1267,11 @@ rib_uninstall_kernel (struct route_node *rn, struct rib *rib) { int ret = 0; struct nexthop *nexthop, *tnexthop; - rib_table_info_t *info = rn->table->info; + rib_table_info_t *info = srcdest_rnode_table_info(rn); int recursing; + struct prefix *p, *src_p; + + srcdest_rnode_prefixes (rn, &p, &src_p); if (info->safi != SAFI_UNICAST) { @@ -1272,7 +1285,7 @@ rib_uninstall_kernel (struct route_node *rn, struct rib *rib) * the kernel. */ zfpm_trigger_update (rn, "uninstalling from kernel"); - ret = kernel_route_rib (&rn->p, rib, NULL); + ret = kernel_route_rib (p, src_p, rib, NULL); for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); @@ -1284,7 +1297,7 @@ rib_uninstall_kernel (struct route_node *rn, struct rib *rib) static void rib_uninstall (struct route_node *rn, struct rib *rib) { - rib_table_info_t *info = rn->table->info; + rib_table_info_t *info = srcdest_rnode_table_info(rn); if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB)) { @@ -1298,7 +1311,10 @@ rib_uninstall (struct route_node *rn, struct rib *rib) if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) { - redistribute_delete (&rn->p, rib); + struct prefix *p, *src_p; + srcdest_rnode_prefixes (rn, &p, &src_p); + + redistribute_delete (p, src_p, rib); UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED); } } @@ -1367,8 +1383,6 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct rib *new) { - char buf[INET6_ADDRSTRLEN]; - zfpm_trigger_update (rn, "new route selected"); /* Update real nexthop. This may actually determine if nexthop is active or not. */ @@ -1381,18 +1395,20 @@ rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, SET_FLAG (new->status, RIB_ENTRY_SELECTED_FIB); if (IS_ZEBRA_DEBUG_RIB) { - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Adding route rn %p, rib %p (type %d)", - zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type); + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug ("%u:%s: Adding route rn %p, rib %p (type %d)", + zvrf_id (zvrf), buf, rn, new, new->type); } if (!RIB_SYSTEM_ROUTE (new)) { if (rib_install_kernel (rn, new, NULL)) { - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - zlog_warn ("%u:%s/%d: Route install failed", - zvrf_id (zvrf), buf, rn->p.prefixlen); + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_warn ("%u:%s: Route install failed", + zvrf_id (zvrf), buf); } } @@ -1403,16 +1419,15 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct rib *old) { - char buf[INET6_ADDRSTRLEN]; - zfpm_trigger_update (rn, "removing existing route"); /* Uninstall from kernel. */ if (IS_ZEBRA_DEBUG_RIB) { - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d)", - zvrf_id (zvrf), buf, rn->p.prefixlen, rn, old, old->type); + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug ("%u:%s: Deleting route rn %p, rib %p (type %d)", + zvrf_id (zvrf), buf, rn, old, old->type); } if (!RIB_SYSTEM_ROUTE (old)) @@ -1429,15 +1444,11 @@ static void rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *old, struct rib *new) { - char buf[INET6_ADDRSTRLEN]; struct nexthop *nexthop = NULL, *tnexthop; int recursing; int nh_active = 0; int installed = 1; - if (IS_ZEBRA_DEBUG_RIB) - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - /* * We have to install or update if a new route has been selected or * something has changed. @@ -1459,23 +1470,25 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, { if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); if (new != old) - zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d) " - "old %p (type %d)", zvrf_id (zvrf), buf, rn->p.prefixlen, + zlog_debug ("%u:%s: Updating route rn %p, rib %p (type %d) " + "old %p (type %d)", zvrf_id (zvrf), buf, rn, new, new->type, old, old->type); else - zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d)", - zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type); + zlog_debug ("%u:%s: Updating route rn %p, rib %p (type %d)", + zvrf_id (zvrf), buf, rn, new, new->type); } /* Non-system route should be installed. */ if (!RIB_SYSTEM_ROUTE (new)) { if (rib_install_kernel (rn, new, old)) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); installed = 0; - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - zlog_warn ("%u:%s/%d: Route install failed", - zvrf_id (zvrf), buf, rn->p.prefixlen); + zlog_warn ("%u:%s: Route install failed", zvrf_id (zvrf), buf); } } @@ -1507,14 +1520,16 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, { if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); if (new != old) - zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) " - "old %p (type %d) - %s", zvrf_id (zvrf), buf, rn->p.prefixlen, + zlog_debug ("%u:%s: Deleting route rn %p, rib %p (type %d) " + "old %p (type %d) - %s", zvrf_id (zvrf), buf, rn, new, new->type, old, old->type, nh_active ? "install failed" : "nexthop inactive"); else - zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) - %s", - zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type, + zlog_debug ("%u:%s: Deleting route rn %p, rib %p (type %d) - %s", + zvrf_id (zvrf), buf, rn, new, new->type, nh_active ? "install failed" : "nexthop inactive"); } @@ -1613,9 +1628,11 @@ rib_process (struct route_node *rn) struct rib *old_fib = NULL; struct rib *new_fib = NULL; struct rib *best = NULL; - char buf[INET6_ADDRSTRLEN]; + char buf[SRCDEST2STR_BUFFER]; rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); vrf_id_t vrf_id = VRF_UNKNOWN; assert (rn); @@ -1628,17 +1645,17 @@ rib_process (struct route_node *rn) } if (IS_ZEBRA_DEBUG_RIB) - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); + srcdest_rnode2str(rn, buf, sizeof(buf)); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u:%s/%d: Processing rn %p", vrf_id, buf, rn->p.prefixlen, rn); + zlog_debug ("%u:%s: Processing rn %p", vrf_id, buf, rn); RNODE_FOREACH_RIB_SAFE (rn, rib, next) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u:%s/%d: Examine rib %p (type %d) status %x flags %x " + zlog_debug ("%u:%s: Examine rib %p (type %d) status %x flags %x " "dist %d metric %d", - vrf_id, buf, rn->p.prefixlen, rib, rib->type, rib->status, + vrf_id, buf, rib, rib->type, rib->status, rib->flags, rib->distance, rib->metric); UNSET_FLAG(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); @@ -1687,9 +1704,9 @@ rib_process (struct route_node *rn) if (rib != old_selected) { if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: %s/%d: imported via import-table but denied " + zlog_debug ("%s: %s: imported via import-table but denied " "by the ip protocol table route-map", - __func__, buf, rn->p.prefixlen); + __func__, buf); rib_unlink (rn, rib); } else @@ -1740,8 +1757,8 @@ rib_process (struct route_node *rn) if (IS_ZEBRA_DEBUG_RIB_DETAILED) { - zlog_debug ("%u:%s/%d: After processing: old_selected %p new_selected %p old_fib %p new_fib %p", - vrf_id, buf, rn->p.prefixlen, + zlog_debug ("%u:%s: After processing: old_selected %p new_selected %p old_fib %p new_fib %p", + vrf_id, buf, (void *)old_selected, (void *)new_selected, (void *)old_fib, @@ -1789,7 +1806,7 @@ rib_process (struct route_node *rn) if (old_selected) { if (!new_selected) - redistribute_delete(&rn->p, old_selected); + redistribute_delete(p, src_p, old_selected); if (old_selected != new_selected) UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED); } @@ -1798,7 +1815,7 @@ rib_process (struct route_node *rn) { /* Install new or replace existing redistributed entry */ SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED); - redistribute_update (&rn->p, new_selected, old_selected); + redistribute_update (p, src_p, new_selected, old_selected); } } @@ -2006,7 +2023,6 @@ process_subq (struct list * subq, u_char qindex) { struct listnode *lnode = listhead (subq); struct route_node *rnode; - char buf[INET6_ADDRSTRLEN]; rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; @@ -2022,9 +2038,10 @@ process_subq (struct list * subq, u_char qindex) if (IS_ZEBRA_DEBUG_RIB_DETAILED) { - inet_ntop (rnode->p.family, &rnode->p.u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: rn %p dequeued from sub-queue %u", - zvrf ? zvrf_id (zvrf) : 0, buf, rnode->p.prefixlen, rnode, qindex); + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rnode, buf, sizeof(buf)); + zlog_debug ("%u:%s: rn %p dequeued from sub-queue %u", + zvrf ? zvrf_id (zvrf) : 0, buf, rnode, qindex); } if (rnode->info) @@ -2405,13 +2422,10 @@ rib_delnode (struct route_node *rn, struct rib *rib) /* Just clean up if non main table */ if (IS_ZEBRA_DEBUG_RIB) { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Freeing route rn %p, rib %p (type %d)", - rib->vrf_id, buf, rn->p.prefixlen, rn, rib, rib->type); - } + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug ("%u:%s: Freeing route rn %p, rib %p (type %d)", + rib->vrf_id, buf, rn, rib, rib->type); } rib_unlink(rn, rib); @@ -2428,15 +2442,23 @@ rib_delnode (struct route_node *rn, struct rib *rib) */ void _rib_dump (const char * func, - union prefix46constptr pp, const struct rib * rib) + union prefix46constptr pp, + union prefix46constptr src_pp, + const struct rib * rib) { const struct prefix *p = pp.p; + const struct prefix *src_p = src_pp.p; + bool is_srcdst = src_p && src_p->prefixlen; char straddr[PREFIX_STRLEN]; + char srcaddr[PREFIX_STRLEN]; struct nexthop *nexthop, *tnexthop; int recursing; - zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (const void *)rib, - prefix2str(pp, straddr, sizeof(straddr)), rib->vrf_id); + zlog_debug ("%s: dumping RIB entry %p for %s%s%s vrf %u", func, (const void *)rib, + prefix2str(pp, straddr, sizeof(straddr)), + is_srcdst ? " from " : "", + is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr)) : "", + rib->vrf_id); zlog_debug ( "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", @@ -2527,7 +2549,7 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p, vrf_id_t vrf_id) (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"), (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected") ); - rib_dump (p, rib); + rib_dump (p, NULL, rib); } } @@ -2574,7 +2596,7 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id) char buf[PREFIX_STRLEN]; zlog_debug ("%u:%s: freeing way for connected prefix", rib->vrf_id, prefix2str(&rn->p, buf, sizeof(buf))); - rib_dump (&rn->p, rib); + rib_dump (&rn->p, NULL, rib); } rib_uninstall (rn, rib); } @@ -2602,6 +2624,8 @@ rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, else family = AFI_IP6; + assert(!src_p || family == AFI_IP6); + /* Lookup table. */ table = zebra_vrf_table_with_table_id (family, safi, rib->vrf_id, rib->table); if (! table) @@ -2609,6 +2633,8 @@ rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, /* Make it sure prefixlen is applied to the prefix. */ apply_mask (p); + if (src_p) + apply_mask_ipv6 (src_p); /* Set default distance by route type. */ if (rib->distance == 0) @@ -2622,7 +2648,7 @@ rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, } /* Lookup route node.*/ - rn = route_node_get (table, p); + rn = srcdest_rnode_get (table, p, src_p); /* If same type of route are installed, treat it as a implicit withdraw. */ @@ -2645,18 +2671,11 @@ rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, /* Link new rib to node.*/ 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) " - "existing %p", - rib->vrf_id, buf, p->prefixlen, (void *)rn, - (void *)rib, rib->type, (void *)same); - } + rnode_debug(rn, rib->vrf_id, "Inserting route rn %p, rib %p (type %d) existing %p", + (void *)rn, (void *)rib, rib->type, (void *)same); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump ((struct prefix *)p, rib); + rib_dump (p, src_p, rib); } rib_addnode (rn, rib, 1); ret = 1; @@ -2684,9 +2703,10 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, struct rib *same = NULL; struct nexthop *nexthop, *tnexthop; int recursing; - char buf1[PREFIX_STRLEN]; char buf2[INET6_ADDRSTRLEN]; + assert(!src_p || afi == AFI_IP6); + /* Lookup table. */ table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); if (! table) @@ -2694,14 +2714,26 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, /* Apply mask. */ apply_mask (p); + if (src_p) + apply_mask_ipv6 (src_p); /* Lookup route node. */ - rn = route_node_lookup (table, p); + rn = srcdest_rnode_lookup (table, p, src_p); if (! rn) { + char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; + + prefix2str(p, dst_buf, sizeof(dst_buf)); + if (src_p && src_p->prefixlen) + prefix2str(src_p, src_buf, sizeof(src_buf)); + else + src_buf[0] = '\0'; + if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s: doesn't exist in rib", - vrf_id, prefix2str (p, buf1, sizeof(buf1))); + zlog_debug ("%u:%s%s%s doesn't exist in rib", + vrf_id, dst_buf, + (src_buf[0] != '\0') ? " from " : "", + src_buf); return ZEBRA_ERR_RTNOEXIST; } @@ -2761,10 +2793,8 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, { if (IS_ZEBRA_DEBUG_RIB) { - zlog_debug ("%u:%s: rn %p, rib %p (type %d) was deleted " - "from kernel, adding", - vrf_id, prefix2str(p, buf1, INET6_ADDRSTRLEN), - rn, fib, fib->type); + rnode_debug (rn, vrf_id, "rn %p, rib %p (type %d) was deleted from kernel, adding", + rn, fib, fib->type); } if (allow_delete) { @@ -2786,15 +2816,13 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, if (IS_ZEBRA_DEBUG_RIB) { if (gate) - zlog_debug ("%u:%s: via %s ifindex %d type %d " + rnode_debug(rn, vrf_id, "via %s ifindex %d type %d " "doesn't exist in rib", - vrf_id, prefix2str (p, buf1, sizeof(buf1)), - inet_ntop (family2afi(afi), gate, buf2, INET_ADDRSTRLEN), + inet_ntop (family2afi(afi), gate, buf2, INET_ADDRSTRLEN), /* FIXME */ ifindex, type); else - zlog_debug ("%u:%s: ifindex %d type %d doesn't exist in rib", - vrf_id, prefix2str (p, buf1, sizeof(buf1)), + rnode_debug (rn, vrf_id, "ifindex %d type %d doesn't exist in rib", ifindex, type); } @@ -2826,6 +2854,8 @@ rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, struct route_node *rn; struct nexthop *nexthop; + assert(!src_p || afi == AFI_IP6); + /* Lookup table. */ table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); if (! table) @@ -2833,6 +2863,8 @@ rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, /* Make sure mask is applied. */ apply_mask (p); + if (src_p) + apply_mask_ipv6 (src_p); /* Set default distance by route type. */ if (distance == 0) @@ -2848,7 +2880,7 @@ rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, } /* Lookup route node.*/ - rn = route_node_get (table, p); + rn = srcdest_rnode_get (table, p, src_p); /* If same type of route are installed, treat it as a implicit withdraw. */ @@ -2920,18 +2952,11 @@ rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, /* Link new rib to node.*/ 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) " - "existing %p", - vrf_id, buf, p->prefixlen, (void *)rn, - (void *)rib, rib->type, (void *)same); - } + rnode_debug (rn, vrf_id, "Inserting route rn %p, rib %p (type %d) existing %p", + (void *)rn, (void *)rib, rib->type, (void *)same); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rib_dump (p, rib); + rib_dump (p, src_p, rib); } rib_addnode (rn, rib, 1); @@ -2953,7 +2978,7 @@ rib_update_table (struct route_table *table, rib_update_event_t event) /* Walk all routes and queue for processing, if appropriate for * the trigger event. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) { switch (event) { @@ -3029,7 +3054,7 @@ rib_weed_table (struct route_table *table) struct rib *next; if (table) - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) { if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) @@ -3066,7 +3091,7 @@ rib_sweep_table (struct route_table *table) int ret = 0; if (table) - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) { if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) @@ -3107,7 +3132,7 @@ rib_score_proto_table (u_char proto, u_short instance, struct route_table *table unsigned long n = 0; if (table) - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) { if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) @@ -3118,7 +3143,6 @@ rib_score_proto_table (u_char proto, u_short instance, struct route_table *table n++; } } - return n; } @@ -3147,7 +3171,7 @@ rib_close_table (struct route_table *table) struct rib *rib; if (table) - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB)) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 7d104f30d9..33f0a2bd72 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -328,13 +328,13 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ rib_install_kernel (rn, rib, rib); /* Update redistribution if it's selected */ if (CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED)) - redistribute_update (&rn->p, rib, NULL); + redistribute_update (&rn->p, NULL, rib, NULL); } else { /* Remove from redistribute if selected route becomes inactive */ if (CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED)) - redistribute_delete (&rn->p, rib); + redistribute_delete (&rn->p, NULL, rib); /* Remove from kernel if fib route becomes inactive */ if (CHECK_FLAG(rib->status, RIB_ENTRY_SELECTED_FIB)) rib_uninstall_kernel (rn, rib); diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 929743859e..bc86e4a10b 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -25,6 +25,7 @@ #include "linklist.h" #include "command.h" #include "memory.h" +#include "srcdest_table.h" #include "vty.h" #include "zebra/debug.h" @@ -331,8 +332,7 @@ zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, } static void -zebra_rtable_node_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *node) +zebra_rtable_node_cleanup (struct route_table *table, struct route_node *node) { struct rib *rib, *next; @@ -341,8 +341,6 @@ zebra_rtable_node_destroy (route_table_delegate_t *delegate, if (node->info) XFREE (MTYPE_RIB_DEST, node->info); - - route_node_destroy (delegate, table, node); } static void @@ -362,30 +360,17 @@ zebra_stable_node_destroy (route_table_delegate_t *delegate, } static void -zebra_rnhtable_node_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *node) +zebra_rnhtable_node_cleanup (struct route_table *table, struct route_node *node) { if (node->info) zebra_free_rnh (node->info); - - route_node_destroy (delegate, table, node); } -route_table_delegate_t zebra_rtable_delegate = { - .create_node = route_node_create, - .destroy_node = zebra_rtable_node_destroy -}; - route_table_delegate_t zebra_stable_delegate = { .create_node = route_node_create, .destroy_node = zebra_stable_node_destroy }; -route_table_delegate_t zebra_rnhtable_delegate = { - .create_node = route_node_create, - .destroy_node = zebra_rnhtable_node_destroy -}; - /* * Create a routing table for the specific AFI/SAFI in the given VRF. */ @@ -397,7 +382,11 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) assert (!zvrf->table[afi][safi]); - table = route_table_init_with_delegate (&zebra_rtable_delegate); + if (afi == AFI_IP6) + table = srcdest_table_init(); + else + table = route_table_init(); + table->cleanup = zebra_rtable_node_cleanup; zvrf->table[afi][safi] = table; info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); @@ -414,6 +403,7 @@ zebra_vrf_alloc (void) struct zebra_vrf *zvrf; afi_t afi; safi_t safi; + struct route_table *table; zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); @@ -426,10 +416,13 @@ zebra_vrf_alloc (void) route_table_init_with_delegate (&zebra_stable_delegate); } - zvrf->rnh_table[afi] = - route_table_init_with_delegate (&zebra_rnhtable_delegate); - zvrf->import_check_table[afi] = - route_table_init_with_delegate (&zebra_rnhtable_delegate); + table = route_table_init(); + table->cleanup = zebra_rnhtable_node_cleanup; + zvrf->rnh_table[afi] = table; + + table = route_table_init(); + table->cleanup = zebra_rnhtable_node_cleanup; + zvrf->import_check_table[afi] = table; } zebra_mpls_init_tables (zvrf); @@ -509,7 +502,7 @@ zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id) { if (zvrf->other_table[afi][table_id] == NULL) { - table = route_table_init(); + table = (afi == AFI_IP6) ? srcdest_table_init() : route_table_init(); info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); info->zvrf = zvrf; info->afi = afi; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index f075677575..bba0571c9e 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -32,6 +32,7 @@ #include "vrf.h" #include "mpls.h" #include "routemap.h" +#include "srcdest_table.h" #include "zebra/zserv.h" #include "zebra/zebra_vrf.h" @@ -639,7 +640,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) struct rib *rib; struct nexthop *nexthop, *tnexthop; int recursing; - char buf[PREFIX_STRLEN]; + char buf[SRCDEST2STR_BUFFER]; struct zebra_vrf *zvrf; RNODE_FOREACH_RIB (rn, rib) @@ -647,14 +648,14 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) const char *mcast_info = ""; if (mcast) { - rib_table_info_t *info = rn->table->info; + rib_table_info_t *info = srcdest_rnode_table_info(rn); mcast_info = (info->safi == SAFI_MULTICAST) ? " using Multicast RIB" : " using Unicast RIB"; } vty_out (vty, "Routing entry for %s%s%s", - prefix2str (&rn->p, buf, sizeof(buf)), mcast_info, + srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info, VTY_NEWLINE); vty_out (vty, " Known via \"%s", zebra_route_string (rib->type)); if (rib->instance) @@ -797,7 +798,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, struct nexthop *nexthop, *tnexthop; int recursing; int len = 0; - char buf[BUFSIZ]; + char buf[SRCDEST2STR_BUFFER]; json_object *json_nexthops = NULL; json_object *json_nexthop = NULL; json_object *json_route = NULL; @@ -807,7 +808,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, json_route = json_object_new_object(); json_nexthops = json_object_new_array(); - json_object_string_add(json_route, "prefix", prefix2str (&rn->p, buf, sizeof buf)); + json_object_string_add(json_route, "prefix", srcdest_rnode2str (rn, buf, sizeof buf)); json_object_string_add(json_route, "protocol", zebra_route_string(rib->type)); if (rib->instance) @@ -951,7 +952,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, ? '>' : ' ', CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ', - prefix2str (&rn->p, buf, sizeof buf)); + srcdest_rnode2str (rn, buf, sizeof buf)); /* Distance and metric display. */ if (rib->type != ZEBRA_ROUTE_CONNECT @@ -1665,7 +1666,7 @@ vty_show_ip_route_summary (struct vty *vty, struct route_table *table) memset (&rib_cnt, 0, sizeof(rib_cnt)); memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { is_ibgp = (rib->type == ZEBRA_ROUTE_BGP && @@ -1741,7 +1742,7 @@ vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) memset (&rib_cnt, 0, sizeof(rib_cnt)); memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { @@ -2767,7 +2768,7 @@ DEFUN (show_ipv6_route, int first = 1; vrf_id_t vrf_id = VRF_DEFAULT; struct zebra_vrf *zvrf = NULL; - char buf[BUFSIZ]; + char buf[SRCDEST2STR_BUFFER]; json_object *json = NULL; json_object *json_prefix = NULL; @@ -2811,7 +2812,7 @@ DEFUN (show_ipv6_route, json = json_object_new_object(); /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) { RNODE_FOREACH_RIB (rn, rib) { @@ -2822,7 +2823,7 @@ DEFUN (show_ipv6_route, if (json_prefix) { - prefix2str (&rn->p, buf, sizeof buf); + srcdest_rnode2str (rn, buf, sizeof buf); json_object_object_add(json, buf, json_prefix); json_prefix = NULL; } @@ -2834,7 +2835,7 @@ DEFUN (show_ipv6_route, else { /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) { RNODE_FOREACH_RIB (rn, rib) { @@ -2887,7 +2888,7 @@ DEFUN (show_ipv6_route_tag, return CMD_SUCCESS; /* Show all IPv6 routes with matching tag value. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { if (rib->tag != tag) @@ -2942,17 +2943,22 @@ DEFUN (show_ipv6_route_prefix_longer, return CMD_SUCCESS; /* Show matched type IPv6 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) - if (prefix_match (&p, &rn->p)) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib, NULL); - } + { + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); + + if (prefix_match (p, &rn->p)) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib, NULL); + } + } return CMD_SUCCESS; } @@ -2990,7 +2996,7 @@ DEFUN (show_ipv6_route_protocol, return CMD_SUCCESS; /* Show matched type IPv6 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) if (rib->type == type) { @@ -3180,7 +3186,7 @@ DEFUN (show_ipv6_mroute, return CMD_SUCCESS; /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { if (first) @@ -3217,7 +3223,7 @@ DEFUN (show_ipv6_route_vrf_all, continue; /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { if (first) @@ -3269,7 +3275,7 @@ DEFUN (show_ipv6_route_vrf_all_tag, continue; /* Show all IPv6 routes with matching tag value. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { if (rib->tag != tag) @@ -3329,23 +3335,27 @@ DEFUN (show_ipv6_route_vrf_all_prefix_longer, continue; /* Show matched type IPv6 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) - if (prefix_match (&p, &rn->p)) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - - if (vrf_header) + { + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); + if (prefix_match (p, &rn->p)) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); - vrf_header = 0; + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + + if (vrf_header) + { + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); + vrf_header = 0; + } + vty_show_ip_route (vty, rn, rib, NULL); } - vty_show_ip_route (vty, rn, rib, NULL); - } + } vrf_header = 1; } @@ -3386,7 +3396,7 @@ DEFUN (show_ipv6_route_vrf_all_protocol, continue; /* Show matched type IPv6 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) if (rib->type == type) { @@ -3539,7 +3549,7 @@ DEFUN (show_ipv6_mroute_vrf_all, continue; /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = route_next (rn)) + for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { if (first) diff --git a/zebra/zserv.c b/zebra/zserv.c index fd40ed123b..9749efb75d 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -601,7 +601,7 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp) */ int zsend_redistribute_route (int add, struct zserv *client, struct prefix *p, - struct rib *rib) + struct prefix *src_p, struct rib *rib) { afi_t afi; int cmd; @@ -667,6 +667,14 @@ zsend_redistribute_route (int add, struct zserv *client, struct prefix *p, stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->u.prefix, psize); + if (src_p) + { + SET_FLAG (zapi_flags, ZAPI_MESSAGE_SRCPFX); + psize = PSIZE (src_p->prefixlen); + stream_putc (s, src_p->prefixlen); + stream_write (s, (u_char *) & src_p->u.prefix, psize); + } + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { /* We don't send any nexthops when there's a multipath */ diff --git a/zebra/zserv.h b/zebra/zserv.h index d17a28eb6a..a5a9979468 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -162,7 +162,7 @@ extern void nbr_connected_add_ipv6 (struct interface *, struct in6_addr *); extern void nbr_connected_delete_ipv6 (struct interface *, struct in6_addr *); extern int zsend_interface_update (int, struct zserv *, struct interface *); extern int zsend_redistribute_route (int, struct zserv *, struct prefix *, - struct rib *); + struct prefix *, struct rib *); extern int zsend_router_id_update (struct zserv *, struct prefix *, vrf_id_t); extern int zsend_interface_vrf_update (struct zserv *, struct interface *,