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