Here's a first attempt at using one rx socket per device, and binding to that particular device. This keeps us from receiving multicast traffic not destined for us when we are running
multiple instances of xorp on the same system.

This code appears to work, but it does not properly clean up sockets when devices
are un-configured.  I'll be working on that next.

This code will be less efficient than the old way if the OS doesn't support
SO_BINDTODEVICE, so I'll also add some code to mimic the old behaviour
in that case (ie, windows).

There's also some other cruft in there to deal with races around removing interfaces and removing the OSPF multicast groups. These changes have nothing in particular
to do with per-interface rx sockets.

Suggestions for improvements are welcome.

Thanks,
Ben

--
Ben Greear <[EMAIL PROTECTED]> Candela Technologies Inc http://www.candelatech.com


? data_plane/control_socket/click_socket.cc.flc
? data_plane/io/io_ip_socket.cc.ben
? data_plane/io/io_ip_socket.cc.flc
? data_plane/io/io_tcpudp_socket.cc.flc
Index: io_ip.hh
===================================================================
RCS file: /cvs/xorp/fea/io_ip.hh,v
retrieving revision 1.3
diff -u -r1.3 io_ip.hh
--- io_ip.hh	4 Jan 2008 03:15:47 -0000	1.3
+++ io_ip.hh	1 Mar 2008 00:55:57 -0000
@@ -255,10 +255,10 @@
     /**
      * Get the file descriptor for receiving protocol messages.
      *
-     * @return a reference to the file descriptor for receiving protocol
-     * messages.
+     * @return a pointer to the file descriptor for receiving protocol
+     * messages, or NULL if it cannot be found.
      */
-    virtual XorpFd& protocol_fd_in() = 0;
+    virtual XorpFd* mcast_protocol_fd_in() = 0;
 
 protected:
     /**
Index: io_ip_manager.cc
===================================================================
RCS file: /cvs/xorp/fea/io_ip_manager.cc,v
retrieving revision 1.12
diff -u -r1.12 io_ip_manager.cc
--- io_ip_manager.cc	4 Jan 2008 03:15:47 -0000	1.12
+++ io_ip_manager.cc	1 Mar 2008 00:55:58 -0000
@@ -457,6 +457,44 @@
     return (ret_value);
 }
 
+
+int
+IoIpComm::leave_all_multicast_groups(const string&	if_name,
+				const string&	vif_name,
+				string&		error_msg)
+{
+    //XLOG_ERROR("IoIpComm::leave_all_multicast_groups, if: %s  vif: %s\n",
+    //if_name.c_str(), vif_name.c_str());
+  start:
+    {
+	JoinedGroupsTable::iterator joined_iter;
+	for (joined_iter = _joined_groups_table.begin();
+	     joined_iter != _joined_groups_table.end(); joined_iter++) {
+	    //XLOG_ERROR("Found group, if: %s  vif: %s\n",
+	    //	       joined_iter->second.if_name().c_str(),
+	    //	       joined_iter->second.vif_name().c_str());
+	    if ((joined_iter->second.if_name() == if_name) &&
+		((vif_name.size() == 0) || (joined_iter->second.vif_name() == vif_name))) {
+
+		string tmp_vifn(joined_iter->second.vif_name());
+
+		//XLOG_ERROR("Matched, looking for receivers.\n");
+		set<string>::iterator ri = joined_iter->second.get_receivers().begin();
+		while (ri != joined_iter->second.get_receivers().end()) {
+		    //XLOG_ERROR("Found receiver: %s\n", ri->c_str());
+		    leave_multicast_group(if_name, tmp_vifn, joined_iter->second.group_address(),
+					  *ri, error_msg);
+		    // Maybe there are more...back out to top and search again.  This should keep our iterators
+		    // from being corrupted by the leave_multicast_group call.
+		    goto start;
+		}//for all receivers
+	    }//if this joined group matches our interface and vif (if specified)
+	}//for all joined groups
+    }//scoping brace
+    // We delete all we can find...whatever we found must have been OK.
+    return XORP_OK;
+}
+
 int
 IoIpComm::leave_multicast_group(const string&	if_name,
 				const string&	vif_name,
@@ -643,7 +681,7 @@
 }
 
 XorpFd
-IoIpComm::first_valid_protocol_fd_in()
+IoIpComm::first_valid_mcast_protocol_fd_in()
 {
     XorpFd xorp_fd;
 
@@ -651,7 +689,7 @@
     IoIpPlugins::iterator iter;
     for (iter = _io_ip_plugins.begin(); iter != _io_ip_plugins.end(); ++iter) {
 	IoIp* io_ip = iter->second;
-	xorp_fd = io_ip->protocol_fd_in();
+	xorp_fd = *(io_ip->mcast_protocol_fd_in());
 	if (xorp_fd.is_valid())
 	    return (xorp_fd);
     }
@@ -1005,6 +1043,19 @@
     return (XORP_ERROR);
 }
 
+
+int IoIpManager::leave_all_multicast_groups(const string& if_name,
+				       const string& vif_name,
+				       string& error_msg) {
+    CommTable::iterator cti;
+    for (cti = _comm_table4.begin(); cti != _comm_table4.end(); cti++) {
+	IoIpComm* c = cti->second;
+	c->leave_all_multicast_groups(if_name, vif_name, error_msg);
+    }
+    return XORP_OK;
+}
+
+
 int
 IoIpManager::leave_multicast_group(const string&	receiver_name,
 				   const string&	if_name,
@@ -1053,7 +1104,7 @@
     int		family,
     uint8_t	ip_protocol,
     IoIpManager::UpcallReceiverCb receiver_cb,
-    XorpFd&	receiver_fd,
+    XorpFd&	mcast_receiver_fd,
     string&	error_msg)
 {
     SystemMulticastUpcallFilter* filter;
@@ -1093,7 +1144,7 @@
 	if (filter->ip_protocol() == ip_protocol) {
 	    // Already have this filter
 	    filter->set_receiver_cb(receiver_cb);
-	    receiver_fd = io_ip_comm->first_valid_protocol_fd_in();
+	    mcast_receiver_fd = io_ip_comm->first_valid_mcast_protocol_fd_in();
 	    return (XORP_OK);
 	}
     }
@@ -1110,7 +1161,7 @@
     // Add the filter to those associated with empty receiver_name
     filters.insert(FilterBag::value_type(receiver_name, filter));
 
-    receiver_fd = io_ip_comm->first_valid_protocol_fd_in();
+    mcast_receiver_fd = io_ip_comm->first_valid_mcast_protocol_fd_in();
 
     return (XORP_OK);
 }
Index: io_ip_manager.hh
===================================================================
RCS file: /cvs/xorp/fea/io_ip_manager.hh,v
retrieving revision 1.13
diff -u -r1.13 io_ip_manager.hh
--- io_ip_manager.hh	4 Jan 2008 03:15:47 -0000	1.13
+++ io_ip_manager.hh	1 Mar 2008 00:55:58 -0000
@@ -196,6 +196,8 @@
 	 */
 	bool empty() const { return _receivers.empty(); }
 
+	set<string>& get_receivers() { return _receivers; }
+
     private:
 	string		_if_name;
 	string		_vif_name;
@@ -398,6 +400,19 @@
 				      string&		error_msg);
 
     /**
+     * Leave all IP multicast groups on this interface.
+     * 
+     * @param if_name the interface through which packets should not be
+     * accepted.
+     * @param vif_name the vif through which packets should not be accepted.
+     * @param error_msg the error message (if error).
+     * @return XORP_OK on success, otherwise XORP_ERROR.
+     */
+    int leave_all_multicast_groups(const string& if_name,
+			      const string& vif_name,
+			      string& error_msg);
+
+    /**
      * Get the IP protocol.
      *
      * @return the IP protocol.
@@ -410,7 +425,7 @@
      * @return the first valid file descriptor for receiving protocol
      * messages.
      */
-    XorpFd first_valid_protocol_fd_in();
+    XorpFd first_valid_mcast_protocol_fd_in();
 
 private:
     IoIpComm(const IoIpComm&);			// Not implemented.
@@ -609,6 +624,12 @@
 			      const IPvX&	group_address,
 			      string&		error_msg);
 
+    /** Leave all multicast groups on this vif */
+    int leave_all_multicast_groups(const string& if_name,
+				   const string& vif_name,
+				   string& error_msg);
+
+
     /**
      * Register to receive multicast forwarding related upcalls from the
      * system.
@@ -628,7 +649,7 @@
     int register_system_multicast_upcall_receiver(int		family,
 						  uint8_t	ip_protocol,
 						  IoIpManager::UpcallReceiverCb receiver_cb,
-						  XorpFd&	receiver_fd,
+						  XorpFd&	mcast_receiver_fd,
 						  string&	error_msg);
 
     /**
Index: io_link_manager.cc
===================================================================
RCS file: /cvs/xorp/fea/io_link_manager.cc,v
retrieving revision 1.8
diff -u -r1.8 io_link_manager.cc
--- io_link_manager.cc	4 Jan 2008 03:15:47 -0000	1.8
+++ io_link_manager.cc	1 Mar 2008 00:55:59 -0000
@@ -893,6 +893,7 @@
     return (XORP_ERROR);
 }
 
+
 int
 IoLinkManager::register_data_plane_manager(FeaDataPlaneManager* fea_data_plane_manager,
 					   bool is_exclusive)
Index: io_link_manager.hh
===================================================================
RCS file: /cvs/xorp/fea/io_link_manager.hh,v
retrieving revision 1.8
diff -u -r1.8 io_link_manager.hh
--- io_link_manager.hh	4 Jan 2008 03:15:47 -0000	1.8
+++ io_link_manager.hh	1 Mar 2008 00:55:59 -0000
@@ -202,6 +202,8 @@
 	 */
 	bool empty() const { return _receivers.empty(); }
 
+	set<string>& get_receivers() { return _receivers; }
+
     private:
 	Mac		_group_address;
 	set<string>	_receivers;
Index: xrl_fea_target.cc
===================================================================
RCS file: /cvs/xorp/fea/xrl_fea_target.cc,v
retrieving revision 1.37
diff -u -r1.37 xrl_fea_target.cc
--- xrl_fea_target.cc	4 Jan 2008 03:15:51 -0000	1.37
+++ xrl_fea_target.cc	1 Mar 2008 00:56:02 -0000
@@ -1438,6 +1438,15 @@
     IfTree& iftree = ifconfig().local_config();
     string error_msg;
 
+    XLOG_ERROR("Deleting interface, ifname: %s\n", ifname.c_str());
+
+    // Hack:  Remove multicast addrs first. --Ben
+    string empty;
+    _io_ip_manager.leave_all_multicast_groups(ifname, empty, error_msg);
+    if (error_msg.size()) {
+	XLOG_ERROR(error_msg.c_str());
+    }
+
     if (ifconfig().add_transaction_operation(
 	    tid,
 	    new RemoveInterface(iftree, ifname),
@@ -1708,6 +1717,15 @@
     IfTree& iftree = ifconfig().local_config();
     string error_msg;
 
+
+    XLOG_ERROR("Deleting vif, ifname: %s  vif: %s\n", ifname.c_str(), vifname.c_str());
+
+    // Hack:  Remove multicast addrs first. --Ben
+    _io_ip_manager.leave_all_multicast_groups(ifname, vifname, error_msg);
+    if (error_msg.size()) {
+	XLOG_ERROR(error_msg.c_str());
+    }
+
     if (ifconfig().add_transaction_operation(
 	    tid,
 	    new RemoveInterfaceVif(iftree, ifname, vifname),
Index: data_plane/control_socket/netlink_socket_utilities.cc
===================================================================
RCS file: /cvs/xorp/fea/data_plane/control_socket/netlink_socket_utilities.cc,v
retrieving revision 1.12
diff -u -r1.12 netlink_socket_utilities.cc
--- data_plane/control_socket/netlink_socket_utilities.cc	8 Jan 2008 23:30:09 -0000	1.12
+++ data_plane/control_socket/netlink_socket_utilities.cc	1 Mar 2008 00:56:03 -0000
@@ -332,9 +332,10 @@
 	const IfTreeVif* vifp = iftree.find_vif(if_index);
 	if (vifp == NULL) {
 	    if (! is_deleted) {
-		XLOG_FATAL("Could not find interface and vif for index %d",
+		XLOG_ERROR("Could not find interface and vif for index %d",
 			   if_index);
 	    }
+	    return XORP_ERROR;
 	}
 	if_name = vifp->ifname();
 	vif_name = vifp->vifname();
Index: data_plane/fibconfig/fibconfig_entry_set_netlink_socket.cc
===================================================================
RCS file: /cvs/xorp/fea/data_plane/fibconfig/fibconfig_entry_set_netlink_socket.cc,v
retrieving revision 1.17
diff -u -r1.17 fibconfig_entry_set_netlink_socket.cc
--- data_plane/fibconfig/fibconfig_entry_set_netlink_socket.cc	4 Jan 2008 03:15:59 -0000	1.17
+++ data_plane/fibconfig/fibconfig_entry_set_netlink_socket.cc	1 Mar 2008 00:56:04 -0000
@@ -275,9 +275,9 @@
 	if (if_index != NULL)
 	    break;
 
-	XLOG_FATAL("Could not find interface index for interface %s vif %s",
+	XLOG_ERROR("Could not find interface index for interface %s vif %s",
 		   fte.ifname().c_str(), fte.vifname().c_str());
-	break;
+	return XORP_ERROR;
     } while (false);
 
     //
Index: data_plane/ifconfig/ifconfig_parse_netlink_socket.cc
===================================================================
RCS file: /cvs/xorp/fea/data_plane/ifconfig/ifconfig_parse_netlink_socket.cc,v
retrieving revision 1.17
diff -u -r1.17 ifconfig_parse_netlink_socket.cc
--- data_plane/ifconfig/ifconfig_parse_netlink_socket.cc	21 Feb 2008 02:02:33 -0000	1.17
+++ data_plane/ifconfig/ifconfig_parse_netlink_socket.cc	1 Mar 2008 00:56:05 -0000
@@ -603,7 +603,8 @@
 	    //
 	    return;
 	}
-	XLOG_FATAL("Could not find vif with index %u in IfTree", if_index);
+	XLOG_ERROR("Could not find vif with index %u in IfTree", if_index);
+        return;
     }
     debug_msg("Address event on interface %s vif %s with interface index %u\n",
 	      vifp->ifname().c_str(), vifp->vifname().c_str(),
Index: data_plane/io/io_ip_dummy.hh
===================================================================
RCS file: /cvs/xorp/fea/data_plane/io/io_ip_dummy.hh,v
retrieving revision 1.3
diff -u -r1.3 io_ip_dummy.hh
--- data_plane/io/io_ip_dummy.hh	4 Jan 2008 03:16:14 -0000	1.3
+++ data_plane/io/io_ip_dummy.hh	1 Mar 2008 00:56:05 -0000
@@ -183,7 +183,9 @@
      * @return a reference to the file descriptor for receiving protocol
      * messages.
      */
-    XorpFd& protocol_fd_in() { return (_dummy_protocol_fd_in); }
+    XorpFd* mcast_protocol_fd_in() {
+	return (&_dummy_protocol_fd_in);
+    }
 
 private:
     // Private state
Index: data_plane/io/io_ip_socket.cc
===================================================================
RCS file: /cvs/xorp/fea/data_plane/io/io_ip_socket.cc,v
retrieving revision 1.17
diff -u -r1.17 io_ip_socket.cc
--- data_plane/io/io_ip_socket.cc	4 Jan 2008 03:16:14 -0000	1.17
+++ data_plane/io/io_ip_socket.cc	1 Mar 2008 00:56:07 -0000
@@ -515,26 +515,37 @@
 				 string& error_msg)
 {
     const IfTreeVif* vifp;
+    XorpFd* _proto_socket_in = NULL;
 
     // Find the vif
     vifp = iftree().find_vif(if_name, vif_name);
     if (vifp == NULL) {
-	error_msg = c_format("Joining multicast group %s failed: "
+	error_msg += c_format("Joining multicast group %s failed: "
 			     "interface %s vif %s not found",
 			     cstring(group),
 			     if_name.c_str(),
 			     vif_name.c_str());
-	return (XORP_ERROR);
+	goto out_err;
+    }
+
+    _proto_socket_in = findOrCreateInputSocket(if_name, vif_name, error_msg);
+
+    if (! _proto_socket_in) {
+	string em = c_format("ERROR:  Could not find or create input socket, if_name: %s  vif_name: %s  error_msg: %s",
+			     if_name.c_str(), vif_name.c_str(), error_msg.c_str());
+	XLOG_WARNING("%s", em.c_str());
+	error_msg += em;
+	goto out_err;
     }
     
 #if 0	// TODO: enable or disable the enabled() check?
     if (! vifp->enabled()) {
-	error_msg = c_format("Cannot join group %s on interface %s vif %s: "
+	error_msg += c_format("Cannot join group %s on interface %s vif %s: "
 			     "interface/vif is DOWN",
 			     cstring(group),
 			     if_name.c_str(),
 			     vif_name.c_str());
-	return (XORP_ERROR);
+	goto out_err;
     }
 #endif // 0/1
     
@@ -547,12 +558,12 @@
 	// Find the first address
 	IfTreeVif::IPv4Map::const_iterator ai = vifp->ipv4addrs().begin();
 	if (ai == vifp->ipv4addrs().end()) {
-	    error_msg = c_format("Cannot join group %s on interface %s vif %s: "
+	    error_msg += c_format("Cannot join group %s on interface %s vif %s: "
 				 "interface/vif has no address",
 				 cstring(group),
 				 if_name.c_str(),
 				 vif_name.c_str());
-	    return (XORP_ERROR);
+	    goto out_err;
 	}
 	const IfTreeAddr4& fa = ai->second;
 	
@@ -560,14 +571,18 @@
 	group.copy_out(mreq.imr_multiaddr);
 	mreq.imr_interface.s_addr = in_addr.s_addr;
 
-	if (setsockopt(_proto_socket_in, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+	if (setsockopt(*_proto_socket_in, IPPROTO_IP, IP_ADD_MEMBERSHIP,
 		       XORP_SOCKOPT_CAST(&mreq), sizeof(mreq)) < 0) {
-	    error_msg = c_format("Cannot join group %s on interface %s vif %s: %s",
+	    error_msg += c_format("Cannot join group %s on interface %s vif %s: %s",
 				 cstring(group),
 				 if_name.c_str(),
 				 vif_name.c_str(),
 				 strerror(errno));
-	    return (XORP_ERROR);
+	    goto out_err;
+	}
+	else {
+	    XLOG_ERROR("Joined IPv4 group: %s on interface %s vif %s",
+		       cstring(group), if_name.c_str(), vif_name.c_str());
 	}
     }
     break;
@@ -576,22 +591,26 @@
     case AF_INET6:
     {
 #ifndef HAVE_IPV6_MULTICAST
-	error_msg = c_format("join_multicast_group() failed: "
+	error_msg += c_format("join_multicast_group() failed: "
 			     "IPv6 multicast not supported");
-	return (XORP_ERROR);
+	goto out_err;
 #else
 	struct ipv6_mreq mreq6;
 	
 	group.copy_out(mreq6.ipv6mr_multiaddr);
 	mreq6.ipv6mr_interface = vifp->pif_index();
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+	if (setsockopt(*_proto_socket_in, IPPROTO_IPV6, IPV6_JOIN_GROUP,
 		       XORP_SOCKOPT_CAST(&mreq6), sizeof(mreq6)) < 0) {
-	    error_msg = c_format("Cannot join group %s on interface %s vif %s: %s",
+	    error_msg += c_format("Cannot join group %s on interface %s vif %s: %s",
 				 cstring(group),
 				 if_name.c_str(),
 				 vif_name.c_str(),
 				 strerror(errno));
-	    return (XORP_ERROR);
+	    goto out_err;
+	}
+	else {
+	    XLOG_ERROR("Joined IPv6 group: %s on interface %s vif %s",
+		       cstring(group), if_name.c_str(), vif_name.c_str());
 	}
 #endif // HAVE_IPV6_MULTICAST
     }
@@ -600,13 +619,61 @@
     
     default:
 	XLOG_UNREACHABLE();
-	error_msg = c_format("Invalid address family %d", family());
-	return (XORP_ERROR);
+	error_msg += c_format("Invalid address family %d", family());
+	goto out_err;
     }
     
     return (XORP_OK);
+
+  out_err:
+    if (error_msg.size()) {
+	XLOG_ERROR("ERROR in join_multicast_group: %s", error_msg.c_str());
+    }
+    return XORP_ERROR;
 }
 
+
+XorpFd* IoIpSocket::mcast_protocol_fd_in() {
+    if (! _mcast_proto_socket_in.is_valid()) {
+	// Try to open the socket.
+	_mcast_proto_socket_in = socket(family(), SOCK_RAW, ip_protocol());
+	if (!_mcast_proto_socket_in.is_valid()) {
+	    char *errstr;
+
+#ifdef HAVE_STRERROR
+	    errstr = strerror(errno);
+#else
+	    errstr = "unknown error";
+#endif
+	    XLOG_WARNING("Cannot open multicast IP protocol %u raw socket: %s",
+				 ip_protocol(), errstr);
+	}
+	else {
+	    string err_msg;
+	    initializeInputSocket(&_mcast_proto_socket_in, err_msg);
+	    if (err_msg.size()) {
+		XLOG_WARNING("%s", err_msg.c_str());
+	    }
+	}
+    }
+    return &_mcast_proto_socket_in;
+}
+
+
+XorpFd* IoIpSocket::findExistingInputSocket(const string& if_name, const string& vif_name) {
+    string k(if_name);
+    k += " ";
+    k += vif_name;
+    map<string, XorpFd*>::iterator i = _proto_sockets_in.find(k);
+    if (i == _proto_sockets_in.end()) {
+	return NULL;
+    }
+    else {
+	return i->second;
+    }
+}
+
+
 int
 IoIpSocket::leave_multicast_group(const string& if_name,
 				  const string& vif_name,
@@ -618,18 +685,28 @@
     // Find the vif
     vifp = iftree().find_vif(if_name, vif_name);
     if (vifp == NULL) {
-	error_msg = c_format("Leaving multicast group %s failed: "
-			     "interface %s vif %s not found",
+	error_msg += c_format("Leaving multicast group %s failed: "
+			     "interface %s vif %s not found\n",
 			     cstring(group),
 			     if_name.c_str(),
 			     vif_name.c_str());
 	return (XORP_ERROR);
     }
+
+    XorpFd* _proto_socket_in = findExistingInputSocket(if_name, vif_name);
+    if (!_proto_socket_in) {
+	error_msg += c_format("Leaving multicast group %s failed: "
+			     "interface %s vif %s does not have a socket assigned.\n",
+			      cstring(group),
+			      if_name.c_str(),
+			      vif_name.c_str());
+	return (XORP_ERROR);
+    }
     
 #if 0	// TODO: enable or disable the enabled() check?
     if (! vifp->enabled()) {
-	error_msg = c_format("Cannot leave group %s on interface %s vif %s: "
-			     "interface/vif is DOWN",
+	error_msg += c_format("Cannot leave group %s on interface %s vif %s: "
+			     "interface/vif is DOWN\n",
 			     cstring(group),
 			     if_name.c_str(),
 			     vif_name.c_str());
@@ -646,8 +723,8 @@
 	// Find the first address
 	IfTreeVif::IPv4Map::const_iterator ai = vifp->ipv4addrs().begin();
 	if (ai == vifp->ipv4addrs().end()) {
-	    error_msg = c_format("Cannot leave group %s on interface %s vif %s: "
-				 "interface/vif has no address",
+	    error_msg += c_format("Cannot leave group %s on interface %s vif %s: "
+				 "interface/vif has no address\n",
 				 cstring(group),
 				 if_name.c_str(),
 				 vif_name.c_str());
@@ -658,15 +735,19 @@
 	fa.addr().copy_out(in_addr);
 	group.copy_out(mreq.imr_multiaddr);
 	mreq.imr_interface.s_addr = in_addr.s_addr;
-	if (setsockopt(_proto_socket_in, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+	if (setsockopt(*_proto_socket_in, IPPROTO_IP, IP_DROP_MEMBERSHIP,
 		       XORP_SOCKOPT_CAST(&mreq), sizeof(mreq)) < 0) {
-	    error_msg = c_format("Cannot leave group %s on interface %s vif %s: %s",
+	    error_msg += c_format("Cannot leave group %s on interface %s vif %s: %s\n",
 				 cstring(group),
 				 if_name.c_str(),
 				 vif_name.c_str(),
 				 strerror(errno));
 	    return (XORP_ERROR);
 	}
+	else {
+	    XLOG_ERROR("Left group: %s on interface %s vif %s",
+		       cstring(group), if_name.c_str(), vif_name.c_str());
+	}
     }
     break;
     
@@ -674,17 +755,17 @@
     case AF_INET6:
     {
 #ifndef HAVE_IPV6_MULTICAST
-	error_msg = c_format("leave_multicast_group() failed: "
-			     "IPv6 multicast not supported");
+	error_msg += c_format("leave_multicast_group() failed: "
+			     "IPv6 multicast not supported\n");
 	return (XORP_ERROR);
 #else
 	struct ipv6_mreq mreq6;
 	
 	group.copy_out(mreq6.ipv6mr_multiaddr);
 	mreq6.ipv6mr_interface = vifp->pif_index();
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+	if (setsockopt(*_proto_socket_in, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
 		       XORP_SOCKOPT_CAST(&mreq6), sizeof(mreq6)) < 0) {
-	    error_msg = c_format("Cannot leave group %s on interface %s vif %s: %s",
+	    error_msg += c_format("Cannot leave group %s on interface %s vif %s: %s\n",
 				 cstring(group),
 				 if_name.c_str(),
 				 vif_name.c_str(),
@@ -698,25 +779,27 @@
     
     default:
 	XLOG_UNREACHABLE();
-	error_msg = c_format("Invalid address family %d", family());
+	error_msg += c_format("Invalid address family %d\n", family());
 	return (XORP_ERROR);
     }
     
     return (XORP_OK);
 }
 
-int
-IoIpSocket::open_proto_sockets(string& error_msg)
-{
-    string dummy_error_msg;
 
-    if (_proto_socket_in.is_valid() && _proto_socket_out.is_valid())
-	return (XORP_OK);
-    
-    // If necessary, open the protocol sockets
-    if (! _proto_socket_in.is_valid()) {
-	_proto_socket_in = socket(family(), SOCK_RAW, ip_protocol());
-	if (!_proto_socket_in.is_valid()) {
+XorpFd* IoIpSocket::findOrCreateInputSocket(const string& if_name, const string& vif_name,
+					    string& error_msg) {
+    XorpFd* rv = findExistingInputSocket(if_name, vif_name);
+
+    string key(if_name);
+    key += " ";
+    key += vif_name;
+
+    if (!rv) {
+	// Create a new one
+	rv = new XorpFd();
+	*rv = socket(family(), SOCK_RAW, ip_protocol());
+	if (!rv->is_valid()) {
 	    char *errstr;
 
 #ifdef HAVE_STRERROR
@@ -724,28 +807,47 @@
 #else
 	    errstr = "unknown error";
 #endif
-	    error_msg = c_format("Cannot open IP protocol %u raw socket: %s",
-				 ip_protocol(), errstr);
-	    return (XORP_ERROR);
+	    error_msg += c_format("Cannot open IP protocol %u raw socket: %s",
+				  ip_protocol(), errstr);
+	    delete rv;
+	    return NULL;
+	}
+	else {
+	    _proto_sockets_in[key] = rv;
 	}
-    }
 
-    if (! _proto_socket_out.is_valid()) {
-	_proto_socket_out = socket(family(), SOCK_RAW, ip_protocol());
-	if (!_proto_socket_out.is_valid()) {
-	    char *errstr;
+	int rslt = initializeInputSocket(rv, error_msg);
+	if (rslt != XORP_OK) {
+	    _proto_sockets_in.erase(key);
+	    cleanupXorpFd(rv);
+	    return NULL;
+	}
 
+	// Bind to a particular interface.
+#ifdef SO_BINDTODEVICE
+	if (setsockopt(*rv, SOL_SOCKET, SO_BINDTODEVICE,
+		       vif_name.c_str(), vif_name.size() + 1)) {
+	    error_msg += c_format("ERROR:  IoIpSocket::open_proto_socket, setsockopt (BINDTODEVICE):  failed: %s",
 #ifdef HAVE_STRERROR
-	    errstr = strerror(errno);
+				  strerror(errno)
 #else
-	    errstr = "unknown error";
-#endif
-	    error_msg = c_format("Cannot open IP protocol %u raw socket: %s",
-				 ip_protocol(), errstr);
-	    return (XORP_ERROR);
+				  "unknown error"
+#endif 
+		);
+	}
+	else {
+	    XLOG_WARNING("Successfully bound socket: %i to interface: %s\n",
+			 (int)(*rv), vif_name.c_str());
 	}
+#endif
     }
 
+    return rv;
+}
+
+
+int IoIpSocket::initializeInputSocket(XorpFd* rv, string& error_msg) {
+
 #ifdef HOST_OS_WINDOWS
     switch (family()) {
     case AF_INET:
@@ -758,7 +860,7 @@
 	    int result;
 	    DWORD nbytes;
 
-	    result = WSAIoctl(_proto_socket_in,
+	    result = WSAIoctl(*rv,
 			      SIO_GET_EXTENSION_FUNCTION_POINTER,
 			      const_cast<GUID *>(&guidWSARecvMsg),
 			      sizeof(guidWSARecvMsg),
@@ -777,7 +879,7 @@
 	    int result;
 	    DWORD nbytes;
 
-	    result = WSAIoctl(_proto_socket_in,
+	    result = WSAIoctl(*rv,
 			      SIO_GET_EXTENSION_FUNCTION_POINTER,
 			      const_cast<GUID *>(&guidWSASendMsg),
 			      sizeof(guidWSASendMsg),
@@ -794,8 +896,8 @@
 #endif // HAVE_IPV6
     default:
 	XLOG_UNREACHABLE();
-	error_msg = c_format("Invalid address family %d", family());
-	return (XORP_ERROR);
+	error_msg += c_format("Invalid address family %d", family());
+	return XORP_ERROR;
     }
 #endif // HOST_OS_WINDOWS
 
@@ -804,43 +906,21 @@
     //
 
     // Lots of input buffering
-    if (comm_sock_set_rcvbuf(_proto_socket_in, SO_RCV_BUF_SIZE_MAX,
+    if (comm_sock_set_rcvbuf(*rv, SO_RCV_BUF_SIZE_MAX,
 			     SO_RCV_BUF_SIZE_MIN)
 	< SO_RCV_BUF_SIZE_MIN) {
-	error_msg = c_format("Cannot set the receiver buffer size: %s",
-			     comm_get_last_error_str());
-	close_proto_sockets(dummy_error_msg);
-	return (XORP_ERROR);
-    }
-    // Lots of output buffering
-    if (comm_sock_set_rcvbuf(_proto_socket_out, SO_SND_BUF_SIZE_MAX,
-			     SO_SND_BUF_SIZE_MIN)
-	< SO_SND_BUF_SIZE_MIN) {
-	error_msg = c_format("Cannot set the sender buffer size: %s",
-			     comm_get_last_error_str());
-	close_proto_sockets(dummy_error_msg);
-	return (XORP_ERROR);
-    }
-    // Include IP header when sending (XXX: doesn't do anything for IPv6)
-    if (enable_ip_hdr_include(true, error_msg) != XORP_OK) {
-	close_proto_sockets(dummy_error_msg);
-	return (XORP_ERROR);
+	error_msg += c_format("Cannot set the receiver buffer size: %s",
+			      comm_get_last_error_str());
+	// doesn't seem fatal....continue on.
+	//close_proto_sockets(error_msg);
+	//return (XORP_ERROR);
     }
+
     // Show interest in receiving information from IP header
-    if (enable_recv_pktinfo(true, error_msg) != XORP_OK) {
-	close_proto_sockets(dummy_error_msg);
-	return (XORP_ERROR);
-    }
-    // Restrict multicast TTL
-    if (set_multicast_ttl(MINTTL, error_msg) != XORP_OK) {
-	close_proto_sockets(dummy_error_msg);
-	return (XORP_ERROR);
-    }
-    // Disable mcast loopback
-    if (enable_multicast_loopback(false, error_msg) != XORP_OK) {
-	close_proto_sockets(dummy_error_msg);
-	return (XORP_ERROR);
+    if (enable_recv_pktinfo(rv, true, error_msg) != XORP_OK) {
+	return XORP_ERROR;
     }
+
     // Protocol-specific setup
     switch (family()) {
     case AF_INET:
@@ -870,12 +950,11 @@
 	    }
 #endif // 0
 #endif // HAVE_IPV6_MULTICAST_ROUTING
-	    if (setsockopt(_proto_socket_in, ip_protocol(), ICMP6_FILTER,
+	    if (setsockopt(*rv, ip_protocol(), ICMP6_FILTER,
 			   XORP_SOCKOPT_CAST(&filter), sizeof(filter)) < 0) {
-		close_proto_sockets(dummy_error_msg);
-		error_msg = c_format("setsockopt(ICMP6_FILTER) failed: %s",
-				     strerror(errno));
-		return (XORP_ERROR);
+		error_msg += c_format("setsockopt(ICMP6_FILTER) failed: %s",
+				      strerror(errno));
+		return XORP_ERROR;
 	    }
 	}
     }
@@ -883,8 +962,8 @@
 #endif // HAVE_IPV6
     default:
 	XLOG_UNREACHABLE();
-	error_msg = c_format("Invalid address family %d", family());
-	return (XORP_ERROR);
+	error_msg += c_format("Invalid address family %d", family());
+	return XORP_ERROR;
     }
 
 #ifdef HOST_OS_WINDOWS
@@ -898,20 +977,77 @@
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = INADDR_ANY;
     
-    if (SOCKET_ERROR == bind(_proto_socket_in, (sockaddr *)&sin,
+    if (SOCKET_ERROR == bind(*rv, (sockaddr *)&sin,
 			     sizeof(sockaddr_in))) {
 	XLOG_WARNING("bind() failed: %s\n", win_strerror(GetLastError()));
     }
 #endif // HOST_OS_WINDOWS
 
     // Assign a method to read from this socket
-    if (eventloop().add_ioevent_cb(_proto_socket_in, IOT_READ,
+    if (eventloop().add_ioevent_cb(*rv, IOT_READ,
 				   callback(this,
 					    &IoIpSocket::proto_socket_read))
 	== false) {
+	error_msg += c_format("Cannot add protocol socket: %i to the set of "
+			      "sockets to read from in the event loop", (int)(*rv));
+	return XORP_ERROR;
+    }
+
+    return XORP_OK;
+}//initializeInputSocket
+
+
+int
+IoIpSocket::open_proto_sockets(string& error_msg)
+{
+    string dummy_error_msg;
+
+    // We will open input sockets as interfaces are registered (due to listening for mcast addrs)
+    if (_proto_socket_out.is_valid())
+	return (XORP_OK);
+    
+    if (! _proto_socket_out.is_valid()) {
+	_proto_socket_out = socket(family(), SOCK_RAW, ip_protocol());
+	if (!_proto_socket_out.is_valid()) {
+	    char *errstr;
+
+#ifdef HAVE_STRERROR
+	    errstr = strerror(errno);
+#else
+	    errstr = "unknown error";
+#endif
+	    error_msg = c_format("Cannot open IP protocol %u raw socket: %s",
+				 ip_protocol(), errstr);
+	    return (XORP_ERROR);
+	}
+    }
+
+    //
+    // Set various socket options
+    //
+
+    // Lots of output buffering
+    if (comm_sock_set_rcvbuf(_proto_socket_out, SO_SND_BUF_SIZE_MAX,
+			     SO_SND_BUF_SIZE_MIN)
+	< SO_SND_BUF_SIZE_MIN) {
+	error_msg = c_format("Cannot set the sender buffer size: %s",
+			     comm_get_last_error_str());
+	close_proto_sockets(dummy_error_msg);
+	return (XORP_ERROR);
+    }
+    // Include IP header when sending (XXX: doesn't do anything for IPv6)
+    if (enable_ip_hdr_include(true, error_msg) != XORP_OK) {
+	close_proto_sockets(dummy_error_msg);
+	return (XORP_ERROR);
+    }
+    // Restrict multicast TTL
+    if (set_multicast_ttl(MINTTL, error_msg) != XORP_OK) {
+	close_proto_sockets(dummy_error_msg);
+	return (XORP_ERROR);
+    }
+    // Disable mcast loopback
+    if (enable_multicast_loopback(false, error_msg) != XORP_OK) {
 	close_proto_sockets(dummy_error_msg);
-	error_msg = c_format("Cannot add a protocol socket to the set of "
-			     "sockets to read from in the event loop");
 	return (XORP_ERROR);
     }
 
@@ -931,12 +1067,30 @@
 	_proto_socket_out.clear();
     }
 
+    if (_mcast_proto_socket_in.is_valid()) {
+	comm_close(_mcast_proto_socket_in);
+	_mcast_proto_socket_in.clear();
+    }
+
+    map<string, XorpFd*>::iterator i;
+    for (i = _proto_sockets_in.begin(); i != _proto_sockets_in.end(); i++) {
+    
+	XorpFd* fd = i->second;
+
+	cleanupXorpFd(fd);
+    }
+    _proto_sockets_in.clear();
+
+    return (XORP_OK);
+}
+
+int IoIpSocket::cleanupXorpFd(XorpFd* fd) {
     //
     // Close the incoming protocol socket
     //
-    if (_proto_socket_in.is_valid()) {
+    if (fd->is_valid()) {
 	// Remove it just in case, even though it may not be select()-ed
-	eventloop().remove_ioevent_cb(_proto_socket_in);
+	eventloop().remove_ioevent_cb(*fd);
 
 #ifdef HOST_OS_WINDOWS
 	switch (family()) {
@@ -955,14 +1109,15 @@
 	    return (XORP_ERROR);
 	}
 #endif // HOST_OS_WINDOWS
-
-	comm_close(_proto_socket_in);
-	_proto_socket_in.clear();
+	
+	comm_close(*fd);
+	fd->clear();
     }
-    
-    return (XORP_OK);
+    delete fd;
+    return XORP_OK;
 }
 
+
 int
 IoIpSocket::enable_ip_hdr_include(bool is_enabled, string& error_msg)
 {
@@ -1002,7 +1157,7 @@
 }
 
 int
-IoIpSocket::enable_recv_pktinfo(bool is_enabled, string& error_msg)
+IoIpSocket::enable_recv_pktinfo(XorpFd* input_fd, bool is_enabled, string& error_msg)
 {
     switch (family()) {
     case AF_INET:
@@ -1015,7 +1170,7 @@
 	//
 #ifdef IP_RECVIF
 	// XXX: BSD
-	if (setsockopt(_proto_socket_in, IPPROTO_IP, IP_RECVIF,
+	if (setsockopt(*input_fd, IPPROTO_IP, IP_RECVIF,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    XLOG_ERROR("setsockopt(IP_RECVIF, %u) failed: %s",
 		       bool_flag, strerror(errno));
@@ -1025,7 +1180,7 @@
 
 #ifdef IP_PKTINFO
 	// XXX: Linux
-	if (setsockopt(_proto_socket_in, IPPROTO_IP, IP_PKTINFO,
+	if (setsockopt(*input_fd, IPPROTO_IP, IP_PKTINFO,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    XLOG_ERROR("setsockopt(IP_PKTINFO, %u) failed: %s",
 		       bool_flag, strerror(errno));
@@ -1048,7 +1203,7 @@
 	//
 #ifdef IPV6_RECVPKTINFO
 	// The new option (applies to receiving only)
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_RECVPKTINFO, %u) failed: %s",
 				 bool_flag, strerror(errno));
@@ -1056,7 +1211,7 @@
 	}
 #else
 	// The old option (see RFC-2292)
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_PKTINFO,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_PKTINFO,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_PKTINFO, %u) failed: %s",
 				 bool_flag, strerror(errno));
@@ -1068,14 +1223,14 @@
 	// Hop-limit field
 	//
 #ifdef IPV6_RECVHOPLIMIT
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_RECVHOPLIMIT, %u) failed: %s",
 				 bool_flag, strerror(errno));
 	    return (XORP_ERROR);
 	}
 #else
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_HOPLIMIT,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_HOPLIMIT,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_HOPLIMIT, %u) failed: %s",
 				 bool_flag, strerror(errno));
@@ -1087,7 +1242,7 @@
 	// Traffic class value
 	//
 #ifdef IPV6_RECVTCLASS
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_RECVTCLASS,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_RECVTCLASS,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_RECVTCLASS, %u) failed: %s",
 				 bool_flag, strerror(errno));
@@ -1099,14 +1254,14 @@
 	// Hop-by-hop options
 	//
 #ifdef IPV6_RECVHOPOPTS
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_RECVHOPOPTS,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_RECVHOPOPTS,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_RECVHOPOPTS, %u) failed: %s",
 				 bool_flag, strerror(errno));
 	    return (XORP_ERROR);
 	}
 #else
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_HOPOPTS,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_HOPOPTS,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_HOPOPTS, %u) failed: %s",
 				 bool_flag, strerror(errno));
@@ -1118,14 +1273,14 @@
 	// Routing header options
 	//
 #ifdef IPV6_RECVRTHDR
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_RECVRTHDR,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_RECVRTHDR,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_RECVRTHDR, %u) failed: %s",
 				 bool_flag, strerror(errno));
 	    return (XORP_ERROR);
 	}
 #else
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_RTHDR,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_RTHDR,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_RTHDR, %u) failed: %s",
 				 bool_flag, strerror(errno));
@@ -1137,14 +1292,14 @@
 	// Destination options
 	//
 #ifdef IPV6_RECVDSTOPTS
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_RECVDSTOPTS,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_RECVDSTOPTS,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_RECVDSTOPTS, %u) failed: %s",
 				 bool_flag, strerror(errno));
 	    return (XORP_ERROR);
 	}
 #else
-	if (setsockopt(_proto_socket_in, IPPROTO_IPV6, IPV6_DSTOPTS,
+	if (setsockopt(*input_fd, IPPROTO_IPV6, IPV6_DSTOPTS,
 		       XORP_SOCKOPT_CAST(&bool_flag), sizeof(bool_flag)) < 0) {
 	    error_msg = c_format("setsockopt(IPV6_DSTOPTS, %u) failed: %s",
 				 bool_flag, strerror(errno));
@@ -1187,6 +1342,8 @@
     UNUSED(int_val);
     UNUSED(cmsg_data);
 
+    XLOG_WARNING("proto_socket_read, fd: %i", (int)(fd));
+
 #ifndef HOST_OS_WINDOWS
     // Zero and reset various fields
     _rcvmh.msg_controllen = CMSG_BUF_SIZE;
@@ -1210,12 +1367,12 @@
     }
    
     // Read from the socket
-    nbytes = recvmsg(_proto_socket_in, &_rcvmh, 0);
+    nbytes = recvmsg(fd, &_rcvmh, 0);
     if (nbytes < 0) {
 	if (errno == EINTR)
 	    return;		// OK: restart receiving
 	XLOG_ERROR("recvmsg() on socket %s failed: %s",
-		   _proto_socket_in.str().c_str(), strerror(errno));
+		   fd.str().c_str(), strerror(errno));
 	return;			// Error
     }
 
@@ -1227,12 +1384,12 @@
 	struct sockaddr_storage from;
 	socklen_t from_len = sizeof(from);
 
-	nbytes = recvfrom(_proto_socket_in, XORP_BUF_CAST(_rcvbuf),
+	nbytes = recvfrom(fd, XORP_BUF_CAST(_rcvbuf),
 			  IO_BUF_SIZE, 0,
 			  reinterpret_cast<struct sockaddr *>(&from),
 			  &from_len);
 	debug_msg("Read fd %s, %d bytes\n",
-		  _proto_socket_in.str().c_str(), XORP_INT_CAST(nbytes));
+		  fd.str().c_str(), XORP_INT_CAST(nbytes));
 	if (nbytes < 0) {
 	    // XLOG_ERROR("recvfrom() failed: %s", strerror(errno));
 	    return;			// Error
@@ -1258,10 +1415,10 @@
 	    XLOG_ERROR("lpWSARecvMsg is NULL");
 	    return;			// Error
 	}
-	error = lpWSARecvMsg(_proto_socket_in, &mh, &nrecvd, NULL, NULL);
+	error = lpWSARecvMsg(fd, &mh, &nrecvd, NULL, NULL);
 	nbytes = (ssize_t)nrecvd;
 	debug_msg("Read fd %s, %d bytes\n",
-		  _proto_socket_in.str().c_str(), XORP_INT_CAST(nbytes));
+		  fd.str().c_str(), XORP_INT_CAST(nbytes));
 	if (nbytes < 0) {
 	    // XLOG_ERROR("lpWSARecvMsg() failed: %s", strerror(errno));
 	    return;			// Error
@@ -1748,10 +1905,36 @@
     
     if ((ifp == NULL) || (vifp == NULL)) {
 	// No vif found. Ignore this packet.
-	XLOG_WARNING("proto_socket_read() failed: "
-		     "RX packet from %s to %s pif_index %u: no vif found",
-		     cstring(src_address), cstring(dst_address), pif_index);
-	return;			// Error
+	static uint32_t bad_ifs = 0;
+	bad_ifs++;
+	if ((bad_ifs % 1000) == 0) {
+	    XLOG_WARNING("proto_socket_read() warning:  Received: %u packets for vifs not in use by this instance",
+			 bad_ifs);
+	}
+	if (1 || (pif_index == 1)) { // idx 1 is 'lo', and we shouldn't see pkts from here if we have bound correctly
+	    XLOG_WARNING("proto_socket_read() failed: "
+			 "RX packet from %s to %s pif_index %u: no vif found",
+			 cstring(src_address), cstring(dst_address), pif_index);
+	}
+	
+#if 0
+	if (pif_index != 0) {
+	    // So, since we shouldn't be receiving here..we should un-register this socket.
+	    // We have to find it the hard way since we don't know the name of the interface.
+	    map<string, XorpFd*>::iterator i;
+	    for (i = _proto_sockets_in.begin(); i != _proto_sockets_in.end(); i++) {
+		XorpFd* mfd = i->second;
+		if ((int)(*mfd) == (int)(fd)) {
+		    XLOG_WARNING("closing socket: %i on interface: %s because it does not seem to exist anymore, pif_index: %u\n",
+				 (int)(fd), i->first.c_str(), pif_index);
+		    _proto_sockets_in.erase(i);
+		    cleanupXorpFd(mfd);
+		    break;
+		}
+	    }   
+	}
+#endif
+	return;// Error
     }
     if (! (ifp->enabled() || vifp->enabled())) {
 	// This vif is down. Silently ignore this packet.
Index: data_plane/io/io_ip_socket.hh
===================================================================
RCS file: /cvs/xorp/fea/data_plane/io/io_ip_socket.hh,v
retrieving revision 1.10
diff -u -r1.10 io_ip_socket.hh
--- data_plane/io/io_ip_socket.hh	4 Jan 2008 03:16:14 -0000	1.10
+++ data_plane/io/io_ip_socket.hh	1 Mar 2008 00:56:07 -0000
@@ -180,12 +180,18 @@
 			    string&		error_msg);
 
     /**
-     * Get the file descriptor for receiving protocol messages.
+     * Get the file descriptor for receiving protocol messages on the specified vif.
      *
      * @return a reference to the file descriptor for receiving protocol
      * messages.
      */
-    XorpFd& protocol_fd_in() { return (_proto_socket_in); }
+    XorpFd* findExistingInputSocket(const string& if_name, const string& vif_name);
+
+    /** Get the input file descriptor to be used for multicast routing.  This
+     * should not be bound to any specific interface.  Returns NULL if cannot
+     * find or create one.
+     */
+    XorpFd* mcast_protocol_fd_in();
 
 private:
     /**
@@ -199,6 +205,16 @@
      */
     int		open_proto_sockets(string& error_msg);
 
+
+    /** Returns XORP_ERROR on error. */
+    int initializeInputSocket(XorpFd* rv, string& error_msg);
+
+    /** Find or create an input socket for the specified VIF.  Returns NULL
+     * if the socket cannot be found or created.
+     */
+    XorpFd* findOrCreateInputSocket(const string& if_name, const string& vif_name,
+				    string& error_msg);
+
     /**
      * Close the protocol sockets.
      * 
@@ -207,6 +223,11 @@
      */
     int		close_proto_sockets(string& error_msg);
 
+    /** Helper method to close a single socket.  Does not remove from
+     * socket map structure.  Deletes memory associated with 'fd'.
+     */
+    int cleanupXorpFd(XorpFd* fd);
+
     /**
      * Enable/disable the "Header Included" option (for IPv4) on the outgoing
      * protocol socket.
@@ -239,7 +260,7 @@
      * @param error_msg the error message (if error).
      * @return XORP_OK on success, otherwise XORP_ERROR.
      */
-    int		enable_recv_pktinfo(bool is_enabled, string& error_msg);
+    int enable_recv_pktinfo(XorpFd* input_fd, bool is_enabled, string& error_msg);
 
     /**
      * Read data from a protocol socket, and then call the appropriate protocol
@@ -269,7 +290,10 @@
 				      string&		error_msg);
 
     // Private state
-    XorpFd	_proto_socket_in;    // The socket to receive protocol message
+    //XorpFd	_proto_socket_in;    // The socket to receive protocol message
+    // The key is "if_name vif_name"
+    map<string, XorpFd*> _proto_sockets_in;
+    XorpFd        _mcast_proto_socket_in;
     XorpFd	_proto_socket_out;   // The socket to end protocol message
     bool	_is_ip_hdr_included; // True if IP header is included on send
     uint16_t	_ip_id;		     // IPv4 Header ID
_______________________________________________
Xorp-hackers mailing list
[email protected]
http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-hackers

Reply via email to