Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <base/os.h>
7 : #include <base/util.h>
8 : #include <base/logging.h>
9 : #include <base/connection_info.h>
10 : #include "base/address_util.h"
11 : #include <net/bgp_af.h>
12 : #include "cmn/agent_cmn.h"
13 : #include "init/agent_param.h"
14 : #include "controller/controller_route_path.h"
15 : #include "controller/controller_peer.h"
16 : #include "controller/controller_vrf_export.h"
17 : #include "controller/controller_init.h"
18 : #include "controller/controller_ifmap.h"
19 : #include "oper/operdb_init.h"
20 : #include "oper/vrf.h"
21 : #include "oper/nexthop.h"
22 : #include "oper/tunnel_nh.h"
23 : #include "oper/mirror_table.h"
24 : #include "oper/multicast.h"
25 : #include "oper/peer.h"
26 : #include "oper/vxlan.h"
27 : #include "oper/agent_path.h"
28 : #include "oper/ecmp_load_balance.h"
29 : #include "oper/global_system_config.h"
30 : #include "cmn/agent_stats.h"
31 : #include <pugixml/pugixml.hpp>
32 : #include "xml/xml_pugi.h"
33 : #include "ifmap/ifmap_agent_table.h"
34 : #include "controller/controller_types.h"
35 : #include <oper/vxlan_routing_manager.h>
36 : #include "xmpp/xmpp_init.h"
37 : #include <xmpp_enet_types.h>
38 : #include <xmpp_unicast_types.h>
39 : #include <xmpp_multicast_types.h>
40 : #include <xmpp_mvpn_types.h>
41 : #include <assert.h>
42 :
43 : using namespace boost::asio;
44 : using namespace autogen;
45 :
46 : using std::unique_ptr;
47 : using std::stringstream;
48 :
49 : using process::ConnectionType;
50 : using process::ConnectionStatus;
51 : using process::ConnectionState;
52 :
53 : // Parses string ipv4-addr/plen or ipv6-addr/plen
54 : // Stores address in addr and returns plen
55 0 : static int ParseEvpnAddress(const string &str, IpAddress *addr,
56 : const MacAddress &mac) {
57 0 : bool is_type5 = mac.IsZero();
58 0 : size_t pos = str.find('/');
59 0 : if (pos == string::npos) {
60 0 : return -1;
61 : }
62 :
63 0 : int plen = 0;
64 0 : boost::system::error_code ec;
65 0 : string plen_str = str.substr(pos + 1);
66 0 : if (is_type5) {
67 : //IpAddress::from_string
68 0 : string addrstr = str.substr(0, pos);
69 0 : boost::system::error_code ec1;
70 0 : *addr = IpAddress::from_string(addrstr, ec1);
71 0 : if (ec1)
72 0 : return -1;
73 0 : return atoi(plen_str.c_str());
74 0 : } else {
75 0 : if (plen_str == "32") {
76 0 : Ip4Address ip4_addr;
77 0 : ec = Ip4PrefixParse(str, &ip4_addr, &plen);
78 0 : if (ec || plen != 32) {
79 0 : return -1;
80 : }
81 0 : *addr = ip4_addr;
82 0 : } else if (plen_str == "128") {
83 0 : Ip6Address ip6_addr;
84 0 : ec = Inet6PrefixParse(str, &ip6_addr, &plen);
85 0 : if (ec || plen != 128) {
86 0 : return -1;
87 : }
88 0 : *addr = ip6_addr;
89 : } else {
90 0 : return -1;
91 : }
92 : }
93 0 : return plen;
94 0 : }
95 :
96 21 : AgentXmppChannel::AgentXmppChannel(Agent *agent,
97 : const std::string &xmpp_server,
98 : const std::string &label_range,
99 21 : uint8_t xs_idx)
100 21 : : channel_(NULL), channel_str_(),
101 21 : xmpp_server_(xmpp_server), label_range_(label_range),
102 42 : xs_idx_(xs_idx), route_published_time_(0), agent_(agent) {
103 21 : bgp_peer_id_.reset();
104 21 : end_of_rib_tx_timer_.reset(new EndOfRibTxTimer(agent));
105 21 : end_of_rib_rx_timer_.reset(new EndOfRibRxTimer(agent));
106 21 : llgr_stale_timer_.reset(new LlgrStaleTimer(agent));
107 21 : CreateBgpPeer();
108 21 : }
109 :
110 42 : AgentXmppChannel::~AgentXmppChannel() {
111 21 : end_of_rib_tx_timer_.reset();
112 21 : end_of_rib_rx_timer_.reset();
113 21 : llgr_stale_timer_.reset();
114 42 : }
115 :
116 21 : void AgentXmppChannel::Unregister() {
117 21 : if (bgp_peer_id()) {
118 21 : bgp_peer_id()->StopRouteExports();
119 : }
120 21 : channel_->UnRegisterWriteReady(xmps::BGP);
121 21 : channel_->UnRegisterReceive(xmps::BGP);
122 21 : channel_ = NULL;
123 21 : }
124 :
125 0 : InetUnicastAgentRouteTable *AgentXmppChannel::PrefixToRouteTable
126 : (const std::string &vrf_name, const IpAddress &prefix_addr) {
127 0 : InetUnicastAgentRouteTable *rt_table = NULL;
128 :
129 0 : if (prefix_addr.is_v4()) {
130 0 : rt_table = agent_->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
131 0 : } else if (prefix_addr.is_v6()) {
132 0 : rt_table = agent_->vrf_table()->GetInet6UnicastRouteTable(vrf_name);
133 : }
134 0 : if (rt_table == NULL) {
135 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
136 : "Unable to fetch route table for prefix " +
137 : prefix_addr.to_string());
138 : }
139 0 : return rt_table;
140 : }
141 :
142 0 : InetUnicastAgentRouteTable *AgentXmppChannel::PrefixToRouteMplsTable
143 : (const std::string &vrf_name, const IpAddress &prefix_addr) {
144 0 : InetUnicastAgentRouteTable *rt_table = NULL;
145 :
146 0 : if (prefix_addr.is_v4()) {
147 0 : rt_table = agent_->vrf_table()->GetInet4MplsUnicastRouteTable(vrf_name);
148 : }
149 0 : if (rt_table == NULL) {
150 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
151 : "Unable to fetch route table for prefix " +
152 : prefix_addr.to_string());
153 : }
154 0 : return rt_table;
155 : }
156 21 : void AgentXmppChannel::RegisterXmppChannel(XmppChannel *channel) {
157 21 : if (channel == NULL)
158 0 : return;
159 :
160 21 : channel_ = channel;
161 21 : channel_str_ = channel_->ToString();
162 21 : channel->RegisterReceive(xmps::BGP,
163 : boost::bind(&AgentXmppChannel::ReceiveInternal,
164 : this, _1));
165 : }
166 :
167 347 : std::string AgentXmppChannel::GetBgpPeerName() const {
168 347 : if (bgp_peer_id_.get() == NULL)
169 0 : return "No BGP peer";
170 :
171 347 : return bgp_peer_id_.get()->GetName();
172 : }
173 :
174 21 : void AgentXmppChannel::CreateBgpPeer() {
175 21 : assert(bgp_peer_id_.get() == NULL);
176 : DBTableBase::ListenerId id =
177 21 : agent_->vrf_table()->Register(boost::bind(&VrfExport::Notify,
178 : agent_, this, _1, _2));
179 21 : boost::system::error_code ec;
180 21 : const string &addr = agent_->controller_ifmap_xmpp_server(xs_idx_);
181 21 : IpAddress ip = AddressFromString(addr, &ec);
182 21 : assert(ec.value() == 0);
183 21 : bgp_peer_id_.reset(new BgpPeer(this, ip.to_v4(), addr, id, Peer::BGP_PEER));
184 21 : }
185 :
186 0 : void InetRequestDelete(const IpAddress& ip_address,
187 : const int prefix_len,
188 : std::string vrf_name,
189 : const Peer* bgp_peer) {
190 :
191 0 : InetUnicastAgentRouteTable::DeleteReq(bgp_peer, vrf_name,
192 : ip_address, prefix_len,
193 : NULL);
194 0 : }
195 :
196 541 : bool AgentXmppChannel::SendUpdate(const uint8_t *msg, size_t size) {
197 :
198 541 : if (agent_->stats())
199 541 : agent_->stats()->incr_xmpp_out_msgs(xs_idx_);
200 :
201 1082 : return channel_->Send(msg, size, xmps::BGP,
202 1082 : boost::bind(&AgentXmppChannel::WriteReadyCb, this, _1));
203 : }
204 :
205 0 : void AgentXmppChannel::ReceiveEvpnUpdate(XmlPugi *pugi) {
206 0 : pugi::xml_node node = pugi->FindNode("items");
207 0 : pugi::xml_attribute attr = node.attribute("node");
208 :
209 : char *saveptr;
210 0 : strtok_r(const_cast<char *>(attr.value()), "/", &saveptr);
211 0 : strtok_r(NULL, "/", &saveptr);
212 0 : char *vrf_name = strtok_r(NULL, "", &saveptr);
213 0 : const std::string vrf(vrf_name);
214 : EvpnAgentRouteTable *rt_table =
215 : static_cast<EvpnAgentRouteTable *>
216 0 : (agent_->vrf_table()->GetEvpnRouteTable(vrf_name));
217 0 : if (rt_table == NULL) {
218 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
219 : "Invalid VRF. Ignoring route retract" +
220 : string(attr.value()));
221 0 : return;
222 : }
223 :
224 0 : pugi::xml_node node_check = pugi->FindNode("retract");
225 0 : if (!pugi->IsNull(node_check)) {
226 0 : for (node = node.first_child(); node; node = node.next_sibling()) {
227 0 : if (strcmp(node.name(), "retract") == 0) {
228 0 : std::string id = node.first_attribute().value();
229 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
230 : "EVPN Delete Node id:" + id);
231 :
232 0 : boost::scoped_array<char> buff(new char[id.length() + 1]);
233 0 : strcpy(buff.get(), id.c_str());
234 :
235 : // retract does not have nlri. Need to decode key fields from
236 : // retract id. Format of retract-id expected are:
237 : // 00:00:00:01:01:01,1.1.1.1/32 - Mac and IP for Non-VXLAN Encap
238 : // 10-00:00:00:01:01:01,1.1.1.1/32 - VXLAN, mac, ip.
239 : //
240 : // In case of not finding pattern "-" whole string will be
241 : // returned in token. So dont use it for ethernet_tag.
242 : // Check for string length of saveptr to know if string was
243 : // tokenised.
244 :
245 0 : uint16_t offset = 0;
246 0 : uint32_t ethernet_tag = 0;
247 0 : saveptr = NULL;
248 :
249 : // If id has "-", the value before "-" is treated as
250 : // ethernet-tag
251 0 : char *token = strtok_r(buff.get() + offset, "-", &saveptr);
252 0 : if ((strlen(saveptr) != 0) && token) {
253 0 : ethernet_tag = atoi(token);
254 0 : offset += strlen(token) + 1;
255 : }
256 :
257 : // Get MAC address. Its delimited by ","
258 0 : token = strtok_r(buff.get() + offset, ",", &saveptr);
259 0 : if ((strlen(saveptr) == 0) || (token == NULL)) {
260 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
261 : "Error parsing MAC from retract-id: " +id);
262 0 : continue;
263 : }
264 :
265 0 : boost::system::error_code ec;
266 0 : MacAddress mac(token, &ec);
267 0 : if (ec) {
268 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
269 : "Error decoding MAC from retract-id: "+id);
270 0 : continue;
271 : }
272 :
273 0 : offset += strlen(token) + 1;
274 0 : IpAddress ip_addr, group, source;
275 :
276 0 : string str = buff.get() + offset;
277 0 : size_t pos = str.find(',');
278 0 : if (pos != string::npos) {
279 0 : string group_str = str.substr(pos + 1);
280 0 : pos = group_str.find(',');
281 0 : if (pos == string::npos) {
282 0 : continue;
283 : }
284 0 : string addrstr = group_str.substr(0, pos);
285 0 : group = IpAddress::from_string(group_str, ec);
286 0 : if (ec) {
287 0 : continue;
288 : }
289 :
290 0 : string source_str = str.substr(pos + 1);
291 0 : source = IpAddress::from_string(source_str, ec);
292 0 : if (ec) {
293 0 : continue;
294 : }
295 0 : }
296 :
297 0 : uint32_t plen = ParseEvpnAddress(buff.get() + offset,
298 0 : &ip_addr, mac);
299 : if (plen < 0) {
300 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
301 : "Error decoding IP address from "
302 : "retract-id: "+id);
303 : continue;
304 : }
305 :
306 0 : if (mac.IsMulticast()) {
307 0 : TunnelOlist olist;
308 0 : agent_->oper_db()->multicast()->
309 0 : ModifyEvpnMembers(bgp_peer_id(), vrf_name,
310 0 : group.to_v4(), source.to_v4(),
311 : olist, ethernet_tag,
312 : ControllerPeerPath::kInvalidPeerIdentifier);
313 0 : continue;
314 0 : } else if (mac == MacAddress::BroadcastMac()) {
315 : //Deletes the peer path for all boradcast and
316 : //traverses the subnet route in VRF to issue delete of peer
317 : //for them as well.
318 0 : TunnelOlist olist;
319 0 : agent_->oper_db()->multicast()->
320 0 : ModifyEvpnMembers(bgp_peer_id(),
321 : vrf_name, olist,
322 : ethernet_tag,
323 : ControllerPeerPath::kInvalidPeerIdentifier);
324 :
325 : //Ideally in non TSN node leaf olist is not to be
326 : //present
327 0 : if (agent_->tsn_enabled() == false)
328 0 : return;
329 0 : agent_->oper_db()->multicast()->
330 0 : ModifyTorMembers(bgp_peer_id(),
331 : vrf_name, olist,
332 : ethernet_tag,
333 : ControllerPeerPath::kInvalidPeerIdentifier);
334 0 : } else {
335 0 : const Peer *bgp_peer = bgp_peer_id();
336 : AgentRouteData *rt_data =
337 0 : new ControllerVmRoute(bgp_peer_id());
338 0 : rt_table->DeleteReq(bgp_peer, vrf_name, mac,
339 : ip_addr, plen, ethernet_tag,
340 : rt_data);
341 :
342 0 : if (VxlanRoutingManager::IsVxlanAvailable(agent_) &&
343 0 : VxlanRoutingManager::IsRoutingVrf(vrf_name, agent_)) {
344 0 : bgp_peer =
345 : VxlanRoutingManager::routing_vrf_vxlan_bgp_peer_;
346 0 : InetRequestDelete(ip_addr,
347 : plen, vrf_name, bgp_peer);
348 : }
349 : }
350 0 : }
351 : }
352 0 : return;
353 : }
354 :
355 : //Call Auto-generated Code to return struct
356 0 : std::unique_ptr<AutogenProperty> xparser(new AutogenProperty());
357 0 : if (EnetItemsType::XmlParseProperty(node, &xparser) == false) {
358 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
359 : "Xml Parsing for evpn Failed");
360 0 : return;
361 : }
362 :
363 : EnetItemsType *items;
364 : EnetItemType *item;
365 :
366 0 : items = (static_cast<EnetItemsType *>(xparser.get()));
367 0 : std::vector<EnetItemType>::iterator iter;
368 0 : for (vector<EnetItemType>::iterator iter =items->item.begin();
369 0 : iter != items->item.end(); iter++) {
370 0 : item = &*iter;
371 :
372 0 : boost::system::error_code ec;
373 0 : MacAddress mac = MacAddress(item->entry.nlri.mac);
374 0 : IpAddress ip_addr, group, source;
375 0 : group = IpAddress::from_string(item->entry.nlri.group, ec);
376 0 : source = IpAddress::from_string(item->entry.nlri.source, ec);
377 :
378 0 : uint32_t plen = ParseEvpnAddress(item->entry.nlri.address, &ip_addr,
379 0 : mac);
380 : if (plen < 0) {
381 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
382 : "Error parsing address : " + item->entry.nlri.address);
383 : return;
384 : }
385 :
386 0 : if (mac.IsMulticast()) {
387 : // Requires changes for case when multicast source
388 : // is inside contrail.
389 0 : AddMulticastEvpnRoute(vrf_name, source, group, item);
390 0 : continue;
391 : }
392 :
393 0 : if (IsEcmp(item->entry.next_hops.next_hop)) {
394 0 : VnListType vn_list;
395 0 : vn_list.insert(item->entry.virtual_network);
396 0 : AddEvpnEcmpRoute(vrf_name, mac, ip_addr, plen, item, vn_list);
397 0 : } else {
398 0 : AddEvpnRoute(vrf_name, item->entry.nlri.mac, ip_addr, plen, item);
399 : }
400 : }
401 0 : }
402 :
403 0 : void AgentXmppChannel::ReceiveMulticastUpdate(XmlPugi *pugi) {
404 :
405 0 : pugi::xml_node node = pugi->FindNode("items");
406 0 : pugi::xml_attribute attr = node.attribute("node");
407 :
408 : char *saveptr;
409 0 : strtok_r(const_cast<char *>(attr.value()), "/", &saveptr);
410 0 : strtok_r(NULL, "/", &saveptr);
411 0 : char *vrf_name = strtok_r(NULL, "", &saveptr);
412 0 : const std::string vrf(vrf_name);
413 :
414 0 : pugi::xml_node node_check = pugi->FindNode("retract");
415 0 : if (!pugi->IsNull(node_check)) {
416 0 : pugi->ReadNode("retract"); //sets the context
417 0 : std::string retract_id = pugi->ReadAttrib("id");
418 0 : if (bgp_peer_id() != agent_->mulitcast_builder()->
419 0 : bgp_peer_id()) {
420 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
421 : "Ignore retract request from non multicast tree "
422 : "builder peer; Multicast Delete Node id:" + retract_id);
423 0 : return;
424 : }
425 :
426 0 : for (node = node.first_child(); node; node = node.next_sibling()) {
427 0 : if (strcmp(node.name(), "retract") == 0) {
428 0 : std::string id = node.first_attribute().value();
429 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
430 : "Multicast Delete Node id:" + id);
431 :
432 : // Parse identifier to obtain group,source
433 : // <addr:VRF:Group,Source)
434 0 : strtok_r(const_cast<char *>(id.c_str()), ":", &saveptr);
435 0 : strtok_r(NULL, ":", &saveptr);
436 0 : char *group = strtok_r(NULL, ",", &saveptr);
437 0 : char *source = strtok_r(NULL, "", &saveptr);
438 0 : if (group == NULL || source == NULL) {
439 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
440 : "Error parsing multicast group address from retract id");
441 0 : return;
442 : }
443 :
444 0 : boost::system::error_code ec;
445 0 : IpAddress g_address = IpAddress::from_string(group, ec);
446 0 : if (ec.value() != 0) {
447 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
448 : "Error parsing multicast group address");
449 0 : return;
450 : }
451 :
452 0 : IpAddress s_address = IpAddress::from_string(source, ec);
453 0 : if (ec.value() != 0) {
454 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
455 : "Error parsing multicast source address");
456 0 : return;
457 : }
458 :
459 0 : TunnelOlist olist;
460 : //Retract with invalid identifier
461 0 : agent_->oper_db()->multicast()->
462 0 : ModifyFabricMembers(agent_->multicast_tree_builder_peer(),
463 0 : vrf, g_address.to_v4(),
464 0 : s_address.to_v4(), 0, olist,
465 : ControllerPeerPath::kInvalidPeerIdentifier);
466 0 : }
467 : }
468 0 : return;
469 0 : }
470 :
471 0 : pugi::xml_node items_node = pugi->FindNode("item");
472 0 : if (!pugi->IsNull(items_node)) {
473 0 : pugi->ReadNode("item"); //sets the context
474 0 : std::string item_id = pugi->ReadAttrib("id");
475 0 : if (!(agent_->mulitcast_builder()) || (bgp_peer_id() !=
476 0 : agent_->mulitcast_builder()->bgp_peer_id())) {
477 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
478 : "Ignore request from non multicast tree "
479 : "builder peer; Multicast Delete Node:" + item_id);
480 0 : return;
481 : }
482 0 : }
483 :
484 : //Call Auto-generated Code to return struct
485 0 : std::unique_ptr<AutogenProperty> xparser(new AutogenProperty());
486 0 : if (McastItemsType::XmlParseProperty(node, &xparser) == false) {
487 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
488 : "Xml Parsing for Multicast Message Failed");
489 0 : return;
490 : }
491 :
492 : McastItemsType *items;
493 : McastItemType *item;
494 :
495 0 : items = (static_cast<McastItemsType *>(xparser.get()));
496 0 : std::vector<McastItemType>::iterator items_iter;
497 0 : boost::system::error_code ec;
498 0 : for (items_iter = items->item.begin(); items_iter != items->item.end();
499 0 : items_iter++) {
500 :
501 0 : item = &*items_iter;
502 :
503 0 : IpAddress g_address = IpAddress::from_string(item->entry.nlri.group, ec);
504 0 : if (ec.value() != 0) {
505 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
506 : "Error parsing multicast group address");
507 0 : return;
508 : }
509 :
510 0 : IpAddress s_address = IpAddress::from_string(item->entry.nlri.source, ec);
511 0 : if (ec.value() != 0) {
512 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
513 : "Error parsing multicast source address");
514 0 : return;
515 : }
516 :
517 0 : TunnelOlist olist;
518 0 : std::vector<McastNextHopType>::iterator iter;
519 0 : for (iter = item->entry.olist.next_hop.begin();
520 0 : iter != item->entry.olist.next_hop.end(); iter++) {
521 :
522 0 : McastNextHopType nh = *iter;
523 0 : IpAddress addr = IpAddress::from_string(nh.address, ec);
524 0 : if (ec.value() != 0) {
525 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
526 : "Error parsing next-hop address");
527 0 : return;
528 : }
529 :
530 : int label;
531 0 : stringstream nh_label(nh.label);
532 0 : nh_label >> label;
533 0 : TunnelType::TypeBmap encap = agent_->controller()->
534 0 : GetTypeBitmap(nh.tunnel_encapsulation_list);
535 0 : olist.push_back(OlistTunnelEntry(boost::uuids::nil_uuid(), label,
536 0 : addr.to_v4(), encap));
537 0 : }
538 :
539 : IpAddress source_address =
540 0 : IpAddress::from_string(item->entry.nlri.source_address, ec);
541 0 : if ((ec.value() == 0) && (source_address != IpAddress(Ip4Address()))) {
542 0 : olist.push_back(OlistTunnelEntry(boost::uuids::nil_uuid(), 0,
543 0 : source_address.to_v4(),
544 : TunnelType::MplsType()));
545 : }
546 :
547 0 : agent_->oper_db()->multicast()->ModifyFabricMembers(
548 0 : agent_->multicast_tree_builder_peer(),
549 0 : vrf, g_address.to_v4(), s_address.to_v4(),
550 0 : item->entry.nlri.source_label, olist,
551 0 : agent_->controller()->multicast_sequence_number());
552 0 : }
553 0 : }
554 :
555 0 : void AgentXmppChannel::ReceiveMvpnUpdate(XmlPugi *pugi) {
556 :
557 0 : pugi::xml_node node = pugi->FindNode("items");
558 0 : pugi::xml_attribute attr = node.attribute("node");
559 :
560 : char *saveptr;
561 0 : strtok_r(const_cast<char *>(attr.value()), "/", &saveptr);
562 0 : strtok_r(NULL, "/", &saveptr);
563 0 : char *vrf_name = strtok_r(NULL, "", &saveptr);
564 0 : const std::string vrf(vrf_name);
565 :
566 0 : pugi::xml_node node_check = pugi->FindNode("retract");
567 0 : if (!pugi->IsNull(node_check)) {
568 0 : pugi->ReadNode("retract"); //sets the context
569 0 : std::string retract_id = pugi->ReadAttrib("id");
570 :
571 0 : for (node = node.first_child(); node; node = node.next_sibling()) {
572 0 : if (strcmp(node.name(), "retract") == 0) {
573 0 : std::string id = node.first_attribute().value();
574 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
575 : "Multicast Delete Node id:" + id);
576 :
577 : // Parse identifier to obtain group,source
578 : // <addr:VRF:Group,Source)
579 0 : strtok_r(const_cast<char *>(id.c_str()), ":", &saveptr);
580 0 : strtok_r(NULL, ":", &saveptr);
581 0 : char *group = strtok_r(NULL, ",", &saveptr);
582 0 : char *source = strtok_r(NULL, "", &saveptr);
583 0 : if (group == NULL || source == NULL) {
584 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
585 : "Error parsing multicast group address from retract id");
586 0 : return;
587 : }
588 :
589 0 : boost::system::error_code ec;
590 0 : IpAddress g_address = IpAddress::from_string(group, ec);
591 0 : if (ec.value() != 0) {
592 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
593 : "Error parsing multicast group address");
594 0 : return;
595 : }
596 :
597 0 : IpAddress s_address = IpAddress::from_string(source, ec);
598 0 : if (ec.value() != 0) {
599 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
600 : "Error parsing multicast source address");
601 0 : return;
602 : }
603 :
604 : //Retract with invalid identifier
605 0 : agent_->oper_db()->multicast()->ModifyMvpnVrfRegistration(
606 0 : bgp_peer_id(), vrf, g_address.to_v4(),
607 0 : s_address.to_v4(),
608 : ControllerPeerPath::kInvalidPeerIdentifier);
609 0 : }
610 : }
611 0 : return;
612 0 : }
613 :
614 0 : pugi::xml_node items_node = pugi->FindNode("item");
615 0 : if (!pugi->IsNull(items_node)) {
616 0 : pugi->ReadNode("item"); //sets the context
617 0 : std::string item_id = pugi->ReadAttrib("id");
618 0 : if (!(agent_->mulitcast_builder()) || (bgp_peer_id() !=
619 0 : agent_->mulitcast_builder()->bgp_peer_id())) {
620 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
621 : "Ignore request from non multicast tree "
622 : "builder peer; Multicast Delete Node:" + item_id);
623 0 : return;
624 : }
625 0 : }
626 :
627 : //Call Auto-generated Code to return struct
628 0 : std::unique_ptr<AutogenProperty> xparser(new AutogenProperty());
629 0 : if (MvpnItemsType::XmlParseProperty(node, &xparser) == false) {
630 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
631 : "Xml Parsing for Multicast Message Failed");
632 0 : return;
633 : }
634 :
635 : MvpnItemsType *items;
636 : MvpnItemType *item;
637 :
638 0 : items = (static_cast<MvpnItemsType *>(xparser.get()));
639 0 : std::vector<MvpnItemType>::iterator items_iter;
640 0 : boost::system::error_code ec;
641 0 : for (items_iter = items->item.begin(); items_iter != items->item.end();
642 0 : items_iter++) {
643 :
644 0 : item = &*items_iter;
645 :
646 0 : IpAddress g_address = IpAddress::from_string(item->entry.nlri.group, ec);
647 0 : if (ec.value() != 0) {
648 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
649 : "Error parsing multicast group address");
650 0 : return;
651 : }
652 :
653 0 : IpAddress s_address = IpAddress::from_string(item->entry.nlri.source, ec);
654 0 : if (ec.value() != 0) {
655 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
656 : "Error parsing multicast source address");
657 0 : return;
658 : }
659 :
660 0 : int route_type = item->entry.nlri.route_type;
661 0 : if (route_type != 7) {
662 0 : continue;
663 : }
664 :
665 0 : agent_->oper_db()->multicast()->ModifyMvpnVrfRegistration(
666 0 : bgp_peer_id(), vrf, g_address.to_v4(),
667 0 : s_address.to_v4(),
668 0 : agent_->controller()->
669 : multicast_sequence_number());
670 : }
671 0 : }
672 :
673 0 : void AgentXmppChannel::ReceiveV4V6Update(XmlPugi *pugi) {
674 :
675 0 : pugi::xml_node node = pugi->FindNode("items");
676 0 : pugi::xml_attribute attr = node.attribute("node");
677 :
678 0 : const char *af = NULL;
679 : char *saveptr;
680 0 : af = strtok_r(const_cast<char *>(attr.value()), "/", &saveptr);
681 0 : strtok_r(NULL, "/", &saveptr);
682 0 : char *vrf_name = strtok_r(NULL, "", &saveptr);
683 :
684 0 : VrfKey vrf_key(vrf_name);
685 : VrfEntry *vrf =
686 0 : static_cast<VrfEntry *>(agent_->vrf_table()->
687 0 : FindActiveEntry(&vrf_key));
688 0 : if (!vrf) {
689 0 : CONTROLLER_INFO_TRACE (Trace, GetBgpPeerName(), vrf_name,
690 : "VRF not found");
691 0 : return;
692 : }
693 :
694 0 : InetUnicastAgentRouteTable *rt_table = NULL;
695 0 : if (atoi(af) == BgpAf::IPv4) {
696 0 : rt_table = vrf->GetInet4UnicastRouteTable();
697 0 : } else if (atoi(af) == BgpAf::IPv6) {
698 0 : rt_table = vrf->GetInet6UnicastRouteTable();
699 : }
700 :
701 0 : if (!rt_table) {
702 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
703 : "VRF not found");
704 0 : return;
705 : }
706 :
707 0 : if (!pugi->IsNull(node)) {
708 0 : pugi::xml_node node_check = pugi->FindNode("retract");
709 0 : if (!pugi->IsNull(node_check)) {
710 0 : for (node = node.first_child(); node; node = node.next_sibling()) {
711 0 : if (strcmp(node.name(), "retract") == 0) {
712 0 : std::string id = node.first_attribute().value();
713 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
714 : "Delete Node id:" + id);
715 :
716 0 : boost::system::error_code ec;
717 : int prefix_len;
718 :
719 0 : if (VxlanRoutingManager::IsVxlanAvailable(agent_) &&
720 0 : VxlanRoutingManager::IsRoutingVrf(vrf_name, agent_)) {
721 0 : return;
722 : }
723 0 : if (atoi(af) == BgpAf::IPv4) {
724 0 : Ip4Address prefix_addr;
725 0 : ec = Ip4PrefixParse(id, &prefix_addr, &prefix_len);
726 0 : if (ec.value() != 0) {
727 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
728 : "Error parsing v4 prefix for delete");
729 0 : return;
730 : }
731 0 : rt_table->DeleteReq(bgp_peer_id(), vrf_name,
732 : prefix_addr, prefix_len,
733 0 : new ControllerVmRoute(bgp_peer_id()));
734 :
735 0 : } else if (atoi(af) == BgpAf::IPv6) {
736 0 : Ip6Address prefix_addr;
737 0 : ec = Inet6PrefixParse(id, &prefix_addr, &prefix_len);
738 0 : if (ec.value() != 0) {
739 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
740 : "Error parsing v6 prefix for delete");
741 0 : return;
742 : }
743 0 : rt_table->DeleteReq(bgp_peer_id(), vrf_name,
744 : prefix_addr, prefix_len,
745 0 : new ControllerVmRoute(bgp_peer_id()));
746 : }
747 0 : }
748 : }
749 0 : return;
750 : }
751 :
752 : //Call Auto-generated Code to return struct
753 0 : std::unique_ptr<AutogenProperty> xparser(new AutogenProperty());
754 0 : if (ItemsType::XmlParseProperty(node, &xparser) == false) {
755 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
756 : "Xml Parsing Failed");
757 0 : return;
758 : }
759 : ItemsType *items;
760 : ItemType *item;
761 :
762 0 : items = (static_cast<ItemsType *>(xparser.get()));
763 0 : for (vector<ItemType>::iterator iter =items->item.begin();
764 0 : iter != items->item.end();
765 0 : ++iter) {
766 0 : item = &*iter;
767 0 : boost::system::error_code ec;
768 : int prefix_len;
769 :
770 0 : if (atoi(af) == BgpAf::IPv4) {
771 0 : Ip4Address prefix_addr;
772 0 : ec = Ip4PrefixParse(item->entry.nlri.address, &prefix_addr,
773 : &prefix_len);
774 0 : if (ec.value() != 0) {
775 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
776 : "Error parsing v4 route address");
777 0 : return;
778 : }
779 0 : AddRoute(vrf_name, prefix_addr, prefix_len, item);
780 0 : } else if (atoi(af) == BgpAf::IPv6) {
781 0 : Ip6Address prefix_addr;
782 0 : ec = Inet6PrefixParse(item->entry.nlri.address, &prefix_addr,
783 : &prefix_len);
784 0 : if (ec.value() != 0) {
785 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
786 : "Error parsing v6 route address");
787 0 : return;
788 : }
789 0 : AddRoute(vrf_name, prefix_addr, prefix_len, item);
790 : } else {
791 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
792 : "Error updating route, Unknown IP family");
793 : }
794 : }
795 0 : }
796 0 : }
797 :
798 :
799 0 : void AgentXmppChannel::ReceiveInet4MplsUpdate(XmlPugi *pugi) {
800 :
801 0 : pugi::xml_node node = pugi->FindNode("items");
802 0 : pugi::xml_attribute attr = node.attribute("node");
803 :
804 0 : const char *af = NULL;
805 : char *saveptr;
806 0 : af = strtok_r(const_cast<char *>(attr.value()), "/", &saveptr);
807 0 : strtok_r(NULL, "/", &saveptr);
808 0 : char *vrf_name = strtok_r(NULL, "", &saveptr);
809 :
810 0 : VrfKey vrf_key(vrf_name);
811 : VrfEntry *vrf =
812 0 : static_cast<VrfEntry *>(agent_->vrf_table()->
813 0 : FindActiveEntry(&vrf_key));
814 0 : if (!vrf) {
815 0 : CONTROLLER_INFO_TRACE (Trace, GetBgpPeerName(), vrf_name,
816 : "VRF not found");
817 0 : return;
818 : }
819 :
820 0 : InetUnicastAgentRouteTable *rt_table = NULL;
821 0 : if (atoi(af) == BgpAf::IPv4) {
822 0 : rt_table = vrf->GetInet4MplsUnicastRouteTable();
823 : }
824 :
825 0 : if (!rt_table) {
826 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
827 : "Route Table not found");
828 0 : return;
829 : }
830 :
831 0 : if (!pugi->IsNull(node)) {
832 :
833 0 : pugi::xml_node node_check = pugi->FindNode("retract");
834 0 : if (!pugi->IsNull(node_check)) {
835 0 : for (node = node.first_child(); node; node = node.next_sibling()) {
836 0 : if (strcmp(node.name(), "retract") == 0) {
837 0 : std::string id = node.first_attribute().value();
838 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
839 : "Delete Node id:" + id);
840 :
841 0 : boost::system::error_code ec;
842 : int prefix_len;
843 0 : if (atoi(af) == BgpAf::IPv4) {
844 0 : Ip4Address prefix_addr;
845 0 : ec = Ip4PrefixParse(id, &prefix_addr, &prefix_len);
846 0 : if (ec.value() != 0) {
847 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
848 : "Error parsing v4 prefix for delete");
849 0 : return;
850 : }
851 :
852 0 : rt_table->DeleteMplsRouteReq(bgp_peer_id(), vrf_name,
853 : prefix_addr, prefix_len,
854 0 : new ControllerVmRoute(bgp_peer_id()));
855 :
856 : }
857 0 : }
858 : }
859 0 : return;
860 : }
861 :
862 : //Call Auto-generated Code to return struct
863 0 : std::unique_ptr<AutogenProperty> xparser(new AutogenProperty());
864 0 : if (ItemsType::XmlParseProperty(node, &xparser) == false) {
865 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
866 : "Xml Parsing Failed");
867 0 : return;
868 : }
869 : ItemsType *items;
870 : ItemType *item;
871 :
872 0 : items = (static_cast<ItemsType *>(xparser.get()));
873 0 : for (vector<ItemType>::iterator iter =items->item.begin();
874 0 : iter != items->item.end();
875 0 : ++iter) {
876 0 : item = &*iter;
877 0 : boost::system::error_code ec;
878 : int prefix_len;
879 :
880 0 : if (atoi(af) == BgpAf::IPv4) {
881 0 : Ip4Address prefix_addr;
882 0 : ec = Ip4PrefixParse(item->entry.nlri.address, &prefix_addr,
883 : &prefix_len);
884 0 : if (ec.value() != 0) {
885 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
886 : "Error parsing v4 route address");
887 0 : return;
888 : }
889 0 : AddMplsRoute(vrf_name, prefix_addr, prefix_len, item);
890 : } else {
891 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
892 : "Error updating route, Unknown IP family");
893 : }
894 : }
895 0 : }
896 0 : }
897 :
898 : template <typename TYPE>
899 0 : static void GetEcmpHashFieldsToUse(TYPE *item,
900 : EcmpLoadBalance &ecmp_load_balance) {
901 0 : ecmp_load_balance.ResetAll();
902 0 : if (item->entry.load_balance.load_balance_decision.empty() ||
903 0 : item->entry.load_balance.load_balance_decision !=
904 : LoadBalanceDecision)
905 0 : ecmp_load_balance.SetAll();
906 :
907 0 : uint8_t field_list_size = item->entry.
908 0 : load_balance.load_balance_fields.load_balance_field_list.size();
909 0 : if (field_list_size == 0)
910 0 : ecmp_load_balance.SetAll();
911 :
912 0 : for (uint32_t i = 0; i < field_list_size; i++) {
913 0 : std::string field_type = item->entry.
914 0 : load_balance.load_balance_fields.load_balance_field_list[i];
915 0 : if (field_type == ecmp_load_balance.source_ip_str())
916 0 : ecmp_load_balance.set_source_ip();
917 0 : if (field_type == ecmp_load_balance.destination_ip_str())
918 0 : ecmp_load_balance.set_destination_ip();
919 0 : if (field_type == ecmp_load_balance.ip_protocol_str())
920 0 : ecmp_load_balance.set_ip_protocol();
921 0 : if (field_type == ecmp_load_balance.source_port_str())
922 0 : ecmp_load_balance.set_source_port();
923 0 : if (field_type == ecmp_load_balance.destination_port_str())
924 0 : ecmp_load_balance.set_destination_port();
925 : }
926 0 : }
927 :
928 0 : void AgentXmppChannel::AddInetEcmpRoute(string vrf_name, IpAddress prefix_addr,
929 : uint32_t prefix_len, ItemType *item,
930 : const VnListType &vn_list) {
931 0 : const Peer *bgp_peer = bgp_peer_id();
932 0 : if (VxlanRoutingManager::IsVxlanAvailable(agent_) &&
933 0 : VxlanRoutingManager::IsRoutingVrf(vrf_name, agent_)) {
934 0 : return;
935 : }
936 0 : InetUnicastAgentRouteTable *rt_table = PrefixToRouteTable(vrf_name,
937 : prefix_addr);
938 0 : if (rt_table == NULL) {
939 0 : return;
940 : }
941 :
942 0 : std::stringstream str;
943 0 : str << prefix_addr.to_string();
944 0 : str << "/";
945 0 : str << prefix_len;
946 :
947 0 : EcmpLoadBalance ecmp_load_balance;
948 0 : GetEcmpHashFieldsToUse(item, ecmp_load_balance);
949 0 : ControllerEcmpRoute *data = BuildEcmpData(item, vn_list, ecmp_load_balance,
950 0 : rt_table, str.str());
951 : ControllerEcmpRoute::ClonedLocalPathListIter iter =
952 0 : data->cloned_local_path_list().begin();
953 0 : while (iter != data->cloned_local_path_list().end()) {
954 0 : rt_table->AddClonedLocalPathReq(bgp_peer, vrf_name,
955 : prefix_addr, prefix_len,
956 0 : (*iter));
957 0 : iter++;
958 : }
959 : // ECMP create component NH
960 0 : rt_table->AddRemoteVmRouteReq(bgp_peer, vrf_name,
961 : prefix_addr, prefix_len, data);
962 0 : }
963 :
964 0 : void AgentXmppChannel::AddEvpnEcmpRoute(string vrf_name,
965 : const MacAddress &mac,
966 : const IpAddress &prefix_addr,
967 : uint32_t plen,
968 : EnetItemType *item,
969 : const VnListType &vn_list) {
970 : // Verify that vrf is present and active
971 0 : VrfKey vrf_key(vrf_name);
972 : VrfEntry *vrf =
973 0 : static_cast<VrfEntry *>(agent_->vrf_table()->
974 0 : FindActiveEntry(&vrf_key));
975 0 : if (!vrf) {
976 0 : CONTROLLER_INFO_TRACE (Trace, GetBgpPeerName(), vrf_name,
977 : "VRF not found");
978 0 : return;
979 : }
980 :
981 0 : const Peer *bgp_peer = bgp_peer_id();
982 :
983 : EvpnAgentRouteTable *rt_table = static_cast<EvpnAgentRouteTable *>
984 0 : (agent_->vrf_table()->GetEvpnRouteTable(vrf_name));
985 0 : if (rt_table == NULL || rt_table->vrf_entry() == NULL) {
986 0 : return;
987 : }
988 :
989 0 : std::stringstream str;
990 0 : str << item->entry.nlri.ethernet_tag;
991 0 : str << ":";
992 0 : str << mac.ToString();
993 0 : str << ":";
994 0 : str << prefix_addr.to_string();
995 :
996 0 : ControllerEcmpRoute *data = BuildEcmpData(item, vn_list, EcmpLoadBalance(),
997 0 : rt_table, str.str());
998 : ControllerEcmpRoute::ClonedLocalPathListIter iter =
999 0 : data->cloned_local_path_list().begin();
1000 0 : while (iter != data->cloned_local_path_list().end()) {
1001 0 : rt_table->AddClonedLocalPathReq(bgp_peer, vrf_name,
1002 : mac, prefix_addr,
1003 0 : item->entry.nlri.ethernet_tag,
1004 0 : (*iter));
1005 0 : iter++;
1006 : }
1007 : //ECMP create component NH
1008 0 : rt_table->AddRemoteVmRouteReq(bgp_peer, vrf_name, mac, prefix_addr,
1009 0 : plen, item->entry.nlri.ethernet_tag, data);
1010 0 : }
1011 :
1012 : template <typename TYPE>
1013 0 : ControllerEcmpRoute *AgentXmppChannel::BuildEcmpData(TYPE *item,
1014 : const VnListType &vn_list,
1015 : const EcmpLoadBalance &ecmp_load_balance,
1016 : const AgentRouteTable *rt_table,
1017 : const std::string &prefix_str) {
1018 0 : TagList tag_list;
1019 0 : BuildTagList(item, tag_list);
1020 :
1021 0 : ControllerEcmpRoute *data = new ControllerEcmpRoute(bgp_peer_id(),
1022 : vn_list, ecmp_load_balance, tag_list,
1023 : item, rt_table, prefix_str);
1024 0 : return data;
1025 0 : }
1026 :
1027 0 : static bool FillEvpnOlist(Agent *agent,
1028 : EnetOlistType &olist,
1029 : TunnelOlist *tunnel_olist) {
1030 0 : for (uint32_t i = 0; i < olist.next_hop.size(); i++) {
1031 0 : boost::system::error_code ec;
1032 : IpAddress addr =
1033 0 : IpAddress::from_string(olist.next_hop[i].address,
1034 0 : ec);
1035 0 : if (ec.value() != 0) {
1036 0 : return false;
1037 : }
1038 :
1039 0 : int label = olist.next_hop[i].label;
1040 : TunnelType::TypeBmap encap = agent->controller()->
1041 0 : GetTypeBitmap(olist.next_hop[i].tunnel_encapsulation_list);
1042 0 : tunnel_olist->push_back(OlistTunnelEntry(boost::uuids::nil_uuid(), label,
1043 0 : addr.to_v4(), encap));
1044 : }
1045 0 : return true;
1046 : }
1047 :
1048 0 : void AgentXmppChannel::AddMulticastEvpnRoute(const std::string &vrf_name,
1049 : const IpAddress &source,
1050 : const IpAddress &group,
1051 : EnetItemType *item) {
1052 :
1053 : //Traverse Leaf Olist
1054 0 : TunnelOlist leaf_olist;
1055 0 : TunnelOlist olist;
1056 : //Fill leaf olist and olist
1057 : //TODO can check for item->entry.assisted_replication_supported
1058 : //and then populate leaf_olist
1059 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), "Composite",
1060 : "add leaf evpn multicast route");
1061 0 : if (FillEvpnOlist(agent_, item->entry.leaf_olist, &leaf_olist) == false) {
1062 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1063 : "Error parsing next-hop address");
1064 0 : return;
1065 : }
1066 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), "Composite",
1067 : "add evpn multicast route");
1068 0 : if (FillEvpnOlist(agent_, item->entry.olist, &olist) == false) {
1069 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1070 : "Error parsing next-hop address");
1071 0 : return;
1072 : }
1073 :
1074 0 : agent_->oper_db()->multicast()->
1075 0 : ModifyEvpnMembers(bgp_peer_id(), vrf_name, group.to_v4(),
1076 0 : source.to_v4(), leaf_olist,
1077 0 : item->entry.nlri.ethernet_tag,
1078 0 : agent_->controller()->
1079 : multicast_sequence_number());
1080 0 : }
1081 :
1082 0 : void AgentXmppChannel::AddMulticastEvpnRoute(const string &vrf_name,
1083 : const MacAddress &mac,
1084 : EnetItemType *item) {
1085 : //Traverse Leaf Olist
1086 0 : TunnelOlist leaf_olist;
1087 0 : TunnelOlist olist;
1088 : //Fill leaf olist and olist
1089 : //TODO can check for item->entry.assisted_replication_supported
1090 : //and then populate leaf_olist
1091 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), "Composite",
1092 : "add leaf evpn multicast route");
1093 0 : if (FillEvpnOlist(agent_, item->entry.leaf_olist, &leaf_olist) == false) {
1094 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1095 : "Error parsing next-hop address");
1096 0 : return;
1097 : }
1098 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), "Composite",
1099 : "add evpn multicast route");
1100 0 : if (FillEvpnOlist(agent_, item->entry.olist, &olist) == false) {
1101 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1102 : "Error parsing next-hop address");
1103 0 : return;
1104 : }
1105 :
1106 0 : agent_->oper_db()->multicast()->
1107 0 : ModifyTorMembers(bgp_peer_id(), vrf_name, leaf_olist,
1108 0 : item->entry.nlri.ethernet_tag,
1109 0 : agent_->controller()->
1110 : multicast_sequence_number());
1111 :
1112 0 : agent_->oper_db()->multicast()->
1113 0 : ModifyEvpnMembers(bgp_peer_id(), vrf_name, olist,
1114 0 : item->entry.nlri.ethernet_tag,
1115 0 : agent_->controller()->
1116 : multicast_sequence_number());
1117 0 : }
1118 :
1119 0 : void AgentXmppChannel::AddFabricVrfRoute(const Ip4Address &prefix_addr,
1120 : uint32_t prefix_len,
1121 : const Ip4Address &addr,
1122 : const VnListType &vn_list,
1123 : const SecurityGroupList &sg_list,
1124 : const TagList &tag_list) {
1125 : InetUnicastAgentRouteTable *table =
1126 0 : agent_->fabric_vrf()->GetInet4UnicastRouteTable();
1127 :
1128 0 : if (prefix_addr == agent_->router_id() && prefix_len == 32) {
1129 0 : return;
1130 : }
1131 :
1132 0 : if (addr == agent_->router_id()) {
1133 : ClonedLocalPath *data =
1134 : new ClonedLocalPath(MplsTable::kInvalidExportLabel,
1135 0 : vn_list, sg_list, tag_list, sequence_number());
1136 0 : table->AddClonedLocalPathReq(bgp_peer_id(), agent_->fabric_vrf_name(),
1137 : prefix_addr, prefix_len, data);
1138 0 : return;
1139 : }
1140 :
1141 0 : AddressList nh;
1142 0 : nh.push_back(addr);
1143 :
1144 0 : if (table->FindResolveRoute(addr) == NULL) {
1145 0 : nh = agent_->vhost_default_gateway();
1146 : }
1147 :
1148 0 : if (prefix_addr == addr && prefix_len == 32 &&
1149 0 : table->FindResolveRoute(addr)) {
1150 : //Route is resolvable dont add any entry
1151 0 : return;
1152 : }
1153 :
1154 0 : InetUnicastRouteEntry *rt = table->FindResolveRoute(prefix_addr);
1155 0 : if (rt && rt->prefix_address() == prefix_addr && rt->prefix_length() == prefix_len) {
1156 : //Dont overwrite resolve route
1157 0 : return;
1158 : }
1159 :
1160 0 : CommunityList cl;
1161 0 : table->AddGatewayRoute(bgp_peer_id(), agent_->fabric_vrf_name(),
1162 : prefix_addr, prefix_len, nh,
1163 : vn_list, MplsTable::kInvalidExportLabel,
1164 : sg_list, tag_list, cl, true);
1165 0 : }
1166 :
1167 0 : void AgentXmppChannel::AddEvpnRoute(const std::string &vrf_name,
1168 : std::string mac_str,
1169 : const IpAddress &ip_addr,
1170 : uint32_t plen,
1171 : EnetItemType *item) {
1172 : // Verify that vrf is present and active
1173 0 : VrfKey vrf_key(vrf_name);
1174 : VrfEntry *vrf =
1175 0 : static_cast<VrfEntry *>(agent_->vrf_table()->
1176 0 : FindActiveEntry(&vrf_key));
1177 0 : if (!vrf) {
1178 0 : CONTROLLER_INFO_TRACE (Trace, GetBgpPeerName(), vrf_name,
1179 : "VRF not found, ignoring request");
1180 0 : return;
1181 : }
1182 :
1183 : // Validate VRF first
1184 : EvpnAgentRouteTable *rt_table =
1185 : static_cast<EvpnAgentRouteTable *>
1186 0 : (agent_->vrf_table()->GetEvpnRouteTable(vrf_name));
1187 0 : if (rt_table == NULL || rt_table->vrf_entry() == NULL) {
1188 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1189 : "Invalid VRF. Ignoring route");
1190 0 : return;
1191 : }
1192 :
1193 0 : boost::system::error_code ec;
1194 0 : MacAddress mac(mac_str);
1195 0 : if (mac == MacAddress::BroadcastMac()) {
1196 0 : AddMulticastEvpnRoute(vrf_name, mac, item);
1197 0 : return;
1198 : }
1199 :
1200 0 : string nexthop_addr = item->entry.next_hops.next_hop[0].address;
1201 0 : IpAddress nh_ip = IpAddress::from_string(nexthop_addr, ec);
1202 0 : uint32_t label = item->entry.next_hops.next_hop[0].label;
1203 0 : TunnelType::TypeBmap encap = agent_->controller()->GetTypeBitmap
1204 0 : (item->entry.next_hops.next_hop[0].tunnel_encapsulation_list);
1205 : // use LOW PathPreference if local preference attribute is not set
1206 0 : uint32_t preference = PathPreference::LOW;
1207 0 : if (item->entry.local_preference != 0) {
1208 0 : preference = item->entry.local_preference;
1209 : }
1210 0 : PathPreference path_preference(item->entry.sequence_number, preference,
1211 0 : false, false);
1212 :
1213 0 : TagList tag_list;
1214 0 : BuildTagList(item, tag_list);
1215 :
1216 0 : CONTROLLER_INFO_TRACE(RouteImport, GetBgpPeerName(), vrf_name,
1217 : mac.ToString(), 0, nexthop_addr, label, "");
1218 :
1219 : // Check that VxLAN message is not destined to service-chained VRF instance
1220 0 : VnEntry *si_ref_vn = vrf->si_vn_ref();
1221 :
1222 0 : if (VxlanRoutingManager::IsVxlanAvailable(agent_) &&
1223 0 : agent_->oper_db()->vxlan_routing_manager()->IsRoutingVrf(vrf) &&
1224 : si_ref_vn == NULL) {
1225 :
1226 0 : EcmpLoadBalance ecmp_load_balance;
1227 0 : VnListType vn_list;
1228 0 : vn_list.insert(item->entry.virtual_network);
1229 0 : std::vector<std::string> peer_sources;
1230 0 : for (const auto &peer_addr : item->entry.peers.peer) {
1231 0 : peer_sources.push_back(peer_addr);
1232 : }
1233 0 : agent_->oper_db()->vxlan_routing_manager()->XmppAdvertiseEvpnRoute(
1234 : ip_addr,
1235 : plen,
1236 : label, // vrf->vxlan_id(), // VxLAN ID
1237 : vrf_name,
1238 0 : RouteParameters(nh_ip,
1239 0 : MacAddress(item->entry.next_hops.next_hop[0].mac),
1240 : vn_list,
1241 0 : item->entry.security_group_list.security_group,
1242 0 : CommunityList(),
1243 : tag_list,
1244 : path_preference,
1245 : ecmp_load_balance,
1246 : sequence_number()),
1247 0 : bgp_peer_id(),
1248 : peer_sources);
1249 0 : return;
1250 0 : }
1251 :
1252 0 : if (agent_->router_id() != nh_ip.to_v4()) {
1253 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), nexthop_addr,
1254 : "add remote evpn route");
1255 0 : VnListType vn_list;
1256 0 : vn_list.insert(item->entry.virtual_network);
1257 : // for number of nexthops more than 1, carry flag ecmp suppressed
1258 : // to indicate the same to all modules, till we handle L2 ecmp
1259 : ControllerVmRoute *data =
1260 0 : ControllerVmRoute::MakeControllerVmRoute(bgp_peer_id(),
1261 0 : agent_->fabric_vrf_name(),
1262 0 : agent_->router_id(),
1263 0 : vrf_name, nh_ip.to_v4(),
1264 : encap, label,
1265 0 : MacAddress(item->entry.next_hops.next_hop[0].mac),
1266 : vn_list,
1267 0 : item->entry.security_group_list.security_group,
1268 : tag_list,
1269 : path_preference,
1270 0 : (item->entry.next_hops.next_hop.size() > 1),
1271 0 : EcmpLoadBalance(),
1272 0 : item->entry.etree_leaf);
1273 0 : rt_table->AddRemoteVmRouteReq(bgp_peer_id(), vrf_name, mac, ip_addr,
1274 0 : plen, item->entry.nlri.ethernet_tag, data);
1275 0 : return;
1276 0 : }
1277 :
1278 : // In EVPN VNF service chaining, control-node sends the route originated
1279 : // by us for the routing-vrf in the service-chain vrf as well.
1280 : // When encapsulation used is VXLAN, nexthop cannot be found from the
1281 : // message. Since EVPN Type5 local-route is not available in the
1282 : // serivce-chain vrf evpn table, set the next-hop for the local route
1283 : // (in the serice-chain's vrf) to primary-routing-vrf to have the common
1284 : // design for the EVPN Type5.
1285 :
1286 : // Checking if the vrf received is service-chain vrf that belongs to
1287 : // Vxlan routing VN (service-chaining between LRs).
1288 0 : if (si_ref_vn && (si_ref_vn->vxlan_routing_vn() == true)) {
1289 : // Vxlan routing VN (service-chaining between LRs). Local EVPN routes
1290 : // for service-chain VRF's will be allowed for the service-chain between
1291 : // Internal-VN (IVN) of the Vxlan Logiical Router (LR).
1292 :
1293 : // service-chain vrf will have si_vn_ref set to primary vrf,
1294 : // in EVPN VNF service chaining, this vrf is to routing vrf
1295 0 : VrfEntry *routing_vrf = si_ref_vn->GetVrf();
1296 0 : assert(routing_vrf != vrf);
1297 :
1298 : // service instance vrf received, adding evpn type5 route for
1299 : // that have local path
1300 0 : if (!(routing_vrf->vn() && routing_vrf->vn()->vxlan_routing_vn())) {
1301 : // primary vrf is not a routing vrf
1302 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1303 : "Not a Routing VRF. Ignoring route");
1304 0 : return;
1305 : }
1306 :
1307 : // getting the local export path from the routing vrf
1308 : EvpnAgentRouteTable *evpn_rt_table =
1309 : static_cast<EvpnAgentRouteTable *>
1310 0 : (agent_->vrf_table()->GetEvpnRouteTable(routing_vrf->GetName()));
1311 0 : if (evpn_rt_table == NULL || evpn_rt_table->vrf_entry() == NULL) {
1312 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1313 : "Invalid Routing VRF. Ignoring route");
1314 0 : return;
1315 : }
1316 :
1317 0 : EvpnRouteKey rt_key(agent_->local_vm_export_peer(),
1318 0 : routing_vrf->GetName(), MacAddress(), ip_addr,
1319 0 : plen, 0); // Ethernet tag is zero in Type5
1320 : const EvpnRouteEntry *evpn_rt = static_cast<EvpnRouteEntry *>
1321 0 : (evpn_rt_table->FindActiveEntry(&rt_key));
1322 0 : if (evpn_rt == NULL) {
1323 0 : CONTROLLER_INFO_TRACE (Trace, GetBgpPeerName(), vrf_name,
1324 : "Local EVPN route not found, ignoring request");
1325 0 : return;
1326 : }
1327 :
1328 : // Local port available, Add EVPN type5 route to service-chain vrf
1329 0 : VnListType vn_list;
1330 0 : vn_list.insert(item->entry.virtual_network);
1331 :
1332 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1333 0 : nh_req.key.reset(new VrfNHKey(routing_vrf->GetName(), false, false));
1334 0 : nh_req.data.reset(new VrfNHData(false, false, false));
1335 :
1336 : EvpnRoutingData *data = new EvpnRoutingData(nh_req,
1337 0 : item->entry.security_group_list.security_group,
1338 0 : CommunityList(),
1339 : path_preference,
1340 0 : EcmpLoadBalance(),
1341 : tag_list,
1342 : routing_vrf,
1343 0 : routing_vrf->vxlan_id(), vn_list);
1344 :
1345 : // adding local type5 route to service-chain vrf
1346 0 : rt_table->AddType5Route(bgp_peer_id(),
1347 : vrf_name,
1348 : ip_addr,
1349 : 0, // item->entry.nlri.ethernet_tag, is 0
1350 : data);
1351 :
1352 0 : return;
1353 0 : }
1354 :
1355 :
1356 : // Route originated by us and reflected back by control-node
1357 : // When encap is MPLS based, the nexthop can be found by label lookup
1358 : // When encapsulation used is VXLAN, nexthop cannot be found from message
1359 : // To have common design, get nexthop from the route already present.
1360 : // VxLAN routes destined to a Routing VRF instance are handled
1361 : // above
1362 :
1363 0 : EvpnRouteKey key(agent_->local_vm_peer(), vrf_name, mac,
1364 0 : ip_addr, plen, item->entry.nlri.ethernet_tag);
1365 : EvpnRouteEntry *route = static_cast<EvpnRouteEntry *>
1366 0 : (rt_table->FindActiveEntry(&key));
1367 0 : if (route == NULL) {
1368 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
1369 : "route not found, ignoring request");
1370 0 : return;
1371 : }
1372 :
1373 0 : AgentPath *local_path = route->FindLocalVmPortPath();
1374 0 : const NextHop *nh = local_path ? local_path->nexthop() : NULL;
1375 0 : if (nh == NULL) {
1376 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
1377 : "nexthop not found, ignoring request");
1378 0 : return;
1379 : }
1380 :
1381 : //In EVPN, if interface IP is not same as IP received in Evpn route
1382 : //then use receive NH. This is done because this received evpn ip is
1383 : //a floating IP associated with VM and it shoul be routed.
1384 0 : if (nh->GetType() == NextHop::L2_RECEIVE) {
1385 0 : rt_table->AddControllerReceiveRouteReq(bgp_peer_id(), vrf_name,
1386 : label, mac, ip_addr,
1387 0 : item->entry.nlri.ethernet_tag,
1388 0 : item->entry.virtual_network,
1389 : path_preference, sequence_number());
1390 0 : return;
1391 : }
1392 :
1393 : // We expect only INTERFACE nexthop for evpn routes
1394 0 : const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>(nh);
1395 0 : if (nh->GetType() != NextHop::INTERFACE) {
1396 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(), vrf_name,
1397 : "Invalid nexthop in evpn route");
1398 0 : return;
1399 : }
1400 :
1401 0 : SecurityGroupList sg_list = item->entry.security_group_list.security_group;
1402 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_nh->GetIfUuid(),
1403 0 : intf_nh->GetInterface()->name());
1404 0 : LocalVmRoute *local_vm_route = NULL;
1405 0 : VnListType vn_list;
1406 0 : vn_list.insert(item->entry.virtual_network);
1407 0 : EcmpLoadBalance ecmp_load_balance;
1408 :
1409 0 : if (encap == TunnelType::VxlanType()) {
1410 0 : local_vm_route =
1411 : new LocalVmRoute(intf_key,
1412 : MplsTable::kInvalidLabel,
1413 : label, false, vn_list,
1414 0 : intf_nh->GetFlags(),
1415 0 : sg_list, tag_list, CommunityList(), path_preference,
1416 0 : Ip4Address(0), ecmp_load_balance, false, false,
1417 0 : sequence_number(), item->entry.etree_leaf,
1418 0 : false);
1419 : } else {
1420 0 : local_vm_route =
1421 : new LocalVmRoute(intf_key,
1422 : label,
1423 : VxLanTable::kInvalidvxlan_id,
1424 : false, vn_list,
1425 0 : intf_nh->GetFlags(),
1426 0 : sg_list, tag_list, CommunityList(), path_preference,
1427 0 : Ip4Address(0), ecmp_load_balance, false, false,
1428 0 : sequence_number(), item->entry.etree_leaf,
1429 0 : false);
1430 : }
1431 0 : rt_table->AddLocalVmRouteReq(bgp_peer_id(), vrf_name, mac,
1432 0 : ip_addr, item->entry.nlri.ethernet_tag,
1433 : static_cast<LocalVmRoute *>(local_vm_route));
1434 0 : }
1435 :
1436 0 : void AgentXmppChannel::AddRemoteRoute(string vrf_name, IpAddress prefix_addr,
1437 : uint32_t prefix_len, ItemType *item,
1438 : const VnListType &vn_list) {
1439 0 : InetUnicastAgentRouteTable *rt_table = PrefixToRouteTable(vrf_name,
1440 : prefix_addr);
1441 :
1442 0 : if (rt_table == NULL) {
1443 0 : return;
1444 : }
1445 :
1446 0 : boost::system::error_code ec;
1447 0 : string nexthop_addr = item->entry.next_hops.next_hop[0].address;
1448 0 : uint32_t label = item->entry.next_hops.next_hop[0].label;
1449 0 : IpAddress addr = IpAddress::from_string(nexthop_addr, ec);
1450 0 : TunnelType::TypeBmap encap = agent_->controller()->GetTypeBitmap
1451 0 : (item->entry.next_hops.next_hop[0].tunnel_encapsulation_list);
1452 0 : if (ec.value() != 0) {
1453 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1454 : "Error parsing nexthop ip address");
1455 0 : return;
1456 : }
1457 :
1458 : // use LOW PathPreference if local preference attribute is not set
1459 0 : uint32_t preference = PathPreference::LOW;
1460 0 : if (item->entry.local_preference != 0) {
1461 0 : preference = item->entry.local_preference;
1462 : }
1463 0 : PathPreference path_preference(item->entry.sequence_number, preference,
1464 0 : false, false);
1465 :
1466 0 : TagList tag_list;
1467 0 : BuildTagList(item, tag_list);
1468 :
1469 0 : std::string vn_string;
1470 0 : for (VnListType::const_iterator vnit = vn_list.begin();
1471 0 : vnit != vn_list.end(); ++vnit) {
1472 0 : vn_string += *vnit + " ";
1473 : }
1474 0 : CONTROLLER_INFO_TRACE(RouteImport, GetBgpPeerName(), vrf_name,
1475 : prefix_addr.to_string(), prefix_len,
1476 : addr.to_v4().to_string(), label, vn_string);
1477 :
1478 0 : if (item->entry.next_hops.next_hop[0].label ==
1479 0 : MplsTable::kInvalidExportLabel &&
1480 0 : vrf_name == agent_->fabric_vrf_name() && prefix_addr.is_v4()) {
1481 0 : AddFabricVrfRoute(prefix_addr.to_v4(), prefix_len, addr.to_v4(),
1482 : vn_list,
1483 0 : item->entry.security_group_list.security_group,
1484 : tag_list);
1485 0 : return;
1486 : }
1487 :
1488 0 : if (vrf_name == agent_->fabric_policy_vrf_name() && prefix_addr.is_v4()) {
1489 : //Dont override the below routes in ip_fabric vrf
1490 : //default route
1491 : //vhost route
1492 : //vhost subnet routes
1493 0 : if (prefix_addr.to_v4() == Ip4Address(0) && prefix_len == 0) {
1494 0 : return;
1495 : }
1496 0 : if (prefix_addr == agent_->router_id() && prefix_len == 32) {
1497 0 : return;
1498 : }
1499 0 : if (prefix_addr == agent_->vhost_prefix() &&
1500 0 : prefix_len >= agent_->vhost_prefix_len()) {
1501 0 : return;
1502 : }
1503 : }
1504 :
1505 :
1506 : /// Handle VxLAN routes using methods in VxlanRoutingManager
1507 : /// Tunnels, Interfaces and Interface Composites are handled
1508 : /// here when route is destined to the Routing VRF instance.
1509 0 : VrfEntry* vrf = agent_->vrf_table()->FindVrfFromName(vrf_name);
1510 0 : if (VxlanRoutingManager::IsVxlanAvailable(agent_) &&
1511 0 : agent_->oper_db()->vxlan_routing_manager()->IsRoutingVrf(vrf)) {
1512 : // Inet routes are now handled inside the VxlanRoutingManager
1513 0 : return;
1514 : }
1515 :
1516 0 : if (agent_->router_id() != addr.to_v4()) {
1517 0 : EcmpLoadBalance ecmp_load_balance;
1518 0 : GetEcmpHashFieldsToUse(item, ecmp_load_balance);
1519 : ControllerVmRoute *data =
1520 0 : ControllerVmRoute::MakeControllerVmRoute(bgp_peer_id(),
1521 0 : agent_->fabric_vrf_name(), agent_->router_id(),
1522 0 : vrf_name, addr.to_v4(), encap, label,
1523 0 : MacAddress(), vn_list,
1524 0 : item->entry.security_group_list.security_group,
1525 : tag_list,
1526 : path_preference, false, ecmp_load_balance,
1527 : false);
1528 0 : rt_table->AddRemoteVmRouteReq(bgp_peer_id(), vrf_name, prefix_addr,
1529 : prefix_len, data);
1530 0 : return;
1531 0 : }
1532 :
1533 0 : bool native_encap = false;
1534 0 : if (encap & TunnelType::NativeType()) {
1535 0 : native_encap = true;
1536 : }
1537 :
1538 0 : MplsLabel *mpls = agent_->mpls_table()->FindMplsLabel(label);
1539 : // When llgr and xmpp helper mode is enabled for agent
1540 : // llgr route update from bgp peer can have stale mpls label on agent restart
1541 : // do route lookup and add route with correct label if rt update is for local vm port
1542 0 : if ((mpls == NULL) || (mpls->nexthop()
1543 0 : && mpls->nexthop()->GetType() != NextHop::VLAN && mpls->nexthop()->GetType() != NextHop::COMPOSITE)) {
1544 0 : if (agent_->oper_db()->global_system_config()->
1545 0 : gres_parameters().IsEnabled()) {
1546 0 : InetUnicastRouteEntry local_vm_route_key(NULL, prefix_addr, prefix_len, false);
1547 : InetUnicastRouteEntry *local_vm_route =
1548 : static_cast<InetUnicastRouteEntry *>
1549 0 : (rt_table->FindLPM(local_vm_route_key));
1550 0 : if (local_vm_route && local_vm_route->GetLocalVmPortPath() &&
1551 0 : local_vm_route->GetLocalVmPortPath()->nexthop() && local_vm_route->GetLocalVmPortPath()->nexthop()->GetType() == NextHop::INTERFACE) {
1552 0 : const AgentPath* local_vm_port_path = local_vm_route->GetLocalVmPortPath();
1553 0 : const NextHop *vm_nh = local_vm_port_path->nexthop();
1554 0 : const InterfaceNH *vm_intf_nh = static_cast<const InterfaceNH *>(vm_nh);
1555 0 : const Interface *intrface = vm_intf_nh->GetInterface();
1556 0 : if (intrface && intrface->type() == Interface::VM_INTERFACE) {
1557 0 : LOG(DEBUG, "Mpls lablel picked from interface nh for local vm route, received label: " << label);
1558 0 : label = local_vm_port_path->GetActiveLabel();
1559 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE,
1560 0 : vm_intf_nh->GetIfUuid(), intrface->name());
1561 : // Enqueue rt update with correct mpls label and sequence number for bgp peer path
1562 0 : EcmpLoadBalance ecmp_load_balance;
1563 0 : GetEcmpHashFieldsToUse(item, ecmp_load_balance);
1564 0 : BgpPeer *bgp_peer = bgp_peer_id();
1565 : LocalVmRoute *local_vm_rt_update =
1566 : new LocalVmRoute(intf_key, label,
1567 : VxLanTable::kInvalidvxlan_id,
1568 : false, vn_list,
1569 : InterfaceNHFlags::INET4,
1570 0 : item->entry.security_group_list.security_group,
1571 : tag_list,
1572 0 : CommunityList(),
1573 : path_preference,
1574 0 : Ip4Address(0),
1575 : ecmp_load_balance, false, false,
1576 0 : sequence_number(), false, native_encap);
1577 0 : rt_table->AddLocalVmRouteReq(bgp_peer, vrf_name,
1578 : prefix_addr, prefix_len,
1579 : static_cast<LocalVmRoute *>(local_vm_rt_update));
1580 0 : return;
1581 0 : }
1582 : }
1583 0 : }
1584 : }
1585 0 : if (mpls != NULL) {
1586 0 : const NextHop *nh = mpls->nexthop();
1587 0 : switch(nh->GetType()) {
1588 0 : case NextHop::INTERFACE: {
1589 0 : const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh);
1590 0 : const Interface *intrface = intf_nh->GetInterface();
1591 0 : if (intrface == NULL) {
1592 0 : break;
1593 : }
1594 :
1595 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE,
1596 0 : intf_nh->GetIfUuid(), intrface->name());
1597 0 : EcmpLoadBalance ecmp_load_balance;
1598 0 : GetEcmpHashFieldsToUse(item, ecmp_load_balance);
1599 0 : BgpPeer *bgp_peer = bgp_peer_id();
1600 0 : if (intrface->type() == Interface::VM_INTERFACE) {
1601 : LocalVmRoute *local_vm_route =
1602 : new LocalVmRoute(intf_key, label,
1603 : VxLanTable::kInvalidvxlan_id,
1604 : false, vn_list,
1605 : InterfaceNHFlags::INET4,
1606 0 : item->entry.security_group_list.security_group,
1607 : tag_list,
1608 0 : CommunityList(),
1609 : path_preference,
1610 0 : Ip4Address(0),
1611 : ecmp_load_balance, false, false,
1612 0 : sequence_number(), false, native_encap);
1613 0 : rt_table->AddLocalVmRouteReq(bgp_peer, vrf_name,
1614 : prefix_addr, prefix_len,
1615 : static_cast<LocalVmRoute *>(local_vm_route));
1616 0 : } else if (intrface->type() == Interface::INET) {
1617 :
1618 0 : if (!prefix_addr.is_v4()) {
1619 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1620 : "MPLS label inet interface type not supported for non IPv4");
1621 0 : return;
1622 : }
1623 0 : InetInterfaceKey intf_key(intrface->name());
1624 : InetInterfaceRoute *inet_interface_route =
1625 : new InetInterfaceRoute(intf_key, label,
1626 0 : TunnelType::MplsType(),
1627 0 : vn_list, sequence_number());
1628 :
1629 0 : rt_table->AddInetInterfaceRouteReq(bgp_peer, vrf_name,
1630 0 : prefix_addr.to_v4(), prefix_len,
1631 : inet_interface_route);
1632 0 : } else {
1633 : // Unsupported scenario
1634 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1635 : "MPLS label points to invalid interface type");
1636 0 : break;
1637 : }
1638 :
1639 0 : break;
1640 0 : }
1641 :
1642 0 : case NextHop::VLAN: {
1643 0 : const VlanNH *vlan_nh = static_cast<const VlanNH *>(nh);
1644 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE,
1645 0 : vlan_nh->GetIfUuid(), "");
1646 0 : BgpPeer *bgp_peer = bgp_peer_id();
1647 : VlanNhRoute *data =
1648 0 : new VlanNhRoute(intf_key, vlan_nh->GetVlanTag(),
1649 : label, vn_list,
1650 0 : item->entry.security_group_list.security_group,
1651 : tag_list,
1652 0 : path_preference, sequence_number());
1653 0 : rt_table->AddVlanNHRouteReq(bgp_peer, vrf_name, prefix_addr,
1654 : prefix_len, data);
1655 0 : break;
1656 0 : }
1657 0 : case NextHop::COMPOSITE: {
1658 0 : AddInetEcmpRoute(vrf_name, prefix_addr, prefix_len, item, vn_list);
1659 0 : break;
1660 : }
1661 0 : case NextHop::VRF: {
1662 : //In case of gateway interface with example subnet
1663 : //1.1.1.0/24 may be reachable on this gateway inteface,
1664 : //Path added by local vm peer would point to
1665 : //resolve NH, so that if any path hits this route, ARP resolution
1666 : //can begin, and the label exported for this route would point to
1667 : //table nexthop.
1668 : //Hence existing logic of picking up nexthop from mpls label to
1669 : //nexthop, will not work. We have added a special path where we
1670 : //pick nexthop from local vm path, instead of BGP
1671 0 : if (!prefix_addr.is_v4()) {
1672 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1673 : "VRF nexthop is not supported for non IPv4");
1674 0 : return;
1675 : }
1676 0 : BgpPeer *bgp_peer = bgp_peer_id();
1677 : ClonedLocalPath *data =
1678 : new ClonedLocalPath(label, vn_list,
1679 0 : item->entry.security_group_list.security_group,
1680 : tag_list,
1681 0 : sequence_number());
1682 0 : rt_table->AddClonedLocalPathReq(bgp_peer, vrf_name,
1683 0 : prefix_addr.to_v4(),
1684 : prefix_len, data);
1685 0 : break;
1686 : }
1687 :
1688 0 : default:
1689 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1690 : "MPLS label points to invalid NH");
1691 : }
1692 : }
1693 0 : }
1694 0 : void AgentXmppChannel::AddRemoteMplsRoute(string vrf_name, IpAddress prefix_addr,
1695 : uint32_t prefix_len, ItemType *item,
1696 : const VnListType &vn_list) {
1697 0 : InetUnicastAgentRouteTable *rt_table = PrefixToRouteMplsTable(vrf_name,
1698 : prefix_addr);
1699 :
1700 0 : if (rt_table == NULL) {
1701 0 : return;
1702 : }
1703 0 : if (prefix_addr == agent_->router_id() && prefix_len == 32) {
1704 0 : rt_table->AddVhostMplsRoute(prefix_addr, bgp_peer_id());
1705 0 : return;
1706 : }
1707 :
1708 0 : boost::system::error_code ec;
1709 0 : string nexthop_addr = item->entry.next_hops.next_hop[0].address;
1710 0 : uint32_t label = item->entry.next_hops.next_hop[0].label;
1711 0 : IpAddress addr = IpAddress::from_string(nexthop_addr, ec);
1712 :
1713 0 : if (ec.value() != 0) {
1714 0 : CONTROLLER_TRACE(Trace, GetBgpPeerName(), vrf_name,
1715 : "Error parsing nexthop ip address");
1716 0 : return;
1717 : }
1718 :
1719 : // use LOW PathPreference if local preference attribute is not set
1720 0 : uint32_t preference = PathPreference::LOW;
1721 0 : if (item->entry.local_preference != 0) {
1722 0 : preference = item->entry.local_preference;
1723 : }
1724 0 : PathPreference path_preference(item->entry.sequence_number, preference,
1725 0 : false, false);
1726 :
1727 0 : TagList tag_list;
1728 0 : BuildTagList(item, tag_list);
1729 :
1730 0 : std::string vn_string;
1731 0 : for (VnListType::const_iterator vnit = vn_list.begin();
1732 0 : vnit != vn_list.end(); ++vnit) {
1733 0 : vn_string += *vnit + " ";
1734 : }
1735 0 : CONTROLLER_INFO_TRACE(RouteImport, GetBgpPeerName(), vrf_name,
1736 : prefix_addr.to_string(), prefix_len,
1737 : addr.to_v4().to_string(), label, vn_string);
1738 :
1739 0 : CommunityList cl;
1740 :
1741 0 : EcmpLoadBalance ecmp_load_balance;
1742 : ControllerMplsRoute *data =
1743 0 : ControllerMplsRoute::MakeControllerMplsRoute(bgp_peer_id(),
1744 0 : agent_->fabric_vrf_name(), agent_->router_id(),
1745 0 : vrf_name, addr.to_v4(),
1746 : TunnelType::MplsoMplsType(), label,
1747 0 : MacAddress(), vn_list,
1748 0 : item->entry.security_group_list.security_group,
1749 : tag_list,
1750 : path_preference, false, ecmp_load_balance,
1751 : false);
1752 0 : rt_table->AddMplsRouteReq(bgp_peer_id(), vrf_name, prefix_addr,
1753 : prefix_len, data);
1754 0 : return;
1755 0 : }
1756 :
1757 : template <typename TYPE>
1758 0 : bool AgentXmppChannel::IsEcmp(const TYPE &nexthops) {
1759 0 : if (nexthops.size() == 0)
1760 0 : return false;
1761 :
1762 0 : std::string address = nexthops[0].address;
1763 0 : uint32_t label = nexthops[0].label;
1764 0 : for (uint32_t index = 1; index < nexthops.size(); index++) {
1765 0 : if (nexthops[index].address != address ||
1766 0 : (uint32_t)nexthops[index].label != label) {
1767 0 : return true;
1768 : }
1769 : }
1770 :
1771 0 : return false;
1772 0 : }
1773 :
1774 : template <typename TYPE>
1775 0 : void AgentXmppChannel::GetVnList(const TYPE &nexthops, VnListType *vn_list) {
1776 0 : for (uint32_t index = 0; index < nexthops.size(); index++) {
1777 0 : vn_list->insert(nexthops[index].virtual_network);
1778 : }
1779 0 : }
1780 :
1781 0 : void AgentXmppChannel::AddRoute(string vrf_name, IpAddress prefix_addr,
1782 : uint32_t prefix_len, ItemType *item) {
1783 0 : if ((item->entry.next_hops.next_hop[0].label ==
1784 0 : MplsTable::kInvalidExportLabel) &&
1785 0 : (vrf_name != agent_->fabric_vrf_name())) {
1786 0 : return;
1787 : }
1788 :
1789 0 : VnListType vn_list;
1790 0 : GetVnList(item->entry.next_hops.next_hop, &vn_list);
1791 0 : if (IsEcmp(item->entry.next_hops.next_hop)) {
1792 0 : AddInetEcmpRoute(vrf_name, prefix_addr, prefix_len, item, vn_list);
1793 : } else {
1794 0 : AddRemoteRoute(vrf_name, prefix_addr, prefix_len, item, vn_list);
1795 : }
1796 0 : }
1797 :
1798 0 : void AgentXmppChannel::AddInetMplsEcmpRoute(string vrf_name, IpAddress prefix_addr,
1799 : uint32_t prefix_len, ItemType *item,
1800 : const VnListType &vn_list) {
1801 :
1802 0 : InetUnicastAgentRouteTable *rt_table = PrefixToRouteMplsTable(vrf_name,
1803 : prefix_addr);
1804 :
1805 0 : if (rt_table == NULL) {
1806 0 : return;
1807 : }
1808 :
1809 0 : std::stringstream str;
1810 0 : str << prefix_addr.to_string();
1811 0 : str << "/";
1812 0 : str << prefix_len;
1813 :
1814 0 : EcmpLoadBalance ecmp_load_balance;
1815 0 : GetEcmpHashFieldsToUse(item, ecmp_load_balance);
1816 0 : ControllerEcmpRoute *data = BuildEcmpData(item, vn_list, ecmp_load_balance,
1817 0 : rt_table, str.str());
1818 : //ECMP create component NH
1819 0 : rt_table->AddMplsRouteReq(bgp_peer_id(), vrf_name,
1820 : prefix_addr, prefix_len, data);
1821 0 : }
1822 0 : void AgentXmppChannel::AddMplsRoute(string vrf_name, IpAddress prefix_addr,
1823 : uint32_t prefix_len, ItemType *item) {
1824 :
1825 0 : VnListType vn_list;
1826 0 : GetVnList(item->entry.next_hops.next_hop, &vn_list);
1827 0 : if (IsEcmp(item->entry.next_hops.next_hop)) {
1828 0 : AddInetMplsEcmpRoute(vrf_name, prefix_addr, prefix_len, item, vn_list);
1829 : } else {
1830 0 : AddRemoteMplsRoute(vrf_name, prefix_addr, prefix_len, item, vn_list);
1831 : }
1832 0 : }
1833 0 : void AgentXmppChannel::ReceiveUpdate(const XmppStanza::XmppMessage *msg) {
1834 0 : if (msg && msg->type == XmppStanza::MESSAGE_STANZA) {
1835 0 : unique_ptr<XmlBase> impl(XmppXmlImplFactory::Instance()->GetXmlImpl());
1836 0 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
1837 0 : XmlPugi *msg_pugi = reinterpret_cast<XmlPugi *>(msg->dom.get());
1838 0 : pugi->LoadXmlDoc(msg_pugi->doc());
1839 : boost::shared_ptr<ControllerXmppData> data(new ControllerXmppData(xmps::BGP,
1840 : xmps::UNKNOWN,
1841 0 : xs_idx_,
1842 0 : std::move(impl),
1843 0 : true));
1844 0 : agent_->controller()->Enqueue(data);
1845 0 : }
1846 0 : }
1847 :
1848 0 : void AgentXmppChannel::ReceiveBgpMessage(std::unique_ptr<XmlBase> impl) {
1849 0 : if (agent_->stats())
1850 0 : agent_->stats()->incr_xmpp_in_msgs(xs_idx_);
1851 :
1852 0 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
1853 0 : pugi::xml_node node = pugi->FindNode("items");
1854 0 : if (node == 0) {
1855 0 : end_of_rib_rx_timer()->Cancel();
1856 0 : EndOfRibRx();
1857 0 : return;
1858 : }
1859 :
1860 0 : pugi->ReadNode("items"); //sets the context
1861 0 : std::string nodename = pugi->ReadAttrib("node");
1862 :
1863 0 : const char *af = NULL, *safi = NULL, *vrf_name;
1864 0 : char *str = const_cast<char *>(nodename.c_str());
1865 : char *saveptr;
1866 0 : af = strtok_r(str, "/", &saveptr);
1867 0 : safi = strtok_r(NULL, "/", &saveptr);
1868 0 : vrf_name = saveptr;
1869 :
1870 : // No BGP peer
1871 0 : if (bgp_peer_id() == NULL) {
1872 0 : CONTROLLER_TRACE (Trace, GetBgpPeerName(), vrf_name,
1873 : "BGP peer not present, agentxmppchannel is inactive");
1874 0 : return;
1875 : }
1876 :
1877 : // If EndOfRib marker is received, process it accordingly.
1878 0 : if (nodename == XmppInit::kEndOfRibMarker) {
1879 0 : return;
1880 : }
1881 :
1882 0 : if (atoi(af) == BgpAf::IPv4 && atoi(safi) == BgpAf::MVpn) {
1883 0 : ReceiveMvpnUpdate(pugi);
1884 0 : return;
1885 : }
1886 0 : if (atoi(af) == BgpAf::IPv4 && atoi(safi) == BgpAf::Mcast) {
1887 0 : ReceiveMulticastUpdate(pugi);
1888 0 : return;
1889 : }
1890 0 : if (atoi(af) == BgpAf::L2Vpn && atoi(safi) == BgpAf::Enet) {
1891 0 : ReceiveEvpnUpdate(pugi);
1892 0 : return;
1893 : }
1894 0 : if(atoi(af) == BgpAf::IPv4 && atoi(safi) == BgpAf::Mpls) {
1895 0 : ReceiveInet4MplsUpdate(pugi);
1896 0 : return;
1897 : }
1898 :
1899 0 : if (atoi(safi) == BgpAf::Unicast) {
1900 0 : ReceiveV4V6Update(pugi);
1901 0 : return;
1902 : }
1903 0 : CONTROLLER_TRACE (Trace, GetBgpPeerName(), vrf_name,
1904 : "Error Route update, Unknown Address Family or safi");
1905 0 : }
1906 :
1907 0 : void AgentXmppChannel::ReceiveInternal(const XmppStanza::XmppMessage *msg) {
1908 0 : ReceiveUpdate(msg);
1909 0 : }
1910 :
1911 0 : std::string AgentXmppChannel::ToString() const {
1912 0 : return channel_str_;
1913 : }
1914 :
1915 0 : void AgentXmppChannel::WriteReadyCb(const boost::system::error_code &ec) {
1916 0 : }
1917 :
1918 0 : void AgentXmppChannel::CleanConfigStale(AgentXmppChannel *agent_xmpp_channel) {
1919 0 : assert(agent_xmpp_channel);
1920 0 : const Agent *agent = agent_xmpp_channel->agent();
1921 :
1922 : //Start a timer to flush off all old configs
1923 0 : if (agent->ifmap_xmpp_channel(agent_xmpp_channel->GetXmppServerIdx())) {
1924 0 : agent->ifmap_xmpp_channel(agent_xmpp_channel->GetXmppServerIdx())->
1925 0 : StartConfigCleanupTimer();
1926 : }
1927 0 : }
1928 :
1929 3130 : bool AgentXmppChannel::IsXmppChannelActive(const Agent *agent,
1930 : AgentXmppChannel *peer) {
1931 3130 : bool xmpp_channel_found = false;
1932 : //Verify if channel registered is stiil active or has been deleted
1933 : //after bgp peer was down. This is checked under existing agent
1934 : //xmpp channels in agent.
1935 5531 : for (uint8_t idx = 0; idx < MAX_XMPP_SERVERS; idx++) {
1936 5531 : if (agent->controller_xmpp_channel(idx) == peer) {
1937 3130 : xmpp_channel_found = true;
1938 3130 : break;
1939 : }
1940 : }
1941 3130 : return xmpp_channel_found;
1942 : }
1943 :
1944 : /*
1945 : * AgentXmppChannel is active when:
1946 : * 1) bgp peer is not null(bgp_peer_id)
1947 : * 2) xmpp channel is in READY state
1948 : * 3) Valid XMPP channel
1949 : */
1950 2080 : bool AgentXmppChannel::IsBgpPeerActive(const Agent *agent,
1951 : AgentXmppChannel *peer) {
1952 2080 : if (!IsXmppChannelActive(agent, peer))
1953 0 : return false;
1954 :
1955 : //Reach here if channel is present. Now check for BGP peer
1956 : //as channel may have come up and created another BGP peer.
1957 : //Also check for the state of channel.
1958 4160 : if (peer && peer->GetXmppChannel() && peer->bgp_peer_id() &&
1959 2080 : (peer->GetXmppChannel()->GetPeerState() == xmps::READY)) {
1960 1892 : return true;
1961 : }
1962 188 : return false;
1963 : }
1964 :
1965 : /*
1966 : * New peer is config peer. Increment the global config sequence number,
1967 : * Notify for new config peer, set it in agent xmppcfg
1968 : */
1969 19 : bool AgentXmppChannel::SetConfigPeer(AgentXmppChannel *peer) {
1970 19 : Agent *agent = peer->agent();
1971 19 : if (AgentXmppChannel::ControllerSendCfgSubscribe(peer)) {
1972 19 : agent->set_ifmap_active_xmpp_server(peer->GetXmppServer(),
1973 19 : peer->GetXmppServerIdx());
1974 : //Generate a new sequence number for the configuration
1975 19 : AgentIfMapXmppChannel::NewSeqNumber();
1976 19 : agent->ifmap_parser()->reset_statistics();
1977 19 : agent->controller()->agent_ifmap_vm_export()->NotifyAll(peer);
1978 19 : if (agent->ifmap_xmpp_channel(peer->GetXmppServerIdx())) {
1979 0 : agent->ifmap_xmpp_channel(peer->GetXmppServerIdx())->
1980 0 : end_of_config_timer()->Start(peer);
1981 : }
1982 19 : return true;
1983 : }
1984 0 : return false;
1985 : }
1986 :
1987 : /*
1988 : * New multicast peer found - either first one or a lower one got selected.
1989 : * Increment peer identifier so that new peer can update using incremented seq
1990 : * number and multicast entries which didnt get updated can be removed via stale
1991 : * cleanup.
1992 : */
1993 38 : void AgentXmppChannel::SetMulticastPeer(AgentXmppChannel *old_peer,
1994 : AgentXmppChannel *new_peer) {
1995 38 : old_peer->agent()->controller()->increment_multicast_sequence_number();
1996 38 : old_peer->agent()->set_cn_mcast_builder(new_peer);
1997 38 : }
1998 :
1999 0 : void AgentXmppChannel::XmppClientChannelEvent(AgentXmppChannel *peer,
2000 : xmps::PeerState state) {
2001 0 : std::unique_ptr<XmlBase> dummy_dom;
2002 : boost::shared_ptr<ControllerXmppData> data(new ControllerXmppData(xmps::BGP,
2003 : state,
2004 0 : peer->GetXmppServerIdx(),
2005 0 : std::move(dummy_dom),
2006 0 : false));
2007 0 : peer->agent()->controller()->Enqueue(data);
2008 0 : }
2009 :
2010 937 : uint64_t AgentXmppChannel::sequence_number() const {
2011 937 : return (static_cast<BgpPeer *>(bgp_peer_id_.get()))->sequence_number();
2012 : }
2013 :
2014 : /*
2015 : * AgentXmppChanel state - READY
2016 : *
2017 : * - Bump up the sequence number to identify updates of routes on this channel
2018 : * after connection is in ready state and later at the end of EOR TX timer,
2019 : * flush out all the stales(which never got updated after READY state is seen).
2020 : * - Config server selection is done if no config server is present. This can
2021 : * happen when this is the first active channel or is becoming active after
2022 : * other channel has become inactive.
2023 : * - Multicast builder - Same explanation as of config server. If there is no
2024 : * mcast builder, take the ownership.
2025 : * - Notify all routes only if this channel is not becoming config peer. Reason
2026 : * for same is that config peer selection, runs end of config timer which in
2027 : * turn runs route walker to notify. So notification is deferred till end of
2028 : * config is computed. For more explanation on timer check controller_timer.cc
2029 : * - End of Rib Rx timer is started to handle the fallback when EOR from control
2030 : * node is not seen within fallback time.
2031 : */
2032 19 : void AgentXmppChannel::Ready() {
2033 19 : agent_->set_controller_xmpp_channel_setup_time(UTCTimestampUsec(), xs_idx_);
2034 19 : CONTROLLER_TRACE(Session, GetXmppServer(), "READY",
2035 : "NULL", "BGP peer ready.");
2036 : //Increment sequence number, all new updates should use this sequence
2037 : //number.
2038 19 : bgp_peer_id()->incr_sequence_number();
2039 :
2040 : //Stop LLGR stale timer
2041 19 : llgr_stale_timer()->Cancel();
2042 :
2043 : // Switch-over Config Control-node
2044 19 : if (agent_->ifmap_active_xmpp_server().empty()) {
2045 19 : AgentXmppChannel::SetConfigPeer(this);
2046 19 : CONTROLLER_TRACE(Session, GetXmppServer(), "READY",
2047 : "NULL", "BGP peer set as config server.");
2048 : } else {
2049 : //Notify all routes to channel, if channel is not selected as config.
2050 : //Config selection results in end of config computation which internally
2051 : //will start the route notification. So notify is delayed till end of
2052 : //config is computed.
2053 0 : StartEndOfRibTxWalker();
2054 : }
2055 :
2056 19 : AgentXmppChannel *agent_mcast_builder = agent_->mulitcast_builder();
2057 : //Mcast builder was not set it, use the new peer
2058 19 : if (agent_mcast_builder == NULL) {
2059 : //Since this is first time mcast peer so old and new peer are same
2060 19 : AgentXmppChannel::SetMulticastPeer(this, this);
2061 19 : CONTROLLER_TRACE(Session, GetXmppServer(), "READY",
2062 : agent_->mulitcast_builder()->
2063 : GetBgpPeerName(), "Peer elected Mcast builder");
2064 : }
2065 :
2066 : //Timer to delete stale paths in case EOR is not seen fro CN.
2067 : //If EOR is seen it will cancel this timer.
2068 19 : end_of_rib_rx_timer()->Start(this);
2069 :
2070 19 : if (agent_->stats())
2071 19 : agent_->stats()->incr_xmpp_reconnects(GetXmppServerIdx());
2072 19 : }
2073 :
2074 : /*
2075 : * AgentXmppChanel state - NotREADY
2076 : *
2077 : * - Firstly stop all timers and walkers. No stale cleanup is to be
2078 : * done. Caveat: if channel is not config channel then it should not stop any
2079 : * config timers/walker.
2080 : * By default end of rib rx timer is stopped and delete of stale walker is
2081 : * stopped.
2082 : * If channel is config server then stop end of config and config
2083 : * cleanup(PeerIsNotConfig).
2084 : * If channel is config server and there is another active config server
2085 : * select the other channel as config and stop any timer from this channel.
2086 : * - If its a mcast builder, try finding other if any.
2087 : */
2088 21 : void AgentXmppChannel::NotReady() {
2089 21 : CONTROLLER_TRACE(Session, GetXmppServer(), "NOT_READY",
2090 : "NULL", "BGP peer decommissioned for xmpp channel.");
2091 : //Stop stale cleanup if its running
2092 21 : bgp_peer_id()->StopDeleteStale();
2093 : //Also stop notify as there is no CN for this peer.
2094 21 : StopEndOfRibTxWalker();
2095 : //Also stop end-of-rib rx fallback and retain.
2096 21 : end_of_rib_rx_timer()->Cancel();
2097 : //State llgr stale timer to clean stales if CN has issues with getting ready.
2098 21 : llgr_stale_timer()->Start(this);
2099 :
2100 : // evaluate peer change for config and multicast
2101 : AgentXmppChannel *agent_mcast_builder =
2102 21 : agent_->mulitcast_builder();
2103 21 : bool peer_is_config_server = (agent_->
2104 21 : ifmap_active_xmpp_server().compare(GetXmppServer()) == 0);
2105 21 : bool peer_is_agent_mcast_builder = (agent_mcast_builder == this);
2106 :
2107 : // Switch-over Config Control-node
2108 21 : if (peer_is_config_server) {
2109 : //stop all config clean timer, retain old config,
2110 : //if there is a new config selected, it will take care of flushing
2111 : //stale.
2112 19 : PeerIsNotConfig();
2113 : //send cfg subscribe to other peer if exists
2114 19 : uint8_t idx = ((agent_->ifmap_active_xmpp_server_index() == 0) ? 1: 0);
2115 19 : agent_->reset_ifmap_active_xmpp_server();
2116 19 : AgentXmppChannel *new_cfg_peer = agent_->controller_xmpp_channel(idx);
2117 :
2118 19 : if (AgentXmppChannel::IsBgpPeerActive(agent_, new_cfg_peer) &&
2119 0 : AgentXmppChannel::SetConfigPeer(new_cfg_peer)) {
2120 0 : CONTROLLER_TRACE(Session, new_cfg_peer->GetXmppServer(),
2121 : "NOT_READY", "NULL", "BGP peer selected as"
2122 : "config peer on decommission of old config "
2123 : "peer.");
2124 : }
2125 : }
2126 :
2127 : // Switch-over Multicast Tree Builder
2128 21 : if (peer_is_agent_mcast_builder) {
2129 19 : uint8_t idx = ((agent_mcast_builder->GetXmppServerIdx() == 0)
2130 19 : ? 1: 0);
2131 : AgentXmppChannel *new_mcast_builder =
2132 19 : agent_->controller_xmpp_channel(idx);
2133 :
2134 : // Selection of new peer as mcast builder is dependant on following
2135 : // criterias:
2136 : // 1) Channel is present (new_mcast_builder is not null)
2137 : // 2) Channel is in READY state
2138 : // 3) BGP peer is commissioned for channel
2139 : bool evaluate_new_mcast_builder =
2140 19 : AgentXmppChannel::IsBgpPeerActive(agent_, new_mcast_builder);
2141 :
2142 19 : if (!evaluate_new_mcast_builder) {
2143 19 : new_mcast_builder = NULL;
2144 19 : CONTROLLER_TRACE(Session, GetXmppServer(), "NOT_READY",
2145 : "NULL", "No elected Multicast Tree Builder");
2146 : }
2147 19 : AgentXmppChannel::SetMulticastPeer(this, new_mcast_builder);
2148 19 : if (evaluate_new_mcast_builder) {
2149 : //Advertise subnet and all broadcast routes to
2150 : //the new multicast tree builder
2151 0 : new_mcast_builder->StartEndOfRibTxWalker();
2152 0 : CONTROLLER_TRACE(Session, GetXmppServer(), "NOT_READY",
2153 : agent_->mulitcast_builder()->
2154 : GetBgpPeerName(),
2155 : "Peer elected Multicast Tree Builder");
2156 : }
2157 : }
2158 21 : }
2159 :
2160 : /*
2161 : * AgentXmppChannel state TimedOut
2162 : *
2163 : * Injects NotReady event for this channel.
2164 : *
2165 : * If there are more than two channels available in config, then try picking
2166 : * other channel to replace this timed out channel. And push this channel at the
2167 : * end of the channel list so that it is picked only in worst case.
2168 : * Also this channel gets moved to timed out list where it waits for any other
2169 : * channel to take up the slot(xs_idx_) and is stable(Done to retain
2170 : * config/routes till new channel is stable).
2171 : *
2172 : * If there are only two channels configured, no action to be taken.
2173 : */
2174 0 : void AgentXmppChannel::TimedOut() {
2175 0 : CONTROLLER_TRACE(Session, GetXmppServer(), "TIMEDOUT",
2176 : "NULL", "Connection to Xmpp Server, Timed out");
2177 : {
2178 0 : bool update_list = false;
2179 0 : std::vector<string>::iterator iter = agent_->GetControllerlist().begin();
2180 0 : std::vector<string>::iterator end = agent_->GetControllerlist().end();
2181 0 : for (; iter != end; iter++) {
2182 0 : std::vector<string> server;
2183 0 : boost::split(server, *iter, boost::is_any_of(":"));
2184 0 : if (GetXmppServer().compare(server[0]) == 0) {
2185 : // Add the TIMEDOUT server to the end.
2186 0 : if (iter+1 == end) break;
2187 0 : std::rotate(iter, iter+1, end);
2188 0 : update_list = true;
2189 0 : break;
2190 : }
2191 0 : }
2192 0 : if (update_list) {
2193 0 : agent_->controller()->ReConnectXmppServer();
2194 : }
2195 : }
2196 0 : }
2197 :
2198 40 : void AgentXmppChannel::HandleAgentXmppClientChannelEvent(AgentXmppChannel *peer,
2199 : xmps::PeerState state) {
2200 40 : peer->UpdateConnectionInfo(state);
2201 40 : if (state == xmps::READY) {
2202 19 : peer->Ready();
2203 21 : } else if (state == xmps::NOT_READY) {
2204 21 : peer->NotReady();
2205 0 : } else if (state == xmps::TIMEDOUT) {
2206 0 : peer->TimedOut();
2207 : }
2208 40 : }
2209 :
2210 245 : EndOfRibTxTimer *AgentXmppChannel::end_of_rib_tx_timer() {
2211 245 : return end_of_rib_tx_timer_.get();
2212 : }
2213 :
2214 80 : EndOfRibRxTimer *AgentXmppChannel::end_of_rib_rx_timer() {
2215 80 : return end_of_rib_rx_timer_.get();
2216 : }
2217 :
2218 40 : LlgrStaleTimer *AgentXmppChannel::llgr_stale_timer() {
2219 40 : return llgr_stale_timer_.get();
2220 : }
2221 :
2222 19 : void AgentXmppChannel::PeerIsNotConfig() {
2223 19 : if (agent_->ifmap_xmpp_channel(xs_idx_)) {
2224 0 : agent_->ifmap_xmpp_channel(xs_idx_)->end_of_config_timer()->Cancel();
2225 0 : agent_->ifmap_xmpp_channel(xs_idx_)->config_cleanup_timer()->Cancel();
2226 : }
2227 19 : }
2228 :
2229 0 : bool AgentXmppChannel::ControllerSendVmCfgSubscribe(AgentXmppChannel *peer,
2230 : const boost::uuids::uuid &vm_id,
2231 : bool subscribe) {
2232 0 : string repr;
2233 0 : boost::scoped_ptr<XmlWriter> xml_writer(new XmlWriter(&repr));
2234 :
2235 0 : if (!peer) {
2236 0 : return false;
2237 : }
2238 :
2239 : //Build the DOM tree
2240 0 : unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
2241 0 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
2242 :
2243 0 : pugi->AddNode("iq", "");
2244 0 : pugi->AddAttribute("type", "set");
2245 0 : pugi->AddAttribute("from", peer->channel_->FromString());
2246 0 : std::string to(peer->channel_->ToString());
2247 0 : to += "/";
2248 0 : to += XmppInit::kConfigPeer;
2249 0 : pugi->AddAttribute("to", to);
2250 :
2251 0 : pugi->AddChildNode("pubsub", "");
2252 0 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
2253 0 : if (subscribe == true) {
2254 0 : pugi->AddChildNode("subscribe", "");
2255 : } else {
2256 0 : pugi->AddChildNode("unsubscribe", "");
2257 : }
2258 0 : std::string vm("virtual-machine:");
2259 0 : stringstream vmid;
2260 0 : vmid << vm_id;
2261 0 : vm += vmid.str();
2262 0 : pugi->AddAttribute("node", vm);
2263 :
2264 0 : pugi->doc().print(*xml_writer, "", pugi::format_default,
2265 : pugi::encoding_utf8);
2266 0 : CONTROLLER_TX_CONFIG_TRACE(Trace, peer->GetXmppServerIdx(),
2267 : peer->GetBgpPeerName(), "", repr);
2268 : // send data
2269 0 : if (peer->SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()),
2270 0 : repr.length()) == false) {
2271 0 : CONTROLLER_TRACE(Session, peer->GetXmppServer(),
2272 : "VM subscribe Send Update deferred", vm, "");
2273 : }
2274 :
2275 0 : return true;
2276 0 : }
2277 :
2278 19 : bool AgentXmppChannel::ControllerSendCfgSubscribe(AgentXmppChannel *peer) {
2279 :
2280 19 : string repr;
2281 19 : boost::scoped_ptr<XmlWriter> xml_writer(new XmlWriter(&repr));
2282 :
2283 19 : if (!peer) {
2284 0 : return false;
2285 : }
2286 :
2287 : //Build the DOM tree
2288 19 : unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
2289 19 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
2290 :
2291 19 : pugi->AddNode("iq", "");
2292 19 : pugi->AddAttribute("type", "set");
2293 19 : pugi->AddAttribute("from", peer->channel_->FromString());
2294 19 : std::string to(peer->channel_->ToString());
2295 19 : to += "/";
2296 19 : to += XmppInit::kConfigPeer;
2297 19 : pugi->AddAttribute("to", to);
2298 :
2299 19 : pugi->AddChildNode("pubsub", "");
2300 19 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
2301 19 : pugi->AddChildNode("subscribe", "");
2302 19 : string node("virtual-router:");
2303 19 : node = node + XmppInit::kFqnPrependAgentNodeJID + peer->channel_->FromString();
2304 19 : pugi->AddAttribute("node", node);
2305 :
2306 19 : pugi->doc().print(*xml_writer, "", pugi::format_default,
2307 : pugi::encoding_utf8);
2308 19 : CONTROLLER_TX_CONFIG_TRACE(Trace, peer->GetXmppServerIdx(),
2309 : peer->GetBgpPeerName(), "", repr);
2310 : // send data
2311 19 : if (peer->SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()),
2312 19 : repr.length()) == false) {
2313 0 : CONTROLLER_TRACE(Session, peer->GetXmppServer(),
2314 : "Config subscribe Send Update deferred", node, "");
2315 : }
2316 19 : return true;
2317 19 : }
2318 :
2319 32 : bool AgentXmppChannel::ControllerSendSubscribe(AgentXmppChannel *peer,
2320 : VrfEntry *vrf,
2321 : bool subscribe) {
2322 : static int req_id = 0;
2323 32 : string repr;
2324 32 : boost::scoped_ptr<XmlWriter> xml_writer(new XmlWriter(&repr));
2325 :
2326 32 : if (!peer) {
2327 0 : return false;
2328 : }
2329 32 : CONTROLLER_INFO_TRACE(Trace, peer->GetBgpPeerName(), vrf->GetName(),
2330 : subscribe ? "Subscribe" : "Unsubscribe");
2331 : //Build the DOM tree
2332 32 : unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
2333 32 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
2334 :
2335 32 : pugi->AddNode("iq", "");
2336 32 : pugi->AddAttribute("type", "set");
2337 32 : pugi->AddAttribute("from", peer->channel_->FromString());
2338 32 : std::string to(peer->channel_->ToString());
2339 32 : to += "/";
2340 32 : to += XmppInit::kBgpPeer;
2341 32 : pugi->AddAttribute("to", to);
2342 :
2343 32 : stringstream request_id;
2344 32 : request_id << "subscribe" << req_id++;
2345 32 : pugi->AddAttribute("id", request_id.str());
2346 32 : pugi->AddChildNode("pubsub", "");
2347 32 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
2348 32 : if (subscribe) {
2349 16 : pugi->AddChildNode("subscribe", "");
2350 : } else {
2351 16 : pugi->AddChildNode("unsubscribe", "");
2352 : }
2353 32 : pugi->AddAttribute("node", vrf->GetName());
2354 32 : pugi->AddChildNode("options", "" );
2355 32 : stringstream vrf_id;
2356 32 : vrf_id << vrf->rd();
2357 32 : pugi->AddChildNode("instance-id", vrf_id.str());
2358 :
2359 32 : pugi->doc().print(*xml_writer, "", pugi::format_default,
2360 : pugi::encoding_utf8);
2361 : // send data
2362 32 : if (peer->SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()),
2363 32 : repr.length()) == false) {
2364 0 : CONTROLLER_TRACE(Session, peer->GetXmppServer(),
2365 : "Vrf subscribe Send Update deferred", vrf_id.str(), "");
2366 : }
2367 32 : return true;
2368 32 : }
2369 :
2370 58 : void PopulateEcmpHashFieldsToUse(ItemType &item,
2371 : const EcmpLoadBalance &ecmp_load_balance) {
2372 58 : item.entry.load_balance.load_balance_decision = LoadBalanceDecision;
2373 :
2374 58 : if (ecmp_load_balance.AllSet())
2375 58 : return;
2376 :
2377 0 : ecmp_load_balance.GetStringVector(
2378 0 : item.entry.load_balance.load_balance_fields.load_balance_field_list);
2379 : }
2380 :
2381 58 : bool AgentXmppChannel::ControllerSendV4V6UnicastRouteCommon(AgentRoute *route,
2382 : const VnListType &vn_list,
2383 : const SecurityGroupList *sg_list,
2384 : const TagList *tag_list,
2385 : const CommunityList *communities,
2386 : uint32_t mpls_label,
2387 : TunnelType::TypeBmap bmap,
2388 : const PathPreference &path_preference,
2389 : bool associate,
2390 : Agent::RouteTableType type,
2391 : const EcmpLoadBalance &ecmp_load_balance,
2392 : uint32_t native_vrf_id) {
2393 58 : if (route->vrf()) {
2394 58 : const std::string vrf_name = route->vrf()->GetName();
2395 116 : if (VxlanRoutingManager::IsVxlanAvailable(agent_) &&
2396 116 : VxlanRoutingManager::IsRoutingVrf(vrf_name, agent_)) {
2397 0 : return true;
2398 : }
2399 58 : }
2400 :
2401 : static int id = 0;
2402 58 : ItemType item;
2403 58 : string repr;
2404 58 : boost::scoped_ptr<XmlWriter> xml_writer(new XmlWriter(&repr));
2405 :
2406 : //Build the DOM tree
2407 58 : unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
2408 58 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
2409 :
2410 58 : if ((type == Agent::INET4_UNICAST) ||
2411 : (type == Agent::INET4_MPLS)) {
2412 58 : item.entry.nlri.af = BgpAf::IPv4;
2413 0 : } else if (type == Agent::INET6_UNICAST) {
2414 0 : item.entry.nlri.af = BgpAf::IPv6;
2415 : }
2416 58 : if (type == Agent::INET4_MPLS) {
2417 0 : item.entry.nlri.safi = BgpAf::Mpls;
2418 : } else {
2419 58 : item.entry.nlri.safi = BgpAf::Unicast;
2420 : }
2421 :
2422 58 : stringstream rstr;
2423 58 : rstr << route->ToString();
2424 58 : item.entry.nlri.address = rstr.str();
2425 :
2426 58 : string rtr(agent_->router_id().to_string());
2427 :
2428 58 : PopulateEcmpHashFieldsToUse(item, ecmp_load_balance);
2429 58 : autogen::NextHopType nh;
2430 58 : nh.af = BgpAf::IPv4;
2431 58 : nh.address = rtr;
2432 58 : nh.label = mpls_label;
2433 :
2434 : // EVPN (VNF) service chaining requires router MAC address advertisement.
2435 58 : if (agent_->vhost_interface()) {
2436 58 : nh.mac = agent_->vhost_interface()->mac().ToString();
2437 : }
2438 58 : if (bmap & TunnelType::GREType()) {
2439 58 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("gre");
2440 : }
2441 58 : if (bmap & TunnelType::UDPType()) {
2442 58 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("udp");
2443 : }
2444 58 : if (bmap & TunnelType::VxlanType()) {
2445 19 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("vxlan");
2446 19 : const AgentPath *loc_vm_path = route->FindIntfOrCompLocalVmPortPath();
2447 19 : if (loc_vm_path && route->vrf() && route->vrf()->routing_vrf()) {
2448 0 : nh.label = loc_vm_path->vxlan_id();
2449 : }
2450 : }
2451 58 : if (bmap & TunnelType::NativeType()) {
2452 0 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("native");
2453 : }
2454 :
2455 58 : if (tag_list && tag_list->size()) {
2456 0 : nh.tag_list.tag = *tag_list;
2457 0 : nh.is_new_tags_list = true;
2458 0 : const AgentPath *loc_vm_path = route->FindLocalVmPortPath();
2459 0 : const InterfaceNH *interface_nh = loc_vm_path != nullptr ?
2460 0 : dynamic_cast<const InterfaceNH*>(loc_vm_path->nexthop()) :
2461 0 : nullptr;
2462 0 : const VmInterface *vm_interface = interface_nh != nullptr ?
2463 0 : dynamic_cast<const VmInterface*>(interface_nh->GetInterface()) :
2464 0 : nullptr;
2465 0 : if (vm_interface != nullptr &&
2466 0 : !vm_interface->contains_new_tags()) {
2467 0 : nh.is_new_tags_list = false;
2468 0 : for (auto &tag : nh.tag_list.tag) {
2469 0 : tag = (0x00000000FFFF & tag) |
2470 0 : ((0xFFFF00000000 & tag) >> 16);
2471 : }
2472 : }
2473 : }
2474 :
2475 58 : if (path_preference.loc_sequence()) {
2476 0 : nh.local_sequence_number = path_preference.loc_sequence();
2477 : }
2478 :
2479 58 : for (VnListType::const_iterator vnit = vn_list.begin();
2480 116 : vnit != vn_list.end(); ++vnit) {
2481 58 : nh.virtual_network = *vnit;
2482 58 : item.entry.next_hops.next_hop.push_back(nh);
2483 : }
2484 :
2485 58 : if (sg_list && sg_list->size()) {
2486 3 : item.entry.security_group_list.security_group = *sg_list;
2487 : }
2488 :
2489 58 : if (communities && !communities->empty()) {
2490 0 : item.entry.community_tag_list.community_tag = *communities;
2491 : }
2492 :
2493 58 : item.entry.sub_protocol = route->intf_route_type();
2494 58 : item.entry.version = 1; //TODO
2495 58 : item.entry.med = 0;
2496 :
2497 : //Set sequence number and preference of route
2498 58 : item.entry.sequence_number = path_preference.sequence();
2499 58 : item.entry.local_preference = path_preference.preference();
2500 :
2501 58 : pugi->AddNode("iq", "");
2502 58 : pugi->AddAttribute("type", "set");
2503 :
2504 58 : pugi->AddAttribute("from", channel_->FromString());
2505 58 : std::string to(channel_->ToString());
2506 58 : to += "/";
2507 58 : to += XmppInit::kBgpPeer;
2508 58 : pugi->AddAttribute("to", to);
2509 :
2510 58 : stringstream pubsub_id;
2511 58 : pubsub_id << "pubsub" << id;
2512 58 : pugi->AddAttribute("id", pubsub_id.str());
2513 :
2514 58 : pugi->AddChildNode("pubsub", "");
2515 58 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
2516 58 : pugi->AddChildNode("publish", "");
2517 :
2518 : //Catering for inet4 and evpn unicast routes
2519 58 : stringstream ss_node;
2520 58 : ss_node << item.entry.nlri.af << "/"
2521 : << item.entry.nlri.safi << "/"
2522 58 : << route->vrf()->GetName() << "/"
2523 116 : << route->ToString();
2524 58 : if (native_vrf_id != VrfEntry::kInvalidIndex) {
2525 0 : ss_node << "/" << native_vrf_id;
2526 : }
2527 58 : std::string node_id(ss_node.str());
2528 58 : pugi->AddAttribute("node", node_id);
2529 58 : pugi->AddChildNode("item", "");
2530 :
2531 58 : pugi::xml_node node = pugi->FindNode("item");
2532 :
2533 : //Call Auto-generated Code to encode the struct
2534 58 : item.Encode(&node);
2535 :
2536 58 : pugi->doc().print(*xml_writer, "", pugi::format_default,
2537 : pugi::encoding_utf8);
2538 : // send data
2539 58 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
2540 58 : repr.clear();
2541 :
2542 58 : pugi->DeleteNode("pubsub");
2543 58 : pugi->ReadNode("iq");
2544 :
2545 58 : stringstream collection_id;
2546 58 : collection_id << "collection" << id++;
2547 58 : pugi->ModifyAttribute("id", collection_id.str());
2548 58 : pugi->AddChildNode("pubsub", "");
2549 58 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
2550 58 : pugi->AddChildNode("collection", "");
2551 :
2552 58 : pugi->AddAttribute("node", route->vrf()->GetName());
2553 58 : if (associate) {
2554 39 : pugi->AddChildNode("associate", "");
2555 : } else {
2556 19 : pugi->AddChildNode("dissociate", "");
2557 : }
2558 58 : pugi->AddAttribute("node", node_id);
2559 :
2560 58 : pugi->doc().print(*xml_writer, "", pugi::format_default,
2561 : pugi::encoding_utf8);
2562 : // send data
2563 58 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
2564 58 : end_of_rib_tx_timer()->last_route_published_time_ = UTCTimestampUsec();
2565 58 : return true;
2566 58 : }
2567 :
2568 0 : bool AgentXmppChannel::BuildTorMulticastMessage(EnetItemType &item,
2569 : stringstream &node_id,
2570 : AgentRoute *route,
2571 : const Ip4Address *nh_ip,
2572 : const std::string &vn,
2573 : const SecurityGroupList *sg_list,
2574 : const TagList *tag_list,
2575 : const CommunityList *communities,
2576 : uint32_t label,
2577 : uint32_t tunnel_bmap,
2578 : const std::string &destination,
2579 : const std::string &source,
2580 : bool associate) {
2581 0 : assert(route->GetTableType() == Agent::EVPN);
2582 0 : const AgentPath *path = NULL;
2583 : EvpnRouteEntry *evpn_route =
2584 0 : dynamic_cast<EvpnRouteEntry *>(route);
2585 0 : path = evpn_route->FindOvsPath();
2586 0 : if ((path == NULL) && (associate)) {
2587 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(),
2588 : route->vrf()->GetName(),
2589 : "OVS path not found for ff:ff:ff:ff:ff:ff, skip send");
2590 0 : return false;
2591 : }
2592 :
2593 0 : item.entry.local_preference = PathPreference::LOW;
2594 0 : item.entry.sequence_number = 0;
2595 0 : item.entry.replicator_address = source;
2596 0 : item.entry.nlri.af = BgpAf::L2Vpn;
2597 0 : item.entry.nlri.safi = BgpAf::Enet;
2598 0 : stringstream rstr;
2599 0 : rstr << route->ToString();
2600 0 : item.entry.nlri.mac = rstr.str();
2601 0 : item.entry.assisted_replication_supported = false;
2602 0 : item.entry.edge_replication_not_supported = false;
2603 :
2604 0 : rstr.str("");
2605 : //TODO fix this when multicast moves to evpn
2606 0 : assert(evpn_route->is_multicast());
2607 0 : rstr << destination;
2608 0 : rstr << "/32";
2609 0 : item.entry.nlri.ethernet_tag = 0;
2610 0 : if (associate == false)
2611 0 : item.entry.nlri.ethernet_tag = label;
2612 :
2613 0 : item.entry.nlri.address = rstr.str();
2614 0 : assert(item.entry.nlri.address != "0.0.0.0");
2615 :
2616 0 : autogen::EnetNextHopType nh;
2617 0 : nh.af = Address::INET;
2618 0 : nh.address = destination;
2619 0 : nh.label = label;
2620 :
2621 0 : node_id << item.entry.nlri.af << "/" << item.entry.nlri.safi << "/"
2622 0 : << route->ToString() << "," << item.entry.nlri.address;
2623 0 : TunnelType::Type tunnel_type = TunnelType::ComputeType(tunnel_bmap);
2624 :
2625 0 : if (path) {
2626 0 : tunnel_type = path->tunnel_type();
2627 : }
2628 0 : if (associate) {
2629 0 : if (tunnel_type != TunnelType::VXLAN) {
2630 0 : if (tunnel_bmap & TunnelType::GREType()) {
2631 0 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("gre");
2632 : }
2633 0 : if (tunnel_bmap & TunnelType::UDPType()) {
2634 0 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("udp");
2635 : }
2636 : } else {
2637 0 : if (path) {
2638 0 : nh.label = path->vxlan_id();
2639 0 : item.entry.nlri.ethernet_tag = nh.label;
2640 : } else {
2641 0 : nh.label = 0;
2642 : }
2643 0 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("vxlan");
2644 : }
2645 :
2646 0 : if (sg_list && sg_list->size()) {
2647 0 : item.entry.security_group_list.security_group = *sg_list;
2648 : }
2649 :
2650 0 : if (tag_list && tag_list->size()) {
2651 0 : nh.tag_list.tag = *tag_list;
2652 : }
2653 : }
2654 :
2655 0 : item.entry.next_hops.next_hop.push_back(nh);
2656 0 : item.entry.med = 0;
2657 : //item.entry.version = 1; //TODO
2658 : //item.entry.virtual_network = vn;
2659 0 : return true;
2660 0 : }
2661 :
2662 : //TODO simplify label selection below.
2663 54 : bool AgentXmppChannel::BuildEvpnMulticastMessage(EnetItemType &item,
2664 : stringstream &node_id,
2665 : AgentRoute *route,
2666 : const Ip4Address *nh_ip,
2667 : const std::string &vn,
2668 : const SecurityGroupList *sg_list,
2669 : const TagList *tag_list,
2670 : const CommunityList *communities,
2671 : uint32_t label,
2672 : uint32_t tunnel_bmap,
2673 : bool associate,
2674 : const AgentPath *path,
2675 : bool assisted_replication) {
2676 54 : assert(route->is_multicast() == true);
2677 54 : item.entry.local_preference = PathPreference::LOW;
2678 54 : item.entry.sequence_number = 0;
2679 54 : if (agent_->simulate_evpn_tor()) {
2680 0 : item.entry.edge_replication_not_supported = true;
2681 : } else {
2682 54 : item.entry.edge_replication_not_supported = false;
2683 : }
2684 54 : item.entry.nlri.af = BgpAf::L2Vpn;
2685 54 : item.entry.nlri.safi = BgpAf::Enet;
2686 54 : stringstream rstr;
2687 : //TODO fix this when multicast moves to evpn
2688 54 : rstr << "0.0.0.0/32";
2689 54 : item.entry.nlri.address = rstr.str();
2690 54 : assert(item.entry.nlri.address != "0.0.0.0");
2691 :
2692 54 : rstr.str("");
2693 54 : if (assisted_replication) {
2694 0 : rstr << route->ToString();
2695 0 : item.entry.assisted_replication_supported = true;
2696 0 : node_id << item.entry.nlri.af << "/" << item.entry.nlri.safi << "/"
2697 0 : << route->ToString() << "," << item.entry.nlri.address
2698 0 : << "," << route->GetAddressString()
2699 0 : << "," << route->GetSourceAddressString();
2700 : } else {
2701 54 : rstr << route->GetAddressString();
2702 54 : item.entry.assisted_replication_supported = false;
2703 54 : node_id << item.entry.nlri.af << "/" << item.entry.nlri.safi << "/"
2704 54 : << route->GetAddressString() << "," << item.entry.nlri.address
2705 54 : << "," << route->GetAddressString()
2706 54 : << "," << route->GetSourceAddressString();
2707 : }
2708 :
2709 54 : if (route->GetTableType() == Agent::INET4_MULTICAST) {
2710 0 : Inet4MulticastRouteEntry *m_route =
2711 : static_cast<Inet4MulticastRouteEntry *>(route);
2712 :
2713 0 : const Ip4Address group = m_route->dest_ip_addr();
2714 0 : MacAddress mac;
2715 0 : agent_->oper_db()->multicast()->GetMulticastMacFromIp(group, mac);
2716 :
2717 0 : item.entry.nlri.mac = mac.ToString();
2718 0 : item.entry.nlri.group = route->GetAddressString();
2719 0 : item.entry.nlri.source = route->GetSourceAddressString();
2720 0 : item.entry.nlri.flags =
2721 0 : agent_->oper_db()->multicast()->GetEvpnMulticastSGFlags(
2722 : m_route->vrf()->GetName(),
2723 : m_route->src_ip_addr(),
2724 : m_route->dest_ip_addr());
2725 : } else {
2726 54 : item.entry.nlri.mac = route->ToString();
2727 : }
2728 :
2729 54 : autogen::EnetNextHopType nh;
2730 54 : nh.af = Address::INET;
2731 54 : nh.address = nh_ip->to_string();
2732 54 : nh.label = label;
2733 :
2734 54 : TunnelType::Type tunnel_type = TunnelType::ComputeType(tunnel_bmap);
2735 54 : item.entry.nlri.ethernet_tag = route->vrf()->isid();
2736 54 : if (associate == false) {
2737 : //In case of VXLAN ethernet tag is set to vxlan ID.
2738 : //Upon withdraw or encap change label holds the VN ID
2739 : //which is used to withdraw route
2740 22 : item.entry.nlri.ethernet_tag = label;
2741 : }
2742 :
2743 54 : if (path) {
2744 15 : tunnel_type = path->tunnel_type();
2745 : }
2746 54 : if (associate) {
2747 32 : if (tunnel_type != TunnelType::VXLAN) {
2748 8 : if (tunnel_bmap & TunnelType::GREType()) {
2749 8 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("gre");
2750 : }
2751 8 : if (tunnel_bmap & TunnelType::UDPType()) {
2752 8 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("udp");
2753 : }
2754 : } else {
2755 24 : if (path == NULL)
2756 24 : path = route->FindPath(agent_->local_peer());
2757 :
2758 24 : if (path) {
2759 24 : nh.label = path->vxlan_id();
2760 24 : item.entry.nlri.ethernet_tag = nh.label;
2761 : } else {
2762 0 : nh.label = 0;
2763 : }
2764 24 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("vxlan");
2765 : }
2766 :
2767 32 : if (sg_list && sg_list->size()) {
2768 0 : item.entry.security_group_list.security_group = *sg_list;
2769 : }
2770 : }
2771 :
2772 54 : item.entry.next_hops.next_hop.push_back(nh);
2773 54 : item.entry.med = 0;
2774 : //item.entry.version = 1; //TODO
2775 : //item.entry.virtual_network = vn;
2776 54 : return true;
2777 54 : }
2778 :
2779 101 : bool AgentXmppChannel::BuildEvpnUnicastMessage(EnetItemType &item,
2780 : stringstream &node_id,
2781 : AgentRoute *route,
2782 : const Ip4Address *nh_ip,
2783 : const std::string &vn,
2784 : const SecurityGroupList *sg_list,
2785 : const TagList *tag_list,
2786 : const CommunityList *communities,
2787 : uint32_t label,
2788 : uint32_t tunnel_bmap,
2789 : const PathPreference
2790 : &path_preference,
2791 : bool associate) {
2792 101 : assert(route->is_multicast() == false);
2793 101 : assert(route->GetTableType() == Agent::EVPN);
2794 101 : item.entry.local_preference = path_preference.preference();
2795 101 : item.entry.sequence_number = path_preference.sequence();
2796 101 : item.entry.assisted_replication_supported = false;
2797 101 : item.entry.edge_replication_not_supported = false;
2798 101 : item.entry.nlri.af = BgpAf::L2Vpn;
2799 101 : item.entry.nlri.safi = BgpAf::Enet;
2800 :
2801 101 : stringstream rstr;
2802 101 : rstr << route->GetAddressString();
2803 101 : item.entry.nlri.mac = rstr.str();
2804 :
2805 101 : const AgentPath *active_path = NULL;
2806 101 : rstr.str("");
2807 101 : EvpnRouteEntry *evpn_route = static_cast<EvpnRouteEntry *>(route);
2808 202 : rstr << evpn_route->prefix_address().to_string() << "/"
2809 101 : << static_cast<int>(evpn_route->prefix_length());
2810 101 : active_path = evpn_route->FindLocalVmPortPath();
2811 101 : item.entry.nlri.ethernet_tag = evpn_route->ethernet_tag();
2812 :
2813 101 : item.entry.nlri.address = rstr.str();
2814 101 : assert(item.entry.nlri.address != "0.0.0.0");
2815 :
2816 101 : item.entry.etree_leaf = true;
2817 101 : if (active_path) {
2818 63 : item.entry.etree_leaf = active_path->etree_leaf();
2819 : }
2820 :
2821 101 : autogen::EnetNextHopType nh;
2822 101 : nh.af = Address::INET;
2823 101 : nh.address = nh_ip->to_string();
2824 101 : nh.label = label;
2825 101 : if (evpn_route->mac().IsZero()) {
2826 0 : nh.mac = agent_->vhost_interface()->mac().ToString();
2827 : }
2828 101 : TunnelType::Type tunnel_type = TunnelType::ComputeType(tunnel_bmap);
2829 101 : if (active_path) {
2830 63 : tunnel_type = active_path->tunnel_type();
2831 : }
2832 101 : if (associate) {
2833 63 : if (tunnel_type != TunnelType::VXLAN) {
2834 63 : if (tunnel_bmap & TunnelType::GREType()) {
2835 63 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("gre");
2836 : }
2837 63 : if (tunnel_bmap & TunnelType::UDPType()) {
2838 63 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("udp");
2839 : }
2840 : } else {
2841 0 : if (active_path) {
2842 0 : nh.label = active_path->vxlan_id();
2843 : } else {
2844 0 : nh.label = 0;
2845 : }
2846 0 : nh.tunnel_encapsulation_list.tunnel_encapsulation.push_back("vxlan");
2847 : }
2848 :
2849 63 : if (sg_list && sg_list->size()) {
2850 6 : item.entry.security_group_list.security_group = *sg_list;
2851 : }
2852 :
2853 63 : if (tag_list && tag_list->size()) {
2854 0 : nh.tag_list.tag = *tag_list;
2855 0 : nh.is_new_tags_list = true;
2856 0 : const InterfaceNH *interface_nh = active_path != nullptr ?
2857 0 : dynamic_cast<const InterfaceNH*>(active_path->nexthop()) :
2858 0 : nullptr;
2859 0 : const VmInterface *vm_interface = interface_nh != nullptr ?
2860 0 : dynamic_cast<const VmInterface*>(
2861 0 : interface_nh->GetInterface()) :
2862 0 : nullptr;
2863 0 : if (vm_interface != nullptr &&
2864 0 : !vm_interface->contains_new_tags()) {
2865 0 : nh.is_new_tags_list = false;
2866 0 : for (auto &tag : nh.tag_list.tag) {
2867 0 : tag = (0x00000000FFFF & tag) |
2868 0 : ((0xFFFF00000000 & tag) >> 16);
2869 : }
2870 : }
2871 : }
2872 :
2873 63 : if (path_preference.loc_sequence()) {
2874 0 : nh.local_sequence_number = path_preference.loc_sequence();
2875 : }
2876 : }
2877 :
2878 101 : item.entry.next_hops.next_hop.push_back(nh);
2879 101 : item.entry.med = 0;
2880 : //item.entry.version = 1; //TODO
2881 : //item.entry.virtual_network = vn;
2882 :
2883 101 : node_id << item.entry.nlri.af << "/" << item.entry.nlri.safi << "/"
2884 101 : << route->GetAddressString() << "," << item.entry.nlri.address;
2885 101 : return true;
2886 101 : }
2887 :
2888 155 : bool AgentXmppChannel::BuildAndSendEvpnDom(EnetItemType &item,
2889 : stringstream &ss_node,
2890 : const AgentRoute *route,
2891 : bool associate) {
2892 : static int id = 0;
2893 155 : string repr;
2894 155 : boost::scoped_ptr<XmlWriter> xml_writer(new XmlWriter(&repr));
2895 :
2896 : //Build the DOM tree
2897 155 : unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
2898 155 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
2899 :
2900 155 : pugi->AddNode("iq", "");
2901 155 : pugi->AddAttribute("type", "set");
2902 :
2903 155 : pugi->AddAttribute("from", channel_->FromString());
2904 155 : std::string to(channel_->ToString());
2905 155 : to += "/";
2906 155 : to += XmppInit::kBgpPeer;
2907 155 : pugi->AddAttribute("to", to);
2908 :
2909 155 : stringstream pubsub_id;
2910 155 : pubsub_id << "pubsub_l2" << id;
2911 155 : pugi->AddAttribute("id", pubsub_id.str());
2912 :
2913 155 : pugi->AddChildNode("pubsub", "");
2914 155 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
2915 155 : pugi->AddChildNode("publish", "");
2916 :
2917 155 : std::string node_id(ss_node.str());
2918 155 : pugi->AddAttribute("node", node_id);
2919 155 : pugi->AddChildNode("item", "");
2920 :
2921 155 : pugi::xml_node node = pugi->FindNode("item");
2922 :
2923 : //Call Auto-generated Code to encode the struct
2924 155 : item.Encode(&node);
2925 :
2926 155 : pugi->doc().print(*xml_writer, "", pugi::format_default,
2927 : pugi::encoding_utf8);
2928 : // send data
2929 155 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
2930 155 : repr.clear();
2931 :
2932 155 : pugi->DeleteNode("pubsub");
2933 155 : pugi->ReadNode("iq");
2934 :
2935 155 : stringstream collection_id;
2936 155 : collection_id << "collection_l2" << id++;
2937 155 : pugi->ModifyAttribute("id", collection_id.str());
2938 155 : pugi->AddChildNode("pubsub", "");
2939 155 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
2940 155 : pugi->AddChildNode("collection", "");
2941 :
2942 155 : pugi->AddAttribute("node", route->vrf()->GetExportName());
2943 155 : if (associate) {
2944 95 : pugi->AddChildNode("associate", "");
2945 : } else {
2946 60 : pugi->AddChildNode("dissociate", "");
2947 : }
2948 155 : pugi->AddAttribute("node", node_id);
2949 :
2950 155 : pugi->doc().print(*xml_writer, "", pugi::format_default,
2951 : pugi::encoding_utf8);
2952 : // send data
2953 155 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
2954 155 : end_of_rib_tx_timer()->last_route_published_time_ = UTCTimestampUsec();
2955 155 : return true;
2956 155 : }
2957 :
2958 155 : bool AgentXmppChannel::ControllerSendEvpnRouteCommon(AgentRoute *route,
2959 : const Ip4Address *nh_ip,
2960 : std::string vn,
2961 : const SecurityGroupList *sg_list,
2962 : const TagList *tag_list,
2963 : const CommunityList *communities,
2964 : uint32_t label,
2965 : uint32_t tunnel_bmap,
2966 : const std::string &destination,
2967 : const std::string &source,
2968 : const PathPreference
2969 : &path_preference,
2970 : bool associate) {
2971 155 : EnetItemType item;
2972 155 : stringstream ss_node;
2973 155 : bool ret = true;
2974 :
2975 155 : if (label == MplsTable::kInvalidLabel) return false;
2976 :
2977 155 : if (route->is_multicast()) {
2978 : BridgeRouteEntry *l2_route =
2979 54 : dynamic_cast<BridgeRouteEntry *>(route);
2980 54 : if (agent_->tsn_enabled()) {
2981 : //Second subscribe for TSN assited replication
2982 0 : if (BuildEvpnMulticastMessage(item, ss_node, route, nh_ip, vn,
2983 : sg_list, tag_list, communities,
2984 : label, tunnel_bmap, associate,
2985 0 : l2_route->FindPath(agent_->
2986 : local_peer()),
2987 0 : true) == false)
2988 0 : return false;
2989 0 : ret |= BuildAndSendEvpnDom(item, ss_node,
2990 : route, associate);
2991 54 : } else if (agent_->tor_agent_enabled()) {
2992 0 : if (BuildTorMulticastMessage(item, ss_node, route, nh_ip, vn,
2993 : sg_list, tag_list, communities, label,
2994 : tunnel_bmap, destination, source,
2995 0 : associate) == false)
2996 0 : return false;;
2997 0 : ret = BuildAndSendEvpnDom(item, ss_node, route, associate);
2998 : } else {
2999 : const AgentPath *path;
3000 54 : if (route->GetTableType() == Agent::BRIDGE) {
3001 54 : path = l2_route->FindPath(agent_->multicast_peer());
3002 0 : } else if (route->GetTableType() == Agent::INET4_MULTICAST) {
3003 0 : Inet4MulticastRouteEntry *m_route =
3004 : static_cast<Inet4MulticastRouteEntry *>(route);
3005 0 : path = m_route->FindPath(agent_->multicast_peer());
3006 : } else {
3007 0 : return false;
3008 : }
3009 54 : if (BuildEvpnMulticastMessage(item, ss_node, route, nh_ip, vn,
3010 : sg_list, tag_list, communities, label,
3011 : tunnel_bmap, associate,
3012 : path,
3013 54 : false) == false)
3014 0 : return false;
3015 54 : ret = BuildAndSendEvpnDom(item, ss_node, route, associate);
3016 : }
3017 : } else {
3018 101 : if (BuildEvpnUnicastMessage(item, ss_node, route, nh_ip, vn, sg_list,
3019 : tag_list, communities, label, tunnel_bmap,
3020 101 : path_preference, associate) == false)
3021 0 : return false;;
3022 101 : ret = BuildAndSendEvpnDom(item, ss_node, route, associate);
3023 : }
3024 155 : return ret;
3025 155 : }
3026 :
3027 32 : bool AgentXmppChannel::ControllerSendMcastRouteCommon(AgentRoute *route,
3028 : bool add_route) {
3029 : static int id = 0;
3030 32 : autogen::McastItemType item;
3031 32 : string repr;
3032 32 : boost::scoped_ptr<XmlWriter> xml_writer(new XmlWriter(&repr));
3033 :
3034 32 : if (add_route && (agent_->mulitcast_builder() != this)) {
3035 0 : CONTROLLER_INFO_TRACE(Trace, GetBgpPeerName(),
3036 : route->vrf()->GetName(),
3037 : "Peer not elected Multicast Tree Builder");
3038 0 : return false;
3039 : }
3040 :
3041 32 : CONTROLLER_INFO_TRACE(McastSubscribe, GetBgpPeerName(),
3042 : route->vrf()->GetName(), " ",
3043 : route->ToString());
3044 :
3045 : //Build the DOM tree
3046 32 : unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
3047 32 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
3048 :
3049 32 : item.entry.nlri.af = BgpAf::IPv4;
3050 32 : item.entry.nlri.safi = BgpAf::Mcast;
3051 32 : item.entry.nlri.group = route->GetAddressString();
3052 32 : item.entry.nlri.source = route->GetSourceAddressString();
3053 :
3054 32 : autogen::McastNextHopType item_nexthop;
3055 32 : item_nexthop.af = BgpAf::IPv4;
3056 32 : string rtr(agent_->router_id().to_string());
3057 32 : item_nexthop.address = rtr;
3058 32 : item_nexthop.label = GetMcastLabelRange();
3059 32 : item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation.push_back("gre");
3060 32 : item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation.push_back("udp");
3061 32 : item.entry.next_hops.next_hop.push_back(item_nexthop);
3062 :
3063 : //Build the pugi tree
3064 32 : pugi->AddNode("iq", "");
3065 32 : pugi->AddAttribute("type", "set");
3066 32 : pugi->AddAttribute("from", channel_->FromString());
3067 32 : std::string to(channel_->ToString());
3068 32 : to += "/";
3069 32 : to += XmppInit::kBgpPeer;
3070 32 : pugi->AddAttribute("to", to);
3071 :
3072 32 : std::string pubsub_id("pubsub_b");
3073 32 : stringstream str_id;
3074 32 : str_id << id;
3075 32 : pubsub_id += str_id.str();
3076 32 : pugi->AddAttribute("id", pubsub_id);
3077 :
3078 32 : pugi->AddChildNode("pubsub", "");
3079 32 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
3080 32 : pugi->AddChildNode("publish", "");
3081 32 : stringstream ss_node;
3082 32 : ss_node << item.entry.nlri.af << "/"
3083 : << item.entry.nlri.safi << "/"
3084 32 : << route->vrf()->GetExportName() << "/"
3085 64 : << route->GetAddressString();
3086 32 : std::string node_id(ss_node.str());
3087 32 : pugi->AddAttribute("node", node_id);
3088 32 : pugi->AddChildNode("item", "");
3089 :
3090 32 : pugi::xml_node node = pugi->FindNode("item");
3091 :
3092 : //Call Auto-generated Code to encode the struct
3093 32 : item.Encode(&node);
3094 :
3095 32 : pugi->doc().print(*xml_writer, "", pugi::format_default,
3096 : pugi::encoding_utf8);
3097 : // send data
3098 32 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
3099 32 : repr.clear();
3100 :
3101 32 : pugi->DeleteNode("pubsub");
3102 32 : pugi->ReadNode("iq");
3103 :
3104 32 : stringstream collection_id;
3105 32 : collection_id << "collection" << id++;
3106 32 : pugi->ModifyAttribute("id", collection_id.str());
3107 32 : pugi->AddChildNode("pubsub", "");
3108 32 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
3109 32 : pugi->AddChildNode("collection", "");
3110 :
3111 32 : pugi->AddAttribute("node", route->vrf()->GetName());
3112 32 : if (add_route) {
3113 19 : pugi->AddChildNode("associate", "");
3114 : } else {
3115 13 : pugi->AddChildNode("dissociate", "");
3116 : }
3117 32 : pugi->AddAttribute("node", node_id);
3118 :
3119 32 : pugi->doc().print(*xml_writer, "", pugi::format_default,
3120 : pugi::encoding_utf8);
3121 : // send data
3122 32 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
3123 32 : end_of_rib_tx_timer()->last_route_published_time_ = UTCTimestampUsec();
3124 32 : return true;
3125 32 : }
3126 :
3127 0 : bool AgentXmppChannel::ControllerSendIPMcastRouteCommon(AgentRoute *route,
3128 : bool associate) {
3129 :
3130 0 : if (agent_->params()->mvpn_ipv4_enable()) {
3131 0 : if (agent_->fabric_policy_vrf_name() != route->vrf()->GetName()) {
3132 0 : return ControllerSendMvpnRouteCommon(route, associate);
3133 : }
3134 : }
3135 0 : return ControllerSendMcastRouteCommon(route, associate);
3136 : }
3137 :
3138 0 : bool AgentXmppChannel::ControllerSendMvpnRouteCommon(AgentRoute *route,
3139 : bool associate) {
3140 : static int id = 0;
3141 0 : MvpnItemType item;
3142 0 : string repr;
3143 0 : boost::scoped_ptr<XmlWriter> xml_writer(new XmlWriter(&repr));
3144 :
3145 0 : CONTROLLER_INFO_TRACE(McastSubscribe, GetBgpPeerName(),
3146 : route->vrf()->GetName(), " ",
3147 : route->ToString());
3148 :
3149 : //Build the DOM tree
3150 0 : unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
3151 0 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
3152 :
3153 0 : item.entry.nlri.af = BgpAf::IPv4;
3154 0 : item.entry.nlri.safi = BgpAf::MVpn;
3155 0 : item.entry.nlri.group = route->GetAddressString();
3156 0 : item.entry.nlri.source = route->GetSourceAddressString();
3157 0 : item.entry.nlri.route_type = 7;
3158 :
3159 0 : item.entry.next_hop.af = BgpAf::IPv4;
3160 0 : string rtr(agent_->router_id().to_string());
3161 0 : item.entry.next_hop.address = rtr;
3162 0 : item.entry.next_hop.label = 0;
3163 :
3164 : //Build the pugi tree
3165 0 : pugi->AddNode("iq", "");
3166 0 : pugi->AddAttribute("type", "set");
3167 0 : pugi->AddAttribute("from", channel_->FromString());
3168 0 : std::string to(channel_->ToString());
3169 0 : to += "/";
3170 0 : to += XmppInit::kBgpPeer;
3171 0 : pugi->AddAttribute("to", to);
3172 :
3173 0 : std::string pubsub_id("pubsub_b");
3174 0 : stringstream str_id;
3175 0 : str_id << id;
3176 0 : pubsub_id += str_id.str();
3177 0 : pugi->AddAttribute("id", pubsub_id);
3178 :
3179 0 : pugi->AddChildNode("pubsub", "");
3180 0 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
3181 0 : pugi->AddChildNode("publish", "");
3182 0 : stringstream ss_node;
3183 0 : ss_node << item.entry.nlri.af << "/"
3184 : << item.entry.nlri.safi << "/"
3185 0 : << route->vrf()->GetExportName() << "/"
3186 0 : << route->GetAddressString();
3187 0 : std::string node_id(ss_node.str());
3188 0 : pugi->AddAttribute("node", node_id);
3189 0 : pugi->AddChildNode("item", "");
3190 :
3191 0 : pugi::xml_node node = pugi->FindNode("item");
3192 :
3193 : //Call Auto-generated Code to encode the struct
3194 0 : item.Encode(&node);
3195 :
3196 0 : pugi->doc().print(*xml_writer, "", pugi::format_default,
3197 : pugi::encoding_utf8);
3198 : // send data
3199 0 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
3200 0 : repr.clear();
3201 :
3202 0 : pugi->DeleteNode("pubsub");
3203 0 : pugi->ReadNode("iq");
3204 :
3205 0 : stringstream collection_id;
3206 0 : collection_id << "collection" << id++;
3207 0 : pugi->ModifyAttribute("id", collection_id.str());
3208 0 : pugi->AddChildNode("pubsub", "");
3209 0 : pugi->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
3210 0 : pugi->AddChildNode("collection", "");
3211 :
3212 0 : pugi->AddAttribute("node", route->vrf()->GetName());
3213 0 : if (associate) {
3214 0 : pugi->AddChildNode("associate", "");
3215 : } else {
3216 0 : pugi->AddChildNode("dissociate", "");
3217 : }
3218 0 : pugi->AddAttribute("node", node_id);
3219 :
3220 0 : pugi->doc().print(*xml_writer, "", pugi::format_default,
3221 : pugi::encoding_utf8);
3222 : // send data for BgpAf::Mvpn
3223 0 : SendUpdate(reinterpret_cast<const uint8_t *>(repr.c_str()), repr.length());
3224 0 : end_of_rib_tx_timer()->last_route_published_time_ = UTCTimestampUsec();
3225 0 : return true;
3226 0 : }
3227 :
3228 32 : bool AgentXmppChannel::ControllerSendEvpnRouteAdd(AgentXmppChannel *peer,
3229 : AgentRoute *route,
3230 : const Ip4Address *nh_ip,
3231 : std::string vn,
3232 : uint32_t label,
3233 : uint32_t tunnel_bmap,
3234 : const SecurityGroupList *sg_list,
3235 : const TagList *tag_list,
3236 : const CommunityList *communities,
3237 : const std::string &destination,
3238 : const std::string &source,
3239 : const PathPreference
3240 : &path_preference) {
3241 32 : if (!peer) return false;
3242 :
3243 32 : CONTROLLER_INFO_TRACE(RouteExport, peer->GetBgpPeerName(),
3244 : route->vrf()->GetName(),
3245 : route->ToString(), true, label);
3246 64 : return (peer->ControllerSendEvpnRouteCommon(route,
3247 : nh_ip,
3248 : vn,
3249 : sg_list,
3250 : tag_list,
3251 : communities,
3252 : label,
3253 : tunnel_bmap,
3254 : destination,
3255 : source,
3256 : path_preference,
3257 32 : true));
3258 : }
3259 :
3260 22 : bool AgentXmppChannel::ControllerSendEvpnRouteDelete(AgentXmppChannel *peer,
3261 : AgentRoute *route,
3262 : std::string vn,
3263 : uint32_t label,
3264 : const std::string &destination,
3265 : const std::string &source,
3266 : uint32_t tunnel_bmap) {
3267 22 : if (!peer) return false;
3268 :
3269 22 : CONTROLLER_INFO_TRACE(RouteExport, peer->GetBgpPeerName(),
3270 : route->vrf()->GetName(),
3271 : route->ToString(), false, label);
3272 22 : Ip4Address nh_ip = Ip4Address(0);
3273 44 : return (peer->ControllerSendEvpnRouteCommon(route,
3274 : &nh_ip,
3275 : vn,
3276 : NULL,
3277 : NULL,
3278 : NULL,
3279 : label,
3280 : tunnel_bmap,
3281 : destination,
3282 : source,
3283 44 : PathPreference(),
3284 22 : false));
3285 : }
3286 :
3287 102 : bool AgentXmppChannel::ControllerSendRouteAdd(AgentXmppChannel *peer,
3288 : AgentRoute *route,
3289 : const Ip4Address *nexthop_ip,
3290 : const VnListType &vn_list,
3291 : uint32_t label,
3292 : TunnelType::TypeBmap bmap,
3293 : const SecurityGroupList *sg_list,
3294 : const TagList *tag_list,
3295 : const CommunityList *communities,
3296 : Agent::RouteTableType type,
3297 : const PathPreference &path_preference,
3298 : const EcmpLoadBalance &ecmp_load_balance,
3299 : uint32_t native_vrf_id)
3300 : {
3301 102 : if (!peer) return false;
3302 :
3303 102 : CONTROLLER_INFO_TRACE(RouteExport,
3304 : peer->GetBgpPeerName(),
3305 : route->vrf()->GetName(),
3306 : route->ToString(),
3307 : true, label);
3308 102 : bool ret = false;
3309 63 : if (((type == Agent::INET4_UNICAST) || (type == Agent::INET6_UNICAST)
3310 204 : ||(type == Agent::INET4_MPLS)) &&
3311 39 : (peer->agent()->simulate_evpn_tor() == false)) {
3312 39 : ret = peer->ControllerSendV4V6UnicastRouteCommon(route, vn_list,
3313 : sg_list, tag_list, communities, label,
3314 : bmap, path_preference, true,
3315 : type, ecmp_load_balance, native_vrf_id);
3316 : }
3317 102 : if (type == Agent::EVPN) {
3318 63 : std::string vn;
3319 63 : if (vn_list.size())
3320 63 : vn = *vn_list.begin();
3321 63 : ret = peer->ControllerSendEvpnRouteCommon(route, nexthop_ip, vn,
3322 : sg_list, tag_list, communities, label,
3323 : bmap, "", "",
3324 : path_preference, true);
3325 63 : }
3326 102 : return ret;
3327 : }
3328 :
3329 57 : bool AgentXmppChannel::ControllerSendRouteDelete(AgentXmppChannel *peer,
3330 : AgentRoute *route,
3331 : const VnListType &vn_list,
3332 : uint32_t label,
3333 : TunnelType::TypeBmap bmap,
3334 : const SecurityGroupList *sg_list,
3335 : const TagList *tag_list,
3336 : const CommunityList *communities,
3337 : Agent::RouteTableType type,
3338 : const PathPreference
3339 : &path_preference)
3340 : {
3341 57 : if (!peer) return false;
3342 :
3343 57 : CONTROLLER_INFO_TRACE(RouteExport,
3344 : peer->GetBgpPeerName(),
3345 : route->vrf()->GetName(),
3346 : route->ToString(),
3347 : false, 0);
3348 57 : bool ret = false;
3349 76 : if (((type == Agent::INET4_UNICAST) || (type == Agent::INET6_UNICAST)) &&
3350 19 : (peer->agent()->simulate_evpn_tor() == false)) {
3351 19 : EcmpLoadBalance ecmp_load_balance;
3352 19 : ret = peer->ControllerSendV4V6UnicastRouteCommon(route, vn_list,
3353 : sg_list, tag_list, communities,
3354 : label,
3355 : bmap,
3356 : path_preference,
3357 : false,
3358 : type,
3359 : ecmp_load_balance,
3360 : VrfEntry::kInvalidIndex);
3361 19 : }
3362 57 : if (type == Agent::EVPN) {
3363 38 : Ip4Address nh_ip(0);
3364 38 : std::string vn;
3365 38 : if (vn_list.size())
3366 38 : vn = *vn_list.begin();
3367 38 : ret = peer->ControllerSendEvpnRouteCommon(route, &nh_ip,
3368 : vn, NULL, NULL, NULL,
3369 : label, bmap, "", "",
3370 : path_preference, false);
3371 38 : }
3372 57 : return ret;
3373 : }
3374 :
3375 19 : bool AgentXmppChannel::ControllerSendMcastRouteAdd(AgentXmppChannel *peer,
3376 : AgentRoute *route) {
3377 19 : if (!peer) return false;
3378 :
3379 19 : CONTROLLER_INFO_TRACE(RouteExport, peer->GetBgpPeerName(),
3380 : route->vrf()->GetName(),
3381 : route->ToString(), true, 0);
3382 :
3383 19 : if (route->GetTableType() == Agent::INET4_MULTICAST) {
3384 0 : return peer->ControllerSendIPMcastRouteCommon(route, true);
3385 : }
3386 :
3387 19 : return peer->ControllerSendMcastRouteCommon(route, true);
3388 : }
3389 :
3390 13 : bool AgentXmppChannel::ControllerSendMcastRouteDelete(AgentXmppChannel *peer,
3391 : AgentRoute *route) {
3392 13 : if (!peer) return false;
3393 :
3394 13 : CONTROLLER_INFO_TRACE(RouteExport, peer->GetBgpPeerName(),
3395 : route->vrf()->GetName(),
3396 : route->ToString(), false, 0);
3397 :
3398 13 : if (route->GetTableType() == Agent::INET4_MULTICAST) {
3399 0 : return peer->ControllerSendIPMcastRouteCommon(route, false);
3400 : }
3401 :
3402 13 : return peer->ControllerSendMcastRouteCommon(route, false);
3403 : }
3404 :
3405 40 : void AgentXmppChannel::EndOfRibRx() {
3406 40 : end_of_rib_rx_timer()->end_of_rib_rx_time_ = UTCTimestampUsec();
3407 40 : bgp_peer_id()->DeleteStale();
3408 40 : agent()->controller()->FlushTimedOutChannels(xs_idx_);
3409 40 : if (agent()->mulitcast_builder() == this) {
3410 19 : MulticastHandler::GetInstance()->FlushPeerInfo(agent()->
3411 : controller()->multicast_sequence_number());
3412 : }
3413 40 : }
3414 :
3415 0 : void AgentXmppChannel::EndOfRibTx() {
3416 : //This is a callback from walker for bgp peer.
3417 : //It may happen that channel went down and stop of this walk was executed.
3418 : //However stop of the walk is enqueued and by that time, walk done for
3419 : //previously started walk for this peer gets executed.
3420 : //This can result in channel_ being NULL on walk done call.
3421 0 : if (channel_ == NULL) {
3422 0 : return;
3423 : }
3424 :
3425 0 : string msg;
3426 0 : msg += "\n<message from=\"";
3427 0 : msg += channel_->FromString();
3428 0 : msg += "\" to=\"";
3429 0 : msg += channel_->ToString();
3430 0 : msg += "/";
3431 0 : msg += XmppInit::kBgpPeer;
3432 0 : msg += "\">";
3433 0 : msg += "\n\t<event xmlns=\"http://jabber.org/protocol/pubsub\">";
3434 0 : msg = (msg + "\n<items node=\"") + XmppInit::kEndOfRibMarker +
3435 0 : "\"></items>";
3436 0 : msg += "\n\t</event>\n</message>\n";
3437 :
3438 0 : if (channel_->connection()) {
3439 0 : channel_->connection()->Send((const uint8_t *) msg.data(), msg.size());
3440 0 : end_of_rib_tx_timer()->end_of_rib_tx_time_ = UTCTimestampUsec();
3441 : }
3442 0 : }
3443 :
3444 63 : void AgentXmppChannel::UpdateConnectionInfo(xmps::PeerState state) {
3445 :
3446 63 : if (agent_->connection_state() == NULL)
3447 0 : return;
3448 :
3449 63 : boost::asio::ip::tcp::endpoint ep;
3450 63 : boost::system::error_code ec;
3451 63 : string last_state_name;
3452 63 : ep.address(AddressFromString(
3453 63 : agent_->controller_ifmap_xmpp_server(xs_idx_), &ec));
3454 63 : uint16_t port = agent_->controller_ifmap_xmpp_port(xs_idx_);
3455 63 : ep.port(port);
3456 63 : const string name = agent_->xmpp_control_node_prefix() +
3457 126 : ep.address().to_string();
3458 63 : XmppChannel *xc = GetXmppChannel();
3459 63 : if (xc) {
3460 42 : last_state_name = xc->LastStateName();
3461 : }
3462 63 : if (state == xmps::READY) {
3463 19 : agent_->connection_state()->Update(ConnectionType::XMPP, name,
3464 : ConnectionStatus::UP, ep,
3465 : last_state_name);
3466 : } else {
3467 44 : agent_->connection_state()->Update(ConnectionType::XMPP, name,
3468 : ConnectionStatus::DOWN, ep,
3469 : last_state_name);
3470 : }
3471 63 : }
3472 :
3473 0 : void AgentXmppChannel::StartEndOfRibTxWalker() {
3474 0 : if (bgp_peer_id()) {
3475 0 : bgp_peer_id()->PeerNotifyRoutes(
3476 : boost::bind(&AgentXmppChannel::EndOfRibTx, this));
3477 : }
3478 0 : }
3479 :
3480 21 : void AgentXmppChannel::StopEndOfRibTxWalker() {
3481 21 : if (bgp_peer_id()) {
3482 21 : bgp_peer_id()->StopPeerNotifyRoutes();
3483 : }
3484 21 : }
3485 :
3486 : template <typename TYPE>
3487 0 : void AgentXmppChannel::BuildTagList(const TYPE *item,
3488 : TagList &tag_list) {
3489 0 : bool new_tags = item->entry.next_hops.next_hop[0].is_new_tags_list;
3490 0 : tag_list = item->entry.next_hops.next_hop[0].tag_list.tag;
3491 0 : std::sort(tag_list.begin(), tag_list.end());
3492 0 : if (new_tags) {
3493 0 : return;
3494 : }
3495 0 : for (auto &tag : tag_list) {
3496 0 : tag = (0x0000FFFF & tag) | ((0xFFFF0000 & tag) << 16);
3497 : }
3498 : }
|