Skip to content

Commit

Permalink
Add multicast route for handling mcast traffic to vhost.
Browse files Browse the repository at this point in the history
Both v4 and v6 mcast covering route is installed in fabric VRF.
This takes care of mcast traffic over vhost interface.

Closes-bug: 1485432
(cherry picked from commit 086c238)

Conflicts:
	src/vnsw/agent/test/test_agent_route_walker.cc

Change-Id: I929823a3e799f1f103fb59e6731086be62c3b6e4
  • Loading branch information
manishsing committed Aug 19, 2015
1 parent 8f086b0 commit 419ceb0
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 419ceb0

Please sign in to comment.