OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
controller_ifmap.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <stdint.h>
6 #include <string.h>
7 #include <pugixml/pugixml.hpp>
8 #include <xml/xml_base.h>
9 #include <xml/xml_pugi.h>
10 
11 #include <base/util.h>
12 #include <base/logging.h>
13 #include <xmpp/xmpp_channel.h>
15 
16 #include <cmn/agent_cmn.h>
17 #include <cmn/agent_stats.h>
18 
22 #include <controller/controller_types.h>
23 
24 
26 
28  uint8_t cnt) : channel_(channel),
29  xs_idx_(cnt),
30  agent_(agent) {
33  this, _1));
34  config_cleanup_timer_.reset(new ConfigCleanupTimer(agent));
35  end_of_config_timer_.reset(new EndOfConfigTimer(agent, this));
36 }
37 
41  config_cleanup_timer_.reset();
42  end_of_config_timer_.reset();
43 }
44 
46 
47  seq_number_++;
48 
49  if (seq_number_ == 0) {
50  return ++seq_number_;
51  }
52 
53  CONTROLLER_TRACE(IFMapSeqTrace, GetSeqNumber(), seq_number_, "New Config Seq Num");
54  return seq_number_;
55 }
56 
58  return config_cleanup_timer_.get();
59 }
60 
62  return end_of_config_timer_.get();
63 }
64 
65 bool AgentIfMapXmppChannel::SendUpdate(const std::string &msg) {
66  if (!channel_) return false;
67  return channel_->Send((const uint8_t *)msg.data(), msg.size(), xmps::CONFIG,
68  boost::bind(&AgentIfMapXmppChannel::WriteReadyCb, this, _1));
69 }
70 
72  if (msg && msg->type == XmppStanza::IQ_STANZA) {
73  std::unique_ptr<XmlBase> impl(XmppXmlImplFactory::Instance()->GetXmlImpl());
74  XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
75  XmlPugi *msg_pugi = reinterpret_cast<XmlPugi *>(msg->dom.get());
76  pugi->LoadXmlDoc(msg_pugi->doc());
77  boost::shared_ptr<ControllerXmppData> data(new ControllerXmppData(xmps::CONFIG,
79  xs_idx_,
80  std::move(impl),
81  true));
82  agent_->controller()->Enqueue(data);
84  }
85 }
86 
87 void AgentIfMapXmppChannel::ReceiveConfigMessage(std::unique_ptr<XmlBase> impl) {
88 
90  LOG(WARN, "IFMap config on non primary channel");
91  return;
92  }
93 
94  XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
95  pugi::xml_node node = pugi->FindNode("config");
97  assert(parser);
98  parser->ConfigParse(node, seq_number_);
99 }
100 
102  if (agent_->stats())
104  ReceiveUpdate(msg);
105 }
106 
107 std::string AgentIfMapXmppChannel::ToString() const {
108  return channel_->ToString();
109 }
110 
111 void AgentIfMapXmppChannel::WriteReadyCb(const boost::system::error_code &ec) {
112 }
113 
115  //First start for end of config identification.
117 }
118 
120  //First start for end of config identification.
122 }
123 
126 }
127 
130 }
131 
133  EndOfConfigDataPtr data(new EndOfConfigData(this));
135  boost::static_pointer_cast<ControllerWorkQueueData>(data);
136  agent_->controller()->Enqueue(base_data);
137 }
138 
143 }
144 
146  ControllerWorkQueueData(), channel_(ch) {
147 }
148 
149 // Get active xmpp-peer
151  int active_index = agent->ifmap_active_xmpp_server_index();
152  if (active_index == -1) {
153  return NULL;
154  }
155 
156  AgentXmppChannel *peer = agent->controller_xmpp_channel(active_index);
157  if (peer == NULL)
158  return NULL;
159 
160  if (AgentXmppChannel::IsBgpPeerActive(agent, peer) == false) {
161  return NULL;
162  }
163 
164  return peer;
165 }
166 
167 
169 (Agent *agent, struct AgentIfMapVmExport::VmExportInfo *info) {
170  int active_index = agent->ifmap_active_xmpp_server_index();
171  AgentIfMapXmppChannel *ifmap = agent->ifmap_xmpp_channel(active_index);
172  // Peer is valid, but channel may be down
173  if (ifmap == NULL)
174  return NULL;
175 
176  if (info && (info->seq_number_ != ifmap->GetSeqNumber())) {
177  return NULL;
178  }
179 
180  return ifmap;
181 }
182 
184  VmMap::iterator vm_it = vm_map_.find(entry->vm_uuid_);
185  if (vm_map_.end() == vm_it) {
186  return;
187  }
188 
189  struct VmExportInfo *info = vm_it->second;
190  //If delete already processed, neglect the delete
191  if (!info)
192  return;
193 
194  // Find VMI-UUID in the list of VMI
195  UuidList::const_iterator vmi_it = std::find(info->vmi_list_.begin(),
196  info->vmi_list_.end(),
197  entry->vmi_uuid_);
198  if (vmi_it == info->vmi_list_.end())
199  return;
200 
201  CONTROLLER_TRACE(IFMapVmExportTrace, UuidToString(entry->vm_uuid_),
202  UuidToString(entry->vmi_uuid_), "Delete");
203  info->vmi_list_.remove(entry->vmi_uuid_);
204  // Stop here if VM has more interfaces
205  if (info->vmi_list_.size() != 0) {
206  return;
207  }
208 
209  // All interfaces deleted. Remove the VM entry
210  vm_map_.erase(entry->vm_uuid_);
211 
212  // Unsubscribe from config if we have active channel
214  if (peer == NULL) {
215  delete info;
216  CONTROLLER_TRACE(IFMapVmExportTrace, UuidToString(entry->vm_uuid_), "",
217  "Peer NULL skipped Unsubscribe ");
218  return;
219  }
220 
222  delete info;
223  if (ifmap == NULL) {
224  CONTROLLER_TRACE(IFMapVmExportTrace, UuidToString(entry->vm_uuid_), "",
225  "Channel NULL skipped Unsubscribe ");
226  return;
227  }
228 
229  CONTROLLER_TRACE(IFMapVmExportTrace, UuidToString(entry->vm_uuid_), "",
230  "Unsubscribe ");
232  false);
233  return;
234 }
235 
237  struct VmExportInfo *info = NULL;
238  VmMap::iterator vm_it = vm_map_.find(entry->vm_uuid_);
239  if (vm_map_.end() != vm_it) {
240  info = vm_it->second;
241  } else {
242  //If first VMI create the data
243  info = new VmExportInfo(0);
244  vm_map_[entry->vm_uuid_] = info;
245  }
246 
247  //If VMI is not found, insert in the list
248  UuidList::const_iterator vmi_it = std::find(info->vmi_list_.begin(),
249  info->vmi_list_.end(),
250  entry->vmi_uuid_);
251  if (vmi_it == info->vmi_list_.end()) {
252  CONTROLLER_TRACE(IFMapVmExportTrace, UuidToString(entry->vm_uuid_),
253  UuidToString(entry->vmi_uuid_), "Add");
254  info->vmi_list_.push_back(entry->vmi_uuid_);
255  }
256 
257  // Ensure that peer exists and is in active state
259  if (peer == NULL) {
260  return;
261  }
262 
263  // Ensure that channel is valid
265  if (ifmap == NULL) {
266  return;
267  }
268 
269  //We have already sent the subscribe
270  if (info->seq_number_ == ifmap->GetSeqNumber()) {
271  return;
272  }
273 
274  CONTROLLER_TRACE(IFMapVmExportTrace, UuidToString(entry->vm_uuid_),
275  UuidToString(entry->vmi_uuid_), "Subscribe");
277 
278  //Update the sequence number
279  info->seq_number_ = ifmap->GetSeqNumber();
280 }
281 
283  if (entry->del_) {
284  VmiDelete(entry);
285  return;
286  }
287 
288  VmiAdd(entry);
289  return;
290 }
291 
293  VmMap::iterator vm_it;
294  AgentIfMapXmppChannel *ifmap = NULL;
295  struct VmExportInfo *info = NULL;
296  Agent *agent = peer->agent();
297 
298  if (!AgentXmppChannel::IsBgpPeerActive(agent, peer)) {
299  return;
300  }
301 
302  ifmap = agent->ifmap_xmpp_channel(agent->ifmap_active_xmpp_server_index());
303  if (!ifmap) {
304  return;
305  }
306 
307  //We have all the required data. Send config subscribe for all VM's
308  AgentIfMapVmExport *agent_ifmap_vm_export = peer->agent()->controller()->
309  agent_ifmap_vm_export();
310  vm_it = agent_ifmap_vm_export->vm_map_.begin();
311  for(; vm_it != agent_ifmap_vm_export->vm_map_.end(); vm_it++) {
312  info = vm_it->second;
313  if (info->seq_number_ == ifmap->GetSeqNumber()) {
314  continue;
315  }
316 
317  std::stringstream vmid;
318  vmid << vm_it->first;
319  CONTROLLER_TRACE(IFMapVmExportTrace, vmid.str(), "",
320  "Subscribe");
322  vm_it->first, true);
323 
324  //Update the sequence number so that we dont send duplicate
325  //subscribe
326  info->seq_number_ = ifmap->GetSeqNumber();
327  }
328 
329  return;
330 }
331 
333  agent_(agent) {
334 }
335 
337  VmMap::iterator vm_it;
338  struct VmExportInfo *info = NULL;
339 
340  //Destroy the vm_map and vmi list
341  for(vm_it = vm_map_.begin(); vm_it != vm_map_.end(); vm_it++) {
342  info = vm_it->second;
343  delete info;
344  }
345 
346  vm_map_.clear();
347 }
AgentIfMapXmppChannel(Agent *agent, XmppChannel *channel, uint8_t count)
IFMapAgentParser * ifmap_parser() const
Definition: agent.h:1172
pugi::xml_node FindNode(const std::string &name)
Definition: xml_pugi.cc:51
XmppMessageType type
Definition: xmpp_proto.h:57
virtual std::string ToString() const
virtual void RegisterReceive(xmps::PeerId, ReceiveCb)=0
void VmiAdd(const ControllerVmiSubscribeData *entry)
virtual void WriteReadyCb(const boost::system::error_code &ec)
void incr_xmpp_config_in_msgs(uint8_t idx)
Definition: agent_stats.h:69
boost::scoped_ptr< ConfigCleanupTimer > config_cleanup_timer_
AgentStats * stats() const
Definition: agent.cc:881
AgentIfMapVmExport(Agent *agent)
boost::shared_ptr< EndOfConfigData > EndOfConfigDataPtr
const pugi::xml_document & doc()
Definition: xml_pugi.h:68
void ReceiveInternal(const XmppStanza::XmppMessage *msg)
virtual void Start(AgentXmppChannel *agent_xmpp_channel)
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
static bool ControllerSendVmCfgSubscribe(AgentXmppChannel *peer, const boost::uuids::uuid &vm_id, bool subscribe)
AgentXmppChannel * controller_xmpp_channel(uint8_t idx) const
Definition: agent.h:809
void Enqueue(ControllerWorkQueueDataType data)
virtual void ReceiveUpdate(const XmppStanza::XmppMessage *msg)
AgentIfMapXmppChannel * ifmap_xmpp_channel(uint8_t idx) const
Definition: agent.h:792
EndOfConfigTimer * end_of_config_timer()
void StartEndOfRibTxTimer()
virtual bool Send(const uint8_t *, size_t, xmps::PeerId, SendReadyCb)=0
virtual bool SendUpdate(const std::string &msg)
std::unique_ptr< XmlBase > dom
Definition: xmpp_proto.h:62
boost::uuids::uuid vm_uuid_
EndOfConfigData(AgentIfMapXmppChannel *ch)
Definition: agent.h:358
void NotifyAll(AgentXmppChannel *peer)
VNController * controller() const
Definition: agent.cc:981
virtual void Start(AgentXmppChannel *agent_xmpp_channel)
void VmiDelete(const ControllerVmiSubscribeData *entry)
void LoadXmlDoc(const pugi::xml_document &doc)
Definition: xml_pugi.h:67
virtual const std::string & ToString() const =0
virtual void UnRegisterReceive(xmps::PeerId)=0
boost::uuids::uuid vmi_uuid_
void ConfigParse(const pugi::xml_node config, uint64_t seq)
uint64_t end_of_config_processed_time_
boost::shared_ptr< ControllerWorkQueueData > ControllerWorkQueueDataType
static uint64_t UTCTimestampUsec()
Definition: time_util.h:13
static AgentIfMapXmppChannel * GetActiveChannel(Agent *agent, struct AgentIfMapVmExport::VmExportInfo *info)
boost::scoped_ptr< EndOfConfigTimer > end_of_config_timer_
uint64_t last_config_receive_time_
#define LOG(_Level, _Msg)
Definition: logging.h:33
static uint64_t GetSeqNumber()
void ReceiveConfigMessage(std::unique_ptr< XmlBase > impl)
virtual void UnRegisterWriteReady(xmps::PeerId id)=0
static XmppXmlImplFactory * Instance()
Definition: xml_base.cc:18
static uint64_t seq_number_
Agent * agent() const
static uint64_t NewSeqNumber()
#define CONTROLLER_TRACE(obj,...)
const int8_t & ifmap_active_xmpp_server_index() const
Definition: agent.h:780
void VmiEvent(const ControllerVmiSubscribeData *entry)
static AgentXmppChannel * GetActivePeer(Agent *agent)
static bool IsBgpPeerActive(const Agent *agent, AgentXmppChannel *peer)
ConfigCleanupTimer * config_cleanup_timer()