Skip to content

Commit

Permalink
Merge "Add multicast route for handling mcast traffic to vhost."
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Aug 20, 2015
2 parents 1e0ddee + 419ceb0 commit 4093db7
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 26 deletions.
3 changes: 3 additions & 0 deletions src/vnsw/agent/cmn/agent.h
Expand Up @@ -191,6 +191,9 @@ extern void RouterIdDepInit(Agent *agent);
#define METADATA_NAT_PORT 80
#define AGENT_INIT_TASKNAME "Agent::Init"
#define AGENT_SHUTDOWN_TASKNAME "Agent::Shutdown"
#define IPV4_MULTICAST_BASE_ADDRESS "224.0.0.0"
#define IPV6_MULTICAST_BASE_ADDRESS "ff00::"
#define MULTICAST_BASE_ADDRESS_PLEN 8

#define VROUTER_SERVER_PORT 20914

Expand Down
62 changes: 48 additions & 14 deletions src/vnsw/agent/oper/inet_interface.cc
Expand Up @@ -224,6 +224,52 @@ static void DeleteHostRoutes(Agent *agent, InetUnicastAgentRouteTable *table,
GetIp4SubnetBroadcastAddress(addr, plen), 32);
}

void InetInterface::AddHostMulticastRoutes() {
VrfTable *vrf_table = static_cast<VrfTable *>(vrf()->get_table());
InetUnicastAgentRouteTable *uc_rt_table =
(vrf_table->GetInet4UnicastRouteTable(vrf()->GetName()));
boost::system::error_code ec;
// Add v4 route for covering multicast
uc_rt_table->
AddVHostRecvRoute(uc_rt_table->agent()->local_peer(),
vrf()->GetName(),
name_,
Ip4Address::from_string(IPV4_MULTICAST_BASE_ADDRESS,
ec),
MULTICAST_BASE_ADDRESS_PLEN,
vn_name_,
false);
// Add v6 route for covering multicast
uc_rt_table->
AddVHostRecvRoute(uc_rt_table->agent()->local_peer(),
vrf()->GetName(),
name_,
Ip6Address::from_string(IPV6_MULTICAST_BASE_ADDRESS,
ec),
MULTICAST_BASE_ADDRESS_PLEN,
vn_name_,
false);
}

void InetInterface::DelHostMulticastRoutes() {
VrfTable *vrf_table = static_cast<VrfTable *>(vrf()->get_table());
InetUnicastAgentRouteTable *uc_rt_table =
(vrf_table->GetInet4UnicastRouteTable(vrf()->GetName()));
boost::system::error_code ec;
// Del v4 route for covering multicast
uc_rt_table->Delete(uc_rt_table->agent()->local_peer(),
vrf()->GetName(),
Ip4Address::from_string(IPV4_MULTICAST_BASE_ADDRESS,
ec),
MULTICAST_BASE_ADDRESS_PLEN);
// Del v6 route for covering multicast
uc_rt_table->Delete(uc_rt_table->agent()->local_peer(),
vrf()->GetName(),
Ip6Address::from_string(IPV6_MULTICAST_BASE_ADDRESS,
ec),
MULTICAST_BASE_ADDRESS_PLEN);
}

// Things to do to activate VHOST/LL interface
// 1. Create the receive next-hops for interface (with policy and witout policy)
// 2. Add routes needed to manage the IP address on interface
Expand All @@ -243,19 +289,13 @@ void InetInterface::ActivateHostInterface() {
AddHostRoutes(agent, uc_rt_table, vrf(), name(), xconnect_.get(),
ip_addr_, plen_, vn_name_);
}
AddHostMulticastRoutes();

if (gw_.to_ulong()) {
AddDefaultRoute(agent, uc_rt_table, vrf(), xconnect_.get(), gw_,
vn_name_);
}

// Add receive-route for broadcast address
Inet4MulticastAgentRouteTable *mc_rt_table =
static_cast<Inet4MulticastAgentRouteTable *>
(VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName()));
mc_rt_table->AddVHostRecvRoute(vrf()->GetName(), name_,
Ip4Address(0xFFFFFFFF), false);

ReceiveNHKey nh_key(new InetInterfaceKey(name_), false);
flow_key_nh_ = static_cast<const NextHop *>(
agent->nexthop_table()->FindActiveEntry(&nh_key));
Expand All @@ -272,18 +312,12 @@ void InetInterface::DeActivateHostInterface() {
DeleteHostRoutes(agent, uc_rt_table, vrf(), xconnect_.get(), ip_addr_,
plen_);
}
DelHostMulticastRoutes();

if (gw_.to_ulong()) {
DeleteDefaultRoute(agent, uc_rt_table, vrf(), gw_);
}

Inet4MulticastAgentRouteTable *mc_rt_table =
static_cast<Inet4MulticastAgentRouteTable *>
(VrfTable::GetInstance()->GetInet4MulticastRouteTable(vrf()->GetName()));
// Add receive-route for broadcast address
mc_rt_table->Delete(vrf()->GetName(), Ip4Address(0),
Ip4Address(0xFFFFFFFF));

// Delete receive nexthops
ReceiveNH::Delete(agent->nexthop_table(), name_);
flow_key_nh_ = NULL;
Expand Down
2 changes: 2 additions & 0 deletions src/vnsw/agent/oper/inet_interface.h
Expand Up @@ -50,6 +50,8 @@ class InetInterface : public Interface {
void DeActivateSimpleGateway();
void ActivateHostInterface();
void DeActivateHostInterface();
void AddHostMulticastRoutes();
void DelHostMulticastRoutes();

// Helper functions
static void Create(InterfaceTable *table, const std::string &ifname,
Expand Down
18 changes: 13 additions & 5 deletions src/vnsw/agent/oper/inet_unicast_route.cc
Expand Up @@ -1313,7 +1313,7 @@ void InetUnicastAgentRouteTable::AddInetInterfaceRouteReq(const Peer *peer,
static void AddVHostRecvRouteInternal(DBRequest *req, const Peer *peer,
const string &vrf,
const string &interface,
const Ip4Address &addr, uint8_t plen,
const IpAddress &addr, uint8_t plen,
const string &vn_name, bool policy) {
req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
req->key.reset(new InetUnicastRouteKey(peer, vrf, addr, plen));
Expand All @@ -1326,25 +1326,33 @@ static void AddVHostRecvRouteInternal(DBRequest *req, const Peer *peer,
void InetUnicastAgentRouteTable::AddVHostRecvRoute(const Peer *peer,
const string &vrf,
const string &interface,
const Ip4Address &addr,
const IpAddress &addr,
uint8_t plen,
const string &vn_name,
bool policy) {
DBRequest req;
AddVHostRecvRouteInternal(&req, peer, vrf, interface, addr, plen,
vn_name, policy);
static_cast<ReceiveRoute *>(req.data.get())->set_proxy_arp();
Inet4UnicastTableProcess(Agent::GetInstance(), vrf, req);
if (addr.is_v4()) {
Inet4UnicastTableProcess(Agent::GetInstance(), vrf, req);
} else if (addr.is_v6()) {
Inet6UnicastTableProcess(Agent::GetInstance(), vrf, req);
}
}

void InetUnicastAgentRouteTable::AddVHostRecvRouteReq
(const Peer *peer, const string &vrf, const string &interface,
const Ip4Address &addr, uint8_t plen, const string &vn_name, bool policy) {
const IpAddress &addr, uint8_t plen, const string &vn_name, bool policy) {
DBRequest req;
AddVHostRecvRouteInternal(&req, peer, vrf, interface, addr, plen,
vn_name, policy);
static_cast<ReceiveRoute *>(req.data.get())->set_proxy_arp();
Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
if (addr.is_v4()) {
Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
} else if (addr.is_v6()) {
Inet6UnicastTableEnqueue(Agent::GetInstance(), vrf, &req);
}
}

void
Expand Down
4 changes: 2 additions & 2 deletions src/vnsw/agent/oper/inet_unicast_route.h
Expand Up @@ -272,11 +272,11 @@ class InetUnicastAgentRouteTable : public AgentRouteTable {
uint32_t label, const string &vn_name);
static void AddVHostRecvRoute(const Peer *peer, const string &vrf,
const string &interface,
const Ip4Address &addr, uint8_t plen,
const IpAddress &addr, uint8_t plen,
const string &vn_name, bool policy);
static void AddVHostRecvRouteReq(const Peer *peer, const string &vrf,
const string &interface,
const Ip4Address &addr, uint8_t plen,
const IpAddress &addr, uint8_t plen,
const string &vn_name, bool policy);
static void AddVHostSubnetRecvRoute(const Peer *peer, const string &vrf,
const string &interface,
Expand Down
10 changes: 5 additions & 5 deletions src/vnsw/agent/test/test_agent_route_walker.cc
Expand Up @@ -199,7 +199,7 @@ class AgentRouteWalkerTest : public AgentRouteWalker, public ::testing::Test {
uint32_t vrf_notifications_count,
uint32_t total_rt_vrf_walk_done) {
client->WaitForIdle(10);
WAIT_FOR(100, 1000, (route_notifications == route_notifications_));
WAIT_FOR(100, 1000, (route_notifications_ == route_notifications_));
ASSERT_TRUE(route_notifications_ == route_notifications);
ASSERT_TRUE(vrf_notifications_ == vrf_notifications);
ASSERT_TRUE(vrf_notifications_count_ == vrf_notifications_count);
Expand Down Expand Up @@ -266,7 +266,7 @@ TEST_F(AgentRouteWalkerTest, walk_all_routes_wih_no_vrf) {
client->Reset();
SetupEnvironment(0);
StartVrfWalk();
VerifyNotifications(8, 1, 1, Agent::ROUTE_TABLE_MAX - 1);
VerifyNotifications(9, 1, 1, Agent::ROUTE_TABLE_MAX - 1);
EXPECT_TRUE(walk_task_context_mismatch_ == false);
walk_task_context_mismatch_ = true;
DeleteEnvironment(0);
Expand All @@ -276,7 +276,7 @@ TEST_F(AgentRouteWalkerTest, walk_all_routes_wih_1_vrf) {
client->Reset();
SetupEnvironment(1);
StartVrfWalk();
VerifyNotifications(18, 2, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 2));
VerifyNotifications(19, 2, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 2));
EXPECT_TRUE(walk_task_context_mismatch_ == false);
walk_task_context_mismatch_ = true;
DeleteEnvironment(1);
Expand All @@ -286,7 +286,7 @@ TEST_F(AgentRouteWalkerTest, walk_all_routes_with_2_vrf) {
client->Reset();
SetupEnvironment(2);
StartVrfWalk();
VerifyNotifications(28, 3, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 3));
VerifyNotifications(29, 3, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 3));
EXPECT_TRUE(walk_task_context_mismatch_ == false);
walk_task_context_mismatch_ = true;
DeleteEnvironment(2);
Expand All @@ -296,7 +296,7 @@ TEST_F(AgentRouteWalkerTest, walk_all_routes_with_3_vrf) {
client->Reset();
SetupEnvironment(3);
StartVrfWalk();
VerifyNotifications(38, 4, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 4));
VerifyNotifications(39, 4, 1, ((Agent::ROUTE_TABLE_MAX - 1) * 4));
EXPECT_TRUE(walk_task_context_mismatch_ == false);
walk_task_context_mismatch_ = true;
DeleteEnvironment(3);
Expand Down
35 changes: 35 additions & 0 deletions src/vnsw/agent/test/test_vn.cc
Expand Up @@ -953,6 +953,41 @@ TEST_F(CfgTest, CfgUuidChange) {

}

TEST_F(CfgTest, multicast_fabric_routes) {
//Send control node message on subnet bcast after family has changed to L2
client->Reset();
struct PortInfo input[] = {
{"vnet1", 1, "11.1.1.2", "00:00:00:01:01:11", 1, 1},
};

IpamInfo ipam_info[] = {
{"11.1.1.0", 24, "11.1.1.200", true},
};

CreateVmportEnv(input, 1, 0);
client->WaitForIdle();

WAIT_FOR(1000, 1000, (VmPortActive(input, 0) == true));

AddIPAM("vn1", ipam_info, 1);
client->WaitForIdle();
WAIT_FOR(1000, 1000, (RouteFind("vrf1", "11.1.1.200", 32)));
EXPECT_FALSE(RouteFind("vrf1", "224.0.0.0", 8));
EXPECT_FALSE(RouteFindV6("vrf1", "ff00::", 8));
EXPECT_TRUE(RouteFind(Agent::GetInstance()->fabric_vrf_name(),
"224.0.0.0", 8));
EXPECT_TRUE(RouteFindV6(Agent::GetInstance()->fabric_vrf_name(),
"ff00::", 8));

//Restore and cleanup
client->Reset();
DelIPAM("vn1");
client->WaitForIdle();
DeleteVmportEnv(input, 1, true);
client->WaitForIdle();
WAIT_FOR(1000, 1000, (VrfFind("vrf1") == false));
}

int main(int argc, char **argv) {
GETUSERARGS();

Expand Down

0 comments on commit 4093db7

Please sign in to comment.