Skip to content

Commit

Permalink
static-mcast: Add support for static multicast routes.
Browse files Browse the repository at this point in the history
This adds the ability to configure static multicast routes
using the static-route module.

Example config file looks like:

interfaces {
        interface "p3p1" {
                disable: false
                default-system-config
        }
        interface "wlan0" {
                disable: false
                default-system-config
        }
}
fea {
        unicast-forwarding4 {
                disable: false
        }
}

protocols {
  static {
    route 10.2.46.91/16 {
      next-hop: 10.2.46.20
      metric: 1
    }
    mrib-route 10.2.46.0/16 {
      next-hop: 10.2.46.30
      metric: 1
    }
    mcast-route 226.0.0.1 {
      input_if: "p3p1"
      input_ip: 192.168.9.11
      output_ifs: "wlan0"
      distance: 2
    }
  }
}

plumbing {
    mfea4 {
        disable: false
        interface "p3p1" {
            vif "p3p1" {
                disable: false
            }
        }
        interface "wlan0" {
            vif "wlan0" {
                disable: false
            }
        }
        interface "register_vif" {
            vif "register_vif" {
                disable: false
            }
        }
    } /*  mfea4  */
} /* plumbing */

Signed-off-by: Ben Greear <greearb@candelatech.com>
  • Loading branch information
greearb committed Jul 9, 2012
1 parent 5eb6be0 commit d7ecee9
Show file tree
Hide file tree
Showing 9 changed files with 956 additions and 89 deletions.
39 changes: 38 additions & 1 deletion xorp/etc/templates/static_routes.tp
@@ -1,4 +1,3 @@
/* $XORP: xorp/etc/templates/static_routes.tp,v 1.43 2008/08/06 08:23:24 abittau Exp $ */

protocols {
static {
Expand Down Expand Up @@ -26,6 +25,13 @@ protocols {
}
}

mcast-route @: ipv4 {
input_if: txt;
input_ip: ipv4;
output_ifs: txt;
distance: u32 = 0;
}

route4 @: ipv4net { /* %deprecated */
next-hop: ipv4;
nexthop: ipv4; /* %deprecated */
Expand Down Expand Up @@ -284,6 +290,37 @@ protocols {
}
}

mcast-route @: ipv4 {
%help: short "Configure a static Multicast route";
%mandatory: $(@.input_if), $(@.input_ip), $(@.output_ifs);

%create: xrl "$(static.targetname)/static_routes/0.1/add_mcast_route4?mcast_addr:ipv4=$(@)&input_if:txt=$(@.input_if)&input_ip:ipv4=$(@.input_ip)&output_ifs:txt=$(@.output_ifs)&distance:u32=$(@.distance)";
%update: xrl "$(static.targetname)/static_routes/0.1/replace_mcast_route4?mcast_addr:ipv4=$(@)&input_if:txt=$(@.input_if)&input_ip:ipv4=$(@.input_ip)&output_ifs:txt=$(@.output_ifs))&distance:u32=$(@.distance)";
%delete: xrl "$(static.targetname)/static_routes/0.1/delete_mcast_route4?mcast_addr:ipv4=$(@)&input_ip:ipv4=$(@.input_ip)";

input_if {
%help: short "Configure the input interface";
%set:;
}

input_ip {
%help: short "Configure the input IP address";
%set:;
}

output_ifs {
%help: short "Configure the input output interface(s)";
%set:;
}

distance {
%help: short "Configure the routing distance. Lower value wins";
%allow-range: $(@) "0" "7" %help: "The routing distance";
%set:;
}
}


route4 @: ipv4net {
%deprecated: "Statement 'route4' is replaced with 'route'";
%help: short "Configure an IPv4 static route";
Expand Down
1 change: 1 addition & 0 deletions xorp/static_routes/SConscript
Expand Up @@ -51,6 +51,7 @@ env.AppendUnique(LIBS = [
'xst_fea_ifmgr_mirror',
'xst_static_routes',
'xif_rib',
'xif_mfea',
'xif_finder_event_notifier',
'xorp_policy_backend',
'xorp_policy_common',
Expand Down
185 changes: 185 additions & 0 deletions xorp/static_routes/static_routes_node.cc
Expand Up @@ -121,6 +121,9 @@ StaticRoutesNode::shutdown()
//
rib_register_shutdown();

// De-register with the MFEA
rib_register_shutdown();

//
// De-register with the FEA
//
Expand Down Expand Up @@ -306,6 +309,7 @@ StaticRoutesNode::updates_made()
StaticRoutesNode::Table::iterator route_iter;
list<StaticRoute *> add_routes, replace_routes, delete_routes;
list<StaticRoute *>::iterator pending_iter;
list<McastRoute *>::iterator mpending_iter;

for (route_iter = _static_routes.begin();
route_iter != _static_routes.end();
Expand Down Expand Up @@ -395,6 +399,80 @@ StaticRoutesNode::updates_made()
}
}

// Deal with mcast-routes
list<McastRoute *> add_mroutes, replace_mroutes, delete_mroutes;
map<IPvX, McastRoute>::iterator mroute_iter;
for (mroute_iter = _mcast_routes.begin();
mroute_iter != _mcast_routes.end();
++mroute_iter) {
McastRoute& static_route = mroute_iter->second;
bool is_old_up = false;
bool is_new_up = false;
string old_ifname, old_vifname, new_ifname, new_vifname;

//
// Calculate whether the interface was UP before and now.
//
const IfMgrIfAtom* if_atom;
const IfMgrVifAtom* vif_atom;

if_atom = _iftree.find_interface(static_route.ifname());
vif_atom = _iftree.find_vif(static_route.ifname(),
static_route.vifname());
if ((if_atom != NULL) && (if_atom->enabled())
&& (! if_atom->no_carrier())
&& (vif_atom != NULL) && (vif_atom->enabled())) {
is_old_up = true;
}

if_atom = ifmgr_iftree().find_interface(static_route.ifname());
vif_atom = ifmgr_iftree().find_vif(static_route.ifname(),
static_route.vifname());
if ((if_atom != NULL) && (if_atom->enabled())
&& (! if_atom->no_carrier())
&& (vif_atom != NULL) && (vif_atom->enabled())) {
is_new_up = true;
}

if ((is_old_up == is_new_up)
&& (old_ifname == new_ifname)
&& (old_vifname == new_vifname)) {
continue; // Nothing changed
}

if ((! is_old_up) && (! is_new_up)) {
//
// The interface is still down, so nothing to do
//
continue;
}
if ((! is_old_up) && (is_new_up)) {
//
// The interface is now up, hence add the route
//
add_mroutes.push_back(&static_route);
continue;
}
if ((is_old_up) && (! is_new_up)) {
//
// The interface went down, hence cancel all pending requests,
// and withdraw the route.
//
delete_mroutes.push_back(&static_route);
continue;
}
if (is_old_up && is_new_up) {
//
// The interface remains up, hence probably the interface or
// the vif name has changed.
// Delete the route and then add it again so the information
// in the RIB will be updated.
//
replace_mroutes.push_back(&static_route);
continue;
}
}

//
// Update the local copy of the interface tree
//
Expand Down Expand Up @@ -444,6 +522,44 @@ StaticRoutesNode::updates_made()
copy_route.set_delete_route();
inform_rib(copy_route);
}


//
// Process all pending "add mroute" requests
//
for (mpending_iter = add_mroutes.begin();
mpending_iter != add_mroutes.end();
++pending_iter) {
McastRoute& orig_route = *(*mpending_iter);
McastRoute copy_route = orig_route;
copy_route.set_add_route();
inform_mfea(copy_route);
}

//
// Process all pending "replace mroute" requests
//
for (mpending_iter = replace_mroutes.begin();
mpending_iter != replace_mroutes.end();
++mpending_iter) {
McastRoute& orig_route = *(*mpending_iter);
McastRoute copy_route = orig_route;
copy_route.set_replace_route();
inform_mfea(copy_route);
}

//
// Process all pending "delete mroute" requests
//
for (mpending_iter = delete_mroutes.begin();
mpending_iter != delete_mroutes.end();
++mpending_iter) {
McastRoute& orig_route = *(*mpending_iter);
cancel_mfea_mfc_change(orig_route);
McastRoute copy_route = orig_route;
copy_route.set_delete_route();
inform_mfea(copy_route);
}
}

/**
Expand Down Expand Up @@ -670,6 +786,65 @@ StaticRoutesNode::delete_route6(bool unicast, bool multicast,
return (delete_route(static_route, error_msg));
}

int StaticRoutesNode::add_mcast_route4(const IPv4& mcast_addr, const string& input_if,
const IPv4& input_ip, const string& output_ifs,
uint32_t distance, string& error_msg) {
map<IPvX, McastRoute>::const_iterator iter = _mcast_routes.find(mcast_addr);
if (iter == _mcast_routes.end()) {
McastRoute mr(mcast_addr, input_if, input_ip, output_ifs, distance);
_mcast_routes[mcast_addr] = mr;
McastRoute copy_route = mr;
copy_route.set_add_route();
inform_mfea(copy_route);
}
else {
error_msg.append("Mcast-Route: " + mcast_addr.str() + " already exists!\n");
return XORP_ERROR;
}
return XORP_OK;
}

int StaticRoutesNode::replace_mcast_route4(const IPv4& mcast_addr, const string& input_if,
const IPv4& input_ip, const string& output_ifs,
uint32_t distance, string& error_msg) {
UNUSED(error_msg);

McastRoute mr(mcast_addr, input_if, input_ip, output_ifs, distance);
map<IPvX, McastRoute>::const_iterator iter = _mcast_routes.find(mcast_addr);
if (iter == _mcast_routes.end()) {
if (iter->second == mr) {
// no changes
return XORP_OK;
}
}
_mcast_routes.erase(mcast_addr);
_mcast_routes[mcast_addr] = mr;

McastRoute copy_route = mr;
copy_route.set_replace_route();
inform_mfea(copy_route);

return XORP_OK;
}


int StaticRoutesNode::delete_mcast_route4(const IPv4& mcast_addr, const IPv4& input_ip,
string& error_msg) {
UNUSED(error_msg);

map<IPvX, McastRoute>::const_iterator iter = _mcast_routes.find(mcast_addr);
if (iter != _mcast_routes.end()) {
_mcast_routes.erase(mcast_addr);

McastRoute mr(mcast_addr, input_ip);
mr.set_delete_route();
inform_mfea(mr);
}

return XORP_OK;
}


/**
* Find a route from the routing table.
*
Expand Down Expand Up @@ -1296,6 +1471,16 @@ StaticRoutesNode::inform_rib(const StaticRoute& route)
inform_rib_route_change(modified_route);
}


void
StaticRoutesNode::inform_mfea(const McastRoute& route)
{
if (! is_enabled())
return;

inform_mfea_mfc_change(route);
}

/**
* Update a route received from the user configuration.
*
Expand Down

0 comments on commit d7ecee9

Please sign in to comment.