Skip to content

Commit

Permalink
Merge "Multicast traffic gets dropped." into R2.22.x
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Feb 19, 2016
2 parents 01e2667 + 1903658 commit ec91af7
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 58 deletions.
4 changes: 3 additions & 1 deletion src/vnsw/agent/oper/agent_path.cc
Expand Up @@ -871,7 +871,9 @@ bool MulticastRoute::CopyPathParameters(Agent *agent,
path->set_dest_vn_name(vn_name);
path->set_unresolved(unresolved);
path->set_vxlan_id(vxlan_id);
path->set_label(label);
if ((path->peer() != agent->local_vm_peer()) &&
(path->peer() != agent->local_peer()))
path->set_label(label);

//Setting of tunnel is only for simulated TOR.
path->set_tunnel_bmap(tunnel_type);
Expand Down
105 changes: 96 additions & 9 deletions src/vnsw/agent/oper/bridge_route.cc
Expand Up @@ -571,6 +571,89 @@ bool BridgeRouteEntry::ReComputePathDeletion(AgentPath *path) {
return false;
}

void BridgeRouteEntry::HandleMulticastLabel(const Agent *agent,
AgentPath *path,
const AgentPath *local_peer_path,
const AgentPath *local_vm_peer_path,
bool del,
uint32_t *evpn_label) {
*evpn_label = MplsTable::kInvalidLabel;

//EVPN label is present in two paths:
// local_vm_peer(courtesy: vmi) or local_peer(courtesy: vn)
// Irrespective of delete/add operation if one of them is present and is not
// the affected path, then extract the label from same.
// By default pick it from available path (local or local_vm).
switch (path->peer()->GetType()) {
case Peer::LOCAL_VM_PEER:
//Use local_peer path for label
if (local_peer_path) {
*evpn_label = local_peer_path->label();
assert(*evpn_label != MplsTable::kInvalidLabel);
}
break;
case Peer::LOCAL_PEER:
//Use local_peer path for label
if (local_vm_peer_path) {
*evpn_label = local_vm_peer_path->label();
assert(*evpn_label != MplsTable::kInvalidLabel);
}
break;
default:
if (local_vm_peer_path) {
*evpn_label = local_vm_peer_path->label();
assert(*evpn_label != MplsTable::kInvalidLabel);
} else if (local_peer_path) {
*evpn_label = local_peer_path->label();
assert(*evpn_label != MplsTable::kInvalidLabel);
}
break;
}

//Delete path evpn label if path is local_peer or local_vm_peer.
//Delete fabric label if path is multicast_fabric_tree
if (del) {
bool delete_label = false;
// On deletion of fabric path delete fabric label.
// Other type of label is evpn mcast label.
// EVPN label is deleted when both local peer and local_vm_peer path are
// gone.
if (path->peer()->GetType() == Peer::MULTICAST_FABRIC_TREE_BUILDER)
delete_label = true;
else if ((path->peer() == agent->local_vm_peer()) ||
(path->peer() == agent->local_peer())) {
if (local_peer_path == NULL &&
local_vm_peer_path == NULL)
delete_label = true;
}
if (delete_label)
agent->mpls_table()->DeleteMcastLabel(path->label());

return;
}

// Currently other than evpn label no other multicast path requires dynamic
// allocation so return.
if ((path != local_peer_path) && (path != local_vm_peer_path))
return;

// Path already has label, return.
if (path->label() != MplsTable::kInvalidLabel)
return;

// If this is the first time i.e. local_peer has come with no local_vm_peer
// and vice versa then allocate label.
// If its not then we should have valid evpn label calculated above.
if (*evpn_label == MplsTable::kInvalidLabel) {
// XOR use - we shud never reach here when both are NULL or set.
// Only one should be present.
assert((local_vm_peer_path != NULL) ^ (local_peer_path != NULL));
*evpn_label = agent->mpls_table()->AllocLabel();
}
assert(*evpn_label != MplsTable::kInvalidLabel);
path->set_label(*evpn_label);
}

bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
if (path->peer() == NULL) {
return false;
Expand Down Expand Up @@ -600,13 +683,9 @@ bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
AgentPath *evpn_peer_path = NULL;
AgentPath *fabric_peer_path = NULL;
AgentPath *tor_peer_path = NULL;
AgentPath *local_peer_path = NULL;
bool tor_path = false;

//Delete path label
if (del && (path->peer()->GetType() != Peer::BGP_PEER)) {
agent->mpls_table()->DeleteMcastLabel(path->label());
}

const CompositeNH *cnh =
static_cast<const CompositeNH *>(path->nexthop());
if (cnh && (cnh->composite_nh_type() == Composite::TOR)) {
Expand Down Expand Up @@ -659,6 +738,8 @@ bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
fabric_peer_path = it_path;
} else if (it_path->peer() == agent->multicast_peer()) {
multicast_peer_path = it_path;
} else if (it_path->peer() == agent->local_peer()) {
local_peer_path = it_path;
}
}

Expand All @@ -668,6 +749,13 @@ bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
}
}

uint32_t evpn_label = MplsTable::kInvalidLabel;
HandleMulticastLabel(agent, path,
local_peer_path,
local_vm_peer_path,
del,
&evpn_label);

//all paths are gone so delete multicast_peer path as well
if ((local_vm_peer_path == NULL) &&
(tor_peer_path == NULL) &&
Expand Down Expand Up @@ -746,7 +834,6 @@ bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
bool unresolved = false;
uint32_t vxlan_id = 0;
uint32_t label = 0;
uint32_t evpn_label = 0;
uint32_t tunnel_bmap = TunnelType::AllType();

//Select based on priority of path peer.
Expand All @@ -756,7 +843,6 @@ bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
vxlan_id = local_vm_peer_path->vxlan_id();
tunnel_bmap = TunnelType::AllType();
label = local_vm_peer_path->label();
evpn_label = label;
} else if (tor_peer_path) {
dest_vn_name = tor_peer_path->dest_vn_name();
unresolved = tor_peer_path->unresolved();
Expand Down Expand Up @@ -791,6 +877,7 @@ bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
label,
tunnel_bmap,
nh);

//Bake all MPLS label
if (fabric_peer_path) {
//Add new label
Expand All @@ -804,8 +891,8 @@ bool BridgeRouteEntry::ReComputeMulticastPaths(AgentPath *path, bool del) {
}
}

//Populate label only when local vm peer path is present.
if (evpn_label != 0 && local_vm_peer_path) {
// Rebake label with whatever comp NH has been calculated.
if (evpn_label != MplsTable::kInvalidLabel) {
agent->mpls_table()->CreateMcastLabel(evpn_label,
Composite::L2COMP,
component_nh_list,
Expand Down
5 changes: 5 additions & 0 deletions src/vnsw/agent/oper/bridge_route.h
Expand Up @@ -144,6 +144,11 @@ class BridgeRouteEntry : public AgentRoute {
const AgentPath *FindOvsPath() const;

private:
void HandleMulticastLabel(const Agent *agent,
AgentPath *path,
const AgentPath *local_peer_path,
const AgentPath *local_vm_peer_path,
bool del, uint32_t *evpn_label);
bool ReComputeMulticastPaths(AgentPath *path, bool del);
AgentPath *FindEvpnPathUsingKeyData(const AgentRouteKey *key,
const AgentRouteData *data) const;
Expand Down
50 changes: 23 additions & 27 deletions src/vnsw/agent/oper/multicast.cc
Expand Up @@ -116,7 +116,7 @@ void MulticastHandler::HandleVxLanChange(const VnEntry *vn) {
obj->set_vxlan_id(new_vxlan_id);
//Rebake new vxlan id in mcast route
AddL2BroadcastRoute(obj, vn->GetVrf()->GetName(), vn->GetName(),
broadcast, obj->evpn_mpls_label(), new_vxlan_id, 0);
broadcast, MplsTable::kInvalidLabel, new_vxlan_id, 0);
}
}

Expand All @@ -139,11 +139,11 @@ void MulticastHandler::HandleVnParametersChange(DBTablePartBase *partition,
boost::system::error_code ec;
Ip4Address broadcast = IpAddress::from_string("255.255.255.255",
ec).to_v4();

//Add operation
if (!deleted) {
MulticastGroupObject *all_broadcast =
FindFloodGroupObject(vn->GetVrf()->GetName());

if (!state) {
state = new MulticastDBState(vn->GetVrf()->GetName(),
vn_vxlan_id);
Expand All @@ -152,9 +152,10 @@ void MulticastHandler::HandleVnParametersChange(DBTablePartBase *partition,
state);
//Also create multicast object
if (all_broadcast == NULL) {
CreateMulticastGroupObject(state->vrf_name_, broadcast,
vn->GetName(), state->vxlan_id_);
all_broadcast = CreateMulticastGroupObject(state->vrf_name_, broadcast,
vn, state->vxlan_id_);
}
all_broadcast->set_vn(vn);
} else {
if (old_vxlan_id != vn_vxlan_id) {
state->vxlan_id_ = vn_vxlan_id;
Expand Down Expand Up @@ -183,9 +184,13 @@ void MulticastHandler::HandleVnParametersChange(DBTablePartBase *partition,
if (!state)
return;

if (deleted) {
DeleteMulticastObject(state->vrf_name_, broadcast);
MulticastGroupObject *all_broadcast =
FindFloodGroupObject(state->vrf_name_);
if (all_broadcast) {
all_broadcast->reset_vn();
}

DeleteMulticastObject(state->vrf_name_, broadcast);
BridgeAgentRouteTable::DeleteBroadcastReq(agent_->local_peer(),
state->vrf_name_,
old_vxlan_id,
Expand All @@ -206,19 +211,18 @@ void MulticastHandler::ModifyVN(DBTablePartBase *partition, DBEntryBase *e)
}

bool MulticastGroupObject::CanBeDeleted() const {
if (local_olist_.size() == 0)
if ((local_olist_.size() == 0) && (vn_.get() == NULL))
return true;
return false;
}

MulticastGroupObject *MulticastHandler::CreateMulticastGroupObject
(const string &vrf_name, const Ip4Address &ip_addr, const string &vn_name,
(const string &vrf_name, const Ip4Address &ip_addr, const VnEntry *vn,
uint32_t vxlan_id) {
MulticastGroupObject *obj =
new MulticastGroupObject(vrf_name, ip_addr, vn_name);
new MulticastGroupObject(vrf_name, ip_addr, vn->GetName());
obj->set_vxlan_id(vxlan_id);
AddToMulticastObjList(obj);
obj->CreateEvpnMplsLabel(agent_);
return obj;
}

Expand Down Expand Up @@ -384,18 +388,12 @@ MulticastGroupObject *MulticastHandler::FindActiveGroupObject(
return obj;
}

void MulticastGroupObject::CreateEvpnMplsLabel(const Agent *agent) {
//Already added
if ((evpn_mpls_label_ != MplsLabel::INVALID) &&
(evpn_mpls_label_ != 0)) {
return;
}
void MulticastGroupObject::set_vn(const VnEntry *vn) {
vn_.reset(vn);
}

evpn_mpls_label_ = agent->mpls_table()->AllocLabel();
if (evpn_mpls_label_ == MplsLabel::INVALID) {
MCTRACE(Log, "allocation of evpn mpls label failed",
vrf_name_, "FF:FF:FF:FF:FF:FF", 0);
}
void MulticastGroupObject::reset_vn() {
vn_.reset();
}

ComponentNHKeyList
Expand Down Expand Up @@ -427,7 +425,7 @@ void MulticastHandler::TriggerLocalRouteChange(MulticastGroupObject *obj,
AgentRouteData *data =
BridgeAgentRouteTable::BuildNonBgpPeerData(obj->vrf_name(),
obj->GetVnName(),
obj->evpn_mpls_label(),
MplsTable::kInvalidLabel,
obj->vxlan_id(),
route_tunnel_bmap,
Composite::L2INTERFACE,
Expand Down Expand Up @@ -577,7 +575,7 @@ void MulticastHandler::AddVmInterfaceInFloodGroup(const VmInterface *vm_itf) {
all_broadcast = this->FindGroupObject(vrf_name, broadcast);
if (all_broadcast == NULL) {
all_broadcast = CreateMulticastGroupObject(vrf_name, broadcast,
vn_name, vn->GetVxLanId());
vn, vn->GetVxLanId());
add_route = true;
}

Expand Down Expand Up @@ -660,8 +658,7 @@ void MulticastHandler::ModifyEvpnMembers(const Peer *peer,

TriggerRemoteRouteChange(obj, peer, vrf_name, olist,
peer_identifier, delete_op, Composite::EVPN,
(obj ? obj->evpn_mpls_label() : 0), false,
ethernet_tag);
ethernet_tag, false, ethernet_tag);
MCTRACE(Log, "Add EVPN TOR Olist ", vrf_name, grp.to_string(), 0);
}

Expand All @@ -686,8 +683,7 @@ void MulticastHandler::ModifyTorMembers(const Peer *peer,

TriggerRemoteRouteChange(obj, peer, vrf_name, olist,
peer_identifier, delete_op, Composite::TOR,
(obj ? obj->evpn_mpls_label() : 0), false,
ethernet_tag);
MplsTable::kInvalidLabel, false, ethernet_tag);
MCTRACE(Log, "Add external TOR Olist ", vrf_name, grp.to_string(), 0);
}

Expand Down
16 changes: 7 additions & 9 deletions src/vnsw/agent/oper/multicast.h
Expand Up @@ -55,8 +55,7 @@ class MulticastGroupObject {
const Ip4Address &grp_addr,
const std::string &vn_name) :
vrf_name_(vrf_name), grp_address_(grp_addr), vn_name_(vn_name),
evpn_mpls_label_(0), vxlan_id_(0), peer_identifier_(0),
deleted_(false) {
vxlan_id_(0), peer_identifier_(0), deleted_(false), vn_(NULL) {
boost::system::error_code ec;
src_address_ = IpAddress::from_string("0.0.0.0", ec).to_v4();
local_olist_.clear();
Expand All @@ -65,15 +64,12 @@ class MulticastGroupObject {
const Ip4Address &grp_addr,
const Ip4Address &src_addr) :
vrf_name_(vrf_name), grp_address_(grp_addr), src_address_(src_addr),
evpn_mpls_label_(0), vxlan_id_(0), peer_identifier_(0),
deleted_(false) {
vxlan_id_(0), peer_identifier_(0), deleted_(false), vn_(NULL) {
local_olist_.clear();
};
virtual ~MulticastGroupObject() { };

bool CanBeDeleted() const;
uint32_t evpn_mpls_label() const {return evpn_mpls_label_;}
void set_evpn_mpls_label(uint32_t label) {evpn_mpls_label_ = label;}

//Add local member is local VM in server.
bool AddLocalMember(const boost::uuids::uuid &intf_uuid) {
Expand Down Expand Up @@ -116,19 +112,21 @@ class MulticastGroupObject {
uint32_t vxlan_id() const {return vxlan_id_;}
void set_peer_identifier(uint64_t peer_id) {peer_identifier_ = peer_id;}
uint64_t peer_identifier() {return peer_identifier_;}
void CreateEvpnMplsLabel(const Agent *agent);
void set_vn(const VnEntry *vn);
void reset_vn();
const VnEntry *vn() const {return vn_.get();}

private:

std::string vrf_name_;
Ip4Address grp_address_;
std::string vn_name_;
Ip4Address src_address_;
uint32_t evpn_mpls_label_;
uint32_t vxlan_id_;
uint64_t peer_identifier_;
bool deleted_;
std::list<boost::uuids::uuid> local_olist_; /* UUID of local i/f */
VnEntryConstRef vn_;

friend class MulticastHandler;
DISALLOW_COPY_AND_ASSIGN(MulticastGroupObject);
Expand All @@ -144,7 +142,7 @@ class MulticastHandler {

MulticastGroupObject *CreateMulticastGroupObject(const string &vrf_name,
const Ip4Address &ip_addr,
const string &vn_name,
const VnEntry *vn,
uint32_t vxlan_id);

/* Called by XMPP to add ctrl node sent olist and label */
Expand Down
3 changes: 2 additions & 1 deletion src/vnsw/agent/oper/test/test_intf.cc
Expand Up @@ -1830,7 +1830,7 @@ TEST_F(IntfTest, VmPortServiceVlanAdd_2) {
NovaDel(1);
ConfigDel(1);
client->WaitForIdle();
EXPECT_TRUE(VmPortFindRetDel(1) == false);
EXPECT_TRUE(VmPortFind(1) == false);

//Cleanup
DelNode("virtual-machine-interface", input[0].name);
Expand All @@ -1845,6 +1845,7 @@ TEST_F(IntfTest, VmPortServiceVlanAdd_2) {
DelVn("vn2");
DeleteVmportEnv(input, 1, true);
client->WaitForIdle();
EXPECT_TRUE(VmPortFindRetDel(1) == false);
EXPECT_FALSE(VrfFind("vrf1"));
EXPECT_FALSE(VrfFind("vrf2"));
}
Expand Down

0 comments on commit ec91af7

Please sign in to comment.