Skip to content

Commit

Permalink
FEA: Fix tx Mcast packets with duplicate local IPs.
Browse files Browse the repository at this point in the history
When multiple interfaces have the same IP, we must pass
in the interface ifindex instead of just the IP address
when binding the socket before sending mcast packets.

Keep fallback code for systems that do not support
ip_mreqn.  They will work fine as long as there are no
duplicate IP addresses.

Signed-off-by: Ben Greear <greearb@candelatech.com>
  • Loading branch information
greearb committed Aug 30, 2012
1 parent d76b02f commit 843fee0
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 7 deletions.
21 changes: 19 additions & 2 deletions xorp/fea/data_plane/io/io_ip_socket.cc
Expand Up @@ -465,8 +465,6 @@ IoIpSocket::set_default_multicast_interface(const string& if_name,
switch (family()) {
case AF_INET:
{
struct in_addr in_addr;

// Find the first address
IfTreeVif::IPv4Map::const_iterator ai = vifp->ipv4addrs().begin();
if (ai == vifp->ipv4addrs().end()) {
Expand All @@ -476,15 +474,34 @@ IoIpSocket::set_default_multicast_interface(const string& if_name,
if_name.c_str(), vif_name.c_str());
return (XORP_ERROR);
}

const IfTreeAddr4& fa = *(ai->second);

#ifdef HAVE_STRUCT_IP_MREQN
struct ip_mreqn mreqn;
memset(&mreqn, 0, sizeof(mreqn));

fa.addr().copy_out(mreqn.imr_address);
mreqn.imr_ifindex = vifp->pif_index();
if (setsockopt(_proto_socket_out, IPPROTO_IP, IP_MULTICAST_IF,
XORP_SOCKOPT_CAST(&mreqn), sizeof(mreqn)) < 0) {
error_msg = c_format("setsockopt(IP_MULTICAST_IF, %s %i) failed: %s",
cstring(fa.addr()), vifp->pif_index(),
XSTRERROR);
return XORP_ERROR;
}
#else
struct in_addr in_addr;
memset(&in_addr, 0, sizeof(in_addr));

fa.addr().copy_out(in_addr);
if (setsockopt(_proto_socket_out, IPPROTO_IP, IP_MULTICAST_IF,
XORP_SOCKOPT_CAST(&in_addr), sizeof(in_addr)) < 0) {
error_msg = c_format("setsockopt(IP_MULTICAST_IF, %s) failed: %s",
cstring(fa.addr()), XSTRERROR);
return (XORP_ERROR);
}
#endif
}
break;

Expand Down
2 changes: 0 additions & 2 deletions xorp/fea/io_ip.hh
Expand Up @@ -17,8 +17,6 @@
// XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
// http://xorp.net

// $XORP: xorp/fea/io_ip.hh,v 1.5 2008/10/02 21:56:48 bms Exp $


#ifndef __FEA_IO_IP_HH__
#define __FEA_IO_IP_HH__
Expand Down
4 changes: 4 additions & 0 deletions xorp/fea/xrl_fea_target.cc
Expand Up @@ -3696,6 +3696,10 @@ XrlFeaTarget::raw_packet4_0_1_send(
vector<uint8_t> ext_headers_type_vector;
vector<vector<uint8_t> > ext_headers_payload_vector;

//XLOG_INFO("FEA::send_raw pkt on %s/%s. from: %s to: %s",
// if_name.c_str(), vif_name.c_str(),
// src_address.str().c_str(), dst_address.str().c_str());

if (_io_ip_manager.send(if_name, vif_name, IPvX(src_address),
IPvX(dst_address), ip_protocol, ip_ttl, ip_tos,
ip_router_alert, ip_internet_control,
Expand Down
6 changes: 3 additions & 3 deletions xorp/pim/xrl_pim_node.cc
Expand Up @@ -2385,9 +2385,9 @@ XrlPimNode::send_protocol_message()
entry = dynamic_cast<SendProtocolMessage*>(xrl_task_base);
XLOG_ASSERT(entry != NULL);

//XLOG_ERROR("XrlPimNode::send_protocol_message interface/vif %s/%s. ",
// entry->if_name().c_str(),
// entry->vif_name().c_str());
//XLOG_INFO("XrlPimNode::send_protocol_message interface/vif %s/%s. from: %s to: %s",
// entry->if_name().c_str(), entry->vif_name().c_str(),
// entry->src_address().str().c_str(), entry->dst_address().str().c_str());

//
// Check whether we have already registered with the FEA
Expand Down
14 changes: 14 additions & 0 deletions xorp/site_scons/config/allconfig.py
Expand Up @@ -415,12 +415,26 @@ def DoAllConfig(env, conf, host_os):
prereq_netinet_ip_h.append('netinet/in.h')
if has_netinet_in_systm_h:
prereq_netinet_ip_h.append('netinet/in_systm.h')
prereq_mreqn_h = prereq_netinet_ip_h
has_netinet_ip_h = conf.CheckHeader(prereq_netinet_ip_h + ['netinet/ip.h'])
if has_netinet_ip_h:
prereq_mreqn_h.append('netinet/ip.h');

has_netinet_tcp_h = conf.CheckHeader(['sys/param.h', 'sys/socket.h', 'netinet/in.h', 'netinet/in_systm.h', 'netinet/ip.h', 'netinet/tcp.h'])
has_netinet_igmp_h = conf.CheckHeader(['sys/types.h', 'netinet/in.h', 'netinet/igmp.h'])
has_netinet_ether_h = conf.CheckHeader('netinet/ether.h')

# Check for ip_mreqn struct.
mreqn_header_includes = []
for s in prereq_mreqn_h:
mreqn_header_includes.append("#include <%s>\n" % s)
mreqn_header_includes = string.join(mreqn_header_includes, '')
has_struct_ip_mreqn = conf.CheckType('struct ip_mreqn', includes=mreqn_header_includes)
if not has_struct_ip_mreqn:
print "\nWARNING: No struct ip_mreqn found. Each interface must"
print " have a unique IP address or IP multicast (at least) will not"
print " be transmitted on the correct interface."

# Header file <netinet/if_ether.h> might need <sys/types.h>,
# <sys/socket.h>, <net/if.h>, and/or <netinet/in.h>
prereq_netinet_if_ether_h = []
Expand Down

0 comments on commit 843fee0

Please sign in to comment.