[Xorp-hackers] [RFC 1/3] static-mcast: Support multicast address distances.

greearb at candelatech.com greearb at candelatech.com
Mon Jul 9 12:04:16 PDT 2012


From: Ben Greear <greearb at candelatech.com>

Add RIB-like behaviour for multicast addresses in
the MFEA logic.  This will allow static multicast
routes to over-ride dynamic routes, for instance.

PIM currently always uses distance of 1, so if
static uses 0, it will win.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 xorp/fea/mfea_node.cc               |  280 +++++++++++++++++++++++++++++++---
 xorp/fea/mfea_node.hh               |   74 ++++++++--
 xorp/fea/xrl_fea_node.hh            |    5 -
 xorp/fea/xrl_mfea_node.cc           |  107 ++++++++-----
 xorp/fea/xrl_mfea_node.hh           |   23 ++-
 xorp/pim/xrl_pim_node.cc            |    2 +
 xorp/xrl/interfaces/mfea.xif        |   27 +++-
 xorp/xrl/interfaces/mfea_client.xif |    1 -
 xorp/xrl/interfaces/pim.xif         |    2 -
 9 files changed, 423 insertions(+), 98 deletions(-)

diff --git a/xorp/fea/mfea_node.cc b/xorp/fea/mfea_node.cc
index ea65ede..a54de56 100644
--- a/xorp/fea/mfea_node.cc
+++ b/xorp/fea/mfea_node.cc
@@ -42,6 +42,29 @@
 #include "mfea_vif.hh"
 
 
+MfeaRouteStorage::MfeaRouteStorage(uint32_t d, const string module_name, const IPvX& _source,
+				   const IPvX& _group, const string& _iif_name, const string& _oif_names) :
+	distance(d), is_binary(false), module_instance_name(module_name), source(_source),
+	group(_group), iif_name(_iif_name), oif_names(_oif_names) { }
+
+MfeaRouteStorage::MfeaRouteStorage(uint32_t d, const string module_name, const IPvX& _source,
+				   const IPvX& _group, uint32_t iif_vif_idx,
+				   const Mifset& _oiflist, const Mifset& _oif_disable_wrongvif,
+				   uint32_t max_vifs, const IPvX& _rp_addr) :
+	distance(d), is_binary(true), module_instance_name(module_name), source(_source),
+	group(_group), iif_vif_index(iif_vif_idx), oiflist(_oiflist),
+	oiflist_disable_wrongvif(_oif_disable_wrongvif), max_vifs_oiflist(max_vifs),
+	rp_addr(_rp_addr) { }
+
+MfeaRouteStorage::MfeaRouteStorage(const MfeaRouteStorage& o) :
+	distance(o.distance), is_binary(true), module_instance_name(o.module_instance_name),
+	source(o.source), group(o.group), iif_name(o.iif_name),
+	oif_names(o.oif_names), iif_vif_index(o.iif_vif_index),
+	oiflist(o.oiflist), oiflist_disable_wrongvif(o.oiflist_disable_wrongvif),
+	max_vifs_oiflist(o.max_vifs_oiflist), rp_addr(o.rp_addr) { }
+
+MfeaRouteStorage::MfeaRouteStorage() : distance(0), is_binary(false), max_vifs_oiflist(0) { }
+
 /**
  * MfeaNode::MfeaNode:
  * @fea_node: The corresponding FeaNode.
@@ -1816,10 +1839,106 @@ MfeaNode::signal_dataflow_message_recv(const IPvX& source, const IPvX& group,
     return (XORP_OK);
 }
 
+int MfeaNode::add_mfc_str(const string& module_instance_name,
+			  const IPvX& source,
+			  const IPvX& group,
+			  const string& iif_name,
+			  const string& oif_names,
+			  uint32_t distance,
+			  string& error_msg, bool check_stored_routes) {
+    int rv;
+    uint32_t iif_vif_index;
+
+    XLOG_INFO("MFEA add_mfc_str, module: %s  source: %s  group: %s check-stored-routes: %i distance: %u",
+	      module_instance_name.c_str(), source.str().c_str(),
+	      group.str().c_str(), (int)(check_stored_routes), distance);
+
+    if (distance >= MAX_MFEA_DISTANCE) {
+	error_msg += c_format("distance is above maximimum: %u >= %u\n",
+			      distance, MAX_MFEA_DISTANCE);
+	return XORP_ERROR;
+    }
+
+    if (check_stored_routes) {
+	MfeaRouteStorage mrs(distance, module_instance_name, source,
+			     group, iif_name, oif_names);
+	routes[mrs.distance][mrs.getHash()] = mrs;
+
+	// If any lower distance routes are already in place, do nothing and
+	// return.
+	if (mrs.distance > 0) {
+	    for (unsigned int i = mrs.distance - 1; i > 0; i--) {
+		map<string, MfeaRouteStorage>::const_iterator iter = routes[i].find(mrs.getHash());
+		if (iter != routes[i].end()) {
+		    XLOG_INFO("Lower-distance mfea route exists, distance: %i source: %s  group: %s",
+			      i, source.str().c_str(), group.str().c_str());
+		    return XORP_OK;
+		}
+	    }
+	}
+
+	// If any higher distance routes are already in place, remove them from kernel.
+	for (unsigned int i = mrs.distance + 1; i<MAX_MFEA_DISTANCE; i++) {
+	    map<string, MfeaRouteStorage>::const_iterator iter = routes[i].find(mrs.getHash());
+	    if (iter != routes[i].end()) {
+		XLOG_INFO("Removing higher-distance mfea route, distance: %i source: %s  group: %s",
+			  i, source.str().c_str(), group.str().c_str());
+		delete_mfc(iter->second.module_instance_name, iter->second.source,
+			   iter->second.group, error_msg, false);
+		break;
+	    }
+	}
+    }
+
+    // Convert strings to mfc binary stuff and pass to
+    // add_mfc()
+    MfeaVif *mfea_vif = vif_find_by_name(iif_name);
+    if (!mfea_vif) {
+	error_msg = "Could not find iif-interface: " + iif_name;
+	return XORP_ERROR;
+    }
+    iif_vif_index = mfea_vif->vif_index();
+
+    Mifset oiflist;
+    Mifset oiflist_disable_wrongvif;
+    istringstream iss(oif_names);
+    string t;
+    while (!(iss.eof() || iss.fail())) {
+	iss >> t;
+	if (t.size() == 0)
+	    break;
+	mfea_vif = vif_find_by_name(t);
+	if (!mfea_vif) {
+	    error_msg = "Could not find oif-interface: " + t;
+	    return XORP_ERROR;
+	}
+	uint32_t vi = mfea_vif->vif_index();
+	if (vi < MAX_VIFS) {
+	    oiflist.set(vi);
+	}
+	else {
+	    error_msg = c_format("Vif %s has invalid vif_index: %u",
+				 mfea_vif->ifname().c_str(), vi);
+	    return XORP_ERROR;
+	}
+    }
+
+    IPvX rp_addr;
+
+    rv = add_mfc(module_instance_name, source, group,
+		 iif_vif_index, oiflist,
+		 oiflist_disable_wrongvif,
+		 MAX_VIFS, rp_addr, distance, error_msg, false);
+    if (rv != XORP_OK) {
+	error_msg = "call to add_mfc failed";
+    }
+    return rv;
+}
+
 /**
  * MfeaNode::add_mfc:
  * @module_instance_name: The module instance name of the protocol that adds
- * the MFC.
+ *       the MFC.
  * @source: The source address.
  * @group: The group address.
  * @iif_vif_index: The vif index of the incoming interface.
@@ -1827,7 +1946,7 @@ MfeaNode::signal_dataflow_message_recv(const IPvX& source, const IPvX& group,
  * @oiflist_disable_wrongvif: The bitset with the outgoing interfaces to
  * disable the WRONGVIF signal.
  * @max_vifs_oiflist: The number of vifs covered by @oiflist
- * or @oiflist_disable_wrongvif.
+ *        or @oiflist_disable_wrongvif.
  * @rp_addr: The RP address.
  * 
  * Add Multicast Forwarding Cache (MFC) to the kernel.
@@ -1835,24 +1954,78 @@ MfeaNode::signal_dataflow_message_recv(const IPvX& source, const IPvX& group,
  * Return value: %XORP_OK on success, otherwise %XORP_ERROR.
  **/
 int
-MfeaNode::add_mfc(const string& , // module_instance_name,
+MfeaNode::add_mfc(const string& module_instance_name,
 		  const IPvX& source, const IPvX& group,
 		  uint32_t iif_vif_index, const Mifset& oiflist,
 		  const Mifset& oiflist_disable_wrongvif,
 		  uint32_t max_vifs_oiflist,
-		  const IPvX& rp_addr)
+		  const IPvX& rp_addr, uint32_t distance,
+		  string& error_msg,
+		  bool check_stored_routes)
 {
     uint8_t oifs_ttl[MAX_VIFS];
     uint8_t oifs_flags[MAX_VIFS];
-    
-    if (max_vifs_oiflist > MAX_VIFS)
-	return (XORP_ERROR);
+
+    XLOG_INFO("MFEA add_mfc, module: %s  source: %s  group: %s check-stored-routes: %i distance: %u",
+	      module_instance_name.c_str(), source.str().c_str(),
+	      group.str().c_str(), (int)(check_stored_routes), distance);
+
+    if (distance >= MAX_MFEA_DISTANCE) {
+	error_msg += c_format("distance is above maximimum: %u >= %u\n",
+			      distance, MAX_MFEA_DISTANCE);
+	return XORP_ERROR;
+    }
+
+    if (max_vifs_oiflist > MAX_VIFS) {
+	error_msg += c_format("max-vifs-oiflist: %u > MAX_VIFS: %u\n",
+			      max_vifs_oiflist, MAX_VIFS);
+	return XORP_ERROR;
+    }
     
     // Check the iif
-    if (iif_vif_index == Vif::VIF_INDEX_INVALID)
-	return (XORP_ERROR);
-    if (iif_vif_index >= max_vifs_oiflist)
-	return (XORP_ERROR);
+    if (iif_vif_index == Vif::VIF_INDEX_INVALID) {
+	error_msg += "iif_vif_index is VIF_INDEX_INVALID\n";
+	return XORP_ERROR;
+    }
+
+    if (iif_vif_index >= max_vifs_oiflist) {
+	error_msg += c_format("iif_vif_index: %u >= max-vifs-oiflist: %u\n",
+			      iif_vif_index, max_vifs_oiflist);
+	return XORP_ERROR;
+    }
+
+    if (check_stored_routes) {
+	MfeaRouteStorage mrs(distance, module_instance_name, source,
+			     group, iif_vif_index, oiflist,
+			     oiflist_disable_wrongvif, max_vifs_oiflist,
+			     rp_addr);
+	routes[mrs.distance][mrs.getHash()] = mrs;
+
+	// If any lower distance routes are already in place, do nothing and
+	// return.
+	if (mrs.distance > 0) {
+	    for (unsigned int i = mrs.distance - 1; i > 0; i--) {
+		map<string, MfeaRouteStorage>::const_iterator iter = routes[i].find(mrs.getHash());
+		if (iter != routes[i].end()) {
+		    XLOG_INFO("Lower-distance mfea route exists, distance: %i source: %s  group: %s",
+			      i, source.str().c_str(), group.str().c_str());
+		    return XORP_OK;
+		}
+	    }
+	}
+
+	// If any higher distance routes are already in place, remove them from kernel.
+	for (unsigned int i = mrs.distance + 1; i<MAX_MFEA_DISTANCE; i++) {
+	    map<string, MfeaRouteStorage>::const_iterator iter = routes[i].find(mrs.getHash());
+	    if (iter != routes[i].end()) {
+		XLOG_INFO("Removing higher-distance mfea route, distance: %i source: %s  group: %s",
+			  i, source.str().c_str(), group.str().c_str());
+		delete_mfc(iter->second.module_instance_name, iter->second.source,
+			   iter->second.group, error_msg, false);
+		break;
+	    }
+	}
+    }
     
     //
     // Reset the initial values
@@ -1889,9 +2062,10 @@ MfeaNode::add_mfc(const string& , // module_instance_name,
 	    case AF_INET6:
 	    {
 #ifndef HAVE_IPV6_MULTICAST_ROUTING
-		XLOG_ERROR("add_mfc() failed: "
-			   "IPv6 multicast routing not supported");
-		return (XORP_ERROR);
+		string em = "add_mfc() failed: IPv6 multicast routing not supported\n";
+		error_msg += em;
+		XLOG_ERROR(em);
+		return XORP_ERROR;
 #else
 #if defined(MRT6_MFC_FLAGS_DISABLE_WRONGVIF) && defined(ENABLE_ADVANCED_MULTICAST_API)
 		oifs_flags[i] |= MRT6_MFC_FLAGS_DISABLE_WRONGVIF;
@@ -1911,10 +2085,11 @@ MfeaNode::add_mfc(const string& , // module_instance_name,
     if (_mfea_mrouter.add_mfc(source, group, iif_vif_index, oifs_ttl,
 			      oifs_flags, rp_addr)
 	!= XORP_OK) {
-	return (XORP_ERROR);
+	error_msg += "mfea_mrouter add_mfc failed.\n";
+	return XORP_ERROR;
     }
     
-    return (XORP_OK);
+    return XORP_OK;
 }
 
 /**
@@ -1930,19 +2105,74 @@ MfeaNode::add_mfc(const string& , // module_instance_name,
  * Return value: %XORP_OK on success, otherwise %XORP_ERROR.
  **/
 int
-MfeaNode::delete_mfc(const string& , // module_instance_name,
-		     const IPvX& source, const IPvX& group)
+MfeaNode::delete_mfc(const string& module_instance_name,
+		     const IPvX& source, const IPvX& group,
+		     string& error_msg, bool check_stored_routes)
 {
-    if (_mfea_mrouter.delete_mfc(source, group) != XORP_OK) {
-	return (XORP_ERROR);
+    bool do_rem_route = true;
+    int rv;
+    string hash = source.str() + ":" + group.str();
+
+    XLOG_INFO("delete-mfc, module: %s  source: %s  group: %s  check-stored-routes: %i\n",
+	      module_instance_name.c_str(), source.str().c_str(),
+	      group.str().c_str(), (int)(check_stored_routes));
+
+    if (check_stored_routes) {
+	// find existing route by instance-name.
+	for (unsigned int i = 0; i<MAX_MFEA_DISTANCE; i++) {
+	    map<string, MfeaRouteStorage>::iterator iter = routes[i].find(hash);
+	    if (iter != routes[i].end()) {
+		// Found something to delete..see if it belongs to us?
+		if (iter->second.module_instance_name == module_instance_name) {
+		    // Yep, that's us.
+		    routes[i].erase(hash);
+		    goto check_remove_route;
+		}
+		else {
+		    // was some other protocol's route.  Don't mess with this,
+		    // and don't remove anything from the kernel.
+		    do_rem_route = false;
+		}
+	    }
+	}
     }
+
+  check_remove_route:
+
+    if (! do_rem_route) {
+	return XORP_OK;
+    }
+
+    rv = _mfea_mrouter.delete_mfc(source, group);
     
-    //
-    // XXX: Remove all corresponding dataflow entries
-    //
+    // Remove all corresponding dataflow entries
     mfea_dft().delete_entry(source, group);
-    
-    return (XORP_OK);
+
+    if (check_stored_routes) {
+	// Now, see if we have any higher-distance routes to add.
+	for (unsigned int i = 0; i<MAX_MFEA_DISTANCE; i++) {
+	    map<string, MfeaRouteStorage>::iterator iter = routes[i].find(hash);
+	    if (iter != routes[i].end()) {
+		if (iter->second.isBinary()) {
+		    rv = add_mfc(iter->second.module_instance_name,
+				 iter->second.source, iter->second.group,
+				 iter->second.iif_vif_index,
+				 iter->second.oiflist, iter->second.oiflist_disable_wrongvif,
+				 iter->second.max_vifs_oiflist, iter->second.rp_addr,
+				 iter->second.distance, error_msg, false);
+		}
+		else {
+		    rv = add_mfc_str(iter->second.module_instance_name,
+				     iter->second.source, iter->second.group,
+				     iter->second.iif_name, iter->second.oif_names,
+				     iter->second.distance, error_msg, false);
+		}
+		break;
+	    }
+	}
+    }
+
+    return rv;
 }
 
 /**
diff --git a/xorp/fea/mfea_node.hh b/xorp/fea/mfea_node.hh
index b698a7e..39f08d7 100644
--- a/xorp/fea/mfea_node.hh
+++ b/xorp/fea/mfea_node.hh
@@ -17,8 +17,6 @@
 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
 // http://xorp.net
 
-// $XORP: xorp/fea/mfea_node.hh,v 1.51 2008/10/02 21:56:49 bms Exp $
-
 
 #ifndef __FEA_MFEA_NODE_HH__
 #define __FEA_MFEA_NODE_HH__
@@ -48,6 +46,44 @@ class MfeaVif;
 class SgCount;
 class VifCount;
 
+
+class MfeaRouteStorage {
+public:
+    uint32_t distance; // lower is higer priority.
+    bool is_binary;
+
+    string module_instance_name;
+    IPvX source;
+    IPvX group;
+
+    // String based route
+    string iif_name;
+    string oif_names;
+
+    // Binary based route
+    uint32_t iif_vif_index;
+    Mifset oiflist;
+    Mifset oiflist_disable_wrongvif;
+    uint32_t max_vifs_oiflist;
+    IPvX rp_addr;
+
+    MfeaRouteStorage(uint32_t d, const string module_name, const IPvX& _source,
+		     const IPvX& _group, const string& _iif_name, const string& _oif_names);
+
+    MfeaRouteStorage(uint32_t d, const string module_name, const IPvX& _source,
+		     const IPvX& _group, uint32_t iif_vif_idx,
+		     const Mifset& _oiflist, const Mifset& _oif_disable_wrongvif,
+		     uint32_t max_vifs, const IPvX& _rp_addr);
+
+    MfeaRouteStorage(const MfeaRouteStorage& o);
+    MfeaRouteStorage();
+
+    bool isBinary() const { return is_binary; }
+
+    string getHash() { return source.str() + ":" + group.str(); }
+};
+
+
 /**
  * @short The MFEA node class.
  * 
@@ -580,12 +616,22 @@ public:
      * 
      * @return XORP_OK on success, otherwise XORP_ERROR.
      */
-    int		add_mfc(const string& module_instance_name,
-			const IPvX& source, const IPvX& group,
-			uint32_t iif_vif_index, const Mifset& oiflist,
-			const Mifset& oiflist_disable_wrongvif,
-			uint32_t max_vifs_oiflist,
-			const IPvX& rp_addr);
+    int	add_mfc(const string& module_instance_name,
+		const IPvX& source, const IPvX& group,
+		uint32_t iif_vif_index, const Mifset& oiflist,
+		const Mifset& oiflist_disable_wrongvif,
+		uint32_t max_vifs_oiflist,
+		const IPvX& rp_addr, uint32_t distance,
+		string& error_msg,
+		bool check_stored_routes);
+
+    int	add_mfc_str(const string& module_instance_name,
+		    const IPvX& source,
+		    const IPvX& group,
+		    const string& iif_name,
+		    const string& oif_names,
+		    uint32_t distance,
+		    string& error_msg, bool check_stored_routes);
     
     /**
      * Delete Multicast Forwarding Cache (MFC) from the kernel.
@@ -601,8 +647,9 @@ public:
      * 
      * @return XORP_OK on success, otherwise XORP_ERROR.
      */
-    int		delete_mfc(const string& module_instance_name,
-			   const IPvX& source, const IPvX& group);
+    int	delete_mfc(const string& module_instance_name,
+		   const IPvX& source, const IPvX& group,
+		   string& error_msg, bool check_stored_routes);
     
     /**
      * Add a dataflow monitor entry.
@@ -854,6 +901,13 @@ private:
     IfTree			_mfea_iftree;
     IfConfigUpdateReplicator	_mfea_iftree_update_replicator;
 
+    // Store desired routes.  This is a cheap way of doing some of the
+    // RIB logic, but for mcast routes.
+    // Lower distance means higher priority.
+    // key is:  source:group, ie:  192.168.1.1:226.0.0.1
+#define MAX_MFEA_DISTANCE 8
+    map<string, MfeaRouteStorage> routes[MAX_MFEA_DISTANCE];
+
     //
     // Debug and test-related state
     //
diff --git a/xorp/fea/xrl_fea_node.hh b/xorp/fea/xrl_fea_node.hh
index 0096d30..31831f3 100644
--- a/xorp/fea/xrl_fea_node.hh
+++ b/xorp/fea/xrl_fea_node.hh
@@ -17,9 +17,6 @@
 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
 // http://xorp.net
 
-// $XORP: xorp/fea/xrl_fea_node.hh,v 1.15 2008/10/02 21:56:50 bms Exp $
-
-
 #ifndef __FEA_XRL_FEA_NODE_HH__
 #define __FEA_XRL_FEA_NODE_HH__
 
@@ -29,9 +26,7 @@
 //
 
 #include "libxorp/xorp.h"
-
 #include "libxipc/xrl_std_router.hh"
-
 #include "cli/xrl_cli_node.hh"
 
 #include "fea_node.hh"
diff --git a/xorp/fea/xrl_mfea_node.cc b/xorp/fea/xrl_mfea_node.cc
index a3db058..2eb10c1 100644
--- a/xorp/fea/xrl_mfea_node.cc
+++ b/xorp/fea/xrl_mfea_node.cc
@@ -895,7 +895,8 @@ XrlMfeaNode::mfea_0_1_add_mfc6(
     const vector<uint8_t>& oiflist, 
     const vector<uint8_t>& oiflist_disable_wrongvif, 
     const uint32_t&	max_vifs_oiflist, 
-    const IPv6&		rp_address)
+    const IPv6&		rp_address,
+    const uint32_t&     distance)
 {
     string error_msg;
     Mifset mifset;
@@ -930,21 +931,17 @@ XrlMfeaNode::mfea_0_1_add_mfc6(
 			  IPvX(source_address), IPvX(group_address),
 			  iif_vif_index, mifset, mifset_disable_wrongvif,
 			  max_vifs_oiflist,
-			  IPvX(rp_address))
+			  IPvX(rp_address), distance, error_msg, true)
 	!= XORP_OK) {
-	// TODO: must find-out and return the reason for failure
-	error_msg = c_format("Cannot add MFC for "
-			     "source %s and group %s "
-			     "with iif_vif_index = %u",
-			     source_address.str().c_str(),
-			     group_address.str().c_str(),
-			     XORP_UINT_CAST(iif_vif_index));
+	error_msg += c_format("Cannot add MFC for "
+			      "source %s and group %s "
+			      "with iif_vif_index = %u",
+			      source_address.str().c_str(),
+			      group_address.str().c_str(),
+			      XORP_UINT_CAST(iif_vif_index));
 	return XrlCmdError::COMMAND_FAILED(error_msg);
     }
     
-    //
-    // Success
-    //
     return XrlCmdError::OKAY();
 }
 
@@ -967,19 +964,16 @@ XrlMfeaNode::mfea_0_1_delete_mfc6(
     }
 
     if (MfeaNode::delete_mfc(xrl_sender_name,
-			     IPvX(source_address), IPvX(group_address))
+			     IPvX(source_address), IPvX(group_address),
+			     error_msg, true)
 	!= XORP_OK) {
-	// TODO: must find-out and return the reason for failure
-	error_msg = c_format("Cannot delete MFC for "
-			     "source %s and group %s",
-			     source_address.str().c_str(),
-			     group_address.str().c_str());
+	error_msg += c_format("Cannot delete MFC for "
+			      "source %s and group %s",
+			      source_address.str().c_str(),
+			      group_address.str().c_str());
 	return XrlCmdError::COMMAND_FAILED(error_msg);
     }
     
-    //
-    // Success
-    //
     return XrlCmdError::OKAY();
 }
 
@@ -1190,7 +1184,8 @@ XrlMfeaNode::mfea_0_1_add_mfc4(
     const vector<uint8_t>& oiflist, 
     const vector<uint8_t>& oiflist_disable_wrongvif, 
     const uint32_t&	max_vifs_oiflist, 
-    const IPv4&		rp_address)
+    const IPv4&		rp_address,
+    const uint32_t&      distance)
 {
     string error_msg;
     Mifset mifset;
@@ -1225,21 +1220,53 @@ XrlMfeaNode::mfea_0_1_add_mfc4(
 			  IPvX(source_address), IPvX(group_address),
 			  iif_vif_index, mifset, mifset_disable_wrongvif,
 			  max_vifs_oiflist,
-			  IPvX(rp_address))
+			  IPvX(rp_address), distance, error_msg, true)
 	!= XORP_OK) {
-	// TODO: must find-out and return the reason for failure
-	error_msg = c_format("Cannot add MFC for "
-			     "source %s and group %s "
-			     "with iif_vif_index = %u",
-			     source_address.str().c_str(),
-			     group_address.str().c_str(),
-			     XORP_UINT_CAST(iif_vif_index));
+	error_msg += c_format("Cannot add MFC for "
+			      "source %s and group %s "
+			      "with iif_vif_index = %u",
+			      source_address.str().c_str(),
+			      group_address.str().c_str(),
+			      XORP_UINT_CAST(iif_vif_index));
 	return XrlCmdError::COMMAND_FAILED(error_msg);
     }
     
+    return XrlCmdError::OKAY();
+}
+
+XrlCmdError
+XrlMfeaNode::mfea_0_1_add_mfc4_str(
+    // Input values,
+    const string&	xrl_sender_name,
+    const IPv4&		source_address,
+    const IPv4&		group_address,
+    const string&       iif_ifname,
+    const string&       oif_ifnames,
+    const uint32_t&      distance)
+{
+    string error_msg;
+
+    XLOG_INFO("received mfea add-mfc command, sender-name: %s input: %s  mcast-addr: %s  ifname: %s  output_ifs: %s\n",
+	      xrl_sender_name.c_str(),
+	      source_address.str().c_str(),
+	      group_address.str().c_str(),
+	      iif_ifname.c_str(),
+	      oif_ifnames.c_str());
     //
-    // Success
+    // Verify the address family
     //
+    if (! MfeaNode::is_ipv4()) {
+	error_msg = c_format("Received protocol message with "
+			     "invalid address family: IPv4");
+	return XrlCmdError::COMMAND_FAILED(error_msg);
+    }
+
+    if (MfeaNode::add_mfc_str(xrl_sender_name,
+			      IPvX(source_address), IPvX(group_address),
+			      iif_ifname, oif_ifnames, distance, error_msg, true) != XORP_OK) {
+	return XrlCmdError::COMMAND_FAILED(error_msg);
+    }
+
     return XrlCmdError::OKAY();
 }
 
@@ -1262,19 +1289,16 @@ XrlMfeaNode::mfea_0_1_delete_mfc4(
     }
 
     if (MfeaNode::delete_mfc(xrl_sender_name,
-			     IPvX(source_address), IPvX(group_address))
+			     IPvX(source_address), IPvX(group_address),
+			     error_msg, true)
 	!= XORP_OK) {
-	// TODO: must find-out and return the reason for failure
-	error_msg = c_format("Cannot delete MFC for "
-			     "source %s and group %s",
-			     source_address.str().c_str(),
-			     group_address.str().c_str());
+	error_msg += c_format("Cannot delete MFC for "
+			      "source %s and group %s",
+			      source_address.str().c_str(),
+			      group_address.str().c_str());
 	return XrlCmdError::COMMAND_FAILED(error_msg);
     }
     
-    //
-    // Success
-    //
     return XrlCmdError::OKAY();
 }
 
@@ -1435,8 +1459,9 @@ XrlMfeaNode::mfea_0_1_start_vif(
 {
     string error_msg;
     
-    if (MfeaNode::start_vif(vif_name, error_msg) != XORP_OK)
+    if (MfeaNode::start_vif(vif_name, error_msg) != XORP_OK) {
 	return XrlCmdError::COMMAND_FAILED(error_msg);
+    }
     
     return XrlCmdError::OKAY();
 }
diff --git a/xorp/fea/xrl_mfea_node.hh b/xorp/fea/xrl_mfea_node.hh
index 11efb40..ed9367d 100644
--- a/xorp/fea/xrl_mfea_node.hh
+++ b/xorp/fea/xrl_mfea_node.hh
@@ -269,7 +269,8 @@ protected:
 	const vector<uint8_t>&	oiflist, 
 	const vector<uint8_t>&	oiflist_disable_wrongvif, 
 	const uint32_t&	max_vifs_oiflist, 
-	const IPv6&	rp_address);
+	const IPv6&	rp_address,
+	const uint32_t& distance);
 
     XrlCmdError mfea_0_1_delete_mfc6(
 	// Input values, 
@@ -359,13 +360,23 @@ protected:
 	const IPv4&	source_address, 
 	const IPv4&	group_address, 
 	const uint32_t&	iif_vif_index, 
-	const vector<uint8_t>&	oiflist, 
-	const vector<uint8_t>&	oiflist_disable_wrongvif, 
-	const uint32_t&	max_vifs_oiflist, 
-	const IPv4&	rp_address);
+	const vector<uint8_t>&	oiflist,
+	const vector<uint8_t>&	oiflist_disable_wrongvif,
+	const uint32_t&	max_vifs_oiflist,
+	const IPv4&	rp_address,
+	const uint32_t& distance);
+
+    XrlCmdError mfea_0_1_add_mfc4_str(
+	// Input values,
+	const string&	xrl_sender_name,
+	const IPv4&	source_address,
+	const IPv4&	group_address,
+	const string&   iif_ifname,
+	const string&   oif_ifnames,
+	const uint32_t& distance);
 
     XrlCmdError mfea_0_1_delete_mfc4(
-	// Input values, 
+	// Input values,
 	const string&	xrl_sender_name, 
 	const IPv4&	source_address, 
 	const IPv4&	group_address);
diff --git a/xorp/pim/xrl_pim_node.cc b/xorp/pim/xrl_pim_node.cc
index d5db99a..07a32eb 100644
--- a/xorp/pim/xrl_pim_node.cc
+++ b/xorp/pim/xrl_pim_node.cc
@@ -1656,6 +1656,7 @@ XrlPimNode::send_add_delete_mfc()
 		oiflist_disable_wrongvif_vector,
 		max_vifs_oiflist,
 		rp_addr.get_ipv4(),
+		1, /* default distance is 1 for PIM */
 		callback(this, &XrlPimNode::mfea_client_send_add_delete_mfc_cb));
 	    if (success)
 		return;
@@ -1673,6 +1674,7 @@ XrlPimNode::send_add_delete_mfc()
 		oiflist_disable_wrongvif_vector,
 		max_vifs_oiflist,
 		rp_addr.get_ipv6(),
+		1, /* default distance is 1 for PIM */
 		callback(this, &XrlPimNode::mfea_client_send_add_delete_mfc_cb));
 	    if (success)
 		return;
diff --git a/xorp/xrl/interfaces/mfea.xif b/xorp/xrl/interfaces/mfea.xif
index 00fd6b1..3f778c5 100644
--- a/xorp/xrl/interfaces/mfea.xif
+++ b/xorp/xrl/interfaces/mfea.xif
@@ -1,4 +1,3 @@
-/* $XORP: xorp/xrl/interfaces/mfea.xif,v 1.9 2007/05/19 01:52:48 pavlin Exp $ */
 
 #include <xorp_config.h>
 
@@ -41,9 +40,9 @@ interface mfea/0.1 {
 	 *
 	 * @param xrl_sender_name the XRL name of the originator of this XRL.
 	 * @param if_name the name of the interface to unregister for the
-	 * particular protocol.
+	 *        particular protocol.
 	 * @param vif_name the name of the vif to unregister for the
-	 * particular protocol.
+	 *        particular protocol.
 	 */
 	unregister_protocol4 ? xrl_sender_name:txt			\
 			& if_name:txt & vif_name:txt;
@@ -55,12 +54,12 @@ interface mfea/0.1 {
 	 * @param source_address the source address of the MFC to add/delete.
 	 * @param group_address the group address of the MFC to add/delete.
 	 * @param iif_vif_index the index of the vif that is the incoming
-	 * interface.
+	 *        interface.
 	 * @param oiflist the bit-vector with the set of outgoing interfaces.
 	 * @param oiflist_disable_wrongvif the bit-vector with the set of
-	 * outgoing interfaces to disable WRONGVIF kernel signal.
+	 *        outgoing interfaces to disable WRONGVIF kernel signal.
 	 * @param max_vifs_oiflist the number of vifs covered
-	 * by oiflist or oiflist_disable_wrongvif .
+	 *        by oiflist or oiflist_disable_wrongvif .
 	 * @param rp_address the RP address of the MFC to add.
 	 */
 	add_mfc4	? xrl_sender_name:txt				\
@@ -69,9 +68,20 @@ interface mfea/0.1 {
 			& oiflist:binary				\
 			& oiflist_disable_wrongvif:binary		\
 			& max_vifs_oiflist:u32				\
-			& rp_address:ipv4;
+			& rp_address:ipv4				\
+			& distance:u32;
 	delete_mfc4	? xrl_sender_name:txt				\
 			& source_address:ipv4 & group_address:ipv4;
+
+	/**
+	 * Use strings instead of indexes.  Let mfea do the mapping.
+         */
+	add_mfc4_str	? xrl_sender_name:txt				\
+			& source_address:ipv4 				\
+			& group_address:ipv4				\
+			& iif_name:txt					\
+			& oif_names:txt					\
+			& distance:u32;
 	
 	/**
 	 * Add/delete a dataflow monitor with the MFEA.
@@ -193,7 +203,8 @@ interface mfea/0.1 {
 			& oiflist:binary				\
 			& oiflist_disable_wrongvif:binary		\
 			& max_vifs_oiflist:u32				\
-			& rp_address:ipv6;
+			& rp_address:ipv6				\
+			& distance:u32;
 	delete_mfc6	? xrl_sender_name:txt				\
 			& source_address:ipv6 & group_address:ipv6;
 	add_dataflow_monitor6	? xrl_sender_name:txt			\
diff --git a/xorp/xrl/interfaces/mfea_client.xif b/xorp/xrl/interfaces/mfea_client.xif
index 8cecda3..4100190 100644
--- a/xorp/xrl/interfaces/mfea_client.xif
+++ b/xorp/xrl/interfaces/mfea_client.xif
@@ -1,4 +1,3 @@
-/* $XORP: xorp/xrl/interfaces/mfea_client.xif,v 1.11 2007/05/19 01:52:48 pavlin Exp $ */
 
 #include <xorp_config.h>
 
diff --git a/xorp/xrl/interfaces/pim.xif b/xorp/xrl/interfaces/pim.xif
index e38806d..617b3e2 100644
--- a/xorp/xrl/interfaces/pim.xif
+++ b/xorp/xrl/interfaces/pim.xif
@@ -1,5 +1,3 @@
-/* $XORP: xorp/xrl/interfaces/pim.xif,v 1.24 2007/07/12 21:35:29 pavlin Exp $ */
-
 /*
  * Protocol Independent Multicast XRL interface.
  */
-- 
1.7.7.6



More information about the Xorp-hackers mailing list