From: Ben Greear <[email protected]>

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 <[email protected]>
---
 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

_______________________________________________
Xorp-hackers mailing list
[email protected]
http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-hackers

Reply via email to