Exemplo n.º 1
0
bool route_table_mgr::route_resolve(IN route_rule_table_key key, OUT in_addr_t *p_src, OUT in_addr_t *p_gw /*NULL*/)
{
	in_addr_t dst = key.get_dst_ip();
	ip_address dst_addr = dst;
	rt_mgr_logdbg("dst addr '%s'", dst_addr.to_str().c_str());

	route_val *p_val = NULL;
	std::deque<unsigned char> table_id_list;
	
	g_p_rule_table_mgr->rule_resolve(key, table_id_list);

	auto_unlocker lock(m_lock);
	for (std::deque<unsigned char>::iterator table_id_iter = table_id_list.begin(); table_id_iter != table_id_list.end(); table_id_iter++) {
		if (find_route_val(dst, *table_id_iter, p_val)) {
			if (p_src) {
				*p_src = p_val->get_src_addr();
				rt_mgr_logdbg("dst ip '%s' resolved to src addr '%d.%d.%d.%d'", dst_addr.to_str().c_str(), NIPQUAD(*p_src));
			}
			if (p_gw) {
				*p_gw = p_val->get_gw_addr();
				rt_mgr_logdbg("dst ip '%s' resolved to gw addr '%d.%d.%d.%d'", dst_addr.to_str().c_str(), NIPQUAD(*p_gw));
			}
			return true;
		}
	}
	return false;
}
Exemplo n.º 2
0
route_table_mgr::route_table_mgr() : netlink_socket_mgr<route_val>(ROUTE_DATA_TYPE), cache_table_mgr<route_rule_table_key, route_val*>("route_table_mgr")
{
	rt_mgr_logdbg("");

	//Read Route table from kernel and save it in local variable. 
	update_tbl();

	// create route_entry for each net_dev- needed for receiving port up/down events for net_dev_entry
	route_val *p_val;
	for (int i = 0; i < m_tab.entries_num; i++)
	{
		p_val = &m_tab.value[i];
		in_addr_t src_addr = p_val->get_src_addr();
		std::tr1::unordered_map<in_addr_t, route_entry*>::iterator iter = m_rte_list_for_each_net_dev.find(src_addr);
		// if src_addr of interface exists in the map, no need to create another route_entry
		if (iter == m_rte_list_for_each_net_dev.end()) {
			in_addr_t dst_ip	= src_addr;
			in_addr_t src_ip	= 0;
			uint8_t tos		= 0;
			m_rte_list_for_each_net_dev.insert(pair<in_addr_t, route_entry*> (src_addr, create_new_entry(route_rule_table_key(dst_ip, src_ip, tos), NULL)));
		}
	}

	//Print table
	print_val_tbl();
	
	// register to netlink event
	g_p_netlink_handler->register_event(nlgrpROUTE, this);
	rt_mgr_logdbg("Registered to g_p_netlink_handler");

	rt_mgr_logdbg("Done");
}
Exemplo n.º 3
0
bool route_table_mgr::find_route_val(in_addr_t &dst, unsigned char table_id, route_val* &p_val)
{
	ip_address dst_addr = dst;
	rt_mgr_logfunc("dst addr '%s'", dst_addr.to_str().c_str());

	route_val *correct_route_val = NULL;
	int longest_prefix = -1;

	for (int i = 0; i < m_tab.entries_num; i++) {
		route_val* p_val_from_tbl = &m_tab.value[i];
		if (!p_val_from_tbl->is_deleted() && p_val_from_tbl->is_if_up()) { // value was not deleted
			if(p_val_from_tbl->get_table_id() == table_id) { //found a match in routing table ID
				if(p_val_from_tbl->get_dst_addr() == (dst & p_val_from_tbl->get_dst_mask())) { //found a match in routing table
					if(p_val_from_tbl->get_dst_pref_len() > longest_prefix) { // this is the longest prefix match
						longest_prefix = p_val_from_tbl->get_dst_pref_len();
						correct_route_val = p_val_from_tbl;
					}
				}
			}
		}	
	}
	if (correct_route_val) {
		ip_address dst_gw = correct_route_val->get_dst_addr();
		p_val = correct_route_val;
		rt_mgr_logdbg("found route val[%p]: %s", p_val, p_val->to_str());
		return true;
	}

	rt_mgr_logdbg("destination gw wasn't found");
	return false;
}
Exemplo n.º 4
0
route_entry* route_table_mgr::create_new_entry(route_rule_table_key key, const observer *obs)
{
	// no need for lock - lock is activated in cache_collection_mgr::register_observer

	rt_mgr_logdbg("");
	NOT_IN_USE(obs);
	route_entry* p_ent = new route_entry(key);
	update_entry(p_ent, true);
	rt_mgr_logdbg("new entry %p created successfully", p_ent);
	return p_ent;
}
Exemplo n.º 5
0
route_entry* route_table_mgr::create_new_entry(ip_address p_ip, const observer *obs)
{
	// no need for lock - lock is activated in cache_collection_mgr::register_observer

	rt_mgr_logdbg("");
	NOT_IN_USE(obs);
	route_entry* p_rte = new route_entry(p_ip);
	update_entry(p_rte, true);
	rt_mgr_logdbg("new entry %p created successfully", p_rte);
	return p_rte;
}
Exemplo n.º 6
0
route_table_mgr::~route_table_mgr()
{
	rt_mgr_logdbg("");

	// clear all route_entrys created in the constructor
	std::tr1::unordered_map<in_addr_t, route_entry*>::iterator iter;
	for (iter = m_rte_list_for_each_net_dev.begin(); iter != m_rte_list_for_each_net_dev.end(); iter++) {
		route_entry* p_rte = iter->second;
		delete(p_rte);
	}

	rt_mgr_logdbg("Done");
}
Exemplo n.º 7
0
void route_table_mgr::update_entry(INOUT route_entry* p_ent, bool b_register_to_net_dev /*= false*/)
{
	rt_mgr_logdbg("entry [%p]", p_ent);
	auto_unlocker lock(m_lock);
	if (p_ent && !p_ent->is_valid()) { //if entry is found in the collection and is not valid
		rt_mgr_logdbg("route_entry is not valid-> update value");
		rule_entry* p_rr_entry = p_ent->get_rule_entry();
		std::deque<rule_val*>* p_rr_val;
		if (p_rr_entry && p_rr_entry->get_val(p_rr_val)) {
			route_val* p_val = NULL;
			in_addr_t peer_ip = p_ent->get_key().get_dst_ip();
			unsigned char table_id;
			for (std::deque<rule_val*>::iterator p_rule_val = p_rr_val->begin(); p_rule_val != p_rr_val->end(); p_rule_val++) {
				table_id = (*p_rule_val)->get_table_id();
				if (find_route_val(peer_ip, table_id, p_val)) {
					p_ent->set_val(p_val);
					if (b_register_to_net_dev) {
						//in_addr_t src_addr = p_val->get_src_addr();
						//net_device_val* p_ndv = g_p_net_device_table_mgr->get_net_device_val(src_addr);
						
						// Check if broadcast IP which is NOT supported
						if (IS_BROADCAST_N(peer_ip)) {
							rt_mgr_logdbg("Disabling Offload for route_entry '%s' - this is BC address", p_ent->to_str().c_str());
							// Need to route traffic to/from OS
							// Prevent registering of net_device to route entry
						}
						// Check if: Local loopback over Ethernet case which was not supported before OFED 2.1
						/*else if (p_ndv && (p_ndv->get_transport_type() == VMA_TRANSPORT_ETH) &&  (peer_ip == src_addr)) {
							rt_mgr_logdbg("Disabling Offload for route_entry '%s' - this is an Ethernet unicast loopback route", p_ent->to_str().c_str());
							// Need to route traffic to/from OS
							// Prevent registering of net_device to route entry
						}*/
						else {
							// register to net device for bonding events
							p_ent->register_to_net_device();
						}
					}
					// All good, validate the new route entry
					p_ent->set_entry_valid();
					break;
				} else {
					rt_mgr_logdbg("could not find route val for route_entry '%s in table %u'", p_ent->to_str().c_str(), table_id);
				}
			}
		}
		else {
			rt_mgr_logdbg("rule entry is not valid");
		}
	}
}
Exemplo n.º 8
0
void route_table_mgr::notify_cb(event *ev)
{
	NOT_IN_USE(ev); //TODO remove
#if 0
	route_nl_event *route_netlink_ev = dynamic_cast <route_nl_event*>(ev);
	const netlink_route_info *netlink_route_info = route_netlink_ev->get_route_info();
	uint16_t event_type = route_netlink_ev->nl_type;

	if(! is_route_event(event_type))
		return;

	rt_mgr_logdbg("received route event from netlink");
	route_val netlink_route_val;
	create_route_val_from_info(netlink_route_info, netlink_route_val);

	switch(event_type)
	{
	case RTM_DELROUTE:
		del_route_event(netlink_route_val);
		break;
	case RTM_NEWROUTE:
		new_route_event(netlink_route_val);
		break;
	}
#endif
}
Exemplo n.º 9
0
void route_table_mgr::get_default_gw(in_addr_t *p_gw_ip, int *p_if_index)
{
	rt_mgr_logdbg("");
	auto_unlocker lock(m_lock);

	for (int i = 0; i < m_tab.entries_num; i++) {
		route_val *p_val = &(m_tab.value[i]);
		if (p_val->get_gw_addr() &&
		    p_val->get_type() == RTN_UNICAST &&
		    p_val->get_dst_addr() == INADDR_ANY &&
		    p_val->get_dst_pref_len() == 0) {
			rt_mgr_logdbg("detected default gateway %s, index: %d", p_val->get_if_name(), p_val->get_if_index());
			*p_if_index = p_val->get_if_index();
			*p_gw_ip = p_val->get_gw_addr();
			return;
		}
	}
}
Exemplo n.º 10
0
void route_table_mgr::print_route_tbl()
{
	route_val *p_rtv;
	rt_mgr_logdbg("");
	for (int i = 0; i < m_rt_tab.entries_num; i++)
	{
		p_rtv = &m_rt_tab.rtv[i];
		p_rtv->print_route_val();
	}
}
Exemplo n.º 11
0
void route_table_mgr::new_route_event(route_val &netlink_route_val)
{
	int number_of_entries = m_tab.entries_num++;
	netlink_route_val.set_state(true);

	in_addr_t new_dst_addr = netlink_route_val.get_dst_addr();
	in_addr_t new_dst_mask = netlink_route_val.get_dst_mask();
	int new_dst_pref_len = netlink_route_val.get_dst_pref_len();
	char *new_if_name = (char *) netlink_route_val.get_if_name();

	rt_mgr_logdbg("netlink event- route added: dst '%d.%d.%d.%d', netmask '%d.%d.%d.%d', interface '%s'", NIPQUAD(new_dst_addr), NIPQUAD(new_dst_mask), new_if_name);

	if(find_route_val(netlink_route_val)) {
		rt_mgr_logdbg("route already exists: dst '%d.%d.%d.%d', netmask '%d.%d.%d.%d', interface '%s'", NIPQUAD(new_dst_addr), NIPQUAD(new_dst_mask), new_if_name);
		return;
	}

	m_tab.value[number_of_entries] = netlink_route_val;
	in_addr_t common_prefix;
	// set necessary route_vals as not valid
	for (int i = 0; i < m_tab.entries_num; i++) {
		route_val* p_val_from_tbl = &m_tab.value[i];
		if (!p_val_from_tbl->is_deleted() && p_val_from_tbl->is_if_up()) {
			common_prefix = p_val_from_tbl->get_dst_addr() & new_dst_mask;
			// check if the new route is more specific than an existing route
			// example: if route table contains entry for- 1.1.1.1/24
			//			and a new entry for- 1.1.1.1/32 is added
			// then route might change for some dst ips ---> set as invalid
			if((common_prefix == (new_dst_addr & new_dst_mask)) && p_val_from_tbl->get_dst_pref_len() < new_dst_pref_len) {
				p_val_from_tbl->set_state(false);
				rt_mgr_logdbg("route_val %p is not valid", p_val_from_tbl);
				p_val_from_tbl->print_route_val();
			}
		}
	}

	rt_mgr_logdbg("route added: dst '%d.%d.%d.%d', netmask '%d.%d.%d.%d', interface '%s'", NIPQUAD(new_dst_addr), NIPQUAD(new_dst_mask), new_if_name);

	if (g_vlogger_level >= VLOG_FUNC) {
		print_route_tbl();
	}
	update_invalid_entries();
}
Exemplo n.º 12
0
void route_table_mgr::addr_change_event(int if_index)
{
	for (int i = 0; i < m_tab.entries_num; i++) {
		route_val* p_val_from_tbl = &m_tab.value[i];
		if (! p_val_from_tbl->is_deleted() && p_val_from_tbl->get_if_index() == if_index) {
			p_val_from_tbl->set_state(false);
			rt_mgr_logdbg("route_val %p is not valid", p_val_from_tbl);
		}
	}
}
Exemplo n.º 13
0
bool route_table_mgr::route_resolve(IN in_addr_t dst, OUT in_addr_t *p_src, OUT in_addr_t *p_gw /*NULL*/)
{
	ip_address dst_addr = dst;
	rt_mgr_logdbg("dst addr '%s'", dst_addr.to_str().c_str());

	route_val *p_rtv = NULL;
	auto_unlocker lock(m_lock);
	if (find_route_val(dst, p_rtv)) {
		if (p_src) {
			*p_src = p_rtv->get_src_addr();
			rt_mgr_logdbg("dst ip '%s' resolved to src addr '%d.%d.%d.%d'", dst_addr.to_str().c_str(), NIPQUAD(*p_src));
		}
		if (p_gw) {
			*p_gw = p_rtv->get_gw_addr();
			rt_mgr_logdbg("dst ip '%s' resolved to gw addr '%d.%d.%d.%d'", dst_addr.to_str().c_str(), NIPQUAD(*p_gw));
		}
		return true;
	}
	return false;
}
Exemplo n.º 14
0
route_table_mgr::route_table_mgr() : cache_table_mgr<ip_address,route_val*>("route_table_mgr")
{
	rt_mgr_logdbg("");

	m_pid = getpid();
	m_buff_size = MSG_BUFF_SIZE;
	m_seq_num = 0;

	// Create Socket
	BULLSEYE_EXCLUDE_BLOCK_START
	if ((m_fd = orig_os_api.socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
		rt_mgr_logerr("NL socket Creation: ");
		return;
	}
	BULLSEYE_EXCLUDE_BLOCK_END

	//save the routing table
	rt_mgr_update_tbl();

	// create route_entry for each net_dev- needed for receiving port up/down events for net_dev_entry
	route_val *p_rtv;
	for (int i = 0; i < m_rt_tab.entries_num; i++)
	{
		p_rtv = &m_rt_tab.rtv[i];
		in_addr_t src_addr = p_rtv->get_src_addr();
		std::tr1::unordered_map<in_addr_t, route_entry*>::iterator iter = m_rte_list_for_each_net_dev.find(src_addr);
		// if src_addr of interface exists in the map, no need to create another route_entry
		if (iter == m_rte_list_for_each_net_dev.end()) {
			m_rte_list_for_each_net_dev.insert(pair<in_addr_t, route_entry*> (src_addr, create_new_entry(ip_address(src_addr), NULL)));
		}
	}

	print_route_tbl();

	// register to netlink event
	g_p_netlink_handler->register_event(nlgrpROUTE, this);
	rt_mgr_logdbg("Registered to g_p_netlink_handler");

	rt_mgr_logdbg("Done");
}
Exemplo n.º 15
0
void route_table_mgr::del_route_event(route_val &netlink_route_val)
{
	in_addr_t del_dst_addr = netlink_route_val.get_dst_addr();
	in_addr_t del_dst_mask = netlink_route_val.get_dst_mask();
	char *del_if_name = (char *) netlink_route_val.get_if_name();

	rt_mgr_logdbg("netlink event- route deleted: dst '%d.%d.%d.%d', netmask '%d.%d.%d.%d', interface '%s'", NIPQUAD(del_dst_addr), NIPQUAD(del_dst_mask), del_if_name);

	route_val* p_val_from_tbl = find_route_val(netlink_route_val);
	if(p_val_from_tbl) {
		rt_mgr_logdbg("found deleted route val[%p]: %s", p_val_from_tbl, p_val_from_tbl->to_str());
		p_val_from_tbl->set_deleted();
		p_val_from_tbl->set_state(false);
		return;
	}
	rt_mgr_logdbg("route does not exist!");

	if (g_vlogger_level >= VLOG_FUNC) {
		print_route_tbl();
	}
	update_invalid_entries();
}
Exemplo n.º 16
0
void route_table_mgr::update_entry(INOUT route_entry* p_rte, bool b_register_to_net_dev /*= false*/)
{
	rt_mgr_logdbg("entry [%p]", p_rte);
	auto_unlocker lock(m_lock);
	if (p_rte && !p_rte->is_valid()) { //if entry is found in the collection and is not valid
		rt_mgr_logdbg("route_entry is not valid-> update value");
		route_val* p_rtv = NULL;
		in_addr_t peer_ip = p_rte->get_key().get_in_addr();
		if (find_route_val(peer_ip, p_rtv)) {
			p_rte->set_val(p_rtv);
			if (b_register_to_net_dev) {
				in_addr_t src_addr = p_rtv->get_src_addr();
				net_device_val* p_ndv = g_p_net_device_table_mgr->get_net_device_val(src_addr);
				// Check if broadcast IP which is NOT supported
				if (IS_BROADCAST_N(peer_ip)) {
					rt_mgr_logdbg("Disabling Offload for route_entry '%s' - this is BC address", p_rte->to_str().c_str());
					// Need to route traffic to/from OS
					// Prevent registering of net_device to route entry
				}
				// Check if: Local loopback over Ethernet case which is NOT supported yet
				else if (p_ndv && (p_ndv->get_transport_type() == VMA_TRANSPORT_ETH) &&  (peer_ip == src_addr)) {
					rt_mgr_logdbg("Disabling Offload for route_entry '%s' - this is an Ethernet unicast loopback route", p_rte->to_str().c_str());
					// Need to route traffic to/from OS
					// Prevent registering of net_device to route entry
				}
				else {
					// register to net device for bonding events
					p_rte->register_to_net_device();
				}
			}

			// All good, validate the new route entry
			p_rte->set_entry_valid();
		}
	}
}
Exemplo n.º 17
0
void route_table_mgr::rt_mgr_update_source_ip()
{
	route_val *p_val;
	//for route entries which still have no src ip and no gw
	for (int i = 0; i < m_tab.entries_num; i++) {
		p_val = &m_tab.value[i];
		if (p_val->get_src_addr() || p_val->get_gw_addr()) continue;
		if (g_p_net_device_table_mgr) { //try to get src ip from net_dev list of the interface
			in_addr_t longest_prefix = 0;
			in_addr_t correct_src = 0;
			net_dev_lst_t* nd_lst = g_p_net_device_table_mgr->get_net_device_val_lst_from_index(p_val->get_if_index());
			if (nd_lst) {
				net_dev_lst_t::iterator iter = nd_lst->begin();
				while (iter != nd_lst->end()) {
					if((p_val->get_dst_addr() & (*iter)->get_netmask()) == ((*iter)->get_local_addr() & (*iter)->get_netmask())) { //found a match in routing table
						if(((*iter)->get_netmask() | longest_prefix) != longest_prefix){
							longest_prefix = (*iter)->get_netmask(); // this is the longest prefix match
							correct_src = (*iter)->get_local_addr();
						}
					}
					iter++;
				}
				if (correct_src) {
					p_val->set_src_addr(correct_src);
					continue;
				}
			}
		}
		// if still no src ip, get it from ioctl
		struct sockaddr_in src_addr;
		char *if_name = (char *)p_val->get_if_name();
		if (!get_ipv4_from_ifname(if_name, &src_addr)) {
			p_val->set_src_addr(src_addr.sin_addr.s_addr);
		}
		else {
			// Failed mapping if_name to IPv4 address
			rt_mgr_logwarn("could not figure out source ip for rtv = %s", p_val->to_str());
		}
	}

	//for route entries with gateway, do recursive search for src ip
	int num_unresolved_src = m_tab.entries_num;
	int prev_num_unresolved_src = 0;
	do {
		prev_num_unresolved_src = num_unresolved_src;
		num_unresolved_src = 0;
		for (int i = 0; i < m_tab.entries_num; i++) {
			p_val = &m_tab.value[i];
			if (p_val->get_gw_addr() && !p_val->get_src_addr()) {
				route_val* p_val_dst;
				in_addr_t in_addr = p_val->get_gw_addr();
				unsigned char table_id = p_val->get_table_id();
				if (find_route_val(in_addr, table_id, p_val_dst)) {
					if (p_val_dst->get_src_addr()) {
						p_val->set_src_addr(p_val_dst->get_src_addr());
					} else if (p_val == p_val_dst) { //gateway of the entry lead to same entry
						net_dev_lst_t* nd_lst = g_p_net_device_table_mgr->get_net_device_val_lst_from_index(p_val->get_if_index());
						if (nd_lst) {
							net_dev_lst_t::iterator iter = nd_lst->begin();
							while (iter != nd_lst->end()) {
								if(p_val->get_gw_addr() == (*iter)->get_local_addr()) {
									p_val->set_gw(0);
									p_val->set_src_addr((*iter)->get_local_addr());
									break;
								}
								iter++;
							}
						}
						if (!p_val->get_src_addr())
							num_unresolved_src++;
					} else {
						num_unresolved_src++;
					}
					// gateway and source are equal, no need of gw.
					if (p_val->get_src_addr() == p_val->get_gw_addr()) {
						p_val->set_gw(0);
					}
				} else {
					num_unresolved_src++;
				}
			}
		}
	} while (num_unresolved_src && prev_num_unresolved_src > num_unresolved_src);

	//for route entries which still have no src ip
	for (int i = 0; i < m_tab.entries_num; i++) {
		p_val = &m_tab.value[i];
		if (p_val->get_src_addr()) continue;
		if (p_val->get_gw_addr()) {
			rt_mgr_logdbg("could not figure out source ip for gw address. rtv = %s", p_val->to_str());
		}
		// if still no src ip, get it from ioctl
		struct sockaddr_in src_addr;
		char *if_name = (char *)p_val->get_if_name();
		if (!get_ipv4_from_ifname(if_name, &src_addr)) {
			p_val->set_src_addr(src_addr.sin_addr.s_addr);
		}
		else {
			// Failed mapping if_name to IPv4 address
			rt_mgr_logwarn("could not figure out source ip for rtv = %s", p_val->to_str());
		}
	}
}