summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2015-01-06 19:53:24 +0100
committerDavid Lamparter <equinox@opensourcerouting.org>2015-01-30 01:12:38 +0100
commit240c56f3a41cb7018460ba6e36c9b559c897e3d0 (patch)
tree76e7bd769f19a7544b05e0070cdf058a5739eedb /zebra/zebra_rib.c
parent29ce93ebf6427d1d64eae8b385e36873e3ddcb88 (diff)
downloadquagga-240c56f3a41cb7018460ba6e36c9b559c897e3d0.tar.bz2
quagga-240c56f3a41cb7018460ba6e36c9b559c897e3d0.tar.xz
zebra: make MRIB lookup behaviour switchable
depending on the usage scenario (and availability of multitopology IGP protocols, which is currently zero in Quagga), different approaches of Multicast RPF lookups are useful. Reference behaviours from commercial vendors are urib-only/mrib-only (Juniper, depending on inet.2 availability) and lowest-distance (Cisco). As we are currently without MT IGP support, mrib-first seems the most useful default for Quagga. Cc: Everton Marques <everton.marques@gmail.com> Cc: Balaji G <balajig81@gmail.com> Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index abef90fb..effe2338 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -75,6 +75,9 @@ static const struct
/* Vector for routing table. */
static vector vrf_vector;
+/* RPF lookup behaviour */
+static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG;
+
static void
_rnode_zlog(const char *_func, struct route_node *rn, int priority,
const char *msgfmt, ...)
@@ -782,6 +785,78 @@ rib_match_ipv4_safi (struct in_addr addr, safi_t safi, int skip_bgp,
}
struct rib *
+rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
+{
+ struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
+ struct route_node *m_rn = NULL, *u_rn = NULL;
+ int skip_bgp = 0; /* bool */
+
+ switch (ipv4_multicast_mode)
+ {
+ case MCAST_MRIB_ONLY:
+ return rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, rn_out);
+ case MCAST_URIB_ONLY:
+ return rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, rn_out);
+ case MCAST_NO_CONFIG:
+ case MCAST_MIX_MRIB_FIRST:
+ rib = mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
+ if (!mrib)
+ rib = urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
+ break;
+ case MCAST_MIX_DISTANCE:
+ mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
+ urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
+ if (mrib && urib)
+ rib = urib->distance < mrib->distance ? urib : mrib;
+ else if (mrib)
+ rib = mrib;
+ else if (urib)
+ rib = urib;
+ break;
+ case MCAST_MIX_PFXLEN:
+ mrib = rib_match_ipv4_safi (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
+ urib = rib_match_ipv4_safi (addr, SAFI_UNICAST, skip_bgp, &u_rn);
+ if (mrib && urib)
+ rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
+ else if (mrib)
+ rib = mrib;
+ else if (urib)
+ rib = urib;
+ break;
+ }
+
+ if (rn_out)
+ *rn_out = (rib == mrib) ? m_rn : u_rn;
+
+ if (IS_ZEBRA_DEBUG_RIB)
+ {
+ char buf[BUFSIZ];
+ inet_ntop (AF_INET, &addr, buf, BUFSIZ);
+
+ zlog_debug("%s: %s: found %s, using %s",
+ __func__, buf,
+ mrib ? (urib ? "MRIB+URIB" : "MRIB") :
+ urib ? "URIB" : "nothing",
+ rib == urib ? "URIB" : rib == mrib ? "MRIB" : "none");
+ }
+ return rib;
+}
+
+void
+multicast_mode_ipv4_set (enum multicast_mode mode)
+{
+ if (IS_ZEBRA_DEBUG_RIB)
+ zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode);
+ ipv4_multicast_mode = mode;
+}
+
+enum multicast_mode
+multicast_mode_ipv4_get (void)
+{
+ return ipv4_multicast_mode;
+}
+
+struct rib *
rib_lookup_ipv4 (struct prefix_ipv4 *p)
{
struct route_table *table;